hpsa: add sysfs entry path_info to show box and bay information
authorJoe Handzik <joseph.t.handzik@hp.com>
Sat, 18 Jul 2015 16:12:43 +0000 (11:12 -0500)
committerJames Bottomley <JBottomley@Odin.com>
Wed, 26 Aug 2015 23:26:06 +0000 (16:26 -0700)
host no, bus, target, lun, scsi_device_type
for hba mode add: box and bay information

report if the path is active/inactive

Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com>
Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h

index 984bbd9e0535e6f457068ea5cfbdc7979257cd1b..43c34a61c66c36a8292b4f9bdbb9c24b702a4485 100644 (file)
@@ -264,6 +264,7 @@ static int hpsa_scsi_ioaccel_queue_command(struct ctlr_info *h,
 static void hpsa_command_resubmit_worker(struct work_struct *work);
 static u32 lockup_detected(struct ctlr_info *h);
 static int detect_controller_lockup(struct ctlr_info *h);
+static int is_ext_target(struct ctlr_info *h, struct hpsa_scsi_dev_t *device);
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -714,12 +715,106 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev,
        return snprintf(buf, 20, "%d\n", offload_enabled);
 }
 
+#define MAX_PATHS 8
+#define PATH_STRING_LEN 50
+
+static ssize_t path_info_show(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       struct ctlr_info *h;
+       struct scsi_device *sdev;
+       struct hpsa_scsi_dev_t *hdev;
+       unsigned long flags;
+       int i;
+       int output_len = 0;
+       u8 box;
+       u8 bay;
+       u8 path_map_index = 0;
+       char *active;
+       unsigned char phys_connector[2];
+       unsigned char path[MAX_PATHS][PATH_STRING_LEN];
+
+       memset(path, 0, MAX_PATHS * PATH_STRING_LEN);
+       sdev = to_scsi_device(dev);
+       h = sdev_to_hba(sdev);
+       spin_lock_irqsave(&h->devlock, flags);
+       hdev = sdev->hostdata;
+       if (!hdev) {
+               spin_unlock_irqrestore(&h->devlock, flags);
+               return -ENODEV;
+       }
+
+       bay = hdev->bay;
+       for (i = 0; i < MAX_PATHS; i++) {
+               path_map_index = 1<<i;
+               if (i == hdev->active_path_index)
+                       active = "Active";
+               else if (hdev->path_map & path_map_index)
+                       active = "Inactive";
+               else
+                       continue;
+
+               output_len = snprintf(path[i],
+                               PATH_STRING_LEN, "[%d:%d:%d:%d] %20.20s ",
+                               h->scsi_host->host_no,
+                               hdev->bus, hdev->target, hdev->lun,
+                               scsi_device_type(hdev->devtype));
+
+               if (is_ext_target(h, hdev) ||
+                       (hdev->devtype == TYPE_RAID) ||
+                       is_logical_dev_addr_mode(hdev->scsi3addr)) {
+                       output_len += snprintf(path[i] + output_len,
+                                               PATH_STRING_LEN, "%s\n",
+                                               active);
+                       continue;
+               }
+
+               box = hdev->box[i];
+               memcpy(&phys_connector, &hdev->phys_connector[i],
+                       sizeof(phys_connector));
+               if (phys_connector[0] < '0')
+                       phys_connector[0] = '0';
+               if (phys_connector[1] < '0')
+                       phys_connector[1] = '0';
+               if (hdev->phys_connector[i] > 0)
+                       output_len += snprintf(path[i] + output_len,
+                               PATH_STRING_LEN,
+                               "PORT: %.2s ",
+                               phys_connector);
+               if (hdev->devtype == TYPE_DISK && h->hba_mode_enabled) {
+                       if (box == 0 || box == 0xFF) {
+                               output_len += snprintf(path[i] + output_len,
+                                       PATH_STRING_LEN,
+                                       "BAY: %hhu %s\n",
+                                       bay, active);
+                       } else {
+                               output_len += snprintf(path[i] + output_len,
+                                       PATH_STRING_LEN,
+                                       "BOX: %hhu BAY: %hhu %s\n",
+                                       box, bay, active);
+                       }
+               } else if (box != 0 && box != 0xFF) {
+                       output_len += snprintf(path[i] + output_len,
+                               PATH_STRING_LEN, "BOX: %hhu %s\n",
+                               box, active);
+               } else
+                       output_len += snprintf(path[i] + output_len,
+                               PATH_STRING_LEN, "%s\n", active);
+       }
+
+       spin_unlock_irqrestore(&h->devlock, flags);
+       return snprintf(buf, output_len+1, "%s%s%s%s%s%s%s%s",
+               path[0], path[1], path[2], path[3],
+               path[4], path[5], path[6], path[7]);
+}
+
 static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
 static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
 static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
 static DEVICE_ATTR(hp_ssd_smart_path_enabled, S_IRUGO,
                        host_show_hp_ssd_smart_path_enabled, NULL);
