|
@@ -2761,28 +2761,48 @@ static inline int __ata_scsi_queuecmd(struct scsi_cmnd *scmd,
|
|
|
void (*done)(struct scsi_cmnd *),
|
|
|
struct ata_device *dev)
|
|
|
{
|
|
|
+ u8 scsi_op = scmd->cmnd[0];
|
|
|
+ ata_xlat_func_t xlat_func;
|
|
|
int rc = 0;
|
|
|
|
|
|
- if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len)) {
|
|
|
- DPRINTK("bad CDB len=%u, max=%u\n",
|
|
|
- scmd->cmd_len, dev->cdb_len);
|
|
|
- scmd->result = DID_ERROR << 16;
|
|
|
- done(scmd);
|
|
|
- return 0;
|
|
|
- }
|
|
|
-
|
|
|
if (dev->class == ATA_DEV_ATA) {
|
|
|
- ata_xlat_func_t xlat_func = ata_get_xlat_func(dev,
|
|
|
- scmd->cmnd[0]);
|
|
|
+ if (unlikely(!scmd->cmd_len || scmd->cmd_len > dev->cdb_len))
|
|
|
+ goto bad_cdb_len;
|
|
|
|
|
|
- if (xlat_func)
|
|
|
- rc = ata_scsi_translate(dev, scmd, done, xlat_func);
|
|
|
- else
|
|
|
- ata_scsi_simulate(dev, scmd, done);
|
|
|
- } else
|
|
|
- rc = ata_scsi_translate(dev, scmd, done, atapi_xlat);
|
|
|
+ xlat_func = ata_get_xlat_func(dev, scsi_op);
|
|
|
+ } else {
|
|
|
+ if (unlikely(!scmd->cmd_len))
|
|
|
+ goto bad_cdb_len;
|
|
|
+
|
|
|
+ xlat_func = NULL;
|
|
|
+ if (likely((scsi_op != ATA_16) || !atapi_passthru16)) {
|
|
|
+ /* relay SCSI command to ATAPI device */
|
|
|
+ if (unlikely(scmd->cmd_len > dev->cdb_len))
|
|
|
+ goto bad_cdb_len;
|
|
|
+
|
|
|
+ xlat_func = atapi_xlat;
|
|
|
+ } else {
|
|
|
+ /* ATA_16 passthru, treat as an ATA command */
|
|
|
+ if (unlikely(scmd->cmd_len > 16))
|
|
|
+ goto bad_cdb_len;
|
|
|
+
|
|
|
+ xlat_func = ata_get_xlat_func(dev, scsi_op);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (xlat_func)
|
|
|
+ rc = ata_scsi_translate(dev, scmd, done, xlat_func);
|
|
|
+ else
|
|
|
+ ata_scsi_simulate(dev, scmd, done);
|
|
|
|
|
|
return rc;
|
|
|
+
|
|
|
+ bad_cdb_len:
|
|
|
+ DPRINTK("bad CDB len=%u, scsi_op=0x%02x, max=%u\n",
|
|
|
+ scmd->cmd_len, scsi_op, dev->cdb_len);
|
|
|
+ scmd->result = DID_ERROR << 16;
|
|
|
+ done(scmd);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|