aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2015-12-01 04:16:57 -0500
committerMartin K. Petersen <martin.petersen@oracle.com>2015-12-02 16:43:11 -0500
commita8aa3978588a4fa2d9edabc151adedd97bbed091 (patch)
tree9ae512c691e807de7ad4e0aca2b5bbfb3906679f
parent248d4fe95f232010846bc648ce92e40b07544c5d (diff)
scsi: Add scsi_vpd_tpg_id()
Implement scsi_vpd_tpg_id() to extract the target port group id and the relative port id from SCSI VPD page 0x83. Reviewed-by: Johannes Thumshirn <jthumshirn@suse.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/scsi_lib.c48
-rw-r--r--include/scsi/scsi_device.h1
2 files changed, 49 insertions, 0 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index e352c2b7deaf..fa6b2c4eb7a2 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -23,6 +23,7 @@
23#include <linux/scatterlist.h> 23#include <linux/scatterlist.h>
24#include <linux/blk-mq.h> 24#include <linux/blk-mq.h>
25#include <linux/ratelimit.h> 25#include <linux/ratelimit.h>
26#include <asm/unaligned.h>
26 27
27#include <scsi/scsi.h> 28#include <scsi/scsi.h>
28#include <scsi/scsi_cmnd.h> 29#include <scsi/scsi_cmnd.h>
@@ -3294,3 +3295,50 @@ next_desig:
3294 return id_size; 3295 return id_size;
3295} 3296}
3296EXPORT_SYMBOL(scsi_vpd_lun_id); 3297EXPORT_SYMBOL(scsi_vpd_lun_id);
3298
3299/*
3300 * scsi_vpd_tpg_id - return a target port group identifier
3301 * @sdev: SCSI device
3302 *
3303 * Returns the Target Port Group identifier from the information
3304 * froom VPD page 0x83 of the device.
3305 *
3306 * Returns the identifier or error on failure.
3307 */
3308int scsi_vpd_tpg_id(struct scsi_device *sdev, int *rel_id)
3309{
3310 unsigned char *d;
3311 unsigned char __rcu *vpd_pg83;
3312 int group_id = -EAGAIN, rel_port = -1;
3313
3314 rcu_read_lock();
3315 vpd_pg83 = rcu_dereference(sdev->vpd_pg83);
3316 if (!vpd_pg83) {
3317 rcu_read_unlock();
3318 return -ENXIO;
3319 }
3320
3321 d = sdev->vpd_pg83 + 4;
3322 while (d < sdev->vpd_pg83 + sdev->vpd_pg83_len) {
3323 switch (d[1] & 0xf) {
3324 case 0x4:
3325 /* Relative target port */
3326 rel_port = get_unaligned_be16(&d[6]);
3327 break;
3328 case 0x5:
3329 /* Target port group */
3330 group_id = get_unaligned_be16(&d[6]);
3331 break;
3332 default:
3333 break;
3334 }
3335 d += d[3] + 4;
3336 }
3337 rcu_read_unlock();
3338
3339 if (group_id >= 0 && rel_id && rel_port != -1)
3340 *rel_id = rel_port;
3341
3342 return group_id;
3343}
3344EXPORT_SYMBOL(scsi_vpd_tpg_id);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 4c49cfa25cac..f63a16760ae9 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -416,6 +416,7 @@ static inline int scsi_execute_req(struct scsi_device *sdev,
416extern void sdev_disable_disk_events(struct scsi_device *sdev); 416extern void sdev_disable_disk_events(struct scsi_device *sdev);
417extern void sdev_enable_disk_events(struct scsi_device *sdev); 417extern void sdev_enable_disk_events(struct scsi_device *sdev);
418extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t); 418extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t);
419extern int scsi_vpd_tpg_id(struct scsi_device *, int *);
419 420
420#ifdef CONFIG_PM 421#ifdef CONFIG_PM
421extern int scsi_autopm_get_device(struct scsi_device *); 422extern int scsi_autopm_get_device(struct scsi_device *);