+static DEVICE_ATTR(path_info, S_IRUGO, path_info_show, NULL);
 static DEVICE_ATTR(hp_ssd_smart_path_status, S_IWUSR|S_IRUGO|S_IROTH,
                host_show_hp_ssd_smart_path_status,
                host_store_hp_ssd_smart_path_status);
@@ -741,6 +836,7 @@ static struct device_attribute *hpsa_sdev_attrs[] = {
        &dev_attr_lunid,
        &dev_attr_unique_id,
        &dev_attr_hp_ssd_smart_path_enabled,
+       &dev_attr_path_info,
        &dev_attr_lockup_detected,
        NULL,
 };
@@ -3611,6 +3707,31 @@ static void hpsa_get_ioaccel_drive_info(struct ctlr_info *h,
        atomic_set(&dev->reset_cmds_out, 0);
 }
 
+static void hpsa_get_path_info(struct hpsa_scsi_dev_t *this_device,
+       u8 *lunaddrbytes,
+       struct bmic_identify_physical_device *id_phys)
+{
+       if (PHYS_IOACCEL(lunaddrbytes)
+               && this_device->ioaccel_handle)
+               this_device->hba_ioaccel_enabled = 1;
+
+       memcpy(&this_device->active_path_index,
+               &id_phys->active_path_number,
+               sizeof(this_device->active_path_index));
+       memcpy(&this_device->path_map,
+               &id_phys->redundant_path_present_map,
+               sizeof(this_device->path_map));
+       memcpy(&this_device->box,
+               &id_phys->alternate_paths_phys_box_on_port,
+               sizeof(this_device->box));
+       memcpy(&this_device->phys_connector,
+               &id_phys->alternate_paths_phys_connector,
+               sizeof(this_device->phys_connector));
+       memcpy(&this_device->bay,
+               &id_phys->phys_bay_in_box,
+               sizeof(this_device->bay));
+}
+
 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 {
        /* the idea here is we could get notified
@@ -3771,6 +3892,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
 
                        hpsa_get_ioaccel_drive_info(h, this_device,
                                                lunaddrbytes, id_phys);
+                       hpsa_get_path_info(this_device, lunaddrbytes, id_phys);
                        atomic_set(&this_device->ioaccel_cmds_out, 0);
                        ncurrent++;
                        break;
index 6f6084b394201fcdc4e7b592663819b5e6eab7dc..ab014d3f3656a30c9c1fae1f70bf08d1b0c9bb61 100644 (file)
@@ -50,6 +50,11 @@ struct hpsa_scsi_dev_t {
                                         * device via "ioaccel" path.
                                         */
        u32 ioaccel_handle;
+       u8 active_path_index;
+       u8 path_map;
+       u8 bay;
+       u8 box[8];
+       u16 phys_connector[8];
        int offload_config;             /* I/O accel RAID offload configured */
        int offload_enabled;            /* I/O accel RAID offload enabled */
        int offload_to_be_enabled;