* [PATCH v2 0/2] libata: support the ata host which implements a queue depth less than 32
@ 2014-07-06 6:28 Kevin Hao
2014-07-06 6:28 ` [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth() Kevin Hao
2014-07-06 6:28 ` [PATCH v2 2/2] sata_fsl: set the correct queue depth for the host controller Kevin Hao
0 siblings, 2 replies; 9+ messages in thread
From: Kevin Hao @ 2014-07-06 6:28 UTC (permalink / raw)
To: linux-ide; +Cc: Tejun Heo, Dan Williams
Hi,
v2: Remove the changes for the ata tag helper functions.
v1:
The fsl sata on mpc8315e is broken after the commit 8a4aeec8d2d6
("libata/ahci: accommodate tag ordered controllers"). This patch
serial tries to fix this problem. This is based on the next-20140702.
Boot test on the mpc8315rdb board.
Kevin Hao (2):
libata: introduce ata_host_set_queue_depth()
sata_fsl: set the correct queue depth for the host controller
drivers/ata/libata-core.c | 29 ++++++++++++++++++++++++++---
drivers/ata/sata_fsl.c | 3 +++
include/linux/libata.h | 3 +++
3 files changed, 32 insertions(+), 3 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-06 6:28 [PATCH v2 0/2] libata: support the ata host which implements a queue depth less than 32 Kevin Hao
@ 2014-07-06 6:28 ` Kevin Hao
2014-07-07 13:49 ` Tejun Heo
2014-07-07 18:19 ` Dan Williams
2014-07-06 6:28 ` [PATCH v2 2/2] sata_fsl: set the correct queue depth for the host controller Kevin Hao
1 sibling, 2 replies; 9+ messages in thread
From: Kevin Hao @ 2014-07-06 6:28 UTC (permalink / raw)
To: linux-ide; +Cc: Tejun Heo, Dan Williams
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 ~ 17 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. This patch provides the function
for libata to adjust the queue depth for a host controller.
Fixes: 8a4aeec8d2d6 ("libata/ahci: accommodate tag ordered controllers")
Cc: stable@vger.kernel.org
Signed-off-by: Kevin Hao <haokexin@gmail.com>
---
v2: Remove the changes for the ata tag helper functions.
drivers/ata/libata-core.c | 29 ++++++++++++++++++++++++++---
include/linux/libata.h | 3 +++
2 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8f3043165048..c9c51646d8e8 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4728,14 +4728,14 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
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 = ap->host->queue_depth;
/* 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; i < max_queue; i++) {
+ tag = (i + ap->last_tag + 1) % max_queue;
/* the last tag is reserved for internal command. */
if (tag == ATA_TAG_INTERNAL)
@@ -5687,6 +5687,27 @@ static void ata_host_release(struct device *gendev, void *res)
}
/**
+ * ata_host_set_queue_depth - set the ATA host controller's queue depth
+ * @host: ATA host to be set for
+ * @queue_depth: the queue depth implemented on this host controller
+ *
+ * We would assume that the ATA host controller has 32 queue depth and
+ * then set the host->queue_depth to 32 by default. If this is not true
+ * for one specific ATA host controller, you need to invoke this function
+ * to set the correct value.
+ */
+int ata_host_set_queue_depth(struct ata_host *host, unsigned int queue_depth)
+{
+ if (!queue_depth || queue_depth > ATA_MAX_QUEUE) {
+ dev_err(host->dev, "Invalid queue depth\n");
+ return -EINVAL;
+ }
+
+ host->queue_depth = queue_depth;
+ return 0;
+}
+
+/**
* ata_host_alloc - allocate and init basic ATA host resources
* @dev: generic device this host is associated with
* @max_ports: maximum number of ATA ports associated with this host
@@ -5731,6 +5752,7 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
mutex_init(&host->eh_mutex);
host->dev = dev;
host->n_ports = max_ports;
+ host->queue_depth = ATA_MAX_QUEUE;
/* allocate ports bound to this host */
for (i = 0; i < max_ports; i++) {
@@ -6855,6 +6877,7 @@ EXPORT_SYMBOL_GPL(ata_dev_next);
EXPORT_SYMBOL_GPL(ata_std_bios_param);
EXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity);
EXPORT_SYMBOL_GPL(ata_host_init);
+EXPORT_SYMBOL_GPL(ata_host_set_queue_depth);
EXPORT_SYMBOL_GPL(ata_host_alloc);
EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
EXPORT_SYMBOL_GPL(ata_slave_link_init);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5ab4e3a76721..3d912845f7df 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -593,6 +593,7 @@ struct ata_host {
struct device *dev;
void __iomem * const *iomap;
unsigned int n_ports;
+ unsigned int queue_depth;
void *private_data;
struct ata_port_operations *ops;
unsigned long flags;
@@ -1104,6 +1105,8 @@ extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
+extern int ata_host_set_queue_depth(struct ata_host *host,
+ unsigned int queue_depth);
extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
const struct ata_port_info * const * ppi, int n_ports);
--
1.9.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/2] sata_fsl: set the correct queue depth for the host controller
2014-07-06 6:28 [PATCH v2 0/2] libata: support the ata host which implements a queue depth less than 32 Kevin Hao
2014-07-06 6:28 ` [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth() Kevin Hao
@ 2014-07-06 6:28 ` Kevin Hao
1 sibling, 0 replies; 9+ messages in thread
From: Kevin Hao @ 2014-07-06 6:28 UTC (permalink / raw)
To: linux-ide; +Cc: Tejun Heo, Dan Williams
The fsl sata controller only implement a queue depth of 16. So use
the ata_host_set_queue_depth() to set the correct queue depth for
host controller. Also add a WARN_ON_ONCE() if a tag above 16 is
used.
Fixes: 8a4aeec8d2d6 ("libata/ahci: accommodate tag ordered controllers")
Cc: stable@vger.kernel.org
Signed-off-by: Kevin Hao <haokexin@gmail.com>
---
v2: Add a WARN_ON_ONCE().
drivers/ata/sata_fsl.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c
index 07bc7e4dbd04..ae55440af86d 100644
--- a/drivers/ata/sata_fsl.c
+++ b/drivers/ata/sata_fsl.c
@@ -402,6 +402,7 @@ static inline unsigned int sata_fsl_tag(unsigned int tag,
if (unlikely(tag >= SATA_FSL_QUEUE_DEPTH)) {
DPRINTK("tag %d invalid : out of range\n", tag);
+ WARN_ON_ONCE(1);
return 0;
}
@@ -1506,6 +1507,8 @@ static int sata_fsl_probe(struct platform_device *ofdev)
goto error_exit_with_cleanup;
}
+ ata_host_set_queue_depth(host, SATA_FSL_QUEUE_DEPTH);
+
/* host->iomap is not used currently */
host->private_data = host_priv;
--
1.9.3
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-06 6:28 ` [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth() Kevin Hao
@ 2014-07-07 13:49 ` Tejun Heo
2014-07-08 2:58 ` Kevin Hao
2014-07-07 18:19 ` Dan Williams
1 sibling, 1 reply; 9+ messages in thread
From: Tejun Heo @ 2014-07-07 13:49 UTC (permalink / raw)
To: Kevin Hao; +Cc: linux-ide, Dan Williams
Hello,
On Sun, Jul 06, 2014 at 02:28:40PM +0800, Kevin Hao wrote:
> +int ata_host_set_queue_depth(struct ata_host *host, unsigned int queue_depth)
Hmmm... is there a reason we're doing this separately when the same
information is available from scsi_host_template->can_queue from
ata_host_register()?
> @@ -5731,6 +5752,7 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
> mutex_init(&host->eh_mutex);
> host->dev = dev;
> host->n_ports = max_ports;
> + host->queue_depth = ATA_MAX_QUEUE;
And shouldn't this be one for !NCQ controllers?
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-06 6:28 ` [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth() Kevin Hao
2014-07-07 13:49 ` Tejun Heo
@ 2014-07-07 18:19 ` Dan Williams
2014-07-07 20:06 ` Tejun Heo
1 sibling, 1 reply; 9+ messages in thread
From: Dan Williams @ 2014-07-07 18:19 UTC (permalink / raw)
To: Kevin Hao; +Cc: IDE/ATA development list, Tejun Heo
On Sat, Jul 5, 2014 at 11:28 PM, Kevin Hao <haokexin@gmail.com> wrote:
> 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 ~ 17 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. This patch provides the function
> for libata to adjust the queue depth for a host controller.
>
> Fixes: 8a4aeec8d2d6 ("libata/ahci: accommodate tag ordered controllers")
> Cc: stable@vger.kernel.org
> Signed-off-by: Kevin Hao <haokexin@gmail.com>
> ---
> v2: Remove the changes for the ata tag helper functions.
>
> drivers/ata/libata-core.c | 29 ++++++++++++++++++++++++++---
> include/linux/libata.h | 3 +++
> 2 files changed, 29 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
> index 8f3043165048..c9c51646d8e8 100644
> --- a/drivers/ata/libata-core.c
> +++ b/drivers/ata/libata-core.c
> @@ -4728,14 +4728,14 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
> 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 = ap->host->queue_depth;
>
> /* 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; i < max_queue; i++) {
> + tag = (i + ap->last_tag + 1) % max_queue;
This change may cause the compiler to do a full divide where
previously it could optimize to power-of-2 math with the visibility of
the ATA_MAX_QUEUE constant. How about converting
ap->host->queue_depth to ap->host->queue_depth_mask? ...then this
becomes:
tag = (i + ap->last_tag + 1) & max_queue_mask
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-07 18:19 ` Dan Williams
@ 2014-07-07 20:06 ` Tejun Heo
2014-07-07 20:56 ` Dan Williams
0 siblings, 1 reply; 9+ messages in thread
From: Tejun Heo @ 2014-07-07 20:06 UTC (permalink / raw)
To: Dan Williams; +Cc: Kevin Hao, IDE/ATA development list
On Mon, Jul 07, 2014 at 11:19:25AM -0700, Dan Williams wrote:
> This change may cause the compiler to do a full divide where
> previously it could optimize to power-of-2 math with the visibility of
> the ATA_MAX_QUEUE constant. How about converting
> ap->host->queue_depth to ap->host->queue_depth_mask? ...then this
> becomes:
>
> tag = (i + ap->last_tag + 1) & max_queue_mask
Given how inefficient the test_and_set bit is, I don't think a single
moduls matters. Plus, we don't even need modulus there. We can
simply use >= max_depth.
Thanks.
--
tejun
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-07 20:06 ` Tejun Heo
@ 2014-07-07 20:56 ` Dan Williams
2014-07-08 2:41 ` Kevin Hao
0 siblings, 1 reply; 9+ messages in thread
From: Dan Williams @ 2014-07-07 20:56 UTC (permalink / raw)
To: Tejun Heo; +Cc: Kevin Hao, IDE/ATA development list
On Mon, Jul 7, 2014 at 1:06 PM, Tejun Heo <tj@kernel.org> wrote:
> On Mon, Jul 07, 2014 at 11:19:25AM -0700, Dan Williams wrote:
>> This change may cause the compiler to do a full divide where
>> previously it could optimize to power-of-2 math with the visibility of
>> the ATA_MAX_QUEUE constant. How about converting
>> ap->host->queue_depth to ap->host->queue_depth_mask? ...then this
>> becomes:
>>
>> tag = (i + ap->last_tag + 1) & max_queue_mask
>
> Given how inefficient the test_and_set bit is, I don't think a single
> moduls matters. Plus, we don't even need modulus there. We can
> simply use >= max_depth.
True, sounds good.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-07 20:56 ` Dan Williams
@ 2014-07-08 2:41 ` Kevin Hao
0 siblings, 0 replies; 9+ messages in thread
From: Kevin Hao @ 2014-07-08 2:41 UTC (permalink / raw)
To: Dan Williams; +Cc: Tejun Heo, IDE/ATA development list
[-- Attachment #1: Type: text/plain, Size: 437 bytes --]
On Mon, Jul 07, 2014 at 01:56:59PM -0700, Dan Williams wrote:
> On Mon, Jul 7, 2014 at 1:06 PM, Tejun Heo <tj@kernel.org> wrote:
> > On Mon, Jul 07, 2014 at 11:19:25AM -0700, Dan Williams wrote:
> > Given how inefficient the test_and_set bit is, I don't think a single
> > moduls matters. Plus, we don't even need modulus there. We can
> > simply use >= max_depth.
>
> True, sounds good.
OK, will change.
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth()
2014-07-07 13:49 ` Tejun Heo
@ 2014-07-08 2:58 ` Kevin Hao
0 siblings, 0 replies; 9+ messages in thread
From: Kevin Hao @ 2014-07-08 2:58 UTC (permalink / raw)
To: Tejun Heo; +Cc: linux-ide, Dan Williams
[-- Attachment #1: Type: text/plain, Size: 1593 bytes --]
On Mon, Jul 07, 2014 at 09:49:45AM -0400, Tejun Heo wrote:
> Hello,
>
> On Sun, Jul 06, 2014 at 02:28:40PM +0800, Kevin Hao wrote:
> > +int ata_host_set_queue_depth(struct ata_host *host, unsigned int queue_depth)
>
> Hmmm... is there a reason we're doing this separately when the same
> information is available from scsi_host_template->can_queue from
> ata_host_register()?
This was my first thought. But given that scsi_host_template are the parameters
passed to the scsi layer, it seems a bit weird to set the ata_host based a
value in that. Anyway if we decide to use can_queue, how about directly use
it in ata_qc_new(), just like the following codes?
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8f3043165048..4792fea79acf 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4728,14 +4728,17 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
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;
+ WARN_ON_ONCE(max_queue > ATA_MAX_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)
Thanks,
Kevin
[-- Attachment #2: Type: application/pgp-signature, Size: 473 bytes --]
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2014-07-08 2:58 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-06 6:28 [PATCH v2 0/2] libata: support the ata host which implements a queue depth less than 32 Kevin Hao
2014-07-06 6:28 ` [PATCH v2 1/2] libata: introduce ata_host_set_queue_depth() Kevin Hao
2014-07-07 13:49 ` Tejun Heo
2014-07-08 2:58 ` Kevin Hao
2014-07-07 18:19 ` Dan Williams
2014-07-07 20:06 ` Tejun Heo
2014-07-07 20:56 ` Dan Williams
2014-07-08 2:41 ` Kevin Hao
2014-07-06 6:28 ` [PATCH v2 2/2] sata_fsl: set the correct queue depth for the host controller Kevin Hao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox