Merge tag 'kbuild-v5.12' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
[linux-2.6-microblaze.git] / drivers / target / target_core_transport.c
index fca4bd0..93ea17c 100644 (file)
@@ -1313,12 +1313,32 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
                        " %u does not match SCSI CDB Length: %u for SAM Opcode:"
                        " 0x%02x\n", cmd->se_tfo->fabric_name,
                                cmd->data_length, size, cmd->t_task_cdb[0]);
+               /*
+                * For READ command for the overflow case keep the existing
+                * fabric provided ->data_length. Otherwise for the underflow
+                * case, reset ->data_length to the smaller SCSI expected data
+                * transfer length.
+                */
+               if (size > cmd->data_length) {
+                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
+                       cmd->residual_count = (size - cmd->data_length);
+               } else {
+                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
+                       cmd->residual_count = (cmd->data_length - size);
+                       /*
+                        * Do not truncate ->data_length for WRITE command to
+                        * dump all payload
+                        */
+                       if (cmd->data_direction == DMA_FROM_DEVICE) {
+                               cmd->data_length = size;
+                       }
+               }
 
                if (cmd->data_direction == DMA_TO_DEVICE) {
                        if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
                                pr_err_ratelimited("Rejecting underflow/overflow"
                                                   " for WRITE data CDB\n");
-                               return TCM_INVALID_CDB_FIELD;
+                               return TCM_INVALID_FIELD_IN_COMMAND_IU;
                        }
                        /*
                         * Some fabric drivers like iscsi-target still expect to
@@ -1332,31 +1352,6 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
                                return TCM_INVALID_CDB_FIELD;
                        }
                }
-               /*
-                * Reject READ_* or WRITE_* with overflow/underflow for
-                * type SCF_SCSI_DATA_CDB.
-                */
-               if (dev->dev_attrib.block_size != 512)  {
-                       pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
-                               " CDB on non 512-byte sector setup subsystem"
-                               " plugin: %s\n", dev->transport->name);
-                       /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
-                       return TCM_INVALID_CDB_FIELD;
-               }
-               /*
-                * For the overflow case keep the existing fabric provided
-                * ->data_length.  Otherwise for the underflow case, reset
-                * ->data_length to the smaller SCSI expected data transfer
-                * length.
-                */
-               if (size > cmd->data_length) {
-                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
-                       cmd->residual_count = (size - cmd->data_length);
-               } else {
-                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
-                       cmd->residual_count = (cmd->data_length - size);
-                       cmd->data_length = size;
-               }
        }
 
        return target_check_max_data_sg_nents(cmd, dev, size);
@@ -1512,17 +1507,14 @@ int transport_handle_cdb_direct(
 {
        sense_reason_t ret;
 
+       might_sleep();
+
        if (!cmd->se_lun) {
                dump_stack();
                pr_err("cmd->se_lun is NULL\n");
                return -EINVAL;
        }
-       if (in_interrupt()) {
-               dump_stack();
-               pr_err("transport_generic_handle_cdb cannot be called"
-                               " from interrupt context\n");
-               return -EINVAL;
-       }
+
        /*
         * Set TRANSPORT_NEW_CMD state and CMD_T_ACTIVE to ensure that
         * outstanding descriptors are handled correctly during shutdown via
@@ -1613,10 +1605,11 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
        sense_reason_t rc;
        int ret;
 
+       might_sleep();
+
        se_tpg = se_sess->se_tpg;
        BUG_ON(!se_tpg);
        BUG_ON(se_cmd->se_tfo || se_cmd->se_sess);
-       BUG_ON(in_interrupt());
 
        if (flags & TARGET_SCF_USE_CPUID)
                se_cmd->se_cmd_flags |= SCF_USE_CPUID;
@@ -1884,6 +1877,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
        case TCM_UNSUPPORTED_TARGET_DESC_TYPE_CODE:
        case TCM_TOO_MANY_SEGMENT_DESCS:
        case TCM_UNSUPPORTED_SEGMENT_DESC_TYPE_CODE:
+       case TCM_INVALID_FIELD_IN_COMMAND_IU:
                break;
        case TCM_OUT_OF_RESOURCES:
                cmd->scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -3210,6 +3204,11 @@ static const struct sense_detail sense_detail_table[] = {
                .asc = 0x55,
                .ascq = 0x04, /* INSUFFICIENT REGISTRATION RESOURCES */
        },
+       [TCM_INVALID_FIELD_IN_COMMAND_IU] = {
+               .key = ILLEGAL_REQUEST,
+               .asc = 0x0e,
+               .ascq = 0x03, /* INVALID FIELD IN COMMAND INFORMATION UNIT */
+       },
 };
 
 /**