Linux ATA/IDE development
 help / color / mirror / Atom feed
* [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