diff options
author | Mahesh Rajashekhara <Mahesh.Rajashekhara@pmcs.com> | 2015-03-26 10:41:26 -0400 |
---|---|---|
committer | James Bottomley <JBottomley@Odin.com> | 2015-04-09 19:51:29 -0400 |
commit | 5d9106490c7f7533abc6b8e15ceab64f2c7f466a (patch) | |
tree | 32b532066ae0d6111f4d6b6187bda57b86c8aeaa | |
parent | 495c021767bd78c998a46cf8cdd7a4ebf3a9cfd1 (diff) |
aacraid: vpd page code 0x83 support
Signed-off-by: Mahesh Rajashekhara <Mahesh.Rajashekhara@pmcs.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Murthy Bhat <Murthy.Bhat@pmcs.com>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 165 |
1 files changed, 153 insertions, 12 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index aee3eaa0bd5d..09027e9edfd5 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -163,6 +163,48 @@ struct inquiry_data { | |||
163 | u8 inqd_prl[4]; /* Product Revision Level */ | 163 | u8 inqd_prl[4]; /* Product Revision Level */ |
164 | }; | 164 | }; |
165 | 165 | ||
166 | /* Added for VPD 0x83 */ | ||
167 | typedef struct { | ||
168 | u8 CodeSet:4; /* VPD_CODE_SET */ | ||
169 | u8 Reserved:4; | ||
170 | u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | ||
171 | u8 Reserved2:4; | ||
172 | u8 Reserved3; | ||
173 | u8 IdentifierLength; | ||
174 | u8 VendId[8]; | ||
175 | u8 ProductId[16]; | ||
176 | u8 SerialNumber[8]; /* SN in ASCII */ | ||
177 | |||
178 | } TVPD_ID_Descriptor_Type_1; | ||
179 | |||
180 | typedef struct { | ||
181 | u8 CodeSet:4; /* VPD_CODE_SET */ | ||
182 | u8 Reserved:4; | ||
183 | u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | ||
184 | u8 Reserved2:4; | ||
185 | u8 Reserved3; | ||
186 | u8 IdentifierLength; | ||
187 | struct TEU64Id { | ||
188 | u32 Serial; | ||
189 | /* The serial number supposed to be 40 bits, | ||
190 | * bit we only support 32, so make the last byte zero. */ | ||
191 | u8 Reserved; | ||
192 | u8 VendId[3]; | ||
193 | } EU64Id; | ||
194 | |||
195 | } TVPD_ID_Descriptor_Type_2; | ||
196 | |||
197 | typedef struct { | ||
198 | u8 DeviceType:5; | ||
199 | u8 DeviceTypeQualifier:3; | ||
200 | u8 PageCode; | ||
201 | u8 Reserved; | ||
202 | u8 PageLength; | ||
203 | TVPD_ID_Descriptor_Type_1 IdDescriptorType1; | ||
204 | TVPD_ID_Descriptor_Type_2 IdDescriptorType2; | ||
205 | |||
206 | } TVPD_Page83; | ||
207 | |||
166 | /* | 208 | /* |
167 | * M O D U L E G L O B A L S | 209 | * M O D U L E G L O B A L S |
168 | */ | 210 | */ |
@@ -890,14 +932,88 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) | |||
890 | get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); | 932 | get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); |
891 | /* Failure is irrelevant, using default value instead */ | 933 | /* Failure is irrelevant, using default value instead */ |
892 | if (le32_to_cpu(get_serial_reply->status) == CT_OK) { | 934 | if (le32_to_cpu(get_serial_reply->status) == CT_OK) { |
893 | char sp[13]; | 935 | /*Check to see if it's for VPD 0x83 or 0x80 */ |
894 | /* EVPD bit set */ | 936 | if (scsicmd->cmnd[2] == 0x83) { |
895 | sp[0] = INQD_PDT_DA; | 937 | /* vpd page 0x83 - Device Identification Page */ |
896 | sp[1] = scsicmd->cmnd[2]; | 938 | int i; |
897 | sp[2] = 0; | 939 | TVPD_Page83 VPDPage83Data; |
898 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | 940 | |
899 | le32_to_cpu(get_serial_reply->uid)); | 941 | memset(((u8 *)&VPDPage83Data), 0, |
900 | scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp)); | 942 | sizeof(VPDPage83Data)); |
943 | |||
944 | /* DIRECT_ACCESS_DEVIC */ | ||
945 | VPDPage83Data.DeviceType = 0; | ||
946 | /* DEVICE_CONNECTED */ | ||
947 | VPDPage83Data.DeviceTypeQualifier = 0; | ||
948 | /* VPD_DEVICE_IDENTIFIERS */ | ||
949 | VPDPage83Data.PageCode = 0x83; | ||
950 | VPDPage83Data.Reserved = 0; | ||
951 | VPDPage83Data.PageLength = | ||
952 | sizeof(VPDPage83Data.IdDescriptorType1) + | ||
953 | sizeof(VPDPage83Data.IdDescriptorType2); | ||
954 | |||
955 | /* T10 Vendor Identifier Field Format */ | ||
956 | /* VpdCodeSetAscii */ | ||
957 | VPDPage83Data.IdDescriptorType1.CodeSet = 2; | ||
958 | /* VpdIdentifierTypeVendorId */ | ||
959 | VPDPage83Data.IdDescriptorType1.IdentifierType = 1; | ||
960 | VPDPage83Data.IdDescriptorType1.IdentifierLength = | ||
961 | sizeof(VPDPage83Data.IdDescriptorType1) - 4; | ||
962 | |||
963 | /* "ADAPTEC " for adaptec */ | ||
964 | memcpy(VPDPage83Data.IdDescriptorType1.VendId, | ||
965 | "ADAPTEC ", | ||
966 | sizeof(VPDPage83Data.IdDescriptorType1.VendId)); | ||
967 | memcpy(VPDPage83Data.IdDescriptorType1.ProductId, | ||
968 | "ARRAY ", | ||
969 | sizeof( | ||
970 | VPDPage83Data.IdDescriptorType1.ProductId)); | ||
971 | |||
972 | /* Convert to ascii based serial number. | ||
973 | * The LSB is the the end. | ||
974 | */ | ||
975 | for (i = 0; i < 8; i++) { | ||
976 | u8 temp = | ||
977 | (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF); | ||
978 | if (temp > 0x9) { | ||
979 | VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | ||
980 | 'A' + (temp - 0xA); | ||
981 | } else { | ||
982 | VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | ||
983 | '0' + temp; | ||
984 | } | ||
985 | } | ||
986 | |||
987 | /* VpdCodeSetBinary */ | ||
988 | VPDPage83Data.IdDescriptorType2.CodeSet = 1; | ||
989 | /* VpdIdentifierTypeEUI64 */ | ||
990 | VPDPage83Data.IdDescriptorType2.IdentifierType = 2; | ||
991 | VPDPage83Data.IdDescriptorType2.IdentifierLength = | ||
992 | sizeof(VPDPage83Data.IdDescriptorType2) - 4; | ||
993 | |||
994 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0; | ||
995 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0; | ||
996 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0; | ||
997 | |||
998 | VPDPage83Data.IdDescriptorType2.EU64Id.Serial = | ||
999 | get_serial_reply->uid; | ||
1000 | VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0; | ||
1001 | |||
1002 | /* Move the inquiry data to the response buffer. */ | ||
1003 | scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data, | ||
1004 | sizeof(VPDPage83Data)); | ||
1005 | } else { | ||
1006 | /* It must be for VPD 0x80 */ | ||
1007 | char sp[13]; | ||
1008 | /* EVPD bit set */ | ||
1009 | sp[0] = INQD_PDT_DA; | ||
1010 | sp[1] = scsicmd->cmnd[2]; | ||
1011 | sp[2] = 0; | ||
1012 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | ||
1013 | le32_to_cpu(get_serial_reply->uid)); | ||
1014 | scsi_sg_copy_from_buffer(scsicmd, sp, | ||
1015 | sizeof(sp)); | ||
1016 | } | ||
901 | } | 1017 | } |
902 | 1018 | ||
903 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1019 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
@@ -2309,9 +2425,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2309 | INQD_PDT_PROC : INQD_PDT_DA; | 2425 | INQD_PDT_PROC : INQD_PDT_DA; |
2310 | if (scsicmd->cmnd[2] == 0) { | 2426 | if (scsicmd->cmnd[2] == 0) { |
2311 | /* supported vital product data pages */ | 2427 | /* supported vital product data pages */ |
2312 | arr[3] = 2; | 2428 | arr[3] = 3; |
2313 | arr[4] = 0x0; | 2429 | arr[4] = 0x0; |
2314 | arr[5] = 0x80; | 2430 | arr[5] = 0x80; |
2431 | arr[6] = 0x83; | ||
2315 | arr[1] = scsicmd->cmnd[2]; | 2432 | arr[1] = scsicmd->cmnd[2]; |
2316 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, | 2433 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
2317 | sizeof(inq_data)); | 2434 | sizeof(inq_data)); |
@@ -2327,7 +2444,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2327 | if (aac_wwn != 2) | 2444 | if (aac_wwn != 2) |
2328 | return aac_get_container_serial( | 2445 | return aac_get_container_serial( |
2329 | scsicmd); | 2446 | scsicmd); |
2330 | /* SLES 10 SP1 special */ | 2447 | scsicmd->result = DID_OK << 16 | |
2448 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
2449 | } else if (scsicmd->cmnd[2] == 0x83) { | ||
2450 | /* vpd page 0x83 - Device Identification Page */ | ||
2451 | char *sno = (char *)&inq_data; | ||
2452 | sno[3] = setinqserial(dev, &sno[4], | ||
2453 | scmd_id(scsicmd)); | ||
2454 | if (aac_wwn != 2) | ||
2455 | return aac_get_container_serial( | ||
2456 | scsicmd); | ||
2331 | scsicmd->result = DID_OK << 16 | | 2457 | scsicmd->result = DID_OK << 16 | |
2332 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2458 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
2333 | } else { | 2459 | } else { |
@@ -2482,6 +2608,18 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2482 | (fsa_dev_ptr[cid].block_size >> 8) & 0xff; | 2608 | (fsa_dev_ptr[cid].block_size >> 8) & 0xff; |
2483 | mpd.bd.block_length[2] = | 2609 | mpd.bd.block_length[2] = |
2484 | fsa_dev_ptr[cid].block_size & 0xff; | 2610 | fsa_dev_ptr[cid].block_size & 0xff; |
2611 | |||
2612 | mpd.mpc_buf[0] = scsicmd->cmnd[2]; | ||
2613 | if (scsicmd->cmnd[2] == 0x1C) { | ||
2614 | /* page length */ | ||
2615 | mpd.mpc_buf[1] = 0xa; | ||
2616 | /* Mode data length */ | ||
2617 | mpd.hd.data_length = 23; | ||
2618 | } else { | ||
2619 | /* Mode data length */ | ||
2620 | mpd.hd.data_length = 15; | ||
2621 | } | ||
2622 | |||
2485 | if (capacity > 0xffffff) { | 2623 | if (capacity > 0xffffff) { |
2486 | mpd.bd.block_count[0] = 0xff; | 2624 | mpd.bd.block_count[0] = 0xff; |
2487 | mpd.bd.block_count[1] = 0xff; | 2625 | mpd.bd.block_count[1] = 0xff; |
@@ -2500,9 +2638,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2500 | mpd.mpc_buf[2] = ((aac_cache & 6) == 2) | 2638 | mpd.mpc_buf[2] = ((aac_cache & 6) == 2) |
2501 | ? 0 : 0x04; /* WCE */ | 2639 | ? 0 : 0x04; /* WCE */ |
2502 | mode_buf_length = sizeof(mpd); | 2640 | mode_buf_length = sizeof(mpd); |
2503 | if (mode_buf_length > scsicmd->cmnd[4]) | ||
2504 | mode_buf_length = scsicmd->cmnd[4]; | ||
2505 | } | 2641 | } |
2642 | |||
2643 | if (mode_buf_length > scsicmd->cmnd[4]) | ||
2644 | mode_buf_length = scsicmd->cmnd[4]; | ||
2645 | else | ||
2646 | mode_buf_length = sizeof(mpd); | ||
2506 | scsi_sg_copy_from_buffer(scsicmd, | 2647 | scsi_sg_copy_from_buffer(scsicmd, |
2507 | (char *)&mpd, | 2648 | (char *)&mpd, |
2508 | mode_buf_length); | 2649 | mode_buf_length); |