mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
libata: switch to using block layer tagging support
libata currently has a pretty dumb ATA_MAX_QUEUE loop for finding a free tag to use. Instead of fixing that up, convert libata to using block layer tagging - gets rid of code in libata, and is also much faster. Signed-off-by: Jens Axboe <jens.axboe@oracle.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
332edc2f7f
commit
2fca5ccf97
4 changed files with 31 additions and 65 deletions
|
@ -1713,8 +1713,6 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
|
||||||
else
|
else
|
||||||
tag = 0;
|
tag = 0;
|
||||||
|
|
||||||
if (test_and_set_bit(tag, &ap->qc_allocated))
|
|
||||||
BUG();
|
|
||||||
qc = __ata_qc_from_tag(ap, tag);
|
qc = __ata_qc_from_tag(ap, tag);
|
||||||
|
|
||||||
qc->tag = tag;
|
qc->tag = tag;
|
||||||
|
@ -4552,37 +4550,6 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
|
||||||
#endif /* __BIG_ENDIAN */
|
#endif /* __BIG_ENDIAN */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ata_qc_new - Request an available ATA command, for queueing
|
|
||||||
* @ap: Port associated with device @dev
|
|
||||||
* @dev: Device from whom we request an available command structure
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
* None.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
|
||||||
{
|
|
||||||
struct ata_queued_cmd *qc = NULL;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
/* no command while frozen */
|
|
||||||
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
/* the last tag is reserved for internal command. */
|
|
||||||
for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
|
|
||||||
if (!test_and_set_bit(i, &ap->qc_allocated)) {
|
|
||||||
qc = __ata_qc_from_tag(ap, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qc)
|
|
||||||
qc->tag = i;
|
|
||||||
|
|
||||||
return qc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_qc_new_init - Request an available ATA command, and initialize it
|
* ata_qc_new_init - Request an available ATA command, and initialize it
|
||||||
* @dev: Device from whom we request an available command structure
|
* @dev: Device from whom we request an available command structure
|
||||||
|
@ -4591,16 +4558,20 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
||||||
* None.
|
* None.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
|
struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = dev->link->ap;
|
struct ata_port *ap = dev->link->ap;
|
||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
|
|
||||||
qc = ata_qc_new(ap);
|
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
qc = __ata_qc_from_tag(ap, tag);
|
||||||
if (qc) {
|
if (qc) {
|
||||||
qc->scsicmd = NULL;
|
qc->scsicmd = NULL;
|
||||||
qc->ap = ap;
|
qc->ap = ap;
|
||||||
qc->dev = dev;
|
qc->dev = dev;
|
||||||
|
qc->tag = tag;
|
||||||
|
|
||||||
ata_qc_reinit(qc);
|
ata_qc_reinit(qc);
|
||||||
}
|
}
|
||||||
|
@ -4608,31 +4579,6 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev)
|
||||||
return qc;
|
return qc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ata_qc_free - free unused ata_queued_cmd
|
|
||||||
* @qc: Command to complete
|
|
||||||
*
|
|
||||||
* Designed to free unused ata_queued_cmd object
|
|
||||||
* in case something prevents using it.
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
* spin_lock_irqsave(host lock)
|
|
||||||
*/
|
|
||||||
void ata_qc_free(struct ata_queued_cmd *qc)
|
|
||||||
{
|
|
||||||
struct ata_port *ap = qc->ap;
|
|
||||||
unsigned int tag;
|
|
||||||
|
|
||||||
WARN_ON(qc == NULL); /* ata_qc_from_tag _might_ return NULL */
|
|
||||||
|
|
||||||
qc->flags = 0;
|
|
||||||
tag = qc->tag;
|
|
||||||
if (likely(ata_tag_valid(tag))) {
|
|
||||||
qc->tag = ATA_TAG_POISON;
|
|
||||||
clear_bit(tag, &ap->qc_allocated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void __ata_qc_complete(struct ata_queued_cmd *qc)
|
void __ata_qc_complete(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
struct ata_port *ap = qc->ap;
|
struct ata_port *ap = qc->ap;
|
||||||
|
|
|
@ -708,7 +708,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
|
||||||
{
|
{
|
||||||
struct ata_queued_cmd *qc;
|
struct ata_queued_cmd *qc;
|
||||||
|
|
||||||
qc = ata_qc_new_init(dev);
|
qc = ata_qc_new_init(dev, cmd->request->tag);
|
||||||
if (qc) {
|
if (qc) {
|
||||||
qc->scsicmd = cmd;
|
qc->scsicmd = cmd;
|
||||||
qc->scsidone = done;
|
qc->scsidone = done;
|
||||||
|
@ -1103,7 +1103,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
|
||||||
|
|
||||||
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
|
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
|
||||||
depth = min(ATA_MAX_QUEUE - 1, depth);
|
depth = min(ATA_MAX_QUEUE - 1, depth);
|
||||||
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
|
scsi_set_tag_type(sdev, MSG_SIMPLE_TAG);
|
||||||
|
scsi_activate_tcq(sdev, depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1943,6 +1944,11 @@ static unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf)
|
||||||
hdr[1] |= (1 << 7);
|
hdr[1] |= (1 << 7);
|
||||||
|
|
||||||
memcpy(rbuf, hdr, sizeof(hdr));
|
memcpy(rbuf, hdr, sizeof(hdr));
|
||||||
|
|
||||||
|
/* if ncq, set tags supported */
|
||||||
|
if (ata_id_has_ncq(args->id))
|
||||||
|
rbuf[7] |= (1 << 1);
|
||||||
|
|
||||||
memcpy(&rbuf[8], "ATA ", 8);
|
memcpy(&rbuf[8], "ATA ", 8);
|
||||||
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
|
ata_id_string(args->id, &rbuf[16], ATA_ID_PROD, 16);
|
||||||
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
|
ata_id_string(args->id, &rbuf[32], ATA_ID_FW_REV, 4);
|
||||||
|
|
|
@ -74,7 +74,7 @@ extern struct ata_link *ata_dev_phys_link(struct ata_device *dev);
|
||||||
extern void ata_force_cbl(struct ata_port *ap);
|
extern void ata_force_cbl(struct ata_port *ap);
|
||||||
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
|
extern u64 ata_tf_to_lba(const struct ata_taskfile *tf);
|
||||||
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
|
extern u64 ata_tf_to_lba48(const struct ata_taskfile *tf);
|
||||||
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
|
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag);
|
||||||
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
|
||||||
u64 block, u32 n_block, unsigned int tf_flags,
|
u64 block, u32 n_block, unsigned int tf_flags,
|
||||||
unsigned int tag);
|
unsigned int tag);
|
||||||
|
@ -103,7 +103,6 @@ extern int ata_dev_configure(struct ata_device *dev);
|
||||||
extern int sata_down_spd_limit(struct ata_link *link);
|
extern int sata_down_spd_limit(struct ata_link *link);
|
||||||
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
|
extern int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel);
|
||||||
extern void ata_sg_clean(struct ata_queued_cmd *qc);
|
extern void ata_sg_clean(struct ata_queued_cmd *qc);
|
||||||
extern void ata_qc_free(struct ata_queued_cmd *qc);
|
|
||||||
extern void ata_qc_issue(struct ata_queued_cmd *qc);
|
extern void ata_qc_issue(struct ata_queued_cmd *qc);
|
||||||
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
|
extern void __ata_qc_complete(struct ata_queued_cmd *qc);
|
||||||
extern int atapi_check_dma(struct ata_queued_cmd *qc);
|
extern int atapi_check_dma(struct ata_queued_cmd *qc);
|
||||||
|
@ -119,6 +118,22 @@ extern struct ata_port *ata_port_alloc(struct ata_host *host);
|
||||||
extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
|
extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
|
||||||
extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
|
extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_qc_free - free unused ata_queued_cmd
|
||||||
|
* @qc: Command to complete
|
||||||
|
*
|
||||||
|
* Designed to free unused ata_queued_cmd object
|
||||||
|
* in case something prevents using it.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host lock)
|
||||||
|
*/
|
||||||
|
static inline void ata_qc_free(struct ata_queued_cmd *qc)
|
||||||
|
{
|
||||||
|
qc->flags = 0;
|
||||||
|
qc->tag = ATA_TAG_POISON;
|
||||||
|
}
|
||||||
|
|
||||||
/* libata-acpi.c */
|
/* libata-acpi.c */
|
||||||
#ifdef CONFIG_ATA_ACPI
|
#ifdef CONFIG_ATA_ACPI
|
||||||
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
|
extern void ata_acpi_associate_sata_port(struct ata_port *ap);
|
||||||
|
|
|
@ -695,7 +695,6 @@ struct ata_port {
|
||||||
unsigned int cbl; /* cable type; ATA_CBL_xxx */
|
unsigned int cbl; /* cable type; ATA_CBL_xxx */
|
||||||
|
|
||||||
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
|
struct ata_queued_cmd qcmd[ATA_MAX_QUEUE];
|
||||||
unsigned long qc_allocated;
|
|
||||||
unsigned int qc_active;
|
unsigned int qc_active;
|
||||||
int nr_active_links; /* #links with active qcs */
|
int nr_active_links; /* #links with active qcs */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue