aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Grover <agrover@redhat.com>2012-01-16 19:57:08 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2012-01-18 03:35:58 -0500
commit4949314c7283ea4f9ade182ca599583b89f7edd6 (patch)
treebbd2316996bc2f19c1b3a8c24f8591f12d2330fa
parente8904dc5008ef92f0f62391d6557f03f921eeb32 (diff)
target: Allow control CDBs with data > 1 page
We need to handle >1 page control cdbs, so extend the code to do a vmap if bigger than 1 page. It seems like kmap() is still preferable if just a page, fewer TLB shootdowns(?), so keep using that when possible. Rename function pair for their new scope. Signed-off-by: Andy Grover <agrover@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/target_core_alua.c8
-rw-r--r--drivers/target/target_core_cdb.c28
-rw-r--r--drivers/target/target_core_device.c4
-rw-r--r--drivers/target/target_core_pr.c38
-rw-r--r--drivers/target/target_core_pscsi.c4
-rw-r--r--drivers/target/target_core_transport.c45
-rw-r--r--include/target/target_core_backend.h4
-rw-r--r--include/target/target_core_base.h1
8 files changed, 78 insertions, 54 deletions
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 1b1edd14f4bf..01a2691dfb47 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
78 return -EINVAL; 78 return -EINVAL;
79 } 79 }
80 80
81 buf = transport_kmap_first_data_page(cmd); 81 buf = transport_kmap_data_sg(cmd);
82 82
83 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); 83 spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
84 list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, 84 list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
@@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
163 buf[2] = ((rd_len >> 8) & 0xff); 163 buf[2] = ((rd_len >> 8) & 0xff);
164 buf[3] = (rd_len & 0xff); 164 buf[3] = (rd_len & 0xff);
165 165
166 transport_kunmap_first_data_page(cmd); 166 transport_kunmap_data_sg(cmd);
167 167
168 task->task_scsi_status = GOOD; 168 task->task_scsi_status = GOOD;
169 transport_complete_task(task, 1); 169 transport_complete_task(task, 1);
@@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
194 cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; 194 cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
195 return -EINVAL; 195 return -EINVAL;
196 } 196 }
197 buf = transport_kmap_first_data_page(cmd); 197 buf = transport_kmap_data_sg(cmd);
198 198
199 /* 199 /*
200 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed 200 * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
@@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
351 } 351 }
352 352
353out: 353out:
354 transport_kunmap_first_data_page(cmd); 354 transport_kunmap_data_sg(cmd);
355 task->task_scsi_status = GOOD; 355 task->task_scsi_status = GOOD;
356 transport_complete_task(task, 1); 356 transport_complete_task(task, 1);
357 return 0; 357 return 0;
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
index 2f2235edefff..07a3025d0622 100644
--- a/drivers/target/target_core_cdb.c
+++ b/drivers/target/target_core_cdb.c
@@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
83 return -EINVAL; 83 return -EINVAL;
84 } 84 }
85 85
86 buf = transport_kmap_first_data_page(cmd); 86 buf = transport_kmap_data_sg(cmd);
87 87
88 if (dev == tpg->tpg_virt_lun0.lun_se_dev) { 88 if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
89 buf[0] = 0x3f; /* Not connected */ 89 buf[0] = 0x3f; /* Not connected */
@@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
134 buf[4] = 31; /* Set additional length to 31 */ 134 buf[4] = 31; /* Set additional length to 31 */
135 135
136out: 136out:
137 transport_kunmap_first_data_page(cmd); 137 transport_kunmap_data_sg(cmd);
138 return 0; 138 return 0;
139} 139}
140 140
@@ -716,7 +716,7 @@ int target_emulate_inquiry(struct se_task *task)
716 return -EINVAL; 716 return -EINVAL;
717 } 717 }
718 718
719 buf = transport_kmap_first_data_page(cmd); 719 buf = transport_kmap_data_sg(cmd);
720 720
721 buf[0] = dev->transport->get_device_type(dev); 721 buf[0] = dev->transport->get_device_type(dev);
722 722
@@ -733,7 +733,7 @@ int target_emulate_inquiry(struct se_task *task)
733 ret = -EINVAL; 733 ret = -EINVAL;
734 734
735out_unmap: 735out_unmap:
736 transport_kunmap_first_data_page(cmd); 736 transport_kunmap_data_sg(cmd);
737out: 737out:
738 if (!ret) { 738 if (!ret) {
739 task->task_scsi_status = GOOD; 739 task->task_scsi_status = GOOD;
@@ -755,7 +755,7 @@ int target_emulate_readcapacity(struct se_task *task)
755 else 755 else
756 blocks = (u32)blocks_long; 756 blocks = (u32)blocks_long;
757 757
758 buf = transport_kmap_first_data_page(cmd); 758 buf = transport_kmap_data_sg(cmd);
759 759
760 buf[0] = (blocks >> 24) & 0xff; 760 buf[0] = (blocks >> 24) & 0xff;
761 buf[1] = (blocks >> 16) & 0xff; 761 buf[1] = (blocks >> 16) & 0xff;
@@ -771,7 +771,7 @@ int target_emulate_readcapacity(struct se_task *task)
771 if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) 771 if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
772 put_unaligned_be32(0xFFFFFFFF, &buf[0]); 772 put_unaligned_be32(0xFFFFFFFF, &buf[0]);
773 773
774 transport_kunmap_first_data_page(cmd); 774 transport_kunmap_data_sg(cmd);
775 775
776 task->task_scsi_status = GOOD; 776 task->task_scsi_status = GOOD;
777 transport_complete_task(task, 1); 777 transport_complete_task(task, 1);
@@ -785,7 +785,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
785 unsigned char *buf; 785 unsigned char *buf;
786 unsigned long long blocks = dev->transport->get_blocks(dev); 786 unsigned long long blocks = dev->transport->get_blocks(dev);
787 787
788 buf = transport_kmap_first_data_page(cmd); 788 buf = transport_kmap_data_sg(cmd);
789 789
790 buf[0] = (blocks >> 56) & 0xff; 790 buf[0] = (blocks >> 56) & 0xff;
791 buf[1] = (blocks >> 48) & 0xff; 791 buf[1] = (blocks >> 48) & 0xff;
@@ -806,7 +806,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
806 if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) 806 if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
807 buf[14] = 0x80; 807 buf[14] = 0x80;
808 808
809 transport_kunmap_first_data_page(cmd); 809 transport_kunmap_data_sg(cmd);
810 810
811 task->task_scsi_status = GOOD; 811 task->task_scsi_status = GOOD;
812 transport_complete_task(task, 1); 812 transport_complete_task(task, 1);
@@ -1019,9 +1019,9 @@ int target_emulate_modesense(struct se_task *task)
1019 offset = cmd->data_length; 1019 offset = cmd->data_length;
1020 } 1020 }
1021 1021
1022 rbuf = transport_kmap_first_data_page(cmd); 1022 rbuf = transport_kmap_data_sg(cmd);
1023 memcpy(rbuf, buf, offset); 1023 memcpy(rbuf, buf, offset);
1024 transport_kunmap_first_data_page(cmd); 1024 transport_kunmap_data_sg(cmd);
1025 1025
1026 task->task_scsi_status = GOOD; 1026 task->task_scsi_status = GOOD;
1027 transport_complete_task(task, 1); 1027 transport_complete_task(task, 1);
@@ -1043,7 +1043,7 @@ int target_emulate_request_sense(struct se_task *task)
1043 return -ENOSYS; 1043 return -ENOSYS;
1044 } 1044 }
1045 1045
1046 buf = transport_kmap_first_data_page(cmd); 1046 buf = transport_kmap_data_sg(cmd);
1047 1047
1048 if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { 1048 if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
1049 /* 1049 /*
@@ -1089,7 +1089,7 @@ int target_emulate_request_sense(struct se_task *task)
1089 } 1089 }
1090 1090
1091end: 1091end:
1092 transport_kunmap_first_data_page(cmd); 1092 transport_kunmap_data_sg(cmd);
1093 task->task_scsi_status = GOOD; 1093 task->task_scsi_status = GOOD;
1094 transport_complete_task(task, 1); 1094 transport_complete_task(task, 1);
1095 return 0; 1095 return 0;
@@ -1123,7 +1123,7 @@ int target_emulate_unmap(struct se_task *task)
1123 dl = get_unaligned_be16(&cdb[0]); 1123 dl = get_unaligned_be16(&cdb[0]);
1124 bd_dl = get_unaligned_be16(&cdb[2]); 1124 bd_dl = get_unaligned_be16(&cdb[2]);
1125 1125
1126 buf = transport_kmap_first_data_page(cmd); 1126 buf = transport_kmap_data_sg(cmd);
1127 1127
1128 ptr = &buf[offset]; 1128 ptr = &buf[offset];
1129 pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" 1129 pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
@@ -1147,7 +1147,7 @@ int target_emulate_unmap(struct se_task *task)
1147 } 1147 }
1148 1148
1149err: 1149err:
1150 transport_kunmap_first_data_page(cmd); 1150 transport_kunmap_data_sg(cmd);
1151 if (!ret) { 1151 if (!ret) {
1152 task->task_scsi_status = GOOD; 1152 task->task_scsi_status = GOOD;
1153 transport_complete_task(task, 1); 1153 transport_complete_task(task, 1);
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
index de5f4fea7f62..edbcabbf85f7 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -657,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
657 unsigned char *buf; 657 unsigned char *buf;
658 u32 cdb_offset = 0, lun_count = 0, offset = 8, i; 658 u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
659 659
660 buf = transport_kmap_first_data_page(se_cmd); 660 buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
661 661
662 /* 662 /*
663 * If no struct se_session pointer is present, this struct se_cmd is 663 * If no struct se_session pointer is present, this struct se_cmd is
@@ -695,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
695 * See SPC3 r07, page 159. 695 * See SPC3 r07, page 159.
696 */ 696 */
697done: 697done:
698 transport_kunmap_first_data_page(se_cmd); 698 transport_kunmap_data_sg(se_cmd);
699 lun_count *= 8; 699 lun_count *= 8;
700 buf[0] = ((lun_count >> 24) & 0xff); 700 buf[0] = ((lun_count >> 24) & 0xff);
701 buf[1] = ((lun_count >> 16) & 0xff); 701 buf[1] = ((lun_count >> 16) & 0xff);
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 68c71cd7a88e..b7c779389eea 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1535,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
1535 tidh_new->dest_local_nexus = 1; 1535 tidh_new->dest_local_nexus = 1;
1536 list_add_tail(&tidh_new->dest_list, &tid_dest_list); 1536 list_add_tail(&tidh_new->dest_list, &tid_dest_list);
1537 1537
1538 buf = transport_kmap_first_data_page(cmd); 1538 buf = transport_kmap_data_sg(cmd);
1539 /* 1539 /*
1540 * For a PERSISTENT RESERVE OUT specify initiator ports payload, 1540 * For a PERSISTENT RESERVE OUT specify initiator ports payload,
1541 * first extract TransportID Parameter Data Length, and make sure 1541 * first extract TransportID Parameter Data Length, and make sure
@@ -1786,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
1786 1786
1787 } 1787 }
1788 1788
1789 transport_kunmap_first_data_page(cmd); 1789 transport_kunmap_data_sg(cmd);
1790 1790
1791 /* 1791 /*
1792 * Go ahead and create a registrations from tid_dest_list for the 1792 * Go ahead and create a registrations from tid_dest_list for the
@@ -1834,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(
1834 1834
1835 return 0; 1835 return 0;
1836out: 1836out:
1837 transport_kunmap_first_data_page(cmd); 1837 transport_kunmap_data_sg(cmd);
1838 /* 1838 /*
1839 * For the failure case, release everything from tid_dest_list 1839 * For the failure case, release everything from tid_dest_list
1840 * including *dest_pr_reg and the configfs dependances.. 1840 * including *dest_pr_reg and the configfs dependances..
@@ -3411,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(
3411 * will be moved to for the TransportID containing SCSI initiator WWN 3411 * will be moved to for the TransportID containing SCSI initiator WWN
3412 * information. 3412 * information.
3413 */ 3413 */
3414 buf = transport_kmap_first_data_page(cmd); 3414 buf = transport_kmap_data_sg(cmd);
3415 rtpi = (buf[18] & 0xff) << 8; 3415 rtpi = (buf[18] & 0xff) << 8;
3416 rtpi |= buf[19] & 0xff; 3416 rtpi |= buf[19] & 0xff;
3417 tid_len = (buf[20] & 0xff) << 24; 3417 tid_len = (buf[20] & 0xff) << 24;
3418 tid_len |= (buf[21] & 0xff) << 16; 3418 tid_len |= (buf[21] & 0xff) << 16;
3419 tid_len |= (buf[22] & 0xff) << 8; 3419 tid_len |= (buf[22] & 0xff) << 8;
3420 tid_len |= buf[23] & 0xff; 3420 tid_len |= buf[23] & 0xff;
3421 transport_kunmap_first_data_page(cmd); 3421 transport_kunmap_data_sg(cmd);
3422 buf = NULL; 3422 buf = NULL;
3423 3423
3424 if ((tid_len + 24) != cmd->data_length) { 3424 if ((tid_len + 24) != cmd->data_length) {
@@ -3470,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(
3470 return -EINVAL; 3470 return -EINVAL;
3471 } 3471 }
3472 3472
3473 buf = transport_kmap_first_data_page(cmd); 3473 buf = transport_kmap_data_sg(cmd);
3474 proto_ident = (buf[24] & 0x0f); 3474 proto_ident = (buf[24] & 0x0f);
3475#if 0 3475#if 0
3476 pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" 3476 pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
@@ -3504,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(
3504 goto out; 3504 goto out;
3505 } 3505 }
3506 3506
3507 transport_kunmap_first_data_page(cmd); 3507 transport_kunmap_data_sg(cmd);
3508 buf = NULL; 3508 buf = NULL;
3509 3509
3510 pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" 3510 pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
@@ -3769,13 +3769,13 @@ after_iport_check:
3769 " REGISTER_AND_MOVE\n"); 3769 " REGISTER_AND_MOVE\n");
3770 } 3770 }
3771 3771
3772 transport_kunmap_first_data_page(cmd); 3772 transport_kunmap_data_sg(cmd);
3773 3773
3774 core_scsi3_put_pr_reg(dest_pr_reg); 3774 core_scsi3_put_pr_reg(dest_pr_reg);
3775 return 0; 3775 return 0;
3776out: 3776out:
3777 if (buf) 3777 if (buf)
3778 transport_kunmap_first_data_page(cmd); 3778 transport_kunmap_data_sg(cmd);
3779 if (dest_se_deve) 3779 if (dest_se_deve)
3780 core_scsi3_lunacl_undepend_item(dest_se_deve); 3780 core_scsi3_lunacl_undepend_item(dest_se_deve);
3781 if (dest_node_acl) 3781 if (dest_node_acl)
@@ -3849,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
3849 scope = (cdb[2] & 0xf0); 3849 scope = (cdb[2] & 0xf0);
3850 type = (cdb[2] & 0x0f); 3850 type = (cdb[2] & 0x0f);
3851 3851
3852 buf = transport_kmap_first_data_page(cmd); 3852 buf = transport_kmap_data_sg(cmd);
3853 /* 3853 /*
3854 * From PERSISTENT_RESERVE_OUT parameter list (payload) 3854 * From PERSISTENT_RESERVE_OUT parameter list (payload)
3855 */ 3855 */
@@ -3867,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
3867 aptpl = (buf[17] & 0x01); 3867 aptpl = (buf[17] & 0x01);
3868 unreg = (buf[17] & 0x02); 3868 unreg = (buf[17] & 0x02);
3869 } 3869 }
3870 transport_kunmap_first_data_page(cmd); 3870 transport_kunmap_data_sg(cmd);
3871 buf = NULL; 3871 buf = NULL;
3872 3872
3873 /* 3873 /*
@@ -3967,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
3967 return -EINVAL; 3967 return -EINVAL;
3968 } 3968 }
3969 3969
3970 buf = transport_kmap_first_data_page(cmd); 3970 buf = transport_kmap_data_sg(cmd);
3971 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); 3971 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
3972 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); 3972 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
3973 buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); 3973 buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4001,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
4001 buf[6] = ((add_len >> 8) & 0xff); 4001 buf[6] = ((add_len >> 8) & 0xff);
4002 buf[7] = (add_len & 0xff); 4002 buf[7] = (add_len & 0xff);
4003 4003
4004 transport_kunmap_first_data_page(cmd); 4004 transport_kunmap_data_sg(cmd);
4005 4005
4006 return 0; 4006 return 0;
4007} 4007}
@@ -4027,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
4027 return -EINVAL; 4027 return -EINVAL;
4028 } 4028 }
4029 4029
4030 buf = transport_kmap_first_data_page(cmd); 4030 buf = transport_kmap_data_sg(cmd);
4031 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); 4031 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
4032 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); 4032 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
4033 buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); 4033 buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
@@ -4086,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
4086 4086
4087err: 4087err:
4088 spin_unlock(&se_dev->dev_reservation_lock); 4088 spin_unlock(&se_dev->dev_reservation_lock);
4089 transport_kunmap_first_data_page(cmd); 4089 transport_kunmap_data_sg(cmd);
4090 4090
4091 return 0; 4091 return 0;
4092} 4092}
@@ -4110,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
4110 return -EINVAL; 4110 return -EINVAL;
4111 } 4111 }
4112 4112
4113 buf = transport_kmap_first_data_page(cmd); 4113 buf = transport_kmap_data_sg(cmd);
4114 4114
4115 buf[0] = ((add_len << 8) & 0xff); 4115 buf[0] = ((add_len << 8) & 0xff);
4116 buf[1] = (add_len & 0xff); 4116 buf[1] = (add_len & 0xff);
@@ -4142,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
4142 buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ 4142 buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
4143 buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ 4143 buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
4144 4144
4145 transport_kunmap_first_data_page(cmd); 4145 transport_kunmap_data_sg(cmd);
4146 4146
4147 return 0; 4147 return 0;
4148} 4148}
@@ -4172,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
4172 return -EINVAL; 4172 return -EINVAL;
4173 } 4173 }
4174 4174
4175 buf = transport_kmap_first_data_page(cmd); 4175 buf = transport_kmap_data_sg(cmd);
4176 4176
4177 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); 4177 buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
4178 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); 4178 buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
@@ -4293,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
4293 buf[6] = ((add_len >> 8) & 0xff); 4293 buf[6] = ((add_len >> 8) & 0xff);
4294 buf[7] = (add_len & 0xff); 4294 buf[7] = (add_len & 0xff);
4295 4295
4296 transport_kunmap_first_data_page(cmd); 4296 transport_kunmap_data_sg(cmd);
4297 4297
4298 return 0; 4298 return 0;
4299} 4299}
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index d35467d42e12..8d4def30e9e8 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)
693 693
694 if (task->task_se_cmd->se_deve->lun_flags & 694 if (task->task_se_cmd->se_deve->lun_flags &
695 TRANSPORT_LUNFLAGS_READ_ONLY) { 695 TRANSPORT_LUNFLAGS_READ_ONLY) {
696 unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd); 696 unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
697 697
698 if (cdb[0] == MODE_SENSE_10) { 698 if (cdb[0] == MODE_SENSE_10) {
699 if (!(buf[3] & 0x80)) 699 if (!(buf[3] & 0x80))
@@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)
703 buf[2] |= 0x80; 703 buf[2] |= 0x80;
704 } 704 }
705 705
706 transport_kunmap_first_data_page(task->task_se_cmd); 706 transport_kunmap_data_sg(task->task_se_cmd);
707 } 707 }
708 } 708 }
709after_mode_sense: 709after_mode_sense:
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index e186f7db3860..cf996d81cfcb 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -3084,11 +3084,6 @@ static int transport_generic_cmd_sequencer(
3084 (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) 3084 (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
3085 goto out_unsupported_cdb; 3085 goto out_unsupported_cdb;
3086 3086
3087 /* Let's limit control cdbs to a page, for simplicity's sake. */
3088 if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
3089 size > PAGE_SIZE)
3090 goto out_invalid_cdb_field;
3091
3092 transport_set_supported_SAM_opcode(cmd); 3087 transport_set_supported_SAM_opcode(cmd);
3093 return ret; 3088 return ret;
3094 3089
@@ -3492,9 +3487,11 @@ int transport_generic_map_mem_to_cmd(
3492} 3487}
3493EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); 3488EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
3494 3489
3495void *transport_kmap_first_data_page(struct se_cmd *cmd) 3490void *transport_kmap_data_sg(struct se_cmd *cmd)
3496{ 3491{
3497 struct scatterlist *sg = cmd->t_data_sg; 3492 struct scatterlist *sg = cmd->t_data_sg;
3493 struct page **pages;
3494 int i;
3498 3495
3499 BUG_ON(!sg); 3496 BUG_ON(!sg);
3500 /* 3497 /*
@@ -3502,15 +3499,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)
3502 * tcm_loop who may be using a contig buffer from the SCSI midlayer for 3499 * tcm_loop who may be using a contig buffer from the SCSI midlayer for
3503 * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd() 3500 * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
3504 */ 3501 */
3505 return kmap(sg_page(sg)) + sg->offset; 3502 if (!cmd->t_data_nents)
3503 return NULL;
3504 else if (cmd->t_data_nents == 1)
3505 return kmap(sg_page(sg)) + sg->offset;
3506
3507 /* >1 page. use vmap */
3508 pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
3509 if (!pages)
3510 return NULL;
3511
3512 /* convert sg[] to pages[] */
3513 for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
3514 pages[i] = sg_page(sg);
3515 }
3516
3517 cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL);
3518 kfree(pages);
3519 if (!cmd->t_data_vmap)
3520 return NULL;
3521
3522 return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
3506} 3523}
3507EXPORT_SYMBOL(transport_kmap_first_data_page); 3524EXPORT_SYMBOL(transport_kmap_data_sg);
3508 3525
3509void transport_kunmap_first_data_page(struct se_cmd *cmd) 3526void transport_kunmap_data_sg(struct se_cmd *cmd)
3510{ 3527{
3511 kunmap(sg_page(cmd->t_data_sg)); 3528 if (!cmd->t_data_nents)
3529 return;
3530 else if (cmd->t_data_nents == 1)
3531 kunmap(sg_page(cmd->t_data_sg));
3532
3533 vunmap(cmd->t_data_vmap);
3534 cmd->t_data_vmap = NULL;
3512} 3535}
3513EXPORT_SYMBOL(transport_kunmap_first_data_page); 3536EXPORT_SYMBOL(transport_kunmap_data_sg);
3514 3537
3515static int 3538static int
3516transport_generic_get_mem(struct se_cmd *cmd) 3539transport_generic_get_mem(struct se_cmd *cmd)
diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h
index 4866499bdeeb..e5e6ff98f0fa 100644
--- a/include/target/target_core_backend.h
+++ b/include/target/target_core_backend.h
@@ -59,7 +59,7 @@ int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
59int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); 59int transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
60 60
61/* core helpers also used by command snooping in pscsi */ 61/* core helpers also used by command snooping in pscsi */
62void *transport_kmap_first_data_page(struct se_cmd *); 62void *transport_kmap_data_sg(struct se_cmd *);
63void transport_kunmap_first_data_page(struct se_cmd *); 63void transport_kunmap_data_sg(struct se_cmd *);
64 64
65#endif /* TARGET_CORE_BACKEND_H */ 65#endif /* TARGET_CORE_BACKEND_H */
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index daf532bc721a..dc4e345a0163 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -582,6 +582,7 @@ struct se_cmd {
582 582
583 struct scatterlist *t_data_sg; 583 struct scatterlist *t_data_sg;
584 unsigned int t_data_nents; 584 unsigned int t_data_nents;
585 void *t_data_vmap;
585 struct scatterlist *t_bidi_data_sg; 586 struct scatterlist *t_bidi_data_sg;
586 unsigned int t_bidi_data_nents; 587 unsigned int t_bidi_data_nents;
587 588