]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - drivers/ata/libata-scsi.c
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.git] / drivers / ata / libata-scsi.c
index 66be961c93a4e3311a7d477ec666e3f17150397d..504ad9488ef744249c54f2f513a0e1b3c85e17a0 100644 (file)
@@ -110,6 +110,7 @@ static const char *ata_lpm_policy_names[] = {
        [ATA_LPM_MAX_POWER]             = "max_performance",
        [ATA_LPM_MED_POWER]             = "medium_power",
        [ATA_LPM_MED_POWER_WITH_DIPM]   = "med_power_with_dipm",
+       [ATA_LPM_MIN_POWER_WITH_PARTIAL] = "min_power_with_partial",
        [ATA_LPM_MIN_POWER]             = "min_power",
 };
 
@@ -1805,6 +1806,21 @@ nothing_to_do:
        return 1;
 }
 
+static bool ata_check_nblocks(struct scsi_cmnd *scmd, u32 n_blocks)
+{
+       struct request *rq = scmd->request;
+       u32 req_blocks;
+
+       if (!blk_rq_is_passthrough(rq))
+               return true;
+
+       req_blocks = blk_rq_bytes(rq) / scmd->device->sector_size;
+       if (n_blocks > req_blocks)
+               return false;
+
+       return true;
+}
+
 /**
  *     ata_scsi_rw_xlat - Translate SCSI r/w command into an ATA one
  *     @qc: Storage for translated ATA taskfile
@@ -1849,6 +1865,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_10_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_6:
        case WRITE_6:
@@ -1863,6 +1881,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                 */
                if (!n_block)
                        n_block = 256;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        case READ_16:
        case WRITE_16:
@@ -1873,6 +1893,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc)
                scsi_16_lba_len(cdb, &block, &n_block);
                if (cdb[1] & (1 << 3))
                        tf_flags |= ATA_TFLAG_FUA;
+               if (!ata_check_nblocks(scmd, n_block))
+                       goto invalid_fld;
                break;
        default:
                DPRINTK("no-byte command\n");
@@ -3316,6 +3338,12 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
                goto invalid_fld;
        }
 
+       /* We may not issue NCQ commands to devices not supporting NCQ */
+       if (ata_is_ncq(tf->protocol) && !ata_ncq_enabled(dev)) {
+               fp = 1;
+               goto invalid_fld;
+       }
+
        /* sanity check for pio multi commands */
        if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf)) {
                fp = 1;
@@ -3796,10 +3824,20 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
                 */
                goto invalid_param_len;
        }
-       if (block > dev->n_sectors)
-               goto out_of_range;
 
        all = cdb[14] & 0x1;
+       if (all) {
+               /*
+                * Ignore the block address (zone ID) as defined by ZBC.
+                */
+               block = 0;
+       } else if (block >= dev->n_sectors) {
+               /*
+                * Block must be a valid zone ID (a zone start LBA).
+                */
+               fp = 2;
+               goto invalid_fld;
+       }
 
        if (ata_ncq_enabled(qc->dev) &&
            ata_fpdma_zac_mgmt_out_supported(qc->dev)) {
@@ -3828,10 +3866,6 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
  invalid_fld:
        ata_scsi_set_invalid_field(qc->dev, scmd, fp, 0xff);
        return 1;
- out_of_range:
-       /* "Logical Block Address out of range" */
-       ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x21, 0x00);
-       return 1;
 invalid_param_len:
        /* "Parameter list length error" */
        ata_scsi_set_sense(qc->dev, scmd, ILLEGAL_REQUEST, 0x1a, 0x0);
@@ -4282,7 +4316,7 @@ static inline void ata_scsi_dump_cdb(struct ata_port *ap,
 #ifdef ATA_DEBUG
        struct scsi_device *scsidev = cmd->device;
 
-       DPRINTK("CDB (%u:%d,%d,%d) %9ph\n",
+       DPRINTK("CDB (%u:%d,%d,%lld) %9ph\n",
                ap->print_id,
                scsidev->channel, scsidev->id, scsidev->lun,
                cmd->cmnd);
@@ -4309,7 +4343,9 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
                if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
                        /* relay SCSI command to ATAPI device */
                        int len = COMMAND_SIZE(scsi_op);
-                       if (unlikely(len > scmd->cmd_len || len > dev->cdb_len))
+                       if (unlikely(len > scmd->cmd_len ||
+                                    len > dev->cdb_len ||
+                                    scmd->cmd_len > ATAPI_CDB_LEN))
                                goto bad_cdb_len;
 
                        xlat_func = atapi_xlat;