aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/target/target_core_cdb.c
diff options
context:
space:
mode:
authorRoland Dreier <roland@purestorage.com>2011-07-05 16:34:51 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2011-07-22 05:37:47 -0400
commitb2eb705e00a9b9a9b3122192a7ab3e9058f0c48a (patch)
tree3eec44a2dcec8d389a5363f2d7b0748a904eceae /drivers/target/target_core_cdb.c
parentf5fbed856931faa1e94a76caf0f0c273c67f0d32 (diff)
target: Fix reporting of supported VPD pages
The current handling of VPD page 00h (Supported VPD Pages) for INQUIRY commands has a couple of problems: - The page length field is incorrectly set to 3, so the entry for 86h (Extended INQUIRY Data) is ignored since it is in the fourth slot. - Even though the code handles pages B0h and B2h, those pages aren't mentioned in the Supported VPD Pages list, so eg the Linux SCSI stack won't actually try to use them. Fix these problems and make things more robust to avoid future problems by moving to a table of supported VPD pages, which means that any added VPD page support will automatically get reported on page 0. Signed-off-by: Roland Dreier <roland@purestorage.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target/target_core_cdb.c')
-rw-r--r--drivers/target/target_core_cdb.c95
1 files changed, 47 insertions, 48 deletions
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 09ef3f811567..1157e0c6dba6 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -114,31 +114,6 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
114 return 0; 114 return 0;
115} 115}
116 116
117/* supported vital product data pages */
118static int
119target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
120{
121 buf[1] = 0x00;
122 if (cmd->data_length < 8)
123 return 0;
124
125 buf[4] = 0x0;
126 /*
127 * Only report the INQUIRY EVPD=1 pages after a valid NAA
128 * Registered Extended LUN WWN has been set via ConfigFS
129 * during device creation/restart.
130 */
131 if (cmd->se_dev->se_sub_dev->su_dev_flags &
132 SDF_EMULATED_VPD_UNIT_SERIAL) {
133 buf[3] = 3;
134 buf[5] = 0x80;
135 buf[6] = 0x83;
136 buf[7] = 0x86;
137 }
138
139 return 0;
140}
141
142/* unit serial number */ 117/* unit serial number */
143static int 118static int
144target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf) 119target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
@@ -146,7 +121,6 @@ target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
146 struct se_device *dev = cmd->se_dev; 121 struct se_device *dev = cmd->se_dev;
147 u16 len = 0; 122 u16 len = 0;
148 123
149 buf[1] = 0x80;
150 if (dev->se_sub_dev->su_dev_flags & 124 if (dev->se_sub_dev->su_dev_flags &
151 SDF_EMULATED_VPD_UNIT_SERIAL) { 125 SDF_EMULATED_VPD_UNIT_SERIAL) {
152 u32 unit_serial_len; 126 u32 unit_serial_len;
@@ -190,7 +164,6 @@ target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
190 int i; 164 int i;
191 u16 len = 0, id_len; 165 u16 len = 0, id_len;
192 166
193 buf[1] = 0x83;
194 off = 4; 167 off = 4;
195 168
196 /* 169 /*
@@ -471,7 +444,6 @@ target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
471 if (cmd->data_length < 60) 444 if (cmd->data_length < 60)
472 return 0; 445 return 0;
473 446
474 buf[1] = 0x86;
475 buf[2] = 0x3c; 447 buf[2] = 0x3c;
476 /* Set HEADSUP, ORDSUP, SIMPSUP */ 448 /* Set HEADSUP, ORDSUP, SIMPSUP */
477 buf[5] = 0x07; 449 buf[5] = 0x07;
@@ -512,7 +484,6 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
512 } 484 }
513 485
514 buf[0] = dev->transport->get_device_type(dev); 486 buf[0] = dev->transport->get_device_type(dev);
515 buf[1] = 0xb0;
516 buf[3] = have_tp ? 0x3c : 0x10; 487 buf[3] = have_tp ? 0x3c : 0x10;
517 488
518 /* 489 /*
@@ -579,7 +550,6 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
579 * defined in table 162. 550 * defined in table 162.
580 */ 551 */
581 buf[0] = dev->transport->get_device_type(dev); 552 buf[0] = dev->transport->get_device_type(dev);
582 buf[1] = 0xb2;
583 553
584 /* 554 /*
585 * Set Hardcoded length mentioned above for DP=0 555 * Set Hardcoded length mentioned above for DP=0
@@ -618,11 +588,51 @@ target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
618} 588}
619 589
620static int 590static int
591target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
592
593static struct {
594 uint8_t page;
595 int (*emulate)(struct se_cmd *, unsigned char *);
596} evpd_handlers[] = {
597 { .page = 0x00, .emulate = target_emulate_evpd_00 },
598 { .page = 0x80, .emulate = target_emulate_evpd_80 },
599 { .page = 0x83, .emulate = target_emulate_evpd_83 },
600 { .page = 0x86, .emulate = target_emulate_evpd_86 },
601 { .page = 0xb0, .emulate = target_emulate_evpd_b0 },
602 { .page = 0xb2, .emulate = target_emulate_evpd_b2 },
603};
604
605/* supported vital product data pages */
606static int
607target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
608{
609 int p;
610
611 if (cmd->data_length < 8)
612 return 0;
613 /*
614 * Only report the INQUIRY EVPD=1 pages after a valid NAA
615 * Registered Extended LUN WWN has been set via ConfigFS
616 * during device creation/restart.
617 */
618 if (cmd->se_dev->se_sub_dev->su_dev_flags &
619 SDF_EMULATED_VPD_UNIT_SERIAL) {
620 buf[3] = ARRAY_SIZE(evpd_handlers);
621 for (p = 0; p < min_t(int, ARRAY_SIZE(evpd_handlers),
622 cmd->data_length - 4); ++p)
623 buf[p + 4] = evpd_handlers[p].page;
624 }
625
626 return 0;
627}
628
629static int
621target_emulate_inquiry(struct se_cmd *cmd) 630target_emulate_inquiry(struct se_cmd *cmd)
622{ 631{
623 struct se_device *dev = cmd->se_dev; 632 struct se_device *dev = cmd->se_dev;
624 unsigned char *buf = cmd->t_task_buf; 633 unsigned char *buf = cmd->t_task_buf;
625 unsigned char *cdb = cmd->t_task_cdb; 634 unsigned char *cdb = cmd->t_task_cdb;
635 int p;
626 636
627 if (!(cdb[1] & 0x1)) 637 if (!(cdb[1] & 0x1))
628 return target_emulate_inquiry_std(cmd); 638 return target_emulate_inquiry_std(cmd);
@@ -641,25 +651,14 @@ target_emulate_inquiry(struct se_cmd *cmd)
641 } 651 }
642 buf[0] = dev->transport->get_device_type(dev); 652 buf[0] = dev->transport->get_device_type(dev);
643 653
644 switch (cdb[2]) { 654 for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
645 case 0x00: 655 if (cdb[2] == evpd_handlers[p].page) {
646 return target_emulate_evpd_00(cmd, buf); 656 buf[1] = cdb[2];
647 case 0x80: 657 return evpd_handlers[p].emulate(cmd, buf);
648 return target_emulate_evpd_80(cmd, buf); 658 }
649 case 0x83:
650 return target_emulate_evpd_83(cmd, buf);
651 case 0x86:
652 return target_emulate_evpd_86(cmd, buf);
653 case 0xb0:
654 return target_emulate_evpd_b0(cmd, buf);
655 case 0xb2:
656 return target_emulate_evpd_b2(cmd, buf);
657 default:
658 printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]);
659 return -EINVAL;
660 }
661 659
662 return 0; 660 printk(KERN_ERR "Unknown VPD Code: 0x%02x\n", cdb[2]);
661 return -EINVAL;
663} 662}
664 663
665static int 664static int