diff options
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 72 |
1 files changed, 71 insertions, 1 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 96517ca021e3..9bef68c7c1de 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -1103,7 +1103,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1103 | */ | 1103 | */ |
1104 | goto nothing_to_do; | 1104 | goto nothing_to_do; |
1105 | 1105 | ||
1106 | if (dev->flags & ATA_DFLAG_LBA) { | 1106 | if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) { |
1107 | /* yay, NCQ */ | ||
1108 | if (!lba_48_ok(block, n_block)) | ||
1109 | goto out_of_range; | ||
1110 | |||
1111 | tf->protocol = ATA_PROT_NCQ; | ||
1112 | tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48; | ||
1113 | |||
1114 | if (tf->flags & ATA_TFLAG_WRITE) | ||
1115 | tf->command = ATA_CMD_FPDMA_WRITE; | ||
1116 | else | ||
1117 | tf->command = ATA_CMD_FPDMA_READ; | ||
1118 | |||
1119 | qc->nsect = n_block; | ||
1120 | |||
1121 | tf->nsect = qc->tag << 3; | ||
1122 | tf->hob_feature = (n_block >> 8) & 0xff; | ||
1123 | tf->feature = n_block & 0xff; | ||
1124 | |||
1125 | tf->hob_lbah = (block >> 40) & 0xff; | ||
1126 | tf->hob_lbam = (block >> 32) & 0xff; | ||
1127 | tf->hob_lbal = (block >> 24) & 0xff; | ||
1128 | tf->lbah = (block >> 16) & 0xff; | ||
1129 | tf->lbam = (block >> 8) & 0xff; | ||
1130 | tf->lbal = block & 0xff; | ||
1131 | |||
1132 | tf->device = 1 << 6; | ||
1133 | if (tf->flags & ATA_TFLAG_FUA) | ||
1134 | tf->device |= 1 << 7; | ||
1135 | } else if (dev->flags & ATA_DFLAG_LBA) { | ||
1107 | tf->flags |= ATA_TFLAG_LBA; | 1136 | tf->flags |= ATA_TFLAG_LBA; |
1108 | 1137 | ||
1109 | if (lba_28_ok(block, n_block)) { | 1138 | if (lba_28_ok(block, n_block)) { |
@@ -1227,6 +1256,39 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) | |||
1227 | } | 1256 | } |
1228 | 1257 | ||
1229 | /** | 1258 | /** |
1259 | * ata_scmd_need_defer - Check whether we need to defer scmd | ||
1260 | * @dev: ATA device to which the command is addressed | ||
1261 | * @is_io: Is the command IO (and thus possibly NCQ)? | ||
1262 | * | ||
1263 | * NCQ and non-NCQ commands cannot run together. As upper layer | ||
1264 | * only knows the queue depth, we are responsible for maintaining | ||
1265 | * exclusion. This function checks whether a new command can be | ||
1266 | * issued to @dev. | ||
1267 | * | ||
1268 | * LOCKING: | ||
1269 | * spin_lock_irqsave(host_set lock) | ||
1270 | * | ||
1271 | * RETURNS: | ||
1272 | * 1 if deferring is needed, 0 otherwise. | ||
1273 | */ | ||
1274 | static int ata_scmd_need_defer(struct ata_device *dev, int is_io) | ||
1275 | { | ||
1276 | struct ata_port *ap = dev->ap; | ||
1277 | |||
1278 | if (!(dev->flags & ATA_DFLAG_NCQ)) | ||
1279 | return 0; | ||
1280 | |||
1281 | if (is_io) { | ||
1282 | if (!ata_tag_valid(ap->active_tag)) | ||
1283 | return 0; | ||
1284 | } else { | ||
1285 | if (!ata_tag_valid(ap->active_tag) && !ap->sactive) | ||
1286 | return 0; | ||
1287 | } | ||
1288 | return 1; | ||
1289 | } | ||
1290 | |||
1291 | /** | ||
1230 | * ata_scsi_translate - Translate then issue SCSI command to ATA device | 1292 | * ata_scsi_translate - Translate then issue SCSI command to ATA device |
1231 | * @dev: ATA device to which the command is addressed | 1293 | * @dev: ATA device to which the command is addressed |
1232 | * @cmd: SCSI command to execute | 1294 | * @cmd: SCSI command to execute |
@@ -1259,9 +1321,13 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd, | |||
1259 | { | 1321 | { |
1260 | struct ata_queued_cmd *qc; | 1322 | struct ata_queued_cmd *qc; |
1261 | u8 *scsicmd = cmd->cmnd; | 1323 | u8 *scsicmd = cmd->cmnd; |
1324 | int is_io = xlat_func == ata_scsi_rw_xlat; | ||
1262 | 1325 | ||
1263 | VPRINTK("ENTER\n"); | 1326 | VPRINTK("ENTER\n"); |
1264 | 1327 | ||
1328 | if (unlikely(ata_scmd_need_defer(dev, is_io))) | ||
1329 | goto defer; | ||
1330 | |||
1265 | qc = ata_scsi_qc_new(dev, cmd, done); | 1331 | qc = ata_scsi_qc_new(dev, cmd, done); |
1266 | if (!qc) | 1332 | if (!qc) |
1267 | goto err_mem; | 1333 | goto err_mem; |
@@ -1308,6 +1374,10 @@ err_mem: | |||
1308 | done(cmd); | 1374 | done(cmd); |
1309 | DPRINTK("EXIT - internal\n"); | 1375 | DPRINTK("EXIT - internal\n"); |
1310 | return 0; | 1376 | return 0; |
1377 | |||
1378 | defer: | ||
1379 | DPRINTK("EXIT - defer\n"); | ||
1380 | return SCSI_MLQUEUE_DEVICE_BUSY; | ||
1311 | } | 1381 | } |
1312 | 1382 | ||
1313 | /** | 1383 | /** |