mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:44:45 +01:00
ata: libata-scsi: refactor ata_scsi_translate()
Factor out of ata_scsi_translate() the code handling queued command deferral using the port qc_defer callback and issuing the queued command with ata_qc_issue() into the new function ata_scsi_qc_issue(), and simplify the goto used in ata_scsi_translate(). While at it, also add a lockdep annotation to check that the port lock is held when ata_scsi_translate() is called. No functional changes. Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Niklas Cassel <cassel@kernel.org> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Reviewed-by: John Garry <john.g.garry@oracle.com> Reviewed-by: Igor Pylypiv <ipylypiv@google.com>
This commit is contained in:
parent
97e01439e9
commit
bb3a8154b1
1 changed files with 50 additions and 31 deletions
|
|
@ -1691,6 +1691,42 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
|||
ata_qc_done(qc);
|
||||
}
|
||||
|
||||
static int ata_scsi_qc_issue(struct ata_port *ap, struct ata_queued_cmd *qc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ap->ops->qc_defer)
|
||||
goto issue;
|
||||
|
||||
/* Check if the command needs to be deferred. */
|
||||
ret = ap->ops->qc_defer(qc);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
break;
|
||||
case ATA_DEFER_LINK:
|
||||
ret = SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
break;
|
||||
case ATA_DEFER_PORT:
|
||||
ret = SCSI_MLQUEUE_HOST_BUSY;
|
||||
break;
|
||||
default:
|
||||
WARN_ON_ONCE(1);
|
||||
ret = SCSI_MLQUEUE_HOST_BUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
/* Force a requeue of the command to defer its execution. */
|
||||
ata_qc_free(qc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
issue:
|
||||
ata_qc_issue(qc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ata_scsi_translate - Translate then issue SCSI command to ATA device
|
||||
* @dev: ATA device to which the command is addressed
|
||||
|
|
@ -1714,66 +1750,49 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
|
|||
* spin_lock_irqsave(host lock)
|
||||
*
|
||||
* RETURNS:
|
||||
* 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY if the command
|
||||
* needs to be deferred.
|
||||
* 0 on success, SCSI_ML_QUEUE_DEVICE_BUSY or SCSI_MLQUEUE_HOST_BUSY if the
|
||||
* command needs to be deferred.
|
||||
*/
|
||||
static int ata_scsi_translate(struct ata_device *dev, struct scsi_cmnd *cmd,
|
||||
ata_xlat_func_t xlat_func)
|
||||
{
|
||||
struct ata_port *ap = dev->link->ap;
|
||||
struct ata_queued_cmd *qc;
|
||||
int rc;
|
||||
|
||||
lockdep_assert_held(ap->lock);
|
||||
|
||||
/*
|
||||
* ata_scsi_qc_new() calls scsi_done(cmd) in case of failure. So we
|
||||
* have nothing further to do when allocating a qc fails.
|
||||
*/
|
||||
qc = ata_scsi_qc_new(dev, cmd);
|
||||
if (!qc)
|
||||
goto err_mem;
|
||||
return 0;
|
||||
|
||||
/* data is present; dma-map it */
|
||||
if (cmd->sc_data_direction == DMA_FROM_DEVICE ||
|
||||
cmd->sc_data_direction == DMA_TO_DEVICE) {
|
||||
if (unlikely(scsi_bufflen(cmd) < 1)) {
|
||||
ata_dev_warn(dev, "WARNING: zero len r/w req\n");
|
||||
goto err_did;
|
||||
cmd->result = (DID_ERROR << 16);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ata_sg_init(qc, scsi_sglist(cmd), scsi_sg_count(cmd));
|
||||
|
||||
qc->dma_dir = cmd->sc_data_direction;
|
||||
}
|
||||
|
||||
qc->complete_fn = ata_scsi_qc_complete;
|
||||
|
||||
if (xlat_func(qc))
|
||||
goto early_finish;
|
||||
goto done;
|
||||
|
||||
if (ap->ops->qc_defer) {
|
||||
if ((rc = ap->ops->qc_defer(qc)))
|
||||
goto defer;
|
||||
}
|
||||
return ata_scsi_qc_issue(ap, qc);
|
||||
|
||||
/* select device, send command to hardware */
|
||||
ata_qc_issue(qc);
|
||||
|
||||
return 0;
|
||||
|
||||
early_finish:
|
||||
done:
|
||||
ata_qc_free(qc);
|
||||
scsi_done(cmd);
|
||||
return 0;
|
||||
|
||||
err_did:
|
||||
ata_qc_free(qc);
|
||||
cmd->result = (DID_ERROR << 16);
|
||||
scsi_done(cmd);
|
||||
err_mem:
|
||||
return 0;
|
||||
|
||||
defer:
|
||||
ata_qc_free(qc);
|
||||
if (rc == ATA_DEFER_LINK)
|
||||
return SCSI_MLQUEUE_DEVICE_BUSY;
|
||||
else
|
||||
return SCSI_MLQUEUE_HOST_BUSY;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue