ata: libata-core: Remove ata_exec_internal_sg()
ata_exec_internal() is the only caller of ata_exec_internal_sg() and always calls this function with a single element scattergather list. Remove ata_exec_internal_sg() and code it directly in ata_exec_internal(), simplifying a little the sgl handling for the command. While at it, change the function signature to use the proper enum dma_data_direction type for the dma_dir argument, cleanup comments (capitalization and remove useless comments) and change the variable auto_timeout type to a boolean. No functional change. Signed-off-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: John Garry <john.g.garry@oracle.com> Reviewed-by: Niklas Cassel <cassel@kernel.org>
This commit is contained in:
parent
21a6f37d88
commit
9e6938e14e
@ -1480,19 +1480,19 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_exec_internal_sg - execute libata internal command
|
* ata_exec_internal - execute libata internal command
|
||||||
* @dev: Device to which the command is sent
|
* @dev: Device to which the command is sent
|
||||||
* @tf: Taskfile registers for the command and the result
|
* @tf: Taskfile registers for the command and the result
|
||||||
* @cdb: CDB for packet command
|
* @cdb: CDB for packet command
|
||||||
* @dma_dir: Data transfer direction of the command
|
* @dma_dir: Data transfer direction of the command
|
||||||
* @sgl: sg list for the data buffer of the command
|
* @buf: Data buffer of the command
|
||||||
* @n_elem: Number of sg entries
|
* @buflen: Length of data buffer
|
||||||
* @timeout: Timeout in msecs (0 for default)
|
* @timeout: Timeout in msecs (0 for default)
|
||||||
*
|
*
|
||||||
* Executes libata internal command with timeout. @tf contains
|
* Executes libata internal command with timeout. @tf contains
|
||||||
* command on entry and result on return. Timeout and error
|
* the command on entry and the result on return. Timeout and error
|
||||||
* conditions are reported via return value. No recovery action
|
* conditions are reported via the return value. No recovery action
|
||||||
* is taken after a command times out. It's caller's duty to
|
* is taken after a command times out. It is the caller's duty to
|
||||||
* clean up after timeout.
|
* clean up after timeout.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
@ -1501,34 +1501,38 @@ static void ata_qc_complete_internal(struct ata_queued_cmd *qc)
|
|||||||
* RETURNS:
|
* RETURNS:
|
||||||
* Zero on success, AC_ERR_* mask on failure
|
* Zero on success, AC_ERR_* mask on failure
|
||||||
*/
|
*/
|
||||||
static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
unsigned int ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf,
|
||||||
struct ata_taskfile *tf, const u8 *cdb,
|
const u8 *cdb, enum dma_data_direction dma_dir,
|
||||||
int dma_dir, struct scatterlist *sgl,
|
void *buf, unsigned int buflen,
|
||||||
unsigned int n_elem, unsigned int timeout)
|
unsigned int timeout)
|
||||||
{
|
{
|
||||||
struct ata_link *link = dev->link;
|
struct ata_link *link = dev->link;
|
||||||
struct ata_port *ap = link->ap;
|
struct ata_port *ap = link->ap;
|
||||||
u8 command = tf->command;
|
u8 command = tf->command;
|
||||||
int auto_timeout = 0;
|
|
||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
|
struct scatterlist sgl;
|
||||||
unsigned int preempted_tag;
|
unsigned int preempted_tag;
|
||||||
u32 preempted_sactive;
|
u32 preempted_sactive;
|
||||||
u64 preempted_qc_active;
|
u64 preempted_qc_active;
|
||||||
int preempted_nr_active_links;
|
int preempted_nr_active_links;
|
||||||
|
bool auto_timeout = false;
|
||||||
DECLARE_COMPLETION_ONSTACK(wait);
|
DECLARE_COMPLETION_ONSTACK(wait);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int err_mask;
|
unsigned int err_mask;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
if (WARN_ON(dma_dir != DMA_NONE && !buf))
|
||||||
|
return AC_ERR_INVALID;
|
||||||
|
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
/* no internal command while frozen */
|
/* No internal command while frozen */
|
||||||
if (ata_port_is_frozen(ap)) {
|
if (ata_port_is_frozen(ap)) {
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
return AC_ERR_SYSTEM;
|
return AC_ERR_SYSTEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize internal qc */
|
/* Initialize internal qc */
|
||||||
qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
|
qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
|
||||||
|
|
||||||
qc->tag = ATA_TAG_INTERNAL;
|
qc->tag = ATA_TAG_INTERNAL;
|
||||||
@ -1547,12 +1551,12 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
ap->qc_active = 0;
|
ap->qc_active = 0;
|
||||||
ap->nr_active_links = 0;
|
ap->nr_active_links = 0;
|
||||||
|
|
||||||
/* prepare & issue qc */
|
/* Prepare and issue qc */
|
||||||
qc->tf = *tf;
|
qc->tf = *tf;
|
||||||
if (cdb)
|
if (cdb)
|
||||||
memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
|
memcpy(qc->cdb, cdb, ATAPI_CDB_LEN);
|
||||||
|
|
||||||
/* some SATA bridges need us to indicate data xfer direction */
|
/* Some SATA bridges need us to indicate data xfer direction */
|
||||||
if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) &&
|
if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) &&
|
||||||
dma_dir == DMA_FROM_DEVICE)
|
dma_dir == DMA_FROM_DEVICE)
|
||||||
qc->tf.feature |= ATAPI_DMADIR;
|
qc->tf.feature |= ATAPI_DMADIR;
|
||||||
@ -1560,13 +1564,8 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
qc->flags |= ATA_QCFLAG_RESULT_TF;
|
qc->flags |= ATA_QCFLAG_RESULT_TF;
|
||||||
qc->dma_dir = dma_dir;
|
qc->dma_dir = dma_dir;
|
||||||
if (dma_dir != DMA_NONE) {
|
if (dma_dir != DMA_NONE) {
|
||||||
unsigned int i, buflen = 0;
|
sg_init_one(&sgl, buf, buflen);
|
||||||
struct scatterlist *sg;
|
ata_sg_init(qc, &sgl, 1);
|
||||||
|
|
||||||
for_each_sg(sgl, sg, n_elem, i)
|
|
||||||
buflen += sg->length;
|
|
||||||
|
|
||||||
ata_sg_init(qc, sgl, n_elem);
|
|
||||||
qc->nbytes = buflen;
|
qc->nbytes = buflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1578,11 +1577,11 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
|
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
if (ata_probe_timeout)
|
if (ata_probe_timeout) {
|
||||||
timeout = ata_probe_timeout * 1000;
|
timeout = ata_probe_timeout * 1000;
|
||||||
else {
|
} else {
|
||||||
timeout = ata_internal_cmd_timeout(dev, command);
|
timeout = ata_internal_cmd_timeout(dev, command);
|
||||||
auto_timeout = 1;
|
auto_timeout = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1595,30 +1594,25 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
ata_sff_flush_pio_task(ap);
|
ata_sff_flush_pio_task(ap);
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
/*
|
||||||
|
* We are racing with irq here. If we lose, the following test
|
||||||
/* We're racing with irq here. If we lose, the
|
* prevents us from completing the qc twice. If we win, the port
|
||||||
* following test prevents us from completing the qc
|
* is frozen and will be cleaned up by ->post_internal_cmd().
|
||||||
* twice. If we win, the port is frozen and will be
|
|
||||||
* cleaned up by ->post_internal_cmd().
|
|
||||||
*/
|
*/
|
||||||
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
if (qc->flags & ATA_QCFLAG_ACTIVE) {
|
if (qc->flags & ATA_QCFLAG_ACTIVE) {
|
||||||
qc->err_mask |= AC_ERR_TIMEOUT;
|
qc->err_mask |= AC_ERR_TIMEOUT;
|
||||||
|
|
||||||
ata_port_freeze(ap);
|
ata_port_freeze(ap);
|
||||||
|
|
||||||
ata_dev_warn(dev, "qc timeout after %u msecs (cmd 0x%x)\n",
|
ata_dev_warn(dev, "qc timeout after %u msecs (cmd 0x%x)\n",
|
||||||
timeout, command);
|
timeout, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do post_internal_cmd */
|
|
||||||
if (ap->ops->post_internal_cmd)
|
if (ap->ops->post_internal_cmd)
|
||||||
ap->ops->post_internal_cmd(qc);
|
ap->ops->post_internal_cmd(qc);
|
||||||
|
|
||||||
/* perform minimal error analysis */
|
/* Perform minimal error analysis */
|
||||||
if (qc->flags & ATA_QCFLAG_EH) {
|
if (qc->flags & ATA_QCFLAG_EH) {
|
||||||
if (qc->result_tf.status & (ATA_ERR | ATA_DF))
|
if (qc->result_tf.status & (ATA_ERR | ATA_DF))
|
||||||
qc->err_mask |= AC_ERR_DEV;
|
qc->err_mask |= AC_ERR_DEV;
|
||||||
@ -1632,7 +1626,7 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
qc->result_tf.status |= ATA_SENSE;
|
qc->result_tf.status |= ATA_SENSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finish up */
|
/* Finish up */
|
||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
*tf = qc->result_tf;
|
*tf = qc->result_tf;
|
||||||
@ -1652,44 +1646,6 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
|
|||||||
return err_mask;
|
return err_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ata_exec_internal - execute libata internal command
|
|
||||||
* @dev: Device to which the command is sent
|
|
||||||
* @tf: Taskfile registers for the command and the result
|
|
||||||
* @cdb: CDB for packet command
|
|
||||||
* @dma_dir: Data transfer direction of the command
|
|
||||||
* @buf: Data buffer of the command
|
|
||||||
* @buflen: Length of data buffer
|
|
||||||
* @timeout: Timeout in msecs (0 for default)
|
|
||||||
*
|
|
||||||
* Wrapper around ata_exec_internal_sg() which takes simple
|
|
||||||
* buffer instead of sg list.
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
* None. Should be called with kernel context, might sleep.
|
|
||||||
*
|
|
||||||
* RETURNS:
|
|
||||||
* Zero on success, AC_ERR_* mask on failure
|
|
||||||
*/
|
|
||||||
unsigned ata_exec_internal(struct ata_device *dev,
|
|
||||||
struct ata_taskfile *tf, const u8 *cdb,
|
|
||||||
int dma_dir, void *buf, unsigned int buflen,
|
|
||||||
unsigned int timeout)
|
|
||||||
{
|
|
||||||
struct scatterlist *psg = NULL, sg;
|
|
||||||
unsigned int n_elem = 0;
|
|
||||||
|
|
||||||
if (dma_dir != DMA_NONE) {
|
|
||||||
WARN_ON(!buf);
|
|
||||||
sg_init_one(&sg, buf, buflen);
|
|
||||||
psg = &sg;
|
|
||||||
n_elem++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem,
|
|
||||||
timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_pio_need_iordy - check if iordy needed
|
* ata_pio_need_iordy - check if iordy needed
|
||||||
* @adev: ATA device
|
* @adev: ATA device
|
||||||
|
@ -50,10 +50,10 @@ extern int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block,
|
|||||||
unsigned int tf_flags, int dld, int class);
|
unsigned int tf_flags, int dld, int class);
|
||||||
extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
|
extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
|
||||||
struct ata_device *dev);
|
struct ata_device *dev);
|
||||||
extern unsigned ata_exec_internal(struct ata_device *dev,
|
unsigned int ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf,
|
||||||
struct ata_taskfile *tf, const u8 *cdb,
|
const u8 *cdb, enum dma_data_direction dma_dir,
|
||||||
int dma_dir, void *buf, unsigned int buflen,
|
void *buf, unsigned int buflen,
|
||||||
unsigned int timeout);
|
unsigned int timeout);
|
||||||
extern int ata_wait_ready(struct ata_link *link, unsigned long deadline,
|
extern int ata_wait_ready(struct ata_link *link, unsigned long deadline,
|
||||||
int (*check_ready)(struct ata_link *link));
|
int (*check_ready)(struct ata_link *link));
|
||||||
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
|
||||||
|
Loading…
Reference in New Issue
Block a user