Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] imx6: fix pcie enumeration
From: Bjorn Helgaas @ 2018-01-04 20:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515080883-30066-1-git-send-email-koen.vandeputte@ncentric.com>

[+cc Richard, Lucas, Lorenzo, linux-arm-kernel]

Hi Koen,

Thanks a lot for the fix!

Please run "git log --oneline drivers/pci/dwc/pci-imx6.c" and follow
the style convention, including "PCIe" capitalization.

"fix pcie enumeration" is not very descriptive.  It should say something
about the specific problem, e.g., setting the root port's subordinate
bus number.

On Thu, Jan 04, 2018 at 04:48:03PM +0100, Koen Vandeputte wrote:
> By default, when the imx6 PCIe RC boots up, the subordinate is set

Not sure what "RC boots up" means.  Maybe you're talking about a
hardware-defined default value at power-up, or maybe a value
programmed by a boot-loader?  Please clarify and update the similar
comment in the code.

> equally to the secondary bus (1), and does not alter afterwards.
> 
> This means that theoretically, the highest bus reachable downstream is
> bus 1.

Not just theoretically.  If the bridge is operating correctly, it
should not forward any config transaction for a bus number greater
than the subordinate bus number.

> Before commit a20c7f36bd3d ("PCI: Do not allocate more buses than
> available in parent"), the driver ignored the subord value and just
> allowed up to 0xff on each device downstream.
> 
> This caused a lot of errors to be printed, as this is not logical
> according to spec. (but it worked ..)

Including a sample error in the changelog might help somebody
suffering from the problem find this solution.

> After this commit, the driver stopped scanning deeper when the last
> allocated busnr equals the subordinate of it's master, causing devices
> to be undiscovered (especially behind bridges), uncovering the impact of
> this bug.
> 
> Before:
> 
> 00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00 ...
> 	Bus: primary=00, secondary=01, subordinate=01, sec-latency=0
> 
> 00:00.0 0604: 16c3:abcd (rev 01)
> 01:00.0 0604: 10b5:8604 (rev ba)
> ... stops after bus 1 ...
> 
> After:
> 
> 00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00
> ...
> 	Bus: primary=00, secondary=01, subordinate=ff, sec-latency=0
> 
> 00:00.0 0604: 16c3:abcd (rev 01)
> 01:00.0 0604: 10b5:8604 (rev ba)
> 02:01.0 0604: 10b5:8604 (rev ba)
> 02:04.0 0604: 10b5:8604 (rev ba)
> 02:05.0 0604: 10b5:8604 (rev ba)
> 03:00.0 0280: 168c:0033 (rev 01)
> 05:00.0 0280: 168c:0033 (rev 01)
> 

Should have a "Fixes: a20c7f36bd3d ..." tag if that's really the
correct commit.

> Signed-off-by: Koen Vandeputte <koen.vandeputte@ncentric.com>
> ---
> 
> Needs backports to 4.14 & 4.9 stables

Add a "CC: stable at vger.kernel.org" after your signed-off-by to handle
this.  But something's wrong because a20c7f36bd3d only appeared in
v4.15-rc1, so either that's the wrong commit or stable kernels don't
need the fix.

>  drivers/pci/dwc/pci-imx6.c | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c
> index b73483534a5b..3d13fa8c2eb1 100644
> --- a/drivers/pci/dwc/pci-imx6.c
> +++ b/drivers/pci/dwc/pci-imx6.c
> @@ -76,6 +76,9 @@ struct imx6_pcie {
>  
>  #define PCIE_RC_LCSR				0x80
>  
> +#define PCIE_RC_BNR				0x18
> +#define PCIE_RC_BNR_MAX_SUBORDINATE		(0xff << 16)
> +
>  /* PCIe Port Logic registers (memory-mapped) */
>  #define PL_OFFSET 0x700
>  #define PCIE_PL_PFLR (PL_OFFSET + 0x08)
> @@ -562,6 +565,17 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
>  	int ret;
>  
>  	/*
> +	 * By default, the subordinate is set equally to the secondary
> +	 * bus (0x01) when the RC boots.
> +	 * This means that theoretically, only bus 1 is reachable from the RC.
> +	 * Force the PCIe RC subordinate to 0xff, otherwise no downstream
> +	 * devices will be detected behind bus 1.
> +	*/
> +	tmp = dw_pcie_readl_rc(pp, PCIE_RC_BNR);
> +	tmp |= PCIE_RC_BNR_MAX_SUBORDINATE;
> +	dw_pcie_writel_rc(pp, PCIE_RC_BNR, tmp);

This functionality is not related to establishing the link, so I think
it should be put elsewhere, maybe either directly in imx6_pcie_probe()
or in imx6_pcie_host_init().

The DT really should contain a "bus-range" property and
dw_pcie_host_init() will already pay attention to that if it's
present, and I think it defaults to 0-0xff if it's not present.

So I think you should be using pp->busn instead of hard-coding
PCIE_RC_BNR_MAX_SUBORDINATE.

> +	/*
>  	 * Force Gen1 operation when starting the link.  In case the link is
>  	 * started in Gen2 mode, there is a possibility the devices on the
>  	 * bus will not be detected at all.  This happens with PCIe switches.
> -- 
> 2.7.4
> 

^ permalink raw reply

* [GIT PULL] Qualcomm Driver updates for 4.16 - Redo
From: Andy Gross @ 2018-01-04 20:32 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:

  Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git tags/qcom-drivers-for-4.16

for you to fetch changes up to 3aa0582fdb824139630298880fbf78d4ac774d3c:

  of: platform: populate /firmware/ node from of_platform_default_populate_init() (2018-01-04 14:00:20 -0600)

----------------------------------------------------------------
Qualcomm ARM Based Driver Updates for v4.16 - Redo

* Fix error handling code in SMP2P probe
* Update SMP2P to use ACPS as mailbox client
* Add QMI support
* Fixups for Qualcomm SCM
* Fix licensing on rmtfs_mem
* Correct SMSM child node lookup
* Populate firmware nodes during platform init

----------------------------------------------------------------
Bjorn Andersson (3):
      soc: qcom: smp2p: Access APCS as mailbox client
      soc: qcom: Introduce QMI encoder/decoder
      soc: qcom: Introduce QMI helpers

Jesse Chan (1):
      soc: qcom: rmtfs_mem: add missing MODULE_DESCRIPTION/AUTHOR/LICENSE

Johan Hovold (1):
      soc: qcom: smsm: fix child-node lookup

Jordan Crouse (1):
      firmware: qcom_scm: Add dependent headers to qcom_scm.h

Markus Elfring (1):
      soc: qcom: smp2p: Use common error handling code in qcom_smp2p_probe()

Sudeep Holla (2):
      firmware: qcom_scm: drop redandant of_platform_populate
      of: platform: populate /firmware/ node from of_platform_default_populate_init()

 .../devicetree/bindings/soc/qcom/qcom,smp2p.txt    |   8 +-
 drivers/firmware/qcom_scm.c                        |  24 -
 drivers/of/platform.c                              |   4 +
 drivers/soc/qcom/Kconfig                           |  10 +
 drivers/soc/qcom/Makefile                          |   2 +
 drivers/soc/qcom/qmi_encdec.c                      | 816 ++++++++++++++++++++
 drivers/soc/qcom/qmi_interface.c                   | 848 +++++++++++++++++++++
 drivers/soc/qcom/rmtfs_mem.c                       |   4 +
 drivers/soc/qcom/smp2p.c                           |  55 +-
 drivers/soc/qcom/smsm.c                            |   6 +-
 include/linux/qcom_scm.h                           |   3 +
 include/linux/soc/qcom/qmi.h                       | 271 +++++++
 12 files changed, 2010 insertions(+), 41 deletions(-)
 create mode 100644 drivers/soc/qcom/qmi_encdec.c
 create mode 100644 drivers/soc/qcom/qmi_interface.c
 create mode 100644 include/linux/soc/qcom/qmi.h

^ permalink raw reply

* [PATCH] ARM: dts: kirkwood: fix pin-muxing of MPP7
From: Andrew Lunn @ 2018-01-04 20:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180104165312.14052-1-thomas.petazzoni@free-electrons.com>

On Thu, Jan 04, 2018 at 05:53:12PM +0100, Thomas Petazzoni wrote:
> MPP7 is currently muxed as "gpio", but this function doesn't exist for
> MPP7, only "gpo" is available. This causes the following error:
> 
> kirkwood-pinctrl f1010000.pin-controller: unsupported function gpio on pin mpp7
> pinctrl core: failed to register map default (6): invalid type given
> kirkwood-pinctrl f1010000.pin-controller: error claiming hogs: -22
> kirkwood-pinctrl f1010000.pin-controller: could not claim hogs: -22
> kirkwood-pinctrl f1010000.pin-controller: unable to register pinctrl driver
> kirkwood-pinctrl: probe of f1010000.pin-controller failed with error -22
> 
> So the pinctrl driver is not probed, all device drivers (including the
> UART driver) do a -EPROBE_DEFER, and therefore the system doesn't
> really boot (well, it boots, but with no UART, and no devices that
> require pin-muxing).
> 
> Back when the Device Tree file for this board was introduced, the
> definition was already wrong. The pinctrl driver also always described
> as "gpo" this function for MPP7. However, between Linux 4.10 and 4.11,
> a hog pin failing to be muxed was turned from a simple warning to a
> hard error that caused the entire pinctrl driver probe to bail
> out. This is probably the result of commit 6118714275f0a ("pinctrl:
> core: Fix pinctrl_register_and_init() with pinctrl_enable()").
> 
> This commit fixes the Device Tree to use the proper "gpo" function for
> MPP7, which fixes the boot of OpenBlocks A7, which was broken since
> Linux 4.11.
> 
> Fixes: f24b56cbcd9d ("ARM: kirkwood: add support for OpenBlocks A7 platform")
> Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>

Hi Thomas

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

I just checked the other Kirkwood boards. This is the only one that
got MPP7 wrong.

    Andrew

^ permalink raw reply

* [PATCH v2 0/8] ARM: sun9i: SMP support with Multi-Cluster Power Management
From: Nicolas Pitre @ 2018-01-04 20:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180104143754.2425-1-wens@csie.org>

On Thu, 4 Jan 2018, Chen-Yu Tsai wrote:

> Nicolas mentioned that the MCPM framework is likely overkill in our
> case [4]. However the framework does provide cluster/core state tracking
> and proper sequencing of cache related operations. We could rework
> the code to use standard smp_ops, but I would like to actually get
> a working version in first.
> 
> [...] For now however I'm using a
> dedicated single thread workqueue. CPU and cluster power off work is
> queued from the .{cpu,cluster}_powerdown_prepare callbacks. This solution
> is somewhat heavy, as I have a total of 10 static work structs. It might
> also be a bit racy, as nothing prevents the system from bringing a core
> back before the asynchronous work shuts it down. This would likely
> happen under a heavily loaded system with a scheduler that brings cores
> in and out of the system frequently. In simple use-cases it performs OK.

If you know up front your code is racy then this doesn't fully qualify 
as a "working version". Furthermore you're trading custom cluster/core 
state tracking for workqueue handling which doesn't look like a winning 
tradeoff to me. Especially given you can't have asynchronous CPU wakeups 
in hardware from an IRQ to deal with then the state tracking becomes 
very simple.

If you hook into struct smp_operations directly, you'll have direct 
access to both .cpu_die and .cpu_kill methods which are executed on the 
target CPU and on a different CPU respectively, which is exactly what 
you need. Those calls are already serialized with .smp_boot_secondary so 
you don't have to worry about races. The only thing you need to protect 
against races is your cluster usage count. Your code will end up being 
simpler than what you have now. See arch/arm/mach-hisi/platmcpm.c for 
example.


Nicolas

^ permalink raw reply

* [PATCH v4 6/7] ARM: davinci: convert to common clock framework
From: David Lechner @ 2018-01-04 21:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAHCN7x+N7KThCXsqrKiSetNeyaEW3BzwVBH_8KSqJVtb8hXFNg@mail.gmail.com>

On 01/04/2018 01:26 PM, Adam Ford wrote:
> On Thu, Jan 4, 2018 at 11:50 AM, David Lechner <david@lechnology.com> wrote:
>>
>>
>> On 1/4/18 6:39 AM, Sekhar Nori wrote:
>>>
>>> On Monday 01 January 2018 05:09 AM, David Lechner wrote:
>>>>
>>>> This converts all of arch/arm/mach-davinci to the common clock framework.
>>>> The clock drivers from clock.c and psc.c have been moved to drivers/clk,
>>>> so these files are removed.
>>>>
>>>> There is one subtle change in the clock trees. AUX, BPDIV and OSCDIV
>>>> clocks now have "ref_clk" as a parent instead of the PLL clock. These
>>>> clocks are part of the PLL's MMIO block, but they bypass the PLL and
>>>> therefore it makes more sense to have "ref_clk" as their parent since
>>>> "ref_clk" is the input clock of the PLL.
>>>>
>>>> CONFIG_DAVINCI_RESET_CLOCKS is removed since the common clock frameworks
>>>> takes care of disabling unused clocks.
>>>>
>>>> Known issue: This breaks CPU frequency scaling on da850.
>>>
>>>
>>> This functionality needs to be restored as part of this series since we
>>> cannot commit anything with regressions.
>>>
>>
>> Do you have a suggestion on how to accomplish this? I don't have a board for
>> testing, so I don't have a way of knowing if my changes will work or not.
> 
> I work for Logic PD who makes the original da850-evm.  I can help if
> you want to send me patches.  It would be better if you had a git repo
> setup where I could just clone the repo and tests.
> 
> Having a larger collection of smaller the patches would also give me
> the ability to bisect down to help determine what actually breaks the
> da850-evm vs a few large patches.
> 
> Do you still need me to run the board with some of the extra debugging
> enabled, or should I wait for the next round of patches?
> 

You might as well wait until I resubmit. There are going to be some significant
changes.

^ permalink raw reply

* [PATCH V7 12/12] arm64: dts: add clocks for SC9860
From: Arnd Bergmann @ 2018-01-04 21:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171207125715.16160-13-chunyan.zhang@spreadtrum.com>

On Thu, Dec 7, 2017 at 1:57 PM, Chunyan Zhang
<chunyan.zhang@spreadtrum.com> wrote:
> Some clocks on SC9860 are in the same address area with syscon devices,
> those are what have a property of 'sprd,syscon' which would refer to
> syscon devices, others would have a reg property indicated their address
> ranges.
>
> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
> ---
>  arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 +++++++++++++++++++++++++++++++++++
>  arch/arm64/boot/dts/sprd/whale2.dtsi |  18 +++++-
>  2 files changed, 131 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
> index 7b7d8ce..bf03da4 100644
> --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
> +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
> @@ -7,6 +7,7 @@
>   */
>
>  #include <dt-bindings/interrupt-controller/arm-gic.h>
> +#include <dt-bindings/clock/sprd,sc9860-clk.h>
>  #include "whale2.dtsi"

This caused a build error since the sprd,sc9860-clk.h file does not
exist, I'll revert or
undo the patch tomorrow.

        Arnd

^ permalink raw reply

* [PATCH V3 3/3] arm64: Extend early page table code to allow for larger kernels
From: Jeremy Linton @ 2018-01-04 21:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu8tpRhri5CbvhYzE-ZZViqt7EAiDhf=EY_Ft=LoWu5-cQ@mail.gmail.com>

Hi,

On 01/02/2018 04:01 PM, Ard Biesheuvel wrote:
> Hi Steve,
> 
> On 2 January 2018 at 15:12, Steve Capper <steve.capper@arm.com> wrote:
>> Currently the early assembler page table code assumes that precisely
>> 1xpgd, 1xpud, 1xpmd are sufficient to represent the early kernel text
>> mappings.
>>
>> Unfortunately this is rarely the case when running with a 16KB granule,
>> and we also run into limits with 4KB granule when building much larger
>> kernels.
>>
>> This patch re-writes the early page table logic to compute indices of
>> mappings for each level of page table, and if multiple indices are
>> required, the next-level page table is scaled up accordingly.
>>
>> Also the required size of the swapper_pg_dir is computed at link time
>> to cover the mapping [KIMAGE_ADDR + VOFFSET, _end]. When KASLR is
>> enabled, an extra page is set aside for each level that may require extra
>> entries at runtime.
>>
>> Signed-off-by: Steve Capper <steve.capper@arm.com>
>>
>> ---
>> Changed in V3:
>> Corrected KASLR computation
>> Rebased against arm64/for-next/core, particularly Kristina's 52-bit
>> PA series.
>> ---
>>   arch/arm64/include/asm/kernel-pgtable.h |  47 ++++++++++-
>>   arch/arm64/include/asm/pgtable.h        |   1 +
>>   arch/arm64/kernel/head.S                | 145 +++++++++++++++++++++++---------
>>   arch/arm64/kernel/vmlinux.lds.S         |   1 +
>>   arch/arm64/mm/mmu.c                     |   3 +-
>>   5 files changed, 157 insertions(+), 40 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
>> index 77a27af01371..82386e860dd2 100644
>> --- a/arch/arm64/include/asm/kernel-pgtable.h
>> +++ b/arch/arm64/include/asm/kernel-pgtable.h
>> @@ -52,7 +52,52 @@
>>   #define IDMAP_PGTABLE_LEVELS   (ARM64_HW_PGTABLE_LEVELS(PHYS_MASK_SHIFT))
>>   #endif
>>
>> -#define SWAPPER_DIR_SIZE       (SWAPPER_PGTABLE_LEVELS * PAGE_SIZE)
>> +
>> +/*
>> + * If KASLR is enabled, then an offset K is added to the kernel address
>> + * space. The bottom 21 bits of this offset are zero to guarantee 2MB
>> + * alignment for PA and VA.
>> + *
>> + * For each pagetable level of the swapper, we know that the shift will
>> + * be larger than 21 (for the 4KB granule case we use section maps thus
>> + * the smallest shift is actually 30) thus there is the possibility that
>> + * KASLR can increase the number of pagetable entries by 1, so we make
>> + * room for this extra entry.
>> + *
>> + * Note KASLR cannot increase the number of required entries for a level
>> + * by more than one because it increments both the virtual start and end
>> + * addresses equally (the extra entry comes from the case where the end
>> + * address is just pushed over a boundary and the start address isn't).
>> + */
>> +
>> +#ifdef CONFIG_RANDOMIZE_BASE
>> +#define EARLY_KASLR    (1)
>> +#else
>> +#define EARLY_KASLR    (0)
>> +#endif
>> +
>> +#define EARLY_ENTRIES(vstart, vend, shift) (((vend) >> (shift)) \
>> +                                       - ((vstart) >> (shift)) + 1 + EARLY_KASLR)
>> +
>> +#define EARLY_PGDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PGDIR_SHIFT))
>> +
>> +#if SWAPPER_PGTABLE_LEVELS > 3
>> +#define EARLY_PUDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, PUD_SHIFT))
>> +#else
>> +#define EARLY_PUDS(vstart, vend) (0)
>> +#endif
>> +
>> +#if SWAPPER_PGTABLE_LEVELS > 2
>> +#define EARLY_PMDS(vstart, vend) (EARLY_ENTRIES(vstart, vend, SWAPPER_TABLE_SHIFT))
>> +#else
>> +#define EARLY_PMDS(vstart, vend) (0)
>> +#endif
>> +
>> +#define EARLY_PAGES(vstart, vend) ( 1                  /* PGDIR page */                                \
>> +                       + EARLY_PGDS((vstart), (vend))  /* each PGDIR needs a next level page table */  \
>> +                       + EARLY_PUDS((vstart), (vend))  /* each PUD needs a next level page table */    \
>> +                       + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */
>> +#define SWAPPER_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR + TEXT_OFFSET, _end))
>>   #define IDMAP_DIR_SIZE         (IDMAP_PGTABLE_LEVELS * PAGE_SIZE)
>>
>>   #ifdef CONFIG_ARM64_SW_TTBR0_PAN
>> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
>> index bfa237e892f1..54b0a8398055 100644
>> --- a/arch/arm64/include/asm/pgtable.h
>> +++ b/arch/arm64/include/asm/pgtable.h
>> @@ -706,6 +706,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
>>   #endif
>>
>>   extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
>> +extern pgd_t swapper_pg_end[];
>>   extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
>>   extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
>>
>> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
>> index 66f01869e97c..539e2642ed41 100644
>> --- a/arch/arm64/kernel/head.S
>> +++ b/arch/arm64/kernel/head.S
>> @@ -191,44 +191,110 @@ ENDPROC(preserve_boot_args)
>>          .endm
>>
>>   /*
>> - * Macro to populate the PGD (and possibily PUD) for the corresponding
>> - * block entry in the next level (tbl) for the given virtual address.
>> + * Macro to populate page table entries, these entries can be pointers to the next level
>> + * or last level entries pointing to physical memory.
>>    *
>> - * Preserves:  tbl, next, virt
>> - * Corrupts:   ptrs_per_pgd, tmp1, tmp2
>> + *     tbl:    page table address
>> + *     rtbl:   pointer to page table or physical memory
>> + *     index:  start index to write
>> + *     eindex: end index to write - [index, eindex] written to
>> + *     flags:  flags for pagetable entry to or in
>> + *     inc:    increment to rtbl between each entry
>> + *     tmp1:   temporary variable
>> + *
>> + * Preserves:  tbl, eindex, flags, inc
>> + * Corrupts:   index, tmp1
>> + * Returns:    rtbl
>>    */
>> -       .macro  create_pgd_entry, tbl, virt, ptrs_per_pgd, tmp1, tmp2
>> -       create_table_entry \tbl, \virt, PGDIR_SHIFT, \ptrs_per_pgd, \tmp1, \tmp2
>> -#if SWAPPER_PGTABLE_LEVELS > 3
>> -       mov     \ptrs_per_pgd, PTRS_PER_PUD
>> -       create_table_entry \tbl, \virt, PUD_SHIFT, \ptrs_per_pgd, \tmp1, \tmp2
>> -#endif
>> -#if SWAPPER_PGTABLE_LEVELS > 2
>> -       mov     \ptrs_per_pgd, PTRS_PER_PTE
>> -       create_table_entry \tbl, \virt, SWAPPER_TABLE_SHIFT, \ptrs_per_pgd, \tmp1, \tmp2
>> -#endif
>> +       .macro populate_entries, tbl, rtbl, index, eindex, flags, inc, tmp1
>> +9999:  phys_to_pte \rtbl, \tmp1
> 
> I know this is existing code, but you could take the opportunity to
> replace this label with
> 
> .L\@  >
> (and update the branch instruction accordingly) so that we don't have
> to rely on the uniqueness of '9999'

As this was pointed out, it seems that the common method do this in the 
kernel is actually

.Lsomename\@

which is required if your macro has more than one branch.. 
Alternatively, it seems some of the more recent code is using the 
LOCAL/.altmacro method which avoids hardcoding the local prefix. Either 
one fixes the nested macro's and wrong jump target problem.


> 
>> +       orr     \tmp1, \tmp1, \flags    // tmp1 = table entry
>> +       str     \tmp1, [\tbl, \index, lsl #3]
>> +       add     \rtbl, \rtbl, \inc      // rtbl = pa next level
>> +       add     \index, \index, #1
>> +       cmp     \index, \eindex
>> +       b.ls    9999b
>>          .endm
>>
>>   /*
>> - * Macro to populate block entries in the page table for the start..end
>> - * virtual range (inclusive).
>> + * Compute indices of table entries from virtual address range. If multiple entries
>> + * were needed in the previous page table level then the next page table level is assumed
>> + * to be composed of multiple pages. (This effectively scales the end index).
>> + *
>> + *     vstart: virtual address of start of range
>> + *     vend:   virtual address of end of range
>> + *     shift:  shift used to transform virtual address into index
>> + *     ptrs:   number of entries in page table
>> + *     istart: index in table corresponding to vstart
>> + *     iend:   index in table corresponding to vend
>> + *     count:  On entry: how many entries required in previous level, scales our end index
>> + *             On exit: returns how many entries required for next page table level
>>    *
> 
> If you make 'count' the number of /additional/ entries, you no longer
> have to add/sub #1 each time.
> 
>> - * Preserves:  tbl, flags
>> - * Corrupts:   phys, start, end, tmp, pstate
>> + * Preserves:  vstart, vend, shift, ptrs
>> + * Returns:    istart, iend, count
>>    */
>> -       .macro  create_block_map, tbl, flags, phys, start, end, tmp
>> -       lsr     \start, \start, #SWAPPER_BLOCK_SHIFT
>> -       and     \start, \start, #PTRS_PER_PTE - 1       // table index
>> -       bic     \phys, \phys, #SWAPPER_BLOCK_SIZE - 1
>> -       lsr     \end, \end, #SWAPPER_BLOCK_SHIFT
>> -       and     \end, \end, #PTRS_PER_PTE - 1           // table end index
>> -9999:  phys_to_pte \phys, \tmp
>> -       orr     \tmp, \tmp, \flags                      // table entry
>> -       str     \tmp, [\tbl, \start, lsl #3]            // store the entry
>> -       add     \start, \start, #1                      // next entry
>> -       add     \phys, \phys, #SWAPPER_BLOCK_SIZE               // next block
>> -       cmp     \start, \end
>> -       b.ls    9999b
>> +       .macro compute_indices, vstart, vend, shift, ptrs, istart, iend, count
>> +       lsr     \iend, \vend, \shift
>> +       mov     \istart, \ptrs
>> +       sub     \istart, \istart, #1
>> +       and     \iend, \iend, \istart   // iend = (vend >> shift) & (ptrs - 1)
>> +       mov     \istart, \ptrs
>> +       sub     \count, \count, #1
>> +       mul     \istart, \istart, \count
>> +       add     \iend, \iend, \istart   // iend += (count - 1) * ptrs
>> +                                       // our entries span multiple tables
>> +
>> +       lsr     \istart, \vstart, \shift
>> +       mov     \count, \ptrs
>> +       sub     \count, \count, #1
>> +       and     \istart, \istart, \count
>> +
>> +       sub     \count, \iend, \istart
>> +       add     \count, \count, #1
>> +       .endm
>> +
> 
> You can simplify this macro by using an immediate for \ptrs. Please
> see the diff below [whitespace mangling courtesy of Gmail]
> 
>> +/*
>> + * Map memory for specified virtual address range. Each level of page table needed supports
>> + * multiple entries. If a level requires n entries the next page table level is assumed to be
>> + * formed from n pages.
>> + *
>> + *     tbl:    location of page table
>> + *     rtbl:   address to be used for first level page table entry (typically tbl + PAGE_SIZE)
>> + *     vstart: start address to map
>> + *     vend:   end address to map - we map [vstart, vend]
>> + *     flags:  flags to use to map last level entries
>> + *     phys:   physical address corresponding to vstart - physical memory is contiguous
>> + *     pgds:   the number of pgd entries
>> + *
>> + * Temporaries:        istart, iend, tmp, count, sv - these need to be different registers
>> + * Preserves:  vstart, vend, flags
>> + * Corrupts:   tbl, rtbl, istart, iend, tmp, count, sv
>> + */
>> +       .macro map_memory, tbl, rtbl, vstart, vend, flags, phys, pgds, istart, iend, tmp, count, sv
>> +       add \rtbl, \tbl, #PAGE_SIZE
>> +       mov \sv, \rtbl
>> +       mov \count, #1
> 
> #0 if you make \count the number of additional entries.
> 
> In any case, for the series:
> 
> Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> 
>> +       compute_indices \vstart, \vend, #PGDIR_SHIFT, \pgds, \istart, \iend, \count
>> +       populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
>> +       mov \tbl, \sv
>> +       mov \sv, \rtbl
>> +
>> +#if SWAPPER_PGTABLE_LEVELS > 3
>> +       compute_indices \vstart, \vend, #PUD_SHIFT, #PTRS_PER_PUD, \istart, \iend, \count
>> +       populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
>> +       mov \tbl, \sv
>> +       mov \sv, \rtbl
>> +#endif
>> +
>> +#if SWAPPER_PGTABLE_LEVELS > 2
>> +       compute_indices \vstart, \vend, #SWAPPER_TABLE_SHIFT, #PTRS_PER_PMD, \istart, \iend, \count
>> +       populate_entries \tbl, \rtbl, \istart, \iend, #PMD_TYPE_TABLE, #PAGE_SIZE, \tmp
>> +       mov \tbl, \sv
>> +#endif
>> +
>> +       compute_indices \vstart, \vend, #SWAPPER_BLOCK_SHIFT, #PTRS_PER_PTE, \istart, \iend, \count
>> +       bic \count, \phys, #SWAPPER_BLOCK_SIZE - 1
>> +       populate_entries \tbl, \count, \istart, \iend, \flags, #SWAPPER_BLOCK_SIZE, \tmp
>>          .endm
>>
>>   /*
>> @@ -246,14 +312,16 @@ __create_page_tables:
>>           * dirty cache lines being evicted.
>>           */
>>          adrp    x0, idmap_pg_dir
>> -       ldr     x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
>> +       adrp    x1, swapper_pg_end
>> +       sub     x1, x1, x0
>>          bl      __inval_dcache_area
>>
>>          /*
>>           * Clear the idmap and swapper page tables.
>>           */
>>          adrp    x0, idmap_pg_dir
>> -       ldr     x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
>> +       adrp    x1, swapper_pg_end
>> +       sub     x1, x1, x0
>>   1:     stp     xzr, xzr, [x0], #16
>>          stp     xzr, xzr, [x0], #16
>>          stp     xzr, xzr, [x0], #16
>> @@ -318,10 +386,10 @@ __create_page_tables:
>>   #endif
>>   1:
>>          ldr_l   x4, idmap_ptrs_per_pgd
>> -       create_pgd_entry x0, x3, x4, x5, x6
>>          mov     x5, x3                          // __pa(__idmap_text_start)
>>          adr_l   x6, __idmap_text_end            // __pa(__idmap_text_end)
>> -       create_block_map x0, x7, x3, x5, x6, x4
>> +
>> +       map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14
>>
>>          /*
>>           * Map the kernel image (starting with PHYS_OFFSET).
>> @@ -330,12 +398,12 @@ __create_page_tables:
>>          mov_q   x5, KIMAGE_VADDR + TEXT_OFFSET  // compile time __va(_text)
>>          add     x5, x5, x23                     // add KASLR displacement
>>          mov     x4, PTRS_PER_PGD
>> -       create_pgd_entry x0, x5, x4, x3, x6
>>          adrp    x6, _end                        // runtime __pa(_end)
>>          adrp    x3, _text                       // runtime __pa(_text)
>>          sub     x6, x6, x3                      // _end - _text
>>          add     x6, x6, x5                      // runtime __va(_end)
>> -       create_block_map x0, x7, x3, x5, x6, x4
>> +
>> +       map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
>>
>>          /*
>>           * Since the page tables have been populated with non-cacheable
>> @@ -343,7 +411,8 @@ __create_page_tables:
>>           * tables again to remove any speculatively loaded cache lines.
>>           */
>>          adrp    x0, idmap_pg_dir
>> -       ldr     x1, =(IDMAP_DIR_SIZE + SWAPPER_DIR_SIZE + RESERVED_TTBR0_SIZE)
>> +       adrp    x1, swapper_pg_end
>> +       sub     x1, x1, x0
>>          dmb     sy
>>          bl      __inval_dcache_area
>>
>> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
>> index 4c7112a47469..0221aca6493d 100644
>> --- a/arch/arm64/kernel/vmlinux.lds.S
>> +++ b/arch/arm64/kernel/vmlinux.lds.S
>> @@ -230,6 +230,7 @@ SECTIONS
>>   #endif
>>          swapper_pg_dir = .;
>>          . += SWAPPER_DIR_SIZE;
>> +       swapper_pg_end = .;
>>
>>          __pecoff_data_size = ABSOLUTE(. - __initdata_begin);
>>          _end = .;
>> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> index 4071602031ed..fdac11979bae 100644
>> --- a/arch/arm64/mm/mmu.c
>> +++ b/arch/arm64/mm/mmu.c
>> @@ -644,7 +644,8 @@ void __init paging_init(void)
>>           * allocated with it.
>>           */
>>          memblock_free(__pa_symbol(swapper_pg_dir) + PAGE_SIZE,
>> -                     SWAPPER_DIR_SIZE - PAGE_SIZE);
>> +                     __pa_symbol(swapper_pg_end) - __pa_symbol(swapper_pg_dir)
>> +                     - PAGE_SIZE);
>>   }
>>
>>   /*
>> --
>> 2.11.0
>>
> 
> 
> ------8<---------
> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index 539e2642ed41..0432dd8d083c 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -235,9 +235,7 @@ ENDPROC(preserve_boot_args)
>    */
>          .macro compute_indices, vstart, vend, shift, ptrs, istart, iend, count
>          lsr     \iend, \vend, \shift
> -       mov     \istart, \ptrs
> -       sub     \istart, \istart, #1
> -       and     \iend, \iend, \istart   // iend = (vend >> shift) & (ptrs - 1)
> +       and     \iend, \iend, \ptrs - 1 // iend = (vend >> shift) & (ptrs - 1)
>          mov     \istart, \ptrs
>          sub     \count, \count, #1
>          mul     \istart, \istart, \count
> @@ -245,9 +243,7 @@ ENDPROC(preserve_boot_args)
>                                          // our entries span multiple tables
> 
>          lsr     \istart, \vstart, \shift
> -       mov     \count, \ptrs
> -       sub     \count, \count, #1
> -       and     \istart, \istart, \count
> +       and     \istart, \istart, \ptrs - 1
> 
>          sub     \count, \iend, \istart
>          add     \count, \count, #1
> @@ -376,6 +372,7 @@ __create_page_tables:
> 
>          mov     x4, EXTRA_PTRS
>          create_table_entry x0, x3, EXTRA_SHIFT, x4, x5, x6
> +       .set    .Lidmap_ptrs_per_pgd, PTRS_PER_PGD
>   #else
>          /*
>           * If VA_BITS == 48, we don't have to configure an additional
> @@ -383,13 +380,13 @@ __create_page_tables:
>           */
>          mov     x4, #1 << (PHYS_MASK_SHIFT - PGDIR_SHIFT)
>          str_l   x4, idmap_ptrs_per_pgd, x5
> +       .set    .Lidmap_ptrs_per_pgd, 1 << (PHYS_MASK_SHIFT - PGDIR_SHIFT)
>   #endif
>   1:
> -       ldr_l   x4, idmap_ptrs_per_pgd
>          mov     x5, x3                          // __pa(__idmap_text_start)
>          adr_l   x6, __idmap_text_end            // __pa(__idmap_text_end)
> 
> -       map_memory x0, x1, x3, x6, x7, x3, x4, x10, x11, x12, x13, x14
> +       map_memory x0, x1, x3, x6, x7, x3, .Lidmap_ptrs_per_pgd, x10,
> x11, x12, x13, x14
> 
>          /*
>           * Map the kernel image (starting with PHYS_OFFSET).
> @@ -397,13 +394,12 @@ __create_page_tables:
>          adrp    x0, swapper_pg_dir
>          mov_q   x5, KIMAGE_VADDR + TEXT_OFFSET  // compile time __va(_text)
>          add     x5, x5, x23                     // add KASLR displacement
> -       mov     x4, PTRS_PER_PGD
>          adrp    x6, _end                        // runtime __pa(_end)
>          adrp    x3, _text                       // runtime __pa(_text)
>          sub     x6, x6, x3                      // _end - _text
>          add     x6, x6, x5                      // runtime __va(_end)
> 
> -       map_memory x0, x1, x5, x6, x7, x3, x4, x10, x11, x12, x13, x14
> +       map_memory x0, x1, x5, x6, x7, x3, PTRS_PER_PGD, x10, x11, x12, x13, x14
> 
>          /*
>           * Since the page tables have been populated with non-cacheable
> 
> _______________________________________________
> 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 v5 20/20] cpufreq: scmi: add support for fast frequency switching
From: Alexey Klimov @ 2018-01-04 22:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1514904162-11201-21-git-send-email-sudeep.holla@arm.com>

Hi Sudeep,

On Tue, Jan 2, 2018 at 2:42 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> The cpufreq core provides option for drivers to implement fast_switch
> callback which is invoked for frequency switching from interrupt context.
>
> This patch adds support for fast_switch callback in SCMI cpufreq driver
> by making use of polling based SCMI transfer. It also sets the flag
> fast_switch_possible.
>
> Cc: linux-pm at vger.kernel.org
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
> ---
>  drivers/cpufreq/scmi-cpufreq.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
>
> diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
> index 0ee9335d0063..d0a82d7c6fd4 100644
> --- a/drivers/cpufreq/scmi-cpufreq.c
> +++ b/drivers/cpufreq/scmi-cpufreq.c
> @@ -64,6 +64,19 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
>         return perf_ops->freq_set(handle, priv->domain_id, freq, false);
>  }
>
> +static unsigned int scmi_cpufreq_fast_switch(struct cpufreq_policy *policy,
> +                                            unsigned int target_freq)
> +{
> +       struct scmi_data *priv = policy->driver_data;
> +       struct scmi_perf_ops *perf_ops = handle->perf_ops;
> +
> +       if (!perf_ops->freq_set(handle, priv->domain_id,
> +                               target_freq * 1000, true))
> +               return target_freq;
> +
> +       return 0;
> +}

Could you please explain how it's supposed to work for purpose of fast
frequency switching?

I am trying to track down ->freq_set.
So it looks like this will fire an scmi perf level set command and
will poll for this command to complete without asking for firmware to
send command completion irq.

scmi_perf_level_set() will call the following functions:

scmi_one_xfer_init();
scmi_do_xfer(handle, t);
scmi_one_xfer_put(handle, t);


The first function in the list calls scmi_one_xfer_get() which has
this in the description (I guess because of down_timeout()):
"This function can sleep depending on pending requests already in the system
for the SCMI entity. Further, this also holds a spinlock to maintain
integrity of internal data structures."

So it can sleep.

As far as I see description of fast frequency switching it's required
for fast_switch to not sleep:
(file Documentation/cpu-freq/cpu-drivers.txt)

"This function is used for frequency switching from scheduler's context.
Not all drivers are expected to implement it, as sleeping from within
this callback isn't allowed. This callback must be highly optimized to
do switching as fast as possible."


The other questions to this implementation of fast switching:

1) Fast switching callback must be highly optimized. Is it now? I see
few spinlocks (in scmi mbox client and in the mailbox framework) there
and polling functionality with udelay(5) inside that will timeout (if
my calculations are correct) after 0.5 ms.
2) Is it highly dependent on transport? If mailbox transport
->send_data() may sleep or hrtimer-based polling in mailbox framework
will be used, then this fast switch won't work, right?

I am still looking into that: I can be wrong and just trying to
understand if it is all okay.

[..]

Thanks,
Alexey

^ permalink raw reply

* [PATCH v2 1/3] drm/sun4i: hdmi: Check for unset best_parent in sun4i_tmds_determine_rate
From: Jonathan Liu @ 2018-01-04 22:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180104195650.vmbooz3pwjy77wt7@flea.lan>

Hi Maxime,

On 5 January 2018 at 06:56, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> On Tue, Dec 26, 2017 at 10:12:25PM +1100, Jonathan Liu wrote:
>> We should check if the best match has been set before comparing it.
>>
>> Fixes: 9c5681011a0c ("drm/sun4i: Add HDMI support")
>> Signed-off-by: Jonathan Liu <net147@gmail.com>
>> ---
>>  drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
>> index dc332ea56f6c..4d235e5ea31c 100644
>> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
>> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_tmds_clk.c
>> @@ -102,7 +102,7 @@ static int sun4i_tmds_determine_rate(struct clk_hw *hw,
>>                                       goto out;
>>                               }
>>
>> -                             if (abs(rate - rounded / i) <
>> +                             if (!best_parent || abs(rate - rounded / i) <
>
> Why is that causing any issue?
>
> If best_parent is set to 0...
>
>>                                   abs(rate - best_parent / best_div)) {
>
> ... the value returned here is going to be rate, which is going to be
> higher than the first part of the comparison meaning ...
>
>>                                       best_parent = rounded;
>
> ... that best_parent is going to be set there.

Consider the following:
rate = 83500000
rounded = ideal * 2

It is possible that if "rounded = clk_hw_round_rate(parent, ideal)"
gives high enough values that the condition "abs(rate - rounded / i) <
abs(rate - best_parent / best_div)" is never met.

Then you can end up with:
req->rate = 0
req->best_parent_rate = 0
req->best_parent_hw = ...

Also, the sun4i_tmds_calc_divider function has a similar check.

Regards,
Jonathan

^ permalink raw reply

* [PATCH v6 10/10] clocksource: timer-dm: Check prescaler value
From: Ladislav Michl @ 2018-01-04 22:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1514887799-24605-11-git-send-email-j-keerthy@ti.com>

On Tue, Jan 02, 2018 at 03:39:59PM +0530, Keerthy wrote:
> From: Ladislav Michl <ladis@linux-mips.org>
> 
> Invalid prescaler value is silently ignored. Fix that
> by returning -EINVAL in such case. As invalid value
> disabled use of the prescaler, use -1 explicitely for
> that purpose.
> 
> Signed-off-by: Ladislav Michl <ladis@linux-mips.org>
> ---
>  drivers/clocksource/timer-dm.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/clocksource/timer-dm.c b/drivers/clocksource/timer-dm.c
> index 60db173..01a9cb0 100644
> --- a/drivers/clocksource/timer-dm.c
> +++ b/drivers/clocksource/timer-dm.c
> @@ -672,6 +672,9 @@ int omap_dm_timer_set_prescaler(struct omap_dm_timer *timer, int prescaler)
>  	if (prescaler >= 0x00 && prescaler <= 0x07) {
>  		l |= OMAP_TIMER_CTRL_PRE;
>  		l |= prescaler << 2;
> +	} else {
> +		if (prescaler != -1)
> +			return -EINVAL;

Argh... This is actually wrong, as it leaves timer enabled.
I suggest simply dropping this patch and I'll rethink whole
approach a bit later (and better).

>  	}
>  	omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
>  

Sorry for the noise,
	ladis

^ permalink raw reply

* v4.14.9 on ARMv5: OK with gcc 4.8/5.4, NOK with gcc 7.2
From: Russell King - ARM Linux @ 2018-01-04 22:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAAQYJAuwE9n-M7pcpJL53JLVY0PmO721mHh7aZ5KkCoYTzdRMQ@mail.gmail.com>

On Thu, Jan 04, 2018 at 07:19:45PM +0100, Andrea Adami wrote:
> On Thu, Jan 4, 2018 at 6:16 PM, Russell King - ARM Linux
> <linux@armlinux.org.uk> wrote:
> > On Thu, Jan 04, 2018 at 06:02:38PM +0100, Thomas Petazzoni wrote:
> >> Hello,
> >>
> >> I'm pretty sure it has already been reported, but just in case: I'm
> >> testing v4.14.9 on an ARMv5 platform (Kirkwood-based OpenBlocks A7).
> >> mvebu_v5_defconfig boots fine when built with gcc 4.8 (good old
> >> Sourcery toolchain) or gcc 5.4 (some old Linaro toolchain), but doesn't
> >> boot at all when built with gcc 7.2 (Fedora toolchain). Even when
> >> configured and booted with earlyprintk, the kernel doesn't say anything.
> >>
> >> The toolchain being used is the default ARM toolchain provided by
> >> Fedora 27. It says:
> >>
> >> gcc version 7.2.1 20170915 (Red Hat Cross 7.2.1-1) (GCC)
> >> GNU ld version 2.29.1-1.fc27
> >>
> >> So it's quite bleeding edge.
> >>
> >> Let me know if this has already been fixed, or if I should test a
> >> patch. I have not tested 4.15-rc or next at this point, assuming that
> >> if a fix had been made, it would have been backported to 4.14-stable.
> >
> > It's a known issue -
> >
> > http://archive.armlinux.org.uk/lurker/message/20171018.095713.a56a717b.en.html
> >
> > but so far no patches have been forthcoming for the kernel, because
> > (I guess) it's deemed to be a gcc bug.
> >
> > It's one of those discussions that just seemed to die without any
> > real conclusion.
> >
> > --
> > RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
> > FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
> > According to speedtest.net: 8.21Mbps down 510kbps up
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> 
> I am happy to report the gcc bug has been fixed in trunk.
> I am as well dubious where they say this should also fix gcc6 where we
> have no known issues with gcc6.
> 
> "
> This should also fix
> incorrect generation of ldrd/strd with unaligned accesses that could
> previously have occurred on ARMv5e where all such operations must be
> 64-bit aligned."
> 
> https://github.com/gcc-mirror/gcc/commit/f59996b56aaa1c1d62a16cbb4010775b624cbde0
> 
> In OpenEmbedded we backported the patch a while ago, see the
> discussion about qemu booting where real hw doesn't:
> http://lists.openembedded.org/pipermail/openembedded-core/2017-November/144045.html

Thanks for reporting the update Andrea!

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* [PATCH] arm64: dts: sprd: remove broken header inclusion
From: Arnd Bergmann @ 2018-01-04 22:58 UTC (permalink / raw)
  To: linux-arm-kernel

The added header inclusion broke the 'allmodconfig' build in
arm-soc, presumably since the file is added in a different tree:

In file included from arch/arm64/boot/dts/sprd/sp9860g-1h10.dts:11:0:
arch/arm64/boot/dts/sprd/sc9860.dtsi:10:10: fatal error: dt-bindings/clock/sprd,sc9860-clk.h: No such file or directory

It turns out we don't actually need to include it at all, so
I'm removing the line again to fix the build.

Fixes: 22f37a242925 ("arm64: dts: add clocks for SC9860")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
I've added this one as a fixup now.

 arch/arm64/boot/dts/sprd/sc9860.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index bf03da45336a..5dbfb796d9f9 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -7,7 +7,6 @@
  */
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/clock/sprd,sc9860-clk.h>
 #include "whale2.dtsi"
 
 / {
-- 
2.9.0

^ permalink raw reply related

* [PATCH V7 12/12] arm64: dts: add clocks for SC9860
From: Arnd Bergmann @ 2018-01-04 23:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK8P3a3XA+p__p9+B-jCONUDe1MuOgsee6oD0USmwK06iXqH9g@mail.gmail.com>

On Thu, Jan 4, 2018 at 10:34 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Thu, Dec 7, 2017 at 1:57 PM, Chunyan Zhang
> <chunyan.zhang@spreadtrum.com> wrote:
>> Some clocks on SC9860 are in the same address area with syscon devices,
>> those are what have a property of 'sprd,syscon' which would refer to
>> syscon devices, others would have a reg property indicated their address
>> ranges.
>>
>> Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
>> ---
>>  arch/arm64/boot/dts/sprd/sc9860.dtsi | 115 +++++++++++++++++++++++++++++++++++
>>  arch/arm64/boot/dts/sprd/whale2.dtsi |  18 +++++-
>>  2 files changed, 131 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
>> index 7b7d8ce..bf03da4 100644
>> --- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
>> +++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
>> @@ -7,6 +7,7 @@
>>   */
>>
>>  #include <dt-bindings/interrupt-controller/arm-gic.h>
>> +#include <dt-bindings/clock/sprd,sc9860-clk.h>
>>  #include "whale2.dtsi"
>
> This caused a build error since the sprd,sc9860-clk.h file does not
> exist, I'll revert or undo the patch tomorrow.

I've taken another look, and fixing it by removing the broken #include
was easier than undoing the patches, so I did that now, see
https://patchwork.kernel.org/patch/10145773/

      Arnd

^ permalink raw reply

* [PATCH 03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Laura Abbott @ 2018-01-04 23:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515078515-13723-4-git-send-email-will.deacon@arm.com>

On 01/04/2018 07:08 AM, Will Deacon wrote:
> For non-KASLR kernels where the KPTI behaviour has not been overridden
> on the command line we can use ID_AA64PFR0_EL1.CSV3 to determine whether
> or not we should unmap the kernel whilst running at EL0.
> 
> Signed-off-by: Will Deacon <will.deacon@arm.com>
> ---
>   arch/arm64/include/asm/sysreg.h | 1 +
>   arch/arm64/kernel/cpufeature.c  | 7 ++++++-
>   2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 08cc88574659..ae519bbd3f9e 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -437,6 +437,7 @@
>   #define ID_AA64ISAR1_DPB_SHIFT		0
>   
>   /* id_aa64pfr0 */
> +#define ID_AA64PFR0_CSV3_SHIFT		60
>   #define ID_AA64PFR0_SVE_SHIFT		32
>   #define ID_AA64PFR0_GIC_SHIFT		24
>   #define ID_AA64PFR0_ASIMD_SHIFT		20
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 9f0545dfe497..e11c11bb5b02 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -145,6 +145,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
>   };
>   
>   static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
> +	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
>   	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
>   	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
>   	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
> @@ -851,6 +852,8 @@ static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
>   static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>   				int __unused)
>   {
> +	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
> +
>   	/* Forced on command line? */
>   	if (__kpti_forced) {
>   		pr_info_once("kernel page table isolation forced %s by command line option\n",
> @@ -862,7 +865,9 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>   	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
>   		return true;
>   
> -	return false;
> +	/* Defer to CPU feature registers */
> +	return !cpuid_feature_extract_unsigned_field(pfr0,
> +						     ID_AA64PFR0_CSV3_SHIFT);
>   }
>   
>   static int __init parse_kpti(char *str)
> 

Nit: we only print a message if it's forced on the command line,
can we get a message similar to x86 regardless of state to
clearly indicate if KPTI is enabled?

Thanks,
Laura

^ permalink raw reply

* [PATCH v3 00/20] arm64: Unmap the kernel whilst running in userspace (KPTI)
From: Russell King - ARM Linux @ 2018-01-04 23:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <092a51ec-f856-2b51-5d47-8acbdc671031@gmail.com>

On Thu, Jan 04, 2018 at 10:23:40AM -0800, Florian Fainelli wrote:
> Great, thanks! Bonus question, if someone is using any of the affected
> devices in AArch32, should we be expecting to see ARM/Linux changes as
> well, that is, is there a plan to come up with a kpti implementation for
> ARM?

Given what little information there is, I've been trying today to see
whether I can detect whether a userspace address is cached or uncached
- the results suggest that I have code that works with an error rate of
between 2 and 20 in 10000 in a 32-bit VM on Cortex A72.  Whether that
translates to Cortex A15, I don't know yet - I need a working Cortex
A15 platform for that.  Unfortunately, my only Cortex A15 platform does
not setup the architected timer, and so the kernel doesn't make it
available to userspace.  I will be raising this with those concerned on
Monday, in the hope of getting it resolved.

Based on this and the information on developer.arm.com, my gut feeling
is that 32-bit kernels running on a CPU with an architected timer _or_
with some other high resolution timer available to non-privileged
userspace are likely to be vulnerable in some way, as it seems to be
possible to measure whether a specific load results in data being
sourced from the cache or from memory.

That all said, what I read about Chrome OS is that google believes
that isn't exploitable - which seems to be a contradiction to the
information ARM have published.  I'm not sure what the reasoning is
there, maybe there's just no current working exploit yet.

So, the message to take away is that 32-bit kernels are rather behind
on this issue, there are no known patches in development, and it is
not really known whether there is an exploitable problem for 32-bit
kernels or not.

Not really where I'd like 32-bit kernels to be.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* [PATCH v3 0/2] Xilinx ZynqMP IPI Mailbox Controller Driver
From: Wendy Liang @ 2018-01-04 23:51 UTC (permalink / raw)
  To: linux-arm-kernel

Introduce mailbox controller driver for ZynqMP IPI(Inter-processor
interrupt) IP core.

There is previous discussion on the DT bindings:
https://patchwork.kernel.org/patch/10012755/

v3:
 - add NULL entry to of_device_id of IPI controller

v2:
 - change SPDX-License-Identifier license text style in .c file
 - replace xlnx-ipi-ids with xlnx,ipi-ids

Wendy Liang (2):
  mailbox: ZynqMP IPI mailbox controller
  dt-bindings: mailbox: Add Xilinx IPI Mailbox

 .../bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt   | 104 ++++
 drivers/mailbox/Kconfig                            |   8 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/zynqmp-ipi-mailbox.c               | 635 +++++++++++++++++++++
 include/linux/mailbox/zynqmp-ipi-message.h         |  24 +
 5 files changed, 773 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
 create mode 100644 drivers/mailbox/zynqmp-ipi-mailbox.c
 create mode 100644 include/linux/mailbox/zynqmp-ipi-message.h

-- 
2.7.4

^ permalink raw reply

* [PATCH v3 1/2] mailbox: ZynqMP IPI mailbox controller
From: Wendy Liang @ 2018-01-04 23:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515109891-17133-1-git-send-email-jliang@xilinx.com>

This patch is to introduce ZynqMP IPI mailbox controller driver
to use the ZynqMP IPI block as mailboxes.

Signed-off-by: Wendy Liang <jliang@xilinx.com>
---
 drivers/mailbox/Kconfig                    |   8 +
 drivers/mailbox/Makefile                   |   2 +
 drivers/mailbox/zynqmp-ipi-mailbox.c       | 635 +++++++++++++++++++++++++++++
 include/linux/mailbox/zynqmp-ipi-message.h |  24 ++
 4 files changed, 669 insertions(+)
 create mode 100644 drivers/mailbox/zynqmp-ipi-mailbox.c
 create mode 100644 include/linux/mailbox/zynqmp-ipi-message.h

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index ba2f152..876614a 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -171,4 +171,12 @@ config BCM_FLEXRM_MBOX
 	  Mailbox implementation of the Broadcom FlexRM ring manager,
 	  which provides access to various offload engines on Broadcom
 	  SoCs. Say Y here if you want to use the Broadcom FlexRM.
+
+config ZYNQMP_IPI_MBOX
+	tristate "Xilinx ZynqMP IPI Mailbox"
+	depends on ARCH_ZYNQMP && OF
+	help
+	  Mailbox implementation for Xilinx ZynqMP IPI. It is used to send
+	  notification or short message between processors with Xilinx
+	  ZynqMP IPI.
 endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 4896f8d..155f72f 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -36,3 +36,5 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX)	+= bcm-flexrm-mailbox.o
 obj-$(CONFIG_QCOM_APCS_IPC)	+= qcom-apcs-ipc-mailbox.o
 
 obj-$(CONFIG_TEGRA_HSP_MBOX)	+= tegra-hsp.o
+
+obj-$(CONFIG_ZYNQMP_IPI_MBOX)	+= zynqmp-ipi-mailbox.o
diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
new file mode 100644
index 0000000..4258360d
--- /dev/null
+++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
@@ -0,0 +1,635 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Inter Processor Interrupt(IPI) Mailbox Driver
+ *
+ * Copyright (C) 2017 Xilinx Inc.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/arm-smccc.h>
+#include <linux/delay.h>
+#include <linux/mailbox/zynqmp-ipi-message.h>
+
+/* IPI agent ID any */
+#define IPI_ID_ANY 0xFFUL
+
+/* indicate if ZynqMP IPI mailbox driver uses SMC calls or HVC calls */
+#define USE_SMC 0
+#define USE_HVC 1
+
+/* Default IPI SMC function IDs */
+#define SMC_IPI_MAILBOX_OPEN            0x82001000U
+#define SMC_IPI_MAILBOX_RELEASE         0x82001001U
+#define SMC_IPI_MAILBOX_STATUS_ENQUIRY  0x82001002U
+#define SMC_IPI_MAILBOX_NOTIFY          0x82001003U
+#define SMC_IPI_MAILBOX_ACK             0x82001004U
+#define SMC_IPI_MAILBOX_ENABLE_IRQ      0x82001005U
+#define SMC_IPI_MAILBOX_DISABLE_IRQ     0x82001006U
+
+/* IPI SMC Macros */
+#define IPI_SMC_OPEN_IRQ_MASK		0x00000001UL /* IRQ enable bit in IPI
+						      * open SMC call
+						      */
+#define IPI_SMC_NOTIFY_BLOCK_MASK	0x00000001UL /* Flag to indicate if
+						      * IPI notification needs
+						      * to be blocking.
+						      */
+#define IPI_SMC_ENQUIRY_DIRQ_MASK       0x00000001UL /* Flag to indicate if
+						      * notification interrupt
+						      * to be disabled.
+						      */
+#define IPI_SMC_ACK_EIRQ_MASK           0x00000001UL /* Flag to indicate if
+						      * notification interrupt
+						      * to be enabled.
+						      */
+
+/* IPI mailbox status */
+#define IPI_MB_STATUS_IDLE              0
+#define IPI_MB_STATUS_SEND_PENDING      1
+#define IPI_MB_STATUS_RECV_PENDING      2
+
+#define IPI_MB_CHNL_TX 0 /* IPI mailbox TX channel */
+#define IPI_MB_CHNL_RX 1 /* IPI mailbox RX channel */
+
+/**
+ * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel
+ * @is_opened: indicate if the IPI channel is opened
+ * @req_buf: local to remote request buffer start address
+ * @resp_buf: local to remote response buffer start address
+ * @req_buf_size: request buffer size
+ * @resp_buf_size: response buffer size
+ * @chan_type: channel type
+ */
+struct zynqmp_ipi_mchan {
+	int is_opened;
+	void __iomem *req_buf;
+	void __iomem *resp_buf;
+	size_t req_buf_size;
+	size_t resp_buf_size;
+	unsigned int chan_type;
+};
+
+/**
+ * struct zynqmp_ipi_mbox_pdata - Description of a ZynqMP IPI mailbox
+ *                                platform data.
+ * @dev:                  device pointer corresponding to the Xilinx ZynqMP
+ *                        IPI mailbox
+ * @local_id:             local IPI agent ID
+ * @remote_id:            remote IPI agent ID
+ * @method:               IPI SMC or HVC is going to be used
+ * @mbox:                 mailbox Controller
+ * @mchans:               array for channels, tx channel and rx channel.
+ * @irq:                  IPI agent interrupt ID
+ * @lock:                 IPI mailbox platform data lock
+ */
+struct zynqmp_ipi_mbox_pdata {
+	struct device *dev;
+	u32 local_id;
+	u32 remote_id;
+	unsigned int method;
+	struct mbox_controller mbox;
+	struct zynqmp_ipi_mchan mchans[2];
+	int irq;
+	spinlock_t lock; /* spin lock for local data */
+};
+
+static void zynqmp_ipi_fw_call(struct zynqmp_ipi_mbox_pdata *pdata,
+			       unsigned long a0, unsigned long a3,
+			       unsigned long a4, unsigned long a5,
+			       unsigned long a6, unsigned long a7,
+			       struct arm_smccc_res *res)
+{
+	unsigned long a1, a2;
+
+	a1 = pdata->local_id;
+	a2 = pdata->remote_id;
+	if (pdata->method == USE_SMC)
+		arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+	else
+		arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+/**
+ * zynqmp_ipi_interrupt - Interrupt handler for IPI notification
+ *
+ * @irq:  Interrupt number
+ * @data: ZynqMP IPI mailbox platform data.
+ *
+ * Return: -EINVAL if there is no instance
+ * IRQ_NONE if the interrupt is not ours.
+ * IRQ_HANDLED if the rx interrupt was successfully handled.
+ */
+static irqreturn_t zynqmp_ipi_interrupt(int irq, void *data)
+{
+	struct zynqmp_ipi_mbox_pdata *pdata = data;
+	struct mbox_chan *chan;
+	struct zynqmp_ipi_mchan *mchan;
+	struct zynqmp_ipi_message msg;
+	u64 arg0, arg3;
+	struct arm_smccc_res res;
+	int ret;
+
+	arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
+	arg3 = IPI_SMC_ENQUIRY_DIRQ_MASK;
+	zynqmp_ipi_fw_call(pdata, arg0, arg3, 0, 0, 0, 0, &res);
+	ret = (int)(res.a0 & 0xFFFFFFFF);
+	if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {
+		chan = &pdata->mbox.chans[IPI_MB_CHNL_RX];
+		mchan = chan->con_priv;
+		if (mchan->is_opened) {
+			msg.len = mchan->req_buf_size;
+			msg.data = mchan->req_buf;
+			/* Client will direclty copy data from
+			 * IPI buffer to client data memory
+			 */
+			mbox_chan_received_data(chan, (void *)&msg);
+			return IRQ_HANDLED;
+		}
+	}
+	return IRQ_NONE;
+}
+
+/**
+ * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.
+ *
+ * @chan: Channel Pointer
+ *
+ * Return: 'true' if there is pending rx data, 'false' if there is none.
+ */
+static bool zynqmp_ipi_peek_data(struct mbox_chan *chan)
+{
+	struct device *dev = chan->mbox->dev;
+	struct zynqmp_ipi_mbox_pdata *pdata = dev_get_drvdata(dev);
+	struct zynqmp_ipi_mchan *mchan = chan->con_priv;
+	int ret;
+	u64 arg0;
+	struct arm_smccc_res res;
+
+	if (WARN_ON(!pdata)) {
+		dev_err(dev, "no platform drv data??\n");
+		return false;
+	}
+
+	arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
+	zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+	ret = (int)(res.a0 & 0xFFFFFFFF);
+
+	if (mchan->chan_type == IPI_MB_CHNL_TX) {
+		/* TX channel, check if the message has been acked
+		 * by the remote, if yes, response is available.
+		 */
+		if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)
+			return false;
+		else
+			return true;
+	} else if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {
+		/* RX channel, check if there is message arrived. */
+		return true;
+	}
+	return false;
+}
+
+/**
+ * zynqmp_ipi_last_tx_done - See if the last tx message is sent
+ *
+ * @chan: Channel pointer
+ *
+ * Return: 'true' is no pending tx data, 'false' if there are any.
+ */
+static bool zynqmp_ipi_last_tx_done(struct mbox_chan *chan)
+{
+	struct device *dev = chan->mbox->dev;
+	struct zynqmp_ipi_mbox_pdata *pdata = dev_get_drvdata(dev);
+	struct zynqmp_ipi_mchan *mchan = chan->con_priv;
+	int ret;
+	u64 arg0;
+	struct arm_smccc_res res;
+	struct zynqmp_ipi_message msg;
+
+	if (WARN_ON(!pdata)) {
+		dev_err(dev, "no platform drv data??\n");
+		return false;
+	}
+
+	if (mchan->chan_type == IPI_MB_CHNL_TX) {
+		/* We only need to check if the message been taken
+		 * by the remote in the TX channel
+		 */
+		arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+		/* Check the SMC call status, a0 of the result */
+		ret = (int)(res.a0 & 0xFFFFFFFF);
+		if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)
+			return false;
+
+		msg.len = mchan->resp_buf_size;
+		msg.data = mchan->resp_buf;
+		/* Client will direclty copy data from
+		 * IPI buffer to client data memory
+		 */
+		mbox_chan_received_data(chan, (void *)&msg);
+		return true;
+	}
+	/* Always true for the response message in RX channel */
+	return true;
+}
+
+/**
+ * zynqmp_ipi_send_data - Send data
+ *
+ * @chan: Channel Pointer
+ * @data: Message Pointer
+ *
+ * Return: 0 if all goes good, else appropriate error messages.
+ */
+static int zynqmp_ipi_send_data(struct mbox_chan *chan, void *data)
+{
+	struct device *dev = chan->mbox->dev;
+	struct zynqmp_ipi_mbox_pdata *pdata = dev_get_drvdata(dev);
+	struct zynqmp_ipi_mchan *mchan = chan->con_priv;
+	struct zynqmp_ipi_message *msg = data;
+	u64 arg0;
+	struct arm_smccc_res res;
+	u32 timeout;
+	int ret;
+
+	if (WARN_ON(!pdata)) {
+		dev_err(dev, "no platform drv data??\n");
+		return -EINVAL;
+	}
+
+	if (mchan->chan_type == IPI_MB_CHNL_TX) {
+		/* Send request message */
+		if (msg && msg->len > mchan->resp_buf_size) {
+			dev_err(dev, "channel %d message length %u > max %lu\n",
+				mchan->chan_type, (unsigned int)msg->len,
+				mchan->resp_buf_size);
+			return -EINVAL;
+		}
+		/* Enquire if the mailbox is free to send message */
+		arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;
+		timeout = 10;
+		do {
+			zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+			ret = res.a0 & 0xFFFFFFFF;
+			if (ret >= 0 && !(ret & IPI_MB_STATUS_SEND_PENDING))
+				break;
+			usleep_range(1, 2);
+			timeout--;
+		} while (timeout);
+		if (!timeout) {
+			dev_warn(dev, "channel %d sending msg timesout.\n",
+				 pdata->remote_id);
+			return -ETIME;
+		}
+		/* Copy message to the request buffer */
+		if (msg && msg->len)
+			memcpy_toio(mchan->req_buf, msg->data, msg->len);
+		/* Kick IPI mailbox to send message */
+		arg0 = SMC_IPI_MAILBOX_NOTIFY;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+	} else {
+		/* Send response message */
+		if (msg && msg->len > mchan->resp_buf_size) {
+			dev_err(dev, "channel %d message length %u > max %lu\n",
+				mchan->chan_type, (unsigned int)msg->len,
+				mchan->resp_buf_size);
+			return -EINVAL;
+		}
+		if (msg && msg->len)
+			memcpy(mchan->resp_buf, msg->data, msg->len);
+		arg0 = SMC_IPI_MAILBOX_NOTIFY;
+		arg0 = SMC_IPI_MAILBOX_ACK;
+		zynqmp_ipi_fw_call(pdata, arg0, IPI_SMC_ACK_EIRQ_MASK,
+				   0, 0, 0, 0, &res);
+	}
+	return 0;
+}
+
+/**
+ * zynqmp_ipi_startup - Startup the IPI channel
+ *
+ * @chan: Channel pointer
+ *
+ * Return: 0 if all goes good, else return corresponding error message
+ */
+static int zynqmp_ipi_startup(struct mbox_chan *chan)
+{
+	struct device *dev = chan->mbox->dev;
+	struct zynqmp_ipi_mbox_pdata *pdata = dev_get_drvdata(dev);
+	struct zynqmp_ipi_mchan *mchan = chan->con_priv;
+	u64 arg0;
+	struct arm_smccc_res res;
+	int ret = 0;
+	unsigned long flags;
+	unsigned int nchan_type;
+
+	spin_lock_irqsave(&pdata->lock, flags);
+	if (mchan->is_opened) {
+		/* IPI mailbox has been opened */
+		spin_unlock_irqrestore(&pdata->lock, flags);
+		return -EBUSY;
+	}
+
+	/* If no channel has been opened, open the IPI mailbox */
+	nchan_type = (mchan->chan_type + 1) % 2;
+	if (!pdata->mchans[nchan_type].is_opened) {
+		arg0 = SMC_IPI_MAILBOX_OPEN;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+		/* Check the SMC call status, a0 of the result */
+		ret = (int)(res.a0 | 0xFFFFFFFF);
+		if (res.a0 < 0) {
+			dev_err(dev, "SMC to open the IPI channel failed.\n");
+			ret = res.a0;
+			spin_unlock_irqrestore(&pdata->lock, flags);
+			return ret;
+		}
+		ret = 0;
+	}
+
+	/* If it is RX channel, enable the IPI notification interrupt */
+	if (mchan->chan_type == IPI_MB_CHNL_RX) {
+		arg0 = SMC_IPI_MAILBOX_ENABLE_IRQ;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+	}
+	mchan->is_opened = 1;
+	spin_unlock_irqrestore(&pdata->lock, flags);
+
+	return ret;
+}
+
+/**
+ * zynqmp_ipi_shutdown - Shutdown the IPI channel
+ *
+ * @chan: Channel pointer
+ */
+static void zynqmp_ipi_shutdown(struct mbox_chan *chan)
+{
+	struct device *dev = chan->mbox->dev;
+	struct zynqmp_ipi_mbox_pdata *pdata = dev_get_drvdata(dev);
+	struct zynqmp_ipi_mchan *mchan = chan->con_priv;
+	u64 arg0;
+	struct arm_smccc_res res;
+	unsigned long flags;
+	unsigned int chan_type;
+
+	spin_lock_irqsave(&pdata->lock, flags);
+	if (!mchan->is_opened) {
+		spin_unlock_irqrestore(&pdata->lock, flags);
+		return;
+	}
+
+	/* If it is RX channel, disable notification interrupt */
+	chan_type = mchan->chan_type;
+	if (chan_type == IPI_MB_CHNL_RX) {
+		arg0 = SMC_IPI_MAILBOX_DISABLE_IRQ;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+	}
+	/* Release IPI mailbox if no other channel is opened */
+	chan_type = (chan_type + 1) % 2;
+	if (!pdata->mchans[chan_type].is_opened) {
+		arg0 = SMC_IPI_MAILBOX_RELEASE;
+		zynqmp_ipi_fw_call(pdata, arg0, 0, 0, 0, 0, 0, &res);
+	}
+
+	mchan->is_opened = 0;
+	spin_unlock_irqrestore(&pdata->lock, flags);
+}
+
+/* ZynqMP IPI mailbox operations */
+static const struct mbox_chan_ops zynqmp_ipi_chan_ops = {
+	.startup = zynqmp_ipi_startup,
+	.shutdown = zynqmp_ipi_shutdown,
+	.peek_data = zynqmp_ipi_peek_data,
+	.last_tx_done = zynqmp_ipi_last_tx_done,
+	.send_data = zynqmp_ipi_send_data,
+};
+
+/**
+ * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel
+ *
+ * @mbox: mailbox controller pointer
+ * @p:    phandle pointer
+ *
+ * Return: Mailbox channel, else return error pointer.
+ */
+static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox,
+					     const struct of_phandle_args *p)
+{
+	struct zynqmp_ipi_mbox_pdata *pdata;
+	struct mbox_chan *chan;
+	struct device *dev = mbox->dev;
+	unsigned int chan_type;
+
+	pdata = container_of(mbox, struct zynqmp_ipi_mbox_pdata, mbox);
+
+	/* Only supports TX and RX channels */
+	chan_type = p->args[0];
+	if (chan_type != IPI_MB_CHNL_TX && chan_type != IPI_MB_CHNL_RX) {
+		dev_err(dev, "req chnl failure: invalid chnl type %u.\n",
+			chan_type);
+		return ERR_PTR(-EINVAL);
+	}
+	chan = &mbox->chans[chan_type];
+	return chan;
+}
+
+static const struct of_device_id zynqmp_ipi_of_match[] = {
+	{.compatible = "xlnx,zynqmp-ipi-mailbox"},
+	{},
+};
+MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);
+
+static int zynqmp_ipi_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = pdev->dev.of_node;
+	struct zynqmp_ipi_mbox_pdata *pdata;
+	struct zynqmp_ipi_mchan *mchan;
+	struct mbox_chan *chans;
+	struct mbox_controller *mbox;
+	const unsigned char *prop;
+	struct resource *res;
+	int ret = -EINVAL;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = dev;
+
+	mchan = &pdata->mchans[IPI_MB_CHNL_TX];
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "local_request_region");
+	if (res) {
+		mchan->req_buf_size = resource_size(res);
+		mchan->req_buf = devm_ioremap(&pdev->dev, res->start,
+					      mchan->req_buf_size);
+		if (IS_ERR(mchan->req_buf)) {
+			dev_err(dev, "Unable to map IPI buffer I/O memory\n");
+			ret = PTR_ERR(mchan->req_buf);
+			return ret;
+		}
+	}
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "remote_response_region");
+	if (res) {
+		mchan->resp_buf_size = resource_size(res);
+		mchan->resp_buf = devm_ioremap(&pdev->dev, res->start,
+					       mchan->resp_buf_size);
+		if (IS_ERR(mchan->resp_buf)) {
+			dev_err(dev, "Unable to map IPI buffer I/O memory\n");
+			ret = PTR_ERR(mchan->resp_buf);
+			return ret;
+		}
+	}
+
+	mchan = &pdata->mchans[IPI_MB_CHNL_RX];
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "remote_request_region");
+	if (res) {
+		mchan->req_buf_size = resource_size(res);
+		mchan->req_buf = devm_ioremap(&pdev->dev, res->start,
+					      mchan->req_buf_size);
+		if (IS_ERR(mchan->req_buf)) {
+			dev_err(dev, "Unable to map IPI buffer I/O memory\n");
+			ret = PTR_ERR(mchan->req_buf);
+			return ret;
+		}
+	}
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "local_response_region");
+	if (res) {
+		mchan->resp_buf_size = resource_size(res);
+		mchan->resp_buf = devm_ioremap(&pdev->dev, res->start,
+					       mchan->resp_buf_size);
+		if (IS_ERR(mchan->resp_buf)) {
+			dev_err(dev, "Unable to map IPI buffer I/O memory\n");
+			ret = PTR_ERR(mchan->resp_buf);
+			return ret;
+		}
+	}
+
+	/* Get the IPI local and remote agents IDs */
+	ret = of_property_read_u32_index(np, "xlnx,ipi-ids", 0,
+					 &pdata->local_id);
+	if (ret < 0) {
+		dev_err(dev, "No IPI local ID is specified.\n");
+		return ret;
+	}
+	ret = of_property_read_u32_index(np, "xlnx,ipi-ids", 1,
+					 &pdata->remote_id);
+	if (ret < 0) {
+		dev_err(dev, "No IPI remote ID is specified.\n");
+		return ret;
+	}
+
+	/* Get how to access IPI agent method */
+	prop = of_get_property(np, "method", NULL);
+	if (!prop) {
+		pdata->method = USE_SMC;
+	} else if (!strcmp(prop, "smc")) {
+		pdata->method = USE_SMC;
+	} else if (!strcmp(prop, "hvc")) {
+		pdata->method = USE_HVC;
+	} else {
+		dev_err(dev, "Invalid \"method\" %s.\n", prop);
+		return ret;
+	}
+
+	/* IPI IRQ */
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0) {
+		dev_err(dev, "unable to find IPI IRQ.\n");
+		return ret;
+	}
+	pdata->irq = ret;
+	ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt,
+			       IRQF_SHARED, dev_name(dev), pdata);
+	if (ret) {
+		dev_err(dev, "IRQ %d is not requested successfully.\n",
+			pdata->irq);
+		return ret;
+	}
+
+	mbox = &pdata->mbox;
+	mbox->dev = dev;
+	mbox->ops = &zynqmp_ipi_chan_ops;
+	mbox->num_chans = 2;
+	mbox->txdone_irq = false;
+	mbox->txdone_poll = true;
+	mbox->txpoll_period = 5;
+	mbox->of_xlate = zynqmp_ipi_of_xlate;
+	chans = devm_kzalloc(dev, 2 * sizeof(*chans), GFP_KERNEL);
+	if (!chans)
+		return -ENOMEM;
+	mbox->chans = chans;
+	mbox->chans[IPI_MB_CHNL_TX].con_priv = &pdata->mchans[IPI_MB_CHNL_TX];
+	mbox->chans[IPI_MB_CHNL_RX].con_priv = &pdata->mchans[IPI_MB_CHNL_RX];
+	pdata->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;
+	pdata->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;
+	spin_lock_init(&pdata->lock);
+	platform_set_drvdata(pdev, pdata);
+	ret = mbox_controller_register(mbox);
+	if (ret)
+		dev_err(dev, "Failed to register mbox_controller(%d)\n", ret);
+	else
+		dev_info(dev, "Probed ZynqMP IPI Mailbox driver.\n");
+	return ret;
+}
+
+static int zynqmp_ipi_remove(struct platform_device *pdev)
+{
+	struct zynqmp_ipi_mbox_pdata *pdata;
+
+	pdata = platform_get_drvdata(pdev);
+	mbox_controller_unregister(&pdata->mbox);
+
+	return 0;
+}
+
+static struct platform_driver zynqmp_ipi_driver = {
+	.probe = zynqmp_ipi_probe,
+	.remove = zynqmp_ipi_remove,
+	.driver = {
+		   .name = "zynqmp-ipi",
+		   .of_match_table = of_match_ptr(zynqmp_ipi_of_match),
+	},
+};
+
+static struct class zynqmp_ipi_class = { .name = "zynqmp_ipi_mbox", };
+
+static int __init zynqmp_ipi_init(void)
+{
+	int err;
+
+	err = class_register(&zynqmp_ipi_class);
+	if (err)
+		return err;
+
+	return platform_driver_register(&zynqmp_ipi_driver);
+}
+subsys_initcall(zynqmp_ipi_init);
+
+static void __exit zynqmp_ipi_exit(void)
+{
+	platform_driver_unregister(&zynqmp_ipi_driver);
+	class_unregister(&zynqmp_ipi_class);
+}
+module_exit(zynqmp_ipi_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Xilinx ZynqMP IPI Mailbox driver");
+MODULE_AUTHOR("Xilinx Inc.");
diff --git a/include/linux/mailbox/zynqmp-ipi-message.h b/include/linux/mailbox/zynqmp-ipi-message.h
new file mode 100644
index 0000000..173c41d
--- /dev/null
+++ b/include/linux/mailbox/zynqmp-ipi-message.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  Copyright (C) 2017 Xilinx Inc.
+ *
+ */
+
+#ifndef _LINUX_ZYNQMP_IPI_MESSAGE_H_
+#define _LINUX_ZYNQMP_IPI_MESSAGE_H_
+
+/**
+ * struct zynqmp_ipi_message - ZynqMP IPI message structure
+ * @len:  Length of the request message
+ * @data: Request message pointer
+ *
+ * This is the structure for data used in mbox_send_message
+ * the maximum length of data buffer is fixed to 12 bytes.
+ * Client is supposed to be aware of this.
+ */
+struct zynqmp_ipi_message {
+	size_t len;
+	u8 *data;
+};
+
+#endif /* _LINUX_ZYNQMP_IPI_MESSAGE_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v3 2/2] dt-bindings: mailbox: Add Xilinx IPI Mailbox
From: Wendy Liang @ 2018-01-04 23:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515109891-17133-1-git-send-email-jliang@xilinx.com>

Xilinx ZynqMP IPI(Inter Processor Interrupt) is a hardware block
in ZynqMP SoC used for the communication between various processor
systems.

Signed-off-by: Wendy Liang <jliang@xilinx.com>
---
 .../bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt   | 104 +++++++++++++++++++++
 1 file changed, 104 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt

diff --git a/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
new file mode 100644
index 0000000..5e270a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt
@@ -0,0 +1,104 @@
+Xilinx IPI Mailbox Controller
+========================================
+
+The Xilinx IPI(Inter Processor Interrupt) mailbox controller is to manage
+messaging between two Xilinx Zynq UltraScale+ MPSoC IPI agents. Each IPI
+agent owns registers used for notification and buffers for message.
+
+               +-------------------------------------+
+               | Xilinx ZynqMP IPI Controller        |
+               +-------------------------------------+
+    +--------------------------------------------------+
+ATF                    |                     |
+                       |                     |
+                       |                     |
+    +--------------------------+             |
+                       |                     |
+                       |                     |
+    +--------------------------------------------------+
+            +------------------------------------------+
+            |  +----------------+   +----------------+ |
+Hardware    |  |  IPI Agent     |   |  IPI Buffers   | |
+            |  |  Registers     |   |                | |
+            |  |                |   |                | |
+            |  +----------------+   +----------------+ |
+            |                                          |
+            | Xilinx IPI Agent Block                   |
+            +------------------------------------------+
+
+
+Controller Device Node:
+===========================
+Required properties:
+--------------------
+- compatible:		Shall be: "xlnx,zynqmp-ipi-mailbox"
+- reg:			IPI buffers address ranges
+- reg-names:		Names of the reg resources. It should have:
+			* local_request_region
+			  - IPI request msg buffer written by local and read
+			    by remote
+			* local_response_region
+			  - IPI response msg buffer written by local and read
+			    by remote
+			* remote_request_region
+			  - IPI request msg buffer written by remote and read
+			    by local
+			* remote_response_region
+			  - IPI response msg buffer written by remote and read
+			    by local
+- #mbox-cells:		Shall be 1. It contains:
+			* tx(0) or rx(1) channel
+- xlnx,ipi-ids:		Xilinx IPI agent IDs of the two peers of the
+			Xilinx IPI communication channel.
+- interrupt-parent:	Phandle for the interrupt controller
+- interrupts:		Interrupt information corresponding to the
+			interrupt-names property.
+
+Optional properties:
+--------------------
+- method:              The method of accessing the IPI agent registers.
+                       Permitted values are: "smc" and "hvc". Default is
+                       "smc".
+
+Example:
+===========================
+	/* APU<->RPU0 IPI mailbox controller */
+	ipi_mailbox_rpu0: mailbox at ff90400 {
+		compatible = "xlnx,zynqmp-ipi-mailbox";
+		reg = <0x0 0xff990400 0x0 0x20>,
+		      <0x0 0xff990420 0x0 0x20>,
+		      <0x0 0xff990080 0x0 0x20>,
+		      <0x0 0xff9900a0 0x0 0x20>;
+		reg-names = "local_request_region", "local_response_region",
+			    "remote_request_region", "remote_response_region";
+		#mbox-cells = <1>;
+		xlnx-ipi-ids = <0 1>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 29 4>;
+	};
+	/* APU<->RPU1 IPI mailbox controller */
+	ipi_mailbox_rpu1: mailbox at ff990440 {
+		compatible = "xlnx,zynqmp-ipi-mailbox";
+		reg = <0x0 0xff990440 0x0 0x20>,
+		      <0x0 0xff990460 0x0 0x20>,
+		      <0x0 0xff990280 0x0 0x20>,
+		      <0x0 0xff9902a0 0x0 0x20>;
+		reg-names = "local_request_region", "local_response_region",
+			    "remote_request_region", "remote_response_region";
+		#mbox-cells = <1>;
+		xlnx-ipi-ids = <0 2>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 29 4>;
+	};
+	rpu0 {
+		...
+		mboxes = <&ipi_mailbox_rpu0 0>,
+			 <&ipi_mailbox_rpu0 1>;
+		mbox-names = "tx", "rx";
+	};
+	rpu1 {
+		...
+		mboxes = <&ipi_mailbox_rpu1 0>,
+			 <&ipi_mailbox_rpu1 1>;
+		mbox-names = "tx", "rx";
+	};
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/7] clk: add helper functions for managing clk_onecell_data
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel

