[SCSI] qla2xxx: Retrieve board serial-number and description from VPD.
authorJoe Carnuccio <joe.carnuccio@qlogic.com>
Thu, 10 Jul 2008 23:55:53 +0000 (16:55 -0700)
committerJames Bottomley <James.Bottomley@HansenPartnership.com>
Sat, 26 Jul 2008 19:14:39 +0000 (15:14 -0400)
Recent ISPs have this information written at manufacturing time,
so use the information.  This also reduces future churn of the
qla_devtbl.h file contents, as the driver can now depend on the
information to be present in VPD.

Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_sup.c

index fe8d708..612e3d0 100644 (file)
@@ -557,8 +557,10 @@ qla2x00_serial_num_show(struct device *dev, struct device_attribute *attr,
        scsi_qla_host_t *ha = shost_priv(class_to_shost(dev));
        uint32_t sn;
 
-       if (IS_FWI2_CAPABLE(ha))
-               return snprintf(buf, PAGE_SIZE, "\n");
+       if (IS_FWI2_CAPABLE(ha)) {
+               qla2xxx_get_vpd_field(ha, "SN", buf, PAGE_SIZE);
+               return snprintf(buf, PAGE_SIZE, "%s\n", buf);
+       }
 
        sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1;
        return snprintf(buf, PAGE_SIZE, "%c%05d\n", 'A' + sn / 100000,
index 00c7052..6da31ba 100644 (file)
@@ -2518,7 +2518,7 @@ typedef struct scsi_qla_host {
 
        uint8_t         model_number[16+1];
 #define BINZERO                "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
-       char            *model_desc;
+       char            model_desc[80];
        uint8_t         adapter_id[16+1];
 
        uint8_t         *node_name;
index f921ccd..0b15673 100644 (file)
@@ -314,6 +314,7 @@ extern int qla2xxx_hw_event_log(scsi_qla_host_t *, uint16_t , uint16_t,
     uint16_t, uint16_t);
 
 extern void qla2xxx_get_flash_info(scsi_qla_host_t *);
+extern int qla2xxx_get_vpd_field(scsi_qla_host_t *, char *, char *, size_t);
 
 /*
  * Global Function Prototypes in qla_dbg.c source file.
index f4cd2cd..08bdba5 100644 (file)
@@ -1501,18 +1501,25 @@ qla2x00_set_model_info(scsi_qla_host_t *ha, uint8_t *model, size_t len, char *de
                index = (ha->pdev->subsystem_device & 0xff);
                if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES)
-                       ha->model_desc = qla2x00_model_name[index * 2 + 1];
+                       strncpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc) - 1);
        } else {
                index = (ha->pdev->subsystem_device & 0xff);
                if (ha->pdev->subsystem_vendor == PCI_VENDOR_ID_QLOGIC &&
                    index < QLA_MODEL_NAMES) {
                        strcpy(ha->model_number,
                            qla2x00_model_name[index * 2]);
-                       ha->model_desc = qla2x00_model_name[index * 2 + 1];
+                       strncpy(ha->model_desc,
+                           qla2x00_model_name[index * 2 + 1],
+                           sizeof(ha->model_desc) - 1);
                } else {
                        strcpy(ha->model_number, def);
                }
        }
+       if (IS_FWI2_CAPABLE(ha))
+               qla2xxx_get_vpd_field(ha, "\x82", ha->model_desc,
+                   sizeof(ha->model_desc));
 }
 
 /* On sparc systems, obtain port and node WWN from firmware
index ebea622..1bca744 100644 (file)
@@ -2303,6 +2303,51 @@ qla24xx_get_flash_version(scsi_qla_host_t *ha, void *mbuf)
 }
 
 static int
+qla2xxx_is_vpd_valid(uint8_t *pos, uint8_t *end)
+{
+       if (pos >= end || *pos != 0x82)
+               return 0;
+
+       pos += 3 + pos[1];
+       if (pos >= end || *pos != 0x90)
+               return 0;
+
+       pos += 3 + pos[1];
+       if (pos >= end || *pos != 0x78)
+               return 0;
+
+       return 1;
+}
+
+int
+qla2xxx_get_vpd_field(scsi_qla_host_t *ha, char *key, char *str, size_t size)
+{
+       uint8_t *pos = ha->vpd;
+       uint8_t *end = pos + ha->vpd_size;
+       int len = 0;
+
+       if (!IS_FWI2_CAPABLE(ha) || !qla2xxx_is_vpd_valid(pos, end))
+               return 0;
+
+       while (pos < end && *pos != 0x78) {
+               len = (*pos == 0x82) ? pos[1] : pos[2];
+
+               if (!strncmp(pos, key, strlen(key)))
+                       break;
+
+               if (*pos != 0x90 && *pos != 0x91)
+                       pos += len;
+
+               pos += 3;
+       }
+
+       if (pos < end - len && *pos != 0x78)
+               return snprintf(str, size, "%.*s", len, pos + 3);
+
+       return 0;
+}
+
+static int
 qla2xxx_hw_event_store(scsi_qla_host_t *ha, uint32_t *fdata)
 {
        uint32_t d[2], faddr;