Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 999b3ffc authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen
Browse files

scsi: aacraid: VPD 83 type3 support



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: default avatarRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: default avatarDave Carroll <David.Carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 954b2b5a
Loading
Loading
Loading
Loading
+117 −63
Original line number Diff line number Diff line
@@ -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];
+2 −0
Original line number Diff line number Diff line
@@ -2106,6 +2106,8 @@ struct aac_fsinfo {

struct  aac_blockdevinfo {
	__le32	block_size;
	__le32  logical_phys_map;
	u8	identifier[16];
};

union aac_contentinfo {
+31 −0
Original line number Diff line number Diff line
@@ -556,8 +556,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,
};