I am writing some clock drivers that use struct clk_onecell_data a few
times, so I decided to write a helper function to allocate the memory
since it is a two step process and can be tedious. Then I noticed that
mediatek already had such a helper function, so I have moved that to the
clk core and made use of it in other drivers where possible.

David Lechner (7):
  clk: add helper function for allocating clk_onecell_data
  clk: mediatek: make use of clk_alloc_onecell_data()
  clk: qoriq: make use of clk_alloc_onecell_data()
  clk: hisilicon: make use of clk_alloc_onecell_data()
  clk: rockchip: make use of clk_alloc_onecell_data()
  clk: st: make use of clk_alloc_onecell_data()
  clk: sunxi: make use of clk_alloc_onecell_data()

 drivers/clk/clk-qoriq.c                  | 13 +++------
 drivers/clk/clk.c                        | 49 ++++++++++++++++++++++++++++++++
 drivers/clk/hisilicon/clk-hi3620.c       |  7 +----
 drivers/clk/mediatek/clk-mt2701-bdp.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-eth.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-hif.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt2701-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt2701.c        | 10 +++----
 drivers/clk/mediatek/clk-mt2712-bdp.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-jpgdec.c |  2 +-
 drivers/clk/mediatek/clk-mt2712-mfg.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt2712-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt2712-venc.c   |  2 +-
 drivers/clk/mediatek/clk-mt2712.c        | 12 ++++----
 drivers/clk/mediatek/clk-mt6797-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt6797-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt6797-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt6797-venc.c   |  2 +-
 drivers/clk/mediatek/clk-mt6797.c        |  8 +++---
 drivers/clk/mediatek/clk-mt7622-aud.c    |  2 +-
 drivers/clk/mediatek/clk-mt7622-eth.c    |  4 +--
 drivers/clk/mediatek/clk-mt7622-hif.c    |  4 +--
 drivers/clk/mediatek/clk-mt7622.c        |  8 +++---
 drivers/clk/mediatek/clk-mt8135.c        |  8 +++---
 drivers/clk/mediatek/clk-mt8173.c        | 18 ++++++------
 drivers/clk/mediatek/clk-mtk.c           | 25 ----------------
 drivers/clk/mediatek/clk-mtk.h           |  2 --
 drivers/clk/rockchip/clk-rockchip.c      | 11 +------
 drivers/clk/st/clk-flexgen.c             | 17 ++++-------
 drivers/clk/st/clkgen-fsyn.c             | 11 +------
 drivers/clk/st/clkgen-pll.c              | 12 ++------
 drivers/clk/sunxi/clk-a10-pll2.c         | 14 +++------
 drivers/clk/sunxi/clk-mod0.c             | 13 ++-------
 drivers/clk/sunxi/clk-simple-gates.c     | 13 ++-------
 drivers/clk/sunxi/clk-sun8i-bus-gates.c  | 13 ++-------
 drivers/clk/sunxi/clk-sunxi.c            | 14 +++------
 drivers/clk/sunxi/clk-usb.c              |  8 +-----
 include/linux/clk-provider.h             |  3 ++
 42 files changed, 138 insertions(+), 195 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/7] clk: add helper functions for managing clk_onecell_data
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

