]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/ata/libata-scsi.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / drivers / ata / libata-scsi.c
index 4c6eb22cc85df05bc1245cc6dc7175f5c38503b2..e207b33e4ce9d602ca5d72144a7332c91f2515c9 100644 (file)
@@ -304,7 +304,7 @@ static void ata_scsi_set_invalid_field(struct ata_device *dev,
                                       struct scsi_cmnd *cmd, u16 field, u8 bit)
 {
        ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x24, 0x0);
-       /* "Invalid field in cbd" */
+       /* "Invalid field in CDB" */
        scsi_set_sense_field_pointer(cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE,
                                     field, bit, 1);
 }
@@ -2075,8 +2075,8 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
                0x03,
                0x20,   /* SBC-2 (no version claimed) */
 
-               0x02,
-               0x60    /* SPC-3 (no version claimed) */
+               0x03,
+               0x00    /* SPC-3 (no version claimed) */
        };
        const u8 versions_zbc[] = {
                0x00,
@@ -2097,7 +2097,10 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
                0,
                0x5,    /* claim SPC-3 version compatibility */
                2,
-               95 - 4
+               95 - 4,
+               0,
+               0,
+               2
        };
 
        VPRINTK("ENTER\n");
@@ -2109,8 +2112,10 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
            (args->dev->link->ap->pflags & ATA_PFLAG_EXTERNAL))
                hdr[1] |= (1 << 7);
 
-       if (args->dev->class == ATA_DEV_ZAC)
+       if (args->dev->class == ATA_DEV_ZAC) {
                hdr[0] = TYPE_ZBC;
+               hdr[2] = 0x7; /* claim SPC-5 version compatibility */
+       }
 
        memcpy(rbuf, hdr, sizeof(hdr));
        memcpy(&rbuf[8], "ATA     ", 8);
@@ -2314,7 +2319,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
         * with the unmap bit set.
         */
        if (ata_id_has_trim(args->id)) {
-               put_unaligned_be64(65535 * 512 / 8, &rbuf[36]);
+               put_unaligned_be64(65535 * ATA_MAX_TRIM_RNUM, &rbuf[36]);
                put_unaligned_be32(1, &rbuf[28]);
        }
 
@@ -2424,15 +2429,17 @@ static void modecpy(u8 *dest, const u8 *src, int n, bool changeable)
 static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
 {
        modecpy(buf, def_cache_mpage, sizeof(def_cache_mpage), changeable);
-       if (changeable || ata_id_wcache_enabled(id))
-               buf[2] |= (1 << 2);     /* write cache enable */
-       if (!changeable && !ata_id_rahead_enabled(id))
-               buf[12] |= (1 << 5);    /* disable read ahead */
+       if (changeable) {
+               buf[2] |= (1 << 2);     /* ata_mselect_caching() */
+       } else {
+               buf[2] |= (ata_id_wcache_enabled(id) << 2);     /* write cache enable */
+               buf[12] |= (!ata_id_rahead_enabled(id) << 5);   /* disable read ahead */
+       }
        return sizeof(def_cache_mpage);
 }
 
 /**
- *     ata_msense_ctl_mode - Simulate MODE SENSE control mode page
+ *     ata_msense_control - Simulate MODE SENSE control mode page
  *     @dev: ATA device of interest
  *     @buf: output buffer
  *     @changeable: whether changeable parameters are requested
@@ -2442,12 +2449,17 @@ static unsigned int ata_msense_caching(u16 *id, u8 *buf, bool changeable)
  *     LOCKING:
  *     None.
  */
-static unsigned int ata_msense_ctl_mode(struct ata_device *dev, u8 *buf,
+static unsigned int ata_msense_control(struct ata_device *dev, u8 *buf,
                                        bool changeable)
 {
        modecpy(buf, def_control_mpage, sizeof(def_control_mpage), changeable);
-       if (changeable && (dev->flags & ATA_DFLAG_D_SENSE))
-               buf[2] |= (1 << 2);     /* Descriptor sense requested */
+       if (changeable) {
+               buf[2] |= (1 << 2);     /* ata_mselect_control() */
+       } else {
+               bool d_sense = (dev->flags & ATA_DFLAG_D_SENSE);
+
+               buf[2] |= (d_sense << 2);       /* descriptor format sense data */
+       }
        return sizeof(def_control_mpage);
 }
 
@@ -2566,13 +2578,13 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf)
                break;
 
        case CONTROL_MPAGE:
-               p += ata_msense_ctl_mode(args->dev, p, page_control == 1);
+               p += ata_msense_control(args->dev, p, page_control == 1);
                break;
 
        case ALL_MPAGES:
                p += ata_msense_rw_recovery(p, page_control == 1);
                p += ata_msense_caching(args->id, p, page_control == 1);
-               p += ata_msense_ctl_mode(args->dev, p, page_control == 1);
+               p += ata_msense_control(args->dev, p, page_control == 1);
                break;
 
        default:                /* invalid page code */
