* [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
* 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-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
* 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
* [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
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