This adds helper functions for allocating and freeing struct
clk_onecell_data.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/clk.c            | 49 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h |  3 +++
 2 files changed, 52 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index e24968f..83c8df7 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3551,6 +3551,55 @@ struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data)
 }
 EXPORT_SYMBOL_GPL(of_clk_hw_simple_get);
 
+/**
+ * clk_alloc_onecell_data - allocate new struct clk_onecell_data
+ * @num_clks: Number of clock pointers to allocate
+ *
+ * An array of clock pointers is allocated and each clock pointer is
+ * initialized to ERR_PTR(-ENOENT).
+ *
+ * Returns: Pointer to struct clk_onecell_data or NULL on failure.
+ */
+struct clk_onecell_data *clk_alloc_onecell_data(size_t num_clks)
+{
+	struct clk_onecell_data *clk_data;
+	int i;
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (!clk_data)
+		return NULL;
+
+	clk_data->clks = kcalloc(num_clks, sizeof(*clk_data->clks), GFP_KERNEL);
+	if (!clk_data->clks) {
+		kfree(clk_data);
+		return NULL;
+	}
+
+	for (i = 0; i < num_clks; i++)
+		clk_data->clks[i] = ERR_PTR(-ENOENT);
+
+	clk_data->clk_num = num_clks;
+
+	return clk_data;
+}
+EXPORT_SYMBOL_GPL(clk_alloc_onecell_data);
+
+/**
+ * clk_free_onecell_data - frees @clk_data and associated resources
+ * @clk_data: Pointer to struct clk_onecelldata that was allocated with
+ *            clk_alloc_onecell_data()
+ *
+ * It is safe to call this function even if @clk_data is NULL or an error value.
+ */
+void clk_free_onecell_data(struct clk_onecell_data *clk_data)
+{
+	if (IS_ERR_OR_NULL(clk_data))
+		return;
+
+	kfree(clk_data->clks);
+	kfree(clk_data);
+}
+
 struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
 {
 	struct clk_onecell_data *clk_data = data;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 175a62a..b1f51f7 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -786,6 +786,9 @@ struct clk_onecell_data {
 	unsigned int clk_num;
 };
 
+struct clk_onecell_data *clk_alloc_onecell_data(size_t num_clks);
+void clk_free_onecell_data(struct clk_onecell_data *clk_data);
+
 struct clk_hw_onecell_data {
 	unsigned int num;
 	struct clk_hw *hws[];
-- 
2.7.4

^ permalink raw reply related

* [PATCH 2/7] clk: mediatek: make use of clk_alloc_onecell_data()
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

A new function clk_alloc_onecell_data() has been added to the clk core
that performs the same function as mtk_alloc_clk_data(), so we can replace
all instances with the new function.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/mediatek/clk-mt2701-bdp.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-eth.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-hif.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt2701-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt2701-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt2701.c        | 10 +++++-----
 drivers/clk/mediatek/clk-mt2712-bdp.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-jpgdec.c |  2 +-
 drivers/clk/mediatek/clk-mt2712-mfg.c    |  2 +-
 drivers/clk/mediatek/clk-mt2712-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt2712-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt2712-venc.c   |  2 +-
 drivers/clk/mediatek/clk-mt2712.c        | 12 ++++++------
 drivers/clk/mediatek/clk-mt6797-img.c    |  2 +-
 drivers/clk/mediatek/clk-mt6797-mm.c     |  2 +-
 drivers/clk/mediatek/clk-mt6797-vdec.c   |  2 +-
 drivers/clk/mediatek/clk-mt6797-venc.c   |  2 +-
 drivers/clk/mediatek/clk-mt6797.c        |  8 ++++----
 drivers/clk/mediatek/clk-mt7622-aud.c    |  2 +-
 drivers/clk/mediatek/clk-mt7622-eth.c    |  4 ++--
 drivers/clk/mediatek/clk-mt7622-hif.c    |  4 ++--
 drivers/clk/mediatek/clk-mt7622.c        |  8 ++++----
 drivers/clk/mediatek/clk-mt8135.c        |  8 ++++----
 drivers/clk/mediatek/clk-mt8173.c        | 18 +++++++++---------
 drivers/clk/mediatek/clk-mtk.c           | 25 -------------------------
 drivers/clk/mediatek/clk-mtk.h           |  2 --
 28 files changed, 54 insertions(+), 81 deletions(-)

diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c
index fe4964d..b055a92 100644
--- a/drivers/clk/mediatek/clk-mt2701-bdp.c
+++ b/drivers/clk/mediatek/clk-mt2701-bdp.c
@@ -113,7 +113,7 @@ static int clk_mt2701_bdp_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_BDP_NR);
+	clk_data = clk_alloc_onecell_data(CLK_BDP_NR);
 
 	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c
index 9251a65..4b7570e 100644
--- a/drivers/clk/mediatek/clk-mt2701-eth.c
+++ b/drivers/clk/mediatek/clk-mt2701-eth.c
@@ -55,7 +55,7 @@ static int clk_mt2701_eth_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR);
+	clk_data = clk_alloc_onecell_data(CLK_ETHSYS_NR);
 
 	mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c
