| From: Kevin Hao <haokexin@gmail.com> |
| Date: Sat, 12 Jul 2014 12:08:24 +0800 |
| Subject: libata: support the ata host which implements a queue depth less than |
| 32 |
| |
| commit 1871ee134b73fb4cadab75752a7152ed2813c751 upstream. |
| |
| The sata on fsl mpc8315e is broken after the commit 8a4aeec8d2d6 |
| ("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: 8a4aeec8d2d6 ("libata/ahci: accommodate tag ordered controllers") |
| Signed-off-by: Kevin Hao <haokexin@gmail.com> |
| Acked-by: Dan Williams <dan.j.williams@intel.com> |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/ata/libata-core.c | 22 +++++++++++++++++++--- |
| 1 file changed, 19 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/ata/libata-core.c |
| +++ b/drivers/ata/libata-core.c |
| @@ -4711,6 +4711,10 @@ void swap_buf_le16(u16 *buf, unsigned in |
| * 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. |
| */ |
| @@ -4718,14 +4722,16 @@ void swap_buf_le16(u16 *buf, unsigned in |
| 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) |
| @@ -5998,6 +6004,16 @@ int ata_host_register(struct ata_host *h |
| { |
| 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"); |