This patch adds support to retrieve the unique identifier data (VPD page
83 type3) for Logical drives created on SmartIOC 2000 products. In
addition  added a sysfs device structure to expose the id information.

Signed-off-by: Raghava Aditya Renukunta <raghavaaditya.renuku...@microsemi.com>
Signed-off-by: Dave Carroll <david.carr...@microsemi.com>

---
 Changes in  V2:
  None

 drivers/scsi/aacraid/aachba.c  | 180 ++++++++++++++++++++++++++---------------
 drivers/scsi/aacraid/aacraid.h |   2 +
 drivers/scsi/aacraid/linit.c   |  31 +++++++
 3 files changed, 150 insertions(+), 63 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index a5a195c..1f43ab8 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -167,46 +167,56 @@ struct inquiry_data {
 };
 
 /* Added for VPD 0x83 */
-typedef struct {
-       u8 CodeSet:4;   /* VPD_CODE_SET */
-       u8 Reserved:4;
-       u8 IdentifierType:4;    /* VPD_IDENTIFIER_TYPE */
-       u8 Reserved2:4;
-       u8 Reserved3;
-       u8 IdentifierLength;
-       u8 VendId[8];
-       u8 ProductId[16];
-       u8 SerialNumber[8];     /* SN in ASCII */
-
-} TVPD_ID_Descriptor_Type_1;
+struct  tvpd_id_descriptor_type_1 {
+       u8 codeset:4;           /* VPD_CODE_SET */
+       u8 reserved:4;
+       u8 identifiertype:4;    /* VPD_IDENTIFIER_TYPE */
+       u8 reserved2:4;
+       u8 reserved3;
+       u8 identifierlength;
+       u8 venid[8];
+       u8 productid[16];
+       u8 serialnumber[8];     /* SN in ASCII */
 
-typedef struct {
-       u8 CodeSet:4;   /* VPD_CODE_SET */
-       u8 Reserved:4;
-       u8 IdentifierType:4;    /* VPD_IDENTIFIER_TYPE */
-       u8 Reserved2:4;
-       u8 Reserved3;
-       u8 IdentifierLength;
-       struct TEU64Id {
+};
+
+struct tvpd_id_descriptor_type_2 {
+       u8 codeset:4;           /* VPD_CODE_SET */
+       u8 reserved:4;
+       u8 identifiertype:4;    /* VPD_IDENTIFIER_TYPE */
+       u8 reserved2:4;
+       u8 reserved3;
+       u8 identifierlength;
+       struct teu64id {
                u32 Serial;
                 /* The serial number supposed to be 40 bits,
                  * bit we only support 32, so make the last byte zero. */
-               u8 Reserved;
-               u8 VendId[3];
-       } EU64Id;
+               u8 reserved;
+               u8 venid[3];
+       } eu64id;
 
-} TVPD_ID_Descriptor_Type_2;
+};
 
-typedef struct {
+struct tvpd_id_descriptor_type_3 {
+       u8 codeset : 4;          /* VPD_CODE_SET */
+       u8 reserved : 4;
+       u8 identifiertype : 4;   /* VPD_IDENTIFIER_TYPE */
+       u8 reserved2 : 4;
+       u8 reserved3;
+       u8 identifierlength;
+       u8 Identifier[16];
+};
+
+struct tvpd_page83 {
        u8 DeviceType:5;
        u8 DeviceTypeQualifier:3;
        u8 PageCode;
-       u8 Reserved;
+       u8 reserved;
        u8 PageLength;
-       TVPD_ID_Descriptor_Type_1 IdDescriptorType1;
-       TVPD_ID_Descriptor_Type_2 IdDescriptorType2;
-
-} TVPD_Page83;
+       struct tvpd_id_descriptor_type_1 type1;
+       struct tvpd_id_descriptor_type_2 type2;
+       struct tvpd_id_descriptor_type_3 type3;
+};
 
 /*
  *              M O D U L E   G L O B A L S
@@ -613,6 +623,7 @@ static void _aac_probe_container2(void * context, struct 
fib * fibptr)
        struct fsa_dev_info *fsa_dev_ptr;
        int (*callback)(struct scsi_cmnd *);
        struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
+       int i;
 
 
        if (!aac_valid_context(scsicmd, fibptr))
@@ -635,6 +646,10 @@ static void _aac_probe_container2(void * context, struct 
fib * fibptr)
                                fsa_dev_ptr->block_size =
                                        
le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size);
                        }
+                       for (i = 0; i < 16; i++)
+                               fsa_dev_ptr->identifier[i] =
+                                       dresp->mnt[0].fileinfo.bdevinfo
+                                                               .identifier[i];
                        fsa_dev_ptr->valid = 1;
                        /* sense_key holds the current state of the spin-up */
                        if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY))
