diff options
| author | Hannes Reinecke <hare@suse.de> | 2015-12-01 04:16:57 -0500 |
|---|---|---|
| committer | Martin K. Petersen <martin.petersen@oracle.com> | 2015-12-02 16:43:11 -0500 |
| commit | a8aa3978588a4fa2d9edabc151adedd97bbed091 (patch) | |
| tree | 9ae512c691e807de7ad4e0aca2b5bbfb3906679f | |
| parent | 248d4fe95f232010846bc648ce92e40b07544c5d (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.c | 48 | ||||
| -rw-r--r-- | include/scsi/scsi_device.h | 1 |
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 | } |
| 3296 | EXPORT_SYMBOL(scsi_vpd_lun_id); | 3297 | EXPORT_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 | */ | ||
| 3308 | int 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 | } | ||
| 3344 | EXPORT_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, | |||
| 416 | extern void sdev_disable_disk_events(struct scsi_device *sdev); | 416 | extern void sdev_disable_disk_events(struct scsi_device *sdev); |
| 417 | extern void sdev_enable_disk_events(struct scsi_device *sdev); | 417 | extern void sdev_enable_disk_events(struct scsi_device *sdev); |
| 418 | extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t); | 418 | extern int scsi_vpd_lun_id(struct scsi_device *, char *, size_t); |
| 419 | extern int scsi_vpd_tpg_id(struct scsi_device *, int *); | ||
| 419 | 420 | ||
| 420 | #ifdef CONFIG_PM | 421 | #ifdef CONFIG_PM |
| 421 | extern int scsi_autopm_get_device(struct scsi_device *); | 422 | extern int scsi_autopm_get_device(struct scsi_device *); |
