* at91: serial: Can't use DMA on 4.x kernels in RS-485 mode on at91sam9x5
From: Bryan Evenson @ 2017-04-11 20:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411185924.6g4cgk4h6ogsmyd5@piout.net>
Alexandre,
> -----Original Message-----
> From: Alexandre Belloni [mailto:alexandre.belloni at free-electrons.com]
> Sent: Tuesday, April 11, 2017 2:59 PM
> To: Bryan Evenson <bevenson@melinkcorp.com>
> Cc: Sylvain Rochet <sylvain.rochet@finsecur.com>; Nicolas Ferre
> <nicolas.ferre@atmel.com>; linux-arm-kernel at lists.infradead.org
> Subject: Re: at91: serial: Can't use DMA on 4.x kernels in RS-485 mode on
> at91sam9x5
>
> Hi,
>
> On 11/04/2017 at 18:32:20 +0000, Bryan Evenson wrote:
> > I narrowed my issues down to this commit:
> https://github.com/linux4sam/linux-
> at91/commit/0058f0871efe7b01c6f2b3046c68196ab73e96da
> >
> > tty/serial: atmel: fix RS485 half duplex with DMA
> >
> > When using DMA, half duplex doesn't work properly because rx is
> not stopped
> > before starting tx. Ensure we call atmel_stop_rx() in the DMA case.
> >
> > Signed-off-by: Alexandre Belloni <alexandre.belloni@free-
> electrons.com>
> > Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> > Cc: stable <stable@vger.kernel.org>
> > Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> >
> > If I revert this commit, I can use both TX and RX DMA on all three RS-485
> ports (USART0, USART1 and USART3) with the current head of linux-4.4-at91
> and linux-4.1-at91 on Atmel's fork. I have not yet tried the mainline releases,
> but I see that atmel_start_tx() (the function modified by this commit) is
> identical in mainline so I'm assuming I'll have the same results. In my case I
> am using my RS-485 ports in half-duplex mode, so the call to atmel_stop_rx()
> inside of atmel_start_tx() is the cause of my problems.
> >
> > Anyone know why this would be a problem? The commit makes sense to
> me and I don't see a good reason why it would break things. I'm willing to
> test things out to see why this is causing a problem.
> >
>
> Do you have b389f173aaa1204d6dc1f299082a162eb0491545 in your tree ?
>
No, I did not have that commit in my tree. I cherry-picked from the linux-stable repository, tested and verified it fixed my DMA issues.
I checked the various branches on the linux-stable repository, and I see this commit in master and on 4.9, but I don't see it in any branches prior to that one. Since this issue was introduced back in 4.1, I think this patch would be suitable for backporting to the 4.1 and 4.4 stable branches. Is there something I can do to help make that happen?
Thanks,
Bryan
>
> --
> Alexandre Belloni, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* [PATCH v2 2/2] ARM: dts: imx7: add USDHC NAND and IPG clock to SDHC instances
From: Dong Aisheng @ 2017-04-11 20:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170410210015.1620-2-stefan@agner.ch>
On Mon, Apr 10, 2017 at 02:00:15PM -0700, Stefan Agner wrote:
> The USDHC instances need the USDHC NAND and IPG clock in order to
> operate. Reference them properly by replacing the dummy clocks with
> the actual clocks.
>
> Note that both clocks are currently implicitly enabled since they
> are part of the i.MX 7 clock drivers init_on list. This might
> change in the future.
>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
Acked-by: Dong Aisheng <aisheng.dong@nxp.com>
Regards
Dong Aisheng
> ---
> This patch depends on "clk: imx7d: add the missing ipg_root_clk"
> which adds the IPG clock.
>
> --
> Stefan
>
> arch/arm/boot/dts/imx7s.dtsi | 12 ++++++------
> 1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
> index c4f12fd2e044..843eb379e1ea 100644
> --- a/arch/arm/boot/dts/imx7s.dtsi
> +++ b/arch/arm/boot/dts/imx7s.dtsi
> @@ -934,8 +934,8 @@
> compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
> reg = <0x30b40000 0x10000>;
> interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
> - clocks = <&clks IMX7D_CLK_DUMMY>,
> - <&clks IMX7D_CLK_DUMMY>,
> + clocks = <&clks IMX7D_IPG_ROOT_CLK>,
> + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
> <&clks IMX7D_USDHC1_ROOT_CLK>;
> clock-names = "ipg", "ahb", "per";
> bus-width = <4>;
> @@ -946,8 +946,8 @@
> compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
> reg = <0x30b50000 0x10000>;
> interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
> - clocks = <&clks IMX7D_CLK_DUMMY>,
> - <&clks IMX7D_CLK_DUMMY>,
> + clocks = <&clks IMX7D_IPG_ROOT_CLK>,
> + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
> <&clks IMX7D_USDHC2_ROOT_CLK>;
> clock-names = "ipg", "ahb", "per";
> bus-width = <4>;
> @@ -958,8 +958,8 @@
> compatible = "fsl,imx7d-usdhc", "fsl,imx6sl-usdhc";
> reg = <0x30b60000 0x10000>;
> interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
> - clocks = <&clks IMX7D_CLK_DUMMY>,
> - <&clks IMX7D_CLK_DUMMY>,
> + clocks = <&clks IMX7D_IPG_ROOT_CLK>,
> + <&clks IMX7D_NAND_USDHC_BUS_ROOT_CLK>,
> <&clks IMX7D_USDHC3_ROOT_CLK>;
> clock-names = "ipg", "ahb", "per";
> bus-width = <4>;
> --
> 2.12.1
>
^ permalink raw reply
* [PATCH v2 1/2] clk: imx7d: fix USDHC NAND clock
From: Dong Aisheng @ 2017-04-11 19:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170410210015.1620-1-stefan@agner.ch>
On Mon, Apr 10, 2017 at 02:00:14PM -0700, Stefan Agner wrote:
> The USDHC NAND root clock is not gated by any CCM clock gate. Remove
> the bogus gate definition.
>
> Signed-off-by: Stefan Agner <stefan@agner.ch>
Acked-by: Dong Aisheng <aisheng.dong@nxp.com>
Regards
Dong Aisheng
> ---
> drivers/clk/imx/clk-imx7d.c | 3 +--
> 1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 562055129ed8..93b03640da9b 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -724,7 +724,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
> clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
> clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
> clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
> - clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
> + clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
> clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
> clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
> clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
> @@ -798,7 +798,6 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
> clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
> clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
> clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
> - clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
> clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
> clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
> clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
> --
> 2.12.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [GIT PULL] PCI: Support for configurable PCI endpoint
From: Bjorn Helgaas @ 2017-04-11 19:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170410154328.GB13170@bhelgaas-glaptop.roam.corp.google.com>
On Mon, Apr 10, 2017 at 10:43:28AM -0500, Bjorn Helgaas wrote:
> On Wed, Apr 05, 2017 at 02:22:20PM +0530, Kishon Vijay Abraham I wrote:
> > Hi Bjorn,
> >
> > Please find the pull request for PCI endpoint support below. I've
> > also included all the history here.
>
> Thanks, I applied these (with v7 of the first patch) to pci/host-designware
> for v4.12.
Ok, sorry, I screwed this up. I think my branch actually had v5, not
v6. But I *think* I fixed it. Here's the diff from my branch to your
git tree. Apparently you haven't pushed the v7 patch there, so I
*think* the diff below is the diff between v6 and v7 of that first
patch.
$ git diff pci/host-designware a5c85ba45c96
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
index caa7be10e473..9ae9e59b2a74 100644
--- a/drivers/pci/endpoint/pci-epc-core.c
+++ b/drivers/pci/endpoint/pci-epc-core.c
@@ -83,7 +83,6 @@ struct pci_epc *pci_epc_get(const char *epc_name)
goto err;
}
- class_dev_iter_exit(&iter);
get_device(&epc->dev);
return epc;
}
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
index 6877d6a5bcc9..92db7dcd911c 100644
--- a/drivers/pci/endpoint/pci-epf-core.c
+++ b/drivers/pci/endpoint/pci-epf-core.c
@@ -40,10 +40,8 @@ static struct device_type pci_epf_type;
*/
void pci_epf_linkup(struct pci_epf *epf)
{
- if (!epf->driver) {
+ if (!epf->driver)
dev_WARN(&epf->dev, "epf device not bound to driver\n");
- return;
- }
epf->driver->ops->linkup(epf);
}
@@ -59,10 +57,8 @@ EXPORT_SYMBOL_GPL(pci_epf_linkup);
*/
void pci_epf_unbind(struct pci_epf *epf)
{
- if (!epf->driver) {
+ if (!epf->driver)
dev_WARN(&epf->dev, "epf device not bound to driver\n");
- return;
- }
epf->driver->ops->unbind(epf);
module_put(epf->driver->owner);
@@ -78,10 +74,8 @@ EXPORT_SYMBOL_GPL(pci_epf_unbind);
*/
int pci_epf_bind(struct pci_epf *epf)
{
- if (!epf->driver) {
+ if (!epf->driver)
dev_WARN(&epf->dev, "epf device not bound to driver\n");
- return -EINVAL;
- }
if (!try_module_get(epf->driver->owner))
return -EAGAIN;
@@ -233,7 +227,7 @@ struct pci_epf *pci_epf_create(const char *name)
epf->name = kstrdup(func_name, GFP_KERNEL);
if (!epf->name) {
ret = -ENOMEM;
- goto free_func_name;
+ goto free_epf;
}
dev = &epf->dev;
@@ -255,8 +249,6 @@ struct pci_epf *pci_epf_create(const char *name)
put_dev:
put_device(dev);
kfree(epf->name);
-
-free_func_name:
kfree(func_name);
free_epf:
^ permalink raw reply related
* [GIT PULL] arm64: fixes for -rc6
From: Jon Masters @ 2017-04-11 19:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170407160239.GS19342@arm.com>
On 04/07/2017 12:02 PM, Will Deacon wrote:
> Please pull these two arm64 fixes for -rc6. We've got a regression fix for
> the signal raised when userspace makes an unsupported unaligned access and a
> revert of the contiguous (hugepte) support for hugetlb, which has once again
> been found to be broken. One day, maybe, we'll get it right.
<snip>
> - Revert broken support for the contiguous bit in hugetlb (again...)
Quick aside: is this being worked on for 4.12? If not, should we ping
Linaro and look to get some focus on this? It's right to disable this,
but also painful to those wanting to work on various NFV use cases.
Jon.
--
Computer Architect | Sent from my Fedora powered laptop
^ permalink raw reply
* at91: serial: Can't use DMA on 4.x kernels in RS-485 mode on at91sam9x5
From: Alexandre Belloni @ 2017-04-11 18:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <DM5PR05MB2954F35F2EBB9EEE987F3401BB000@DM5PR05MB2954.namprd05.prod.outlook.com>
Hi,
On 11/04/2017 at 18:32:20 +0000, Bryan Evenson wrote:
> I narrowed my issues down to this commit: https://github.com/linux4sam/linux-at91/commit/0058f0871efe7b01c6f2b3046c68196ab73e96da
>
> tty/serial: atmel: fix RS485 half duplex with DMA
>
> When using DMA, half duplex doesn't work properly because rx is not stopped
> before starting tx. Ensure we call atmel_stop_rx() in the DMA case.
>
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
> Cc: stable <stable@vger.kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>
> If I revert this commit, I can use both TX and RX DMA on all three RS-485 ports (USART0, USART1 and USART3) with the current head of linux-4.4-at91 and linux-4.1-at91 on Atmel's fork. I have not yet tried the mainline releases, but I see that atmel_start_tx() (the function modified by this commit) is identical in mainline so I'm assuming I'll have the same results. In my case I am using my RS-485 ports in half-duplex mode, so the call to atmel_stop_rx() inside of atmel_start_tx() is the cause of my problems.
>
> Anyone know why this would be a problem? The commit makes sense to me and I don't see a good reason why it would break things. I'm willing to test things out to see why this is causing a problem.
>
Do you have b389f173aaa1204d6dc1f299082a162eb0491545 in your tree ?
--
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH v7 resend 00/20] ILP32 for ARM64
From: Florian Weimer @ 2017-04-11 18:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411183636.GB5091@yury-N73SV>
On 04/11/2017 08:36 PM, Yury Norov wrote:
>> Also, the latest benchmarks I've seen were mostly for user space
>> while I'm more concerned with the user-kernel interface
>> (https://marc.info/?l=linux-arm-kernel&m=148690490713310&w=2).
>
>> On the glibc testing side, have the regressions been identified/fixed?
>
> I run LTP for testing the ABI and kernel, and there is no failures in
> ltplite scenario. With glibc testsuite, there's only 3 failures
> comparing to lp64. (Steve, fix me if something changed.) This is
> slides on ilp32 from Linaro Connect, hope you'll find it useful.
>
> https://docs.google.com/presentation/d/1TKZqgH0XJUgMMGkw2fJA3Lzr57slht1sGKYJVBJTNM4/edit?usp=sharing
The listed failures are:
misc/tst-sync_file_range
nptl/tst-stack4
malloc/tst-mallocstate
If necessary, I will fix malloc/tst-mallocstate once there's support for
a new architecture in build-many-glibcs.py. The failure is
architecture-independent, it's related to the lack of a compat symbol
and the difficulty of checking for that at the Makefile or test level.
nptl/tst-stack4 is also a generic failure, I think.
misc/tst-sync_file_range is probably a real failure related to argument
passing. I think this system call was problematic on other
architectures, too.
Thanks,
Florian
(Sorry for the wide Cc: list despite the glibc content.)
^ permalink raw reply
* [PATCH v7 resend 00/20] ILP32 for ARM64
From: Yury Norov @ 2017-04-11 18:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411113334.GA27857@e104818-lin.cambridge.arm.com>
> Also, the latest benchmarks I've seen were mostly for user space
> while I'm more concerned with the user-kernel interface
> (https://marc.info/?l=linux-arm-kernel&m=148690490713310&w=2).
> On the glibc testing side, have the regressions been identified/fixed?
I run LTP for testing the ABI and kernel, and there is no failures in
ltplite scenario. With glibc testsuite, there's only 3 failures
comparing to lp64. (Steve, fix me if something changed.) This is
slides on ilp32 from Linaro Connect, hope you'll find it useful.
https://docs.google.com/presentation/d/1TKZqgH0XJUgMMGkw2fJA3Lzr57slht1sGKYJVBJTNM4/edit?usp=sharing
Yury
^ permalink raw reply
* at91: serial: Can't use DMA on 4.x kernels in RS-485 mode on at91sam9x5
From: Bryan Evenson @ 2017-04-11 18:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <DM5PR05MB29548291A13C348889156EDDBB0C0@DM5PR05MB2954.namprd05.prod.outlook.com>
All,
I found the commit that is causing problems for me. More details below.
> -----Original Message-----
> From: Bryan Evenson
> Sent: Friday, April 07, 2017 10:22 AM
> To: Bryan Evenson <bevenson@melinkcorp.com>; Sylvain Rochet
> <sylvain.rochet@finsecur.com>
> Cc: Nicolas Ferre <nicolas.ferre@atmel.com>; linux-arm-
> kernel at lists.infradead.org
> Subject: RE: at91: serial: Can't use DMA on 4.x kernels in RS-485 mode on
> at91sam9x5
>
> All,
>
> > -----Original Message-----
> > From: linux-arm-kernel [mailto:linux-arm-kernel-
> > bounces at lists.infradead.org] On Behalf Of Bryan Evenson
> > Sent: Tuesday, April 04, 2017 4:48 PM
> > To: Sylvain Rochet <sylvain.rochet@finsecur.com>
> > Cc: Nicolas Ferre <nicolas.ferre@atmel.com>; linux-arm-
> > kernel at lists.infradead.org
> > Subject: RE: at91: serial: Can't use DMA on 4.x kernels in RS-485 mode
> > on
> > at91sam9x5
> >
> >
> > Hi Sylvain,
> >
> > > -----Original Message-----
> > > From: Sylvain Rochet [mailto:sylvain.rochet at finsecur.com]
> > > Sent: Tuesday, April 04, 2017 4:33 PM
> > > To: Bryan Evenson <bevenson@melinkcorp.com>
> > > Cc: linux-arm-kernel at lists.infradead.org; Nicolas Ferre
> > > <nicolas.ferre@atmel.com>
> > > Subject: Re: at91: serial: Can't use DMA on 4.x kernels in RS-485
> > > mode on
> > > at91sam9x5
> > >
> > > Hi Bryan,
> > >
> > > On Tue, Apr 04, 2017 at 08:28:34PM +0000, Bryan Evenson wrote:
> > > >
> > > > With the 3.10 kernel, I had to use the TX DMA only. For some
> > > > reason receive wouldn't work for me with the DMA. Now with the
> > > > latest on the
> > > > linux-4.4-at91 branch I can't use the TX DMA. The data is
> > > > transmitted correctly out the USART (verified on a receiving
> > > > device), but then the return message is not received. I verified
> > > > the same results when both RX&TX DMA was enabled and only when
> the
> > > > TX DMA was enabled. If I use only the RX DMA, everything works
> > > > fine if I have only one device on the RS-485 port. As soon as I
> > > > daisy chain more than one device on an
> > > > RS-485 port, then I start dropping messages. If I turn off both
> > > > the RX and TX DMA, then all data transfers work just fine.
> > > >
> > > > I'd like to get both TX and RX DMA working for all three RS-485 ports.
> > > > Anyone have any suggestions for what to look at to get DMA working
> > > > while in RS-485 mode? I'm planning to start trying a git bisect,
> > > > but given these are different branches I wasn't sure how well that
> > > > was going to work.
>
> I found a working version with my setup. Back at commit
> 1e1257860fd10487795b782f1dbb5b5f2c203474
> (https://github.com/linux4sam/linux-
> at91/commit/1e1257860fd10487795b782f1dbb5b5f2c203474) I can use both
> RX and TX DMA on the RS-485 ports. As recent as commit
> b6f9cb564bcbfff46dc618bb7c246369194dfe11
> (https://github.com/linux4sam/linux-
> at91/commit/b6f9cb564bcbfff46dc618bb7c246369194dfe11) neither the RX
> or TX DMA work for my RS-485 ports. I've been trying to bisect, but this has
> been slow going as I keep getting builds that don't boot (probably because I
> get a commit that is in the middle of a series). I'm assuming the change
> either has to do with the Atmel device tree, the Atmel DMA driver or the
> Atmel serial port driver. My current git bisect I started as follows:
>
> git bisect start -- arch/arm/boot/dts/at91* drivers/tty/serial/atmel_serial.c
> drivers/dma/at_*
>
> If there a section of source code that I should also focus on or if someone
> knows of a specific change I should test, I'd appreciate the suggestion.
I narrowed my issues down to this commit: https://github.com/linux4sam/linux-at91/commit/0058f0871efe7b01c6f2b3046c68196ab73e96da
tty/serial: atmel: fix RS485 half duplex with DMA
When using DMA, half duplex doesn't work properly because rx is not stopped
before starting tx. Ensure we call atmel_stop_rx() in the DMA case.
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
If I revert this commit, I can use both TX and RX DMA on all three RS-485 ports (USART0, USART1 and USART3) with the current head of linux-4.4-at91 and linux-4.1-at91 on Atmel's fork. I have not yet tried the mainline releases, but I see that atmel_start_tx() (the function modified by this commit) is identical in mainline so I'm assuming I'll have the same results. In my case I am using my RS-485 ports in half-duplex mode, so the call to atmel_stop_rx() inside of atmel_start_tx() is the cause of my problems.
Anyone know why this would be a problem? The commit makes sense to me and I don't see a good reason why it would break things. I'm willing to test things out to see why this is causing a problem.
Thanks,
Bryan
>
> Thanks,
> Bryan
>
> > >
> > > Did you check that you didn't run out of available DMA channels on
> > > each DMA controller ? AT91SAM9G25 unfortunately doesn't have much
> of
> > them.
> > >
> >
> > Here's what dmesg is telling me about the DMA channel access when I am
> > enabling DMA on TX only.
> >
> > root at at91sam9x5ek:~# dmesg | grep -E '(DMA|dma)'
> > [ 0.109375] DMA: preallocated 256 KiB pool for atomic coherent allocations
> > [ 0.210937] at_hdmac ffffec00.dma-controller: Atmel AHB DMA Controller
> (
> > cpy set slave sg-cpy ), 8 channels
> > [ 0.218750] at_hdmac ffffee00.dma-controller: Atmel AHB DMA Controller
> (
> > cpy set slave sg-cpy ), 8 channels
> > [ 0.234375] at91_i2c f8010000.i2c: using dma0chan0 (tx) and dma0chan1
> (rx)
> > for DMA transfers
> > [ 0.765625] atmel_nand 40000000.nand: Using dma0chan2 for DMA
> > transfers.
> > [ 0.914062] atmel_spi f0004000.spi: Using dma1chan0 (tx) and dma1chan1
> > (rx) for DMA transfers
> > [ 22.351562] atmel_usart f8020000.serial: using dma0chan3 for tx DMA
> > transfers
> > [ 22.406250] atmel_usart f8028000.serial: using dma1chan2 for tx DMA
> > transfers
> > [ 23.078125] atmel_usart f801c000.serial: using dma0chan4 for tx DMA
> > transfers
> >
> > It looks like there should be enough DMA channels left (eight by my
> > count) for me to also enable RX DMA on all three USARTs.
> >
> > Thanks,
> > Bryan
> >
> > > Sylvain
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCH 1/2] drivers: pci: do not disregard parent resources starting at 0x0
From: Ard Biesheuvel @ 2017-04-11 18:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411163313.18577-2-ard.biesheuvel@linaro.org>
On 11 April 2017 at 17:33, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Commit f44116ae8818 ("PCI: Remove pci_find_parent_resource() use for
> allocation") updated the logic that iterates over all bus resources
> and compares them to a given resource, in order to decide whether one
> is the parent of the latter.
>
> This change inadvertently causes pci_find_parent_resource() to disregard
> resources starting at address 0x0, resulting in an error such as the one
> below on ARM systems whose I/O window starts at 0x0.
>
> pci_bus 0000:00: root bus resource [mem 0x10000000-0x3efeffff window]
> pci_bus 0000:00: root bus resource [io 0x0000-0xffff window]
> pci_bus 0000:00: root bus resource [mem 0x8000000000-0xffffffffff window]
> pci_bus 0000:00: root bus resource [bus 00-0f]
> pci 0000:00:01.0: PCI bridge to [bus 01]
> pci 0000:00:02.0: PCI bridge to [bus 02]
> pci 0000:00:03.0: PCI bridge to [bus 03]
> pci 0000:00:03.0: can't claim BAR 13 [io 0x0000-0x0fff]: no compatible bridge window
> pci 0000:03:01.0: can't claim BAR 0 [io 0x0000-0x001f]: no compatible bridge window
>
> While this never happens on x86, it is perfectly legal in general for a
> PCI MMIO or IO window to start at address 0x0, and it was supported in
> the code before commit f44116ae8818.
>
> So let's drop the test for res->start != 0; resource_contains() already
> checks whether [start, end) completely covers the resource, and so it
> should be redundant.
>
> Fixes: f44116ae8818 ("PCI: Remove pci_find_parent_resource() use for allocation")
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> drivers/pci/pci.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 7904d02ffdb9..53a41b1f7ef7 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -454,7 +454,7 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev,
> pci_bus_for_each_resource(bus, r, i) {
> if (!r)
> continue;
> - if (res->start && resource_contains(r, res)) {
> + if (resource_contains(r, res)) {
>
> /*
> * If the window is prefetchable but the BAR is
Actually, I managed to confuse myself a bit here: $SUBJECT is
inaccurate, given that it is not the parent resource being disregarded
if it starts at 0x0 but the containee.
^ permalink raw reply
* [PATCH v5 2/2] crypto: hw_random - Add new Exynos RNG driver
From: Krzysztof Kozlowski @ 2017-04-11 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411180835.8928-1-krzk@kernel.org>
Replace existing hw_ranndom/exynos-rng driver with a new, reworked one.
This is a driver for pseudo random number generator block which on
Exynos4 chipsets must be seeded with some value. On newer Exynos5420
chipsets it might seed itself from true random number generator block
but this is not implemented yet.
New driver is a complete rework to use the crypto ALGAPI instead of
hw_random API. Rationale for the change:
1. hw_random interface is for true RNG devices.
2. The old driver was seeding itself with jiffies which is not a
reliable source for randomness.
3. Device generates five random 32-bit numbers in each pass but old
driver was returning only one 32-bit number thus its performance was
reduced.
Compatibility with DeviceTree bindings is preserved.
New driver does not use runtime power management but manually enables
and disables the clock when needed. This is preferred approach because
using runtime PM just to toggle clock is huge overhead.
Another difference is reseeding itself with generated random data
periodically and during resuming from system suspend (previously driver
was re-seeding itself again with jiffies).
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Reviewed-by: Stephan M?ller <smueller@chronox.de>
Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
---
MAINTAINERS | 8 +
drivers/char/hw_random/Kconfig | 14 --
drivers/char/hw_random/Makefile | 1 -
drivers/char/hw_random/exynos-rng.c | 231 ---------------------
drivers/crypto/Kconfig | 15 ++
drivers/crypto/Makefile | 1 +
drivers/crypto/exynos-rng.c | 389 ++++++++++++++++++++++++++++++++++++
7 files changed, 413 insertions(+), 246 deletions(-)
delete mode 100644 drivers/char/hw_random/exynos-rng.c
create mode 100644 drivers/crypto/exynos-rng.c
diff --git a/MAINTAINERS b/MAINTAINERS
index affecc6d59f4..371fda859d43 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -10977,6 +10977,14 @@ L: alsa-devel at alsa-project.org (moderated for non-subscribers)
S: Supported
F: sound/soc/samsung/
+SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER
+M: Krzysztof Kozlowski <krzk@kernel.org>
+L: linux-crypto at vger.kernel.org
+L: linux-samsung-soc at vger.kernel.org
+S: Maintained
+F: drivers/crypto/exynos-rng.c
+F: Documentation/devicetree/bindings/rng/samsung,exynos-rng4.txt
+
SAMSUNG FRAMEBUFFER DRIVER
M: Jingoo Han <jingoohan1@gmail.com>
L: linux-fbdev at vger.kernel.org
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 0cafe08919c9..bdae802e7154 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -294,20 +294,6 @@ config HW_RANDOM_POWERNV
If unsure, say Y.
-config HW_RANDOM_EXYNOS
- tristate "EXYNOS HW random number generator support"
- depends on ARCH_EXYNOS || COMPILE_TEST
- depends on HAS_IOMEM
- default HW_RANDOM
- ---help---
- This driver provides kernel-side support for the Random Number
- Generator hardware found on EXYNOS SOCs.
-
- To compile this driver as a module, choose M here: the
- module will be called exynos-rng.
-
- If unsure, say Y.
-
config HW_RANDOM_TPM
tristate "TPM HW Random Number Generator support"
depends on TCG_TPM
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5f52b1e4e7be..6f1eecc2045c 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -24,7 +24,6 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
-obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
deleted file mode 100644
index 23d358553b21..000000000000
--- a/drivers/char/hw_random/exynos-rng.c
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * exynos-rng.c - Random Number Generator driver for the exynos
- *
- * Copyright (C) 2012 Samsung Electronics
- * Jonghwa Lee <jonghwa3.lee@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/hw_random.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/pm_runtime.h>
-#include <linux/err.h>
-
-#define EXYNOS_PRNG_STATUS_OFFSET 0x10
-#define EXYNOS_PRNG_SEED_OFFSET 0x140
-#define EXYNOS_PRNG_OUT1_OFFSET 0x160
-#define SEED_SETTING_DONE BIT(1)
-#define PRNG_START 0x18
-#define PRNG_DONE BIT(5)
-#define EXYNOS_AUTOSUSPEND_DELAY 100
-
-struct exynos_rng {
- struct device *dev;
- struct hwrng rng;
- void __iomem *mem;
- struct clk *clk;
-};
-
-static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset)
-{
- return readl_relaxed(rng->mem + offset);
-}
-
-static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset)
-{
- writel_relaxed(val, rng->mem + offset);
-}
-
-static int exynos_rng_configure(struct exynos_rng *exynos_rng)
-{
- int i;
- int ret = 0;
-
- for (i = 0 ; i < 5 ; i++)
- exynos_rng_writel(exynos_rng, jiffies,
- EXYNOS_PRNG_SEED_OFFSET + 4*i);
-
- if (!(exynos_rng_readl(exynos_rng, EXYNOS_PRNG_STATUS_OFFSET)
- & SEED_SETTING_DONE))
- ret = -EIO;
-
- return ret;
-}
-
-static int exynos_init(struct hwrng *rng)
-{
- struct exynos_rng *exynos_rng = container_of(rng,
- struct exynos_rng, rng);
- int ret = 0;
-
- pm_runtime_get_sync(exynos_rng->dev);
- ret = exynos_rng_configure(exynos_rng);
- pm_runtime_mark_last_busy(exynos_rng->dev);
- pm_runtime_put_autosuspend(exynos_rng->dev);
-
- return ret;
-}
-
-static int exynos_read(struct hwrng *rng, void *buf,
- size_t max, bool wait)
-{
- struct exynos_rng *exynos_rng = container_of(rng,
- struct exynos_rng, rng);
- u32 *data = buf;
- int retry = 100;
- int ret = 4;
-
- pm_runtime_get_sync(exynos_rng->dev);
-
- exynos_rng_writel(exynos_rng, PRNG_START, 0);
-
- while (!(exynos_rng_readl(exynos_rng,
- EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
- cpu_relax();
- if (!retry) {
- ret = -ETIMEDOUT;
- goto out;
- }
-
- exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
-
- *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
-
-out:
- pm_runtime_mark_last_busy(exynos_rng->dev);
- pm_runtime_put_sync_autosuspend(exynos_rng->dev);
-
- return ret;
-}
-
-static int exynos_rng_probe(struct platform_device *pdev)
-{
- struct exynos_rng *exynos_rng;
- struct resource *res;
- int ret;
-
- exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng),
- GFP_KERNEL);
- if (!exynos_rng)
- return -ENOMEM;
-
- exynos_rng->dev = &pdev->dev;
- exynos_rng->rng.name = "exynos";
- exynos_rng->rng.init = exynos_init;
- exynos_rng->rng.read = exynos_read;
- exynos_rng->clk = devm_clk_get(&pdev->dev, "secss");
- if (IS_ERR(exynos_rng->clk)) {
- dev_err(&pdev->dev, "Couldn't get clock.\n");
- return -ENOENT;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- exynos_rng->mem = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(exynos_rng->mem))
- return PTR_ERR(exynos_rng->mem);
-
- platform_set_drvdata(pdev, exynos_rng);
-
- pm_runtime_set_autosuspend_delay(&pdev->dev, EXYNOS_AUTOSUSPEND_DELAY);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
-
- ret = devm_hwrng_register(&pdev->dev, &exynos_rng->rng);
- if (ret) {
- pm_runtime_dont_use_autosuspend(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- }
-
- return ret;
-}
-
-static int exynos_rng_remove(struct platform_device *pdev)
-{
- pm_runtime_dont_use_autosuspend(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-
- return 0;
-}
-
-static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(exynos_rng->clk);
-
- return 0;
-}
-
-static int __maybe_unused exynos_rng_runtime_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
-
- return clk_prepare_enable(exynos_rng->clk);
-}
-
-static int __maybe_unused exynos_rng_suspend(struct device *dev)
-{
- return pm_runtime_force_suspend(dev);
-}
-
-static int __maybe_unused exynos_rng_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
- int ret;
-
- ret = pm_runtime_force_resume(dev);
- if (ret)
- return ret;
-
- return exynos_rng_configure(exynos_rng);
-}
-
-static const struct dev_pm_ops exynos_rng_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(exynos_rng_suspend, exynos_rng_resume)
- SET_RUNTIME_PM_OPS(exynos_rng_runtime_suspend,
- exynos_rng_runtime_resume, NULL)
-};
-
-static const struct of_device_id exynos_rng_dt_match[] = {
- {
- .compatible = "samsung,exynos4-rng",
- },
- { },
-};
-MODULE_DEVICE_TABLE(of, exynos_rng_dt_match);
-
-static struct platform_driver exynos_rng_driver = {
- .driver = {
- .name = "exynos-rng",
- .pm = &exynos_rng_pm_ops,
- .of_match_table = exynos_rng_dt_match,
- },
- .probe = exynos_rng_probe,
- .remove = exynos_rng_remove,
-};
-
-module_platform_driver(exynos_rng_driver);
-
-MODULE_DESCRIPTION("EXYNOS 4 H/W Random Number Generator driver");
-MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 1a60626937e4..7d1fdf6a751c 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -388,6 +388,21 @@ config CRYPTO_DEV_MXC_SCC
This option enables support for the Security Controller (SCC)
found in Freescale i.MX25 chips.
+config CRYPTO_DEV_EXYNOS_RNG
+ tristate "EXYNOS HW pseudo random number generator support"
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ depends on HAS_IOMEM
+ select CRYPTO_RNG
+ ---help---
+ This driver provides kernel-side support through the
+ cryptographic API for the pseudo random number generator hardware
+ found on Exynos SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called exynos-rng.
+
+ If unsure, say Y.
+
config CRYPTO_DEV_S5P
tristate "Support for Samsung S5PV210/Exynos crypto accelerator"
depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile
index 41ca339e89d3..9603f1862b30 100644
--- a/drivers/crypto/Makefile
+++ b/drivers/crypto/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_CRYPTO_DEV_CAVIUM_ZIP) += cavium/
obj-$(CONFIG_CRYPTO_DEV_CCP) += ccp/
obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chelsio/
obj-$(CONFIG_CRYPTO_DEV_CPT) += cavium/cpt/
+obj-$(CONFIG_CRYPTO_DEV_EXYNOS_RNG) += exynos-rng.o
obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/
obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o
obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o
diff --git a/drivers/crypto/exynos-rng.c b/drivers/crypto/exynos-rng.c
new file mode 100644
index 000000000000..451620b475a0
--- /dev/null
+++ b/drivers/crypto/exynos-rng.c
@@ -0,0 +1,389 @@
+/*
+ * exynos-rng.c - Random Number Generator driver for the Exynos
+ *
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
+ *
+ * Loosely based on old driver from drivers/char/hw_random/exynos-rng.c:
+ * Copyright (C) 2012 Samsung Electronics
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#include <crypto/internal/rng.h>
+
+#define EXYNOS_RNG_CONTROL 0x0
+#define EXYNOS_RNG_STATUS 0x10
+#define EXYNOS_RNG_SEED_BASE 0x140
+#define EXYNOS_RNG_SEED(n) (EXYNOS_RNG_SEED_BASE + (n * 0x4))
+#define EXYNOS_RNG_OUT_BASE 0x160
+#define EXYNOS_RNG_OUT(n) (EXYNOS_RNG_OUT_BASE + (n * 0x4))
+
+/* EXYNOS_RNG_CONTROL bit fields */
+#define EXYNOS_RNG_CONTROL_START 0x18
+/* EXYNOS_RNG_STATUS bit fields */
+#define EXYNOS_RNG_STATUS_SEED_SETTING_DONE BIT(1)
+#define EXYNOS_RNG_STATUS_RNG_DONE BIT(5)
+
+/* Five seed and output registers, each 4 bytes */
+#define EXYNOS_RNG_SEED_REGS 5
+#define EXYNOS_RNG_SEED_SIZE (EXYNOS_RNG_SEED_REGS * 4)
+
+/*
+ * Driver re-seeds itself with generated random numbers to increase
+ * the randomness.
+ *
+ * Time for next re-seed in ms.
+ */
+#define EXYNOS_RNG_RESEED_TIME 100
+/*
+ * In polling mode, do not wait infinitely for the engine to finish the work.
+ */
+#define EXYNOS_RNG_WAIT_RETRIES 100
+
+/* Context for crypto */
+struct exynos_rng_ctx {
+ struct exynos_rng_dev *rng;
+};
+
+/* Device associated memory */
+struct exynos_rng_dev {
+ struct device *dev;
+ void __iomem *mem;
+ struct clk *clk;
+ /* Generated numbers stored for seeding during resume */
+ u8 seed_save[EXYNOS_RNG_SEED_SIZE];
+ unsigned int seed_save_len;
+ /* Time of last seeding in jiffies */
+ unsigned long last_seeding;
+};
+
+static struct exynos_rng_dev *exynos_rng_dev;
+
+static u32 exynos_rng_readl(struct exynos_rng_dev *rng, u32 offset)
+{
+ return readl_relaxed(rng->mem + offset);
+}
+
+static void exynos_rng_writel(struct exynos_rng_dev *rng, u32 val, u32 offset)
+{
+ writel_relaxed(val, rng->mem + offset);
+}
+
+static int exynos_rng_set_seed(struct exynos_rng_dev *rng,
+ const u8 *seed, unsigned int slen)
+{
+ u32 val;
+ int i;
+
+ /* Round seed length because loop iterates over full register size */
+ slen = ALIGN_DOWN(slen, 4);
+
+ if (slen < EXYNOS_RNG_SEED_SIZE)
+ return -EINVAL;
+
+ for (i = 0; i < slen ; i += 4) {
+ unsigned int seed_reg = (i / 4) % EXYNOS_RNG_SEED_REGS;
+
+ val = seed[i] << 24;
+ val |= seed[i + 1] << 16;
+ val |= seed[i + 2] << 8;
+ val |= seed[i + 3] << 0;
+
+ exynos_rng_writel(rng, val, EXYNOS_RNG_SEED(seed_reg));
+ }
+
+ val = exynos_rng_readl(rng, EXYNOS_RNG_STATUS);
+ if (!(val & EXYNOS_RNG_STATUS_SEED_SETTING_DONE)) {
+ dev_warn(rng->dev, "Seed setting not finished\n");
+ return -EIO;
+ }
+
+ rng->last_seeding = jiffies;
+
+ return 0;
+}
+
+/*
+ * Read from output registers and put the data under 'dst' array,
+ * up to dlen bytes.
+ *
+ * Returns number of bytes actually stored in 'dst' (dlen
+ * or EXYNOS_RNG_SEED_SIZE).
+ */
+static unsigned int exynos_rng_copy_random(struct exynos_rng_dev *rng,
+ u8 *dst, unsigned int dlen)
+{
+ unsigned int cnt = 0;
+ int i, j;
+ u32 val;
+
+ for (j = 0; j < EXYNOS_RNG_SEED_REGS; j++) {
+ val = exynos_rng_readl(rng, EXYNOS_RNG_OUT(j));
+
+ for (i = 0; i < 4; i++) {
+ dst[cnt] = val & 0xff;
+ val >>= 8;
+ if (++cnt >= dlen)
+ return cnt;
+ }
+ }
+
+ return cnt;
+}
+
+/*
+ * Start the engine and poll for finish. Then read from output registers
+ * filling the 'dst' buffer up to 'dlen' bytes or up to size of generated
+ * random data (EXYNOS_RNG_SEED_SIZE).
+ *
+ * On success: return 0 and store number of read bytes under 'read' address.
+ * On error: return -ERRNO.
+ */
+static int exynos_rng_get_random(struct exynos_rng_dev *rng,
+ u8 *dst, unsigned int dlen,
+ unsigned int *read)
+{
+ int retry = EXYNOS_RNG_WAIT_RETRIES;
+
+ exynos_rng_writel(rng, EXYNOS_RNG_CONTROL_START,
+ EXYNOS_RNG_CONTROL);
+
+ while (!(exynos_rng_readl(rng,
+ EXYNOS_RNG_STATUS) & EXYNOS_RNG_STATUS_RNG_DONE) && --retry)
+ cpu_relax();
+
+ if (!retry)
+ return -ETIMEDOUT;
+
+ /* Clear status bit */
+ exynos_rng_writel(rng, EXYNOS_RNG_STATUS_RNG_DONE,
+ EXYNOS_RNG_STATUS);
+ *read = exynos_rng_copy_random(rng, dst, dlen);
+
+ return 0;
+}
+
+/* Re-seed itself from time to time */
+static void exynos_rng_reseed(struct exynos_rng_dev *rng)
+{
+ unsigned long next_seeding = rng->last_seeding + \
+ msecs_to_jiffies(EXYNOS_RNG_RESEED_TIME);
+ unsigned long now = jiffies;
+ unsigned int read = 0;
+ u8 seed[EXYNOS_RNG_SEED_SIZE];
+
+ if (time_before(now, next_seeding))
+ return;
+
+ if (exynos_rng_get_random(rng, seed, sizeof(seed), &read))
+ return;
+
+ exynos_rng_set_seed(rng, seed, read);
+}
+
+static int exynos_rng_generate(struct crypto_rng *tfm,
+ const u8 *src, unsigned int slen,
+ u8 *dst, unsigned int dlen)
+{
+ struct exynos_rng_ctx *ctx = crypto_rng_ctx(tfm);
+ struct exynos_rng_dev *rng = ctx->rng;
+ unsigned int read = 0;
+ int ret;
+
+ ret = clk_prepare_enable(rng->clk);
+ if (ret)
+ return ret;
+
+ do {
+ ret = exynos_rng_get_random(rng, dst, dlen, &read);
+ if (ret)
+ break;
+
+ dlen -= read;
+ dst += read;
+
+ exynos_rng_reseed(rng);
+ } while (dlen > 0);
+
+ clk_disable_unprepare(rng->clk);
+
+ return ret;
+}
+
+static int exynos_rng_seed(struct crypto_rng *tfm, const u8 *seed,
+ unsigned int slen)
+{
+ struct exynos_rng_ctx *ctx = crypto_rng_ctx(tfm);
+ struct exynos_rng_dev *rng = ctx->rng;
+ int ret;
+
+ ret = clk_prepare_enable(rng->clk);
+ if (ret)
+ return ret;
+
+ ret = exynos_rng_set_seed(ctx->rng, seed, slen);
+
+ clk_disable_unprepare(rng->clk);
+
+ return ret;
+}
+
+static int exynos_rng_kcapi_init(struct crypto_tfm *tfm)
+{
+ struct exynos_rng_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ ctx->rng = exynos_rng_dev;
+
+ return 0;
+}
+
+static struct rng_alg exynos_rng_alg = {
+ .generate = exynos_rng_generate,
+ .seed = exynos_rng_seed,
+ .seedsize = EXYNOS_RNG_SEED_SIZE,
+ .base = {
+ .cra_name = "stdrng",
+ .cra_driver_name = "exynos_rng",
+ .cra_priority = 100,
+ .cra_ctxsize = sizeof(struct exynos_rng_ctx),
+ .cra_module = THIS_MODULE,
+ .cra_init = exynos_rng_kcapi_init,
+ }
+};
+
+static int exynos_rng_probe(struct platform_device *pdev)
+{
+ struct exynos_rng_dev *rng;
+ struct resource *res;
+ int ret;
+
+ if (exynos_rng_dev)
+ return -EEXIST;
+
+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
+ if (!rng)
+ return -ENOMEM;
+
+ rng->dev = &pdev->dev;
+ rng->clk = devm_clk_get(&pdev->dev, "secss");
+ if (IS_ERR(rng->clk)) {
+ dev_err(&pdev->dev, "Couldn't get clock.\n");
+ return PTR_ERR(rng->clk);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rng->mem = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rng->mem))
+ return PTR_ERR(rng->mem);
+
+ platform_set_drvdata(pdev, rng);
+
+ exynos_rng_dev = rng;
+
+ ret = crypto_register_rng(&exynos_rng_alg);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Couldn't register rng crypto alg: %d\n", ret);
+ exynos_rng_dev = NULL;
+ }
+
+ return ret;
+}
+
+static int exynos_rng_remove(struct platform_device *pdev)
+{
+ crypto_unregister_rng(&exynos_rng_alg);
+
+ exynos_rng_dev = NULL;
+
+ return 0;
+}
+
+static int __maybe_unused exynos_rng_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_rng_dev *rng = platform_get_drvdata(pdev);
+ int ret;
+
+ /* If we were never seeded then after resume it will be the same */
+ if (!rng->last_seeding)
+ return 0;
+
+ rng->seed_save_len = 0;
+ ret = clk_prepare_enable(rng->clk);
+ if (ret)
+ return ret;
+
+ /* Get new random numbers and store them for seeding on resume. */
+ exynos_rng_get_random(rng, rng->seed_save, sizeof(rng->seed_save),
+ &(rng->seed_save_len));
+ dev_dbg(rng->dev, "Stored %u bytes for seeding on system resume\n",
+ rng->seed_save_len);
+
+ clk_disable_unprepare(rng->clk);
+
+ return 0;
+}
+
+static int __maybe_unused exynos_rng_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_rng_dev *rng = platform_get_drvdata(pdev);
+ int ret;
+
+ /* Never seeded so nothing to do */
+ if (!rng->last_seeding)
+ return 0;
+
+ ret = clk_prepare_enable(rng->clk);
+ if (ret)
+ return ret;
+
+ ret = exynos_rng_set_seed(rng, rng->seed_save, rng->seed_save_len);
+
+ clk_disable_unprepare(rng->clk);
+
+ return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_suspend,
+ exynos_rng_resume);
+
+static const struct of_device_id exynos_rng_dt_match[] = {
+ {
+ .compatible = "samsung,exynos4-rng",
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(of, exynos_rng_dt_match);
+
+static struct platform_driver exynos_rng_driver = {
+ .driver = {
+ .name = "exynos-rng",
+ .pm = &exynos_rng_pm_ops,
+ .of_match_table = exynos_rng_dt_match,
+ },
+ .probe = exynos_rng_probe,
+ .remove = exynos_rng_remove,
+};
+
+module_platform_driver(exynos_rng_driver);
+
+MODULE_DESCRIPTION("Exynos H/W Random Number Generator driver");
+MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
+MODULE_LICENSE("GPL");
--
2.9.3
^ permalink raw reply related
* [PATCH v5 1/2] linux/kernel.h: Add ALIGN_DOWN macro
From: Krzysztof Kozlowski @ 2017-04-11 18:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20170411180835.8928-1-krzk@kernel.org>
Few parts of kernel define their own macro for aligning down so provide
a common define for this, with the same usage and assumptions as existing
ALIGN.
Convert also three existing implementations to this one.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
The metag change was not even compiled due to lack of cross compiler.
---
arch/metag/kernel/stacktrace.c | 2 --
drivers/gpu/drm/udl/udl_fb.c | 2 +-
include/linux/kernel.h | 1 +
include/video/udlfb.h | 2 +-
4 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/arch/metag/kernel/stacktrace.c b/arch/metag/kernel/stacktrace.c
index 91ffc4b75c33..09d67b7f51ca 100644
--- a/arch/metag/kernel/stacktrace.c
+++ b/arch/metag/kernel/stacktrace.c
@@ -31,8 +31,6 @@ static void tbi_boing_init(void)
}
#endif
-#define ALIGN_DOWN(addr, size) ((addr)&(~((size)-1)))
-
/*
* Unwind the current stack frame and store the new register values in the
* structure passed as argument. Unwinding is equivalent to a function return,
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c
index d05abc69e305..4a6500362564 100644
--- a/drivers/gpu/drm/udl/udl_fb.c
+++ b/drivers/gpu/drm/udl/udl_fb.c
@@ -37,7 +37,7 @@ struct udl_fbdev {
};
#define DL_ALIGN_UP(x, a) ALIGN(x, a)
-#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
+#define DL_ALIGN_DOWN(x, a) ALIGN_DOWN(x, a)
/** Read the red component (0..255) of a 32 bpp colour. */
#define DLO_RGB_GETRED(col) (uint8_t)((col) & 0xFF)
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 4c26dc3a8295..3d9f8420f973 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -47,6 +47,7 @@
/* @a is a power of 2 value */
#define ALIGN(x, a) __ALIGN_KERNEL((x), (a))
+#define ALIGN_DOWN(x, a) __ALIGN_KERNEL((x) - ((a) - 1), (a))
#define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask))
#define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a)))
#define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0)
diff --git a/include/video/udlfb.h b/include/video/udlfb.h
index f9466fa54ba4..3ea90aea5617 100644
--- a/include/video/udlfb.h
+++ b/include/video/udlfb.h
@@ -92,6 +92,6 @@ struct dlfb_data {
/* remove these once align.h patch is taken into kernel */
#define DL_ALIGN_UP(x, a) ALIGN(x, a)
-#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
+#define DL_ALIGN_DOWN(x, a) ALIGN_DOWN(x, a)
#endif
--
2.9.3
^ permalink raw reply related
* [PATCH v5 0/2] crypto: hw_random - Add new Exynos RNG driver
From: Krzysztof Kozlowski @ 2017-04-11 18:08 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This is a follow up of my questions around exynos-rng [1].
Changes since v4:
=================
1. Patch 2/2: Use "stdrng" name, as suggested by Herbert.
2. Patch 2/2: Add Bartlomiej's reviewed-by.
Changes since v3:
=================
1. New patch: 1/2 for ALIGN_DOWN macro. The change in metag architecture
was not compiled. Please test it.
2. Dropped patches touching ARM defconfig as they are not changing and
they pollute this submission.
3. Utilize all seed provided by kcapi (suggested by Stephan M?ller).
4. Drop dev->ctx (suggested by PrasannaKumar Muralidharan).
5. Remove any printks from set_seed callback as this might be a way
for unprivileged user to pollute the log (suggested by Stephan).
6. Minor cleanups: initialize 'read' variable in exynos_rng_reseed()
for readability (it is not strictly required).
7. Add review tags from Stephen and PrasannaKumar.
Changes since v2:
=================
1. Do not re-use random numbers for re-seed (neither for system resume
nor for periodic re-seed). Instead the driver will just generate new
random numbers (suggested by Stephan M?ller).
Suspend path tested with suspend-to-freeze, not real suspend. Testing
on Trats2 would be welcomed.
Changes since v1:
=================
1. Re-work the code for seeding after system resume, following suggestions
and review by Stephan M?ller.
2. Re-seed itself from time to time (every 100 ms), suggested by Stephan
M?ller.
3. Use a define for retries (Bartlomiej Zolnierkiewicz).
4. Add some docs.
Description:
============
The existing exynos-rng has many issues. The most important one is that
it is a pseudo RNG device but uses hw_random interface which does not allow
proper seeding.
The RNG module on Exynos4 requires seeding. On newer SoCs (like Exynos5420)
it can seed itself from a true RNG. Converting the existing driver
to use TRNG would effectively drop support for Exynos4 and break
compatibility with existing users.
Instead I decided to convert it to crypto API. In the future I hope
to add support for seeding from TRNG module.
Tested with app [2].
Patches are independent. I will take the defconfig changes (2/3 and 3/3)
through samsung-soc tree.
Best regards,
Krzysztof
[1] https://www.spinics.net/lists/arm-kernel/msg569641.html
[2] https://www.spinics.net/lists/arm-kernel/msg571184.html
Krzysztof Kozlowski (2):
linux/kernel.h: Add ALIGN_DOWN macro
crypto: hw_random - Add new Exynos RNG driver
MAINTAINERS | 8 +
arch/metag/kernel/stacktrace.c | 2 -
drivers/char/hw_random/Kconfig | 14 --
drivers/char/hw_random/Makefile | 1 -
drivers/char/hw_random/exynos-rng.c | 231 ---------------------
drivers/crypto/Kconfig | 15 ++
drivers/crypto/Makefile | 1 +
drivers/crypto/exynos-rng.c | 389 ++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/udl/udl_fb.c | 2 +-
include/linux/kernel.h | 1 +
include/video/udlfb.h | 2 +-
11 files changed, 416 insertions(+), 250 deletions(-)
delete mode 100644 drivers/char/hw_random/exynos-rng.c
create mode 100644 drivers/crypto/exynos-rng.c
--
2.9.3
^ permalink raw reply
* [RFC PATCH v0.2] PCI: Add support for tango PCIe host bridge
From: Mason @ 2017-04-11 17:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <67014006-a380-9e3b-c9af-a421052cb8e0@arm.com>
On 11/04/2017 18:43, Marc Zyngier wrote:
> On 11/04/17 17:26, Mason wrote:
>
>> Is there a function to map virq to the hwirq in any domain?
>
> Be more precise. If you want the hwirq associated with the view of a
> virq in a given domain, that's the hwirq field in the corresponding
> irq_data structure. Or are you after something else?
I registered an unmask method for my irq_chip.
(IIUC, I'm supposed to unmask a specific MSI in this callback.)
# cat /proc/interrupts
CPU0 CPU1
30: 0 0 MSIfoo 0 Edge aerdrv
34: 0 0 MSIfoo 524288 Edge xhci_hcd
35: 0 0 MSIfoo 524289 Edge xhci_hcd
36: 0 0 MSIfoo 524290 Edge xhci_hcd
void foo_unmask(struct irq_data *data)
{
int xx,yy;
struct irq_domain *dom = data->domain;
printk("%s: irq_data=%p irq=%u hwirq=%lu chip=%p dom=%p pdata=%p data=%p\n",
__func__, data, data->irq, data->hwirq, data->chip, data->domain,
data->parent_data, data->chip_data);
printk("%s ops=%p data=%p parent=%p\n\n",
dom->name, dom->ops, dom->host_data, dom->parent);
printk("pcie=%p\n", dom->parent->host_data);
//dump_stack();
pci_msi_unmask_irq(data);
struct tango_pcie *pcie = data->domain->parent->host_data;
printk("\n%s: pcie=%p irq=%u hwirq=%lu\n\n",
__func__, pcie, data->irq, data->hwirq);
xx = irq_find_mapping(pcie->irq_domain, data->hwirq);
yy = irq_find_mapping(pcie->msi_domain, data->hwirq);
printk("xx=%d yy=%d\n", xx, yy);
}
so data->irq is the virq (30, 34, 35, 36)
and data->hwirq is the domain hwirq (0, 524288, 524289, 524290)
Is there a way to map hwirq 524288 to MSI 0, hwirq 524289 to MSI 1, etc?
Regards.
^ permalink raw reply
* [RFC PATCH 3/3] cpufreq: imx6q: refine clk operations
From: Leonard Crestez @ 2017-04-11 17:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-4-git-send-email-aisheng.dong@nxp.com>
On Wed, 2017-04-12 at 12:03 +0800, Dong Aisheng wrote:
> +static int num_clks;
> +static struct clk_bulk_data clks[] = {
> + { .id = "arm" },
> + { .id = "pll1_sys" },
> + { .id = "step" },
> + { .id = "pll1_sw" },
> + { .id = "pll2_pfd2_396m" },
> + { .id = "pll2_bus" },
> + { .id = "secondary_sel" },
> +};
The .id is only required for initialization, it seems strange to keep
it around runtime data. It might be better for this API to work with an
array of clk* and separate array of names (or clk_bulk_init_data if we
need flags). Variable references would be shorter and it would allow
more data to be const.
> -put_clk:
> - if (!IS_ERR(arm_clk))
> - clk_put(arm_clk);
> - if (!IS_ERR(pll1_sys_clk))
> - clk_put(pll1_sys_clk);
> - if (!IS_ERR(pll1_sw_clk))
> - clk_put(pll1_sw_clk);
> - if (!IS_ERR(step_clk))
> - clk_put(step_clk);
> - if (!IS_ERR(pll2_pfd2_396m_clk))
> - clk_put(pll2_pfd2_396m_clk);
> - if (!IS_ERR(pll2_bus_clk))
> - clk_put(pll2_bus_clk);
> - if (!IS_ERR(secondary_sel_clk))
> - clk_put(secondary_sel_clk);
> +
> + clk_bulk_put(num_clks, clks);
> +put_node:
> ? of_node_put(np);
> +
> ? return ret;
> ?}
My subjective opinion is that a better way to clean this up would be to
have a single imx6q_cpufreq_clean function that takes all resources and
does stuff like:
if (!IS_ERR(clk)) clk_put(clk);
clk = NULL;
That function can be called from both _remove and failed _probe without
having to keep track of which resources have been allocated until then.
Just free and NULL all clocks/regulators and simplify control flow.
--
Regards,
Leonard
^ permalink raw reply
* [PATCH v2 1/5] dt-bindings: gpu: add bindings for the ARM Mali Midgard GPU
From: Guillaume Tucker @ 2017-04-11 17:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a01a50d3-bb1b-2c56-2a15-30651fa2fac9@baylibre.com>
On 03/04/17 09:12, Neil Armstrong wrote:
> On 04/02/2017 09:59 AM, Guillaume Tucker wrote:
>> The ARM Mali Midgard GPU family is present in a number of SoCs
>> from many different vendors such as Samsung Exynos and Rockchip.
>>
>> Import the device tree bindings documentation from the r16p0
>> release of the Mali Midgard GPU kernel driver:
>>
>> https://developer.arm.com/-/media/Files/downloads/mali-drivers/kernel/mali-midgard-gpu/TX011-SW-99002-r16p0-00rel0.tgz
>>
>> The following optional bindings have been omitted in this initial
>> version as they are only used in very specific cases:
>>
>> * snoop_enable_smc
>> * snoop_disable_smc
>> * jm_config
>> * power_model
>> * system-coherency
>> * ipa-model
>>
>> The example has been simplified accordingly.
>>
>> The compatible string definition has been limited to
>> "arm,mali-midgard" to avoid checkpatch.pl warnings and to match
>> what the driver actually expects (as of r16p0 out-of-tree).
>>
>> CC: John Reitan <john.reitan@arm.com>
>> Signed-off-by: Guillaume Tucker <guillaume.tucker@collabora.com>
>> ---
>> .../devicetree/bindings/gpu/arm,mali-midgard.txt | 53 ++++++++++++++++++++++
>> 1 file changed, 53 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
>>
>> diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
>> new file mode 100644
>> index 000000000000..da8fc6d21bbf
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
>> @@ -0,0 +1,53 @@
>> +#
>> +# (C) COPYRIGHT 2013-2016 ARM Limited.
>> +# Copyright (C) 2017 Collabora Ltd
>> +#
>> +# This program is free software and is provided to you under the terms of the
>> +# GNU General Public License version 2 as published by the Free Software
>> +# Foundation, and any use by you of this program is subject to the terms
>> +# of such GNU licence.
>> +#
> Hi Guillaume,
> This is unnecessary, please remove.
Hi Neil,
I see most other documentation files don't have such a header,
including the arm,mali-utgard.txt one. I left it in my patch
after copying the file from the driver tarball as removing it
didn't seem right from a GPL and copyright point of view. If
it's safe in practice to remove it then fine.
>> +
>> +
>> +ARM Mali Midgard GPU
>> +====================
>> +
>> +Required properties:
>> +
>> +- compatible : Should be "arm,mali-midgard".
>> +- reg : Physical base address of the device and length of the register area.
>> +- interrupts : Contains the three IRQ lines required by Mali Midgard devices.
>> +- interrupt-names : Contains the names of IRQ resources in the order they were
>> + provided in the interrupts property. Must contain: "JOB, "MMU", "GPU".
>
>
> Please follow the bindings introduced for the utgard family :
> https://patchwork.kernel.org/patch/9553745/
>
> - an entry for each mali-midgard revision, i.e. "arm,mali-t820"
Sure. It's a bit more complicated with Midgard (more variants,
some have the number of cores in the last digit...) but it should
be possible to put together a suitable list in v3.
> - an entry for each vendor specific wrapping if necessary, i.e. "amlogic,meson-gxm-mali"
Well, fine although I'm a bit confused about this - please see
below.
> - low-case for interrupt names
OK, can change that in v3. It means however that the out-of-tree
driver will need to be patched as it's looking for these names in
capital letters. This shouldn't be a big issue but adds a bit of
work to anyone maintaining a kernel driver package.
>> +
>> +Optional:
>> +
>> +- clocks : Phandle to clock for the Mali Midgard device.
>> +- clock-names : Shall be "clk_mali".
>> +- mali-supply : Phandle to regulator for the Mali device. Refer to
>> + Documentation/devicetree/bindings/regulator/regulator.txt for details.
>> +- operating-points : Refer to Documentation/devicetree/bindings/power/opp.txt
>> + for details.
>
> Please add :
> * Must be one of the following:
> "arm,mali-t820"
> * And, optionally, one of the vendor specific compatible:
> "amlogic,meson-gxm-mali"
>
> with my Ack for the amlogic platform.
It seems to me that as long as the GPU architecture hasn't been
modified (I don't think I've ever encountered such a case) then
it has to be a standard ARM Mali type regardless of the SoC
vendor. So unless a Mali-T820 in the Amlogic S912 SoC is not the
same as a T820 in a different SoC, please forgive me but I don't
understand why a vendor compatible string is needed. My main
concern is that it's going to be very hard to keep that list
up-to-date with all existing Midgard SoC variants. If do we need
to add vendor compatible strings to correctly describe the
hardware then I'm happy to add the amlogic one in my patch v3; I
would just like to understand why that's necessary.
Thanks,
Guillaume
^ permalink raw reply
* [RFC PATCH 1/3] clk: add clk_bulk_get accessories
From: Leonard Crestez @ 2017-04-11 17:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-2-git-send-email-aisheng.dong@nxp.com>
On Wed, 2017-04-12 at 12:03 +0800, Dong Aisheng wrote:
> +/**
> + * clk_bulk_enable - ungate a bulk of clocks
> + * @num_clks: the number of clk_bulk_data
> + * @clks: the clk_bulk_data table being ungated
> + *
> + * clk_bulk_enable must not sleep
> + * Returns 0 on success, -EERROR otherwise.
> + */
> +int clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
> +{
> +???????int ret;
> +???????int i;
> +
> +???????for (i = 0; i < num_clks; i++) {
> +???????????????ret = clk_enable(clks[i].clk);
> +???????????????if (ret) {
> +???????????????????????pr_err("Failed to enable clk '%s': %d\n",
> +???????????????????????????????clks[i].id, ret);
> +???????????????????????goto err;
> +???????????????}
> +???????}
> +
> +???????return 0;
> +
> +err:
> +???????while (--i >= 0)
> +???????????????clk_put(clks[i].clk);
Shouldn't this be clk_disable?
And you can probably use clk_bulk_disable(i, clks) instead
^ permalink raw reply
* [PATCH V14 01/10] acpi: apei: read ack upon ghes record consumption
From: Borislav Petkov @ 2017-04-11 17:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1490729440-32591-2-git-send-email-tbaicar@codeaurora.org>
On Tue, Mar 28, 2017 at 01:30:31PM -0600, Tyler Baicar wrote:
> A RAS (Reliability, Availability, Serviceability) controller
> may be a separate processor running in parallel with OS
> execution, and may generate error records for consumption by
> the OS. If the RAS controller produces multiple error records,
> then they may be overwritten before the OS has consumed them.
>
> The Generic Hardware Error Source (GHES) v2 structure
> introduces the capability for the OS to acknowledge the
> consumption of the error record generated by the RAS
> controller. A RAS controller supporting GHESv2 shall wait for
> the acknowledgment before writing a new error record, thus
> eliminating the race condition.
>
> Add support for parsing of GHESv2 sub-tables as well.
>
> Signed-off-by: Tyler Baicar <tbaicar@codeaurora.org>
> CC: Jonathan (Zhixiong) Zhang <zjzhang@codeaurora.org>
> Reviewed-by: James Morse <james.morse@arm.com>
> ---
> drivers/acpi/apei/ghes.c | 49 +++++++++++++++++++++++++++++++++++++++++++++---
> drivers/acpi/apei/hest.c | 7 +++++--
> include/acpi/ghes.h | 5 ++++-
> 3 files changed, 55 insertions(+), 6 deletions(-)
...
> @@ -249,10 +254,18 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic)
> ghes = kzalloc(sizeof(*ghes), GFP_KERNEL);
> if (!ghes)
> return ERR_PTR(-ENOMEM);
> +
> ghes->generic = generic;
> + if (IS_HEST_TYPE_GENERIC_V2(ghes)) {
> + rc = apei_map_generic_address(
> + &ghes->generic_v2->read_ack_register);
Yeah, that linebreak just to keep the 80-cols rule makes the code ugly
and hard to read.
Please put that mapping and unmapping in wrappers called
map_gen_v2(ghes) and unmap_gen_v2(ghes) or so, so that you can call them
wherever needed. Thus should make the flow a bit more understandable
what's going on and you won't have to repeat the unmapping lines in
ghes_fini().
> @@ -649,6 +669,23 @@ static void ghes_estatus_cache_add(
> rcu_read_unlock();
> }
>
> +static int ghes_ack_error(struct acpi_hest_generic_v2 *generic_v2)
> +{
> + int rc;
> + u64 val = 0;
> +
> + rc = apei_read(&val, &generic_v2->read_ack_register);
> + if (rc)
> + return rc;
> + val &= generic_v2->read_ack_preserve <<
> + generic_v2->read_ack_register.bit_offset;
> + val |= generic_v2->read_ack_write <<
> + generic_v2->read_ack_register.bit_offset;
Yeah, let them stick out, it more readable this way. Line spacing is
helpful too:
...
rc = apei_read(&val, &generic_v2->read_ack_register);
if (rc)
return rc;
val &= generic_v2->read_ack_preserve << generic_v2->read_ack_register.bit_offset;
val |= generic_v2->read_ack_write << generic_v2->read_ack_register.bit_offset;
return apei_write(val, &generic_v2->read_ack_register);
}
> + rc = apei_write(val, &generic_v2->read_ack_register);
> +
> + return rc;
> +}
> +
> static int ghes_proc(struct ghes *ghes)
> {
> int rc;
--
Regards/Gruss,
Boris.
Good mailing practices for 400: avoid top-posting and trim the reply.
^ permalink raw reply
* [PATCH 4/5] Hot-remove implementation for arm64
From: Mark Rutland @ 2017-04-11 17:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <897973dd5d3fc91c70aba4b44350099a61c3a12c.1491920513.git.ar@linux.vnet.ibm.com>
Hi,
On Tue, Apr 11, 2017 at 03:55:42PM +0100, Andrea Reale wrote:
> +static inline unsigned long pmd_page_vaddr(pmd_t pmd)
> +{
> + return (unsigned long) __va(pmd_page_paddr(pmd));
> +}
> +
> /* Find an entry in the third-level page table. */
> #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
>
> @@ -450,6 +455,11 @@ static inline phys_addr_t pud_page_paddr(pud_t pud)
> return pud_val(pud) & PHYS_MASK & (s32)PAGE_MASK;
> }
>
> +static inline unsigned long pud_page_vaddr(pud_t pud)
> +{
> + return (unsigned long) __va(pud_page_paddr(pud));
> +}
> +
> /* Find an entry in the second-level page table. */
> #define pmd_index(addr) (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1))
>
> @@ -502,6 +512,11 @@ static inline phys_addr_t pgd_page_paddr(pgd_t pgd)
> return pgd_val(pgd) & PHYS_MASK & (s32)PAGE_MASK;
> }
>
> +static inline unsigned long pgd_page_vaddr(pgd_t pgd)
> +{
> + return (unsigned long) __va(pgd_page_paddr(pgd));
> +}
> +
These duplicate the existing p*d_offset*() functions, and I do not think
they are necessary. More on that below.
[...]
> @@ -551,7 +551,6 @@ int arch_add_memory(int nid, u64 start, u64 size, bool for_device)
> unsigned long nr_pages = size >> PAGE_SHIFT;
> unsigned long end_pfn = start_pfn + nr_pages;
> unsigned long max_sparsemem_pfn = 1UL << (MAX_PHYSMEM_BITS-PAGE_SHIFT);
> - unsigned long pfn;
> int ret;
>
> if (end_pfn > max_sparsemem_pfn) {
Should this have been part of a prior patch?
This patch doesn't remove any users of this variable.
[...]
> +static void free_pagetable(struct page *page, int order, bool direct)
This "direct" parameter needs a better name, and a description in a
comment block above this function.
> +{
> + unsigned long magic;
> + unsigned int nr_pages = 1 << order;
> + struct vmem_altmap *altmap = to_vmem_altmap((unsigned long) page);
> +
> + if (altmap) {
> + vmem_altmap_free(altmap, nr_pages);
> + return;
> + }
> +
> + /* bootmem page has reserved flag */
> + if (PageReserved(page)) {
> + __ClearPageReserved(page);
> +
> + magic = (unsigned long)page->lru.next;
> + if (magic == SECTION_INFO || magic == MIX_SECTION_INFO) {
> + while (nr_pages--)
> + put_page_bootmem(page++);
> + } else {
> + while (nr_pages--)
> + free_reserved_page(page++);
> + }
> + } else {
> + /*
> + * Only direct pagetable allocation (those allocated via
> + * hotplug) call the pgtable_page_ctor; vmemmap pgtable
> + * allocations don't.
> + */
> + if (direct)
> + pgtable_page_dtor(page);
> +
> + free_pages((unsigned long)page_address(page), order);
> + }
> +}
This largely looks like a copy of the x86 code. Why can that not be
factored out to an arch-neutral location?
> +
> +static void free_pte_table(pmd_t *pmd, bool direct)
> +{
> + pte_t *pte_start, *pte;
> + struct page *page;
> + int i;
> +
> + pte_start = (pte_t *) pmd_page_vaddr(*pmd);
> + /* Check if there is no valid entry in the PMD */
> + for (i = 0; i < PTRS_PER_PTE; i++) {
> + pte = pte_start + i;
> + if (!pte_none(*pte))
> + return;
> + }
If we must walk the tables in this way, please use the existing pattern
from arch/arm64/mm/dump.c.
e.g.
pte_t *pte;
pte = pte_offset_kernel(pmd, 0UL);
for (i = 0; i < PTRS_PER_PTE; i++, pte++)
if (!pte_none)
return;
> +
> + page = pmd_page(*pmd);
> +
> + free_pagetable(page, 0, direct);
The page has been freed here, and may be subject to arbitrary
modification...
> +
> + /*
> + * This spin lock could be only taken in _pte_aloc_kernel
> + * in mm/memory.c and nowhere else (for arm64). Not sure if
> + * the function above can be called concurrently. In doubt,
> + * I am living it here for now, but it probably can be removed
> + */
> + spin_lock(&init_mm.page_table_lock);
> + pmd_clear(pmd);
... but we only remove it from the page tables here, so the page table
walkers can see junk in the tables, were the page reused in the mean
timer.
After clearing the PMD, it needs to be cleared from TLBs. We allow
partial walks to be cached, so the TLBs may still start walking this
entry or beyond.
> + spin_unlock(&init_mm.page_table_lock);
> +}
The same comments apply to all the free_p*d_table() functions, so I
shan't repeat them.
[...]
> +static void remove_pte_table(pte_t *pte, unsigned long addr,
> + unsigned long end, bool direct)
> +{
> + unsigned long next;
> + void *page_addr;
> +
> + for (; addr < end; addr = next, pte++) {
> + next = (addr + PAGE_SIZE) & PAGE_MASK;
> + if (next > end)
> + next = end;
Please use the usual p*d_addr_end() functions. See alloc_init_pmd() and
friends in arch/arm64/mm/mmu.c for examples of how to use them.
> +
> + if (!pte_present(*pte))
> + continue;
> +
> + if (PAGE_ALIGNED(addr) && PAGE_ALIGNED(next)) {
When would those addresses *not* be page-aligned? By construction, next
must be. Unplugging partial pages of memory makes no sense, so surely
addr is page-aligned when passed in?
> + /*
> + * Do not free direct mapping pages since they were
> + * freed when offlining, or simplely not in use.
> + */
> + if (!direct)
> + free_pagetable(pte_page(*pte), 0, direct);
> +
> + /*
> + * This spin lock could be only
> + * taken in _pte_aloc_kernel in
> + * mm/memory.c and nowhere else
> + * (for arm64). Not sure if the
> + * function above can be called
> + * concurrently. In doubt,
> + * I am living it here for now,
> + * but it probably can be removed.
> + */
> + spin_lock(&init_mm.page_table_lock);
> + pte_clear(&init_mm, addr, pte);
> + spin_unlock(&init_mm.page_table_lock);
> + } else {
> + /*
> + * If we are here, we are freeing vmemmap pages since
> + * direct mapped memory ranges to be freed are aligned.
> + *
> + * If we are not removing the whole page, it means
> + * other page structs in this page are being used and
> + * we canot remove them. So fill the unused page_structs
> + * with 0xFD, and remove the page when it is wholly
> + * filled with 0xFD.
> + */
> + memset((void *)addr, PAGE_INUSE, next - addr);
What's special about 0xFD?
Why do we need to mess with the page array in this manner? Why can't we
detect when a range is free by querying memblock, for example?
> +
> + page_addr = page_address(pte_page(*pte));
> + if (!memchr_inv(page_addr, PAGE_INUSE, PAGE_SIZE)) {
> + free_pagetable(pte_page(*pte), 0, direct);
> +
> + /*
> + * This spin lock could be only
> + * taken in _pte_aloc_kernel in
> + * mm/memory.c and nowhere else
> + * (for arm64). Not sure if the
> + * function above can be called
> + * concurrently. In doubt,
> + * I am living it here for now,
> + * but it probably can be removed.
> + */
> + spin_lock(&init_mm.page_table_lock);
> + pte_clear(&init_mm, addr, pte);
> + spin_unlock(&init_mm.page_table_lock);
This logic appears to be duplicated with the free_*_table functions, and
looks incredibly suspicious.
To me, it doesn't make sense that we'd need the lock *only* to alter the
leaf entries.
> + }
> + }
> + }
> +
> + // I am adding this flush here in simmetry to the x86 code.
> + // Why do I need to call it here and not in remove_p[mu]d
> + flush_tlb_all();
If the page tables weren't freed until this point, it might be that this
is just amortizing the cost of removing them from the TLBs.
Given that they're freed first, this makes no sense to me.
> +}
The same commenst apply to all the remove_p*d_table() functions, so I
shan't repeat them.
> +
> +static void remove_pmd_table(pmd_t *pmd, unsigned long addr,
> + unsigned long end, bool direct)
> +{
> + unsigned long next;
> + void *page_addr;
> + pte_t *pte;
> +
> + for (; addr < end; addr = next, pmd++) {
> + next = pmd_addr_end(addr, end);
> +
> + if (!pmd_present(*pmd))
> + continue;
> +
> + // check if we are using 2MB section mappings
> + if (pmd_sect(*pmd)) {
> + if (PAGE_ALIGNED(addr) && PAGE_ALIGNED(next)) {
Surely you're intending to check if you can free the whole pmd? i.e.
that addr and next are pmd-aligned?
Can we ever be in a situation where we're requested to free a partial
pmd that could be section mapped?
If that's the case, we'll *need* to split the pmd, which we can't do on
live page tables.
> + if (!direct) {
> + free_pagetable(pmd_page(*pmd),
> + get_order(PMD_SIZE), direct);
> + }
> + /*
> + * This spin lock could be only
> + * taken in _pte_aloc_kernel in
> + * mm/memory.c and nowhere else
> + * (for arm64). Not sure if the
> + * function above can be called
> + * concurrently. In doubt,
> + * I am living it here for now,
> + * but it probably can be removed.
> + */
> + spin_lock(&init_mm.page_table_lock);
> + pmd_clear(pmd);
> + spin_unlock(&init_mm.page_table_lock);
> + } else {
> + /* If here, we are freeing vmemmap pages. */
> + memset((void *)addr, PAGE_INUSE, next - addr);
> +
> + page_addr = page_address(pmd_page(*pmd));
> + if (!memchr_inv(page_addr, PAGE_INUSE,
> + PMD_SIZE)) {
> + free_pagetable(pmd_page(*pmd),
> + get_order(PMD_SIZE), direct);
> +
> + /*
> + * This spin lock could be only
> + * taken in _pte_aloc_kernel in
> + * mm/memory.c and nowhere else
> + * (for arm64). Not sure if the
> + * function above can be called
> + * concurrently. In doubt,
> + * I am living it here for now,
> + * but it probably can be removed.
> + */
> + spin_lock(&init_mm.page_table_lock);
> + pmd_clear(pmd);
> + spin_unlock(&init_mm.page_table_lock);
> + }
I don't think this is correct.
If we're getting rid of a partial pmd, we *must* split the pmd.
Otherwise, we're leaving bits mapped that should not be. If we split the
pmd, we can free the individual pages as we would for a non-section
mapping.
As above, we can't split block entries within live tables, so that will
be painful at best.
If we can't split a pmd, hen we cannot free a partial pmd, and will need
to reject request to do so.
The same comments (with s/pmu/pud/, etc) apply for the higher level
remove_p*d_table functions.
[...]
> +void remove_pagetable(unsigned long start, unsigned long end, bool direct)
> +{
> + unsigned long next;
> + unsigned long addr;
> + pgd_t *pgd;
> + pud_t *pud;
> +
> + for (addr = start; addr < end; addr = next) {
> + next = pgd_addr_end(addr, end);
> +
> + pgd = pgd_offset_k(addr);
> + if (pgd_none(*pgd))
> + continue;
> +
> + pud = pud_offset(pgd, addr);
> + remove_pud_table(pud, addr, next, direct);
> + /*
> + * When the PUD is folded on the PGD (three levels of paging),
> + * I did already clear the PMD page in free_pmd_table,
> + * and reset the corresponding PGD==PUD entry.
> + */
> +#if CONFIG_PGTABLE_LEVELS > 3
> + free_pud_table(pgd, direct);
> #endif
This looks suspicious. Shouldn't we have a similar check for PMD, to
cater for CONFIG_PGTABLE_LEVELS == 2? e.g. 64K pages, 42-bit VA.
We should be able to hide this distinction in helpers for both cases.
> + }
> +
> + flush_tlb_all();
This is too late to be useful.
Thanks,
Mark.
^ permalink raw reply
* [RFC PATCH 0/3] clk: introduce clk_bulk_get accessories
From: Florian Fainelli @ 2017-04-11 17:01 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1491969809-20154-1-git-send-email-aisheng.dong@nxp.com>
On 04/11/2017 09:03 PM, Dong Aisheng wrote:
> These helper function allows drivers to get several clk consumers in
> one operation. If any of the clk cannot be acquired then any clks
> that were got will be put before returning to the caller.
>
> The idea firstly came out when i wanted to clean up and optimize
> imx6q-cpufreq driver which needs to handle a lot of clocks as it
> becomes a bit mess.
>
> e.g. drivers/cpufreq/imx6q-cpufreq.c
>
> You will see we need get 7 clocks during driver probe.
> (Add there will be more, e.g. pll1, pll1_bypass, pll1_bypass_src,
> in the future when adding busfreq support).
>
> static int imx6q_cpufreq_probe(struct platform_device *pdev)
> {
> ....
> arm_clk = clk_get(cpu_dev, "arm");
> pll1_sys_clk = clk_get(cpu_dev, "pll1_sys");
> pll1_sw_clk = clk_get(cpu_dev, "pll1_sw");
> step_clk = clk_get(cpu_dev, "step");
> pll2_pfd2_396m_clk = clk_get(cpu_dev, "pll2_pfd2_396m");
> if (IS_ERR(arm_clk) || IS_ERR(pll1_sys_clk) || IS_ERR(pll1_sw_clk) ||
> IS_ERR(step_clk) || IS_ERR(pll2_pfd2_396m_clk)) {
> dev_err(cpu_dev, "failed to get clocks\n");
> ret = -ENOENT;
> goto put_clk;
> }
>
> if (of_machine_is_compatible("fsl,imx6ul")) {
> pll2_bus_clk = clk_get(cpu_dev, "pll2_bus");
> secondary_sel_clk = clk_get(cpu_dev, "secondary_sel");
> if (IS_ERR(pll2_bus_clk) || IS_ERR(secondary_sel_clk)) {
> dev_err(cpu_dev, "failed to get clocks specific to imx6ul\n");
> ret = -ENOENT;
> goto put_clk;
> }
> }
> ....
> put_clk:
> if (!IS_ERR(arm_clk))
> clk_put(arm_clk);
> if (!IS_ERR(pll1_sys_clk))
> clk_put(pll1_sys_clk);
> ...........
> }
>
> Together with the err path handling for each clocks, it does make
> things a bit ugly.
>
> Since we already have regulator_bulk_get accessories, i thought we
> probably could introduce clk_bulk_get as well to handle such case to
> ease the driver owners' life.
>
> Besides IMX cpufreq driver, there is also some similar cases
> in kernel which could befinit from this api as well.
> e.g.
> drivers/cpufreq/tegra124-cpufreq.c
> drivers/cpufreq/s3c2412-cpufreq.c
> sound/soc/samsung/smdk_spdif.c
> arch/arm/mach-omap1/serial.c
> ...
>
> And actually, if we handle clocks more than 3, then it might be
> worthy to try, which there is quite many manay in kernel and
> that probably could save a lot codes.
>
> This is a RFC patch intending to bring up the idea to discuss.
>
> Comments are welcome and appreciated!
Thanks a lot for doing this, we have historically done something similar
on ARCH_BRCMSTB platforms in our downstream tree with a concept of a
"software" clock which has multiple parents (yikes), using the bulk
accessors would essentially allow us to remove part of this hack, so I
am all in favor of this!
>
> Dong Aisheng (3):
> clk: add clk_bulk_get accessories
> clk: add managed version of clk_bulk_get
> cpufreq: imx6q: refine clk operations
>
> drivers/clk/clk-devres.c | 36 +++++++++++
> drivers/clk/clk.c | 99 +++++++++++++++++++++++++++++
> drivers/clk/clkdev.c | 42 +++++++++++++
> drivers/cpufreq/imx6q-cpufreq.c | 119 ++++++++++++++++-------------------
> include/linux/clk.h | 135 ++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 365 insertions(+), 66 deletions(-)
>
--
Florian
^ permalink raw reply
* [RFC PATCH 4/7] ACPICA: IORT: Add SMMuV3 model definitions.
From: Sunil Kovvuri @ 2017-04-11 16:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <d60a1fcc-081e-03e8-3454-6802e830ddb9@arm.com>
On Tue, Apr 11, 2017 at 9:29 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> On 11/04/17 15:42, linucherian at gmail.com wrote:
>> From: Linu Cherian <linu.cherian@cavium.com>
>>
>> Add SMMuV3 model definitions.
>>
>> Signed-off-by: Linu Cherian <linu.cherian@cavium.com>
>> ---
>> include/acpi/actbl2.h | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
>> index 2b4af07..9db67d6 100644
>> --- a/include/acpi/actbl2.h
>> +++ b/include/acpi/actbl2.h
>> @@ -778,6 +778,11 @@ struct acpi_iort_smmu {
>> #define ACPI_IORT_SMMU_CORELINK_MMU400 0x00000002 /* ARM Corelink MMU-400 */
>> #define ACPI_IORT_SMMU_CORELINK_MMU500 0x00000003 /* ARM Corelink MMU-500 */
>>
>> +#define ACPI_IORT_SMMU_V3 0x00000000 /* Generic SMMUv3 */
>> +#define ACPI_IORT_SMMU_CORELINK_MMU600 0x00000001 /* ARM Corelink MMU-600 */
>> +#define ACPI_IORT_SMMU_V3_HISILICON 0x00000002 /* HiSilicon SMMUv3 */
>> +#define ACPI_IORT_SMMU_V3_CAVIUM_CN99XX 0x00000003 /* Cavium CN99xx SMMUv3 */
>
> None of those models are listed in the current IORT spec.
As mentioned in the cover letter, we are in the process of getting
model no added for
our silicon in the soon to be published updated IORT spec. Meanwhile
we wanted to take
feedback on the errata patches from experts. Hence patches were
submitted as RFC.
Thanks,
Sunil.
>
> What's MMU-600?
>
> Robin.
>
>> +
>> /* Masks for Flags field above */
>>
>> #define ACPI_IORT_SMMU_DVM_SUPPORTED (1)
>>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* [PATCHv3 13/22] staging: android: ion: Use CMA APIs directly
From: Laura Abbott @ 2017-04-11 16:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20163378.oNfPtYlzx6@avalon>
On 04/10/2017 11:47 PM, Laurent Pinchart wrote:
> Hi Laura,
>
> Thank you for the patch.
>
> On Monday 03 Apr 2017 11:57:55 Laura Abbott wrote:
>> When CMA was first introduced, its primary use was for DMA allocation
>> and the only way to get CMA memory was to call dma_alloc_coherent. This
>> put Ion in an awkward position since there was no device structure
>> readily available and setting one up messed up the coherency model.
>> These days, CMA can be allocated directly from the APIs. Switch to using
>> this model to avoid needing a dummy device. This also mitigates some of
>> the caching problems (e.g. dma_alloc_coherent only returning uncached
>> memory).
>
> Do we have a guarantee that the DMA mapping API, which we have to use for
> cache handling, will always support memory we allocate directly from CMA
> behind its back ?
>
CMA pages are no different than other pages allocated via the buddy
allocator. There should be no issue passing that memory to the
streaming API.
Thanks,
Laura
>> Signed-off-by: Laura Abbott <labbott@redhat.com>
>> ---
>> drivers/staging/android/ion/Kconfig | 7 +++
>> drivers/staging/android/ion/Makefile | 3 +-
>> drivers/staging/android/ion/ion_cma_heap.c | 97 +++++++--------------------
>> 3 files changed, 35 insertions(+), 72 deletions(-)
>>
>> diff --git a/drivers/staging/android/ion/Kconfig
>> b/drivers/staging/android/ion/Kconfig index 206c4de..15108c4 100644
>> --- a/drivers/staging/android/ion/Kconfig
>> +++ b/drivers/staging/android/ion/Kconfig
>> @@ -10,3 +10,10 @@ menuconfig ION
>> If you're not using Android its probably safe to
>> say N here.
>>
>> +config ION_CMA_HEAP
>> + bool "Ion CMA heap support"
>> + depends on ION && CMA
>> + help
>> + Choose this option to enable CMA heaps with Ion. This heap is backed
>> + by the Contiguous Memory Allocator (CMA). If your system has these
>> + regions, you should say Y here.
>> diff --git a/drivers/staging/android/ion/Makefile
>> b/drivers/staging/android/ion/Makefile index 26672a0..66d0c4a 100644
>> --- a/drivers/staging/android/ion/Makefile
>> +++ b/drivers/staging/android/ion/Makefile
>> @@ -1,6 +1,7 @@
>> obj-$(CONFIG_ION) += ion.o ion-ioctl.o ion_heap.o \
>> ion_page_pool.o ion_system_heap.o \
>> - ion_carveout_heap.o ion_chunk_heap.o ion_cma_heap.o
>> + ion_carveout_heap.o ion_chunk_heap.o
>> +obj-$(CONFIG_ION_CMA_HEAP) += ion_cma_heap.o
>> ifdef CONFIG_COMPAT
>> obj-$(CONFIG_ION) += compat_ion.o
>> endif
>> diff --git a/drivers/staging/android/ion/ion_cma_heap.c
>> b/drivers/staging/android/ion/ion_cma_heap.c index d562fd7..f3e0f59 100644
>> --- a/drivers/staging/android/ion/ion_cma_heap.c
>> +++ b/drivers/staging/android/ion/ion_cma_heap.c
>> @@ -19,24 +19,19 @@
>> #include <linux/slab.h>
>> #include <linux/errno.h>
>> #include <linux/err.h>
>> -#include <linux/dma-mapping.h>
>> +#include <linux/cma.h>
>> +#include <linux/scatterlist.h>
>>
>> #include "ion.h"
>> #include "ion_priv.h"
>>
>> struct ion_cma_heap {
>> struct ion_heap heap;
>> - struct device *dev;
>> + struct cma *cma;
>> };
>>
>> #define to_cma_heap(x) container_of(x, struct ion_cma_heap, heap)
>>
>> -struct ion_cma_buffer_info {
>> - void *cpu_addr;
>> - dma_addr_t handle;
>> - struct sg_table *table;
>> -};
>> -
>>
>> /* ION CMA heap operations functions */
>> static int ion_cma_allocate(struct ion_heap *heap, struct ion_buffer
>> *buffer, @@ -44,93 +39,53 @@ static int ion_cma_allocate(struct ion_heap
>> *heap, struct ion_buffer *buffer, unsigned long flags)
>> {
>> struct ion_cma_heap *cma_heap = to_cma_heap(heap);
>> - struct device *dev = cma_heap->dev;
>> - struct ion_cma_buffer_info *info;
>> -
>> - dev_dbg(dev, "Request buffer allocation len %ld\n", len);
>> -
>> - if (buffer->flags & ION_FLAG_CACHED)
>> - return -EINVAL;
>> + struct sg_table *table;
>> + struct page *pages;
>> + int ret;
>>
>> - info = kzalloc(sizeof(*info), GFP_KERNEL);
>> - if (!info)
>> + pages = cma_alloc(cma_heap->cma, len, 0, GFP_KERNEL);
>> + if (!pages)
>> return -ENOMEM;
>>
>> - info->cpu_addr = dma_alloc_coherent(dev, len, &(info->handle),
>> - GFP_HIGHUSER | __GFP_ZERO);
>> -
>> - if (!info->cpu_addr) {
>> - dev_err(dev, "Fail to allocate buffer\n");
>> + table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
>> + if (!table)
>> goto err;
>> - }
>>
>> - info->table = kmalloc(sizeof(*info->table), GFP_KERNEL);
>> - if (!info->table)
>> + ret = sg_alloc_table(table, 1, GFP_KERNEL);
>> + if (ret)
>> goto free_mem;
>>
>> - if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle,
>> - len))
>> - goto free_table;
>> - /* keep this for memory release */
>> - buffer->priv_virt = info;
>> - buffer->sg_table = info->table;
>> - dev_dbg(dev, "Allocate buffer %p\n", buffer);
>> + sg_set_page(table->sgl, pages, len, 0);
>> +
>> + buffer->priv_virt = pages;
>> + buffer->sg_table = table;
>> return 0;
>>
>> -free_table:
>> - kfree(info->table);
>> free_mem:
>> - dma_free_coherent(dev, len, info->cpu_addr, info->handle);
>> + kfree(table);
>> err:
>> - kfree(info);
>> + cma_release(cma_heap->cma, pages, buffer->size);
>> return -ENOMEM;
>> }
>>
>> static void ion_cma_free(struct ion_buffer *buffer)
>> {
>> struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
>> - struct device *dev = cma_heap->dev;
>> - struct ion_cma_buffer_info *info = buffer->priv_virt;
>> + struct page *pages = buffer->priv_virt;
>>
>> - dev_dbg(dev, "Release buffer %p\n", buffer);
>> /* release memory */
>> - dma_free_coherent(dev, buffer->size, info->cpu_addr, info->handle);
>> + cma_release(cma_heap->cma, pages, buffer->size);
>> /* release sg table */
>> - sg_free_table(info->table);
>> - kfree(info->table);
>> - kfree(info);
>> -}
>> -
>> -static int ion_cma_mmap(struct ion_heap *mapper, struct ion_buffer *buffer,
>> - struct vm_area_struct *vma)
>> -{
>> - struct ion_cma_heap *cma_heap = to_cma_heap(buffer->heap);
>> - struct device *dev = cma_heap->dev;
>> - struct ion_cma_buffer_info *info = buffer->priv_virt;
>> -
>> - return dma_mmap_coherent(dev, vma, info->cpu_addr, info->handle,
>> - buffer->size);
>> -}
>> -
>> -static void *ion_cma_map_kernel(struct ion_heap *heap,
>> - struct ion_buffer *buffer)
>> -{
>> - struct ion_cma_buffer_info *info = buffer->priv_virt;
>> - /* kernel memory mapping has been done at allocation time */
>> - return info->cpu_addr;
>> -}
>> -
>> -static void ion_cma_unmap_kernel(struct ion_heap *heap,
>> - struct ion_buffer *buffer)
>> -{
>> + sg_free_table(buffer->sg_table);
>> + kfree(buffer->sg_table);
>> }
>>
>> static struct ion_heap_ops ion_cma_ops = {
>> .allocate = ion_cma_allocate,
>> .free = ion_cma_free,
>> - .map_user = ion_cma_mmap,
>> - .map_kernel = ion_cma_map_kernel,
>> - .unmap_kernel = ion_cma_unmap_kernel,
>> + .map_user = ion_heap_map_user,
>> + .map_kernel = ion_heap_map_kernel,
>> + .unmap_kernel = ion_heap_unmap_kernel,
>> };
>>
>> struct ion_heap *ion_cma_heap_create(struct ion_platform_heap *data)
>> @@ -147,7 +102,7 @@ struct ion_heap *ion_cma_heap_create(struct
>> ion_platform_heap *data) * get device from private heaps data, later it
>> will be
>> * used to make the link with reserved CMA memory
>> */
>> - cma_heap->dev = data->priv;
>> + cma_heap->cma = data->priv;
>> cma_heap->heap.type = ION_HEAP_TYPE_DMA;
>> return &cma_heap->heap;
>> }
>
^ permalink raw reply
* [RFC PATCH v0.2] PCI: Add support for tango PCIe host bridge
From: Marc Zyngier @ 2017-04-11 16:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2b5eef4c-32f2-54f1-ca2f-f9426e68fb2c@free.fr>
On 11/04/17 17:26, Mason wrote:
> On 11/04/2017 17:49, Marc Zyngier wrote:
>> On 11/04/17 16:13, Mason wrote:
>>> On 27/03/2017 19:09, Marc Zyngier wrote:
>>>
>>>> Here's what your system looks like:
>>>>
>>>> PCI-EP -------> MSI Controller ------> INTC
>>>> MSI IRQ
>>>>
>>>> A PCI MSI is always edge. No ifs, no buts. That's what it is, and nothing
>>>> else. Now, your MSI controller signals its output using a level interrupt,
>>>> since you need to whack it on the head so that it lowers its line.
>>>>
>>>> There is not a single trigger, because there is not a single interrupt.
>>>
>>> Hello Marc,
>>>
>>> I was hoping you or Thomas might help clear some confusion
>>> in my mind around IRQ domains (struct irq_domain).
>>>
>>> I have read https://www.kernel.org/doc/Documentation/IRQ-domain.txt
>>>
>>> IIUC, there should be one IRQ domain per IRQ controller.
>>>
>>> I have this MSI controller handling 256 interrupts, so I should
>>> have *one* domain for all possible MSIs. Yet the Altera driver
>>> registers *two* domains (msi_domain and inner_domain).
>>>
>>> Could I make everything work with a single IRQ domain?
>>
>> No, because you have two irqchips. One that deals with the HW, and the
>> other that deals with the MSIs how they are presented to the kernel,
>> depending on the bus (PCI or something else). The fact that it doesn't
>> really drive any HW doesn't make it irrelevant.
>
> The example given in IRQ-domain.txt is
>
> Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU
>
> with an irq_domain for each interrupt controller.
Which doesn't use the generic MSI layer the way arm/arm64 do, so that's
the wrong example.
>
>
> On my system I have:
>
> PCI-EP -> MSI controller -> System INTC -> GIC -> CPU
>
> The driver for System INTC is drivers/irqchip/irq-tango.c
> I think it has only one domain.
>
> For the GIC, drivers/irqchip/irq-gic.c
> I see a call to irq_domain_create_linear()
Can we please stick to the problem at hand and not drift into other
considerations which do not matter at all?
> Is the handling of MSI different, and that is why we need
> two domains? (Sorry, I did not understand that part well.)
Let me repeat it again, then:
- You have a top-level MSI domain that is completely virtual, mapping a
virtual hwirq to the virtual interrupt. Nothing to see here.
- You have your own irqdomain, associated with your own irq_chip, which
does what it needs to do talking to the HW and allocating interrupts.
> When I looked at drivers/pci/host/pci-hyperv.c
> they seem to have a single pci_msi_create_irq_domain call,
> no call to domain_add or domain_create.
> And they have a single struct irq_chip.
Which is not using the generic MSI layer the way we do either.
>
>> You don't need to tell it anything about the number of interrupts you
>> manage. As for your private structure, you've already given it to your
>> low level domain, and there is no need to propagate it any further.
>
> My main issue is that in the ack callback, I was in the "wrong"
> domain, in that d->hwirq was not the MSI number. So I thought
> I needed a single irq_domain.
No. You need two, but you only need to manage yours.
> Is there a function to map virq to the hwirq in any domain?
Be more precise. If you want the hwirq associated with the view of a
virq in a given domain, that's the hwirq field in the corresponding
irq_data structure. Or are you after something else?
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [RFC PATCH 3/7] iommu/arm-smmu-v3: Introduce smmu option USE_SHARED_IRQS for Silicon errata
From: Will Deacon @ 2017-04-11 16:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a971af83-10f1-5696-f0c6-0600c04705c3@arm.com>
On Tue, Apr 11, 2017 at 05:38:21PM +0100, Robin Murphy wrote:
> On 11/04/17 17:21, Will Deacon wrote:
> > On Tue, Apr 11, 2017 at 04:54:26PM +0100, Robin Murphy wrote:
> >> On 11/04/17 15:42, linucherian at gmail.com wrote:
> >>> From: Geetha <gakula@cavium.com>
> >>>
> >>> Cavium 99xx SMMU implementation doesn't not support unique irq lines for
> >>> gerror, eventq and cmdq-sync. USE_SHARED_IRQS option enables to use single
> >>> irq line for all three interrupts.
> >>
> >> AFAICS, there's nothing actually wrong with using shared wired IRQs -
> >> the architecture spec doesn't appear to say anything about it. I think
> >> it might suffice to simply add IRQF_SHARED if we can see the SMMU
> >> doesn't support MSIs anyway - it doesn't really seem like something we
> >> need to treat as a specific quirk.
> >
> > No, this is not permitted by the spec. See 3.18.2 ("Interrupt sources"),
> > where it's clear that each source asserts a *unique* wired interrupt.
>
> Perhaps I'm reading it too generously; it does indeed specify that the
> *implementation* has to provide a unique output for each source, but
> other than suggesting a particular mode of operation based on that I
> don't see anything actually forbidding the *integration* from then just
> munging those lines together externally, as integrators so often like to
> do. That's the case I had in mind.
Sure, but then there wouldn't be any point in the architecture mandating
a unique source, would there? What next, OR all the address lines together
too?
Will
^ permalink raw reply
* [RFC PATCH 2/7] iommu/arm-smmu-v3: Do resource size checks based on smmu option PAGE0_REGS_ONLY
From: Sunil Kovvuri @ 2017-04-11 16:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <802c0a38-f5a6-e584-5795-42d8d3fd7603@arm.com>
On Tue, Apr 11, 2017 at 9:13 PM, Robin Murphy <robin.murphy@arm.com> wrote:
> On 11/04/17 15:42, linucherian at gmail.com wrote:
>> From: Linu Cherian <linu.cherian@cavium.com>
>>
>> With implementations supporting only page 0 of register space,
>> resource size can be 64k as well and hence perform size checks
>> based on smmu option PAGE0_REGS_ONLY.
>
> What harm comes of mapping page 1 if we don't access it?
>
> Robin.
>
There are multiple SMMUs on the silicon and CSRs of each SMMU are
64K apart. Hence can't map page-1 even though it's not accessed.
Thanks,
Sunil.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox