From: Scott Teel <[email protected]>

Before using vendor-specific VPD pages for getting
raid_level and device_id, check for page support.
If page isn't supported, don't try to use it.
Also, pay attention to return status on
hpsa_get_device_id.

Reviewed-by: Scott Benesh <[email protected]>
Reviewed-by: Scott Teel <[email protected]>
Reviewed-by: Kevin Barnett <[email protected]>
Signed-off-by: Don Brace <[email protected]>
---
 drivers/scsi/hpsa.c     |   44 ++++++++++++++++++++++++++++++++++----------
 drivers/scsi/hpsa_cmd.h |    1 +
 2 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 97f50c7..6a5b7df 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -293,6 +293,8 @@ static int detect_controller_lockup(struct ctlr_info *h);
 static void hpsa_disable_rld_caching(struct ctlr_info *h);
 static inline int hpsa_scsi_do_report_phys_luns(struct ctlr_info *h,
        struct ReportExtendedLUNdata *buf, int bufsize);
+static bool hpsa_vpd_page_supported(struct ctlr_info *h,
+       unsigned char scsi3addr[], u8 page);
 static int hpsa_luns_changed(struct ctlr_info *h);
 static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c,
                               struct hpsa_scsi_dev_t *dev,
@@ -3088,11 +3090,19 @@ static void hpsa_get_raid_level(struct ctlr_info *h,
        buf = kzalloc(64, GFP_KERNEL);
        if (!buf)
                return;
-       rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0xC1, buf, 64);
+
+       if (!hpsa_vpd_page_supported(h, scsi3addr,
+               HPSA_VPD_LV_DEVICE_GEOMETRY))
+               goto exit;
+
+       rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE |
+               HPSA_VPD_LV_DEVICE_GEOMETRY, buf, 64);
+
        if (rc == 0)
                *raid_level = buf[8];
        if (*raid_level > RAID_UNKNOWN)
                *raid_level = RAID_UNKNOWN;
+exit:
        kfree(buf);
        return;
 }
@@ -3450,7 +3460,7 @@ static void hpsa_get_sas_address(struct ctlr_info *h, 
unsigned char *scsi3addr,
 }
 
 /* Get a device id from inquiry page 0x83 */
-static int hpsa_vpd_page_supported(struct ctlr_info *h,
+static bool hpsa_vpd_page_supported(struct ctlr_info *h,
        unsigned char scsi3addr[], u8 page)
 {
        int rc;
@@ -3539,18 +3549,25 @@ static int hpsa_get_device_id(struct ctlr_info *h, 
unsigned char *scsi3addr,
        int rc;
        unsigned char *buf;
 
-       if (buflen > 16)
-               buflen = 16;
+       /* Does controller have VPD for device id? */
+       if (!hpsa_vpd_page_supported(h, scsi3addr, HPSA_VPD_LV_DEVICE_ID))
+               return 1; /* not supported */
+
        buf = kzalloc(64, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
-       rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE | 0x83, buf, 64);
-       if (rc == 0)
-               memcpy(device_id, &buf[index], buflen);
+
+       rc = hpsa_scsi_do_inquiry(h, scsi3addr, VPD_PAGE |
+                                       HPSA_VPD_LV_DEVICE_ID, buf, 64);
+       if (rc == 0) {
+               if (buflen > 16)
+                       buflen = 16;
+               memcpy(device_id, &buf[8], buflen);
+       }
 
        kfree(buf);
 
-       return rc != 0;
+       return rc; /*0 - got id,  otherwise, didn't */
 }
 
 static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
@@ -3821,8 +3838,15 @@ static int hpsa_update_device_info(struct ctlr_info *h,
                sizeof(this_device->model));
        memset(this_device->device_id, 0,
                sizeof(this_device->device_id));
-       hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
-               sizeof(this_device->device_id));
+       if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
+               sizeof(this_device->device_id)))
+               dev_err(&h->pdev->dev,
+                       "hpsa%d: %s: can't get device id for host 
%d:C0:T%d:L%d\t%s\t%.16s\n",
+                       h->ctlr, __func__,
+                       h->scsi_host->host_no,
+                       this_device->target, this_device->lun,
+                       scsi_device_type(this_device->devtype),
+                       this_device->model);
 
        if ((this_device->devtype == TYPE_DISK ||
                this_device->devtype == TYPE_ZBC) &&
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index a5be153..a584cdf 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -157,6 +157,7 @@
 
 /* VPD Inquiry types */
 #define HPSA_VPD_SUPPORTED_PAGES        0x00
+#define HPSA_VPD_LV_DEVICE_ID           0x83
 #define HPSA_VPD_LV_DEVICE_GEOMETRY     0xC1
 #define HPSA_VPD_LV_IOACCEL_STATUS      0xC2
 #define HPSA_VPD_LV_STATUS             0xC3

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to