@@ -929,6 +944,28 @@ static void setinqstr(struct aac_dev *dev, void *data, int 
tindex)
        inqstrcpy ("V1.0", str->prl);
 }
 
+static void build_vpd83_type3(struct tvpd_page83 *vpdpage83data,
+               struct aac_dev *dev, struct scsi_cmnd *scsicmd)
+{
+       int container;
+
+       vpdpage83data->type3.codeset = 1;
+       vpdpage83data->type3.identifiertype = 3;
+       vpdpage83data->type3.identifierlength = sizeof(vpdpage83data->type3)
+                       - 4;
+
+       for (container = 0; container < dev->maximum_num_containers;
+                       container++) {
+
+               if (scmd_id(scsicmd) == container) {
+                       memcpy(vpdpage83data->type3.Identifier,
+                                       dev->fsa_dev[container].identifier,
+                                       16);
+                       break;
+               }
+       }
+}
+
 static void get_container_serial_callback(void *context, struct fib * fibptr)
 {
        struct aac_get_serial_resp * get_serial_reply;
@@ -946,39 +983,47 @@ static void get_container_serial_callback(void *context, 
struct fib * fibptr)
                /*Check to see if it's for VPD 0x83 or 0x80 */
                if (scsicmd->cmnd[2] == 0x83) {
                        /* vpd page 0x83 - Device Identification Page */
+                       struct aac_dev *dev;
                        int i;
-                       TVPD_Page83 VPDPage83Data;
+                       struct tvpd_page83 vpdpage83data;
 
-                       memset(((u8 *)&VPDPage83Data), 0,
-                              sizeof(VPDPage83Data));
+                       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+
+                       memset(((u8 *)&vpdpage83data), 0,
+                              sizeof(vpdpage83data));
 
                        /* DIRECT_ACCESS_DEVIC */
-                       VPDPage83Data.DeviceType = 0;
+                       vpdpage83data.DeviceType = 0;
                        /* DEVICE_CONNECTED */
-                       VPDPage83Data.DeviceTypeQualifier = 0;
+                       vpdpage83data.DeviceTypeQualifier = 0;
                        /* VPD_DEVICE_IDENTIFIERS */
-                       VPDPage83Data.PageCode = 0x83;
-                       VPDPage83Data.Reserved = 0;
-                       VPDPage83Data.PageLength =
-                               sizeof(VPDPage83Data.IdDescriptorType1) +
-                               sizeof(VPDPage83Data.IdDescriptorType2);
+                       vpdpage83data.PageCode = 0x83;
+                       vpdpage83data.reserved = 0;
+                       vpdpage83data.PageLength =
+                               sizeof(vpdpage83data.type1) +
+                               sizeof(vpdpage83data.type2);
+
+                       /* VPD 83 Type 3 is not supported for ARC */
+                       if (dev->sa_firmware)
+                               vpdpage83data.PageLength +=
+                               sizeof(vpdpage83data.type3);
 
                        /* T10 Vendor Identifier Field Format */
-                       /* VpdCodeSetAscii */
-                       VPDPage83Data.IdDescriptorType1.CodeSet = 2;
+                       /* VpdcodesetAscii */
+                       vpdpage83data.type1.codeset = 2;
                        /* VpdIdentifierTypeVendorId */
-                       VPDPage83Data.IdDescriptorType1.IdentifierType = 1;
-                       VPDPage83Data.IdDescriptorType1.IdentifierLength =
-                               sizeof(VPDPage83Data.IdDescriptorType1) - 4;
+                       vpdpage83data.type1.identifiertype = 1;
+                       vpdpage83data.type1.identifierlength =
+                               sizeof(vpdpage83data.type1) - 4;
 
                        /* "ADAPTEC " for adaptec */
-                       memcpy(VPDPage83Data.IdDescriptorType1.VendId,
+                       memcpy(vpdpage83data.type1.venid,
                                "ADAPTEC ",
-                               sizeof(VPDPage83Data.IdDescriptorType1.VendId));
-                       memcpy(VPDPage83Data.IdDescriptorType1.ProductId,
+                               sizeof(vpdpage83data.type1.venid));
+                       memcpy(vpdpage83data.type1.productid,
                                "ARRAY           ",
                                sizeof(
-                               VPDPage83Data.IdDescriptorType1.ProductId));
+                               vpdpage83data.type1.productid));
 
                        /* Convert to ascii based serial number.
                         * The LSB is the the end.
@@ -987,32 +1032,41 @@ static void get_container_serial_callback(void *context, 
struct fib * fibptr)
                                u8 temp =
                                        (u8)((get_serial_reply->uid >> ((7 - i) 
* 4)) & 0xF);
                                if (temp  > 0x9) {
-                                       
VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
+                                       vpdpage83data.type1.serialnumber[i] =
                                                        'A' + (temp - 0xA);
                                } else {
-                                       
VPDPage83Data.IdDescriptorType1.SerialNumber[i] =
+                                       vpdpage83data.type1.serialnumber[i] =
                                                        '0' + temp;
                                }
                        }
 
                        /* VpdCodeSetBinary */
-                       VPDPage83Data.IdDescriptorType2.CodeSet = 1;
-                       /* VpdIdentifierTypeEUI64 */
-                       VPDPage83Data.IdDescriptorType2.IdentifierType = 2;
-                       VPDPage83Data.IdDescriptorType2.IdentifierLength =
-                               sizeof(VPDPage83Data.IdDescriptorType2) - 4;
+                       vpdpage83data.type2.codeset = 1;
+                       /* VpdidentifiertypeEUI64 */
+                       vpdpage83data.type2.identifiertype = 2;
+                       vpdpage83data.type2.identifierlength =
+                               sizeof(vpdpage83data.type2) - 4;
 
-                       VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0;
-                       VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0;
-                       VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0;
+                       vpdpage83data.type2.eu64id.venid[0] = 0xD0;
+                       vpdpage83data.type2.eu64id.venid[1] = 0;
+                       vpdpage83data.type2.eu64id.venid[2] = 0;
 
-                       VPDPage83Data.IdDescriptorType2.EU64Id.Serial =
+                       vpdpage83data.type2.eu64id.Serial =
                                                        get_serial_reply->uid;
-                       VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0;
+                       vpdpage83data.type2.eu64id.reserved = 0;
+
+                       /*
+                        * VpdIdentifierTypeFCPHName
+                        * VPD 0x83 Type 3 not supported for ARC
+                        */
+                       if (dev->sa_firmware) {
+                               build_vpd83_type3(&vpdpage83data,
+                                               dev, scsicmd);
+                       }
 
                        /* Move the inquiry data to the response buffer. */
-                       scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data,
-                                                sizeof(VPDPage83Data));
+                       scsi_sg_copy_from_buffer(scsicmd, &vpdpage83data,
+                                                sizeof(vpdpage83data));
                } else {
                        /* It must be for VPD 0x80 */
                        char sp[13];
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index afcdee0..daa70a2 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -2110,6 +2110,8 @@ struct aac_fsinfo {
 
 struct  aac_blockdevinfo {
        __le32  block_size;
+       __le32  logical_phys_map;
+       u8      identifier[16];
 };
 
 union aac_contentinfo {
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index d352c27..9da2ae0 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -548,8 +548,39 @@ static struct device_attribute aac_raid_level_attr = {
        .show = aac_show_raid_level
 };
 
+static ssize_t aac_show_unique_id(struct device *dev,
+            struct device_attribute *attr, char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct aac_dev *aac = (struct aac_dev *)(sdev->host->hostdata);
+       unsigned char sn[16];
+
+       memset(sn, 0, sizeof(sn));
+
+       if (sdev_channel(sdev) == CONTAINER_CHANNEL)
+               memcpy(sn, aac->fsa_dev[sdev_id(sdev)].identifier, sizeof(sn));
+
+       return snprintf(buf, 16 * 2 + 2,
+               "%02X%02X%02X%02X%02X%02X%02X%02X 
%02X%02X%02X%02X%02X%02X%02X%02X\n",
+               sn[0], sn[1], sn[2], sn[3],
+               sn[4], sn[5], sn[6], sn[7],
+               sn[8], sn[9], sn[10], sn[11],
+               sn[12], sn[13], sn[14], sn[15]);
+}
+
+static struct device_attribute aac_unique_id_attr = {
+       .attr = {
+               .name = "unique_id",
+               .mode = 0444,
+       },
+       .show = aac_show_unique_id
+};
+
+
+
 static struct device_attribute *aac_dev_attrs[] = {
        &aac_raid_level_attr,
+       &aac_unique_id_attr,
        NULL,
 };
 
-- 
2.7.4

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

Reply via email to