@@ -3077,6 +3089,9 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
                goto invalid_fld;
        }
 
+       if (ata_is_ncq(tf->protocol) && (cdb[2] & 0x3) == 0)
+               tf->protocol = ATA_PROT_NCQ_NODATA;
+
        /* enable LBA */
        tf->flags |= ATA_TFLAG_LBA;
 
@@ -3125,8 +3140,8 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
                tf->command = cdb[9];
        }
 
-       /* For NCQ commands with FPDMA protocol, copy the tag value */
-       if (tf->protocol == ATA_PROT_NCQ)
+       /* For NCQ commands copy the tag value */
+       if (ata_is_ncq(tf->protocol))
                tf->nsect = qc->tag << 3;
 
        /* enforce correct master/slave bit */
@@ -3305,7 +3320,13 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc)
                goto invalid_param_len;
 
        buf = page_address(sg_page(scsi_sglist(scmd)));
-       size = ata_set_lba_range_entries(buf, 512, block, n_block);
+
+       if (n_block <= 65535 * ATA_MAX_TRIM_RNUM) {
+               size = ata_set_lba_range_entries(buf, ATA_MAX_TRIM_RNUM, block, n_block);
+       } else {
+               fp = 2;
+               goto invalid_fld;
+       }
 
        if (ata_ncq_enabled(dev) && ata_fpdma_dsm_supported(dev)) {
                /* Newer devices support queued TRIM commands */
@@ -3454,7 +3475,7 @@ static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc)
                goto invalid_param_len;
        }
        sect = n_block / 512;
-       options = cdb[14];
+       options = cdb[14] & 0xbf;
 
        if (ata_ncq_enabled(qc->dev) &&
            ata_fpdma_zac_mgmt_in_supported(qc->dev)) {
@@ -3464,7 +3485,7 @@ static unsigned int ata_scsi_zbc_in_xlat(struct ata_queued_cmd *qc)
                tf->nsect = qc->tag << 3;
                tf->feature = sect & 0xff;
                tf->hob_feature = (sect >> 8) & 0xff;
-               tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
+               tf->auxiliary = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES | (options << 8);
        } else {
                tf->command = ATA_CMD_ZAC_MGMT_IN;
                tf->feature = ATA_SUBCMD_ZAC_MGMT_IN_REPORT_ZONES;
@@ -3506,7 +3527,7 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
        struct scsi_cmnd *scmd = qc->scsicmd;
        struct ata_device *dev = qc->dev;
        const u8 *cdb = scmd->cmnd;
-       u8 reset_all, sa;
+       u8 all, sa;
        u64 block;
        u32 n_block;
        u16 fp = (u16)-1;
@@ -3533,20 +3554,20 @@ static unsigned int ata_scsi_zbc_out_xlat(struct ata_queued_cmd *qc)
        if (block > dev->n_sectors)
                goto out_of_range;
 
-       reset_all = cdb[14] & 0x1;
+       all = cdb[14] & 0x1;
 
        if (ata_ncq_enabled(qc->dev) &&
            ata_fpdma_zac_mgmt_out_supported(qc->dev)) {
-               tf->protocol = ATA_PROT_NCQ;
+               tf->protocol = ATA_PROT_NCQ_NODATA;
                tf->command = ATA_CMD_NCQ_NON_DATA;
-               tf->hob_nsect = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT;
+               tf->feature = ATA_SUBCMD_NCQ_NON_DATA_ZAC_MGMT_OUT;
                tf->nsect = qc->tag << 3;
-               tf->auxiliary = sa | (reset_all & 0x1) << 8;
+               tf->auxiliary = sa | ((u16)all << 8);
        } else {
                tf->protocol = ATA_PROT_NODATA;
                tf->command = ATA_CMD_ZAC_MGMT_OUT;
                tf->feature = sa;
-               tf->hob_feature = reset_all & 0x1;
+               tf->hob_feature = all;
        }
        tf->lbah = (block >> 16) & 0xff;
        tf->lbam = (block >> 8) & 0xff;
@@ -3667,7 +3688,7 @@ static int ata_mselect_control(struct ata_queued_cmd *qc,
        /*
         * Check that read-only bits are not modified.
         */
-       ata_msense_ctl_mode(dev, mpage, false);
+       ata_msense_control(dev, mpage, false);
        for (i = 0; i < CONTROL_MPAGE_LEN - 2; i++) {
                if (i == 0)
                        continue;
@@ -4039,11 +4060,6 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd)
        args.done = cmd->scsi_done;
 
        switch(scsicmd[0]) {
-       /* TODO: worth improving? */
-       case FORMAT_UNIT:
-               ata_scsi_invalid_field(dev, cmd, 0);
-               break;
-
        case INQUIRY:
                if (scsicmd[1] & 2)                /* is CmdDt set?  */
                    ata_scsi_invalid_field(dev, cmd, 1);