diff options
author | Andy Grover <agrover@redhat.com> | 2012-01-16 19:57:08 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2012-01-18 03:35:58 -0500 |
commit | 4949314c7283ea4f9ade182ca599583b89f7edd6 (patch) | |
tree | bbd2316996bc2f19c1b3a8c24f8591f12d2330fa | |
parent | e8904dc5008ef92f0f62391d6557f03f921eeb32 (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.c | 8 | ||||
-rw-r--r-- | drivers/target/target_core_cdb.c | 28 | ||||
-rw-r--r-- | drivers/target/target_core_device.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_pr.c | 38 | ||||
-rw-r--r-- | drivers/target/target_core_pscsi.c | 4 | ||||
-rw-r--r-- | drivers/target/target_core_transport.c | 45 | ||||
-rw-r--r-- | include/target/target_core_backend.h | 4 | ||||
-rw-r--r-- | include/target/target_core_base.h | 1 |
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 | ||
353 | out: | 353 | out: |
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 | ||
136 | out: | 136 | out: |
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 | ||
735 | out_unmap: | 735 | out_unmap: |
736 | transport_kunmap_first_data_page(cmd); | 736 | transport_kunmap_data_sg(cmd); |
737 | out: | 737 | out: |
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 | ||
1091 | end: | 1091 | end: |
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 | ||
1149 | err: | 1149 | err: |
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 | */ |
697 | done: | 697 | done: |
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; |
1836 | out: | 1836 | out: |
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; |
3776 | out: | 3776 | out: |
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 | ||
4087 | err: | 4087 | err: |
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 | } |
709 | after_mode_sense: | 709 | after_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 | } |
3493 | EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); | 3488 | EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); |
3494 | 3489 | ||
3495 | void *transport_kmap_first_data_page(struct se_cmd *cmd) | 3490 | void *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 | } |
3507 | EXPORT_SYMBOL(transport_kmap_first_data_page); | 3524 | EXPORT_SYMBOL(transport_kmap_data_sg); |
3508 | 3525 | ||
3509 | void transport_kunmap_first_data_page(struct se_cmd *cmd) | 3526 | void 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 | } |
3513 | EXPORT_SYMBOL(transport_kunmap_first_data_page); | 3536 | EXPORT_SYMBOL(transport_kunmap_data_sg); |
3514 | 3537 | ||
3515 | static int | 3538 | static int |
3516 | transport_generic_get_mem(struct se_cmd *cmd) | 3539 | transport_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 *); | |||
59 | int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); | 59 | int 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 */ |
62 | void *transport_kmap_first_data_page(struct se_cmd *); | 62 | void *transport_kmap_data_sg(struct se_cmd *); |
63 | void transport_kunmap_first_data_page(struct se_cmd *); | 63 | void 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 | ||