* [PATCH v12 4/5] arm64: Implement page table free interfaces
From: Will Deacon @ 2018-06-04 15:07 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <98ef3cd0-a9a1-d5b5-f1a6-c0ab8b15ec6a@codeaurora.org>
On Mon, Jun 04, 2018 at 07:13:18PM +0530, Chintan Pandya wrote:
> On 6/4/2018 5:43 PM, Will Deacon wrote:
> >On Fri, Jun 01, 2018 at 06:09:17PM +0530, Chintan Pandya wrote:
> >>+ next = addr;
> >>+ end = addr + PUD_SIZE;
> >>+ do {
> >>+ pmd_free_pte_page(entry, next);
> >>+ } while (entry++, next += PMD_SIZE, next != end);
> >>+
> >>+ pud_clear(pudp);
> >>+ __flush_tlb_kernel_pgtable(addr);
> >>+ pmd_free(NULL, table);
> >>+ }
> >>+ return 1;
> >
> >So with these patches, we only ever return 1 from these helpers. It looks
> >like the same is true for x86, so how about we make them void and move the
> >calls inside the conditionals in lib/ioremap.c? Obviously, this would be a
> >separate patch on the end.
>
> That sounds valid code churn to me. But since x86 discussion is not
> concluded yet, I would wait to share until that gets resolved. May be
> not in v13 but separate effort. Would that be okay to you ?
Yes, fine by me.
Will
^ permalink raw reply
* [PATCH 1/5] arm64: topology: refactor reset_cpu_topology to add support for removing topology
From: Jeffrey Hugo @ 2018-06-04 14:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528108797-13743-2-git-send-email-sudeep.holla@arm.com>
On 6/4/2018 4:39 AM, Sudeep Holla wrote:
> Currently reset_cpu_topology clears all the CPU topology information
> and resets to default values. However we may need to just clear the
> information when we hotplig out the CPU. In preparation to add the
hotplug
> support the same, let's refactor reset_cpu_topology to clear out the
> information and reset them only if explicitly requested.
>
--
Jeffrey Hugo
Qualcomm Datacenter Technologies as an affiliate of Qualcomm
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH v5 4/4] ARM: dts: imx: add missing compatible and clock properties for EPIT
From: kbuild test robot @ 2018-06-04 14:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604100035.19558-5-peron.clem@gmail.com>
Hi Colin,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on shawnguo/for-next]
[also build test ERROR on v4.17 next-20180601]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Cl-ment-P-ron/Reintroduce-i-MX-EPIT-Timer/20180604-211036
base: https://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git for-next
config: arm-realview_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All errors (new ones prefixed by >>):
>> Error: arch/arm/boot/dts/imx6sl.dtsi:661.19-20 syntax error
FATAL ERROR: Unable to parse input tree
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 18007 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180604/87639177/attachment-0001.gz>
^ permalink raw reply
* [PATCH v5 1/2] regulator: dt-bindings: add QCOM RPMh regulator bindings
From: Rob Herring @ 2018-06-04 14:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <af7152133afd7bbf9ad207905ec4e8d5cbe4e718.1527901471.git.collinsd@codeaurora.org>
On Fri, Jun 01, 2018 at 06:34:05PM -0700, David Collins wrote:
> Introduce bindings for RPMh regulator devices found on some
> Qualcomm Technlogies, Inc. SoCs. These devices allow a given
> processor within the SoC to make PMIC regulator requests which
> are aggregated within the RPMh hardware block along with requests
> from other processors in the SoC to determine the final PMIC
> regulator hardware state.
>
> Signed-off-by: David Collins <collinsd@codeaurora.org>
> ---
> .../bindings/regulator/qcom,rpmh-regulator.txt | 160 +++++++++++++++++++++
> .../dt-bindings/regulator/qcom,rpmh-regulator.h | 36 +++++
> 2 files changed, 196 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.txt
> create mode 100644 include/dt-bindings/regulator/qcom,rpmh-regulator.h
Reviewed-by: Rob Herring <robh@kernel.org>
^ permalink raw reply
* [PATCH 2/3] arm64: dts: renesas: condor: specify EtherAVB PHY IRQ
From: Sergei Shtylyov @ 2018-06-04 14:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604103302.f5kx5fqhbl3ohfpi@verge.net.au>
On 06/04/2018 01:33 PM, Simon Horman wrote:
>> Specify EtherAVB PHY IRQ in the Condor board's device tree, now that
>> we have the GPIO support (previously phylib had to resort to polling).
>>
>> Based on the original (and large) patch by Vladimir Barinov.
>>
>> Signed-off-by: Vladimir Barinov <vladimir.barinov@cogentembedded.com>
>> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>>
>> ---
>> arch/arm64/boot/dts/renesas/r8a77980-condor.dts | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> Index: renesas/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
>> ===================================================================
>> --- renesas.orig/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
>> +++ renesas/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
>> @@ -59,6 +59,8 @@
>> phy0: ethernet-phy at 0 {
>> rxc-skew-ps = <1500>;
>> reg = <0>;
>> + interrupt-parent = <&gpio1>;
>> + interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
>
> I don't see this documented. Perhaps I'm missing something obvious.
Have you looked into the V3H PFC section for where in the GPSRs AVB_PHY_INT
is mapped?
The Condor schematics doesn't explicitly list the GPIO for AVB_PHY_INT
because that signal is meant to be routed thru the MAC. Unfortunately, the
sh_eth/ravb drivers don't support the PHY interrupt (the phylib function,
phy_mac_interrupt() reporting the PHY interrupts routed thru MAC is clearly
inadequate as it wants the link state as an argument), so we have to resort
to the GPIO interrupts...
> Or you have some extra information or newer documentation?
No.
> Also, given Olof Johansson's recent comments in ("Re: [GIT PULL] Renesas
> ARM64 Based SoC DT Updates for v4.18") please consider squashing this patch
> and the following one.
Hm... note that the different Ether cores are involved in these 2 PHY IRQ
patches. If that's OK, I can merge the patches...
[...]
MBR< Sergei
^ permalink raw reply
* [PATCH 5/7] regulator: core: Lock dependent regulators
From: Lucas Stach @ 2018-06-04 14:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-6-git-send-email-m.purski@samsung.com>
Hi Maciej,
Am Montag, den 04.06.2018, 15:59 +0200 schrieb Maciej Purski:
> Implementing coupled regulators adds a new dependency between
> regulators. Therefore, the current locking model should be changed.
> Coupled regulators should be locked with regulator's supplies at the
> same time.
>
> Add new function regulator_lock_dependent(), which locks all regulators
> related with the one, that is being changed.
Sort of high level comment, but this doesn't look right: With dependent
regulators you don't strictly lock the regulators in the direction of
the tree root, but also siblings at the same level. This is prone with
deadlocks, as you can't control the order of the regulator locks being
taken by different tasks. This really needs a ww_mutex to be
implemented in a robust way.
Regards,
Lucas
> Signed-off-by: Maciej Purski <m.purski@samsung.com>
> ---
> ?drivers/regulator/core.c | 75 +++++++++++++++++++++++++++++++++---------------
> ?1 file changed, 52 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> index 0b366c5..7c57268 100644
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -201,38 +201,67 @@ static void regulator_unlock(struct regulator_dev *rdev)
> > ? }
> ?}
> ?
> -/**
> - * regulator_lock_supply - lock a regulator and its supplies
> - * @rdev:?????????regulator source
> - */
> -static void regulator_lock_supply(struct regulator_dev *rdev)
> +static int regulator_lock_recursive(struct regulator_dev *rdev,
> > + ????unsigned int subclass)
> ?{
> > + struct regulator_dev *c_rdev;
> > ? int i;
> ?
> > - for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++)
> > - regulator_lock_nested(rdev, i);
> > + for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
> > + c_rdev = rdev->coupling_desc.coupled_rdevs[i];
> +
> > + if (!c_rdev)
> > + continue;
> +
> > + regulator_lock_nested(c_rdev, subclass++);
> +
> > + if (c_rdev->supply)
> > + subclass =
> > + regulator_lock_recursive(c_rdev->supply->rdev,
> > + ?subclass);
> > + }
> +
> > + return subclass;
> ?}
> ?
> ?/**
> - * regulator_unlock_supply - unlock a regulator and its supplies
> - * @rdev:?????????regulator source
> + * regulator_unlock_dependent - unlock regulator's suppliers and coupled
> > + * regulators
> > + * @rdev: regulator source
> + *
> + * Unlock all regulators related with rdev by coupling or suppling.
> ? */
> -static void regulator_unlock_supply(struct regulator_dev *rdev)
> +static void regulator_unlock_dependent(struct regulator_dev *rdev)
> ?{
> > - struct regulator *supply;
> > + struct regulator_dev *c_rdev;
> > + int i;
> ?
> > - while (1) {
> > - regulator_unlock(rdev);
> > - supply = rdev->supply;
> > + for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
> > + c_rdev = rdev->coupling_desc.coupled_rdevs[i];
> ?
> > - if (!rdev->supply)
> > - return;
> > + if (!c_rdev)
> > + continue;
> +
> > + regulator_unlock(c_rdev);
> ?
> > - rdev = supply->rdev;
> > + if (c_rdev->supply)
> > + regulator_unlock_dependent(c_rdev->supply->rdev);
> > ? }
> ?}
> ?
> ?/**
> + * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
> > + * @rdev: regulator source
> + *
> + * This function as a wrapper on regulator_lock_recursive(), which locks
> + * all regulators related with rdev by coupling or suppling.
> + */
> +static inline void regulator_lock_dependent(struct regulator_dev *rdev)
> +{
> > + regulator_lock_recursive(rdev, 0);
> +}
> +
> +/**
> ? * of_get_regulator - get a regulator device node based on supply name
> ? * @dev: Device pointer for the consumer (of regulator) device
> ? * @supply: regulator supply name
> @@ -3332,12 +3361,12 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
> > ? int ret = 0;
> ?
> > ? pr_err("%s: %d\n", __func__, __LINE__);
> > - regulator_lock_supply(regulator->rdev);
> > + regulator_lock_dependent(regulator->rdev);
> ?
> > ? ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
> > ? ?????PM_SUSPEND_ON);
> ?
> > - regulator_unlock_supply(regulator->rdev);
> > + regulator_unlock_dependent(regulator->rdev);
> ?
> > ? return ret;
> ?}
> @@ -3415,12 +3444,12 @@ int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
> > ? if (regulator_check_states(state) || state == PM_SUSPEND_ON)
> > ? return -EINVAL;
> ?
> > - regulator_lock_supply(regulator->rdev);
> > + regulator_lock_dependent(regulator->rdev);
> ?
> > ? ret = _regulator_set_suspend_voltage(regulator, min_uV,
> > ? ?????max_uV, state);
> ?
> > - regulator_unlock_supply(regulator->rdev);
> > + regulator_unlock_dependent(regulator->rdev);
> ?
> > ? return ret;
> ?}
> @@ -3612,11 +3641,11 @@ int regulator_get_voltage(struct regulator *regulator)
> ?{
> > ? int ret;
> ?
> > - regulator_lock_supply(regulator->rdev);
> > + regulator_lock_dependent(regulator->rdev);
> ?
> > ? ret = _regulator_get_voltage(regulator->rdev);
> ?
> > - regulator_unlock_supply(regulator->rdev);
> > + regulator_unlock_dependent(regulator->rdev);
> ?
> > ? return ret;
> ?}
^ permalink raw reply
* [RFC PATCH 7/8] dts: coresight: Define new bindings for direction of data flow
From: Suzuki K Poulose @ 2018-06-04 14:20 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180601203928.GD9838@xps15>
On 06/01/2018 09:39 PM, Mathieu Poirier wrote:
> On Fri, Jun 01, 2018 at 02:16:06PM +0100, Suzuki K Poulose wrote:
>> So far we have relied on an undocumented property "slave-mode",
>> to indicate if the given port is input or not. Since we are
>> redefining the coresight bindings, define new property for the
>> "direction" of data flow for a given connection endpoint in the
>> device.
>>
>> Each endpoint must define the following property.
>>
>> - "direction" : 0 => Port is input
>> 1 => Port is output
>>
>> Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>> ---
>> drivers/hwtracing/coresight/of_coresight.c | 20 ++++++++++++++++----
>
> You haven't documented the binding in bindings/arm/coresight.txt the same way
> you did with "coresight,hwid". I'm guessing you simply forgot to do a "git add"
> on the file when preparing the patchset.
>
>> 1 file changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
>> index 99d7a9c..63c1668 100644
>> --- a/drivers/hwtracing/coresight/of_coresight.c
>> +++ b/drivers/hwtracing/coresight/of_coresight.c
>> @@ -52,7 +52,19 @@ of_coresight_get_endpoint_device(struct device_node *endpoint)
>> endpoint, of_dev_node_match);
>> }
>>
>> -static void of_coresight_get_ports(const struct device_node *node,
>> +static bool of_coresight_ep_is_input(struct device *dev, struct device_node *ep_node)
>
> I suggested of_coresight_endpoint_get_port_id() in my review of 6/8. I'm good
> with either "ep" or "endpoint", as long as the names are consistent.
Yep, that's right. This is what I have for the documentation :
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -103,9 +103,11 @@ with a specific direction of data flow, each
connection must define the
following properties to uniquely identify the connection details.
* Direction of the data flow w.r.t the component :
- Each input port must have the following property defined at the
"endpoint"
+ Each hardware port must have the following property defined at the
"endpoint"
for the port.
- "slave-mode"
+ "direction" - 32bit integer, whose values are defined as follows :
+ 0 => the endpoint is an Input port
+ 1 => the endpoint is an Output port.
and changes to the examples as well..
Cheers
Suzuki
^ permalink raw reply
* [PATCH 1/6] PCI: iproc: Update iProc PCI binding for INTx support
From: Rob Herring @ 2018-06-04 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1527631130-20045-2-git-send-email-ray.jui@broadcom.com>
+Arnd
On Tue, May 29, 2018 at 4:58 PM, Ray Jui <ray.jui@broadcom.com> wrote:
> Update the iProc PCIe binding document for better modeling of the legacy
> interrupt (INTx) support
>
> Signed-off-by: Ray Jui <ray.jui@broadcom.com>
> ---
> .../devicetree/bindings/pci/brcm,iproc-pcie.txt | 31 +++++++++++++++++-----
> 1 file changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt b/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt
> index b8e48b4..7ea24dc 100644
> --- a/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/brcm,iproc-pcie.txt
> @@ -13,9 +13,6 @@ controller, used in Stingray
> PAXB-based root complex is used for external endpoint devices. PAXC-based
> root complex is connected to emulated endpoint devices internal to the ASIC
> - reg: base address and length of the PCIe controller I/O register space
> -- #interrupt-cells: set to <1>
> -- interrupt-map-mask and interrupt-map, standard PCI properties to define the
> - mapping of the PCIe interface to interrupt numbers
> - linux,pci-domain: PCI domain ID. Should be unique for each host controller
> - bus-range: PCI bus numbers covered
> - #address-cells: set to <3>
> @@ -41,6 +38,16 @@ Required:
> - brcm,pcie-ob-axi-offset: The offset from the AXI address to the internal
> address used by the iProc PCIe core (not the PCIe address)
>
> +Legacy interrupt (INTx) support (optional):
> +
> +Note INTx is for PAXB only.
> +
> +- interrupt-controller: claims itself as an interrupt controller for INTx
> +- #interrupt-cells: set to <1>
> +- interrupt-map-mask and interrupt-map, standard PCI properties to define
> +the mapping of the PCIe interface to interrupt numbers
> +- interrupts: interrupt line wired to the generic GIC for INTx support
> +
> MSI support (optional):
>
> For older platforms without MSI integrated in the GIC, iProc PCIe core provides
> @@ -77,9 +84,14 @@ Example:
> compatible = "brcm,iproc-pcie";
> reg = <0x18012000 0x1000>;
>
> + interrupt-controller;
> #interrupt-cells = <1>;
> - interrupt-map-mask = <0 0 0 0>;
> - interrupt-map = <0 0 0 0 &gic GIC_SPI 100 IRQ_TYPE_NONE>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0 0 0 1 &pcie0 1>,
Are you sure this works? The irq parsing code will ignore
interrupt-map if interrupt-controller is found. In other words, you
should have one or the other, but not both.
Maybe it happens to work because "pcie0" is this node and your irq
numbers are the same.
Arnd, any thoughts on this?
> + <0 0 0 2 &pcie0 2>,
> + <0 0 0 3 &pcie0 3>,
> + <0 0 0 4 &pcie0 4>;
> + interrupts = <GIC_SPI 100 IRQ_TYPE_NONE>;
>
> linux,pci-domain = <0>;
>
> @@ -115,9 +127,14 @@ Example:
> compatible = "brcm,iproc-pcie";
> reg = <0x18013000 0x1000>;
>
> + interrupt-controller;
> #interrupt-cells = <1>;
> - interrupt-map-mask = <0 0 0 0>;
> - interrupt-map = <0 0 0 0 &gic GIC_SPI 106 IRQ_TYPE_NONE>;
> + interrupt-map-mask = <0 0 0 7>;
> + interrupt-map = <0 0 0 1 &pcie1 1>,
> + <0 0 0 2 &pcie1 2>,
> + <0 0 0 3 &pcie1 3>,
> + <0 0 0 4 &pcie1 4>;
> + interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
>
> linux,pci-domain = <1>;
>
> --
> 2.1.4
>
^ permalink raw reply
* [PATCH 3/3] rtc: ftrtc010: let the core handle range
From: Alexandre Belloni @ 2018-06-04 14:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604141528.15635-1-alexandre.belloni@bootlin.com>
The current range handling is highly suspicious. Anyway, let the core
handle it.
The RTC has a 32 bit counter on top of days + hh:mm:ss registers.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-ftrtc010.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index 2cdc78ffeb17..61f798c6101f 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -95,9 +95,6 @@ static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
u32 sec, min, hour, day, offset;
timeu64_t time;
- if (tm->tm_year >= 2148) /* EPOCH Year + 179 */
- return -EINVAL;
-
time = rtc_tm_to_time64(tm);
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
@@ -120,6 +117,7 @@ static const struct rtc_class_ops ftrtc010_rtc_ops = {
static int ftrtc010_rtc_probe(struct platform_device *pdev)
{
+ u32 days, hour, min, sec;
struct ftrtc010_rtc *rtc;
struct device *dev = &pdev->dev;
struct resource *res;
@@ -172,6 +170,15 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
+ sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
+ min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
+ hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
+ days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
+
+ rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 +
+ min * 60 + sec;
+ rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min;
+
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
IRQF_SHARED, pdev->name, dev);
if (unlikely(ret))
--
2.17.1
^ permalink raw reply related
* [PATCH 2/3] rtc: ftrtc010: handle dates after 2106
From: Alexandre Belloni @ 2018-06-04 14:15 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604141528.15635-1-alexandre.belloni@bootlin.com>
Use correct types for offset and time and use
rtc_time64_to_tm/rtc_tm_to_time64 to handle dates after 2106 properly.
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-ftrtc010.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index 165d0b62db00..2cdc78ffeb17 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -73,8 +73,8 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
- unsigned int days, hour, min, sec;
- unsigned long offset, time;
+ u32 days, hour, min, sec, offset;
+ timeu64_t time;
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
@@ -84,7 +84,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
- rtc_time_to_tm(time, tm);
+ rtc_time64_to_tm(time, tm);
return 0;
}
@@ -92,13 +92,13 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
- unsigned int sec, min, hour, day;
- unsigned long offset, time;
+ u32 sec, min, hour, day, offset;
+ timeu64_t time;
if (tm->tm_year >= 2148) /* EPOCH Year + 179 */
return -EINVAL;
- rtc_tm_to_time(tm, &time);
+ time = rtc_tm_to_time64(tm);
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
--
2.17.1
^ permalink raw reply related
* [PATCH 1/3] rtc: ftrtc010: switch to devm_rtc_allocate_device
From: Alexandre Belloni @ 2018-06-04 14:15 UTC (permalink / raw)
To: linux-arm-kernel
Switch to devm_rtc_allocate_device/rtc_register_device. This allow or
further improvement and simplifies ftrtc010_rtc_remove().
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
---
drivers/rtc/rtc-ftrtc010.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index af8d6beae20c..165d0b62db00 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -166,14 +166,18 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
if (!rtc->rtc_base)
return -ENOMEM;
+ rtc->rtc_dev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
+
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
IRQF_SHARED, pdev->name, dev);
if (unlikely(ret))
return ret;
- rtc->rtc_dev = rtc_device_register(pdev->name, dev,
- &ftrtc010_rtc_ops, THIS_MODULE);
- return PTR_ERR_OR_ZERO(rtc->rtc_dev);
+ return rtc_register_device(rtc->rtc_dev);
}
static int ftrtc010_rtc_remove(struct platform_device *pdev)
@@ -184,7 +188,6 @@ static int ftrtc010_rtc_remove(struct platform_device *pdev)
clk_disable_unprepare(rtc->extclk);
if (!IS_ERR(rtc->pclk))
clk_disable_unprepare(rtc->pclk);
- rtc_device_unregister(rtc->rtc_dev);
return 0;
}
--
2.17.1
^ permalink raw reply related
* [PATCH v3] of: platform: stop accessing invalid dev in of_platform_device_destroy
From: Srinivas Kandagatla @ 2018-06-04 14:14 UTC (permalink / raw)
To: linux-arm-kernel
Immediately after the platform_device_unregister() the device will be
cleaned up. Accessing the freed pointer immediately after that will
crash the system.
Found this bug when kernel is built with CONFIG_PAGE_POISONING and testing
loading/unloading audio drivers in a loop on Qcom platforms.
Fix this by moving of_node_clear_flag() just before the unregister calls.
Below is the crash trace:
Unable to handle kernel paging request at virtual address 6b6b6b6b6b6c03
Mem abort info:
ESR = 0x96000021
Exception class = DABT (current EL), IL = 32 bits
SET = 0, FnV = 0
EA = 0, S1PTW = 0
Data abort info:
ISV = 0, ISS = 0x00000021
CM = 0, WnR = 0
[006b6b6b6b6b6c03] address between user and kernel address ranges
Internal error: Oops: 96000021 [#1] PREEMPT SMP
Modules linked in:
CPU: 2 PID: 1784 Comm: sh Tainted: G W 4.17.0-rc7-02230-ge3a63a7ef641-dirty #204
Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT)
pstate: 80000005 (Nzcv daif -PAN -UAO)
pc : clear_bit+0x18/0x2c
lr : of_platform_device_destroy+0x64/0xb8
sp : ffff00000c9c3930
x29: ffff00000c9c3930 x28: ffff80003d39b200
x27: ffff000008bb1000 x26: 0000000000000040
x25: 0000000000000124 x24: ffff80003a9a3080
x23: 0000000000000060 x22: ffff00000939f518
x21: ffff80003aa79e98 x20: ffff80003aa3dae0
x19: ffff80003aa3c890 x18: ffff800009feb794
x17: 0000000000000000 x16: 0000000000000000
x15: ffff800009feb790 x14: 0000000000000000
x13: ffff80003a058778 x12: ffff80003a058728
x11: ffff80003a058750 x10: 0000000000000000
x9 : 0000000000000006 x8 : ffff80003a825988
x7 : bbbbbbbbbbbbbbbb x6 : 0000000000000001
x5 : 0000000000000000 x4 : 0000000000000001
x3 : 0000000000000008 x2 : 0000000000000001
x1 : 6b6b6b6b6b6b6c03 x0 : 0000000000000000
Process sh (pid: 1784, stack limit = 0x (ptrval))
Call trace:
clear_bit+0x18/0x2c
q6afe_remove+0x20/0x38
apr_device_remove+0x30/0x70
device_release_driver_internal+0x170/0x208
device_release_driver+0x14/0x20
bus_remove_device+0xcc/0x150
device_del+0x10c/0x310
device_unregister+0x1c/0x70
apr_remove_device+0xc/0x18
device_for_each_child+0x50/0x80
apr_remove+0x18/0x20
rpmsg_dev_remove+0x38/0x68
device_release_driver_internal+0x170/0x208
device_release_driver+0x14/0x20
bus_remove_device+0xcc/0x150
device_del+0x10c/0x310
device_unregister+0x1c/0x70
qcom_smd_remove_device+0xc/0x18
device_for_each_child+0x50/0x80
qcom_smd_unregister_edge+0x3c/0x70
smd_subdev_remove+0x18/0x28
rproc_stop+0x48/0xd8
rproc_shutdown+0x60/0xe8
state_store+0xbc/0xf8
dev_attr_store+0x18/0x28
sysfs_kf_write+0x3c/0x50
kernfs_fop_write+0x118/0x1e0
__vfs_write+0x18/0x110
vfs_write+0xa4/0x1a8
ksys_write+0x48/0xb0
sys_write+0xc/0x18
el0_svc_naked+0x30/0x34
Code: d2800022 8b400c21 f9800031 9ac32043 (c85f7c22)
---[ end trace 32020935775616a2 ]---
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
Changes since v2:
Move the calls to of_node_clear_flag just before unregister,
suggested by Rob.
drivers/of/platform.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index c00d81dfac0b..9c91f97ffbe1 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -537,6 +537,9 @@ int of_platform_device_destroy(struct device *dev, void *data)
if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
device_for_each_child(dev, NULL, of_platform_device_destroy);
+ of_node_clear_flag(dev->of_node, OF_POPULATED);
+ of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
+
if (dev->bus == &platform_bus_type)
platform_device_unregister(to_platform_device(dev));
#ifdef CONFIG_ARM_AMBA
@@ -544,8 +547,6 @@ int of_platform_device_destroy(struct device *dev, void *data)
amba_device_unregister(to_amba_device(dev));
#endif
- of_node_clear_flag(dev->of_node, OF_POPULATED);
- of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
return 0;
}
EXPORT_SYMBOL_GPL(of_platform_device_destroy);
--
2.16.2
^ permalink raw reply related
* [GIT PULL] EDAC pile for 4.18
From: Borislav Petkov @ 2018-06-04 14:12 UTC (permalink / raw)
To: linux-arm-kernel
Hi Linus,
please pull the current pile of fixes to the EDAC tree.
There's a merge commit in there with an immutable branch from
the socfpga's tree as changes there are touching the same
socfpga_stratix10.dtsi file, patches in my tree are touching so I
thought this was the best way to avoid merge conflicts. Please let me
know if this way is wrong.
And that's why you see those unrelated changes in the list below. So
depending on the pull order, you'll either get them through my tree or
through the arm-soc tree.
Btw, I'm not aware of any order those merges are *required* to happen so
let me CC the relevant parties in case order is important after all.
Thanks!
---
The following changes since commit 6d08b06e67cd117f6992c46611dfb4ce267cd71e:
Linux 4.17-rc2 (2018-04-22 19:20:09 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp.git tags/edac_for_4.18
for you to fetch changes up to eaa3a1d46cfdbf1af50311e7a22f5d38c0418b56:
EDAC, ghes: Make platform-based whitelisting x86-only (2018-05-21 12:18:57 +0200)
----------------------------------------------------------------
* Stratix10 SDRAM support to altera_edac (Thor Thayer)
* the usual misc fixes all over the place
----------------------------------------------------------------
Alan Tull (1):
arm64: dts: stratix10: enable i2c, add i2c periperals
Alexandru Gagniuc (1):
EDAC, ghes: Remove unused argument to ghes_edac_report_mem_error()
Bartosz Golaszewski (1):
ARM: dts: consistently use 'atmel' as at24 manufacturer in cyclone5
Borislav Petkov (4):
ghes, EDAC: Fix ghes_edac registration
Merge tag 'socfpga_updates_for_v4.18_part2' into edac-for-4.18
EDAC, ghes: Use BIT() macro
EDAC, ghes: Make platform-based whitelisting x86-only
Colin Ian King (1):
EDAC, i7core: Fix spelling mistake: "redundacy" -> "redundancy"
Dinh Nguyen (1):
arm64: dts: stratix10: use clock bindings for the Stratix10 platform
Graham Moore (1):
arm64: dts: stratix10: Add PL330 DMAC to Stratix10 dts
Ooi, Joyce (1):
arm64: dts: stratix10: Change pad skew values for EMAC0 PHY driver
Randy Dunlap (1):
EDAC, skx: Fix skx_edac build error when ACPI_NFIT=m
Sughosh Ganu (1):
EDAC, ghes: Add a null pointer check in ghes_edac_unregister()
Thor Thayer (6):
arm64: dts: stratix10: add sdram ecc
Documentation: dt: socfpga: Add Stratix10 ECC Manager binding
EDAC, altera: Add support for Stratix10 SDRAM EDAC
Documentation: dt: edac: Move Altera SOCFPGA EDAC file
EDAC, altera: Handle SDRAM Uncorrectable Errors on Stratix10
EDAC, altera: Fix ARM64 build warning
Toshi Kani (1):
EDAC, ghes: Add DDR4 and NVDIMM memory types
.../{arm/altera => edac}/socfpga-eccmgr.txt | 35 ++
arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts | 6 +-
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi | 83 +++-
.../boot/dts/altera/socfpga_stratix10_socdk.dts | 44 +-
drivers/acpi/apei/ghes.c | 16 +-
drivers/edac/Kconfig | 3 +-
drivers/edac/altera_edac.c | 504 ++++++++++++++++++++-
drivers/edac/altera_edac.h | 132 +++++-
drivers/edac/ghes_edac.c | 55 ++-
drivers/edac/i7core_edac.c | 2 +-
include/acpi/ghes.h | 7 +-
11 files changed, 817 insertions(+), 70 deletions(-)
rename Documentation/devicetree/bindings/{arm/altera => edac}/socfpga-eccmgr.txt (87%)
--
Regards/Gruss,
Boris.
SUSE Linux GmbH, GF: Felix Imend?rffer, Jane Smithard, Graham Norton, HRB 21284 (AG N?rnberg)
--
^ permalink raw reply
* [PATCH 7/7] regulator: core: Enable voltage balancing
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Call regulator_balance_voltage() instead of set_voltage_rdev()
in set_voltage_unlocked() and in enabling and disabling functions,
but only if the regulator is coupled.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 2a7ffb7..2dd1f99 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2296,6 +2296,11 @@ int regulator_enable(struct regulator *regulator)
int ret = 0;
pr_err("%s: %d\n", __func__, __LINE__);
+ if (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled) {
+ rdev_err(rdev, "not all coupled regulators registered\n");
+ return -EPERM;
+ }
+
if (regulator->always_on)
return 0;
@@ -2307,6 +2312,9 @@ int regulator_enable(struct regulator *regulator)
regulator_lock_dependent(rdev);
ret = _regulator_enable(rdev);
+ /* balance only if there are regulators coupled */
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (ret != 0 && rdev->supply)
@@ -2417,6 +2425,8 @@ int regulator_disable(struct regulator *regulator)
regulator_lock_dependent(rdev);
ret = _regulator_disable(rdev);
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (ret == 0 && rdev->supply)
@@ -2470,6 +2480,8 @@ int regulator_force_disable(struct regulator *regulator)
regulator_lock_dependent(rdev);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
+ if (rdev->coupling_desc.n_coupled > 1)
+ regulator_balance_voltage(rdev, PM_SUSPEND_ON);
regulator_unlock_dependent(rdev);
if (rdev->supply)
@@ -3031,7 +3043,16 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int old_min_uV, old_max_uV;
int current_uV;
+<<<<<<< HEAD
pr_err("%s: %d\n", __func__, __LINE__);
+=======
+ if (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled) {
+ rdev_err(rdev, "not all coupled regulators registered\n");
+ ret = -EPERM;
+ goto out;
+ }
+
+>>>>>>> fcbf6fa... regulator: core: Enable voltage balancing
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
* voltage for multiple frequencies, for example).
@@ -3074,7 +3095,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (ret < 0)
goto out2;
- ret = regulator_set_voltage_rdev(rdev, min_uV, max_uV, state);
+ /* for not coupled regulators this will just set the voltage */
+ ret = regulator_balance_voltage(rdev, state);
if (ret < 0)
goto out2;
--
2.7.4
^ permalink raw reply related
* [PATCH 6/7] regulator: core: Lock dependent regulators on regulator_enable()
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Since regulator_enable() might now call regulator_balance_voltage(),
it should also lock its coupled regulators and suppliers.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7c57268..2a7ffb7 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2305,9 +2305,9 @@ int regulator_enable(struct regulator *regulator)
return ret;
}
- regulator_lock(rdev);
+ regulator_lock_dependent(rdev);
ret = _regulator_enable(rdev);
- regulator_unlock(rdev);
+ regulator_unlock_dependent(rdev);
if (ret != 0 && rdev->supply)
regulator_disable(rdev->supply);
@@ -2415,9 +2415,9 @@ int regulator_disable(struct regulator *regulator)
if (regulator->always_on)
return 0;
- regulator_lock(rdev);
+ regulator_lock_dependent(rdev);
ret = _regulator_disable(rdev);
- regulator_unlock(rdev);
+ regulator_unlock_dependent(rdev);
if (ret == 0 && rdev->supply)
regulator_disable(rdev->supply);
@@ -2467,10 +2467,10 @@ int regulator_force_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret;
- regulator_lock(rdev);
+ regulator_lock_dependent(rdev);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
- regulator_unlock(rdev);
+ regulator_unlock_dependent(rdev);
if (rdev->supply)
while (rdev->open_count--)
--
2.7.4
^ permalink raw reply related
* [PATCH 5/7] regulator: core: Lock dependent regulators
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Implementing coupled regulators adds a new dependency between
regulators. Therefore, the current locking model should be changed.
Coupled regulators should be locked with regulator's supplies at the
same time.
Add new function regulator_lock_dependent(), which locks all regulators
related with the one, that is being changed.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 75 +++++++++++++++++++++++++++++++++---------------
1 file changed, 52 insertions(+), 23 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 0b366c5..7c57268 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -201,38 +201,67 @@ static void regulator_unlock(struct regulator_dev *rdev)
}
}
-/**
- * regulator_lock_supply - lock a regulator and its supplies
- * @rdev: regulator source
- */
-static void regulator_lock_supply(struct regulator_dev *rdev)
+static int regulator_lock_recursive(struct regulator_dev *rdev,
+ unsigned int subclass)
{
+ struct regulator_dev *c_rdev;
int i;
- for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++)
- regulator_lock_nested(rdev, i);
+ for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
+ c_rdev = rdev->coupling_desc.coupled_rdevs[i];
+
+ if (!c_rdev)
+ continue;
+
+ regulator_lock_nested(c_rdev, subclass++);
+
+ if (c_rdev->supply)
+ subclass =
+ regulator_lock_recursive(c_rdev->supply->rdev,
+ subclass);
+ }
+
+ return subclass;
}
/**
- * regulator_unlock_supply - unlock a regulator and its supplies
- * @rdev: regulator source
+ * regulator_unlock_dependent - unlock regulator's suppliers and coupled
+ * regulators
+ * @rdev: regulator source
+ *
+ * Unlock all regulators related with rdev by coupling or suppling.
*/
-static void regulator_unlock_supply(struct regulator_dev *rdev)
+static void regulator_unlock_dependent(struct regulator_dev *rdev)
{
- struct regulator *supply;
+ struct regulator_dev *c_rdev;
+ int i;
- while (1) {
- regulator_unlock(rdev);
- supply = rdev->supply;
+ for (i = 0; i < rdev->coupling_desc.n_coupled; i++) {
+ c_rdev = rdev->coupling_desc.coupled_rdevs[i];
- if (!rdev->supply)
- return;
+ if (!c_rdev)
+ continue;
+
+ regulator_unlock(c_rdev);
- rdev = supply->rdev;
+ if (c_rdev->supply)
+ regulator_unlock_dependent(c_rdev->supply->rdev);
}
}
/**
+ * regulator_lock_dependent - lock regulator's suppliers and coupled regulators
+ * @rdev: regulator source
+ *
+ * This function as a wrapper on regulator_lock_recursive(), which locks
+ * all regulators related with rdev by coupling or suppling.
+ */
+static inline void regulator_lock_dependent(struct regulator_dev *rdev)
+{
+ regulator_lock_recursive(rdev, 0);
+}
+
+/**
* of_get_regulator - get a regulator device node based on supply name
* @dev: Device pointer for the consumer (of regulator) device
* @supply: regulator supply name
@@ -3332,12 +3361,12 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
int ret = 0;
pr_err("%s: %d\n", __func__, __LINE__);
- regulator_lock_supply(regulator->rdev);
+ regulator_lock_dependent(regulator->rdev);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
PM_SUSPEND_ON);
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev);
return ret;
}
@@ -3415,12 +3444,12 @@ int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV,
if (regulator_check_states(state) || state == PM_SUSPEND_ON)
return -EINVAL;
- regulator_lock_supply(regulator->rdev);
+ regulator_lock_dependent(regulator->rdev);
ret = _regulator_set_suspend_voltage(regulator, min_uV,
max_uV, state);
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev);
return ret;
}
@@ -3612,11 +3641,11 @@ int regulator_get_voltage(struct regulator *regulator)
{
int ret;
- regulator_lock_supply(regulator->rdev);
+ regulator_lock_dependent(regulator->rdev);
ret = _regulator_get_voltage(regulator->rdev);
- regulator_unlock_supply(regulator->rdev);
+ regulator_unlock_dependent(regulator->rdev);
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 4/7] regulator: core: Implement voltage balancing algorithm
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
On Odroid XU3/4 and other Exynos5422 based boards there is a case, that
different devices on the board are supplied by different regulators
with non-fixed voltages. If one of these devices temporarily requires
higher voltage, there might occur a situation that the spread between
two devices' voltages is so high, that there is a risk of changing
'high' and 'low' states on the interconnection between devices powered
by those regulators.
Introduce new function regulator_balance_voltage(), which
keeps max_spread constraint fulfilled between a group of coupled
regulators. It should be called if a regulator changes its
voltage or after disabling or enabling. Disabled regulators should
follow changes of the enabled ones, but their consumers' demands
shouldn't be taken into account while calculating voltage of other
coupled regulators.
Find voltages, which are closest to suiting all the consumers' demands,
while fulfilling max_spread constraint, keeping the following rules:
- if one regulator is about to rise its voltage, rise others
voltages in order to keep the max_spread
- if a regulator, which has caused rising other regulators, is
lowered, lower other regulators if possible
- if one regulator is about to lower its voltage, but it hasn't caused
rising other regulators, don't change its voltage if it breaks the
max_spread
Change regulators' voltages step by step, keeping max_spread constraint
fulfilled all the time. Function regulator_get_optimal_voltage()
should find the best possible change for the regulator, which doesn't
break max_spread constraint. In function regulator_balance_voltage()
optimize number of steps by finding highest voltage difference on
each iteration.
If a regulator, which is about to change its voltage, is not coupled,
method regulator_get_optimal_voltage() should simply return the lowest
voltage fulfilling consumers' demands.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 183 insertions(+)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index c5478d2..0b366c5 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -105,6 +105,8 @@ static int _notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data);
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV);
+static int regulator_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state);
static int regulator_set_voltage_rdev(struct regulator_dev *rdev,
int min_uV, int max_uV,
suspend_state_t state);
@@ -3126,6 +3128,187 @@ static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
return ret;
}
+static int regulator_get_optimal_voltage(struct regulator_dev *rdev)
+{
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ struct regulator_dev **c_rdevs = c_desc->coupled_rdevs;
+ int max_spread = rdev->constraints->max_spread;
+ int n_coupled = c_desc->n_coupled;
+ int desired_min_uV, desired_max_uV, min_current_uV = INT_MAX;
+ int max_current_uV = 0, highest_min_uV = 0, target_uV, possible_uV;
+ int i, ret;
+
+ /* If consumers don't provide any demands, set voltage to min_uV */
+ desired_min_uV = rdev->constraints->min_uV;
+ desired_max_uV = rdev->constraints->max_uV;
+ ret = regulator_check_consumers(rdev,
+ &desired_min_uV,
+ &desired_max_uV, PM_SUSPEND_ON);
+ if (ret < 0)
+ goto out;
+
+ /*
+ * If there are no coupled regulators, simply set the voltage demanded
+ * by consumers.
+ */
+ if (n_coupled == 1) {
+ ret = desired_min_uV;
+ goto out;
+ }
+
+ /* Find highest min desired voltage */
+ for (i = 0; i < n_coupled; i++) {
+ int tmp_min = 0;
+ int tmp_max = INT_MAX;
+
+ if (!_regulator_is_enabled(c_rdevs[i]))
+ continue;
+
+ ret = regulator_check_consumers(c_rdevs[i],
+ &tmp_min,
+ &tmp_max, PM_SUSPEND_ON);
+ if (ret < 0)
+ goto out;
+
+ if (tmp_min > highest_min_uV)
+ highest_min_uV = tmp_min;
+ }
+
+ /*
+ * Let target_uV be equal to the desired one if possible.
+ * If not, set it to minimum voltage, allowed by other coupled
+ * regulators.
+ */
+ target_uV = max(desired_min_uV, highest_min_uV - max_spread);
+
+ /*
+ * Find min and max voltages, which currently aren't
+ * violating max_spread
+ */
+ for (i = 0; i < n_coupled; i++) {
+ int tmp_act;
+
+ /*
+ * Don't check the regulator, which is about
+ * to change voltage
+ */
+ if (c_rdevs[i] == rdev)
+ continue;
+ if (!_regulator_is_enabled(c_rdevs[i]))
+ continue;
+
+ tmp_act = _regulator_get_voltage(c_rdevs[i]);
+ if (tmp_act < 0) {
+ ret = tmp_act;
+ goto out;
+ }
+
+ if (tmp_act < min_current_uV)
+ min_current_uV = tmp_act;
+
+ if (tmp_act > max_current_uV)
+ max_current_uV = tmp_act;
+ }
+
+ /* There aren't any other regulators enabled */
+ if (max_current_uV == 0) {
+ possible_uV = target_uV;
+ } else {
+ /*
+ * Correct target voltage, so as it currently isn't
+ * violating max_spread
+ */
+ possible_uV = max(target_uV, max_current_uV - max_spread);
+ possible_uV = min(possible_uV, min_current_uV + max_spread);
+ }
+
+ if (possible_uV > desired_max_uV) {
+ ret = -EINVAL;
+ goto out;
+ }
+ ret = possible_uV;
+
+out:
+ return ret;
+}
+
+static int regulator_balance_voltage(struct regulator_dev *rdev,
+ suspend_state_t state)
+{
+ struct regulator_dev **c_rdevs;
+ struct regulator_dev *best_rdev;
+ struct coupling_desc *c_desc = &rdev->coupling_desc;
+ int n_coupled;
+ int i, best_delta, best_uV, ret = 1;
+
+ c_rdevs = c_desc->coupled_rdevs;
+ n_coupled = c_desc->n_coupled;
+
+ /*
+ * if system is in a state other than PM_SUSPEND_ON, don't check
+ * other coupled regulators
+ */
+ if (state != PM_SUSPEND_ON)
+ n_coupled = 1;
+
+ /*
+ * Find the best possible voltage change on each loop. Leave the loop
+ * if there isn't any possible change.
+ */
+ while (1) {
+ best_delta = 0;
+ best_uV = 0;
+ best_rdev = NULL;
+
+ /*
+ * Find highest difference between optimal voltage
+ * and current voltage.
+ */
+ for (i = 0; i < n_coupled; i++) {
+ /*
+ * optimal_uV is the best voltage that can be set for
+ * i-th regulator@the moment without violating
+ * max_spread constraint in order to balance
+ * the coupled voltages.
+ */
+ int optimal_uV, current_uV;
+
+ optimal_uV = regulator_get_optimal_voltage(c_rdevs[i]);
+ if (optimal_uV < 0) {
+ ret = optimal_uV;
+ goto out;
+ }
+
+ current_uV = _regulator_get_voltage(c_rdevs[i]);
+ if (current_uV < 0) {
+ ret = optimal_uV;
+ goto out;
+ }
+
+ if (abs(best_delta) < abs(optimal_uV - current_uV)) {
+ best_delta = optimal_uV - current_uV;
+ best_rdev = c_rdevs[i];
+ best_uV = optimal_uV;
+ }
+ }
+
+ /* Nothing to change, return successfully */
+ if (!best_rdev) {
+ ret = 0;
+ goto out;
+ }
+
+ ret = regulator_set_voltage_rdev(best_rdev, best_uV,
+ best_uV, state);
+
+ if (ret < 0)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
/**
* regulator_set_voltage - set regulator output voltage
* @regulator: regulator source
--
2.7.4
^ permalink raw reply related
* [PATCH 3/7] regulator: core: Use re-entrant locks
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Re-entrant locks were implemented in previous patches. They should
substitute all mutex_lock() and mutex_unlock() calls on regulators'
mutexes.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 413a824..c5478d2 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2274,9 +2274,9 @@ int regulator_enable(struct regulator *regulator)
return ret;
}
- mutex_lock(&rdev->mutex);
+ regulator_lock(rdev);
ret = _regulator_enable(rdev);
- mutex_unlock(&rdev->mutex);
+ regulator_unlock(rdev);
if (ret != 0 && rdev->supply)
regulator_disable(rdev->supply);
@@ -2384,9 +2384,9 @@ int regulator_disable(struct regulator *regulator)
if (regulator->always_on)
return 0;
- mutex_lock(&rdev->mutex);
+ regulator_lock(rdev);
ret = _regulator_disable(rdev);
- mutex_unlock(&rdev->mutex);
+ regulator_unlock(rdev);
if (ret == 0 && rdev->supply)
regulator_disable(rdev->supply);
@@ -2436,10 +2436,10 @@ int regulator_force_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret;
- mutex_lock(&rdev->mutex);
+ regulator_lock(rdev);
regulator->uA_load = 0;
ret = _regulator_force_disable(regulator->rdev);
- mutex_unlock(&rdev->mutex);
+ regulator_unlock(rdev);
if (rdev->supply)
while (rdev->open_count--)
@@ -2587,9 +2587,9 @@ int regulator_is_enabled(struct regulator *regulator)
if (regulator->always_on)
return 1;
- mutex_lock(®ulator->rdev->mutex);
+ regulator_lock(regulator->rdev);
ret = _regulator_is_enabled(regulator->rdev);
- mutex_unlock(®ulator->rdev->mutex);
+ regulator_unlock(regulator->rdev);
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH 2/7] regulator: core: Add regulator_set_voltage_rdev()
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Refactor regulator_set_voltage_unlocked() by taking code related to
regulator_dev and creating a new function regulator_set_voltage_rdev(),
which operates only on struct regulator_dev.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 40 ++++++++++++++++++++++++++++------------
1 file changed, 28 insertions(+), 12 deletions(-)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b740426..413a824 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -105,6 +105,9 @@ static int _notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data);
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV);
+static int regulator_set_voltage_rdev(struct regulator_dev *rdev,
+ int min_uV, int max_uV,
+ suspend_state_t state);
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
@@ -2996,8 +2999,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int ret = 0;
int old_min_uV, old_max_uV;
int current_uV;
- int best_supply_uV = 0;
- int supply_change_uV = 0;
pr_err("%s: %d\n", __func__, __LINE__);
/* If we're setting the same range as last time the change
@@ -3042,6 +3043,26 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (ret < 0)
goto out2;
+ ret = regulator_set_voltage_rdev(rdev, min_uV, max_uV, state);
+ if (ret < 0)
+ goto out2;
+
+out:
+ return 0;
+out2:
+ voltage->min_uV = old_min_uV;
+ voltage->max_uV = old_max_uV;
+
+ return ret;
+}
+
+static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV,
+ int max_uV, suspend_state_t state)
+{
+ int best_supply_uV = 0;
+ int supply_change_uV = 0;
+ int ret;
+
if (rdev->supply &&
regulator_ops_is_valid(rdev->supply->rdev,
REGULATOR_CHANGE_VOLTAGE) &&
@@ -3053,13 +3074,13 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
selector = regulator_map_voltage(rdev, min_uV, max_uV);
if (selector < 0) {
ret = selector;
- goto out2;
+ goto out;
}
best_supply_uV = _regulator_list_voltage(rdev, selector, 0);
if (best_supply_uV < 0) {
ret = best_supply_uV;
- goto out2;
+ goto out;
}
best_supply_uV += rdev->desc->min_dropout_uV;
@@ -3067,7 +3088,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
current_supply_uV = _regulator_get_voltage(rdev->supply->rdev);
if (current_supply_uV < 0) {
ret = current_supply_uV;
- goto out2;
+ goto out;
}
supply_change_uV = best_supply_uV - current_supply_uV;
@@ -3079,7 +3100,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (ret) {
dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n",
ret);
- goto out2;
+ goto out;
}
}
@@ -3089,7 +3110,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
ret = _regulator_do_set_suspend_voltage(rdev, min_uV,
max_uV, state);
if (ret < 0)
- goto out2;
+ goto out;
if (supply_change_uV < 0) {
ret = regulator_set_voltage_unlocked(rdev->supply,
@@ -3103,11 +3124,6 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
out:
return ret;
-out2:
- voltage->min_uV = old_min_uV;
- voltage->max_uV = old_max_uV;
-
- return ret;
}
/**
--
2.7.4
^ permalink raw reply related
* [PATCH 1/7] regulator: core: Add debug messages
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528120764-14316-1-git-send-email-m.purski@samsung.com>
Add debug messages on voltage setting and enabling path in order
to debug the coupled regulators problem.
Signed-off-by: Maciej Purski <m.purski@samsung.com>
---
drivers/regulator/core.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 6ed568b..b740426 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1571,6 +1571,7 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
struct device *dev = rdev->dev.parent;
int ret;
+ pr_err("%s: %d\n", __func__, __LINE__);
/* No supply to resovle? */
if (!rdev->supply_name)
return 0;
@@ -2211,6 +2212,7 @@ static int _regulator_enable(struct regulator_dev *rdev)
{
int ret;
+ pr_err("%s: %d\n", __func__, __LINE__);
lockdep_assert_held_once(&rdev->mutex);
/* check voltage and requested load before enabling */
@@ -2259,6 +2261,7 @@ int regulator_enable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
+ pr_err("%s: %d\n", __func__, __LINE__);
if (regulator->always_on)
return 0;
@@ -2275,6 +2278,7 @@ int regulator_enable(struct regulator *regulator)
if (ret != 0 && rdev->supply)
regulator_disable(rdev->supply);
+ pr_err("%s: %d\n", __func__, __LINE__);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_enable);
@@ -2373,6 +2377,7 @@ int regulator_disable(struct regulator *regulator)
struct regulator_dev *rdev = regulator->rdev;
int ret = 0;
+ pr_err("%s: %d\n", __func__, __LINE__);
if (regulator->always_on)
return 0;
@@ -2383,6 +2388,7 @@ int regulator_disable(struct regulator *regulator)
if (ret == 0 && rdev->supply)
regulator_disable(rdev->supply);
+ pr_err("%s: %d\n", __func__, __LINE__);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_disable);
@@ -2858,6 +2864,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
const struct regulator_ops *ops = rdev->desc->ops;
int old_uV = _regulator_get_voltage(rdev);
+ pr_err("%s: %d\n", __func__, __LINE__);
trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
min_uV += rdev->constraints->uV_offset;
@@ -2992,6 +2999,7 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
int best_supply_uV = 0;
int supply_change_uV = 0;
+ pr_err("%s: %d\n", __func__, __LINE__);
/* If we're setting the same range as last time the change
* should be a noop (some cpufreq implementations use the same
* voltage for multiple frequencies, for example).
@@ -3124,6 +3132,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
{
int ret = 0;
+ pr_err("%s: %d\n", __func__, __LINE__);
regulator_lock_supply(regulator->rdev);
ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV,
--
2.7.4
^ permalink raw reply related
* Regression in Linux next again
From: Maciej Purski @ 2018-06-04 13:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180530144505.GB5705@atomide.com>
Hi,
this patchset contains previous two reverted patches. They were split
in order to make it easier to bisect, where the problem lies. It adds
also some simple debugs, which should help us track down the problem.
Tony, please apply this patchset and test it on your Beaglebone. It'd be
great if you could try to find out, which patch causes failure. They should
be appliable on the current next.
Thanks,
Maciej Purski
Maciej Purski (7):
regulator: core: Add debug messages
regulator: core: Add regulator_set_voltage_rdev()
regulator: core: Use re-entrant locks
regulator: core: Implement voltage balancing algorithm
regulator: core: Lock dependent regulators
regulator: core: Lock dependent regulators on regulator_enable()
regulator: core: Enable voltage balancing
drivers/regulator/core.c | 341 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 300 insertions(+), 41 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v2 3/6] clk: ti: dra7: Add clkctrl clock data for the mcan clocks
From: Faiz Abbas @ 2018-06-04 13:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180601142613.GU5705@atomide.com>
Hi,
On Friday 01 June 2018 07:56 PM, Tony Lindgren wrote:
> * Faiz Abbas <faiz_abbas@ti.com> [180601 06:49]:
>> Hi,
>>
>> On Thursday 31 May 2018 06:59 PM, Tero Kristo wrote:
>>> On 31/05/18 13:14, Faiz Abbas wrote:
>>>> Hi,
>>>>
>>>> On Thursday 31 May 2018 09:33 AM, Rob Herring wrote:
>>>>> On Wed, May 30, 2018 at 07:41:30PM +0530, Faiz Abbas wrote:
>>>>>> Add clkctrl data for the m_can clocks and register it within the
>>>> ...
>>>>>> ? diff --git a/include/dt-bindings/clock/dra7.h
>>>>>> b/include/dt-bindings/clock/dra7.h
>>>>>> index 5e1061b15aed..d7549c57cac3 100644
>>>>>> --- a/include/dt-bindings/clock/dra7.h
>>>>>> +++ b/include/dt-bindings/clock/dra7.h
>>>>>> @@ -168,5 +168,6 @@
>>>>>> ? #define DRA7_COUNTER_32K_CLKCTRL??? DRA7_CLKCTRL_INDEX(0x50)
>>>>>> ? #define DRA7_UART10_CLKCTRL??? DRA7_CLKCTRL_INDEX(0x80)
>>>>>> ? #define DRA7_DCAN1_CLKCTRL??? DRA7_CLKCTRL_INDEX(0x88)
>>>>>> +#define DRA7_ADC_CLKCTRL??? DRA7_CLKCTRL_INDEX(0xa0)
>>>>>
>>>>> ADC and mcan are the same thing?
>>>>>
>>>>
>>>> The register to control MCAN clocks is called ADC_CLKCTRL, Yes.
>>>
>>> Is there any reason for this or is that just a documentation bug?
>>>
>>
>> Looks like they meant to have an ADC in dra74 or dra72 but decided
>> against it and then many years later used the same registers for MCAN
>> instead. You can see ADC_CLKCTRL exists in dra72 TRM but is explicitly
>> disabled.
>>
>> http://www.ti.com/lit/ug/spruic2b/spruic2b.pdf pg:1524
>
> How about make add also something like to dra7.h:
>
> #define DRA7_MCAN_CLKCTRL DRA7_ADC_CLKCTRL
>
> And you can add a comment to the dts file to avoid people
> getting confused with this constantly.
>
I would prefer to follow the TRM so that people don't look for registers
that don't exist at all.
Thanks,
Faiz
^ permalink raw reply
* Applied "ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it" to the asoc tree
From: Mark Brown @ 2018-06-04 13:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604111326.15708-1-srinivas.kandagatla@linaro.org>
The patch
ASoC: dapm: delete dapm_kcontrol_data paths list before freeing it
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
>From ff2faf1289c1f81b5b26b9451dd1c2006aac8db8 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Date: Mon, 4 Jun 2018 12:13:26 +0100
Subject: [PATCH] ASoC: dapm: delete dapm_kcontrol_data paths list before
freeing it
dapm_kcontrol_data is freed as part of dapm_kcontrol_free(), leaving the
paths pointer dangling in the list.
This leads to system crash when we try to unload and reload sound card.
I hit this bug during ADSP crash/reboot test case on Dragon board DB410c.
Without this patch, on SLAB Poisoning enabled build, kernel crashes with
"BUG kmalloc-128 (Tainted: G W ): Poison overwritten"
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable at vger.kernel.org
---
sound/soc/soc-dapm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1e9a36389667..36a39ba30226 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -433,6 +433,8 @@ static int dapm_kcontrol_data_alloc(struct snd_soc_dapm_widget *widget,
static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
{
struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
+
+ list_del(&data->paths);
kfree(data->wlist);
kfree(data);
}
--
2.17.0
^ permalink raw reply related
* [PATCH v2] of: platform: stop accessing invalid dev in of_platform_device_destroy
From: Srinivas Kandagatla @ 2018-06-04 13:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqJ9AMDiYCfgGgHZ=XL_1yJjTdSA4Jb_GqHAZML3jwB6+Q@mail.gmail.com>
On 04/06/18 14:44, Rob Herring wrote:
> On Fri, Jun 1, 2018 at 7:03 PM, Srinivas Kandagatla
> <srinivas.kandagatla@linaro.org> wrote:
>> Immediately after the platform_device_unregister() the device will be cleaned up.
>> Accessing the freed pointer immediately after that will crash the system.
>>
>> Found this bug when kernel is built with CONFIG_PAGE_POISONING and testing
>> loading/unloading audio drivers in a loop on Qcom platforms.
>
> Curious, does the unittest not catch this too?
>
Not sure!
>>
>> Fix this by removing accessing the dev pointer.
>> Below is the carsh trace:
>
> s/carsh/crash/
Yep.
>
> [...]
>
>> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
>> index c00d81dfac0b..84c5c899187b 100644
>> --- a/drivers/of/platform.c
>> +++ b/drivers/of/platform.c
>> @@ -529,10 +529,13 @@ arch_initcall_sync(of_platform_default_populate_init);
>>
>> int of_platform_device_destroy(struct device *dev, void *data)
>> {
>> + struct device_node *np;
>> +
>> /* Do not touch devices not populated from the device tree */
>> if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
>> return 0;
>>
>> + np = dev->of_node;
>> /* Recurse for any nodes that were treated as busses */
>> if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
>> device_for_each_child(dev, NULL, of_platform_device_destroy);
>> @@ -544,8 +547,8 @@ int of_platform_device_destroy(struct device *dev, void *data)
>> amba_device_unregister(to_amba_device(dev));
>> #endif
>>
>> - of_node_clear_flag(dev->of_node, OF_POPULATED);
>> - of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
>
> Just move these 2 lines to before unregister calls.
Make sense.. I will do that in v3.
thanks,
srini
>
>> + of_node_clear_flag(np, OF_POPULATED);
>> + of_node_clear_flag(np, OF_POPULATED_BUS);
>> return 0;
>> }
>> EXPORT_SYMBOL_GPL(of_platform_device_destroy);
>> --
>> 2.16.2
>>
^ permalink raw reply
* [PATCH 09/10] dpaa_eth: add support for hardware timestamping
From: Richard Cochran @ 2018-06-04 13:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180604070837.19265-10-yangbo.lu@nxp.com>
On Mon, Jun 04, 2018 at 03:08:36PM +0800, Yangbo Lu wrote:
> +if FSL_DPAA_ETH
> +config FSL_DPAA_ETH_TS
> + bool "DPAA hardware timestamping support"
> + select PTP_1588_CLOCK_QORIQ
> + default n
> + help
> + Enable DPAA hardware timestamping support.
> + This option is useful for applications to get
> + hardware time stamps on the Ethernet packets
> + using the SO_TIMESTAMPING API.
> +endif
You should drop this #ifdef. In general, if a MAC supports time
stamping and PHC, then the driver support should simply be compiled
in.
[ When time stamping incurs a large run time performance penalty to
non-PTP users, then it might make sense to have a Kconfig option to
disable it, but that doesn't appear to be the case here. ]
> @@ -1615,6 +1635,24 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv)
> skbh = (struct sk_buff **)phys_to_virt(addr);
> skb = *skbh;
>
> +#ifdef CONFIG_FSL_DPAA_ETH_TS
> + if (priv->tx_tstamp &&
> + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
This condition fits on one line easily.
> + struct skb_shared_hwtstamps shhwtstamps;
> + u64 ns;
Local variables belong at the top of the function.
> + memset(&shhwtstamps, 0, sizeof(shhwtstamps));
> +
> + if (!dpaa_get_tstamp_ns(priv->net_dev, &ns,
> + priv->mac_dev->port[TX],
> + (void *)skbh)) {
> + shhwtstamps.hwtstamp = ns_to_ktime(ns);
> + skb_tstamp_tx(skb, &shhwtstamps);
> + } else {
> + dev_warn(dev, "dpaa_get_tstamp_ns failed!\n");
> + }
> + }
> +#endif
> if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
> nr_frags = skb_shinfo(skb)->nr_frags;
> dma_unmap_single(dev, addr, qm_fd_get_offset(fd) +
> @@ -2086,6 +2124,14 @@ static int dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
> if (unlikely(err < 0))
> goto skb_to_fd_failed;
>
> +#ifdef CONFIG_FSL_DPAA_ETH_TS
> + if (priv->tx_tstamp &&
> + skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
One line please.
> + fd.cmd |= FM_FD_CMD_UPD;
> + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
> + }
> +#endif
> +
> if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0))
> return NETDEV_TX_OK;
>
Thanks,
Richard
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox