Re: Kernel 4.1-rc1 build fails on Sam460ex amcc 460ex powerpc Canyonlands
On Mon, 2015-04-27 at 23:49 -0400, Tejun Heo wrote: > On Tue, Apr 28, 2015 at 11:12:25AM +1000, Michael Ellerman wrote: > > On Mon, 2015-04-27 at 06:59 -0400, Julian Margetson wrote: > > > Kernel 4.1-rc1 build fails on Sam460ex amcc 460ex powerpc Canyonlands > > > with > > > CONFIG_SATA_DWC=y > > > > > > sata_dwc_460ex.c:(.text+0xa165c): undefined reference to `dw_dma_remove' > > > drivers/built-in.o: In function `sata_dwc_probe': > > > sata_dwc_460ex.c:(.text+0xa1900): undefined reference to `dw_dma_probe' > > > sata_dwc_460ex.c:(.text+0xa1954): undefined reference to `dw_dma_remove' > > > make: *** [vmlinux] Error 1 > > > > Looks like it was caused by: > > > > commit 8b3444852a2b58129ee68a8dd69fef81ceb902a1 > > Author: Andy Shevchenko > > Date: Tue Mar 3 22:41:21 2015 +0200 > > > > sata_dwc_460ex: move to generic DMA driver > > Oops, Andy? > Sorry for late answer. It requires CONFIG_DW_DMAC=y as well. I don't know the details of PPC configuration, we might add this to configuration. -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/1] ata: select DW_DMAC in case of SATA_DWC
Since sata_dwc_460ex.c was moved to generic DMA driver we have to ensure that user can still compile it. Fixes: 8b3444852a2b (sata_dwc_460ex: move to generic DMA driver) Signed-off-by: Andy Shevchenko --- drivers/ata/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ee5209f..9dca4b9 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -270,6 +270,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" depends on 460EX + select DW_DMAC help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. -- 2.1.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 00/12] dma: various minor clean ups for slave drivers
Here is a set of small independent patches that clean up or fix minor things across DMA slave drivers. Andy Shevchenko (12): imx-sdma: remove useless variable mxs-dma: remove useless variable edma: no need to assign residue to 0 explicitly ep93xx_dma: remove useless use of lock fsldma: remove useless use of lock mmp_pdma: remove useless use of lock mpc512x_dma: remove useless use of lock pch_dma: remove useless use of lock tegra20-apb-dma: remove useless use of lock ipu_idmac: re-use dma_cookie_status() mmp_tdma: set cookies as well when asked for tx status txx9dmac: return DMA_SUCCESS immediately from device_tx_status() drivers/dma/edma.c| 2 -- drivers/dma/ep93xx_dma.c | 10 +- drivers/dma/fsldma.c | 10 +- drivers/dma/imx-sdma.c| 9 +++-- drivers/dma/ipu/ipu_idmac.c | 5 + drivers/dma/mmp_pdma.c| 10 +- drivers/dma/mmp_tdma.c| 3 ++- drivers/dma/mpc512x_dma.c | 10 +- drivers/dma/mxs-dma.c | 4 +--- drivers/dma/pch_dma.c | 9 + drivers/dma/tegra20-apb-dma.c | 8 +++- drivers/dma/txx9dmac.c| 13 ++--- 12 files changed, 21 insertions(+), 72 deletions(-) -- 1.8.2.rc0.22.gb3600c3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 05/12] fsldma: remove useless use of lock
Accordingly to dma_cookie_status() description locking is not required. Signed-off-by: Andy Shevchenko Cc: Li Yang Cc: Zhang Wei Cc: linuxppc-dev@lists.ozlabs.org --- drivers/dma/fsldma.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 49e8fbd..b3f3e90 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -979,15 +979,7 @@ static enum dma_status fsl_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, struct dma_tx_state *txstate) { - struct fsldma_chan *chan = to_fsl_chan(dchan); - enum dma_status ret; - unsigned long flags; - - spin_lock_irqsave(&chan->desc_lock, flags); - ret = dma_cookie_status(dchan, cookie, txstate); - spin_unlock_irqrestore(&chan->desc_lock, flags); - - return ret; + return dma_cookie_status(dchan, cookie, txstate); } /**/ -- 1.8.2.rc0.22.gb3600c3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 00/12] dma: various minor clean ups for slave drivers
On Thu, May 30, 2013 at 8:47 PM, Vinod Koul wrote: > On Mon, May 27, 2013 at 03:14:30PM +0300, Andy Shevchenko wrote: >> Here is a set of small independent patches that clean up or fix minor things >> across DMA slave drivers. > The series looks fine. I am going to wait a day more and apply, pls speak up > if > you disagree and ack if you agree I'm not in hurry with it. Please, take your time and do whatever it requires. Thank you! -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 00/12] dma: various minor clean ups for slave drivers
On Thu, 2013-05-30 at 23:17 +0530, Vinod Koul wrote: > On Mon, May 27, 2013 at 03:14:30PM +0300, Andy Shevchenko wrote: > > Here is a set of small independent patches that clean up or fix minor things > > across DMA slave drivers. > The series looks fine. I am going to wait a day more and apply, pls speak up > if > you disagree and ack if you agree Kindly remind about this series. > > -- > ~Vinod > > > > Andy Shevchenko (12): > > imx-sdma: remove useless variable > > mxs-dma: remove useless variable > > edma: no need to assign residue to 0 explicitly > > ep93xx_dma: remove useless use of lock > > fsldma: remove useless use of lock > > mmp_pdma: remove useless use of lock > > mpc512x_dma: remove useless use of lock > > pch_dma: remove useless use of lock > > tegra20-apb-dma: remove useless use of lock > > ipu_idmac: re-use dma_cookie_status() > > mmp_tdma: set cookies as well when asked for tx status > > txx9dmac: return DMA_SUCCESS immediately from device_tx_status() > > > > drivers/dma/edma.c| 2 -- > > drivers/dma/ep93xx_dma.c | 10 +- > > drivers/dma/fsldma.c | 10 +- > > drivers/dma/imx-sdma.c| 9 +++-- > > drivers/dma/ipu/ipu_idmac.c | 5 + > > drivers/dma/mmp_pdma.c| 10 +- > > drivers/dma/mmp_tdma.c| 3 ++- > > drivers/dma/mpc512x_dma.c | 10 +- > > drivers/dma/mxs-dma.c | 4 +--- > > drivers/dma/pch_dma.c | 9 + > > drivers/dma/tegra20-apb-dma.c | 8 +++- > > drivers/dma/txx9dmac.c| 13 ++--- > > 12 files changed, 21 insertions(+), 72 deletions(-) > > > > -- > > 1.8.2.rc0.22.gb3600c3 > > > -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 00/12] dma: various minor clean ups for slave drivers
On Mon, 2013-07-15 at 15:07 +0530, Vinod Koul wrote: > On Thu, May 30, 2013 at 09:32:19PM +0300, Andy Shevchenko wrote: > > >> Here is a set of small independent patches that clean up or fix minor > > >> things > > >> across DMA slave drivers. > > Applied thanks Thank you. You were faster than me, I was just about to send rebased version. -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 2/5] powerpc/pseries: fix a potential memory leak
In case we have a full node name like /foo/bar and /foo is not found the parent_path left unfreed. So, free a memory before return to a caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 1cbd896..2f363e3 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -15,7 +15,7 @@ */ struct device_node *pseries_of_derive_parent(const char *path) { - struct device_node *parent = NULL; + struct device_node *parent; char *parent_path = "/"; size_t parent_path_len = strrchr(path, '/') - path + 1; @@ -30,9 +30,7 @@ struct device_node *pseries_of_derive_parent(const char *path) strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); if (strcmp(parent_path, "/")) kfree(parent_path); - return parent; + return parent ? parent : ERR_PTR(-EINVAL); } -- 2.4.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 1/5] powerpc/pseries: extract of_helpers module
Extract a new module to share the code between other modules. There is no functional change. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/of_helpers.c | 38 + arch/powerpc/platforms/pseries/of_helpers.h | 8 ++ arch/powerpc/platforms/pseries/reconfig.c | 34 ++ 4 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 0348079..2e857c2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,6 +2,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) ccflags-$(CONFIG_PPC_PSERIES_DEBUG)+= -DDEBUG obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + of_helpers.o \ setup.o iommu.o event_sources.o ras.o \ firmware.o power.o dlpar.o mobility.o rng.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c new file mode 100644 index 000..1cbd896 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "of_helpers.h" + +/** + * pseries_of_derive_parent - basically like dirname(1) + * @path: the full_name of a node to be added to the tree + * + * Returns the node which should be the parent of the node + * described by path. E.g., for path = "/foo/bar", returns + * the node with full_name = "/foo". + */ +struct device_node *pseries_of_derive_parent(const char *path) +{ + struct device_node *parent = NULL; + char *parent_path = "/"; + size_t parent_path_len = strrchr(path, '/') - path + 1; + + /* reject if path is "/" */ + if (!strcmp(path, "/")) + return ERR_PTR(-EINVAL); + + if (strrchr(path, '/') != path) { + parent_path = kmalloc(parent_path_len, GFP_KERNEL); + if (!parent_path) + return ERR_PTR(-ENOMEM); + strlcpy(parent_path, path, parent_path_len); + } + parent = of_find_node_by_path(parent_path); + if (!parent) + return ERR_PTR(-EINVAL); + if (strcmp(parent_path, "/")) + kfree(parent_path); + return parent; +} diff --git a/arch/powerpc/platforms/pseries/of_helpers.h b/arch/powerpc/platforms/pseries/of_helpers.h new file mode 100644 index 000..bb83d39 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.h @@ -0,0 +1,8 @@ +#ifndef _PSERIES_OF_HELPERS_H +#define _PSERIES_OF_HELPERS_H + +#include + +struct device_node *pseries_of_derive_parent(const char *path); + +#endif /* _PSERIES_OF_HELPERS_H */ diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 0f31952..7c7fcc0 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -22,37 +22,7 @@ #include #include -/** - * derive_parent - basically like dirname(1) - * @path: the full_name of a node to be added to the tree - * - * Returns the node which should be the parent of the node - * described by path. E.g., for path = "/foo/bar", returns - * the node with full_name = "/foo". - */ -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent = NULL; - char *parent_path = "/"; - size_t parent_path_len = strrchr(path, '/') - path + 1; - - /* reject if path is "/" */ - if (!strcmp(path, "/")) - return ERR_PTR(-EINVAL); - - if (strrchr(path, '/') != path) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); - } - parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); - if (strcmp(parent_path, "/")) - kfree(parent_path); - return parent; -} +#include "of_helpers.h" static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { @@ -71,7 +41,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist of_node_set_flag(np, OF_DYNAMIC); of_node_init(np); - np->parent = derive_parent(path); + np->parent = pseries_of_derive_parent(path); if (IS_ERR(np->parent)) { err = PTR_ERR(np
[PATCH 5/5] powerpc/pseries: re-use code from of_helpers module
The derive_parent() has similar semantics to what we have in newly introduced of_helpers module. The replacement reduces code base and propagates the actual error code to the caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/dlpar.c | 31 +-- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 47d9cebe..b7f243c 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -18,6 +18,8 @@ #include #include #include + +#include "of_helpers.h" #include "offline_states.h" #include "pseries.h" @@ -244,36 +246,13 @@ cc_error: return first_dn; } -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent; - char *last_slash; - - last_slash = strrchr(path, '/'); - if (last_slash == path) { - parent = of_find_node_by_path("/"); - } else { - char *parent_path; - int parent_path_len = last_slash - path + 1; - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return NULL; - - strlcpy(parent_path, path, parent_path_len); - parent = of_find_node_by_path(parent_path); - kfree(parent_path); - } - - return parent; -} - int dlpar_attach_node(struct device_node *dn) { int rc; - dn->parent = derive_parent(dn->full_name); - if (!dn->parent) - return -ENOMEM; + dn->parent = pseries_of_derive_parent(dn->full_name); + if (IS_ERR(dn->parent)) + return PTR_ERR(dn_parent); rc = of_attach_node(dn); if (rc) { -- 2.4.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 4/5] powerpc/pseries: replace kmalloc + strlcpy
The helper kstrndup() will do the same in one line. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 027446a..afa 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -24,10 +24,9 @@ struct device_node *pseries_of_derive_parent(const char *path) return ERR_PTR(-EINVAL); if (parent_path_len > 1) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); + parent_path = kstrndup(path, parent_path_len, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); if (strcmp(parent_path, "/")) -- 2.4.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH 3/5] powerpc/pseries: don't call strrchr() twice
There is no need to call strrchr() second time. We already know that in that case parent_path_len either 1 ("/foo") or bigger ("/foo/bar"). Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 2f363e3..027446a 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -23,7 +23,7 @@ struct device_node *pseries_of_derive_parent(const char *path) if (!strcmp(path, "/")) return ERR_PTR(-EINVAL); - if (strrchr(path, '/') != path) { + if (parent_path_len > 1) { parent_path = kmalloc(parent_path_len, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); -- 2.4.6 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/5] powerpc/pseries: extract of_helpers module
On Wed, 2015-08-05 at 00:20 -0500, Segher Boessenkool wrote: > Hi Andy, > > On Tue, Aug 04, 2015 at 05:36:45PM +0300, Andy Shevchenko wrote: > > +struct device_node *pseries_of_derive_parent(const char *path) > > +{ > > + struct device_node *parent = NULL; > > + char *parent_path = "/"; > > + size_t parent_path_len = strrchr(path, '/') - path + 1; > > + > > + /* reject if path is "/" */ > > + if (!strcmp(path, "/")) > > + return ERR_PTR(-EINVAL); > > + > > + if (strrchr(path, '/') != path) { > > + parent_path = kmalloc(parent_path_len, > > GFP_KERNEL); > > If path doesn't contain any slash this will do interesting things; > you might want to fix that too while you're at it :-) No problem, though it is in the original code. I would do as a separate patch on top of the series. Will be okay for you? > > > Segher -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 5/5] powerpc/pseries: re-use code from of_helpers module
The derive_parent() has similar semantics to what we have in newly introduced of_helpers module. The replacement reduces code base and propagates the actual error code to the caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/dlpar.c | 31 +-- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 47d9cebe..b7f243c 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -18,6 +18,8 @@ #include #include #include + +#include "of_helpers.h" #include "offline_states.h" #include "pseries.h" @@ -244,36 +246,13 @@ cc_error: return first_dn; } -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent; - char *last_slash; - - last_slash = strrchr(path, '/'); - if (last_slash == path) { - parent = of_find_node_by_path("/"); - } else { - char *parent_path; - int parent_path_len = last_slash - path + 1; - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return NULL; - - strlcpy(parent_path, path, parent_path_len); - parent = of_find_node_by_path(parent_path); - kfree(parent_path); - } - - return parent; -} - int dlpar_attach_node(struct device_node *dn) { int rc; - dn->parent = derive_parent(dn->full_name); - if (!dn->parent) - return -ENOMEM; + dn->parent = pseries_of_derive_parent(dn->full_name); + if (IS_ERR(dn->parent)) + return PTR_ERR(dn_parent); rc = of_attach_node(dn); if (rc) { -- 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 1/5] powerpc/pseries: extract of_helpers module
Extract a new module to share the code between other modules. There is no functional change. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/of_helpers.c | 38 + arch/powerpc/platforms/pseries/of_helpers.h | 8 ++ arch/powerpc/platforms/pseries/reconfig.c | 34 ++ 4 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 0348079..2e857c2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,6 +2,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) ccflags-$(CONFIG_PPC_PSERIES_DEBUG)+= -DDEBUG obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + of_helpers.o \ setup.o iommu.o event_sources.o ras.o \ firmware.o power.o dlpar.o mobility.o rng.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c new file mode 100644 index 000..1cbd896 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "of_helpers.h" + +/** + * pseries_of_derive_parent - basically like dirname(1) + * @path: the full_name of a node to be added to the tree + * + * Returns the node which should be the parent of the node + * described by path. E.g., for path = "/foo/bar", returns + * the node with full_name = "/foo". + */ +struct device_node *pseries_of_derive_parent(const char *path) +{ + struct device_node *parent = NULL; + char *parent_path = "/"; + size_t parent_path_len = strrchr(path, '/') - path + 1; + + /* reject if path is "/" */ + if (!strcmp(path, "/")) + return ERR_PTR(-EINVAL); + + if (strrchr(path, '/') != path) { + parent_path = kmalloc(parent_path_len, GFP_KERNEL); + if (!parent_path) + return ERR_PTR(-ENOMEM); + strlcpy(parent_path, path, parent_path_len); + } + parent = of_find_node_by_path(parent_path); + if (!parent) + return ERR_PTR(-EINVAL); + if (strcmp(parent_path, "/")) + kfree(parent_path); + return parent; +} diff --git a/arch/powerpc/platforms/pseries/of_helpers.h b/arch/powerpc/platforms/pseries/of_helpers.h new file mode 100644 index 000..bb83d39 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.h @@ -0,0 +1,8 @@ +#ifndef _PSERIES_OF_HELPERS_H +#define _PSERIES_OF_HELPERS_H + +#include + +struct device_node *pseries_of_derive_parent(const char *path); + +#endif /* _PSERIES_OF_HELPERS_H */ diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 0f31952..7c7fcc0 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -22,37 +22,7 @@ #include #include -/** - * derive_parent - basically like dirname(1) - * @path: the full_name of a node to be added to the tree - * - * Returns the node which should be the parent of the node - * described by path. E.g., for path = "/foo/bar", returns - * the node with full_name = "/foo". - */ -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent = NULL; - char *parent_path = "/"; - size_t parent_path_len = strrchr(path, '/') - path + 1; - - /* reject if path is "/" */ - if (!strcmp(path, "/")) - return ERR_PTR(-EINVAL); - - if (strrchr(path, '/') != path) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); - } - parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); - if (strcmp(parent_path, "/")) - kfree(parent_path); - return parent; -} +#include "of_helpers.h" static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { @@ -71,7 +41,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist of_node_set_flag(np, OF_DYNAMIC); of_node_init(np); - np->parent = derive_parent(path); + np->parent = pseries_of_derive_parent(path); if (IS_ERR(np->parent)) { err = PTR_ERR(np
[PATCH v2 2/5] powerpc/pseries: fix a potential memory leak
In case we have a full node name like /foo/bar and /foo is not found the parent_path left unfreed. So, free a memory before return to a caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 1cbd896..2f363e3 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -15,7 +15,7 @@ */ struct device_node *pseries_of_derive_parent(const char *path) { - struct device_node *parent = NULL; + struct device_node *parent; char *parent_path = "/"; size_t parent_path_len = strrchr(path, '/') - path + 1; @@ -30,9 +30,7 @@ struct device_node *pseries_of_derive_parent(const char *path) strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); if (strcmp(parent_path, "/")) kfree(parent_path); - return parent; + return parent ? parent : ERR_PTR(-EINVAL); } -- 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 3/5] powerpc/pseries: replace kmalloc + strlcpy
The helper kstrndup() will do the same in one line. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 2f363e3..8c6b05a 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -24,10 +24,9 @@ struct device_node *pseries_of_derive_parent(const char *path) return ERR_PTR(-EINVAL); if (strrchr(path, '/') != path) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); + parent_path = kstrndup(path, parent_path_len, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); if (strcmp(parent_path, "/")) -- 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 4/5] powerpc/pseries: handle nodes without '/'
In case we have node without '/' strrchr() returns NULL which might lead to crash. Replace strrchr() by kbasename() and modify condition to avoid such behaviour. Suggested-by: Segher Boessenkool Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 8c6b05a..4417afe 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -17,14 +17,14 @@ struct device_node *pseries_of_derive_parent(const char *path) { struct device_node *parent; char *parent_path = "/"; - size_t parent_path_len = strrchr(path, '/') - path + 1; + const char *tail = kbasename(path); /* reject if path is "/" */ if (!strcmp(path, "/")) return ERR_PTR(-EINVAL); - if (strrchr(path, '/') != path) { - parent_path = kstrndup(path, parent_path_len, GFP_KERNEL); + if (tail > path + 1) { + parent_path = kstrndup(path, tail - path, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); } -- 2.5.0 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH] macintosh: use %*ph to print small buffers
Signed-off-by: Andy Shevchenko --- drivers/macintosh/smu.c | 6 +- drivers/macintosh/via-pmu.c | 5 +++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 9c6b964..b3b2d36 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -120,11 +120,7 @@ static void smu_start_cmd(void) DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, cmd->data_len); - DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", - ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], - ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], - ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); + DPRINTK("SMU: data buffer: %8ph\n", cmd->data_buf); /* Fill the SMU command buffer */ smu->cmd_buf->cmd = cmd->cmd; diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index c31fbab..283e1b5 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -750,8 +750,9 @@ done_battery_state_smart(struct adb_request* req) voltage = (req->reply[8] << 8) | req->reply[9]; break; default: - printk(KERN_WARNING "pmu.c : unrecognized battery info, len: %d, %02x %02x %02x %02x\n", - req->reply_len, req->reply[0], req->reply[1], req->reply[2], req->reply[3]); + pr_warn("pmu.c: unrecognized battery info, " + "len: %d, %4ph\n", req->reply_len, + req->reply); break; } } -- 1.8.2.rc0.22.gb3600c3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH RFC v8 5/5] dma: mpc512x: register for device tree channel lookup
On Mon, 2014-02-24 at 15:09 +0400, Alexander Popov wrote: > From: Gerhard Sittig > > register the controller for device tree based lookup of DMA channels > (non-fatal for backwards compatibility with older device trees) and > provide the '#dma-cells' property in the shared mpc5121.dtsi file > > Signed-off-by: Gerhard Sittig > [ a13xp0p0...@gmail.com: resolve little patch conflict and put > MPC512x DMA controller bindings document to a separate patch ] > --- > arch/powerpc/boot/dts/mpc5121.dtsi | 1 + > drivers/dma/mpc512x_dma.c | 21 ++--- > 2 files changed, 19 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi > b/arch/powerpc/boot/dts/mpc5121.dtsi > index 2c0e155..7f9d14f 100644 > --- a/arch/powerpc/boot/dts/mpc5121.dtsi > +++ b/arch/powerpc/boot/dts/mpc5121.dtsi > @@ -498,6 +498,7 @@ > compatible = "fsl,mpc5121-dma"; > reg = <0x14000 0x1800>; > interrupts = <65 0x8>; > + #dma-cells = <1>; > }; > }; > > diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c > index 8f504cb..d9f8740 100644 > --- a/drivers/dma/mpc512x_dma.c > +++ b/drivers/dma/mpc512x_dma.c > @@ -52,6 +52,7 @@ > #include > #include > #include > +#include > #include > > #include > @@ -1018,11 +1019,23 @@ static int mpc_dma_probe(struct platform_device *op) > /* Register DMA engine */ > dev_set_drvdata(dev, mdma); > retval = dma_async_device_register(dma); > - if (retval) { > - devm_free_irq(dev, mdma->irq, mdma); > - irq_dispose_mapping(mdma->irq); > + if (retval) > + goto out_irq; > + > + /* register with OF helpers for DMA lookups (nonfatal) */ > + if (dev->of_node) { > + retval = of_dma_controller_register(dev->of_node, > + of_dma_xlate_by_chan_id, > + mdma); > + if (retval) > + dev_warn(dev, "could not register for OF lookup\n"); > } > > + return 0; > + > +out_irq: > + devm_free_irq(dev, mdma->irq, mdma); Something wrong either with devm_request_irq() or you don't need to call devm_free_irq() explicitly. Once we already try to discuss this earlier in this mailing list with Lars-Peter(?), though there were no solution how to keep devm_*_irq usability. > + irq_dispose_mapping(mdma->irq); > return retval; > } > > @@ -1031,6 +1044,8 @@ static int mpc_dma_remove(struct platform_device *op) > struct device *dev = &op->dev; > struct mpc_dma *mdma = dev_get_drvdata(dev); > > + if (dev->of_node) > + of_dma_controller_free(dev->of_node); > dma_async_device_unregister(&mdma->dma); > devm_free_irq(dev, mdma->irq, mdma); > irq_dispose_mapping(mdma->irq); -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH RFC v8 2/5] dma: mpc512x: add support for peripheral transfers
spin_unlock_irqrestore(&mchan->lock, iflags); > + } > + > + return &mdesc->desc; > + > +err_prep: > + /* Put the descriptor back */ > + spin_lock_irqsave(&mchan->lock, iflags); > + list_add_tail(&mdesc->node, &mchan->free); > + spin_unlock_irqrestore(&mchan->lock, iflags); > + > + return NULL; > +} > + > +static int mpc_dma_device_control(struct dma_chan *chan, enum dma_ctrl_cmd > cmd, > + unsigned long arg) > +{ > + struct mpc_dma_chan *mchan; > + struct mpc_dma *mdma; > + struct dma_slave_config *cfg; > + unsigned long flags; > + > + mchan = dma_chan_to_mpc_dma_chan(chan); > + switch (cmd) { > + case DMA_TERMINATE_ALL: > + /* disable channel requests */ > + mdma = dma_chan_to_mpc_dma(chan); > + > + spin_lock_irqsave(&mchan->lock, flags); > + > + out_8(&mdma->regs->dmacerq, chan->chan_id); > + list_splice_tail_init(&mchan->prepared, &mchan->free); > + list_splice_tail_init(&mchan->queued, &mchan->free); > + list_splice_tail_init(&mchan->active, &mchan->free); > + > + spin_unlock_irqrestore(&mchan->lock, flags); > + > + return 0; > + case DMA_SLAVE_CONFIG: > + /* Constraints: > + * - only transfers between a peripheral device and > + * memory are supported; > + * - minimal transfer chunk is 4 bytes and consequently > + * source and destination addresses must be 4-byte aligned > + * and transfer size must be aligned on (4 * maxburst) > + * boundary; > + * - during the transfer RAM address is being incremented by > + * the size of minimal transfer chunk; > + * - peripheral port's address is constant during the transfer. > + */ > + > + cfg = (void *)arg; > + > + if (cfg->direction != DMA_DEV_TO_MEM && > + cfg->direction != DMA_MEM_TO_DEV) > + return -EINVAL; is_slave_direction() > + > + if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES && > + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > + return -EINVAL; > + > + spin_lock_irqsave(&mchan->lock, flags); > + > + if (cfg->direction == DMA_DEV_TO_MEM) { > + mchan->per_paddr = cfg->src_addr; > + mchan->tcd_nunits = cfg->src_maxburst; > + } else { > + mchan->per_paddr = cfg->dst_addr; > + mchan->tcd_nunits = cfg->dst_maxburst; > + } > + > + if (!IS_ALIGNED(mchan->per_paddr, 4)) { > + spin_unlock_irqrestore(&mchan->lock, flags); > + return -EINVAL; > + } > + > + if (mchan->tcd_nunits == 0) > + mchan->tcd_nunits = 1; /* apply default */ > + > + spin_unlock_irqrestore(&mchan->lock, flags); > + > + return 0; > + default: > + return -ENOSYS; Use break here. > + } > + > + return -EINVAL; > +} > + > static int mpc_dma_probe(struct platform_device *op) > { > struct device_node *dn = op->dev.of_node; > @@ -727,9 +949,12 @@ static int mpc_dma_probe(struct platform_device *op) > dma->device_issue_pending = mpc_dma_issue_pending; > dma->device_tx_status = mpc_dma_tx_status; > dma->device_prep_dma_memcpy = mpc_dma_prep_memcpy; > + dma->device_prep_slave_sg = mpc_dma_prep_slave_sg; > + dma->device_control = mpc_dma_device_control; > > INIT_LIST_HEAD(&dma->channels); > dma_cap_set(DMA_MEMCPY, dma->cap_mask); > + dma_cap_set(DMA_SLAVE, dma->cap_mask); > > for (i = 0; i < dma->chancnt; i++) { > mchan = &mdma->channels[i]; -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH RFC v9 2/6] dma: mpc512x: add support for peripheral transfers
On Wed, 2014-03-12 at 15:47 +0400, Alexander Popov wrote: > Introduce support for slave s/g transfer preparation and the associated > device control callback in the MPC512x DMA controller driver, which adds > support for data transfers between memory and peripheral I/O to the > previously supported mem-to-mem transfers. > --- a/drivers/dma/mpc512x_dma.c > +++ b/drivers/dma/mpc512x_dma.c > @@ -2,6 +2,7 @@ > * Copyright (C) Freescale Semicondutor, Inc. 2007, 2008. > * Copyright (C) Semihalf 2009 > * Copyright (C) Ilya Yanok, Emcraft Systems 2010 > + * Copyright (C) Alexander Popov, Promcontroller 2013 2014? [] > +static int mpc_dma_device_control(struct dma_chan *chan, enum dma_ctrl_cmd > cmd, > + unsigned long arg) > +{ > + struct mpc_dma_chan *mchan; > + struct mpc_dma *mdma; > + struct dma_slave_config *cfg; > + unsigned long flags; > + > + mchan = dma_chan_to_mpc_dma_chan(chan); > + switch (cmd) { > + case DMA_TERMINATE_ALL: > + /* Disable channel requests */ > + mdma = dma_chan_to_mpc_dma(chan); > + > + spin_lock_irqsave(&mchan->lock, flags); > + > + out_8(&mdma->regs->dmacerq, chan->chan_id); > + list_splice_tail_init(&mchan->prepared, &mchan->free); > + list_splice_tail_init(&mchan->queued, &mchan->free); > + list_splice_tail_init(&mchan->active, &mchan->free); > + > + spin_unlock_irqrestore(&mchan->lock, flags); > + > + return 0; > + case DMA_SLAVE_CONFIG: > + /* Constraints: > + * - only transfers between a peripheral device and > + * memory are supported; > + * - minimal transfer chunk is 4 bytes and consequently > + * source and destination addresses must be 4-byte aligned > + * and transfer size must be aligned on (4 * maxburst) > + * boundary; > + * - during the transfer RAM address is being incremented by > + * the size of minimal transfer chunk; > + * - peripheral port's address is constant during the transfer. > + */ > + > + cfg = (void *)arg; > + > + if (!is_slave_direction(cfg->direction)) > + return -EINVAL; As far as I understand the intention you have not to use direction field in the dma_slave_config. It will be removed once. > + > + if (cfg->src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES && > + cfg->dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES) > + return -EINVAL; > + > + spin_lock_irqsave(&mchan->lock, flags); > + > + if (cfg->direction == DMA_DEV_TO_MEM) { > + mchan->per_paddr = cfg->src_addr; > + mchan->tcd_nunits = cfg->src_maxburst; > + } else { > + mchan->per_paddr = cfg->dst_addr; > + mchan->tcd_nunits = cfg->dst_maxburst; > + } Ditto. -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH RFC v9 3/6] dma: mpc512x: replace devm_request_irq() with request_irq()
On Wed, 2014-03-12 at 15:47 +0400, Alexander Popov wrote: > Replace devm_request_irq() with request_irq() since there is no need > to use it because the original code always frees IRQ manually with > devm_free_irq(). Replace devm_free_irq() with free_irq() accordingly. > > Signed-off-by: Alexander Popov > --- > drivers/dma/mpc512x_dma.c | 11 +-- > 1 file changed, 5 insertions(+), 6 deletions(-) > > diff --git a/drivers/dma/mpc512x_dma.c b/drivers/dma/mpc512x_dma.c > index b1e430c..ff7f678 100644 > --- a/drivers/dma/mpc512x_dma.c > +++ b/drivers/dma/mpc512x_dma.c > @@ -921,16 +921,15 @@ static int mpc_dma_probe(struct platform_device *op) > mdma->tcd = (struct mpc_dma_tcd *)((u8 *)(mdma->regs) > + MPC_DMA_TCD_OFFSET); > > - retval = devm_request_irq(dev, mdma->irq, &mpc_dma_irq, 0, DRV_NAME, > - mdma); > + retval = request_irq(mdma->irq, &mpc_dma_irq, 0, DRV_NAME, mdma); > if (retval) { > dev_err(dev, "Error requesting IRQ!\n"); > return -EINVAL; > } > > if (mdma->is_mpc8308) { > - retval = devm_request_irq(dev, mdma->irq2, &mpc_dma_irq, 0, > - DRV_NAME, mdma); > + retval = request_irq(mdma->irq2, &mpc_dma_irq, 0, > + DRV_NAME, mdma); > if (retval) { > dev_err(dev, "Error requesting IRQ2!\n"); + free_irq(IRQ1) here and may be in other places. > return -EINVAL; > @@ -1020,7 +1019,7 @@ static int mpc_dma_probe(struct platform_device *op) > dev_set_drvdata(dev, mdma); > retval = dma_async_device_register(dma); > if (retval) { > - devm_free_irq(dev, mdma->irq, mdma); > + free_irq(mdma->irq, mdma); > irq_dispose_mapping(mdma->irq); > } > > @@ -1033,7 +1032,7 @@ static int mpc_dma_remove(struct platform_device *op) > struct mpc_dma *mdma = dev_get_drvdata(dev); > > dma_async_device_unregister(&mdma->dma); > - devm_free_irq(dev, mdma->irq, mdma); > + free_irq(mdma->irq, mdma); > irq_dispose_mapping(mdma->irq); > > return 0; -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v3 4/8] DMA: Freescale: add fsl_dma_free_descriptor() to reduce code duplication
On Thu, 2014-04-10 at 15:10 +0800, hongbo.zh...@freescale.com wrote: > From: Hongbo Zhang > > There are several places where descriptors are freed using identical code. > This patch puts this code into a function to reduce code duplication. > > Signed-off-by: Hongbo Zhang > Signed-off-by: Qiang Liu > --- > drivers/dma/fsldma.c | 30 ++ > 1 file changed, 18 insertions(+), 12 deletions(-) > > diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c > index b71cc04..b5a0ffa 100644 > --- a/drivers/dma/fsldma.c > +++ b/drivers/dma/fsldma.c > @@ -418,6 +418,19 @@ static dma_cookie_t fsl_dma_tx_submit(struct > dma_async_tx_descriptor *tx) > } > > /** > + * fsl_dma_free_descriptor - Free descriptor from channel's DMA pool. > + * @chan : Freescale DMA channel > + * @desc: descriptor to be freed > + */ > +static void fsl_dma_free_descriptor(struct fsldma_chan *chan, > + struct fsl_desc_sw *desc) > +{ > + list_del(&desc->node); > + chan_dbg(chan, "LD %p free\n", desc); > + dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); > +} > + > +/** > * fsl_dma_alloc_descriptor - Allocate descriptor from channel's DMA pool. > * @chan : Freescale DMA channel > * > @@ -489,11 +502,8 @@ static void fsldma_free_desc_list(struct fsldma_chan > *chan, > { > struct fsl_desc_sw *desc, *_desc; > > - list_for_each_entry_safe(desc, _desc, list, node) { > - list_del(&desc->node); > - chan_dbg(chan, "LD %p free\n", desc); > - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); > - } > + list_for_each_entry_safe(desc, _desc, list, node) > + fsl_dma_free_descriptor(chan, desc); > } > > static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan, > @@ -501,11 +511,8 @@ static void fsldma_free_desc_list_reverse(struct > fsldma_chan *chan, > { > struct fsl_desc_sw *desc, *_desc; > > - list_for_each_entry_safe_reverse(desc, _desc, list, node) { > - list_del(&desc->node); > - chan_dbg(chan, "LD %p free\n", desc); > - dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys); > - } > + list_for_each_entry_safe_reverse(desc, _desc, list, node) > + fsl_dma_free_descriptor(chan, desc); > } > > /** > @@ -819,8 +826,7 @@ static void fsldma_cleanup_descriptor(struct fsldma_chan > *chan, > dma_run_dependencies(txd); > > dma_descriptor_unmap(txd); > - chan_dbg(chan, "LD %p free\n", desc); > - dma_pool_free(chan->desc_pool, desc, txd->phys); > + fsl_dma_free_descriptor(chan, desc); Here is no list_del() call since it's been called in dma_do_tasklet(). What will be the result of double list_del() against the same node? > } > > /** -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v3 6/8] DMA: Freescale: change descriptor release process for supporting async_tx
> + * Start any pending transactions automatically Dot at the end of the line. > + * > + * In the ideal case, we keep the DMA controller busy while we go > + * ahead and free the descriptors below. > + */ > + fsl_chan_xfer_ld_queue(chan); > > - dma_descriptor_unmap(txd); > - fsl_dma_free_descriptor(chan, desc); > + if (cookie > 0) > + chan->common.completed_cookie = cookie; > } > > /** > @@ -620,8 +729,10 @@ static void fsl_dma_free_chan_resources(struct dma_chan > *dchan) > > chan_dbg(chan, "free all channel resources\n"); > spin_lock_irqsave(&chan->desc_lock, flags); > + fsldma_cleanup_descriptors(chan); > fsldma_free_desc_list(chan, &chan->ld_pending); > fsldma_free_desc_list(chan, &chan->ld_running); > + fsldma_free_desc_list(chan, &chan->ld_completed); > spin_unlock_irqrestore(&chan->desc_lock, flags); > > dma_pool_destroy(chan->desc_pool); > @@ -859,6 +970,7 @@ static int fsl_dma_device_control(struct dma_chan *dchan, > /* Remove and free all of the descriptors in the LD queue */ > fsldma_free_desc_list(chan, &chan->ld_pending); > fsldma_free_desc_list(chan, &chan->ld_running); > + fsldma_free_desc_list(chan, &chan->ld_completed); > chan->idle = true; > > spin_unlock_irqrestore(&chan->desc_lock, flags); > @@ -918,6 +1030,17 @@ static enum dma_status fsl_tx_status(struct dma_chan > *dchan, > dma_cookie_t cookie, > struct dma_tx_state *txstate) > { > + struct fsldma_chan *chan = to_fsl_chan(dchan); > + enum dma_status ret; > + > + ret = dma_cookie_status(dchan, cookie, txstate); > + if (ret == DMA_COMPLETE) > + return ret; > + > + spin_lock_bh(&chan->desc_lock); > + fsldma_cleanup_descriptors(chan); > + spin_unlock_bh(&chan->desc_lock); > + > return dma_cookie_status(dchan, cookie, txstate); > } > > @@ -995,52 +1118,19 @@ static irqreturn_t fsldma_chan_irq(int irq, void *data) > static void dma_do_tasklet(unsigned long data) > { > struct fsldma_chan *chan = (struct fsldma_chan *)data; > - struct fsl_desc_sw *desc, *_desc; > - LIST_HEAD(ld_cleanup); > unsigned long flags; > > chan_dbg(chan, "tasklet entry\n"); > > spin_lock_irqsave(&chan->desc_lock, flags); > > - /* update the cookie if we have some descriptors to cleanup */ > - if (!list_empty(&chan->ld_running)) { > - dma_cookie_t cookie; > - > - desc = to_fsl_desc(chan->ld_running.prev); > - cookie = desc->async_tx.cookie; > - dma_cookie_complete(&desc->async_tx); > - > - chan_dbg(chan, "completed_cookie=%d\n", cookie); > - } > - > - /* > - * move the descriptors to a temporary list so we can drop the lock > - * during the entire cleanup operation > - */ > - list_splice_tail_init(&chan->ld_running, &ld_cleanup); > - > /* the hardware is now idle and ready for more */ > chan->idle = true; > > - /* > - * Start any pending transactions automatically > - * > - * In the ideal case, we keep the DMA controller busy while we go > - * ahead and free the descriptors below. > - */ > - fsl_chan_xfer_ld_queue(chan); > - spin_unlock_irqrestore(&chan->desc_lock, flags); > + /* Run all cleanup for descriptors which have been completed */ > + fsldma_cleanup_descriptors(chan); > > - /* Run the callback for each descriptor, in order */ > - list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) { > - > - /* Remove from the list of transactions */ > - list_del(&desc->node); > - > - /* Run all cleanup for this descriptor */ > - fsldma_cleanup_descriptor(chan, desc); > - } > + spin_unlock_irqrestore(&chan->desc_lock, flags); > > chan_dbg(chan, "tasklet exit\n"); > } > @@ -1224,6 +1314,7 @@ static int fsl_dma_chan_probe(struct fsldma_device > *fdev, > spin_lock_init(&chan->desc_lock); > INIT_LIST_HEAD(&chan->ld_pending); > INIT_LIST_HEAD(&chan->ld_running); > + INIT_LIST_HEAD(&chan->ld_completed); > chan->idle = true; > > chan->common.device = &fdev->common; > diff
Re: [PATCH v3 8/8] DMA: Freescale: add suspend resume functions for DMA driver
MA_MR_CC & ~FSL_DMA_MR_CA; > + DMA_OUT(chan, &chan->regs->mr, mode, 32); > + chan->pm_state = RUNNING; > + spin_unlock_bh(&chan->desc_lock); > + } > + > + return 0; > +} > + > +static const struct dev_pm_ops fsldma_pm_ops = { > + .prepare= fsldma_prepare, > + .suspend= fsldma_suspend, > + .resume = fsldma_resume, > +}; > +#endif > + > static const struct of_device_id fsldma_of_ids[] = { > { .compatible = "fsl,elo3-dma", }, > { .compatible = "fsl,eloplus-dma", }, > @@ -1462,6 +1559,9 @@ static struct platform_driver fsldma_of_driver = { > .name = "fsl-elo-dma", > .owner = THIS_MODULE, > .of_match_table = fsldma_of_ids, > +#ifdef CONFIG_PM > + .pm = &fsldma_pm_ops, > +#endif > }, > .probe = fsldma_of_probe, > .remove = fsldma_of_remove, > diff --git a/drivers/dma/fsldma.h b/drivers/dma/fsldma.h > index ec19517..eecaf9e 100644 > --- a/drivers/dma/fsldma.h > +++ b/drivers/dma/fsldma.h > @@ -134,6 +134,18 @@ struct fsldma_device { > #define FSL_DMA_CHAN_PAUSE_EXT 0x1000 > #define FSL_DMA_CHAN_START_EXT 0x2000 > > +#ifdef CONFIG_PM > +struct fsldma_chan_regs_save { > + u32 mr; > +}; > + > +enum fsldma_pm_state { > + RUNNING = 0, > + SUSPENDING, > + SUSPENDED, > +}; > +#endif > + > struct fsldma_chan { > char name[8]; /* Channel name */ > struct fsldma_chan_regs __iomem *regs; > @@ -161,6 +173,10 @@ struct fsldma_chan { > struct tasklet_struct tasklet; > u32 feature; > bool idle; /* DMA controller is idle */ > +#ifdef CONFIG_PM > + struct fsldma_chan_regs_save regs_save; > + enum fsldma_pm_state pm_state; > +#endif > > void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable); > void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable); -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v3 4/8] DMA: Freescale: add fsl_dma_free_descriptor() to reduce code duplication
On Fri, 2014-04-11 at 16:14 +0800, Hongbo Zhang wrote: > On 04/10/2014 07:29 PM, Andy Shevchenko wrote: > > On Thu, 2014-04-10 at 15:10 +0800, hongbo.zh...@freescale.com wrote: [] > >> @@ -819,8 +826,7 @@ static void fsldma_cleanup_descriptor(struct > >> fsldma_chan *chan, > >>dma_run_dependencies(txd); > >> > >>dma_descriptor_unmap(txd); > >> - chan_dbg(chan, "LD %p free\n", desc); > >> - dma_pool_free(chan->desc_pool, desc, txd->phys); > >> + fsl_dma_free_descriptor(chan, desc); > > Here is no list_del() call since it's been called in dma_do_tasklet(). > > What will be the result of double list_del() against the same node? > > Not clear with your point. > This patch is only introducing a common fsl_dma_free_descriptor() to > reduce code duplication. And later in the patch 6/8 the > fsldma_cleanup_descriptor() is replaced by fsldma_cleanup_descriptorS(). In the last case you could have a broken kernel which will fails on double list_del(). I think it's better to leave this one untouched and you may remove it later. Or move this patch after you have removed that lines. -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v3 6/8] DMA: Freescale: change descriptor release process for supporting async_tx
On Fri, 2014-04-11 at 16:33 +0800, Hongbo Zhang wrote: > >>> + * hardware channel, subsequent descriptors are either in > >>> + * process or have not been submitted > >> Dot at the eol. Check in all comments. > > > > Even though I saw there are other comments without the dots, I think > > it is better to have it. > > Thanks, all. > > > Hmm... think it again, it it really necessary to have it? > Even I have it in my patch, there are already so many comments exists > without it. For my opinion is better to keep style in your patches. Better if it commonly used style in the driver. But comment against comments is really minor thing. -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 1/2] sata_dwc_460ex: move to generic DMA driver
The SATA implementation based on two actually different devices, i.e. SATA and DMA controllers. For Synopsys DesignWare DMA we have already a generic implementation of the driver. Thus, the patch converts the code to use DMAEngine framework and dw_dmac driver. In future it will be better to split the devices inside DTS as well like it's done on other platforms. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 736 +++ 1 file changed, 122 insertions(+), 614 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7bc0c12..08cd63f 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -36,11 +36,16 @@ #include #include #include + #include "libata.h" #include #include +/* Supported DMA engine drivers */ +#include +#include + /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -60,153 +65,9 @@ #define NO_IRQ 0 #endif -/* SATA DMA driver Globals */ -#define DMA_NUM_CHANS 1 -#define DMA_NUM_CHAN_REGS 8 - -/* SATA DMA Register definitions */ #define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ -struct dmareg { - u32 low;/* Low bits 0-31 */ - u32 high; /* High bits 32-63 */ -}; - -/* DMA Per Channel registers */ -struct dma_chan_regs { - struct dmareg sar; /* Source Address */ - struct dmareg dar; /* Destination address */ - struct dmareg llp; /* Linked List Pointer */ - struct dmareg ctl; /* Control */ - struct dmareg sstat;/* Source Status not implemented in core */ - struct dmareg dstat;/* Destination Status not implemented in core*/ - struct dmareg sstatar; /* Source Status Address not impl in core */ - struct dmareg dstatar; /* Destination Status Address not implemente */ - struct dmareg cfg; /* Config */ - struct dmareg sgr; /* Source Gather */ - struct dmareg dsr; /* Destination Scatter */ -}; - -/* Generic Interrupt Registers */ -struct dma_interrupt_regs { - struct dmareg tfr; /* Transfer Interrupt */ - struct dmareg block;/* Block Interrupt */ - struct dmareg srctran; /* Source Transfer Interrupt */ - struct dmareg dsttran; /* Dest Transfer Interrupt */ - struct dmareg error;/* Error */ -}; - -struct ahb_dma_regs { - struct dma_chan_regschan_regs[DMA_NUM_CHAN_REGS]; - struct dma_interrupt_regs interrupt_raw;/* Raw Interrupt */ - struct dma_interrupt_regs interrupt_status; /* Interrupt Status */ - struct dma_interrupt_regs interrupt_mask; /* Interrupt Mask */ - struct dma_interrupt_regs interrupt_clear; /* Interrupt Clear */ - struct dmareg statusInt; /* Interrupt combined*/ - struct dmareg rq_srcreg; /* Src Trans Req */ - struct dmareg rq_dstreg; /* Dst Trans Req */ - struct dmareg rq_sgl_srcreg; /* Sngl Src Trans Req*/ - struct dmareg rq_sgl_dstreg; /* Sngl Dst Trans Req*/ - struct dmareg rq_lst_srcreg; /* Last Src Trans Req*/ - struct dmareg rq_lst_dstreg; /* Last Dst Trans Req*/ - struct dmareg dma_cfg;/* DMA Config */ - struct dmareg dma_chan_en;/* DMA Channel Enable*/ - struct dmareg dma_id; /* DMA ID */ - struct dmareg dma_test; /* DMA Test */ - struct dmareg res1; /* reserved */ - struct dmareg res2; /* reserved */ - /* -* DMA Comp Params -* Param 6 = dma_param[0], Param 5 = dma_param[1], -* Param 4 = dma_param[2] ... -*/ - struct dmareg dma_params[6]; -}; - -/* Data structure for linked list item */ -struct lli { - u32 sar;/* Source Address */ - u32 dar;/* Destination address */ - u32 llp;/* Linked List Pointer */ - struct dmareg ctl;/* Control */ - struct dmareg dstat; /* Destination Status */ -}; - -enum { - SATA_DWC_DMAC_LLI_SZ = (sizeof(struct lli)), - SATA_DWC_DMAC_LLI_NUM = 256, - SATA_DWC_DMAC_LLI_TBL_SZ = (SATA_DWC_DMAC_LLI_SZ * \ - SATA_DWC_DMAC_LLI_NUM), - SATA_DWC_DMAC_TWIDTH_BYTES = 4, - SATA_DWC_DMAC_CTRL_TSIZE_MAX = (0x0800 * \ - SATA_DWC_DMAC_TWIDTH_BYTES), -}; - -/* DMA Register Operation Bits */ enum { - DMA_EN = 0x0001, /* Enable AHB DMA */ - DMA_CTL_LLP_SRCEN = 0x1000, /* Blk chain enable Src */ - DMA_CTL_LLP_DSTEN = 0x0800
[PATCH v1 0/2] sata_dwc_460ex: move to generic DMA driver
The SATA implementation based on two actually different devices, i.e. SATA and DMA controllers. For Synopsys DesignWare DMA we have already a generic implementation of the driver. Thus, the patch 1/2 converts the code to use DMAEngine framework and dw_dmac driver. In future it will be better to split the devices inside DTS as well like it's done on other platforms and remove hardcoded parameters of DMA controller. Besides it's a nice clean up it removes a lot of warnings produced by the original code, that pissed off even Linus [1]. Though, this series doesn't re-enable COMPILE_TEST for this module. The driver is compile tested only on x86. So, it would be nice if anyone who has either AMCC 460EX Canyonlands board or similar SATA controller in possession can test this. [1] http://www.spinics.net/lists/linux-ide/msg50334.html Andy Shevchenko (2): sata_dwc_460ex: move to generic DMA driver sata_dwc_460ex: re-use hsdev->dev instead of dwc_dev drivers/ata/sata_dwc_460ex.c | 753 --- 1 file changed, 130 insertions(+), 623 deletions(-) -- 2.1.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 2/2] sata_dwc_460ex: re-use hsdev->dev instead of dwc_dev
This patch re-uses hsdev->dev which is allocated on heap. Therefore, the private structure, which is global variable, is reduced by one field. In one case ap->dev is used and there it seems to be right decision. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 23 +++ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 08cd63f..5ab4849 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -194,7 +194,6 @@ struct sata_dwc_host_priv { void__iomem *scr_addr_sstatus; u32 sata_dwc_sactive_issued ; u32 sata_dwc_sactive_queued ; - struct device *dwc_dev; }; static struct sata_dwc_host_priv host_pvt; @@ -252,16 +251,16 @@ static const char *get_dma_dir_descript(int dma_dir) } } -static void sata_dwc_tf_dump(struct ata_taskfile *tf) +static void sata_dwc_tf_dump(struct ata_port *ap, struct ata_taskfile *tf) { - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "taskfile cmd: 0x%02x protocol: %s flags: 0x%lx device: %x\n", tf->command, get_prot_descript(tf->protocol), tf->flags, tf->device); - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal, tf->lbam, tf->lbah); - dev_vdbg(host_pvt.dwc_dev, + dev_vdbg(ap->dev, "hob_feature: 0x%02x hob_nsect: 0x%x hob_lbal: 0x%x hob_lbam: 0x%x hob_lbah: 0x%x\n", tf->hob_feature, tf->hob_nsect, tf->hob_lbal, tf->hob_lbam, tf->hob_lbah); @@ -337,7 +336,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd desc->callback = dma_dwc_xfer_done; desc->callback_param = hsdev; - dev_dbg(host_pvt.dwc_dev, "%s sg: 0x%p, count: %d addr: %pad\n", + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", __func__, qc->sg, qc->n_elem, &addr); return desc; @@ -687,7 +686,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) * This should not happen, it indicates the driver is out of * sync. If it does happen, clear dmacr anyway. */ - dev_err(host_pvt.dwc_dev, + dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", __func__, tag, hsdevp->dma_pending[tag], in_le32(&hsdev->sata_dwc_regs->dmacr)); @@ -779,7 +778,7 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) */ out_le32(&hsdev->sata_dwc_regs->errmr, SATA_DWC_SERROR_ERR_BITS); - dev_dbg(host_pvt.dwc_dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", + dev_dbg(hsdev->dev, "%s: INTMR = 0x%08x, ERRMR = 0x%08x\n", __func__, in_le32(&hsdev->sata_dwc_regs->intmr), in_le32(&hsdev->sata_dwc_regs->errmr)); } @@ -855,7 +854,7 @@ static int sata_dwc_port_start(struct ata_port *ap) hsdevp->hsdev = hsdev; hsdevp->dws = &sata_dwc_dma_dws; - hsdevp->dws->dma_dev = host_pvt.dwc_dev; + hsdevp->dws->dma_dev = hsdev->dev; dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); @@ -863,7 +862,7 @@ static int sata_dwc_port_start(struct ata_port *ap) /* Acquire DMA channel */ hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); if (!hsdevp->chan) { - dev_err(host_pvt.dwc_dev, "%s: dma channel unavailable\n", + dev_err(hsdev->dev, "%s: dma channel unavailable\n", __func__); err = -EAGAIN; goto CLEANUP_ALLOC; @@ -990,7 +989,7 @@ static void sata_dwc_bmdma_start_by_tag(struct ata_queued_cmd *qc, u8 tag) "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s start_dma? %x\n", __func__, qc, tag, qc->tf.command, get_dma_dir_descript(qc->dma_dir), start_dma); - sata_dwc_tf_dump(&(qc->tf)); + sata_dwc_tf_dump(ap, &qc->tf); if (start_dma) { reg = core_scr_read(SCR_ERROR); @@ -1244,7 +1243,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) } /* Save dev for later use in dev_xxx() routines */ - host_pvt.dwc_dev = &ofdev->dev; + hsdev->dev = &ofdev->dev; hsdev->dma->dev = &ofdev->dev; -- 2.1.4 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: linux-next: build failure after merge of the aio tree
On Tue, Mar 15, 2016 at 8:46 AM, Stephen Rothwell wrote: > Hi Benjamin, > > After merging the aio tree, today's linux-next build (powerpc > ppc44x_defconfig) failed like this: > > fs/built-in.o: In function `aio_thread_op_foo_at': > aio.c:(.text+0x4dab4): undefined reference to `__get_user_bad' > aio.c:(.text+0x4daec): undefined reference to `__get_user_bad' avr32 seems affected as well and the below solution is not suitable (should be much more verbose in asm, I guess). > > Caused by commit > > 150a0b4905f1 ("aio: add support for async openat()") > > despite commit > > d2f7a973e11e ("aio: don't use __get_user() for 64 bit values") > > This is due to a bug in the powerpc __get_user_check() macro (the return > value is defined to be "unsigned long" which is only 32 bits on a 32 > bit platform). > > I applied the patch below which seems to help (Michael, what do you > think?), but given Al's and Christoph's reactions, I am inclined to > remove the aio tree from tomorrow and maybe it can be revisited after > the merge window. > > From: Stephen Rothwell > Date: Tue, 15 Mar 2016 16:36:06 +1100 > Subject: [PATCH] powerpc: fix get_user for 64 bit typs on 32 bit platforms > > solution borrowed from the x86 uaccess.h > > Signed-off-by: Stephen Rothwell > --- > arch/powerpc/include/asm/uaccess.h | 9 ++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/arch/powerpc/include/asm/uaccess.h > b/arch/powerpc/include/asm/uaccess.h > index b7c20f0b8fbe..52262b2f37fc 100644 > --- a/arch/powerpc/include/asm/uaccess.h > +++ b/arch/powerpc/include/asm/uaccess.h > @@ -261,10 +261,13 @@ do { > \ > } \ > } while (0) > > +#define __inttype(x) \ > + __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL)) > + > #define __get_user_nocheck(x, ptr, size) \ > ({ \ > long __gu_err; \ > - unsigned long __gu_val; \ > + __inttype(*(ptr)) __gu_val; \ > __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ > __chk_user_ptr(ptr);\ > if (!is_kernel_addr((unsigned long)__gu_addr)) \ > @@ -277,7 +280,7 @@ do { > \ > #define __get_user_check(x, ptr, size) \ > ({ \ > long __gu_err = -EFAULT;\ > - unsigned long __gu_val = 0;\ > + __inttype(*(ptr)) __gu_val = 0; \ > __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ > might_fault(); \ > if (access_ok(VERIFY_READ, __gu_addr, (size))) \ > @@ -289,7 +292,7 @@ do { > \ > #define __get_user_nosleep(x, ptr, size) \ > ({ \ > long __gu_err; \ > - unsigned long __gu_val; \ > + __inttype(*(ptr)) __gu_val; \ > __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ > __chk_user_ptr(ptr);\ > __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ > -- > 2.7.0 > > -- > Cheers, > Stephen Rothwell -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: linux-next: build failure after merge of the aio tree
On Wed, Mar 16, 2016 at 12:02 AM, Arnd Bergmann wrote: > On Tuesday 15 March 2016 12:22:28 Benjamin LaHaise wrote: >> On Tue, Mar 15, 2016 at 04:19:02PM +, Sudip Mukherjee wrote: >> > On Tue, Mar 15, 2016 at 05:46:34PM +1100, Stephen Rothwell wrote: >> > > Hi Benjamin, >> > > >> > > After merging the aio tree, today's linux-next build (powerpc >> > > ppc44x_defconfig) failed like this: >> > > >> > > fs/built-in.o: In function `aio_thread_op_foo_at': >> > > aio.c:(.text+0x4dab4): undefined reference to `__get_user_bad' >> > > aio.c:(.text+0x4daec): undefined reference to `__get_user_bad' >> > > >> > > Caused by commit >> > > >> > > 150a0b4905f1 ("aio: add support for async openat()") >> > > >> > > despite commit >> > > >> > > d2f7a973e11e ("aio: don't use __get_user() for 64 bit values") >> > > >> I've removed everything from the aio-next.git tree for now. Will revisit >> after the merge window. I think it is the best solution right now. > I've also sent a patch that fixes the link error on ARM and that should > work on all other architectures too. In case of avr32 signalfd_read() fails. Does your patch help with it as well? P.S. Bisecting shows same culprit: 150a0b4905f1 ("aio: add support for async openat()") -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH V2] mtd: nand: pasemi: switch to pr_* functions
On Fri, Apr 8, 2016 at 2:13 PM, Rafał Miłecki wrote: > 1) Use pr_fmt to keep messages consistent > 2) Don't warn if kzalloc fails as it dumps stack on its own > 3) Use %pR format for displaying whole resource to avoid: > warning: format ‘%08llx’ expects type ‘long long unsigned int’, but argument > 2 has type ‘resource_size_t’ > > Signed-off-by: Rafał Miłecki > --- > drivers/mtd/nand/pasemi_nand.c | 9 - > 1 file changed, 4 insertions(+), 5 deletions(-) > > diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c > index 63fcb8c..e8372b4 100644 > --- a/drivers/mtd/nand/pasemi_nand.c > +++ b/drivers/mtd/nand/pasemi_nand.c > @@ -22,6 +22,8 @@ > > #undef DEBUG > > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt > + > #include > #include > #include > @@ -112,8 +114,6 @@ static int pasemi_nand_probe(struct platform_device > *ofdev) > /* Allocate memory for MTD device structure and private data */ > chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); > if (!chip) { > - printk(KERN_WARNING > - "Unable to allocate PASEMI NAND MTD device > structure\n"); > err = -ENOMEM; > goto out; > } > @@ -163,13 +163,12 @@ static int pasemi_nand_probe(struct platform_device > *ofdev) > } > > if (mtd_device_register(pasemi_nand_mtd, NULL, 0)) { > - printk(KERN_ERR "pasemi_nand: Unable to register MTD > device\n"); > + pr_err("Unable to register MTD device\n"); And why not to use dev_err(&ofdev->dev, …); ? > err = -ENODEV; > goto out_lpc; > } > > - printk(KERN_INFO "PA Semi NAND flash at %08llx, control at I/O %x\n", > - res.start, lpcctl); > + pr_info("PA Semi NAND flash at %pR, control at I/O %x\n", &res, > lpcctl); > Ditto. > return 0; > > -- > 1.8.4.5 > -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 02/23] ata: sata_dwc_460ex: fix crash on offline links without an attached drive
From: Christian Lamparter This patch fixes Machine Check "Data Write PLB Error" which happens when libata-sff's ata_sff_dev_select is trying to write into the device_addr in order to select a drive. However, SATA has no master or slave devices like the old ATA Bus, therefore selecting a different drive is kind of pointless. Data Write PLB Error Oops: Machine check, sig: 7 [#1] PowerPC 44x Platform Modules linked in: CPU: 0 PID: 508 Comm: scsi_eh_0 Not tainted 4.6.0-rc3-next-20160412+ #10 [...] NIP [c027e820] ata_sff_dev_select+0x3c/0x44 LR [c027e810] ata_sff_dev_select+0x2c/0x44 Call Trace: [cec31cd0] [c027da00] ata_sff_postreset+0x40/0xb4 (unreliable) [cec31ce0] [c027a03c] ata_eh_reset+0x5cc/0x928 [cec31d60] [c027a840] ata_eh_recover+0x330/0x10bc [cec31df0] [c027bae0] ata_do_eh+0x4c/0xa4 [...] Signed-off-by: Christian Lamparter --- drivers/ata/sata_dwc_460ex.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 5213e22..7f95389 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1134,6 +1134,11 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class, return ret; } +static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device) +{ + /* SATA DWC is master only */ +} + /* * scsi mid-layer and libata interface structures */ @@ -1164,6 +1169,8 @@ static struct ata_port_operations sata_dwc_ops = { .port_start = sata_dwc_port_start, .port_stop = sata_dwc_port_stop, + .sff_dev_select = sata_dwc_dev_select, + .bmdma_setup= sata_dwc_bmdma_setup, .bmdma_start= sata_dwc_bmdma_start, }; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 04/23] ata: sata_dwc_460ex: burst size must be in items not bytes
The burst size as defined by DMAengine API is in items of address width. Derive burst size from AHB_DMA_BRST_DFLT (64 bytes) by dividing it to DMA_SLAVE_BUSWIDTH_4_BYTES (4 bytes) that gives us 16 items. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index aee8873..4cac27d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -65,7 +65,7 @@ #define NO_IRQ 0 #endif -#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ +#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length */ enum { SATA_DWC_MAX_PORTS = 1, @@ -318,8 +318,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd } sconf.direction = qc->dma_dir; - sconf.src_maxburst = AHB_DMA_BRST_DFLT; - sconf.dst_maxburst = AHB_DMA_BRST_DFLT; + sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ + sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 03/23] ata: sata_dwc_460ex: set dma_boundary to 0x1fff
The original code states: Make sure a LLI block is not created that will span 8K max FIS boundary. If the block spans such a FIS boundary, there is a chance that a DMA burst will cross that boundary -- this results in an error in the host controller. Since we have switched to generic DMAengine API we satisfy above by setting dma_boundary value to 0x1fff. Suggested-by: Mans Rullgard Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7f95389..aee8873 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1151,7 +1151,13 @@ static struct scsi_host_template sata_dwc_sht = { */ .sg_tablesize = LIBATA_MAX_PRD, /* .can_queue = ATA_MAX_QUEUE, */ - .dma_boundary = ATA_DMA_BOUNDARY, + /* +* Make sure a LLI block is not created that will span 8K max FIS +* boundary. If the block spans such a FIS boundary, there is a chance +* that a DMA burst will cross that boundary -- this results in an +* error in the host controller. +*/ + .dma_boundary = 0x1fff /* ATA_DMA_BOUNDARY */, }; static struct ata_port_operations sata_dwc_ops = { -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 01/23] ata: sata_dwc_460ex: remove incorrect locking
From: Mans Rullgard This lock is already taken in ata_scsi_queuecmd() a few levels up the call stack so attempting to take it here is an error. Moreover, it is pointless in the first place since it only protects a single, atomic assignment. Enabling lock debugging gives the following output: = [ INFO: possible recursive locking detected ] 4.4.0-rc5+ #189 Not tainted - kworker/u2:3/37 is trying to acquire lock: (&(&host->lock)->rlock){-.-...}, at: [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c but task is already holding lock: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 other info that might help us debug this: Possible unsafe locking scenario: CPU0 lock(&(&host->lock)->rlock); lock(&(&host->lock)->rlock); *** DEADLOCK *** May be due to missing lock nesting notation 4 locks held by kworker/u2:3/37: #0: ("events_unbound"){.+.+.+}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #1: ((&entry->work)){+.+.+.}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #2: (&bdev->bd_mutex){+.+.+.}, at: [<9011fd54>] __blkdev_get+0x50/0x380 #3: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 stack backtrace: CPU: 0 PID: 37 Comm: kworker/u2:3 Not tainted 4.4.0-rc5+ #189 Workqueue: events_unbound async_run_entry_fn Stack : 90b38e30 0021 0003 9b2a6040 9005f3f0 904fc8dc 0025 906b96e4 90528648 9b3336c4 904fc8dc 9009bf18 0002 0004 9b3336c4 9b3336e4 904fc8dc 9003d074 9050 9005e738 6e657665 755f7374 756f626e 646e 9b00ca00 9b025000 ... Call Trace: [<90009d6c>] show_stack+0x88/0xa4 [<90057744>] __lock_acquire+0x1ce8/0x2154 [<900583e4>] lock_acquire+0x64/0x8c [<9045ff10>] _raw_spin_lock_irqsave+0x54/0x78 [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c [<90283484>] sata_dwc_qc_issue+0x1a8/0x24c [<9026b39c>] ata_qc_issue+0x1f0/0x410 [<90273c6c>] ata_scsi_translate+0xb4/0x200 [<90276234>] ata_scsi_queuecmd+0xb4/0x330 [<9025800c>] scsi_dispatch_cmd+0xd0/0x128 [<90259934>] scsi_request_fn+0x58c/0x638 [<901a3e50>] __blk_run_queue+0x40/0x5c [<901a83d4>] blk_queue_bio+0x27c/0x28c [<901a5914>] generic_make_request+0xf0/0x188 [<901a5a54>] submit_bio+0xa8/0x194 [<9011adcc>] submit_bh_wbc.isra.23+0x15c/0x17c [<9011c908>] block_read_full_page+0x3e4/0x428 [<9009e2e0>] do_read_cache_page+0xac/0x210 [<9009fd90>] read_cache_page+0x18/0x24 [<901bbd18>] read_dev_sector+0x38/0xb0 [<901bd174>] msdos_partition+0xb4/0x5c0 [<901bcb8c>] check_partition+0x140/0x274 [<901bba60>] rescan_partitions+0xa0/0x2b0 [<9011ff68>] __blkdev_get+0x264/0x380 [<901201ac>] blkdev_get+0x128/0x36c [<901b9378>] add_disk+0x3c0/0x4bc [<90268268>] sd_probe_async+0x100/0x224 [<90043a44>] async_run_entry_fn+0x50/0x124 [<9003a11c>] process_one_work+0x1a4/0x430 [<9003a4f4>] worker_thread+0x14c/0x4fc [<900408f4>] kthread+0xd0/0xe8 [<90004338>] ret_from_kernel_thread+0x14/0x1c Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2cb6f7e..5213e22 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -924,15 +924,13 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap, struct ata_taskfile *tf, u8 tag, u32 cmd_issued) { - unsigned long flags; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, ata_get_cmd_descript(tf->command), tag); - spin_lock_irqsave(&ap->host->lock, flags); hsdevp->cmd_issued[tag] = cmd_issued; - spin_unlock_irqrestore(&ap->host->lock, flags); + /* * Clear SError before executing a new command. * sata_dwc_scr_write and read can not be used here. Clearing the PM -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 07/23] ata: sata_dwc_460ex: skip dma setup for non-dma commands
From: Mans Rullgard Calling dmaengine_prep_slave_sg() for non-dma ATA commands is unnecessary at best and could be harmful if the dma driver reacts badly to this. It also causes this driver to print a bogus error message in these cases. This patch changes sata_dwc_qc_issue() to only do the dma setup for dma commands and also reports an error to libata if if fails. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 35 +-- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 1250e18..038e5fb 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1023,36 +1023,12 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) sata_dwc_bmdma_start_by_tag(qc, tag); } -/* - * Function : sata_dwc_qc_prep_by_tag - * arguments : ata_queued_cmd *qc, u8 tag - * Return value : None - * qc_prep for a particular queued command based on tag - */ -static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) -{ - struct dma_async_tx_descriptor *desc; - struct ata_port *ap = qc->ap; - struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); - - dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", - __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir), -qc->n_elem); - - desc = dma_dwc_xfer_setup(qc); - if (!desc) { - dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n", - __func__); - return; - } - hsdevp->desc[tag] = desc; -} - static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) { u32 sactive; u8 tag = qc->tag; struct ata_port *ap = qc->ap; + struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); #ifdef DEBUG_NCQ if (qc->tag > 0 || ap->link.sactive > 1) @@ -1066,7 +1042,14 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) if (!ata_is_ncq(qc->tf.protocol)) tag = 0; - sata_dwc_qc_prep_by_tag(qc, tag); + + if (ata_is_dma(qc->tf.protocol)) { + hsdevp->desc[tag] = dma_dwc_xfer_setup(qc); + if (!hsdevp->desc[tag]) + return AC_ERR_SYSTEM; + } else { + hsdevp->desc[tag] = NULL; + } if (ata_is_ncq(qc->tf.protocol)) { sactive = core_scr_read(SCR_ACTIVE); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 05/23] ata: sata_dwc_460ex: DMA is always a flow controller
In the original code the DMA is always a flow controller. Set this accordingly in updated code. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4cac27d..1250e18 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -311,7 +311,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd if (qc->dma_dir == DMA_DEV_TO_MEM) { sconf.src_addr = addr; - sconf.device_fc = true; + sconf.device_fc = false; } else {/* DMA_MEM_TO_DEV */ sconf.dst_addr = addr; sconf.device_fc = false; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 00/23] ata: sata_dwc_460ex: make it working again
The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic DMA driver") to switch to generic DMA engine API wasn't tested on bare metal. Besides that we expecting new board support coming with the same SATA IP but with different DMA. This series is targetting the following things: - a few bug fixes to the original driver - a part to fix the DMA engine usage and in particularly dw_dmac driver - move driver to use generic PHY and "dmas" property which leads to update in DTS The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g) boards. In any case I ask Christian, Måns, and Julian to independently test and provide Tested-by tag or error report. Series depends on previously published but not yet fully applied series [1]. [1] http://www.spinics.net/lists/kernel/msg2239735.html Andy Shevchenko (11): ata: sata_dwc_460ex: set dma_boundary to 0x1fff ata: sata_dwc_460ex: burst size must be in items not bytes ata: sata_dwc_460ex: DMA is always a flow controller ata: sata_dwc_460ex: select only core part of DMA driver ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros ata: sata_dwc_460ex: supply physical address of FIFO to DMA ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API ata: sata_dwc_460ex: use devm_ioremap ata: sata_dwc_460ex: make debug messages neat powerpc/4xx: Device tree update for the 460ex DWC SATA Christian Lamparter (1): ata: sata_dwc_460ex: fix crash on offline links without an attached drive Mans Rullgard (11): ata: sata_dwc_460ex: remove incorrect locking ata: sata_dwc_460ex: skip dma setup for non-dma commands ata: sata_dwc_460ex: use "dmas" DT property to find dma channel ata: sata_dwc_460ex: add phy support ata: sata_dwc_460ex: get rid of global data ata: sata_dwc_460ex: remove empty libata callback ata: sata_dwc_460ex: get rid of some pointless casts ata: sata_dwc_460ex: get rid of incorrect cast ata: sata_dwc_460ex: add __iomem to register base pointer ata: sata_dwc_460ex: use readl/writel_relaxed() ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr() arch/powerpc/boot/dts/canyonlands.dts | 15 +- drivers/ata/Kconfig | 12 +- drivers/ata/sata_dwc_460ex.c | 554 +- 3 files changed, 307 insertions(+), 274 deletions(-) -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 12/23] ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros
Here we refactor HOSTDEV{P}_FROM_*() macros to fit one line and fix the definition of HSDEV_FROM_HSDEVP() where wrong name of the parameter waas used. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 17 ++--- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 8e7c1b0..5bec790 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -168,18 +168,13 @@ struct sata_dwc_device_port { }; /* - * Commonly used DWC SATA driver Macros + * Commonly used DWC SATA driver macros */ -#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)\ - (host)->private_data) -#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)\ - (ap)->host->private_data) -#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)\ - (ap)->private_data) -#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)\ - (qc)->ap->host->private_data) -#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)\ - (hsdevp)->hsdev) +#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)(host)->private_data) +#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)(ap)->host->private_data) +#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)(ap)->private_data) +#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)(qc)->ap->host->private_data) +#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)(p)->hsdev) enum { SATA_DWC_CMD_ISSUED_NOT = 0, -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 06/23] ata: sata_dwc_460ex: select only core part of DMA driver
There is no need to have a platform driver compiled since the DMA driver is used as a library. Signed-off-by: Andy Shevchenko --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index cfa936a..7c6e43a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -314,7 +314,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" depends on 460EX - select DW_DMAC + select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 09/23] ata: sata_dwc_460ex: use "dmas" DT property to find dma channel
From: Mans Rullgard Currently this driver only works with a DesignWare DMA engine which it registers manually using the second "reg" address range and interrupt number from the DT node. This patch makes the driver instead use the "dmas" property if present, otherwise optionally falling back on the old way so existing device trees can continue to work. With this change, there is no longer any reason to depend on the 460EX machine type so drop that from Kconfig. Signed-off-by: Mans Rullgard --- drivers/ata/Kconfig | 11 ++- drivers/ata/sata_dwc_460ex.c | 198 --- 2 files changed, 138 insertions(+), 71 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 7c6e43a..ede126d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -313,14 +313,21 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" - depends on 460EX - select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. If unsure, say N. +config SATA_DWC_OLD_DMA + bool "Support old device trees" + depends on SATA_DWC + select DW_DMAC_CORE + default y if 460EX + help + This option enables support for old device trees without the + "dmas" property. + config SATA_DWC_DEBUG bool "Debugging driver version" depends on SATA_DWC diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 845c35d..daaa8a6 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -42,10 +43,6 @@ #include #include -/* Supported DMA engine drivers */ -#include -#include - /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -148,7 +145,9 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ +#ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; +#endif }; #define SATA_DWC_QCMD_MAX 32 @@ -159,7 +158,6 @@ struct sata_dwc_device_port { int dma_pending[SATA_DWC_QCMD_MAX]; /* DMA info */ - struct dw_dma_slave *dws; struct dma_chan *chan; struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX]; u32 dma_interrupt_count; @@ -198,13 +196,6 @@ struct sata_dwc_host_priv { static struct sata_dwc_host_priv host_pvt; -static struct dw_dma_slave sata_dwc_dma_dws = { - .src_id = 0, - .dst_id = 0, - .m_master = 1, - .p_master = 0, -}; - /* * Prototypes */ @@ -215,6 +206,99 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); static void sata_dwc_port_stop(struct ata_port *ap); static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); +#ifdef CONFIG_SATA_DWC_OLD_DMA + +#include +#include + +static struct dw_dma_slave sata_dwc_dma_dws = { + .src_id = 0, + .dst_id = 0, + .m_master = 1, + .p_master = 0, +}; + +static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + +static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp) +{ + struct sata_dwc_device *hsdev = hsdevp->hsdev; + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + dma_cap_mask_t mask; + + dws->dma_dev = hsdev->dev; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Acquire DMA channel */ + hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); + if (!hsdevp->chan) { + dev_err(hsdev->dev, "%s: dma channel unavailable\n", +__func__); + return -EAGAIN; + } + + return 0; +} + +static int sata_dwc_dma_init_old(struct platform_device *pdev, +struct sata_dwc_device *hsdev) +{ + struct device_node *np = pdev->dev.of_node; + int err; + + hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) + return -ENOMEM; + + hsdev->dma->dev = &pdev->dev; + + /* Get SATA DMA interrupt number */ + hsdev->dma->irq = irq_of_parse_and_map(np, 1); + if (hsdev->dma->irq == NO_IRQ) { + dev_err(&pdev->dev, "no SATA DMA irq\n"); + return -ENODEV; + } + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = of_iomap(np, 1); + if (!hsdev->dma->regs) { +
[PATCH v1 14/23] ata: sata_dwc_460ex: get rid of some pointless casts
From: Mans Rullgard Casting a pointer to unsigned long only to immediately cast it back to a pointer makes no sense. Fix this. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 30 +++--- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 571ecd1..9e8271d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -844,26 +844,26 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) in_le32(&hsdev->sata_dwc_regs->errmr)); } -static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) +static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base) { - port->cmd_addr = (void __iomem *)base + 0x00; - port->data_addr = (void __iomem *)base + 0x00; + port->cmd_addr = base + 0x00; + port->data_addr = base + 0x00; - port->error_addr = (void __iomem *)base + 0x04; - port->feature_addr = (void __iomem *)base + 0x04; + port->error_addr= base + 0x04; + port->feature_addr = base + 0x04; - port->nsect_addr = (void __iomem *)base + 0x08; + port->nsect_addr= base + 0x08; - port->lbal_addr = (void __iomem *)base + 0x0c; - port->lbam_addr = (void __iomem *)base + 0x10; - port->lbah_addr = (void __iomem *)base + 0x14; + port->lbal_addr = base + 0x0c; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x14; - port->device_addr = (void __iomem *)base + 0x18; - port->command_addr = (void __iomem *)base + 0x1c; - port->status_addr = (void __iomem *)base + 0x1c; + port->device_addr = base + 0x18; + port->command_addr = base + 0x1c; + port->status_addr = base + 0x1c; - port->altstatus_addr = (void __iomem *)base + 0x20; - port->ctl_addr = (void __iomem *)base + 0x20; + port->altstatus_addr= base + 0x20; + port->ctl_addr = base + 0x20; } static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp) @@ -1253,7 +1253,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET; - sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base); + sata_dwc_setup_port(&host->ports[0]->ioaddr, base); /* Read the ID and Version Registers */ idr = in_le32(&hsdev->sata_dwc_regs->idr); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 13/23] ata: sata_dwc_460ex: remove empty libata callback
From: Mans Rullgard The sata_dwc_qc_prep() does nothing. Use the default ata_noop_qc_prep instead. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 22 -- 1 file changed, 22 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 5bec790..571ecd1 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1134,27 +1134,6 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) return 0; } -/* - * Function : sata_dwc_qc_prep - * arguments : ata_queued_cmd *qc - * Return value : None - * qc_prep for a particular queued command - */ - -static void sata_dwc_qc_prep(struct ata_queued_cmd *qc) -{ - if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO)) - return; - -#ifdef DEBUG_NCQ - if (qc->tag > 0) - dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n", -__func__, qc->tag, qc->ap->link.active_tag); - - return ; -#endif -} - static void sata_dwc_error_handler(struct ata_port *ap) { ata_sff_error_handler(ap); @@ -1214,7 +1193,6 @@ static struct ata_port_operations sata_dwc_ops = { .error_handler = sata_dwc_error_handler, .hardreset = sata_dwc_hardreset, - .qc_prep= sata_dwc_qc_prep, .qc_issue = sata_dwc_qc_issue, .scr_read = sata_dwc_scr_read, -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 08/23] ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands
ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for them. Do call ata_bmdma_qc_issue() instead for this case. Suggested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 038e5fb..845c35d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1061,10 +1061,12 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) __func__, tag, qc->ap->link.sactive, sactive); ap->ops->sff_tf_load(ap, &qc->tf); - sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, + sata_dwc_exec_command_by_tag(ap, &qc->tf, tag, SATA_DWC_CMD_ISSUED_PEND); + } else if (ata_is_dma(qc->tf.protocol)) { + return ata_bmdma_qc_issue(qc); } else { - ata_sff_qc_issue(qc); + return ata_sff_qc_issue(qc); } return 0; } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 16/23] ata: sata_dwc_460ex: add __iomem to register base pointer
From: Mans Rullgard The pointer to the mmio register base is missing the __iomem annotation. Fix this. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 0eca56f2..42248b2 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -145,7 +145,7 @@ struct sata_dwc_device { struct ata_probe_ent*pe;/* ptr to probe-ent */ struct ata_host *host; u8 __iomem *reg_base; - struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + struct sata_dwc_regs __iomem *sata_dwc_regs;/* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; struct phy *phy; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 15/23] ata: sata_dwc_460ex: get rid of incorrect cast
From: Mans Rullgard The (void *__iomem) cast is wrong. Change the target type of the "base" pointer to void __iomem instead and drop the cast. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 9e8271d..0eca56f2 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1221,7 +1221,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct sata_dwc_device *hsdev; u32 idr, versionr; char *ver = (char *)&versionr; - u8 __iomem *base; + void __iomem *base; int err = 0; int irq; struct ata_host *host; @@ -1248,7 +1248,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ - hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET); + hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 18/23] ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API
Convert dmaengine_terminate_all() calls to synchronous and asynchronous versions where appropriate. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7810405..229e122 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -968,7 +968,7 @@ static void sata_dwc_port_stop(struct ata_port *ap) dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); - dmaengine_terminate_all(hsdevp->chan); + dmaengine_terminate_sync(hsdevp->chan); dma_release_channel(hsdevp->chan); phy_power_off(hsdev->phy); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 11/23] ata: sata_dwc_460ex: get rid of global data
From: Mans Rullgard This moves all global data into the driver private struct, thus permitting multiple devices of this type to be used. The core_scr_read/write() functions are replaced with equivalent calls to the existing sata_dwc_scr_read/write(). Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 79 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4d23fbd..8e7c1b0 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -146,6 +146,8 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + u32 sactive_issued; + u32 sactive_queued; struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; @@ -190,14 +192,6 @@ enum { SATA_DWC_DMA_PENDING_RX = 2, }; -struct sata_dwc_host_priv { - void__iomem *scr_addr_sstatus; - u32 sata_dwc_sactive_issued ; - u32 sata_dwc_sactive_queued ; -}; - -static struct sata_dwc_host_priv host_pvt; - /* * Prototypes */ @@ -457,21 +451,11 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) return 0; } -static u32 core_scr_read(unsigned int scr) -{ - return in_le32(host_pvt.scr_addr_sstatus + (scr * 4)); -} - -static void core_scr_write(unsigned int scr, u32 val) -{ - out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val); -} - -static void clear_serror(void) +static void clear_serror(struct ata_port *ap) { u32 val; - val = core_scr_read(SCR_ERROR); - core_scr_write(SCR_ERROR, val); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &val); + sata_dwc_scr_write(&ap->link, SCR_ERROR, val); } static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) @@ -498,7 +482,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, ata_ehi_clear_desc(ehi); - serror = core_scr_read(SCR_ERROR); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror); status = ap->ops->sff_check_status(ap); tag = ap->link.active_tag; @@ -509,7 +493,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]); /* Clear error register and interrupt bit */ - clear_serror(); + clear_serror(ap); clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR); /* This is the only error happening now. TODO check for exact error */ @@ -548,7 +532,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) int handled, num_processed, port = 0; uint intpr, sactive, sactive2, tag_mask; struct sata_dwc_device_port *hsdevp; - host_pvt.sata_dwc_sactive_issued = 0; + hsdev->sactive_issued = 0; spin_lock_irqsave(&host->lock, flags); @@ -577,7 +561,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); - host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag); + hsdev->sactive_issued |= qcmd_tag_to_mask(tag); qc = ata_qc_from_tag(ap, tag); /* @@ -591,11 +575,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) handled = 1; goto DONE; } - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; /* If no sactive issued and tag_mask is zero then this is not NCQ */ - if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) { + if (hsdev->sactive_issued == 0 && tag_mask == 0) { if (ap->link.active_tag == ATA_TAG_POISON) tag = 0; else @@ -665,22 +649,19 @@ DRVSTILLBUSY: */ /* process completed commands */ - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; - if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \ - tag_mask > 1) { + if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) { dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", - __func__, sactive, host_pvt.sata_dwc_sactive_issued, -
[PATCH v1 10/23] ata: sata_dwc_460ex: add phy support
From: Mans Rullgard This adds support for powering on an optional PHY when activating the device. Signed-off-by: Mans Rullgard --- drivers/ata/Kconfig | 1 + drivers/ata/sata_dwc_460ex.c | 22 ++ 2 files changed, 23 insertions(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ede126d..41b0725 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -313,6 +313,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" + select GENERIC_PHY help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index daaa8a6..4d23fbd 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,7 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -948,6 +950,10 @@ static int sata_dwc_port_start(struct ata_port *ap) if (err) goto CLEANUP_ALLOC; + err = phy_power_on(hsdev->phy); + if (err) + goto CLEANUP_ALLOC; + for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; @@ -983,11 +989,13 @@ CLEANUP: static void sata_dwc_port_stop(struct ata_port *ap) { struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); dmaengine_terminate_all(hsdevp->chan); dma_release_channel(hsdevp->chan); + phy_power_off(hsdev->phy); kfree(hsdevp); ap->private_data = NULL; @@ -1323,6 +1331,17 @@ static int sata_dwc_probe(struct platform_device *ofdev) } #endif + hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy"); + if (IS_ERR(hsdev->phy)) { + err = PTR_ERR(hsdev->phy); + hsdev->phy = NULL; + goto error_out; + } + + err = phy_init(hsdev->phy); + if (err) + goto error_out; + /* * Now, register with libATA core, this will also initiate the * device discovery process, invoking our port_start() handler & @@ -1336,6 +1355,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) return 0; error_out: + phy_exit(hsdev->phy); iounmap(base); return err; } @@ -1348,6 +1368,8 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); + phy_exit(hsdev->phy); + #ifdef CONFIG_SATA_DWC_OLD_DMA /* Free SATA DMA resources */ sata_dwc_dma_exit_old(hsdev); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 20/23] ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr()
From: Mans Rullgard This consolidates the reads from each of the if/else branches to one place making the code a lot nicer to look at. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2029f43..0ef72e4 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -729,15 +729,14 @@ DONE: static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) { struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); + u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_RX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else { /* * This should not happen, it indicates the driver is out of @@ -745,8 +744,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) */ dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", - __func__, tag, hsdevp->dma_pending[tag], - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); + __func__, tag, hsdevp->dma_pending[tag], dmacr); sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, SATA_DWC_DMACR_TXRXCH_CLEAR); } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 23/23] powerpc/4xx: Device tree update for the 460ex DWC SATA
Device tree update for the Applied micro processor 460ex on-chip SATA to use "dmas" property. Signed-off-by: Andy Shevchenko --- arch/powerpc/boot/dts/canyonlands.dts | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index 3dc75de..549c24c 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts @@ -190,12 +190,21 @@ /* DMA */ 0x2 &UIC0 0xc 0x4>; }; + AHBDMA: dma@bffd0800 { + compatible = "snps,dma-spear1340"; + reg = <4 0xbffd0800 0x400>; + interrupt-parent = <&UIC3>; + interrupts = <0x5 0x4>; + #dma-cells = <3>; + }; + SATA0: sata@bffd1000 { compatible = "amcc,sata-460ex"; - reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>; + reg = <4 0xbffd1000 0x800>; interrupt-parent = <&UIC3>; - interrupts = <0x0 0x4 /* SATA */ - 0x5 0x4>; /* AHBDMA */ + interrupts = <0x0 0x4>; + dmas = <&AHBDMA 0 1 0>; + dma-names = "sata-dma"; }; POB0: opb { -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 22/23] ata: sata_dwc_460ex: make debug messages neat
There is a duplication in the debug messages when accessing SCR registers. Remove duplication to make the messages neat. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 44dca8c..2d73cdf 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -414,16 +414,16 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) } *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, *val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, *val); return 0; } static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) { - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, val); if (scr > SCR_NOTIFICATION) { dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n", __func__, scr); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 21/23] ata: sata_dwc_460ex: use devm_ioremap
This simplifies error handling and cleanup by using devm to manage IO mappings. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 30 +++--- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 0ef72e4..44dca8c 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -139,7 +139,6 @@ struct sata_dwc_device { struct device *dev; /* generic device struct */ struct ata_probe_ent*pe;/* ptr to probe-ent */ struct ata_host *host; - u8 __iomem *reg_base; struct sata_dwc_regs __iomem *sata_dwc_regs;/* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; @@ -242,7 +241,7 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, struct sata_dwc_device *hsdev) { struct device_node *np = pdev->dev.of_node; - int err; + struct resource *res; hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); if (!hsdev->dma) @@ -258,21 +257,16 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, } /* Get physical SATA DMA register base address */ - hsdev->dma->regs = of_iomap(np, 1); - if (!hsdev->dma->regs) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hsdev->dma->regs)) { dev_err(&pdev->dev, "ioremap failed for AHBDMA register address\n"); - return -ENODEV; + return PTR_ERR(hsdev->dma->regs); } /* Initialize AHB DMAC */ - err = dw_dma_probe(hsdev->dma); - if (err) { - iounmap(hsdev->dma->regs); - return err; - } - - return 0; + return dw_dma_probe(hsdev->dma); } static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) @@ -281,7 +275,6 @@ static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) return; dw_dma_remove(hsdev->dma); - iounmap(hsdev->dma->regs); } #endif @@ -1221,6 +1214,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct ata_port_info pi = sata_dwc_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device_node *np = ofdev->dev.of_node; + struct resource *res; /* Allocate DWC SATA device */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); @@ -1231,13 +1225,13 @@ static int sata_dwc_probe(struct platform_device *ofdev) host->private_data = hsdev; /* Ioremap SATA registers */ - base = of_iomap(np, 0); - if (!base) { + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&ofdev->dev, res); + if (IS_ERR(base)) { dev_err(&ofdev->dev, "ioremap failed for SATA register address\n"); - return -ENODEV; + return PTR_ERR(base); } - hsdev->reg_base = base; dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ @@ -1302,7 +1296,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) error_out: phy_exit(hsdev->phy); - iounmap(base); return err; } @@ -1321,7 +1314,6 @@ static int sata_dwc_remove(struct platform_device *ofdev) sata_dwc_dma_exit_old(hsdev); #endif - iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v1 19/23] ata: sata_dwc_460ex: use readl/writel_relaxed()
From: Mans Rullgard Rename the register access macros and use standard _relaxed() ops instead of __raw variants with explicit byte swapping. The original driver used the ppc-specific in/out_le32(). When it was adapted to other systems, these were added to the driver under ifdefs. However, those names are not defined as macros on ppc, so it ended up replacing them there as well with altered semantics. This patch restores the original semantics on ppc and makes the accesses no less strict on other systems. Also fixes too many sparse warnings to count. Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 91 +--- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 229e122..2029f43 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -51,13 +51,8 @@ #define DRV_NAME"sata-dwc" #define DRV_VERSION "1.3" -#ifndef out_le32 -#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (void __iomem *)(a)) -#endif - -#ifndef in_le32 -#define in_le32(a) __le32_to_cpu(__raw_readl((void __iomem *)(a))) -#endif +#define sata_dwc_writel(a, v) writel_relaxed(v, a) +#define sata_dwc_readl(a) readl_relaxed(a) #ifndef NO_IRQ #define NO_IRQ 0 @@ -425,7 +420,7 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) return -EINVAL; } - *val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4)); + *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", __func__, link->ap->print_id, scr, *val); @@ -441,7 +436,7 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) __func__, scr); return -EINVAL; } - out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val); + sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val); return 0; } @@ -455,8 +450,8 @@ static void clear_serror(struct ata_port *ap) static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) { - out_le32(&hsdev->sata_dwc_regs->intpr, -in_le32(&hsdev->sata_dwc_regs->intpr)); + sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, + sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); } static u32 qcmd_tag_to_mask(u8 tag) @@ -532,7 +527,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) spin_lock_irqsave(&host->lock, flags); /* Read the interrupt register */ - intpr = in_le32(&hsdev->sata_dwc_regs->intpr); + intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr); ap = host->ports[port]; hsdevp = HSDEVP_FROM_AP(ap); @@ -551,7 +546,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (intpr & SATA_DWC_INTPR_NEWFP) { clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP); - tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr)); + tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr)); dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag); if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); @@ -736,13 +731,13 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), -SATA_DWC_DMACR_RX_CLEAR( -in_le32(&(hsdev->sata_dwc_regs->dmacr; + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_RX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), -SATA_DWC_DMACR_TX_CLEAR( -in_le32(&(hsdev->sata_dwc_regs->dmacr; + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else { /* * This should not happen, it indicates the driver is out of @@ -751,9 +746,9 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", __func__, tag, hsdevp->dma_pending[tag], - in_le32(&hsdev->sata_dwc_regs->dmacr)); - out_le32(&(hsdev->sata_dw
[PATCH v1 17/23] ata: sata_dwc_460ex: supply physical address of FIFO to DMA
DMA operates with physical addresses which is not exactly the same as ioremap() returns. Introduce variable to keep physical address of the SATA FIFO register and supply it when prepare DMA channel. Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 42248b2..7810405 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -100,7 +100,7 @@ struct sata_dwc_regs { u32 versionr; /* Version Register */ u32 idr;/* ID Register */ u32 unimpl[192];/* Unimplemented */ - u32 dmadr[256]; /* FIFO Locations in DMA Mode */ + u32 dmadr[256]; /* FIFO Locations in DMA Mode */ }; enum { @@ -149,6 +149,7 @@ struct sata_dwc_device { u32 sactive_issued; u32 sactive_queued; struct phy *phy; + phys_addr_t dmadr; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -380,15 +381,14 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd struct ata_port *ap = qc->ap; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); - dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr; struct dma_slave_config sconf; struct dma_async_tx_descriptor *desc; if (qc->dma_dir == DMA_DEV_TO_MEM) { - sconf.src_addr = addr; + sconf.src_addr = hsdev->dmadr; sconf.device_fc = false; } else {/* DMA_MEM_TO_DEV */ - sconf.dst_addr = addr; + sconf.dst_addr = hsdev->dmadr; sconf.device_fc = false; } @@ -411,8 +411,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd desc->callback = dma_dwc_xfer_done; desc->callback_param = hsdev; - dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", - __func__, qc->sg, qc->n_elem, &addr); + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__, + qc->sg, qc->n_elem, &hsdev->dmadr); return desc; } @@ -1249,6 +1249,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Synopsys DWC SATA specific Registers */ hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; + hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr); /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 02/23] ata: sata_dwc_460ex: fix crash on offline links without an attached drive
From: Christian Lamparter This patch fixes Machine Check "Data Write PLB Error" which happens when libata-sff's ata_sff_dev_select is trying to write into the device_addr in order to select a drive. However, SATA has no master or slave devices like the old ATA Bus, therefore selecting a different drive is kind of pointless. Data Write PLB Error Oops: Machine check, sig: 7 [#1] PowerPC 44x Platform Modules linked in: CPU: 0 PID: 508 Comm: scsi_eh_0 Not tainted 4.6.0-rc3-next-20160412+ #10 [...] NIP [c027e820] ata_sff_dev_select+0x3c/0x44 LR [c027e810] ata_sff_dev_select+0x2c/0x44 Call Trace: [cec31cd0] [c027da00] ata_sff_postreset+0x40/0xb4 (unreliable) [cec31ce0] [c027a03c] ata_eh_reset+0x5cc/0x928 [cec31d60] [c027a840] ata_eh_recover+0x330/0x10bc [cec31df0] [c027bae0] ata_do_eh+0x4c/0xa4 [...] Signed-off-by: Christian Lamparter --- drivers/ata/sata_dwc_460ex.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 5213e22..7f95389 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1134,6 +1134,11 @@ static int sata_dwc_hardreset(struct ata_link *link, unsigned int *class, return ret; } +static void sata_dwc_dev_select(struct ata_port *ap, unsigned int device) +{ + /* SATA DWC is master only */ +} + /* * scsi mid-layer and libata interface structures */ @@ -1164,6 +1169,8 @@ static struct ata_port_operations sata_dwc_ops = { .port_start = sata_dwc_port_start, .port_stop = sata_dwc_port_stop, + .sff_dev_select = sata_dwc_dev_select, + .bmdma_setup= sata_dwc_bmdma_setup, .bmdma_start= sata_dwc_bmdma_start, }; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 00/23] ata: sata_dwc_460ex: make it working again
The last approach in the commit 8b3444852a2b ("sata_dwc_460ex: move to generic DMA driver") to switch to generic DMA engine API wasn't tested on bare metal. Besides that we expecting new board support coming with the same SATA IP but with different DMA. This series is targetting the following things: - a few bug fixes to the original driver - a part to fix the DMA engine usage and in particularly dw_dmac driver - move driver to use generic PHY and "dmas" property which leads to update in DTS The driver has been tested myself on Sam460ex and WD MyBookLive (apollo3g) boards. In any case I ask Christian, Måns, and Julian to independently test and provide Tested-by tag or an error report. Series depends on previously published but not yet fully applied series [1]. The patches are also available via public branch [2]. [1] http://www.spinics.net/lists/dmaengine/msg09250.html [2] https://bitbucket.org/andy-shev/linux/branch/topic%2Fdw%2Fsata Since v1: - simplify patch 8 (David Laight) - add Tested-by and Acked-by tags Andy Shevchenko (11): ata: sata_dwc_460ex: set dma_boundary to 0x1fff ata: sata_dwc_460ex: burst size must be in items not bytes ata: sata_dwc_460ex: DMA is always a flow controller ata: sata_dwc_460ex: select only core part of DMA driver ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros ata: sata_dwc_460ex: supply physical address of FIFO to DMA ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API ata: sata_dwc_460ex: use devm_ioremap ata: sata_dwc_460ex: make debug messages neat powerpc/4xx: Device tree update for the 460ex DWC SATA Christian Lamparter (1): ata: sata_dwc_460ex: fix crash on offline links without an attached drive Mans Rullgard (11): ata: sata_dwc_460ex: remove incorrect locking ata: sata_dwc_460ex: skip dma setup for non-dma commands ata: sata_dwc_460ex: use "dmas" DT property to find dma channel ata: sata_dwc_460ex: add phy support ata: sata_dwc_460ex: get rid of global data ata: sata_dwc_460ex: remove empty libata callback ata: sata_dwc_460ex: get rid of some pointless casts ata: sata_dwc_460ex: get rid of incorrect cast ata: sata_dwc_460ex: add __iomem to register base pointer ata: sata_dwc_460ex: use readl/writel_relaxed() ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr() arch/powerpc/boot/dts/canyonlands.dts | 15 +- drivers/ata/Kconfig | 12 +- drivers/ata/sata_dwc_460ex.c | 552 +- 3 files changed, 305 insertions(+), 274 deletions(-) -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 03/23] ata: sata_dwc_460ex: set dma_boundary to 0x1fff
The original code states: Make sure a LLI block is not created that will span 8K max FIS boundary. If the block spans such a FIS boundary, there is a chance that a DMA burst will cross that boundary -- this results in an error in the host controller. Since we have switched to generic DMAengine API we satisfy above by setting dma_boundary value to 0x1fff. Suggested-by: Mans Rullgard Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7f95389..aee8873 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1151,7 +1151,13 @@ static struct scsi_host_template sata_dwc_sht = { */ .sg_tablesize = LIBATA_MAX_PRD, /* .can_queue = ATA_MAX_QUEUE, */ - .dma_boundary = ATA_DMA_BOUNDARY, + /* +* Make sure a LLI block is not created that will span 8K max FIS +* boundary. If the block spans such a FIS boundary, there is a chance +* that a DMA burst will cross that boundary -- this results in an +* error in the host controller. +*/ + .dma_boundary = 0x1fff /* ATA_DMA_BOUNDARY */, }; static struct ata_port_operations sata_dwc_ops = { -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 06/23] ata: sata_dwc_460ex: select only core part of DMA driver
There is no need to have a platform driver compiled since the DMA driver is used as a library. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index cfa936a..7c6e43a 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -314,7 +314,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" depends on 460EX - select DW_DMAC + select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 08/23] ata: sata_dwc_460ex: don't call ata_sff_qc_issue() on DMA commands
ata_sff_qc_issue() can't handle DMA commands and thus we have to avoid it for them. Do call ata_bmdma_qc_issue() instead for this case. Note that the former one distinguishes PIO and DMA mode and behaves accordingly. Suggested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 038e5fb..f1a4d49 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1061,10 +1061,10 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) __func__, tag, qc->ap->link.sactive, sactive); ap->ops->sff_tf_load(ap, &qc->tf); - sata_dwc_exec_command_by_tag(ap, &qc->tf, qc->tag, + sata_dwc_exec_command_by_tag(ap, &qc->tf, tag, SATA_DWC_CMD_ISSUED_PEND); } else { - ata_sff_qc_issue(qc); + return ata_bmdma_qc_issue(qc); } return 0; } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 05/23] ata: sata_dwc_460ex: DMA is always a flow controller
In the original code the DMA is always a flow controller. Set this accordingly in updated code. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4cac27d..1250e18 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -311,7 +311,7 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd if (qc->dma_dir == DMA_DEV_TO_MEM) { sconf.src_addr = addr; - sconf.device_fc = true; + sconf.device_fc = false; } else {/* DMA_MEM_TO_DEV */ sconf.dst_addr = addr; sconf.device_fc = false; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 09/23] ata: sata_dwc_460ex: use "dmas" DT property to find dma channel
From: Mans Rullgard Currently this driver only works with a DesignWare DMA engine which it registers manually using the second "reg" address range and interrupt number from the DT node. This patch makes the driver instead use the "dmas" property if present, otherwise optionally falling back on the old way so existing device trees can continue to work. With this change, there is no longer any reason to depend on the 460EX machine type so drop that from Kconfig. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/Kconfig | 11 ++- drivers/ata/sata_dwc_460ex.c | 198 --- 2 files changed, 138 insertions(+), 71 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 7c6e43a..ede126d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -313,14 +313,21 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" - depends on 460EX - select DW_DMAC_CORE help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. If unsure, say N. +config SATA_DWC_OLD_DMA + bool "Support old device trees" + depends on SATA_DWC + select DW_DMAC_CORE + default y if 460EX + help + This option enables support for old device trees without the + "dmas" property. + config SATA_DWC_DEBUG bool "Debugging driver version" depends on SATA_DWC diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index f1a4d49..200af36 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -42,10 +43,6 @@ #include #include -/* Supported DMA engine drivers */ -#include -#include - /* These two are defined in "libata.h" */ #undef DRV_NAME #undef DRV_VERSION @@ -148,7 +145,9 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ +#ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; +#endif }; #define SATA_DWC_QCMD_MAX 32 @@ -159,7 +158,6 @@ struct sata_dwc_device_port { int dma_pending[SATA_DWC_QCMD_MAX]; /* DMA info */ - struct dw_dma_slave *dws; struct dma_chan *chan; struct dma_async_tx_descriptor *desc[SATA_DWC_QCMD_MAX]; u32 dma_interrupt_count; @@ -198,13 +196,6 @@ struct sata_dwc_host_priv { static struct sata_dwc_host_priv host_pvt; -static struct dw_dma_slave sata_dwc_dma_dws = { - .src_id = 0, - .dst_id = 0, - .m_master = 1, - .p_master = 0, -}; - /* * Prototypes */ @@ -215,6 +206,99 @@ static void sata_dwc_dma_xfer_complete(struct ata_port *ap, u32 check_status); static void sata_dwc_port_stop(struct ata_port *ap); static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag); +#ifdef CONFIG_SATA_DWC_OLD_DMA + +#include +#include + +static struct dw_dma_slave sata_dwc_dma_dws = { + .src_id = 0, + .dst_id = 0, + .m_master = 1, + .p_master = 0, +}; + +static bool sata_dwc_dma_filter(struct dma_chan *chan, void *param) +{ + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + + if (dws->dma_dev != chan->device->dev) + return false; + + chan->private = dws; + return true; +} + +static int sata_dwc_dma_get_channel_old(struct sata_dwc_device_port *hsdevp) +{ + struct sata_dwc_device *hsdev = hsdevp->hsdev; + struct dw_dma_slave *dws = &sata_dwc_dma_dws; + dma_cap_mask_t mask; + + dws->dma_dev = hsdev->dev; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + /* Acquire DMA channel */ + hsdevp->chan = dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); + if (!hsdevp->chan) { + dev_err(hsdev->dev, "%s: dma channel unavailable\n", +__func__); + return -EAGAIN; + } + + return 0; +} + +static int sata_dwc_dma_init_old(struct platform_device *pdev, +struct sata_dwc_device *hsdev) +{ + struct device_node *np = pdev->dev.of_node; + int err; + + hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); + if (!hsdev->dma) + return -ENOMEM; + + hsdev->dma->dev = &pdev->dev; + + /* Get SATA DMA interrupt number */ + hsdev->dma->irq = irq_of_parse_and_map(np, 1); + if (hsdev->dma->irq == NO_IRQ) { + dev_err(&pdev->dev, "no SATA DMA irq\n"); + return -ENODEV; + } + + /* Get physical SATA DMA register base address */ + hsdev->dma->regs = of_iomap(np, 1); + if (!h
[PATCH v2 10/23] ata: sata_dwc_460ex: add phy support
From: Mans Rullgard This adds support for powering on an optional PHY when activating the device. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/Kconfig | 1 + drivers/ata/sata_dwc_460ex.c | 22 ++ 2 files changed, 23 insertions(+) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index ede126d..41b0725 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -313,6 +313,7 @@ config ATA_PIIX config SATA_DWC tristate "DesignWare Cores SATA support" + select GENERIC_PHY help This option enables support for the on-chip SATA controller of the AppliedMicro processor 460EX. diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 200af36..4b8eded 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -145,6 +146,7 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -948,6 +950,10 @@ static int sata_dwc_port_start(struct ata_port *ap) if (err) goto CLEANUP_ALLOC; + err = phy_power_on(hsdev->phy); + if (err) + goto CLEANUP_ALLOC; + for (i = 0; i < SATA_DWC_QCMD_MAX; i++) hsdevp->cmd_issued[i] = SATA_DWC_CMD_ISSUED_NOT; @@ -983,11 +989,13 @@ CLEANUP: static void sata_dwc_port_stop(struct ata_port *ap) { struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); + struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); dmaengine_terminate_all(hsdevp->chan); dma_release_channel(hsdevp->chan); + phy_power_off(hsdev->phy); kfree(hsdevp); ap->private_data = NULL; @@ -1321,6 +1329,17 @@ static int sata_dwc_probe(struct platform_device *ofdev) } #endif + hsdev->phy = devm_phy_optional_get(hsdev->dev, "sata-phy"); + if (IS_ERR(hsdev->phy)) { + err = PTR_ERR(hsdev->phy); + hsdev->phy = NULL; + goto error_out; + } + + err = phy_init(hsdev->phy); + if (err) + goto error_out; + /* * Now, register with libATA core, this will also initiate the * device discovery process, invoking our port_start() handler & @@ -1334,6 +1353,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) return 0; error_out: + phy_exit(hsdev->phy); iounmap(base); return err; } @@ -1346,6 +1366,8 @@ static int sata_dwc_remove(struct platform_device *ofdev) ata_host_detach(host); + phy_exit(hsdev->phy); + #ifdef CONFIG_SATA_DWC_OLD_DMA /* Free SATA DMA resources */ sata_dwc_dma_exit_old(hsdev); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 12/23] ata: sata_dwc_460ex: correct HOSTDEV{P}_FROM_*() macros
Here we refactor HOSTDEV{P}_FROM_*() macros to fit one line and fix the definition of HSDEV_FROM_HSDEVP() where wrong name of the parameter waas used. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 17 ++--- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 24837d6..2258baf 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -168,18 +168,13 @@ struct sata_dwc_device_port { }; /* - * Commonly used DWC SATA driver Macros + * Commonly used DWC SATA driver macros */ -#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)\ - (host)->private_data) -#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)\ - (ap)->host->private_data) -#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)\ - (ap)->private_data) -#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)\ - (qc)->ap->host->private_data) -#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)\ - (hsdevp)->hsdev) +#define HSDEV_FROM_HOST(host) ((struct sata_dwc_device *)(host)->private_data) +#define HSDEV_FROM_AP(ap) ((struct sata_dwc_device *)(ap)->host->private_data) +#define HSDEVP_FROM_AP(ap) ((struct sata_dwc_device_port *)(ap)->private_data) +#define HSDEV_FROM_QC(qc) ((struct sata_dwc_device *)(qc)->ap->host->private_data) +#define HSDEV_FROM_HSDEVP(p) ((struct sata_dwc_device *)(p)->hsdev) enum { SATA_DWC_CMD_ISSUED_NOT = 0, -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 15/23] ata: sata_dwc_460ex: get rid of incorrect cast
From: Mans Rullgard The (void *__iomem) cast is wrong. Change the target type of the "base" pointer to void __iomem instead and drop the cast. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2912e4d..90e3e14 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1219,7 +1219,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct sata_dwc_device *hsdev; u32 idr, versionr; char *ver = (char *)&versionr; - u8 __iomem *base; + void __iomem *base; int err = 0; int irq; struct ata_host *host; @@ -1246,7 +1246,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ - hsdev->sata_dwc_regs = (void *__iomem)(base + SATA_DWC_REG_OFFSET); + hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 14/23] ata: sata_dwc_460ex: get rid of some pointless casts
From: Mans Rullgard Casting a pointer to unsigned long only to immediately cast it back to a pointer makes no sense. Fix this. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 30 +++--- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 3a9dd82..2912e4d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -844,26 +844,26 @@ static void sata_dwc_enable_interrupts(struct sata_dwc_device *hsdev) in_le32(&hsdev->sata_dwc_regs->errmr)); } -static void sata_dwc_setup_port(struct ata_ioports *port, unsigned long base) +static void sata_dwc_setup_port(struct ata_ioports *port, void __iomem *base) { - port->cmd_addr = (void __iomem *)base + 0x00; - port->data_addr = (void __iomem *)base + 0x00; + port->cmd_addr = base + 0x00; + port->data_addr = base + 0x00; - port->error_addr = (void __iomem *)base + 0x04; - port->feature_addr = (void __iomem *)base + 0x04; + port->error_addr= base + 0x04; + port->feature_addr = base + 0x04; - port->nsect_addr = (void __iomem *)base + 0x08; + port->nsect_addr= base + 0x08; - port->lbal_addr = (void __iomem *)base + 0x0c; - port->lbam_addr = (void __iomem *)base + 0x10; - port->lbah_addr = (void __iomem *)base + 0x14; + port->lbal_addr = base + 0x0c; + port->lbam_addr = base + 0x10; + port->lbah_addr = base + 0x14; - port->device_addr = (void __iomem *)base + 0x18; - port->command_addr = (void __iomem *)base + 0x1c; - port->status_addr = (void __iomem *)base + 0x1c; + port->device_addr = base + 0x18; + port->command_addr = base + 0x1c; + port->status_addr = base + 0x1c; - port->altstatus_addr = (void __iomem *)base + 0x20; - port->ctl_addr = (void __iomem *)base + 0x20; + port->altstatus_addr= base + 0x20; + port->ctl_addr = base + 0x20; } static int sata_dwc_dma_get_channel(struct sata_dwc_device_port *hsdevp) @@ -1251,7 +1251,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; host->ports[0]->ioaddr.scr_addr = base + SATA_DWC_SCR_OFFSET; - sata_dwc_setup_port(&host->ports[0]->ioaddr, (unsigned long)base); + sata_dwc_setup_port(&host->ports[0]->ioaddr, base); /* Read the ID and Version Registers */ idr = in_le32(&hsdev->sata_dwc_regs->idr); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 13/23] ata: sata_dwc_460ex: remove empty libata callback
From: Mans Rullgard The sata_dwc_qc_prep() does nothing. Use the default ata_noop_qc_prep instead. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 22 -- 1 file changed, 22 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2258baf..3a9dd82 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1132,27 +1132,6 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) return 0; } -/* - * Function : sata_dwc_qc_prep - * arguments : ata_queued_cmd *qc - * Return value : None - * qc_prep for a particular queued command - */ - -static void sata_dwc_qc_prep(struct ata_queued_cmd *qc) -{ - if ((qc->dma_dir == DMA_NONE) || (qc->tf.protocol == ATA_PROT_PIO)) - return; - -#ifdef DEBUG_NCQ - if (qc->tag > 0) - dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n", -__func__, qc->tag, qc->ap->link.active_tag); - - return ; -#endif -} - static void sata_dwc_error_handler(struct ata_port *ap) { ata_sff_error_handler(ap); @@ -1212,7 +1191,6 @@ static struct ata_port_operations sata_dwc_ops = { .error_handler = sata_dwc_error_handler, .hardreset = sata_dwc_hardreset, - .qc_prep= sata_dwc_qc_prep, .qc_issue = sata_dwc_qc_issue, .scr_read = sata_dwc_scr_read, -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 20/23] ata: sata_dwc_460ex: tidy up sata_dwc_clear_dmacr()
From: Mans Rullgard This consolidates the reads from each of the if/else branches to one place making the code a lot nicer to look at. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 14 ++ 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2e3222f..92f4008 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -729,15 +729,14 @@ DONE: static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) { struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); + u32 dmacr = sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_RX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_RX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, - SATA_DWC_DMACR_TX_CLEAR( - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); + dmacr = SATA_DWC_DMACR_TX_CLEAR(dmacr); + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, dmacr); } else { /* * This should not happen, it indicates the driver is out of @@ -745,8 +744,7 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) */ dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", - __func__, tag, hsdevp->dma_pending[tag], - sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr)); + __func__, tag, hsdevp->dma_pending[tag], dmacr); sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, SATA_DWC_DMACR_TXRXCH_CLEAR); } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 17/23] ata: sata_dwc_460ex: supply physical address of FIFO to DMA
DMA operates with physical addresses which is not exactly the same as ioremap() returns. Introduce variable to keep physical address of the SATA FIFO register and supply it when prepare DMA channel. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 25e00f2..7b73728 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -100,7 +100,7 @@ struct sata_dwc_regs { u32 versionr; /* Version Register */ u32 idr;/* ID Register */ u32 unimpl[192];/* Unimplemented */ - u32 dmadr[256]; /* FIFO Locations in DMA Mode */ + u32 dmadr[256]; /* FIFO Locations in DMA Mode */ }; enum { @@ -149,6 +149,7 @@ struct sata_dwc_device { u32 sactive_issued; u32 sactive_queued; struct phy *phy; + phys_addr_t dmadr; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; #endif @@ -380,15 +381,14 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd struct ata_port *ap = qc->ap; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap); - dma_addr_t addr = (dma_addr_t)&hsdev->sata_dwc_regs->dmadr; struct dma_slave_config sconf; struct dma_async_tx_descriptor *desc; if (qc->dma_dir == DMA_DEV_TO_MEM) { - sconf.src_addr = addr; + sconf.src_addr = hsdev->dmadr; sconf.device_fc = false; } else {/* DMA_MEM_TO_DEV */ - sconf.dst_addr = addr; + sconf.dst_addr = hsdev->dmadr; sconf.device_fc = false; } @@ -411,8 +411,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd desc->callback = dma_dwc_xfer_done; desc->callback_param = hsdev; - dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pad\n", - __func__, qc->sg, qc->n_elem, &addr); + dev_dbg(hsdev->dev, "%s sg: 0x%p, count: %d addr: %pa\n", __func__, + qc->sg, qc->n_elem, &hsdev->dmadr); return desc; } @@ -1247,6 +1247,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) /* Synopsys DWC SATA specific Registers */ hsdev->sata_dwc_regs = base + SATA_DWC_REG_OFFSET; + hsdev->dmadr = res->start + SATA_DWC_REG_OFFSET + offsetof(struct sata_dwc_regs, dmadr); /* Setup port */ host->ports[0]->ioaddr.cmd_addr = base; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 19/23] ata: sata_dwc_460ex: use readl/writel_relaxed()
From: Mans Rullgard Rename the register access macros and use standard _relaxed() ops instead of __raw variants with explicit byte swapping. The original driver used the ppc-specific in/out_le32(). When it was adapted to other systems, these were added to the driver under ifdefs. However, those names are not defined as macros on ppc, so it ended up replacing them there as well with altered semantics. This patch restores the original semantics on ppc and makes the accesses no less strict on other systems. Also fixes too many sparse warnings to count. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 91 +--- 1 file changed, 43 insertions(+), 48 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 113cb3a..2e3222f 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -51,13 +51,8 @@ #define DRV_NAME"sata-dwc" #define DRV_VERSION "1.3" -#ifndef out_le32 -#define out_le32(a, v) __raw_writel(__cpu_to_le32(v), (void __iomem *)(a)) -#endif - -#ifndef in_le32 -#define in_le32(a) __le32_to_cpu(__raw_readl((void __iomem *)(a))) -#endif +#define sata_dwc_writel(a, v) writel_relaxed(v, a) +#define sata_dwc_readl(a) readl_relaxed(a) #ifndef NO_IRQ #define NO_IRQ 0 @@ -425,7 +420,7 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) return -EINVAL; } - *val = in_le32(link->ap->ioaddr.scr_addr + (scr * 4)); + *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", __func__, link->ap->print_id, scr, *val); @@ -441,7 +436,7 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) __func__, scr); return -EINVAL; } - out_le32(link->ap->ioaddr.scr_addr + (scr * 4), val); + sata_dwc_writel(link->ap->ioaddr.scr_addr + (scr * 4), val); return 0; } @@ -455,8 +450,8 @@ static void clear_serror(struct ata_port *ap) static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) { - out_le32(&hsdev->sata_dwc_regs->intpr, -in_le32(&hsdev->sata_dwc_regs->intpr)); + sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, + sata_dwc_readl(&hsdev->sata_dwc_regs->intpr)); } static u32 qcmd_tag_to_mask(u8 tag) @@ -532,7 +527,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) spin_lock_irqsave(&host->lock, flags); /* Read the interrupt register */ - intpr = in_le32(&hsdev->sata_dwc_regs->intpr); + intpr = sata_dwc_readl(&hsdev->sata_dwc_regs->intpr); ap = host->ports[port]; hsdevp = HSDEVP_FROM_AP(ap); @@ -551,7 +546,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (intpr & SATA_DWC_INTPR_NEWFP) { clear_interrupt_bit(hsdev, SATA_DWC_INTPR_NEWFP); - tag = (u8)(in_le32(&hsdev->sata_dwc_regs->fptagr)); + tag = (u8)(sata_dwc_readl(&hsdev->sata_dwc_regs->fptagr)); dev_dbg(ap->dev, "%s: NEWFP tag=%d\n", __func__, tag); if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); @@ -736,13 +731,13 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) struct sata_dwc_device *hsdev = HSDEV_FROM_HSDEVP(hsdevp); if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_RX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), -SATA_DWC_DMACR_RX_CLEAR( -in_le32(&(hsdev->sata_dwc_regs->dmacr; + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_RX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else if (hsdevp->dma_pending[tag] == SATA_DWC_DMA_PENDING_TX) { - out_le32(&(hsdev->sata_dwc_regs->dmacr), -SATA_DWC_DMACR_TX_CLEAR( -in_le32(&(hsdev->sata_dwc_regs->dmacr; + sata_dwc_writel(&hsdev->sata_dwc_regs->dmacr, + SATA_DWC_DMACR_TX_CLEAR( + sata_dwc_readl(&hsdev->sata_dwc_regs->dmacr))); } else { /* * This should not happen, it indicates the driver is out of @@ -751,9 +746,9 @@ static void sata_dwc_clear_dmacr(struct sata_dwc_device_port *hsdevp, u8 tag) dev_err(hsdev->dev, "%s DMA protocol RX and TX DMA not pending tag=0x%02x pending=%d dmacr: 0x%08x\n", __func__, tag, hsdevp->dma_pending[tag], - in_le32(&hsdev->sata_dwc_regs->dmacr)); -
[PATCH v2 11/23] ata: sata_dwc_460ex: get rid of global data
From: Mans Rullgard This moves all global data into the driver private struct, thus permitting multiple devices of this type to be used. The core_scr_read/write() functions are replaced with equivalent calls to the existing sata_dwc_scr_read/write(). Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 79 1 file changed, 29 insertions(+), 50 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 4b8eded..24837d6 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -146,6 +146,8 @@ struct sata_dwc_device { struct ata_host *host; u8 __iomem *reg_base; struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + u32 sactive_issued; + u32 sactive_queued; struct phy *phy; #ifdef CONFIG_SATA_DWC_OLD_DMA struct dw_dma_chip *dma; @@ -190,14 +192,6 @@ enum { SATA_DWC_DMA_PENDING_RX = 2, }; -struct sata_dwc_host_priv { - void__iomem *scr_addr_sstatus; - u32 sata_dwc_sactive_issued ; - u32 sata_dwc_sactive_queued ; -}; - -static struct sata_dwc_host_priv host_pvt; - /* * Prototypes */ @@ -457,21 +451,11 @@ static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) return 0; } -static u32 core_scr_read(unsigned int scr) -{ - return in_le32(host_pvt.scr_addr_sstatus + (scr * 4)); -} - -static void core_scr_write(unsigned int scr, u32 val) -{ - out_le32(host_pvt.scr_addr_sstatus + (scr * 4), val); -} - -static void clear_serror(void) +static void clear_serror(struct ata_port *ap) { u32 val; - val = core_scr_read(SCR_ERROR); - core_scr_write(SCR_ERROR, val); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &val); + sata_dwc_scr_write(&ap->link, SCR_ERROR, val); } static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit) @@ -498,7 +482,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, ata_ehi_clear_desc(ehi); - serror = core_scr_read(SCR_ERROR); + sata_dwc_scr_read(&ap->link, SCR_ERROR, &serror); status = ap->ops->sff_check_status(ap); tag = ap->link.active_tag; @@ -509,7 +493,7 @@ static void sata_dwc_error_intr(struct ata_port *ap, hsdevp->dma_pending[tag], hsdevp->cmd_issued[tag]); /* Clear error register and interrupt bit */ - clear_serror(); + clear_serror(ap); clear_interrupt_bit(hsdev, SATA_DWC_INTPR_ERR); /* This is the only error happening now. TODO check for exact error */ @@ -548,7 +532,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) int handled, num_processed, port = 0; uint intpr, sactive, sactive2, tag_mask; struct sata_dwc_device_port *hsdevp; - host_pvt.sata_dwc_sactive_issued = 0; + hsdev->sactive_issued = 0; spin_lock_irqsave(&host->lock, flags); @@ -577,7 +561,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) if (hsdevp->cmd_issued[tag] != SATA_DWC_CMD_ISSUED_PEND) dev_warn(ap->dev, "CMD tag=%d not pending?\n", tag); - host_pvt.sata_dwc_sactive_issued |= qcmd_tag_to_mask(tag); + hsdev->sactive_issued |= qcmd_tag_to_mask(tag); qc = ata_qc_from_tag(ap, tag); /* @@ -591,11 +575,11 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance) handled = 1; goto DONE; } - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; /* If no sactive issued and tag_mask is zero then this is not NCQ */ - if (host_pvt.sata_dwc_sactive_issued == 0 && tag_mask == 0) { + if (hsdev->sactive_issued == 0 && tag_mask == 0) { if (ap->link.active_tag == ATA_TAG_POISON) tag = 0; else @@ -665,22 +649,19 @@ DRVSTILLBUSY: */ /* process completed commands */ - sactive = core_scr_read(SCR_ACTIVE); - tag_mask = (host_pvt.sata_dwc_sactive_issued | sactive) ^ sactive; + sata_dwc_scr_read(&ap->link, SCR_ACTIVE, &sactive); + tag_mask = (hsdev->sactive_issued | sactive) ^ sactive; - if (sactive != 0 || (host_pvt.sata_dwc_sactive_issued) > 1 || \ - tag_mask > 1) { + if (sactive != 0 || hsdev->sactive_issued > 1 || tag_mask > 1) { dev_dbg(ap->dev, "%s NCQ:sactive=0x%08x sactive_issued=0x%08x tag_mask=0x%08x\n", - __func__, sactive, host_pv
[PATCH v2 16/23] ata: sata_dwc_460ex: add __iomem to register base pointer
From: Mans Rullgard The pointer to the mmio register base is missing the __iomem annotation. Fix this. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 90e3e14..25e00f2 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -145,7 +145,7 @@ struct sata_dwc_device { struct ata_probe_ent*pe;/* ptr to probe-ent */ struct ata_host *host; u8 __iomem *reg_base; - struct sata_dwc_regs*sata_dwc_regs; /* DW Synopsys SATA specific */ + struct sata_dwc_regs __iomem *sata_dwc_regs;/* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; struct phy *phy; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 22/23] ata: sata_dwc_460ex: make debug messages neat
There is a duplication in the debug messages when accessing SCR registers. Remove duplication to make the messages neat. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 6f145f8..00c2af1 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -414,16 +414,16 @@ static int sata_dwc_scr_read(struct ata_link *link, unsigned int scr, u32 *val) } *val = sata_dwc_readl(link->ap->ioaddr.scr_addr + (scr * 4)); - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, *val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, *val); return 0; } static int sata_dwc_scr_write(struct ata_link *link, unsigned int scr, u32 val) { - dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=val=0x%08x\n", - __func__, link->ap->print_id, scr, val); + dev_dbg(link->ap->dev, "%s: id=%d reg=%d val=0x%08x\n", __func__, + link->ap->print_id, scr, val); if (scr > SCR_NOTIFICATION) { dev_err(link->ap->dev, "%s: Incorrect SCR offset 0x%02x\n", __func__, scr); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 04/23] ata: sata_dwc_460ex: burst size must be in items not bytes
The burst size as defined by DMAengine API is in items of address width. Derive burst size from AHB_DMA_BRST_DFLT (64 bytes) by dividing it to DMA_SLAVE_BUSWIDTH_4_BYTES (4 bytes) that gives us 16 items. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index aee8873..4cac27d 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -65,7 +65,7 @@ #define NO_IRQ 0 #endif -#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length*/ +#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length */ enum { SATA_DWC_MAX_PORTS = 1, @@ -318,8 +318,8 @@ static struct dma_async_tx_descriptor *dma_dwc_xfer_setup(struct ata_queued_cmd } sconf.direction = qc->dma_dir; - sconf.src_maxburst = AHB_DMA_BRST_DFLT; - sconf.dst_maxburst = AHB_DMA_BRST_DFLT; + sconf.src_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ + sconf.dst_maxburst = AHB_DMA_BRST_DFLT / 4; /* in items */ sconf.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; sconf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 07/23] ata: sata_dwc_460ex: skip dma setup for non-dma commands
From: Mans Rullgard Calling dmaengine_prep_slave_sg() for non-dma ATA commands is unnecessary at best and could be harmful if the dma driver reacts badly to this. It also causes this driver to print a bogus error message in these cases. This patch changes sata_dwc_qc_issue() to only do the dma setup for dma commands and also reports an error to libata if if fails. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 35 +-- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 1250e18..038e5fb 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -1023,36 +1023,12 @@ static void sata_dwc_bmdma_start(struct ata_queued_cmd *qc) sata_dwc_bmdma_start_by_tag(qc, tag); } -/* - * Function : sata_dwc_qc_prep_by_tag - * arguments : ata_queued_cmd *qc, u8 tag - * Return value : None - * qc_prep for a particular queued command based on tag - */ -static void sata_dwc_qc_prep_by_tag(struct ata_queued_cmd *qc, u8 tag) -{ - struct dma_async_tx_descriptor *desc; - struct ata_port *ap = qc->ap; - struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); - - dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n", - __func__, ap->port_no, get_dma_dir_descript(qc->dma_dir), -qc->n_elem); - - desc = dma_dwc_xfer_setup(qc); - if (!desc) { - dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns NULL\n", - __func__); - return; - } - hsdevp->desc[tag] = desc; -} - static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) { u32 sactive; u8 tag = qc->tag; struct ata_port *ap = qc->ap; + struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); #ifdef DEBUG_NCQ if (qc->tag > 0 || ap->link.sactive > 1) @@ -1066,7 +1042,14 @@ static unsigned int sata_dwc_qc_issue(struct ata_queued_cmd *qc) if (!ata_is_ncq(qc->tf.protocol)) tag = 0; - sata_dwc_qc_prep_by_tag(qc, tag); + + if (ata_is_dma(qc->tf.protocol)) { + hsdevp->desc[tag] = dma_dwc_xfer_setup(qc); + if (!hsdevp->desc[tag]) + return AC_ERR_SYSTEM; + } else { + hsdevp->desc[tag] = NULL; + } if (ata_is_ncq(qc->tf.protocol)) { sactive = core_scr_read(SCR_ACTIVE); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 23/23] powerpc/4xx: Device tree update for the 460ex DWC SATA
Device tree update for the Applied micro processor 460ex on-chip SATA to use "dmas" property. Acked-by: Rob Herring Signed-off-by: Andy Shevchenko --- arch/powerpc/boot/dts/canyonlands.dts | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/boot/dts/canyonlands.dts b/arch/powerpc/boot/dts/canyonlands.dts index 3dc75de..549c24c 100644 --- a/arch/powerpc/boot/dts/canyonlands.dts +++ b/arch/powerpc/boot/dts/canyonlands.dts @@ -190,12 +190,21 @@ /* DMA */ 0x2 &UIC0 0xc 0x4>; }; + AHBDMA: dma@bffd0800 { + compatible = "snps,dma-spear1340"; + reg = <4 0xbffd0800 0x400>; + interrupt-parent = <&UIC3>; + interrupts = <0x5 0x4>; + #dma-cells = <3>; + }; + SATA0: sata@bffd1000 { compatible = "amcc,sata-460ex"; - reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>; + reg = <4 0xbffd1000 0x800>; interrupt-parent = <&UIC3>; - interrupts = <0x0 0x4 /* SATA */ - 0x5 0x4>; /* AHBDMA */ + interrupts = <0x0 0x4>; + dmas = <&AHBDMA 0 1 0>; + dma-names = "sata-dma"; }; POB0: opb { -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 01/23] ata: sata_dwc_460ex: remove incorrect locking
From: Mans Rullgard This lock is already taken in ata_scsi_queuecmd() a few levels up the call stack so attempting to take it here is an error. Moreover, it is pointless in the first place since it only protects a single, atomic assignment. Enabling lock debugging gives the following output: = [ INFO: possible recursive locking detected ] 4.4.0-rc5+ #189 Not tainted - kworker/u2:3/37 is trying to acquire lock: (&(&host->lock)->rlock){-.-...}, at: [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c but task is already holding lock: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 other info that might help us debug this: Possible unsafe locking scenario: CPU0 lock(&(&host->lock)->rlock); lock(&(&host->lock)->rlock); *** DEADLOCK *** May be due to missing lock nesting notation 4 locks held by kworker/u2:3/37: #0: ("events_unbound"){.+.+.+}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #1: ((&entry->work)){+.+.+.}, at: [<9003a0a4>] process_one_work+0x12c/0x430 #2: (&bdev->bd_mutex){+.+.+.}, at: [<9011fd54>] __blkdev_get+0x50/0x380 #3: (&(&host->lock)->rlock){-.-...}, at: [<902761ac>] ata_scsi_queuecmd+0x2c/0x330 stack backtrace: CPU: 0 PID: 37 Comm: kworker/u2:3 Not tainted 4.4.0-rc5+ #189 Workqueue: events_unbound async_run_entry_fn Stack : 90b38e30 0021 0003 9b2a6040 9005f3f0 904fc8dc 0025 906b96e4 90528648 9b3336c4 904fc8dc 9009bf18 0002 0004 9b3336c4 9b3336e4 904fc8dc 9003d074 9050 9005e738 6e657665 755f7374 756f626e 646e 9b00ca00 9b025000 ... Call Trace: [<90009d6c>] show_stack+0x88/0xa4 [<90057744>] __lock_acquire+0x1ce8/0x2154 [<900583e4>] lock_acquire+0x64/0x8c [<9045ff10>] _raw_spin_lock_irqsave+0x54/0x78 [<90283294>] sata_dwc_exec_command_by_tag.constprop.14+0x44/0x8c [<90283484>] sata_dwc_qc_issue+0x1a8/0x24c [<9026b39c>] ata_qc_issue+0x1f0/0x410 [<90273c6c>] ata_scsi_translate+0xb4/0x200 [<90276234>] ata_scsi_queuecmd+0xb4/0x330 [<9025800c>] scsi_dispatch_cmd+0xd0/0x128 [<90259934>] scsi_request_fn+0x58c/0x638 [<901a3e50>] __blk_run_queue+0x40/0x5c [<901a83d4>] blk_queue_bio+0x27c/0x28c [<901a5914>] generic_make_request+0xf0/0x188 [<901a5a54>] submit_bio+0xa8/0x194 [<9011adcc>] submit_bh_wbc.isra.23+0x15c/0x17c [<9011c908>] block_read_full_page+0x3e4/0x428 [<9009e2e0>] do_read_cache_page+0xac/0x210 [<9009fd90>] read_cache_page+0x18/0x24 [<901bbd18>] read_dev_sector+0x38/0xb0 [<901bd174>] msdos_partition+0xb4/0x5c0 [<901bcb8c>] check_partition+0x140/0x274 [<901bba60>] rescan_partitions+0xa0/0x2b0 [<9011ff68>] __blkdev_get+0x264/0x380 [<901201ac>] blkdev_get+0x128/0x36c [<901b9378>] add_disk+0x3c0/0x4bc [<90268268>] sd_probe_async+0x100/0x224 [<90043a44>] async_run_entry_fn+0x50/0x124 [<9003a11c>] process_one_work+0x1a4/0x430 [<9003a4f4>] worker_thread+0x14c/0x4fc [<900408f4>] kthread+0xd0/0xe8 [<90004338>] ret_from_kernel_thread+0x14/0x1c Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex") Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard --- drivers/ata/sata_dwc_460ex.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 2cb6f7e..5213e22 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -924,15 +924,13 @@ static void sata_dwc_exec_command_by_tag(struct ata_port *ap, struct ata_taskfile *tf, u8 tag, u32 cmd_issued) { - unsigned long flags; struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap); dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command, ata_get_cmd_descript(tf->command), tag); - spin_lock_irqsave(&ap->host->lock, flags); hsdevp->cmd_issued[tag] = cmd_issued; - spin_unlock_irqrestore(&ap->host->lock, flags); + /* * Clear SError before executing a new command. * sata_dwc_scr_write and read can not be used here. Clearing the PM -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 21/23] ata: sata_dwc_460ex: use devm_ioremap
This simplifies error handling and cleanup by using devm to manage IO mappings. Tested-by: Christian Lamparter Signed-off-by: Mans Rullgard Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 30 +++--- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 92f4008..6f145f8 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -139,7 +139,6 @@ struct sata_dwc_device { struct device *dev; /* generic device struct */ struct ata_probe_ent*pe;/* ptr to probe-ent */ struct ata_host *host; - u8 __iomem *reg_base; struct sata_dwc_regs __iomem *sata_dwc_regs;/* DW SATA specific */ u32 sactive_issued; u32 sactive_queued; @@ -242,7 +241,7 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, struct sata_dwc_device *hsdev) { struct device_node *np = pdev->dev.of_node; - int err; + struct resource *res; hsdev->dma = devm_kzalloc(&pdev->dev, sizeof(*hsdev->dma), GFP_KERNEL); if (!hsdev->dma) @@ -258,21 +257,16 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev, } /* Get physical SATA DMA register base address */ - hsdev->dma->regs = of_iomap(np, 1); - if (!hsdev->dma->regs) { + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + hsdev->dma->regs = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hsdev->dma->regs)) { dev_err(&pdev->dev, "ioremap failed for AHBDMA register address\n"); - return -ENODEV; + return PTR_ERR(hsdev->dma->regs); } /* Initialize AHB DMAC */ - err = dw_dma_probe(hsdev->dma); - if (err) { - iounmap(hsdev->dma->regs); - return err; - } - - return 0; + return dw_dma_probe(hsdev->dma); } static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) @@ -281,7 +275,6 @@ static void sata_dwc_dma_exit_old(struct sata_dwc_device *hsdev) return; dw_dma_remove(hsdev->dma); - iounmap(hsdev->dma->regs); } #endif @@ -1219,6 +1212,7 @@ static int sata_dwc_probe(struct platform_device *ofdev) struct ata_port_info pi = sata_dwc_port_info[0]; const struct ata_port_info *ppi[] = { &pi, NULL }; struct device_node *np = ofdev->dev.of_node; + struct resource *res; /* Allocate DWC SATA device */ host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_DWC_MAX_PORTS); @@ -1229,13 +1223,13 @@ static int sata_dwc_probe(struct platform_device *ofdev) host->private_data = hsdev; /* Ioremap SATA registers */ - base = of_iomap(np, 0); - if (!base) { + res = platform_get_resource(ofdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&ofdev->dev, res); + if (IS_ERR(base)) { dev_err(&ofdev->dev, "ioremap failed for SATA register address\n"); - return -ENODEV; + return PTR_ERR(base); } - hsdev->reg_base = base; dev_dbg(&ofdev->dev, "ioremap done for SATA register address\n"); /* Synopsys DWC SATA specific Registers */ @@ -1300,7 +1294,6 @@ static int sata_dwc_probe(struct platform_device *ofdev) error_out: phy_exit(hsdev->phy); - iounmap(base); return err; } @@ -1319,7 +1312,6 @@ static int sata_dwc_remove(struct platform_device *ofdev) sata_dwc_dma_exit_old(hsdev); #endif - iounmap(hsdev->reg_base); dev_dbg(&ofdev->dev, "done\n"); return 0; } -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v2 18/23] ata: sata_dwc_460ex: switch to new dmaengine_terminate_* API
Convert dmaengine_terminate_all() calls to synchronous and asynchronous versions where appropriate. Tested-by: Christian Lamparter Signed-off-by: Andy Shevchenko --- drivers/ata/sata_dwc_460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c index 7b73728..113cb3a 100644 --- a/drivers/ata/sata_dwc_460ex.c +++ b/drivers/ata/sata_dwc_460ex.c @@ -968,7 +968,7 @@ static void sata_dwc_port_stop(struct ata_port *ap) dev_dbg(ap->dev, "%s: ap->id = %d\n", __func__, ap->print_id); - dmaengine_terminate_all(hsdevp->chan); + dmaengine_terminate_sync(hsdevp->chan); dma_release_channel(hsdevp->chan); phy_power_off(hsdev->phy); -- 2.8.0.rc3 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 3/5] dma-mapping: cosolidate dma_mapping_error
; - debug_dma_mapping_error(dev, dma_addr); > - if (ops->mapping_error) > - return ops->mapping_error(dev, dma_addr); > - > - return (dma_addr == DMA_ERROR_CODE); > -} > - > extern int dma_supported(struct device *hwdev, u64 mask); > extern int dma_set_mask(struct device *dev, u64 mask); > > diff --git a/include/asm-generic/dma-mapping-common.h > b/include/asm-generic/dma-mapping-common.h > index ec321dd..cdaa241 100644 > --- a/include/asm-generic/dma-mapping-common.h > +++ b/include/asm-generic/dma-mapping-common.h > @@ -313,4 +313,18 @@ static inline void dma_free_noncoherent(struct device > *dev, size_t size, > dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs); > } > > +static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) > +{ > + debug_dma_mapping_error(dev, dma_addr); > + > + if (get_dma_ops(dev)->mapping_error) > + return get_dma_ops(dev)->mapping_error(dev, dma_addr); > + > +#ifdef DMA_ERROR_CODE > + return dma_addr == DMA_ERROR_CODE; > +#else > + return 0; > +#endif > +} > + > #endif > -- > 1.9.1 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [v2,5/5] powerpc/pseries: re-use code from of_helpers module
On Fri, 2015-08-14 at 21:51 +1000, Michael Ellerman wrote: > On Tue, 2015-11-08 at 11:23:09 UTC, Andy Shevchenko wrote: > > The derive_parent() has similar semantics to what we have in newly > > introduced > > of_helpers module. The replacement reduces code base and propagates > > the actual > > error code to the caller. > > > > Signed-off-by: Andy Shevchenko > > --- > > arch/powerpc/platforms/pseries/dlpar.c | 31 +- > > - > > 1 file changed, 5 insertions(+), 26 deletions(-) > > > > diff --git a/arch/powerpc/platforms/pseries/dlpar.c > > b/arch/powerpc/platforms/pseries/dlpar.c > > index 47d9cebe..b7f243c 100644 > > --- a/arch/powerpc/platforms/pseries/dlpar.c > > +++ b/arch/powerpc/platforms/pseries/dlpar.c > > @@ -18,6 +18,8 @@ > > #include > > #include > > #include > > + > > +#include "of_helpers.h" > > #include "offline_states.h" > > #include "pseries.h" > > > > @@ -244,36 +246,13 @@ cc_error: > > return first_dn; > > } > > > > -static struct device_node *derive_parent(const char *path) > > -{ > > - struct device_node *parent; > > - char *last_slash; > > - > > - last_slash = strrchr(path, '/'); > > - if (last_slash == path) { > > - parent = of_find_node_by_path("/"); > > - } else { > > - char *parent_path; > > - int parent_path_len = last_slash - path + 1; > > - parent_path = kmalloc(parent_path_len, > > GFP_KERNEL); > > - if (!parent_path) > > - return NULL; > > - > > - strlcpy(parent_path, path, parent_path_len); > > - parent = of_find_node_by_path(parent_path); > > - kfree(parent_path); > > - } > > - > > - return parent; > > -} > > - > > int dlpar_attach_node(struct device_node *dn) > > { > > int rc; > > > > - dn->parent = derive_parent(dn->full_name); > > - if (!dn->parent) > > - return -ENOMEM; > > + dn->parent = pseries_of_derive_parent(dn->full_name); > > + if (IS_ERR(dn->parent)) > > + return PTR_ERR(dn_parent); > ^ >? > > There are cross compilers on kernel.org, or on Ubuntu you can just: > > $ apt-get install gcc-powerpc-linux-gnu > $ make ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu-gcc Thanks! I tried today and the above the only problem with the series. Would you like me to resend whole series? > > cheers -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [v2,5/5] powerpc/pseries: re-use code from of_helpers module
On Thu, 2015-10-01 at 10:02 +0300, Denis Kirjanov wrote: > On 10/1/15, Michael Ellerman wrote: > > On Wed, 2015-09-30 at 19:19 +0300, Andy Shevchenko wrote: > > > On Fri, 2015-08-14 at 21:51 +1000, Michael Ellerman wrote: > > > > On Tue, 2015-11-08 at 11:23:09 UTC, Andy Shevchenko wrote: > > > > > int dlpar_attach_node(struct device_node *dn) > > > > > { > > > > > int rc; > > > > > > > > > > - dn->parent = derive_parent(dn->full_name); > > > > > - if (!dn->parent) > > > > > - return -ENOMEM; > > > > > + dn->parent = pseries_of_derive_parent(dn > > > > > ->full_name); > > > > > + if (IS_ERR(dn->parent)) > > > > > + return PTR_ERR(dn_parent); > > > > ^ > > > > ? > > > > > > > > There are cross compilers on kernel.org, or on Ubuntu you can > > > > just: > > > > > > > > $ apt-get install gcc-powerpc-linux-gnu > > > > $ make ARCH=powerpc CROSS_COMPILE=powerpc-linux-gnu-gcc > > > > > > Thanks! I tried today and the above the only problem with the > > > series. > > > Would you like me to resend whole series? > > > > I'd like someone to test it. I gather that you haven't because it > > didn't > > compile. > > Oh yeah, totally untested: > > CC arch/powerpc/platforms/pseries/dlpar.o > arch/powerpc/platforms/pseries/dlpar.c: In function > 'dlpar_attach_node': > arch/powerpc/platforms/pseries/dlpar.c:255:18: error: 'dn_parent' > undeclared (first use in this function) >return PTR_ERR(dn_parent); > ^ > arch/powerpc/platforms/pseries/dlpar.c:255:18: note: each undeclared > identifier is reported only once for each function it appears in > scripts/Makefile.build:258: recipe for target > 'arch/powerpc/platforms/pseries/dlpar.o' failed > make[2]: *** [arch/powerpc/platforms/pseries/dlpar.o] Error 1 > scripts/Makefile.build:403: recipe for target > 'arch/powerpc/platforms/pseries' failed > make[1]: *** [arch/powerpc/platforms/pseries] Error 2 > Makefile:941: recipe for target 'arch/powerpc/platforms' failed > make: *** [arch/powerpc/platforms] Error 2 Like I mentioned earlier this is the only one issue to compile the series. Can you fix it and try on real HW? > > > > > I assume you don't have access to hardware to test it on? > > > > cheers > > > > > > > > ___ > > Linuxppc-dev mailing list > > Linuxppc-dev@lists.ozlabs.org > > https://lists.ozlabs.org/listinfo/linuxppc-dev -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 0/5] powerpc/pseries: bug fix and clean up
Changelog v2: - fix compiler error - rebase on top of recent linux-next - compile tested Andy Shevchenko (5): powerpc/pseries: extract of_helpers module powerpc/pseries: fix a potential memory leak powerpc/pseries: replace kmalloc + strlcpy powerpc/pseries: handle nodes without '/' powerpc/pseries: re-use code from of_helpers module arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/dlpar.c | 31 + arch/powerpc/platforms/pseries/of_helpers.c | 35 + arch/powerpc/platforms/pseries/of_helpers.h | 8 +++ arch/powerpc/platforms/pseries/reconfig.c | 34 ++-- 5 files changed, 51 insertions(+), 58 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h -- 2.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 3/5] powerpc/pseries: replace kmalloc + strlcpy
The helper kstrndup() will do the same in one line. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 2f363e3..8c6b05a 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -24,10 +24,9 @@ struct device_node *pseries_of_derive_parent(const char *path) return ERR_PTR(-EINVAL); if (strrchr(path, '/') != path) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); + parent_path = kstrndup(path, parent_path_len, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); if (strcmp(parent_path, "/")) -- 2.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 1/5] powerpc/pseries: extract of_helpers module
Extract a new module to share the code between other modules. There is no functional change. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/of_helpers.c | 38 + arch/powerpc/platforms/pseries/of_helpers.h | 8 ++ arch/powerpc/platforms/pseries/reconfig.c | 34 ++ 4 files changed, 49 insertions(+), 32 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 0348079..2e857c2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -2,6 +2,7 @@ ccflags-$(CONFIG_PPC64) := $(NO_MINIMAL_TOC) ccflags-$(CONFIG_PPC_PSERIES_DEBUG)+= -DDEBUG obj-y := lpar.o hvCall.o nvram.o reconfig.o \ + of_helpers.o \ setup.o iommu.o event_sources.o ras.o \ firmware.o power.o dlpar.o mobility.o rng.o obj-$(CONFIG_SMP) += smp.o diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c new file mode 100644 index 000..1cbd896 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include "of_helpers.h" + +/** + * pseries_of_derive_parent - basically like dirname(1) + * @path: the full_name of a node to be added to the tree + * + * Returns the node which should be the parent of the node + * described by path. E.g., for path = "/foo/bar", returns + * the node with full_name = "/foo". + */ +struct device_node *pseries_of_derive_parent(const char *path) +{ + struct device_node *parent = NULL; + char *parent_path = "/"; + size_t parent_path_len = strrchr(path, '/') - path + 1; + + /* reject if path is "/" */ + if (!strcmp(path, "/")) + return ERR_PTR(-EINVAL); + + if (strrchr(path, '/') != path) { + parent_path = kmalloc(parent_path_len, GFP_KERNEL); + if (!parent_path) + return ERR_PTR(-ENOMEM); + strlcpy(parent_path, path, parent_path_len); + } + parent = of_find_node_by_path(parent_path); + if (!parent) + return ERR_PTR(-EINVAL); + if (strcmp(parent_path, "/")) + kfree(parent_path); + return parent; +} diff --git a/arch/powerpc/platforms/pseries/of_helpers.h b/arch/powerpc/platforms/pseries/of_helpers.h new file mode 100644 index 000..bb83d39 --- /dev/null +++ b/arch/powerpc/platforms/pseries/of_helpers.h @@ -0,0 +1,8 @@ +#ifndef _PSERIES_OF_HELPERS_H +#define _PSERIES_OF_HELPERS_H + +#include + +struct device_node *pseries_of_derive_parent(const char *path); + +#endif /* _PSERIES_OF_HELPERS_H */ diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 0f31952..7c7fcc0 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -22,37 +22,7 @@ #include #include -/** - * derive_parent - basically like dirname(1) - * @path: the full_name of a node to be added to the tree - * - * Returns the node which should be the parent of the node - * described by path. E.g., for path = "/foo/bar", returns - * the node with full_name = "/foo". - */ -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent = NULL; - char *parent_path = "/"; - size_t parent_path_len = strrchr(path, '/') - path + 1; - - /* reject if path is "/" */ - if (!strcmp(path, "/")) - return ERR_PTR(-EINVAL); - - if (strrchr(path, '/') != path) { - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return ERR_PTR(-ENOMEM); - strlcpy(parent_path, path, parent_path_len); - } - parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); - if (strcmp(parent_path, "/")) - kfree(parent_path); - return parent; -} +#include "of_helpers.h" static int pSeries_reconfig_add_node(const char *path, struct property *proplist) { @@ -71,7 +41,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist of_node_set_flag(np, OF_DYNAMIC); of_node_init(np); - np->parent = derive_parent(path); + np->parent = pseries_of_derive_parent(path); if (IS_ERR(np->parent)) { err = PTR_ERR(np
[PATCH v3 5/5] powerpc/pseries: re-use code from of_helpers module
The derive_parent() has similar semantics to what we have in newly introduced of_helpers module. The replacement reduces code base and propagates the actual error code to the caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/dlpar.c | 31 +-- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index db17827..f244dcb 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -18,6 +18,8 @@ #include #include #include + +#include "of_helpers.h" #include "offline_states.h" #include "pseries.h" @@ -244,36 +246,13 @@ cc_error: return first_dn; } -static struct device_node *derive_parent(const char *path) -{ - struct device_node *parent; - char *last_slash; - - last_slash = strrchr(path, '/'); - if (last_slash == path) { - parent = of_find_node_by_path("/"); - } else { - char *parent_path; - int parent_path_len = last_slash - path + 1; - parent_path = kmalloc(parent_path_len, GFP_KERNEL); - if (!parent_path) - return NULL; - - strlcpy(parent_path, path, parent_path_len); - parent = of_find_node_by_path(parent_path); - kfree(parent_path); - } - - return parent; -} - int dlpar_attach_node(struct device_node *dn) { int rc; - dn->parent = derive_parent(dn->full_name); - if (!dn->parent) - return -ENOMEM; + dn->parent = pseries_of_derive_parent(dn->full_name); + if (IS_ERR(dn->parent)) + return PTR_ERR(dn->parent); rc = of_attach_node(dn); if (rc) { -- 2.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 2/5] powerpc/pseries: fix a potential memory leak
In case we have a full node name like /foo/bar and /foo is not found the parent_path left unfreed. So, free a memory before return to a caller. Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 1cbd896..2f363e3 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -15,7 +15,7 @@ */ struct device_node *pseries_of_derive_parent(const char *path) { - struct device_node *parent = NULL; + struct device_node *parent; char *parent_path = "/"; size_t parent_path_len = strrchr(path, '/') - path + 1; @@ -30,9 +30,7 @@ struct device_node *pseries_of_derive_parent(const char *path) strlcpy(parent_path, path, parent_path_len); } parent = of_find_node_by_path(parent_path); - if (!parent) - return ERR_PTR(-EINVAL); if (strcmp(parent_path, "/")) kfree(parent_path); - return parent; + return parent ? parent : ERR_PTR(-EINVAL); } -- 2.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
[PATCH v3 4/5] powerpc/pseries: handle nodes without '/'
In case we have node without '/' strrchr() returns NULL which might lead to crash. Replace strrchr() by kbasename() and modify condition to avoid such behaviour. Suggested-by: Segher Boessenkool Signed-off-by: Andy Shevchenko --- arch/powerpc/platforms/pseries/of_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/pseries/of_helpers.c b/arch/powerpc/platforms/pseries/of_helpers.c index 8c6b05a..4417afe 100644 --- a/arch/powerpc/platforms/pseries/of_helpers.c +++ b/arch/powerpc/platforms/pseries/of_helpers.c @@ -17,14 +17,14 @@ struct device_node *pseries_of_derive_parent(const char *path) { struct device_node *parent; char *parent_path = "/"; - size_t parent_path_len = strrchr(path, '/') - path + 1; + const char *tail = kbasename(path); /* reject if path is "/" */ if (!strcmp(path, "/")) return ERR_PTR(-EINVAL); - if (strrchr(path, '/') != path) { - parent_path = kstrndup(path, parent_path_len, GFP_KERNEL); + if (tail > path + 1) { + parent_path = kstrndup(path, tail - path, GFP_KERNEL); if (!parent_path) return ERR_PTR(-ENOMEM); } -- 2.5.1 ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH] powerpc/pseries: Correct string length in pseries_of_derive_parent()
On Mon, 2015-10-26 at 14:33 -0500, Nathan Fontenot wrote: > Commit a030e1e4bbd085bbcfd0a23f8d355fcd41f39bed made a change to use > kstrndup() instead of kmalloc() + strlcpy() in > pseries_of_derive_parent() > which introduces a subtle change in the parent path name generated. > The kstrndup() routine will copy n characters followed by a > terminating null, > whereas strlcpy() will copy n-1 characters and add a terminating > null. Nice catch! One comment below. > > This slight difference results in having a parent path that includes > the > trailing '/' character, i.e. "/cpus/" vs. "/cpus". This then causes > the > subsequent call to of_find_node_by_path() to fail, and in the case of > DLPAR add operations, the DLPAR request fails. > > This patch reduces the total length of the string to copy in kstrndup > by 1 > so we no longer copy the trailing '/'. > > Signed-off-by: Nathan Fontenot > --- > arch/powerpc/platforms/pseries/of_helpers.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/arch/powerpc/platforms/pseries/of_helpers.c > b/arch/powerpc/platforms/pseries/of_helpers.c > index 4417afe..6d90378 100644 > --- a/arch/powerpc/platforms/pseries/of_helpers.c > +++ b/arch/powerpc/platforms/pseries/of_helpers.c > @@ -24,7 +24,7 @@ struct device_node *pseries_of_derive_parent(const > char *path) > return ERR_PTR(-EINVAL); > > if (tail > path + 1) { > - parent_path = kstrndup(path, tail - path, > GFP_KERNEL); > + parent_path = kstrndup(path, (tail - 1) - path, > GFP_KERNEL); Since previous line has (tail > path + 1) which is equivalent to (tail - 1 > path), can we amend both? For example (might be better, but first comes to my mind) const char *tail = kbasename(path) - 1; ... if (tail > path) { > if (!parent_path) > return ERR_PTR(-ENOMEM); > } > -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2] powerpc/pseries: Correct string length in pseries_of_derive_parent()
On Tue, 2015-10-27 at 10:46 -0500, Nathan Fontenot wrote: > Commit a030e1e4bbd085bbcfd0a23f8d355fcd41f39bed make a change to use > kstrndup() instead of kmalloc() + strlcpy() in the > pseries_of_derive_parent() > routine that introduces a subtle change in the parent path name > generated. > The kstrndup() routine will copy n characters followed by a > terminating null, > whereas strlcpy() will copy n-1 characters and add a terminating > null. > > This slight difference results in having a parent path that includes > the > tailing '/' character, "/cpus/" vs. "/cpus". This then causes the > subsequent > call to of_find_node_by_path() to fail, and in the case of DLPAR add > operations the DLPAR request fails. > > This patch decrements the pointer returned from kbasename() to point > to the > '/' character before the base name instead of the base name. This > then > adjusts the string length calculations to not include the trailing > '/' > in the parent path name. > > Signed-off-by: Nathan Fontenot Reviewed-by: Andy Shevchenko > --- > > Updates for v2: Decrement the pointer returned from kbasename() > instead > of subtracting 1 when calculating the string length. > > arch/powerpc/platforms/pseries/of_helpers.c |7 +-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/arch/powerpc/platforms/pseries/of_helpers.c > b/arch/powerpc/platforms/pseries/of_helpers.c > index 4417afe..2798933 100644 > --- a/arch/powerpc/platforms/pseries/of_helpers.c > +++ b/arch/powerpc/platforms/pseries/of_helpers.c > @@ -17,13 +17,16 @@ struct device_node > *pseries_of_derive_parent(const char *path) > { > struct device_node *parent; > char *parent_path = "/"; > - const char *tail = kbasename(path); > + const char *tail; > + > + /* We do not want the trailing '/' character */ > + tail = kbasename(path) - 1; > > /* reject if path is "/" */ > if (!strcmp(path, "/")) > return ERR_PTR(-EINVAL); > > - if (tail > path + 1) { > + if (tail > path) { > parent_path = kstrndup(path, tail - path, > GFP_KERNEL); > if (!parent_path) > return ERR_PTR(-ENOMEM); > -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v1 1/2] sata_dwc_460ex: move to generic DMA driver
On Sun, 2015-11-22 at 13:03 +, Måns Rullgård wrote: > Andy Shevchenko writes: > > > The SATA implementation based on two actually different devices, > > i.e. SATA and > > DMA controllers. > > > > For Synopsys DesignWare DMA we have already a generic > > implementation of the > > driver. Thus, the patch converts the code to use DMAEngine > > framework and > > dw_dmac driver. > > > > In future it will be better to split the devices inside DTS as well > > like it's > > done on other platforms. > > @@ -1721,16 +1227,16 @@ static int sata_dwc_probe(struct > > platform_device *ofdev) > > idr, ver[0], ver[1], ver[2]); > > > > /* Get SATA DMA interrupt number */ > > - irq = irq_of_parse_and_map(np, 1); > > - if (irq == NO_IRQ) { > > + hsdev->dma->irq = irq_of_parse_and_map(np, 1); > > This doesn't look like it has been more than compile-tested. Yes, that's true, my question [1] was a crying in the wilderness. > Nothing > ever allocates hsdev->dma, so it can't possibly work. You are right. > > Also, has anyone given any thought to getting rid of the dependency > on > the DW DMA controller? How? Before it was even more harder link to it (embedded routines). On the other hand you may introduce dma_ops and use them like it's done, for example, in spi-dw*.c > Presumably support for old device trees would > need to be retained for compatibility. Maybe checking for a "dmas" > property and falling back on the current behaviour if it's missing. I didn't get how DT is related to DW or any other DMAC used with this SATA controller. > My > goal is to get this driver working with another chip using the same > SATA > controller but a different DMA engine. It would be nice to eventually bring this working with generic DMA Engine API. Please, keep me in Cc list regarding this driver. [1] https://lkml.org/lkml/2014/12/12/547 -- Andy Shevchenko Intel Finland Oy ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH 1/3] lib: fix callers of strtobool to use char array
; void cifs_dump_detail(void *); > void cifs_dump_mids(struct TCP_Server_Info *); > -extern int traceSMB; /* flag which enables the function below */ > +extern bool traceSMB; /* flag which enables the function below */ > void dump_smb(void *, int); > #define CIFS_INFO 0x01 > #define CIFS_RC0x02 > diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c > index c48ca13673e3..931b446f2a44 100644 > --- a/fs/cifs/cifsfs.c > +++ b/fs/cifs/cifsfs.c > @@ -54,10 +54,10 @@ > #endif > > int cifsFYI = 0; > -int traceSMB = 0; > +bool traceSMB; > bool enable_oplocks = true; > -unsigned int linuxExtEnabled = 1; > -unsigned int lookupCacheEnabled = 1; > +bool linuxExtEnabled = true; > +bool lookupCacheEnabled = true; > unsigned int global_secflags = CIFSSEC_DEF; > /* unsigned int ntlmv2_support = 0; */ > unsigned int sign_CIFS_PDUs = 1; > diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h > index a25b2513f146..d21da9f05bae 100644 > --- a/fs/cifs/cifsglob.h > +++ b/fs/cifs/cifsglob.h > @@ -1596,11 +1596,11 @@ GLOBAL_EXTERN atomic_t midCount; > > /* Misc globals */ > GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */ > -GLOBAL_EXTERN unsigned int lookupCacheEnabled; > +GLOBAL_EXTERN bool lookupCacheEnabled; > GLOBAL_EXTERN unsigned int global_secflags;/* if on, session setup sent > with more secure ntlmssp2 challenge/resp */ > GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ > -GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS > extensions*/ > +GLOBAL_EXTERN bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ > GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ > GLOBAL_EXTERN unsigned int cifs_min_rcv;/* min size of big ntwrk buf > pool */ > GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ > -- > 2.6.3 > -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 1/4] lib: move strtobool to kstrtobool
On Thu, Feb 4, 2016 at 11:00 PM, Kees Cook wrote: > Create the kstrtobool_from_user helper and moves strtobool logic into > the new kstrtobool (matching all the other kstrto* functions). Provides > an inline wrapper for existing strtobool callers. > > Signed-off-by: Kees Cook Reviewed-by: Andy Shevchenko One minor below. > --- > include/linux/kernel.h | 3 +++ > include/linux/string.h | 6 +- > lib/kstrtox.c | 35 +++ > lib/string.c | 29 - > 4 files changed, 43 insertions(+), 30 deletions(-) > > diff --git a/include/linux/kernel.h b/include/linux/kernel.h > index f31638c6e873..cdc25f47a23f 100644 > --- a/include/linux/kernel.h > +++ b/include/linux/kernel.h > @@ -357,6 +357,7 @@ int __must_check kstrtou16(const char *s, unsigned int > base, u16 *res); > int __must_check kstrtos16(const char *s, unsigned int base, s16 *res); > int __must_check kstrtou8(const char *s, unsigned int base, u8 *res); > int __must_check kstrtos8(const char *s, unsigned int base, s8 *res); > +int __must_check kstrtobool(const char *s, unsigned int base, bool *res); > > int __must_check kstrtoull_from_user(const char __user *s, size_t count, > unsigned int base, unsigned long long *res); > int __must_check kstrtoll_from_user(const char __user *s, size_t count, > unsigned int base, long long *res); > @@ -368,6 +369,8 @@ int __must_check kstrtou16_from_user(const char __user > *s, size_t count, unsigne > int __must_check kstrtos16_from_user(const char __user *s, size_t count, > unsigned int base, s16 *res); > int __must_check kstrtou8_from_user(const char __user *s, size_t count, > unsigned int base, u8 *res); > int __must_check kstrtos8_from_user(const char __user *s, size_t count, > unsigned int base, s8 *res); > +int __must_check kstrtobool_from_user(const char __user *s, size_t count, > + unsigned int base, bool *res); We already are using long lines here, perhaps do the same? > > static inline int __must_check kstrtou64_from_user(const char __user *s, > size_t count, unsigned int base, u64 *res) > { > diff --git a/include/linux/string.h b/include/linux/string.h > index 9eebc66d957a..d2fb21b1081d 100644 > --- a/include/linux/string.h > +++ b/include/linux/string.h > @@ -128,7 +128,11 @@ extern char **argv_split(gfp_t gfp, const char *str, int > *argcp); > extern void argv_free(char **argv); > > extern bool sysfs_streq(const char *s1, const char *s2); > -extern int strtobool(const char *s, bool *res); > +extern int kstrtobool(const char *s, unsigned int base, bool *res); > +static inline int strtobool(const char *s, bool *res) > +{ > + return kstrtobool(s, 0, res); > +} > > #ifdef CONFIG_BINARY_PRINTF > int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); > diff --git a/lib/kstrtox.c b/lib/kstrtox.c > index 94be244e8441..e18f088704d7 100644 > --- a/lib/kstrtox.c > +++ b/lib/kstrtox.c > @@ -321,6 +321,40 @@ int kstrtos8(const char *s, unsigned int base, s8 *res) > } > EXPORT_SYMBOL(kstrtos8); > > +/** > + * kstrtobool - convert common user inputs into boolean values > + * @s: input string > + * @base: ignored > + * @res: result > + * > + * This routine returns 0 iff the first character is one of 'Yy1Nn0'. > + * Otherwise it will return -EINVAL. Value pointed to by res is > + * updated upon finding a match. > + */ > +int kstrtobool(const char *s, unsigned int base, bool *res) > +{ > + if (!s) > + return -EINVAL; > + > + switch (s[0]) { > + case 'y': > + case 'Y': > + case '1': > + *res = true; > + return 0; > + case 'n': > + case 'N': > + case '0': > + *res = false; > + return 0; > + default: > + break; > + } > + > + return -EINVAL; > +} > +EXPORT_SYMBOL(kstrtobool); > + > #define kstrto_from_user(f, g, type) \ > int f(const char __user *s, size_t count, unsigned int base, type *res) > \ > { \ > @@ -345,3 +379,4 @@ kstrto_from_user(kstrtou16_from_user, kstrtou16, > u16); > kstrto_from_user(kstrtos16_from_user, kstrtos16, s16); > kstrto_from_user(kstrtou8_from_user, kstrtou8, u8); > kstrto_from_user(kstrtos8_from_user, kstrtos8, s8); > +kstrto_from_user(kstrtobool_from_user, kstrtobool, bool); > diff --git a/lib/string.c b/lib/string.c > index
Re: [PATCH v2 2/4] lib: update single-char callers of strtobool
return count; > } > > @@ -511,20 +501,12 @@ static int cifs_lookup_cache_proc_open(struct inode > *inode, struct file *file) > static ssize_t cifs_lookup_cache_proc_write(struct file *file, > const char __user *buffer, size_t count, loff_t *ppos) > { > - char c; > - bool bv; > int rc; > > - rc = get_user(c, buffer); > + rc = kstrtobool_from_user(buffer, count, 0, &lookupCacheEnabled); > if (rc) > return rc; > > - rc = strtobool(&c, &bv); > - if (rc) > - return rc; > - > - lookupCacheEnabled = bv; > - > return count; > } > > @@ -551,20 +533,12 @@ static int traceSMB_proc_open(struct inode *inode, > struct file *file) > static ssize_t traceSMB_proc_write(struct file *file, const char __user > *buffer, > size_t count, loff_t *ppos) > { > - char c; > - bool bv; > int rc; > > - rc = get_user(c, buffer); > + rc = kstrtobool_from_user(buffer, count, 0, &traceSMB); > if (rc) > return rc; > > - rc = strtobool(&c, &bv); > - if (rc) > - return rc; > - > - traceSMB = bv; > - > return count; > } > > @@ -622,7 +596,7 @@ static ssize_t cifs_security_flags_proc_write(struct file > *file, > int rc; > unsigned int flags; > char flags_string[12]; > - char c; > + char c[2] = { '\0' }; Can we use flag_string directly here? > bool bv; > > if ((count < 1) || (count > 11)) > @@ -635,11 +609,11 @@ static ssize_t cifs_security_flags_proc_write(struct > file *file, > > if (count < 3) { > /* single char or single char followed by null */ > - c = flags_string[0]; > - if (strtobool(&c, &bv) == 0) { > + c[0] = flags_string[0]; > + if (strtobool(c, &bv) == 0) { > global_secflags = bv ? CIFSSEC_MAX : CIFSSEC_DEF; > return count; > - } else if (!isdigit(c)) { > + } else if (!isdigit(c[0])) { > cifs_dbg(VFS, "Invalid SecurityFlags: %s\n", > flags_string); > return -EINVAL; > diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h > index 66cf0f9fff89..c611ca2339d7 100644 > --- a/fs/cifs/cifs_debug.h > +++ b/fs/cifs/cifs_debug.h > @@ -25,7 +25,7 @@ > void cifs_dump_mem(char *label, void *data, int length); > void cifs_dump_detail(void *); > void cifs_dump_mids(struct TCP_Server_Info *); > -extern int traceSMB; /* flag which enables the function below */ > +extern bool traceSMB; /* flag which enables the function below */ > void dump_smb(void *, int); > #define CIFS_INFO 0x01 > #define CIFS_RC0x02 > diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c > index c48ca13673e3..931b446f2a44 100644 > --- a/fs/cifs/cifsfs.c > +++ b/fs/cifs/cifsfs.c > @@ -54,10 +54,10 @@ > #endif > > int cifsFYI = 0; > -int traceSMB = 0; > +bool traceSMB; > bool enable_oplocks = true; > -unsigned int linuxExtEnabled = 1; > -unsigned int lookupCacheEnabled = 1; > +bool linuxExtEnabled = true; > +bool lookupCacheEnabled = true; > unsigned int global_secflags = CIFSSEC_DEF; > /* unsigned int ntlmv2_support = 0; */ > unsigned int sign_CIFS_PDUs = 1; > diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h > index a25b2513f146..d21da9f05bae 100644 > --- a/fs/cifs/cifsglob.h > +++ b/fs/cifs/cifsglob.h > @@ -1596,11 +1596,11 @@ GLOBAL_EXTERN atomic_t midCount; > > /* Misc globals */ > GLOBAL_EXTERN bool enable_oplocks; /* enable or disable oplocks */ > -GLOBAL_EXTERN unsigned int lookupCacheEnabled; > +GLOBAL_EXTERN bool lookupCacheEnabled; > GLOBAL_EXTERN unsigned int global_secflags;/* if on, session setup sent > with more secure ntlmssp2 challenge/resp */ > GLOBAL_EXTERN unsigned int sign_CIFS_PDUs; /* enable smb packet signing */ > -GLOBAL_EXTERN unsigned int linuxExtEnabled;/*enable Linux/Unix CIFS > extensions*/ > +GLOBAL_EXTERN bool linuxExtEnabled;/*enable Linux/Unix CIFS extensions*/ > GLOBAL_EXTERN unsigned int CIFSMaxBufSize; /* max size not including hdr */ > GLOBAL_EXTERN unsigned int cifs_min_rcv;/* min size of big ntwrk buf > pool */ > GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ > -- > 2.6.3 > -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 3/4] lib: add "on"/"off" support to kstrtobool
On Thu, Feb 4, 2016 at 11:00 PM, Kees Cook wrote: > Add support for "on" and "off" when converting to boolean. > > Signed-off-by: Kees Cook > --- > lib/kstrtox.c | 14 ++ > 1 file changed, 14 insertions(+) > > diff --git a/lib/kstrtox.c b/lib/kstrtox.c > index e18f088704d7..09e83a19a96d 100644 > --- a/lib/kstrtox.c > +++ b/lib/kstrtox.c > @@ -347,6 +347,20 @@ int kstrtobool(const char *s, unsigned int base, bool > *res) Forgot update description? > case '0': > *res = false; > return 0; > + case 'o': > + case 'O': > + switch (s[1]) { > + case 'n': > + case 'N': > + *res = true; > + return 0; > + case 'f': > + case 'F': > + *res = false; > + return 0; > + default: > + break; > + } > default: > break; > } > -- > 2.6.3 > -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 4/4] param: convert some "on"/"off" users to strtobool
ology_enabled = 0; > - return 0; > + return kstrtobool(p, 0, &topology_enabled); > } > early_param("topology", early_parse_topology); > > diff --git a/arch/x86/kernel/aperture_64.c b/arch/x86/kernel/aperture_64.c > index 6e85f713641d..6b423754083a 100644 > --- a/arch/x86/kernel/aperture_64.c > +++ b/arch/x86/kernel/aperture_64.c > @@ -227,19 +227,11 @@ static u32 __init search_agp_bridge(u32 *order, int > *valid_agp) > return 0; > } > > -static int gart_fix_e820 __initdata = 1; > +static bool gart_fix_e820 __initdata = true; > > static int __init parse_gart_mem(char *p) > { > - if (!p) > - return -EINVAL; > - > - if (!strncmp(p, "off", 3)) > - gart_fix_e820 = 0; > - else if (!strncmp(p, "on", 2)) > - gart_fix_e820 = 1; > - > - return 0; > + return kstrtobool(p, 0, &gart_fix_e820); > } > early_param("gart_fix_e820", parse_gart_mem); > > diff --git a/include/linux/tick.h b/include/linux/tick.h > index 97fd4e543846..0ecdf0e248f4 100644 > --- a/include/linux/tick.h > +++ b/include/linux/tick.h > @@ -98,7 +98,7 @@ static inline void tick_broadcast_exit(void) > } > > #ifdef CONFIG_NO_HZ_COMMON > -extern int tick_nohz_enabled; > +extern bool tick_nohz_enabled; > extern int tick_nohz_tick_stopped(void); > extern void tick_nohz_idle_enter(void); > extern void tick_nohz_idle_exit(void); > diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c > index 435b8850dd80..456f066148d5 100644 > --- a/kernel/time/hrtimer.c > +++ b/kernel/time/hrtimer.c > @@ -515,7 +515,7 @@ static inline ktime_t hrtimer_update_base(struct > hrtimer_cpu_base *base) > /* > * High resolution timer enabled ? > */ > -static int hrtimer_hres_enabled __read_mostly = 1; > +static bool hrtimer_hres_enabled __read_mostly = true; > unsigned int hrtimer_resolution __read_mostly = LOW_RES_NSEC; > EXPORT_SYMBOL_GPL(hrtimer_resolution); > > @@ -524,13 +524,7 @@ EXPORT_SYMBOL_GPL(hrtimer_resolution); > */ > static int __init setup_hrtimer_hres(char *str) > { > - if (!strcmp(str, "off")) > - hrtimer_hres_enabled = 0; > - else if (!strcmp(str, "on")) > - hrtimer_hres_enabled = 1; > - else > - return 0; > - return 1; > + return kstrtobool(str, 0, &hrtimer_hres_enabled); > } > > __setup("highres=", setup_hrtimer_hres); > diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c > index 9d7a053545f5..b57f822c2069 100644 > --- a/kernel/time/tick-sched.c > +++ b/kernel/time/tick-sched.c > @@ -387,20 +387,14 @@ void __init tick_nohz_init(void) > /* > * NO HZ enabled ? > */ > -int tick_nohz_enabled __read_mostly = 1; > +bool tick_nohz_enabled __read_mostly = true; > unsigned long tick_nohz_active __read_mostly; > /* > * Enable / Disable tickless mode > */ > static int __init setup_tick_nohz(char *str) > { > - if (!strcmp(str, "off")) > - tick_nohz_enabled = 0; > - else if (!strcmp(str, "on")) > - tick_nohz_enabled = 1; > - else > - return 0; > - return 1; > + return kstrtobool(str, 0, &tick_nohz_enabled); > } > > __setup("nohz=", setup_tick_nohz); > -- > 2.6.3 > -- With Best Regards, Andy Shevchenko ___ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev
Re: [PATCH v2 02/45] drivers: tty: serial: 8250_dw: use devm_ioremap_resource()
On Fri, Mar 15, 2019 at 12:41 AM Enrico Weigelt, metux IT consult wrote: > > Instead of fetching out data from a struct resource for passing > it to devm_ioremap(), directly use devm_ioremap_resource() I don't see any advantage of this change. See also below. > --- a/drivers/tty/serial/8250/8250_dw.c > +++ b/drivers/tty/serial/8250/8250_dw.c > @@ -526,7 +526,7 @@ static int dw8250_probe(struct platform_device *pdev) > p->set_ldisc= dw8250_set_ldisc; > p->set_termios = dw8250_set_termios; > > - p->membase = devm_ioremap(dev, regs->start, resource_size(regs)); > + p->membase = devm_ioremap_resource(dev, regs); > if (!p->membase) And how did you test this? devm_ioremap_resource() returns error pointer in case of error. > return -ENOMEM; -- With Best Regards, Andy Shevchenko