@@ -23,6 +23,7 @@
#include <linux/scatterlist.h>
#include <linux/blk-mq.h>
#include <linux/ratelimit.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -3286,3 +3287,44 @@ next_desig:
return id_size;
}
EXPORT_SYMBOL(scsi_vpd_lun_id);
+
+/*
+ * scsi_vpd_tpg_id - return a target port group identifier
+ * @sdev: SCSI device
+ *
+ * Returns the Target Port Group identifier from the information
+ * froom VPD page 0x83 of the device.
+ *
+ * Returns the identifier or error on failure.
+ */
+int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
+{
+ unsigned char *d;
+ int group_id = -EAGAIN, rel_port = -1;
+
+ if (!sdev->vpd_pg83)
+ return -ENXIO;
+
+ d = sdev->vpd_pg83 + 4;
+ while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
+ switch (d[1] & 0xf) {
+ case 0x4:
+ /* Relative target port */
+ rel_port = get_unaligned_be16(&d[6]);
+ break;
+ case 0x5:
+ /* Target port group */
+ group_id = get_unaligned_be16(&d[6]);
+ break;
+ default:
+ break;
+ }
+ d += d[3] + 4;
+ }
+
+ if (group_id >= 0 && rel_id && rel_port != -1)
+ *rel_id = rel_port;
+
+ return group_id;
+}
+EXPORT_SYMBOL(scsi_vpd_tpg_id);
@@ -415,6 +415,7 @@ static inline int scsi_execute_req(struct scsi_device *sdev,
extern void sdev_disable_disk_events(struct scsi_device *sdev);
extern void sdev_enable_disk_events(struct scsi_device *sdev);
extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t);
+extern int scsi_vpd_tpg_id(struct scsi_device *, int *);
#ifdef CONFIG_PM
extern int scsi_autopm_get_device(struct scsi_device *);
Implement scsi_vpd_tpg_id() to extract the target port group id and the relative port id from SCSI VPD page 0x83. Signed-off-by: Hannes Reinecke <hare@suse.de> --- drivers/scsi/scsi_lib.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_device.h | 1 + 2 files changed, 43 insertions(+)