diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-scsi.c | 81 |
1 files changed, 47 insertions, 34 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 4593258d2b6a..556f7b417f3b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1792,17 +1792,19 @@ static void ata_scsi_rbuf_fill(struct ata_device *dev, struct scsi_cmnd *cmd, unsigned int (*actor)(struct ata_device *dev, struct scsi_cmnd *cmd, u8 *rbuf)) { - unsigned int rc; unsigned long flags; + unsigned int len; spin_lock_irqsave(&ata_scsi_rbuf_lock, flags); memset(ata_scsi_rbuf, 0, ATA_SCSI_RBUF_SIZE); - rc = actor(dev, cmd, ata_scsi_rbuf); - if (rc == 0) { + len = actor(dev, cmd, ata_scsi_rbuf); + if (len) { sg_copy_from_buffer(scsi_sglist(cmd), scsi_sg_count(cmd), ata_scsi_rbuf, ATA_SCSI_RBUF_SIZE); cmd->result = SAM_STAT_GOOD; + if (scsi_bufflen(cmd) > len) + scsi_set_resid(cmd, scsi_bufflen(cmd) - len); } spin_unlock_irqrestore(&ata_scsi_rbuf_lock, flags); @@ -1890,7 +1892,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_device *dev, else memcpy(rbuf + 58, versions, sizeof(versions)); - return 0; + /* + * Include all 8 possible version descriptors, even if not all of + * them are popoulated. + */ + return 96; } /** @@ -1928,7 +1934,8 @@ static unsigned int ata_scsiop_inq_00(struct ata_device *dev, num_pages++; } rbuf[3] = num_pages; /* number of supported VPD pages */ - return 0; + + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -1955,7 +1962,8 @@ static unsigned int ata_scsiop_inq_80(struct ata_device *dev, memcpy(rbuf, hdr, sizeof(hdr)); ata_id_string(dev->id, (unsigned char *) &rbuf[4], ATA_ID_SERNO, ATA_ID_SERNO_LEN); - return 0; + + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2016,7 +2024,8 @@ static unsigned int ata_scsiop_inq_83(struct ata_device *dev, num += ATA_ID_WWN_LEN; } rbuf[3] = num - 4; /* page len (assume less than 256 bytes) */ - return 0; + + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2053,7 +2062,8 @@ static unsigned int ata_scsiop_inq_89(struct ata_device *dev, rbuf[56] = ATA_CMD_ID_ATA; memcpy(&rbuf[60], &dev->id[0], 512); - return 0; + + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2104,7 +2114,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_device *dev, put_unaligned_be32(1, &rbuf[28]); } - return 0; + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2134,7 +2144,7 @@ static unsigned int ata_scsiop_inq_b1(struct ata_device *dev, if (zoned) rbuf[8] = (zoned << 4); - return 0; + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2157,7 +2167,7 @@ static unsigned int ata_scsiop_inq_b2(struct ata_device *dev, rbuf[3] = 0x4; rbuf[5] = 1 << 6; /* TPWS */ - return 0; + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2177,7 +2187,7 @@ static unsigned int ata_scsiop_inq_b6(struct ata_device *dev, { if (!(dev->flags & ATA_DFLAG_ZAC)) { ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); - return 1; + return 0; } /* @@ -2195,7 +2205,7 @@ static unsigned int ata_scsiop_inq_b6(struct ata_device *dev, put_unaligned_be32(dev->zac_zones_optimal_nonseq, &rbuf[12]); put_unaligned_be32(dev->zac_zones_max_open, &rbuf[16]); - return 0; + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2219,7 +2229,7 @@ static unsigned int ata_scsiop_inq_b9(struct ata_device *dev, if (!cpr_log) { ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); - return 1; + return 0; } /* SCSI Concurrent Positioning Ranges VPD page: SBC-5 rev 1 or later */ @@ -2233,7 +2243,7 @@ static unsigned int ata_scsiop_inq_b9(struct ata_device *dev, put_unaligned_be64(cpr_log->cpr[i].num_lbas, &desc[16]); } - return 0; + return get_unaligned_be16(&rbuf[2]) + 4; } /** @@ -2255,7 +2265,7 @@ static unsigned int ata_scsiop_inquiry(struct ata_device *dev, /* is CmdDt set? */ if (scsicmd[1] & 2) { ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - return 1; + return 0; } /* Is EVPD clear? */ @@ -2283,7 +2293,7 @@ static unsigned int ata_scsiop_inquiry(struct ata_device *dev, return ata_scsiop_inq_b9(dev, cmd, rbuf); default: ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); - return 1; + return 0; } } @@ -2614,24 +2624,27 @@ static unsigned int ata_scsiop_mode_sense(struct ata_device *dev, rbuf[3] = sizeof(sat_blk_desc); memcpy(rbuf + 4, sat_blk_desc, sizeof(sat_blk_desc)); } - } else { - put_unaligned_be16(p - rbuf - 2, &rbuf[0]); - rbuf[3] |= dpofua; - if (ebd) { - rbuf[7] = sizeof(sat_blk_desc); - memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc)); - } + + return rbuf[0] + 1; + } + + put_unaligned_be16(p - rbuf - 2, &rbuf[0]); + rbuf[3] |= dpofua; + if (ebd) { + rbuf[7] = sizeof(sat_blk_desc); + memcpy(rbuf + 8, sat_blk_desc, sizeof(sat_blk_desc)); } - return 0; + + return get_unaligned_be16(&rbuf[0]) + 2; invalid_fld: ata_scsi_set_invalid_field(dev, cmd, fp, bp); - return 1; + return 0; saving_not_supp: ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x39, 0x0); /* "Saving parameters not supported" */ - return 1; + return 0; } /** @@ -2674,7 +2687,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev, rbuf[6] = sector_size >> (8 * 1); rbuf[7] = sector_size; - return 0; + return 8; } /* @@ -2684,7 +2697,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev, if (scsicmd[0] != SERVICE_ACTION_IN_16 || (scsicmd[1] & 0x1f) != SAI_READ_CAPACITY_16) { ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - return 1; + return 0; } /* sector count, 64-bit */ @@ -2719,7 +2732,7 @@ static unsigned int ata_scsiop_read_cap(struct ata_device *dev, } } - return 0; + return 16; } /** @@ -2738,7 +2751,7 @@ static unsigned int ata_scsiop_report_luns(struct ata_device *dev, { rbuf[3] = 8; /* just one lun, LUN 0, size 8 bytes */ - return 0; + return 16; } /* @@ -3463,13 +3476,13 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev, if ((cdb[1] & 0x1f) != MI_REPORT_SUPPORTED_OPERATION_CODES) { ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - return 1; + return 0; } if (cdb[2] != 1 && cdb[2] != 3) { ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - return 1; + return 0; } switch (cdb[3]) { @@ -3542,7 +3555,7 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev, rbuf[0] = rwcdlp; rbuf[1] = cdlp | supported; - return 0; + return 4; } /** |