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.Renukunta@xxxxxxxxxxxxx> Signed-off-by: Dave Carroll <David.Carroll@xxxxxxxxxxxxx> --- 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 majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html