index 18f3723..0f0c785 100644
--- a/drivers/clk/mediatek/clk-mt2701-hif.c
+++ b/drivers/clk/mediatek/clk-mt2701-hif.c
@@ -52,7 +52,7 @@ static int clk_mt2701_hif_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR);
+	clk_data = clk_alloc_onecell_data(CLK_HIFSYS_NR);
 
 	mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c
index b7441c9..d66c3e4 100644
--- a/drivers/clk/mediatek/clk-mt2701-img.c
+++ b/drivers/clk/mediatek/clk-mt2701-img.c
@@ -55,7 +55,7 @@ static int clk_mt2701_img_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+	clk_data = clk_alloc_onecell_data(CLK_IMG_NR);
 
 	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c
index fe1f850..02e4736 100644
--- a/drivers/clk/mediatek/clk-mt2701-mm.c
+++ b/drivers/clk/mediatek/clk-mt2701-mm.c
@@ -98,7 +98,7 @@ static int clk_mt2701_mm_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+	clk_data = clk_alloc_onecell_data(CLK_MM_NR);
 
 	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c
index d3c0fc9..f29414e 100644
--- a/drivers/clk/mediatek/clk-mt2701-vdec.c
+++ b/drivers/clk/mediatek/clk-mt2701-vdec.c
@@ -66,7 +66,7 @@ static int clk_mt2701_vdec_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+	clk_data = clk_alloc_onecell_data(CLK_VDEC_NR);
 
 	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c
