Skip to content

Commit

Permalink
libata: support the ata host which implements a queue depth less than 32
Browse files Browse the repository at this point in the history
The sata on fsl mpc8315e is broken after the commit 8a4aeec
("libata/ahci: accommodate tag ordered controllers"). The reason is
that the ata controller on this SoC only implement a queue depth of
16. When issuing the commands in tag order, all the commands in tag
16 ~ 31 are mapped to tag 0 unconditionally and then causes the sata
malfunction. It makes no senses to use a 32 queue in software while
the hardware has less queue depth. So consider the queue depth
implemented by the hardware when requesting a command tag.

Fixes: 8a4aeec ("libata/ahci: accommodate tag ordered controllers")
Cc: [email protected]
Signed-off-by: Kevin Hao <[email protected]>
Acked-by: Dan Williams <[email protected]>
Signed-off-by: Tejun Heo <[email protected]>
  • Loading branch information
haokexin authored and htejun committed Jul 14, 2014
1 parent 7188b06 commit 1871ee1
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -4787,21 +4787,27 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
* ata_qc_new - Request an available ATA command, for queueing
* @ap: target port
*
* Some ATA host controllers may implement a queue depth which is less
* than ATA_MAX_QUEUE. So we shouldn't allocate a tag which is beyond
* the hardware limitation.
*
* LOCKING:
* None.
*/

static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
{
struct ata_queued_cmd *qc = NULL;
unsigned int i, tag;
unsigned int i, tag, max_queue;

max_queue = ap->scsi_host->can_queue;

/* no command while frozen */
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;

for (i = 0; i < ATA_MAX_QUEUE; i++) {
tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
for (i = 0, tag = ap->last_tag + 1; i < max_queue; i++, tag++) {
tag = tag < max_queue ? tag : 0;

/* the last tag is reserved for internal command. */
if (tag == ATA_TAG_INTERNAL)
Expand Down Expand Up @@ -6169,6 +6175,16 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
{
int i, rc;

/*
* The max queue supported by hardware must not be greater than
* ATA_MAX_QUEUE.
*/
if (sht->can_queue > ATA_MAX_QUEUE) {
dev_err(host->dev, "BUG: the hardware max queue is too large\n");
WARN_ON(1);
return -EINVAL;
}

/* host must have been started */
if (!(host->flags & ATA_HOST_STARTED)) {
dev_err(host->dev, "BUG: trying to register unstarted host\n");
Expand Down

0 comments on commit 1871ee1

Please sign in to comment.