Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 29432
b: refs/heads/master
c: 3dc1d88
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo committed May 15, 2006
1 parent e32b97c commit 8e3f76a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dedaf2b0365ccec50714fbde0b3215e7e94fa47c
refs/heads/master: 3dc1d88193b9c65b01b64fb2dc730e486306649f
1 change: 1 addition & 0 deletions trunk/drivers/scsi/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4416,6 +4416,7 @@ static inline int ata_should_dma_map(struct ata_queued_cmd *qc)
struct ata_port *ap = qc->ap;

switch (qc->tf.protocol) {
case ATA_PROT_NCQ:
case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA:
return 1;
Expand Down
72 changes: 71 additions & 1 deletion trunk/drivers/scsi/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,36 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm
*/
goto nothing_to_do;

if (dev->flags & ATA_DFLAG_LBA) {
if ((dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ) {
/* yay, NCQ */
if (!lba_48_ok(block, n_block))
goto out_of_range;

tf->protocol = ATA_PROT_NCQ;
tf->flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;

if (tf->flags & ATA_TFLAG_WRITE)
tf->command = ATA_CMD_FPDMA_WRITE;
else
tf->command = ATA_CMD_FPDMA_READ;

qc->nsect = n_block;

tf->nsect = qc->tag << 3;
tf->hob_feature = (n_block >> 8) & 0xff;
tf->feature = n_block & 0xff;

tf->hob_lbah = (block >> 40) & 0xff;
tf->hob_lbam = (block >> 32) & 0xff;
tf->hob_lbal = (block >> 24) & 0xff;
tf->lbah = (block >> 16) & 0xff;
tf->lbam = (block >> 8) & 0xff;
tf->lbal = block & 0xff;

tf->device = 1 << 6;
if (tf->flags & ATA_TFLAG_FUA)
tf->device |= 1 << 7;
} else if (dev->flags & ATA_DFLAG_LBA) {
tf->flags |= ATA_TFLAG_LBA;

if (lba_28_ok(block, n_block)) {
Expand Down Expand Up @@ -1226,6 +1255,39 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
ata_qc_free(qc);
}

/**
* ata_scmd_need_defer - Check whether we need to defer scmd
* @dev: ATA device to which the command is addressed
* @is_io: Is the command IO (and thus possibly NCQ)?
*
* NCQ and non-NCQ commands cannot run together. As upper layer
* only knows the queue depth, we are responsible for maintaining
* exclusion. This function checks whether a new command can be
* issued to @dev.
*
* LOCKING:
* spin_lock_irqsave(host_set lock)
*
* RETURNS:
* 1 if deferring is needed, 0 otherwise.
*/
static int ata_scmd_need_defer(struct ata_device *dev, int is_io)
{
struct ata_port *ap = dev->ap;

if (!(dev->flags & ATA_DFLAG_NCQ))
return 0;

if (is_io) {
if (!ata_tag_valid(ap->active_tag))
return 0;
} else {
if (!ata_tag_valid(ap->active_tag) && !ap->sactive)
return 0;
}
return 1;
}

/**
* ata_scsi_translate - Translate then issue SCSI command to ATA device
* @dev: ATA device to which the command is addressed
Expand Down Expand Up @@ -1259,9 +1321,13 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
{
struct ata_queued_cmd *qc;
u8 *scsicmd = cmd->cmnd;
int is_io = xlat_func == ata_scsi_rw_xlat;

VPRINTK("ENTER\n");

if (unlikely(ata_scmd_need_defer(dev, is_io)))
goto defer;

qc = ata_scsi_qc_new(dev, cmd, done);
if (!qc)
goto err_mem;
Expand Down Expand Up @@ -1308,6 +1374,10 @@ static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
done(cmd);
DPRINTK("EXIT - internal\n");
return 0;

defer:
DPRINTK("EXIT - defer\n");
return SCSI_MLQUEUE_DEVICE_BUSY;
}

/**
Expand Down

0 comments on commit 8e3f76a

Please sign in to comment.