index 8e7f16f..df861a5 100644
--- a/drivers/clk/mediatek/clk-mt2701.c
+++ b/drivers/clk/mediatek/clk-mt2701.c
@@ -688,7 +688,7 @@ static int mtk_topckgen_init(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+	clk_data = clk_alloc_onecell_data(CLK_TOP_NR);
 
 	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 								clk_data);
@@ -755,7 +755,7 @@ static void __init mtk_infrasys_init_early(struct device_node *node)
 	int r, i;
 
 	if (!infra_clk_data) {
-		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		infra_clk_data = clk_alloc_onecell_data(CLK_INFRA_NR);
 
 		for (i = 0; i < CLK_INFRA_NR; i++)
 			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
@@ -781,7 +781,7 @@ static int mtk_infrasys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 
 	if (!infra_clk_data) {
-		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		infra_clk_data = clk_alloc_onecell_data(CLK_INFRA_NR);
 	} else {
 		for (i = 0; i < CLK_INFRA_NR; i++) {
 			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
@@ -909,7 +909,7 @@ static int mtk_pericfg_init(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk_data = mtk_alloc_clk_data(CLK_PERI_NR);
+	clk_data = clk_alloc_onecell_data(CLK_PERI_NR);
 
 	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
 						clk_data);
@@ -981,7 +981,7 @@ static int mtk_apmixedsys_init(struct platform_device *pdev)
 	struct clk_onecell_data *clk_data;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+	clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR);
 	if (!clk_data)
 		return -ENOMEM;
 
diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c
index 5fe4728..b8b46e5 100644
--- a/drivers/clk/mediatek/clk-mt2712-bdp.c
+++ b/drivers/clk/mediatek/clk-mt2712-bdp.c
@@ -72,7 +72,7 @@ static int clk_mt2712_bdp_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_BDP_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_BDP_NR_CLK);
 
 	mtk_clk_register_gates(node, bdp_clks, ARRAY_SIZE(bdp_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c
index 139ff55..e9fbf20 100644
--- a/drivers/clk/mediatek/clk-mt2712-img.c
+++ b/drivers/clk/mediatek/clk-mt2712-img.c
@@ -50,7 +50,7 @@ static int clk_mt2712_img_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_IMG_NR_CLK);
 
 	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
index c7d4aad..86e7de4 100644
--- a/drivers/clk/mediatek/clk-mt2712-jpgdec.c
+++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c
@@ -46,7 +46,7 @@ static int clk_mt2712_jpgdec_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_JPGDEC_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_JPGDEC_NR_CLK);
 
 	mtk_clk_register_gates(node, jpgdec_clks, ARRAY_SIZE(jpgdec_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c
index 570f72d..2d63776 100644
--- a/drivers/clk/mediatek/clk-mt2712-mfg.c
+++ b/drivers/clk/mediatek/clk-mt2712-mfg.c
@@ -45,7 +45,7 @@ static int clk_mt2712_mfg_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_MFG_NR_CLK);
 
 	mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c
index a8b4b6d..6685425 100644
--- a/drivers/clk/mediatek/clk-mt2712-mm.c
+++ b/drivers/clk/mediatek/clk-mt2712-mm.c
@@ -140,7 +140,7 @@ static int clk_mt2712_mm_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_MM_NR_CLK);
 
 	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c
index 55c64ee..c2de3ea 100644
--- a/drivers/clk/mediatek/clk-mt2712-vdec.c
+++ b/drivers/clk/mediatek/clk-mt2712-vdec.c
@@ -64,7 +64,7 @@ static int clk_mt2712_vdec_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_VDEC_NR_CLK);
 
 	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c
