diff options
| -rw-r--r-- | drivers/target/target_core_cdb.c | 111 | ||||
| -rw-r--r-- | drivers/target/target_core_cdb.h | 14 | ||||
| -rw-r--r-- | drivers/target/target_core_transport.c | 112 |
3 files changed, 97 insertions, 140 deletions
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 5a03085304e5..683ba02b8247 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <target/target_core_transport.h> | 32 | #include <target/target_core_transport.h> |
| 33 | #include <target/target_core_fabric_ops.h> | 33 | #include <target/target_core_fabric_ops.h> |
| 34 | #include "target_core_ua.h" | 34 | #include "target_core_ua.h" |
| 35 | #include "target_core_cdb.h" | ||
| 35 | 36 | ||
| 36 | static void | 37 | static void |
| 37 | target_fill_alua_data(struct se_port *port, unsigned char *buf) | 38 | target_fill_alua_data(struct se_port *port, unsigned char *buf) |
| @@ -679,8 +680,7 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf) | |||
| 679 | return 0; | 680 | return 0; |
| 680 | } | 681 | } |
| 681 | 682 | ||
| 682 | static int | 683 | int target_emulate_inquiry(struct se_task *task) |
| 683 | target_emulate_inquiry(struct se_task *task) | ||
| 684 | { | 684 | { |
| 685 | struct se_cmd *cmd = task->task_se_cmd; | 685 | struct se_cmd *cmd = task->task_se_cmd; |
| 686 | struct se_device *dev = cmd->se_dev; | 686 | struct se_device *dev = cmd->se_dev; |
| @@ -731,8 +731,7 @@ out: | |||
| 731 | return ret; | 731 | return ret; |
| 732 | } | 732 | } |
| 733 | 733 | ||
| 734 | static int | 734 | int target_emulate_readcapacity(struct se_task *task) |
| 735 | target_emulate_readcapacity(struct se_task *task) | ||
| 736 | { | 735 | { |
| 737 | struct se_cmd *cmd = task->task_se_cmd; | 736 | struct se_cmd *cmd = task->task_se_cmd; |
| 738 | struct se_device *dev = cmd->se_dev; | 737 | struct se_device *dev = cmd->se_dev; |
| @@ -768,8 +767,7 @@ target_emulate_readcapacity(struct se_task *task) | |||
| 768 | return 0; | 767 | return 0; |
| 769 | } | 768 | } |
| 770 | 769 | ||
| 771 | static int | 770 | int target_emulate_readcapacity_16(struct se_task *task) |
| 772 | target_emulate_readcapacity_16(struct se_task *task) | ||
| 773 | { | 771 | { |
| 774 | struct se_cmd *cmd = task->task_se_cmd; | 772 | struct se_cmd *cmd = task->task_se_cmd; |
| 775 | struct se_device *dev = cmd->se_dev; | 773 | struct se_device *dev = cmd->se_dev; |
| @@ -939,8 +937,7 @@ target_modesense_dpofua(unsigned char *buf, int type) | |||
| 939 | } | 937 | } |
| 940 | } | 938 | } |
| 941 | 939 | ||
| 942 | static int | 940 | int target_emulate_modesense(struct se_task *task) |
| 943 | target_emulate_modesense(struct se_task *task) | ||
| 944 | { | 941 | { |
| 945 | struct se_cmd *cmd = task->task_se_cmd; | 942 | struct se_cmd *cmd = task->task_se_cmd; |
| 946 | struct se_device *dev = cmd->se_dev; | 943 | struct se_device *dev = cmd->se_dev; |
| @@ -1019,8 +1016,7 @@ target_emulate_modesense(struct se_task *task) | |||
| 1019 | return 0; | 1016 | return 0; |
| 1020 | } | 1017 | } |
| 1021 | 1018 | ||
| 1022 | static int | 1019 | int target_emulate_request_sense(struct se_task *task) |
| 1023 | target_emulate_request_sense(struct se_task *task) | ||
| 1024 | { | 1020 | { |
| 1025 | struct se_cmd *cmd = task->task_se_cmd; | 1021 | struct se_cmd *cmd = task->task_se_cmd; |
| 1026 | unsigned char *cdb = cmd->t_task_cdb; | 1022 | unsigned char *cdb = cmd->t_task_cdb; |
| @@ -1090,8 +1086,7 @@ end: | |||
| 1090 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. | 1086 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. |
| 1091 | * Note this is not used for TCM/pSCSI passthrough | 1087 | * Note this is not used for TCM/pSCSI passthrough |
| 1092 | */ | 1088 | */ |
| 1093 | static int | 1089 | int target_emulate_unmap(struct se_task *task) |
| 1094 | target_emulate_unmap(struct se_task *task) | ||
| 1095 | { | 1090 | { |
| 1096 | struct se_cmd *cmd = task->task_se_cmd; | 1091 | struct se_cmd *cmd = task->task_se_cmd; |
| 1097 | struct se_device *dev = cmd->se_dev; | 1092 | struct se_device *dev = cmd->se_dev; |
| @@ -1150,8 +1145,7 @@ err: | |||
| 1150 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. | 1145 | * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support. |
| 1151 | * Note this is not used for TCM/pSCSI passthrough | 1146 | * Note this is not used for TCM/pSCSI passthrough |
| 1152 | */ | 1147 | */ |
| 1153 | static int | 1148 | int target_emulate_write_same(struct se_task *task) |
| 1154 | target_emulate_write_same(struct se_task *task) | ||
| 1155 | { | 1149 | { |
| 1156 | struct se_cmd *cmd = task->task_se_cmd; | 1150 | struct se_cmd *cmd = task->task_se_cmd; |
| 1157 | struct se_device *dev = cmd->se_dev; | 1151 | struct se_device *dev = cmd->se_dev; |
| @@ -1196,8 +1190,7 @@ target_emulate_write_same(struct se_task *task) | |||
| 1196 | return 0; | 1190 | return 0; |
| 1197 | } | 1191 | } |
| 1198 | 1192 | ||
| 1199 | static int | 1193 | int target_emulate_synchronize_cache(struct se_task *task) |
| 1200 | target_emulate_synchronize_cache(struct se_task *task) | ||
| 1201 | { | 1194 | { |
| 1202 | struct se_device *dev = task->task_se_cmd->se_dev; | 1195 | struct se_device *dev = task->task_se_cmd->se_dev; |
| 1203 | 1196 | ||
| @@ -1211,97 +1204,13 @@ target_emulate_synchronize_cache(struct se_task *task) | |||
| 1211 | return 0; | 1204 | return 0; |
| 1212 | } | 1205 | } |
| 1213 | 1206 | ||
| 1214 | static int | 1207 | int target_emulate_noop(struct se_task *task) |
| 1215 | target_emulate_noop(struct se_task *task) | ||
| 1216 | { | 1208 | { |
| 1217 | task->task_scsi_status = GOOD; | 1209 | task->task_scsi_status = GOOD; |
| 1218 | transport_complete_task(task, 1); | 1210 | transport_complete_task(task, 1); |
| 1219 | return 0; | 1211 | return 0; |
| 1220 | } | 1212 | } |
| 1221 | 1213 | ||
| 1222 | int | ||
| 1223 | transport_emulate_control_cdb(struct se_task *task) | ||
| 1224 | { | ||
| 1225 | struct se_cmd *cmd = task->task_se_cmd; | ||
| 1226 | struct se_device *dev = cmd->se_dev; | ||
| 1227 | unsigned short service_action; | ||
| 1228 | int ret = 0; | ||
| 1229 | |||
| 1230 | switch (cmd->t_task_cdb[0]) { | ||
| 1231 | case INQUIRY: | ||
| 1232 | ret = target_emulate_inquiry(task); | ||
| 1233 | break; | ||
| 1234 | case READ_CAPACITY: | ||
| 1235 | ret = target_emulate_readcapacity(task); | ||
| 1236 | break; | ||
| 1237 | case MODE_SENSE: | ||
| 1238 | ret = target_emulate_modesense(task); | ||
| 1239 | break; | ||
| 1240 | case MODE_SENSE_10: | ||
| 1241 | ret = target_emulate_modesense(task); | ||
| 1242 | break; | ||
| 1243 | case SERVICE_ACTION_IN: | ||
| 1244 | switch (cmd->t_task_cdb[1] & 0x1f) { | ||
| 1245 | case SAI_READ_CAPACITY_16: | ||
| 1246 | ret = target_emulate_readcapacity_16(task); | ||
| 1247 | break; | ||
| 1248 | default: | ||
| 1249 | pr_err("Unsupported SA: 0x%02x\n", | ||
| 1250 | cmd->t_task_cdb[1] & 0x1f); | ||
| 1251 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
| 1252 | } | ||
| 1253 | break; | ||
| 1254 | case REQUEST_SENSE: | ||
| 1255 | ret = target_emulate_request_sense(task); | ||
| 1256 | break; | ||
| 1257 | case UNMAP: | ||
| 1258 | ret = target_emulate_unmap(task); | ||
| 1259 | break; | ||
| 1260 | case WRITE_SAME: | ||
| 1261 | ret = target_emulate_write_same(task); | ||
| 1262 | break; | ||
| 1263 | case WRITE_SAME_16: | ||
| 1264 | ret = target_emulate_write_same(task); | ||
| 1265 | break; | ||
| 1266 | case VARIABLE_LENGTH_CMD: | ||
| 1267 | service_action = | ||
| 1268 | get_unaligned_be16(&cmd->t_task_cdb[8]); | ||
| 1269 | switch (service_action) { | ||
| 1270 | case WRITE_SAME_32: | ||
| 1271 | ret = target_emulate_write_same(task); | ||
| 1272 | break; | ||
| 1273 | default: | ||
| 1274 | pr_err("Unsupported VARIABLE_LENGTH_CMD SA:" | ||
| 1275 | " 0x%02x\n", service_action); | ||
| 1276 | break; | ||
| 1277 | } | ||
| 1278 | break; | ||
| 1279 | case SYNCHRONIZE_CACHE: | ||
| 1280 | case 0x91: /* SYNCHRONIZE_CACHE_16: */ | ||
| 1281 | ret = target_emulate_synchronize_cache(task); | ||
| 1282 | break; | ||
| 1283 | case ALLOW_MEDIUM_REMOVAL: | ||
| 1284 | case ERASE: | ||
| 1285 | case REZERO_UNIT: | ||
| 1286 | case SEEK_10: | ||
| 1287 | case SPACE: | ||
| 1288 | case START_STOP: | ||
| 1289 | case TEST_UNIT_READY: | ||
| 1290 | case VERIFY: | ||
| 1291 | case WRITE_FILEMARKS: | ||
| 1292 | ret = target_emulate_noop(task); | ||
| 1293 | break; | ||
| 1294 | default: | ||
| 1295 | pr_err("Unsupported SCSI Opcode: 0x%02x for %s\n", | ||
| 1296 | cmd->t_task_cdb[0], dev->transport->name); | ||
| 1297 | return PYX_TRANSPORT_UNKNOWN_SAM_OPCODE; | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | if (ret < 0) | ||
| 1301 | return ret; | ||
| 1302 | return PYX_TRANSPORT_SENT_TO_TRANSPORT; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | /* | 1214 | /* |
| 1306 | * Write a CDB into @cdb that is based on the one the intiator sent us, | 1215 | * Write a CDB into @cdb that is based on the one the intiator sent us, |
| 1307 | * but updated to only cover the sectors that the current task handles. | 1216 | * but updated to only cover the sectors that the current task handles. |
diff --git a/drivers/target/target_core_cdb.h b/drivers/target/target_core_cdb.h new file mode 100644 index 000000000000..ad6b1e393001 --- /dev/null +++ b/drivers/target/target_core_cdb.h | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | #ifndef TARGET_CORE_CDB_H | ||
| 2 | #define TARGET_CORE_CDB_H | ||
| 3 | |||
| 4 | int target_emulate_inquiry(struct se_task *task); | ||
| 5 | int target_emulate_readcapacity(struct se_task *task); | ||
| 6 | int target_emulate_readcapacity_16(struct se_task *task); | ||
| 7 | int target_emulate_modesense(struct se_task *task); | ||
| 8 | int target_emulate_request_sense(struct se_task *task); | ||
| 9 | int target_emulate_unmap(struct se_task *task); | ||
| 10 | int target_emulate_write_same(struct se_task *task); | ||
| 11 | int target_emulate_synchronize_cache(struct se_task *task); | ||
| 12 | int target_emulate_noop(struct se_task *task); | ||
| 13 | |||
| 14 | #endif /* TARGET_CORE_CDB_H */ | ||
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 74015793c03a..f603b12485bd 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #include <target/target_core_configfs.h> | 52 | #include <target/target_core_configfs.h> |
| 53 | 53 | ||
| 54 | #include "target_core_alua.h" | 54 | #include "target_core_alua.h" |
| 55 | #include "target_core_cdb.h" | ||
| 55 | #include "target_core_hba.h" | 56 | #include "target_core_hba.h" |
| 56 | #include "target_core_pr.h" | 57 | #include "target_core_pr.h" |
| 57 | #include "target_core_ua.h" | 58 | #include "target_core_ua.h" |
| @@ -2155,31 +2156,11 @@ check_depth: | |||
| 2155 | atomic_set(&cmd->t_transport_sent, 1); | 2156 | atomic_set(&cmd->t_transport_sent, 1); |
| 2156 | 2157 | ||
| 2157 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); | 2158 | spin_unlock_irqrestore(&cmd->t_state_lock, flags); |
| 2158 | /* | ||
| 2159 | * The struct se_cmd->execute_task() function pointer is used | ||
| 2160 | * to grab REPORT_LUNS and other CDBs we want to handle before they hit the | ||
| 2161 | * struct se_subsystem_api->do_task() caller below. | ||
| 2162 | */ | ||
| 2163 | if (cmd->execute_task) { | ||
| 2164 | error = cmd->execute_task(task); | ||
| 2165 | } else { | ||
| 2166 | /* | ||
| 2167 | * Currently for all virtual TCM plugins including IBLOCK, FILEIO and | ||
| 2168 | * RAMDISK we use the internal transport_emulate_control_cdb() logic | ||
| 2169 | * with struct se_subsystem_api callers for the primary SPC-3 TYPE_DISK | ||
| 2170 | * LUN emulation code. | ||
| 2171 | * | ||
| 2172 | * For TCM/pSCSI and all other SCF_SCSI_DATA_SG_IO_CDB I/O tasks we | ||
| 2173 | * call ->do_task() directly and let the underlying TCM subsystem plugin | ||
| 2174 | * code handle the CDB emulation. | ||
| 2175 | */ | ||
| 2176 | if ((dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) && | ||
| 2177 | (!(task->task_se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) | ||
| 2178 | error = transport_emulate_control_cdb(task); | ||
| 2179 | else | ||
| 2180 | error = dev->transport->do_task(task); | ||
| 2181 | } | ||
| 2182 | 2159 | ||
| 2160 | if (cmd->execute_task) | ||
| 2161 | error = cmd->execute_task(task); | ||
| 2162 | else | ||
| 2163 | error = dev->transport->do_task(task); | ||
| 2183 | if (error != 0) { | 2164 | if (error != 0) { |
| 2184 | cmd->transport_error_status = error; | 2165 | cmd->transport_error_status = error; |
| 2185 | spin_lock_irqsave(&cmd->t_state_lock, flags); | 2166 | spin_lock_irqsave(&cmd->t_state_lock, flags); |
| @@ -2622,6 +2603,13 @@ static int transport_generic_cmd_sequencer( | |||
| 2622 | */ | 2603 | */ |
| 2623 | } | 2604 | } |
| 2624 | 2605 | ||
| 2606 | /* | ||
| 2607 | * If we operate in passthrough mode we skip most CDB emulation and | ||
| 2608 | * instead hand the commands down to the physical SCSI device. | ||
| 2609 | */ | ||
| 2610 | passthrough = | ||
| 2611 | (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV); | ||
| 2612 | |||
| 2625 | switch (cdb[0]) { | 2613 | switch (cdb[0]) { |
| 2626 | case READ_6: | 2614 | case READ_6: |
| 2627 | sectors = transport_get_sectors_6(cdb, cmd, §or_ret); | 2615 | sectors = transport_get_sectors_6(cdb, cmd, §or_ret); |
| @@ -2701,9 +2689,12 @@ static int transport_generic_cmd_sequencer( | |||
| 2701 | cmd->t_task_lba = transport_lba_32(cdb); | 2689 | cmd->t_task_lba = transport_lba_32(cdb); |
| 2702 | cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; | 2690 | cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; |
| 2703 | 2691 | ||
| 2704 | if (dev->transport->transport_type == | 2692 | /* |
| 2705 | TRANSPORT_PLUGIN_PHBA_PDEV) | 2693 | * Do now allow BIDI commands for passthrough mode. |
| 2694 | */ | ||
| 2695 | if (passthrough) | ||
| 2706 | goto out_unsupported_cdb; | 2696 | goto out_unsupported_cdb; |
| 2697 | |||
| 2707 | /* | 2698 | /* |
| 2708 | * Setup BIDI XOR callback to be run after I/O completion. | 2699 | * Setup BIDI XOR callback to be run after I/O completion. |
| 2709 | */ | 2700 | */ |
| @@ -2712,13 +2703,6 @@ static int transport_generic_cmd_sequencer( | |||
| 2712 | break; | 2703 | break; |
| 2713 | case VARIABLE_LENGTH_CMD: | 2704 | case VARIABLE_LENGTH_CMD: |
| 2714 | service_action = get_unaligned_be16(&cdb[8]); | 2705 | service_action = get_unaligned_be16(&cdb[8]); |
| 2715 | /* | ||
| 2716 | * Determine if this is TCM/PSCSI device and we should disable | ||
| 2717 | * internal emulation for this CDB. | ||
| 2718 | */ | ||
| 2719 | passthrough = (dev->transport->transport_type == | ||
| 2720 | TRANSPORT_PLUGIN_PHBA_PDEV); | ||
| 2721 | |||
| 2722 | switch (service_action) { | 2706 | switch (service_action) { |
| 2723 | case XDWRITEREAD_32: | 2707 | case XDWRITEREAD_32: |
| 2724 | sectors = transport_get_sectors_32(cdb, cmd, §or_ret); | 2708 | sectors = transport_get_sectors_32(cdb, cmd, §or_ret); |
| @@ -2732,8 +2716,12 @@ static int transport_generic_cmd_sequencer( | |||
| 2732 | cmd->t_task_lba = transport_lba_64_ext(cdb); | 2716 | cmd->t_task_lba = transport_lba_64_ext(cdb); |
| 2733 | cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; | 2717 | cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB; |
| 2734 | 2718 | ||
| 2719 | /* | ||
| 2720 | * Do now allow BIDI commands for passthrough mode. | ||
| 2721 | */ | ||
| 2735 | if (passthrough) | 2722 | if (passthrough) |
| 2736 | goto out_unsupported_cdb; | 2723 | goto out_unsupported_cdb; |
| 2724 | |||
| 2737 | /* | 2725 | /* |
| 2738 | * Setup BIDI XOR callback to be run during after I/O | 2726 | * Setup BIDI XOR callback to be run during after I/O |
| 2739 | * completion. | 2727 | * completion. |
| @@ -2759,7 +2747,8 @@ static int transport_generic_cmd_sequencer( | |||
| 2759 | 2747 | ||
| 2760 | if (target_check_write_same_discard(&cdb[10], dev) < 0) | 2748 | if (target_check_write_same_discard(&cdb[10], dev) < 0) |
| 2761 | goto out_invalid_cdb_field; | 2749 | goto out_invalid_cdb_field; |
| 2762 | 2750 | if (!passthrough) | |
| 2751 | cmd->execute_task = target_emulate_write_same; | ||
| 2763 | break; | 2752 | break; |
| 2764 | default: | 2753 | default: |
| 2765 | pr_err("VARIABLE_LENGTH_CMD service action" | 2754 | pr_err("VARIABLE_LENGTH_CMD service action" |
| @@ -2797,8 +2786,15 @@ static int transport_generic_cmd_sequencer( | |||
| 2797 | case MODE_SENSE: | 2786 | case MODE_SENSE: |
| 2798 | size = cdb[4]; | 2787 | size = cdb[4]; |
| 2799 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 2788 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 2789 | if (!passthrough) | ||
| 2790 | cmd->execute_task = target_emulate_modesense; | ||
| 2800 | break; | 2791 | break; |
| 2801 | case MODE_SENSE_10: | 2792 | case MODE_SENSE_10: |
| 2793 | size = (cdb[7] << 8) + cdb[8]; | ||
| 2794 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | ||
| 2795 | if (!passthrough) | ||
| 2796 | cmd->execute_task = target_emulate_modesense; | ||
| 2797 | break; | ||
| 2802 | case GPCMD_READ_BUFFER_CAPACITY: | 2798 | case GPCMD_READ_BUFFER_CAPACITY: |
| 2803 | case GPCMD_SEND_OPC: | 2799 | case GPCMD_SEND_OPC: |
| 2804 | case LOG_SELECT: | 2800 | case LOG_SELECT: |
| @@ -2867,6 +2863,8 @@ static int transport_generic_cmd_sequencer( | |||
| 2867 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) | 2863 | if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED) |
| 2868 | cmd->sam_task_attr = MSG_HEAD_TAG; | 2864 | cmd->sam_task_attr = MSG_HEAD_TAG; |
| 2869 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 2865 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 2866 | if (!passthrough) | ||
| 2867 | cmd->execute_task = target_emulate_inquiry; | ||
| 2870 | break; | 2868 | break; |
| 2871 | case READ_BUFFER: | 2869 | case READ_BUFFER: |
| 2872 | size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; | 2870 | size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8]; |
| @@ -2875,6 +2873,8 @@ static int transport_generic_cmd_sequencer( | |||
| 2875 | case READ_CAPACITY: | 2873 | case READ_CAPACITY: |
| 2876 | size = READ_CAP_LEN; | 2874 | size = READ_CAP_LEN; |
| 2877 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 2875 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 2876 | if (!passthrough) | ||
| 2877 | cmd->execute_task = target_emulate_readcapacity; | ||
| 2878 | break; | 2878 | break; |
| 2879 | case READ_MEDIA_SERIAL_NUMBER: | 2879 | case READ_MEDIA_SERIAL_NUMBER: |
| 2880 | case SECURITY_PROTOCOL_IN: | 2880 | case SECURITY_PROTOCOL_IN: |
| @@ -2883,6 +2883,21 @@ static int transport_generic_cmd_sequencer( | |||
| 2883 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 2883 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 2884 | break; | 2884 | break; |
| 2885 | case SERVICE_ACTION_IN: | 2885 | case SERVICE_ACTION_IN: |
| 2886 | switch (cmd->t_task_cdb[1] & 0x1f) { | ||
| 2887 | case SAI_READ_CAPACITY_16: | ||
| 2888 | if (!passthrough) | ||
| 2889 | cmd->execute_task = | ||
| 2890 | target_emulate_readcapacity_16; | ||
| 2891 | break; | ||
| 2892 | default: | ||
| 2893 | if (passthrough) | ||
| 2894 | break; | ||
| 2895 | |||
| 2896 | pr_err("Unsupported SA: 0x%02x\n", | ||
| 2897 | cmd->t_task_cdb[1] & 0x1f); | ||
| 2898 | goto out_unsupported_cdb; | ||
| 2899 | } | ||
| 2900 | /*FALLTHROUGH*/ | ||
| 2886 | case ACCESS_CONTROL_IN: | 2901 | case ACCESS_CONTROL_IN: |
| 2887 | case ACCESS_CONTROL_OUT: | 2902 | case ACCESS_CONTROL_OUT: |
| 2888 | case EXTENDED_COPY: | 2903 | case EXTENDED_COPY: |
| @@ -2913,6 +2928,8 @@ static int transport_generic_cmd_sequencer( | |||
| 2913 | case REQUEST_SENSE: | 2928 | case REQUEST_SENSE: |
| 2914 | size = cdb[4]; | 2929 | size = cdb[4]; |
| 2915 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 2930 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 2931 | if (!passthrough) | ||
| 2932 | cmd->execute_task = target_emulate_request_sense; | ||
| 2916 | break; | 2933 | break; |
| 2917 | case READ_ELEMENT_STATUS: | 2934 | case READ_ELEMENT_STATUS: |
| 2918 | size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9]; | 2935 | size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9]; |
| @@ -2977,8 +2994,9 @@ static int transport_generic_cmd_sequencer( | |||
| 2977 | size = transport_get_size(sectors, cdb, cmd); | 2994 | size = transport_get_size(sectors, cdb, cmd); |
| 2978 | cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; | 2995 | cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; |
| 2979 | 2996 | ||
| 2980 | if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) | 2997 | if (passthrough) |
| 2981 | break; | 2998 | break; |
| 2999 | |||
| 2982 | /* | 3000 | /* |
| 2983 | * Check to ensure that LBA + Range does not exceed past end of | 3001 | * Check to ensure that LBA + Range does not exceed past end of |
| 2984 | * device for IBLOCK and FILEIO ->do_sync_cache() backend calls | 3002 | * device for IBLOCK and FILEIO ->do_sync_cache() backend calls |
| @@ -2987,10 +3005,13 @@ static int transport_generic_cmd_sequencer( | |||
| 2987 | if (transport_cmd_get_valid_sectors(cmd) < 0) | 3005 | if (transport_cmd_get_valid_sectors(cmd) < 0) |
| 2988 | goto out_invalid_cdb_field; | 3006 | goto out_invalid_cdb_field; |
| 2989 | } | 3007 | } |
| 3008 | cmd->execute_task = target_emulate_synchronize_cache; | ||
| 2990 | break; | 3009 | break; |
| 2991 | case UNMAP: | 3010 | case UNMAP: |
| 2992 | size = get_unaligned_be16(&cdb[7]); | 3011 | size = get_unaligned_be16(&cdb[7]); |
| 2993 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; | 3012 | cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB; |
| 3013 | if (!passthrough) | ||
| 3014 | cmd->execute_task = target_emulate_unmap; | ||
| 2994 | break; | 3015 | break; |
| 2995 | case WRITE_SAME_16: | 3016 | case WRITE_SAME_16: |
| 2996 | sectors = transport_get_sectors_16(cdb, cmd, §or_ret); | 3017 | sectors = transport_get_sectors_16(cdb, cmd, §or_ret); |
| @@ -3009,6 +3030,8 @@ static int transport_generic_cmd_sequencer( | |||
| 3009 | 3030 | ||
| 3010 | if (target_check_write_same_discard(&cdb[1], dev) < 0) | 3031 | if (target_check_write_same_discard(&cdb[1], dev) < 0) |
| 3011 | goto out_invalid_cdb_field; | 3032 | goto out_invalid_cdb_field; |
| 3033 | if (!passthrough) | ||
| 3034 | cmd->execute_task = target_emulate_write_same; | ||
| 3012 | break; | 3035 | break; |
| 3013 | case WRITE_SAME: | 3036 | case WRITE_SAME: |
| 3014 | sectors = transport_get_sectors_10(cdb, cmd, §or_ret); | 3037 | sectors = transport_get_sectors_10(cdb, cmd, §or_ret); |
| @@ -3030,20 +3053,26 @@ static int transport_generic_cmd_sequencer( | |||
| 3030 | */ | 3053 | */ |
| 3031 | if (target_check_write_same_discard(&cdb[1], dev) < 0) | 3054 | if (target_check_write_same_discard(&cdb[1], dev) < 0) |
| 3032 | goto out_invalid_cdb_field; | 3055 | goto out_invalid_cdb_field; |
| 3056 | if (!passthrough) | ||
| 3057 | cmd->execute_task = target_emulate_write_same; | ||
| 3033 | break; | 3058 | break; |
| 3034 | case ALLOW_MEDIUM_REMOVAL: | 3059 | case ALLOW_MEDIUM_REMOVAL: |
| 3035 | case GPCMD_CLOSE_TRACK: | ||
| 3036 | case ERASE: | 3060 | case ERASE: |
| 3037 | case INITIALIZE_ELEMENT_STATUS: | ||
| 3038 | case GPCMD_LOAD_UNLOAD: | ||
| 3039 | case REZERO_UNIT: | 3061 | case REZERO_UNIT: |
| 3040 | case SEEK_10: | 3062 | case SEEK_10: |
| 3041 | case GPCMD_SET_SPEED: | ||
| 3042 | case SPACE: | 3063 | case SPACE: |
| 3043 | case START_STOP: | 3064 | case START_STOP: |
| 3044 | case TEST_UNIT_READY: | 3065 | case TEST_UNIT_READY: |
| 3045 | case VERIFY: | 3066 | case VERIFY: |
| 3046 | case WRITE_FILEMARKS: | 3067 | case WRITE_FILEMARKS: |
| 3068 | cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; | ||
| 3069 | if (!passthrough) | ||
| 3070 | cmd->execute_task = target_emulate_noop; | ||
| 3071 | break; | ||
| 3072 | case GPCMD_CLOSE_TRACK: | ||
| 3073 | case INITIALIZE_ELEMENT_STATUS: | ||
| 3074 | case GPCMD_LOAD_UNLOAD: | ||
| 3075 | case GPCMD_SET_SPEED: | ||
| 3047 | case MOVE_MEDIUM: | 3076 | case MOVE_MEDIUM: |
| 3048 | cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; | 3077 | cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB; |
| 3049 | break; | 3078 | break; |
| @@ -3100,6 +3129,11 @@ static int transport_generic_cmd_sequencer( | |||
| 3100 | cmd->data_length = size; | 3129 | cmd->data_length = size; |
| 3101 | } | 3130 | } |
| 3102 | 3131 | ||
| 3132 | /* reject any command that we don't have a handler for */ | ||
| 3133 | if (!(passthrough || cmd->execute_task || | ||
| 3134 | (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) | ||
| 3135 | goto out_unsupported_cdb; | ||
| 3136 | |||
| 3103 | /* Let's limit control cdbs to a page, for simplicity's sake. */ | 3137 | /* Let's limit control cdbs to a page, for simplicity's sake. */ |
| 3104 | if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && | 3138 | if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && |
| 3105 | size > PAGE_SIZE) | 3139 | size > PAGE_SIZE) |
