aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2014-03-15 04:51:49 -0400
committerJames Bottomley <JBottomley@Parallels.com>2014-03-27 11:25:33 -0400
commitb3ae8780b42918111387240762f470d5c1e269d6 (patch)
treef3791a3002248327f6f72a9335a275b123e06dab /drivers/scsi/scsi.c
parentbc8945df3c27e8edaa6a6de47cb20df7d12b80c8 (diff)
[SCSI] Add EVPD page 0x83 and 0x80 to sysfs
EVPD page 0x83 is used to uniquely identify the device. So instead of having each and every program issue a separate SG_IO call to retrieve this information it does make far more sense to display it in sysfs. Some older devices (most notably tapes) will only report reliable information in page 0x80 (Unit Serial Number). So export this in the sysfs attribute 'vpd_pg80'. [jejb: checkpatch fix] [hare: attach after transport configure] [fengguang.wu@intel.com: spotted problems with the original now fixed] Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/scsi.c')
-rw-r--r--drivers/scsi/scsi.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index b2526ad7b9a1..1d98ac960887 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1030,6 +1030,93 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
1030EXPORT_SYMBOL_GPL(scsi_get_vpd_page); 1030EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
1031 1031
1032/** 1032/**
1033 * scsi_attach_vpd - Attach Vital Product Data to a SCSI device structure
1034 * @sdev: The device to ask
1035 *
1036 * Attach the 'Device Identification' VPD page (0x83) and the
1037 * 'Unit Serial Number' VPD page (0x80) to a SCSI device
1038 * structure. This information can be used to identify the device
1039 * uniquely.
1040 */
1041void scsi_attach_vpd(struct scsi_device *sdev)
1042{
1043 int result, i;
1044 int vpd_len = SCSI_VPD_PG_LEN;
1045 int pg80_supported = 0;
1046 int pg83_supported = 0;
1047 unsigned char *vpd_buf;
1048
1049 if (sdev->skip_vpd_pages)
1050 return;
1051retry_pg0:
1052 vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
1053 if (!vpd_buf)
1054 return;
1055
1056 /* Ask for all the pages supported by this device */
1057 result = scsi_vpd_inquiry(sdev, vpd_buf, 0, vpd_len);
1058 if (result < 0) {
1059 kfree(vpd_buf);
1060 return;
1061 }
1062 if (result > vpd_len) {
1063 vpd_len = result;
1064 kfree(vpd_buf);
1065 goto retry_pg0;
1066 }
1067
1068 for (i = 4; i < result; i++) {
1069 if (vpd_buf[i] == 0x80)
1070 pg80_supported = 1;
1071 if (vpd_buf[i] == 0x83)
1072 pg83_supported = 1;
1073 }
1074 kfree(vpd_buf);
1075 vpd_len = SCSI_VPD_PG_LEN;
1076
1077 if (pg80_supported) {
1078retry_pg80:
1079 vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
1080 if (!vpd_buf)
1081 return;
1082
1083 result = scsi_vpd_inquiry(sdev, vpd_buf, 0x80, vpd_len);
1084 if (result < 0) {
1085 kfree(vpd_buf);
1086 return;
1087 }
1088 if (result > vpd_len) {
1089 vpd_len = result;
1090 kfree(vpd_buf);
1091 goto retry_pg80;
1092 }
1093 sdev->vpd_pg80_len = result;
1094 sdev->vpd_pg80 = vpd_buf;
1095 vpd_len = SCSI_VPD_PG_LEN;
1096 }
1097
1098 if (pg83_supported) {
1099retry_pg83:
1100 vpd_buf = kmalloc(vpd_len, GFP_KERNEL);
1101 if (!vpd_buf)
1102 return;
1103
1104 result = scsi_vpd_inquiry(sdev, vpd_buf, 0x83, vpd_len);
1105 if (result < 0) {
1106 kfree(vpd_buf);
1107 return;
1108 }
1109 if (result > vpd_len) {
1110 vpd_len = result;
1111 kfree(vpd_buf);
1112 goto retry_pg83;
1113 }
1114 sdev->vpd_pg83_len = result;
1115 sdev->vpd_pg83 = vpd_buf;
1116 }
1117}
1118
1119/**
1033 * scsi_report_opcode - Find out if a given command opcode is supported 1120 * scsi_report_opcode - Find out if a given command opcode is supported
1034 * @sdev: scsi device to query 1121 * @sdev: scsi device to query
1035 * @buffer: scratch buffer (must be at least 20 bytes long) 1122 * @buffer: scratch buffer (must be at least 20 bytes long)