index ccbfe98..4b1a146 100644
--- a/drivers/clk/mediatek/clk-mt2712-venc.c
+++ b/drivers/clk/mediatek/clk-mt2712-venc.c
@@ -47,7 +47,7 @@ static int clk_mt2712_venc_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_VENC_NR_CLK);
 
 	mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
 			clk_data);
diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c
index 498d137..b3e19d3 100644
--- a/drivers/clk/mediatek/clk-mt2712.c
+++ b/drivers/clk/mediatek/clk-mt2712.c
@@ -1226,7 +1226,7 @@ static int clk_mt2712_apmixed_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR_CLK);
 
 	mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
 
@@ -1246,7 +1246,7 @@ static void clk_mt2712_top_init_early(struct device_node *node)
 	int r, i;
 
 	if (!top_clk_data) {
-		top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+		top_clk_data = clk_alloc_onecell_data(CLK_TOP_NR_CLK);
 
 		for (i = 0; i < CLK_TOP_NR_CLK; i++)
 			top_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
@@ -1278,7 +1278,7 @@ static int clk_mt2712_top_probe(struct platform_device *pdev)
 	}
 
 	if (!top_clk_data) {
-		top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+		top_clk_data = clk_alloc_onecell_data(CLK_TOP_NR_CLK);
 	} else {
 		for (i = 0; i < CLK_TOP_NR_CLK; i++) {
 			if (top_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
@@ -1313,7 +1313,7 @@ static int clk_mt2712_infra_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_INFRA_NR_CLK);
 
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 			clk_data);
@@ -1335,7 +1335,7 @@ static int clk_mt2712_peri_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_PERI_NR_CLK);
 
 	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
 			clk_data);
@@ -1365,7 +1365,7 @@ static int clk_mt2712_mcu_probe(struct platform_device *pdev)
 		return PTR_ERR(base);
 	}
 
-	clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_MCU_NR_CLK);
 
 	mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base,
 			&mt2712_clk_lock, clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c
index 94cc480..6debc6d 100644
--- a/drivers/clk/mediatek/clk-mt6797-img.c
+++ b/drivers/clk/mediatek/clk-mt6797-img.c
@@ -51,7 +51,7 @@ static int clk_mt6797_img_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+	clk_data = clk_alloc_onecell_data(CLK_IMG_NR);
 
 	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
index c57d3ee..c32c274 100644
--- a/drivers/clk/mediatek/clk-mt6797-mm.c
+++ b/drivers/clk/mediatek/clk-mt6797-mm.c
@@ -111,7 +111,7 @@ static int clk_mt6797_mm_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+	clk_data = clk_alloc_onecell_data(CLK_MM_NR);
 
 	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c
index 7c402ca..66c0fe3 100644
--- a/drivers/clk/mediatek/clk-mt6797-vdec.c
+++ b/drivers/clk/mediatek/clk-mt6797-vdec.c
@@ -68,7 +68,7 @@ static int clk_mt6797_vdec_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+	clk_data = clk_alloc_onecell_data(CLK_VDEC_NR);
 
 	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c
index e73d517..1669b43 100644
--- a/drivers/clk/mediatek/clk-mt6797-venc.c
+++ b/drivers/clk/mediatek/clk-mt6797-venc.c
@@ -53,7 +53,7 @@ static int clk_mt6797_venc_probe(struct platform_device *pdev)
 	int r;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_VENC_NR);
+	clk_data = clk_alloc_onecell_data(CLK_VENC_NR);
 
 	mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
index 5702bc9..8441633 100644
--- a/drivers/clk/mediatek/clk-mt6797.c
+++ b/drivers/clk/mediatek/clk-mt6797.c
@@ -395,7 +395,7 @@ static int mtk_topckgen_init(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+	clk_data = clk_alloc_onecell_data(CLK_TOP_NR);
 
 	mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
 				 clk_data);
@@ -553,7 +553,7 @@ static void mtk_infrasys_init_early(struct device_node *node)
 	int r, i;
 
 	if (!infra_clk_data) {
-		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		infra_clk_data = clk_alloc_onecell_data(CLK_INFRA_NR);
 
 		for (i = 0; i < CLK_INFRA_NR; i++)
 			infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
@@ -577,7 +577,7 @@ static int mtk_infrasys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 
 	if (!infra_clk_data) {
-		infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+		infra_clk_data = clk_alloc_onecell_data(CLK_INFRA_NR);
 	} else {
 		for (i = 0; i < CLK_INFRA_NR; i++) {
 			if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
@@ -656,7 +656,7 @@ static int mtk_apmixedsys_init(struct platform_device *pdev)
 	struct clk_onecell_data *clk_data;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+	clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR);
 	if (!clk_data)
 		return -ENOMEM;
 
diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c
index fad7d9f..9b1170f 100644
--- a/drivers/clk/mediatek/clk-mt7622-aud.c
+++ b/drivers/clk/mediatek/clk-mt7622-aud.c
@@ -143,7 +143,7 @@ static int clk_mt7622_audiosys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_AUDIO_NR_CLK);
 
 	mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c
index 6328127..881845c 100644
--- a/drivers/clk/mediatek/clk-mt7622-eth.c
+++ b/drivers/clk/mediatek/clk-mt7622-eth.c
@@ -79,7 +79,7 @@ static int clk_mt7622_ethsys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_ETH_NR_CLK);
 
 	mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks),
 			       clk_data);
@@ -101,7 +101,7 @@ static int clk_mt7622_sgmiisys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_SGMII_NR_CLK);
 
 	mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c
index a6e8534..5b0738b 100644
--- a/drivers/clk/mediatek/clk-mt7622-hif.c
+++ b/drivers/clk/mediatek/clk-mt7622-hif.c
@@ -90,7 +90,7 @@ static int clk_mt7622_ssusbsys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_SSUSB_NR_CLK);
 
 	mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks),
 			       clk_data);
@@ -112,7 +112,7 @@ static int clk_mt7622_pciesys_init(struct platform_device *pdev)
 	struct device_node *node = pdev->dev.of_node;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_PCIE_NR_CLK);
 
 	mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c
index 92f7e32..ba6290f 100644
--- a/drivers/clk/mediatek/clk-mt7622.c
+++ b/drivers/clk/mediatek/clk-mt7622.c
@@ -628,7 +628,7 @@ static int mtk_topckgen_init(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_TOP_NR_CLK);
 
 	mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks),
 				    clk_data);
@@ -658,7 +658,7 @@ static int __init mtk_infrasys_init(struct platform_device *pdev)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_INFRA_NR_CLK);
 
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 			       clk_data);
@@ -681,7 +681,7 @@ static int mtk_apmixedsys_init(struct platform_device *pdev)
 	struct clk_onecell_data *clk_data;
 	struct device_node *node = pdev->dev.of_node;
 
-	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR_CLK);
 	if (!clk_data)
 		return -ENOMEM;
 
@@ -709,7 +709,7 @@ static int mtk_pericfg_init(struct platform_device *pdev)
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
-	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_PERI_NR_CLK);
 
 	mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
 			       clk_data);
diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c
index 07c21e4..9ce6e1d 100644
--- a/drivers/clk/mediatek/clk-mt8135.c
+++ b/drivers/clk/mediatek/clk-mt8135.c
@@ -533,7 +533,7 @@ static void __init mtk_topckgen_init(struct device_node *node)
 		return;
 	}
 
-	clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_TOP_NR_CLK);
 
 	mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
 	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
@@ -554,7 +554,7 @@ static void __init mtk_infrasys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_INFRA_NR_CLK);
 
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 						clk_data);
@@ -582,7 +582,7 @@ static void __init mtk_pericfg_init(struct device_node *node)
 		return;
 	}
 
-	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_PERI_NR_CLK);
 
 	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
 						clk_data);
@@ -635,7 +635,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
 {
 	struct clk_onecell_data *clk_data;
 
-	clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR_CLK);
 	if (!clk_data)
 		return;
 
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index 96c292c..1d1d09c 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -941,7 +941,7 @@ static void __init mtk_topckgen_init(struct device_node *node)
 		return;
 	}
 
-	mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
+	mt8173_top_clk_data = clk_data = clk_alloc_onecell_data(CLK_TOP_NR_CLK);
 
 	mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
 	mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
@@ -962,7 +962,7 @@ static void __init mtk_infrasys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_INFRA_NR_CLK);
 
 	mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
 						clk_data);
@@ -992,7 +992,7 @@ static void __init mtk_pericfg_init(struct device_node *node)
 		return;
 	}
 
-	clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_PERI_NR_CLK);
 
 	mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates),
 						clk_data);
@@ -1096,7 +1096,7 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
 		return;
 	}
 
-	mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
+	mt8173_pll_clk_data = clk_data = clk_alloc_onecell_data(CLK_APMIXED_NR_CLK);
 	if (!clk_data) {
 		iounmap(base);
 		return;
@@ -1139,7 +1139,7 @@ static void __init mtk_imgsys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_IMG_NR_CLK);
 
 	mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
 						clk_data);
@@ -1157,7 +1157,7 @@ static void __init mtk_mmsys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_MM_NR_CLK);
 
 	mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
 						clk_data);
@@ -1174,7 +1174,7 @@ static void __init mtk_vdecsys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_VDEC_NR_CLK);
 
 	mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
 						clk_data);
@@ -1191,7 +1191,7 @@ static void __init mtk_vencsys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_VENC_NR_CLK);
 
 	mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
 						clk_data);
@@ -1208,7 +1208,7 @@ static void __init mtk_vencltsys_init(struct device_node *node)
 	struct clk_onecell_data *clk_data;
 	int r;
 
-	clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK);
+	clk_data = clk_alloc_onecell_data(CLK_VENCLT_NR_CLK);
 
 	mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks),
 						clk_data);
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index 9c0ae42..64cf1ef 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -24,31 +24,6 @@
 #include "clk-mtk.h"
 #include "clk-gate.h"
 
-struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
-{
-	int i;
-	struct clk_onecell_data *clk_data;
-
-	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-	if (!clk_data)
-		return NULL;
-
-	clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
-	if (!clk_data->clks)
-		goto err_out;
-
-	clk_data->clk_num = clk_num;
-
-	for (i = 0; i < clk_num; i++)
-		clk_data->clks[i] = ERR_PTR(-ENOENT);
-
-	return clk_data;
-err_out:
-	kfree(clk_data);
-
-	return NULL;
-}
-
 void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
 		int num, struct clk_onecell_data *clk_data)
 {
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index bf8006d..651a9e9 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -190,8 +190,6 @@ void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
 			int num, void __iomem *base, spinlock_t *lock,
 				struct clk_onecell_data *clk_data);
 
-struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num);
-
 #define HAVE_RST_BAR	BIT(0)
 #define PLL_AO		BIT(1)
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/7] clk: qoriq: make use of clk_alloc_onecell_data()
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

Use helper function clk_alloc_onecell_data() to allocate struct
clk_onecell_data.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/clk-qoriq.c | 13 ++++---------
 1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c
index 3a1812f..5278cc7 100644
--- a/drivers/clk/clk-qoriq.c
+++ b/drivers/clk/clk-qoriq.c
@@ -1175,13 +1175,11 @@ static void __init legacy_pll_init(struct device_node *np, int idx)
 	count = of_property_count_strings(np, "clock-output-names");
 
 	BUILD_BUG_ON(ARRAY_SIZE(pll->div) < 4);
-	subclks = kcalloc(4, sizeof(struct clk *), GFP_KERNEL);
-	if (!subclks)
+	onecell_data = clk_alloc_onecell_data(4);
+	if (!onecell_data)
 		return;
 
-	onecell_data = kmalloc(sizeof(*onecell_data), GFP_KERNEL);
-	if (!onecell_data)
-		goto err_clks;
+	subclks = onecell_data->clks;
 
 	if (count <= 3) {
 		subclks[0] = pll->div[0].clk;
@@ -1194,7 +1192,6 @@ static void __init legacy_pll_init(struct device_node *np, int idx)
 		subclks[3] = pll->div[3].clk;
 	}
 
-	onecell_data->clks = subclks;
 	onecell_data->clk_num = count;
 
 	rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
@@ -1206,9 +1203,7 @@ static void __init legacy_pll_init(struct device_node *np, int idx)
 
 	return;
 err_cell:
-	kfree(onecell_data);
-err_clks:
-	kfree(subclks);
+	clk_free_onecell_data(onecell_data);
 }
 
 /* Legacy node */
-- 
2.7.4

^ permalink raw reply related

* [PATCH 4/7] clk: hisilicon: make use of clk_alloc_onecell_data()
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

Use helper function clk_alloc_onecell_data() to allocate struct
clk_onecell_data.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/hisilicon/clk-hi3620.c | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index 77072c7..15f8d50 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -476,21 +476,16 @@ static void __init hi3620_mmc_clk_init(struct device_node *node)
 		return;
 	}
 
-	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	clk_data = clk_alloc_onecell_data(num);
 	if (WARN_ON(!clk_data))
 		return;
 
-	clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
-	if (!clk_data->clks)
-		return;
-
 	for (i = 0; i < num; i++) {
 		struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
 		clk_data->clks[mmc_clk->id] =
 			hisi_register_clk_mmc(mmc_clk, base, node);
 	}
 
-	clk_data->clk_num = num;
 	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 }
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH 5/7] clk: rockchip: make use of clk_alloc_onecell_data()
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

Use helper function clk_alloc_onecell_data() to allocate struct
clk_onecell_data.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/rockchip/clk-rockchip.c | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/clk/rockchip/clk-rockchip.c b/drivers/clk/rockchip/clk-rockchip.c
index 2c9bb81..499af3a 100644
--- a/drivers/clk/rockchip/clk-rockchip.c
+++ b/drivers/clk/rockchip/clk-rockchip.c
@@ -52,19 +52,12 @@ static void __init rk2928_gate_clk_init(struct device_node *node)
 	if (!reg)
 		return;
 
-	clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
+	clk_data = clk_alloc_onecell_data(qty);
 	if (!clk_data) {
 		iounmap(reg);
 		return;
 	}
 
-	clk_data->clks = kzalloc(qty * sizeof(struct clk *), GFP_KERNEL);
-	if (!clk_data->clks) {
-		kfree(clk_data);
-		iounmap(reg);
-		return;
-	}
-
 	flags = CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE;
 
 	for (i = 0; i < qty; i++) {
@@ -91,8 +84,6 @@ static void __init rk2928_gate_clk_init(struct device_node *node)
 		WARN_ON(IS_ERR(clk_data->clks[i]));
 	}
 
-	clk_data->clk_num = qty;
-
 	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
 }
 CLK_OF_DECLARE(rk2928_gate, "rockchip,rk2928-gate-clk", rk2928_gate_clk_init);
-- 
2.7.4

^ permalink raw reply related

* [PATCH 6/7] clk: st: make use of clk_alloc_onecell_data()
From: David Lechner @ 2018-01-05  0:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515112695-3160-1-git-send-email-david@lechnology.com>

Use helper function clk_alloc_onecell_data() to allocate struct
clk_onecell_data.

Signed-off-by: David Lechner <david@lechnology.com>
---
 drivers/clk/st/clk-flexgen.c | 17 +++++------------
 drivers/clk/st/clkgen-fsyn.c | 11 +----------
 drivers/clk/st/clkgen-pll.c  | 12 ++----------
 3 files changed, 8 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/st/clk-flexgen.c b/drivers/clk/st/clk-flexgen.c
index 918ba31..29ff00d 100644
--- a/drivers/clk/st/clk-flexgen.c
+++ b/drivers/clk/st/clk-flexgen.c
@@ -310,7 +310,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 {
 	struct device_node *pnode;
 	void __iomem *reg;
-	struct clk_onecell_data *clk_data;
+	struct clk_onecell_data *clk_data = NULL;
 	const char **parents;
 	int num_parents, i;
 	spinlock_t *rlock = NULL;
@@ -341,21 +341,15 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 		clk_mode = data->mode;
 	}
 
-	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-	if (!clk_data)
-		goto err;
-
 	ret = of_property_count_strings(np, "clock-output-names");
 	if (ret <= 0) {
 		pr_err("%s: Failed to get number of output clocks (%d)",
-				__func__, clk_data->clk_num);
+				__func__, ret);
 		goto err;
 	}
-	clk_data->clk_num = ret;
 
-	clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
-			GFP_KERNEL);
-	if (!clk_data->clks)
+	clk_data = clk_alloc_onecell_data(ret);
+	if (!clk_data)
 		goto err;
 
 	rlock = kzalloc(sizeof(spinlock_t), GFP_KERNEL);
@@ -397,8 +391,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
 
 err:
 	iounmap(reg);
-	if (clk_data)
-		kfree(clk_data->clks);
+	clk_free_onecell_data(clk_data);
 	kfree(clk_data);
 	kfree(parents);
 	kfree(rlock);
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index 14819d9..48e6bff 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -869,19 +869,10 @@ static void __init st_of_create_quadfs_fsynths(
 	struct clk_onecell_data *clk_data;
 	int fschan;
 
-	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	clk_data = clk_alloc_onecell_data(QUADFS_MAX_CHAN);
 	if (!clk_data)
 		return;
 
-	clk_data->clk_num = QUADFS_MAX_CHAN;
-	clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *),
-				 GFP_KERNEL);
-
-	if (!clk_data->clks) {
-		kfree(clk_data);
-		return;
-	}
-
 	for (fschan = 0; fschan < QUADFS_MAX_CHAN; fschan++) {
 		struct clk *clk;
 		const char *clk_name;
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index 25bda48..07795ee 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -733,17 +733,10 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
 
 	num_odfs = data->num_odfs;
 
-	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	clk_data = clk_alloc_onecell_data(num_odfs);
 	if (!clk_data)
 		return;
 
-	clk_data->clk_num = num_odfs;
-	clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
-				 GFP_KERNEL);
-
-	if (!clk_data->clks)
-		goto err;
-
 	for (odf = 0; odf < num_odfs; odf++) {
 		struct clk *clk;
 		const char *clk_name;
@@ -768,8 +761,7 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
 
 err:
 	kfree(pll_name);
-	kfree(clk_data->clks);
-	kfree(clk_data);
+	clk_free_onecell_data(clk_data);
 }
 static void __init clkgen_c32_pll0_setup(struct device_node *np)
 {
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox