[PATCH] powerpc/eeh:Fix some mistakes in comments
Get rid of warning: arch/powerpc/kernel/eeh.c:774: warning: expecting prototype for eeh_set_pe_freset(). Prototype was for eeh_set_dev_freset() instead Signed-off-by: Kai Song --- arch/powerpc/kernel/eeh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index e9b597ed423c..4cd4acb049ec 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -761,8 +761,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat } /** - * eeh_set_pe_freset - Check the required reset for the indicated device - * @data: EEH device + * eeh_set_dev_freset - Check the required reset for the indicated device + * @edev: EEH device * @flag: return value * * Each device might have its preferred reset type: fundamental or -- 2.27.0
Re: [PATCH] mm: Remove HARDENED_USERCOPY_FALLBACK
On Tue, 21 Sep 2021, Stephen Kitt wrote: > This has served its purpose and is no longer used. All usercopy > violations appear to have been handled by now, any remaining > instances (or new bugs) will cause copies to be rejected. > > This isn't a direct revert of commit 2d891fbc3bb6 ("usercopy: Allow > strict enforcement of whitelists"); since usercopy_fallback is > effectively 0, the fallback handling is removed too. > > This also removes the usercopy_fallback module parameter on > slab_common. > > Link: https://github.com/KSPP/linux/issues/153 > Signed-off-by: Stephen Kitt > Suggested-by: Kees Cook Acked-by: David Rientjes
Re: Add Apple M1 support to PASemi i2c driver
Hi Sven, I can't apply your patch 5 (i2c: pasemi: Split pci driver to its own file). [1] Error message: patching file b/drivers/i2c/busses/i2c-pasemi-core.c (renamed from a/drivers/i2c/busses/i2c-pasemi.c) Hunk #3 FAILED at 344. 1 out of 3 hunks FAILED -- saving rejects to file b/drivers/i2c/busses/i2c-pasemi-core.c.rej patching file b/drivers/i2c/busses/i2c-pasemi-core.h patching file b/drivers/i2c/busses/i2c-pasemi-pci.c Please post one patch with all your modifications. Thanks, Christian [1] https://lists.ozlabs.org/pipermail/linuxppc-dev/2021-September/234636.html On 26 September 2021 at 04:55 pm, Christian Zigotzky wrote: Hi Sven, Thanks a lot for your nice explanation of the history of the PASemi i2c driver. We are using Nemo boards with 64-bit dual-core PWRficient PA6T-1682M CPUs (A-EON AmigaOne X1000). [1] The RC2 of kernel 5.15 works without any problems on our Nemo boards. [2] Could you please post all your patches merged in one patch? It's easier for me to apply one patch. Thanks, Christian [1] https://en.wikipedia.org/wiki/AmigaOne_X1000 [2] https://forum.hyperion-entertainment.com/viewtopic.php?p=54056#p54056
[PATCH 01/10] dt-bindings: i2c: Add Apple I2C controller bindings
The Apple I2C controller is based on the PASemi I2C controller. It is present on Apple SoCs such as the M1. Signed-off-by: Sven Peter --- .../devicetree/bindings/i2c/apple,i2c.yaml| 61 +++ MAINTAINERS | 1 + 2 files changed, 62 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/apple,i2c.yaml diff --git a/Documentation/devicetree/bindings/i2c/apple,i2c.yaml b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml new file mode 100644 index ..22fc8483256f --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/apple,i2c.yaml @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/i2c/apple,i2c.yaml#; +$schema: "http://devicetree.org/meta-schemas/core.yaml#; + +title: Apple/PASemi I2C controller + +maintainers: + - Sven Peter + +description: | + Apple SoCs such as the M1 come with a I2C controller based on the one found + in machines with P. A. Semi's PWRficient processors. + The bus is used to communicate with e.g. USB PD chips or the speaker + amp. + +allOf: + - $ref: /schemas/i2c/i2c-controller.yaml# + +properties: + compatible: +enum: + - apple,t8103-i2c + - apple,i2c + + reg: +maxItems: 1 + + clocks: +items: + - description: I2C bus reference clock + + interrupts: +maxItems: 1 + + clock-frequency: +description: | + Desired I2C bus clock frequency in Hz. If not specified, 100 kHz will be + used. This frequency is generated by dividing the reference clock. + Allowed values are between ref_clk/(16*4) and ref_clk/(16*255). + +required: + - compatible + - reg + - clocks + - interrupts + +unevaluatedProperties: false + +examples: + - | +i2c@3501 { + compatible = "apple,t8103-i2c"; + reg = <0x3501 0x4000>; + interrupt-parent = <>; + interrupts = <0 627 4>; + clocks = <_clk>; + #address-cells = <1>; + #size-cells = <0>; +}; diff --git a/MAINTAINERS b/MAINTAINERS index 329d3a0a9fdb..380a680db92f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1734,6 +1734,7 @@ B:https://github.com/AsahiLinux/linux/issues C: irc://irc.oftc.net/asahi-dev T: git https://github.com/AsahiLinux/linux.git F: Documentation/devicetree/bindings/arm/apple.yaml +F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml F: arch/arm64/boot/dts/apple/ -- 2.25.1
[PATCH 07/10] i2c: pasemi: Allow to configure bus frequency
Right now the bus frequency has always been hardcoded as 100 KHz with the specific reference clock used in the PASemi PCI controllers. Make this configurable to prepare for the platform driver. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi-core.c | 8 +++- drivers/i2c/busses/i2c-pasemi-core.h | 1 + drivers/i2c/busses/i2c-pasemi-pci.c | 4 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 7c6715f5dbb8..a39e3258b162 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -39,9 +39,6 @@ #define CTL_MTR0x0200 #define CTL_CLK_M 0x00ff -#define CLK_100K_DIV 84 -#define CLK_400K_DIV 21 - static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", @@ -63,8 +60,9 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) static void pasemi_reset(struct pasemi_smbus *smbus) { - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M)); + + reg_write(smbus, REG_CTL, val); } static void pasemi_smb_clear(struct pasemi_smbus *smbus) diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index 7acc33de6ce1..30a7990825ef 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -14,6 +14,7 @@ struct pasemi_smbus { void __iomem*ioaddr; unsigned longbase; int size; + unsigned int clk_div; }; int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index 9a19df31866b..7405e0b48514 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -17,6 +17,9 @@ #include "i2c-pasemi-core.h" +#define CLK_100K_DIV 84 +#define CLK_400K_DIV 21 + static struct pci_driver pasemi_smb_pci_driver; static int pasemi_smb_pci_probe(struct pci_dev *dev, @@ -35,6 +38,7 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, smbus->dev = >dev; smbus->base = pci_resource_start(dev, 0); smbus->size = pci_resource_len(dev, 0); + smbus->clk_div = CLK_100K_DIV; if (!request_region(smbus->base, smbus->size, pasemi_smb_pci_driver.name)) { -- 2.25.1
[PATCH 03/10] i2c: pasemi: Remove usage of pci_dev
Prepare to create a platform driver by removing all usages of pci_dev we can. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index dd31d902a621..5a25c2e54b9e 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -18,7 +18,7 @@ static struct pci_driver pasemi_smb_driver; struct pasemi_smbus { - struct pci_dev *dev; + struct device *dev; struct i2c_adapter adapter; void __iomem*ioaddr; unsigned longbase; @@ -52,7 +52,7 @@ struct pasemi_smbus { static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { - dev_dbg(>dev->dev, "smbus write reg %lx val %08x\n", + dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", smbus->base + reg, val); iowrite32(val, smbus->ioaddr + reg); } @@ -61,7 +61,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; ret = ioread32(smbus->ioaddr + reg); - dev_dbg(>dev->dev, "smbus read reg %lx val %08x\n", + dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n", smbus->base + reg, ret); return ret; } @@ -94,7 +94,7 @@ static int pasemi_smb_waitready(struct pasemi_smbus *smbus) return -ENXIO; if (timeout < 0) { - dev_warn(>dev->dev, "Timeout, status 0x%08x\n", status); + dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status); reg_write(smbus, REG_SMSTA, status); return -ETIME; } @@ -342,7 +342,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, if (!smbus) return -ENOMEM; - smbus->dev = dev; + smbus->dev = >dev; smbus->base = pci_resource_start(dev, 0); smbus->size = pci_resource_len(dev, 0); @@ -366,7 +366,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, smbus->adapter.algo_data = smbus; /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = >dev; + smbus->adapter.dev.parent = smbus->dev; reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | (CLK_100K_DIV & CTL_CLK_M))); -- 2.25.1
[PATCH 02/10] i2c: pasemi: Use io{read,write}32
In preparation for splitting this driver up into a platform_driver and a pci_driver, replace outl/inl usage with ioport_map and ioread32/iowrite32. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi.c | 16 +--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 20f2772c0e79..dd31d902a621 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -20,6 +20,7 @@ static struct pci_driver pasemi_smb_driver; struct pasemi_smbus { struct pci_dev *dev; struct i2c_adapter adapter; + void __iomem*ioaddr; unsigned longbase; int size; }; @@ -53,13 +54,13 @@ static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { dev_dbg(>dev->dev, "smbus write reg %lx val %08x\n", smbus->base + reg, val); - outl(val, smbus->base + reg); + iowrite32(val, smbus->ioaddr + reg); } static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; - ret = inl(smbus->base + reg); + ret = ioread32(smbus->ioaddr + reg); dev_dbg(>dev->dev, "smbus read reg %lx val %08x\n", smbus->base + reg, ret); return ret; @@ -351,6 +352,12 @@ static int pasemi_smb_probe(struct pci_dev *dev, goto out_kfree; } + smbus->ioaddr = ioport_map(smbus->base, smbus->size); + if (!smbus->ioaddr) { + error = -EBUSY; + goto out_release_region; + } + smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), "PA Semi SMBus adapter at 0x%lx", smbus->base); @@ -366,12 +373,14 @@ static int pasemi_smb_probe(struct pci_dev *dev, error = i2c_add_adapter(>adapter); if (error) - goto out_release_region; + goto out_ioport_unmap; pci_set_drvdata(dev, smbus); return 0; + out_ioport_unmap: + ioport_unmap(smbus->ioaddr); out_release_region: release_region(smbus->base, smbus->size); out_kfree: @@ -384,6 +393,7 @@ static void pasemi_smb_remove(struct pci_dev *dev) struct pasemi_smbus *smbus = pci_get_drvdata(dev); i2c_del_adapter(>adapter); + ioport_unmap(smbus->ioaddr); release_region(smbus->base, smbus->size); kfree(smbus); } -- 2.25.1
[PATCH 04/10] i2c: pasemi: Split off common probing code
Split off common probing code that will be used by both the PCI and the platform device. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi.c | 39 + 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c index 5a25c2e54b9e..9d69ff63f674 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi.c @@ -329,6 +329,30 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = pasemi_smb_func, }; +static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) +{ + int error; + + smbus->adapter.owner = THIS_MODULE; + snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), +"PA Semi SMBus adapter at 0x%lx", smbus->base); + smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; + smbus->adapter.algo = _algorithm; + smbus->adapter.algo_data = smbus; + + /* set up the sysfs linkage to our parent device */ + smbus->adapter.dev.parent = smbus->dev; + + reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | + (CLK_100K_DIV & CTL_CLK_M))); + + error = i2c_add_adapter(>adapter); + if (error) + return error; + + return 0; +} + static int pasemi_smb_probe(struct pci_dev *dev, const struct pci_device_id *id) { @@ -358,20 +382,7 @@ static int pasemi_smb_probe(struct pci_dev *dev, goto out_release_region; } - smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), -"PA Semi SMBus adapter at 0x%lx", smbus->base); - smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus->adapter.algo = _algorithm; - smbus->adapter.algo_data = smbus; - - /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = smbus->dev; - - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); - - error = i2c_add_adapter(>adapter); + int error = pasemi_i2c_common_probe(smbus); if (error) goto out_ioport_unmap; -- 2.25.1
[PATCH 08/10] i2c: pasemi: Refactor _probe to use devm_*
Using managed device resources means there's nothing left to be done in pasemi_smb_pci_remove and also allows to remove base and size from struct pasemi_smbus. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi-core.c | 10 +++ drivers/i2c/busses/i2c-pasemi-core.h | 2 -- drivers/i2c/busses/i2c-pasemi-pci.c | 45 3 files changed, 16 insertions(+), 41 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index a39e3258b162..0ec65263fd08 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -41,8 +41,7 @@ static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) { - dev_dbg(smbus->dev, "smbus write reg %lx val %08x\n", - smbus->base + reg, val); + dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val); iowrite32(val, smbus->ioaddr + reg); } @@ -50,8 +49,7 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) { int ret; ret = ioread32(smbus->ioaddr + reg); - dev_dbg(smbus->dev, "smbus read reg %lx val %08x\n", - smbus->base + reg, ret); + dev_dbg(smbus->dev, "smbus read reg %x val %08x\n", reg, ret); return ret; } @@ -329,7 +327,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) smbus->adapter.owner = THIS_MODULE; snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), -"PA Semi SMBus adapter at 0x%lx", smbus->base); +"PA Semi SMBus adapter at 0x%p", smbus->ioaddr); smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; smbus->adapter.algo = _algorithm; smbus->adapter.algo_data = smbus; @@ -339,7 +337,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) pasemi_reset(smbus); - error = i2c_add_adapter(>adapter); + error = devm_i2c_add_adapter(smbus->dev, >adapter); if (error) return error; diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index 30a7990825ef..aca4e2da9089 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -12,8 +12,6 @@ struct pasemi_smbus { struct device *dev; struct i2c_adapter adapter; void __iomem*ioaddr; - unsigned longbase; - int size; unsigned int clk_div; }; diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index 7405e0b48514..c1b8901110c0 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -26,57 +26,37 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { struct pasemi_smbus *smbus; + unsigned long base; + int size; int error; if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) return -ENODEV; - smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); + smbus = devm_kzalloc(>dev, sizeof(*smbus), GFP_KERNEL); if (!smbus) return -ENOMEM; smbus->dev = >dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); + base = pci_resource_start(dev, 0); + size = pci_resource_len(dev, 0); smbus->clk_div = CLK_100K_DIV; - if (!request_region(smbus->base, smbus->size, - pasemi_smb_pci_driver.name)) { - error = -EBUSY; - goto out_kfree; - } + if (!devm_request_region(>dev, base, size, + pasemi_smb_pci_driver.name)) + return -EBUSY; - smbus->ioaddr = ioport_map(smbus->base, smbus->size); - if (!smbus->ioaddr) { - error = -EBUSY; - goto out_release_region; - } + smbus->ioaddr = devm_ioport_map(>dev, base, size); + if (!smbus->ioaddr) + return -EBUSY; error = pasemi_i2c_common_probe(smbus); if (error) - goto out_ioport_unmap; + return error; pci_set_drvdata(dev, smbus); return 0; - - out_ioport_unmap: - ioport_unmap(smbus->ioaddr); - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void pasemi_smb_pci_remove(struct pci_dev *dev) -{ - struct pasemi_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(>adapter); - ioport_unmap(smbus->ioaddr); - release_region(smbus->base, smbus->size); - kfree(smbus); } static const struct pci_device_id pasemi_smb_pci_ids[] = { @@ -90,7 +70,6 @@ static struct pci_driver pasemi_smb_pci_driver = { .name = "i2c-pasemi", .id_table =
[PATCH 09/10] i2c: pasemi: Add Apple platform driver
With all the previous preparations we can now finally add the platform driver to support the PASemi-based controllers in Apple SoCs. This does not work on the M1 yet but should work on the early iPhones already. Signed-off-by: Sven Peter --- MAINTAINERS | 1 + drivers/i2c/busses/Kconfig| 11 +++ drivers/i2c/busses/Makefile | 2 + drivers/i2c/busses/i2c-pasemi-apple.c | 122 ++ 4 files changed, 136 insertions(+) create mode 100644 drivers/i2c/busses/i2c-pasemi-apple.c diff --git a/MAINTAINERS b/MAINTAINERS index 380a680db92f..6e952158b6e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1738,6 +1738,7 @@ F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml F: Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml F: Documentation/devicetree/bindings/pinctrl/apple,pinctrl.yaml F: arch/arm64/boot/dts/apple/ +F: drivers/i2c/busses/i2c-pasemi-apple.c F: drivers/irqchip/irq-apple-aic.c F: include/dt-bindings/interrupt-controller/apple-aic.h F: include/dt-bindings/pinctrl/apple.h diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index e17790fe35a7..cf4dae07e319 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -856,6 +856,17 @@ config I2C_PASEMI help Supports the PA Semi PWRficient on-chip SMBus interfaces. +config I2C_APPLE + tristate "Apple SMBus platform driver" + depends on ARCH_APPLE || COMPILE_TEST + default ARCH_APPLE + help + Say Y here if you want to use the I2C controller present on Apple + Silicon chips such as the M1. + + This driver can also be built as a module. If so, the module + will be called i2c-apple. + config I2C_PCA_PLATFORM tristate "PCA9564/PCA9665 as platform device" select I2C_ALGOPCA diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 0ab1b4cb2228..474fe2c520d0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -86,6 +86,8 @@ obj-$(CONFIG_I2C_OMAP)+= i2c-omap.o obj-$(CONFIG_I2C_OWL) += i2c-owl.o i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o +i2c-apple-objs := i2c-pasemi-core.o i2c-pasemi-apple.o +obj-$(CONFIG_I2C_APPLE)+= i2c-apple.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o obj-$(CONFIG_I2C_PXA) += i2c-pxa.o diff --git a/drivers/i2c/busses/i2c-pasemi-apple.c b/drivers/i2c/busses/i2c-pasemi-apple.c new file mode 100644 index ..c87f8e516eff --- /dev/null +++ b/drivers/i2c/busses/i2c-pasemi-apple.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 The Asahi Linux Contributors + * + * PA Semi PWRficient SMBus host driver for Apple SoCs + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "i2c-pasemi-core.h" + +struct pasemi_apple_i2c_data { + struct pasemi_smbus smbus; + struct clk *clk_ref; + struct pinctrl *pctrl; +}; + +static int pasemi_apple_i2c_calc_clk_div(struct pasemi_apple_i2c_data *data, +u32 frequency) +{ + unsigned long clk_rate = clk_get_rate(data->clk_ref); + + if (!clk_rate) + return -EINVAL; + + data->smbus.clk_div = DIV_ROUND_UP(clk_rate, 16 * frequency); + if (data->smbus.clk_div < 4) + return dev_err_probe(data->smbus.dev, -EINVAL, +"Bus frequency %d is too fast.\n", +frequency); + if (data->smbus.clk_div > 0xff) + return dev_err_probe(data->smbus.dev, -EINVAL, +"Bus frequency %d is too slow.\n", +frequency); + + return 0; +} + +static int pasemi_apple_i2c_probe(struct platform_device *pdev) +{ + struct device *dev = >dev; + struct pasemi_apple_i2c_data *data; + struct pasemi_smbus *smbus; + u32 frequency; + int error; + + data = devm_kzalloc(dev, sizeof(struct pasemi_apple_i2c_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + smbus = >smbus; + smbus->dev = dev; + + smbus->ioaddr = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(smbus->ioaddr)) + return PTR_ERR(smbus->ioaddr); + + if (of_property_read_u32(dev->of_node, "clock-frequency", )) + frequency = I2C_MAX_STANDARD_MODE_FREQ; + + data->clk_ref = devm_clk_get(dev, NULL); + if (IS_ERR(data->clk_ref)) + return PTR_ERR(data->clk_ref); + + error = clk_prepare_enable(data->clk_ref); + if (error) + return error; + + error = pasemi_apple_i2c_calc_clk_div(data,
[PATCH 05/10] i2c: pasemi: Split pci driver to its own file
Split off the PCI driver so that we can reuse common code for the platform driver. Signed-off-by: Sven Peter --- drivers/i2c/busses/Makefile | 1 + .../{i2c-pasemi.c => i2c-pasemi-core.c} | 88 + drivers/i2c/busses/i2c-pasemi-core.h | 19 drivers/i2c/busses/i2c-pasemi-pci.c | 96 +++ 4 files changed, 118 insertions(+), 86 deletions(-) rename drivers/i2c/busses/{i2c-pasemi.c => i2c-pasemi-core.c} (81%) create mode 100644 drivers/i2c/busses/i2c-pasemi-core.h create mode 100644 drivers/i2c/busses/i2c-pasemi-pci.c diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 1336b04f40e2..0ab1b4cb2228 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_I2C_NPCM7XX) += i2c-npcm7xx.o obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_OWL) += i2c-owl.o +i2c-pasemi-objs := i2c-pasemi-core.o i2c-pasemi-pci.o obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o obj-$(CONFIG_I2C_PNX) += i2c-pnx.o diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi-core.c similarity index 81% rename from drivers/i2c/busses/i2c-pasemi.c rename to drivers/i2c/busses/i2c-pasemi-core.c index 9d69ff63f674..3eda5e375fa2 100644 --- a/drivers/i2c/busses/i2c-pasemi.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -15,15 +15,7 @@ #include #include -static struct pci_driver pasemi_smb_driver; - -struct pasemi_smbus { - struct device *dev; - struct i2c_adapter adapter; - void __iomem*ioaddr; - unsigned longbase; - int size; -}; +#include "i2c-pasemi-core.h" /* Register offsets */ #define REG_MTXFIFO0x00 @@ -329,7 +321,7 @@ static const struct i2c_algorithm smbus_algorithm = { .functionality = pasemi_smb_func, }; -static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) +int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) { int error; @@ -352,79 +344,3 @@ static int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) return 0; } - -static int pasemi_smb_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - struct pasemi_smbus *smbus; - int error; - - if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) - return -ENODEV; - - smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); - if (!smbus) - return -ENOMEM; - - smbus->dev = >dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); - - if (!request_region(smbus->base, smbus->size, - pasemi_smb_driver.name)) { - error = -EBUSY; - goto out_kfree; - } - - smbus->ioaddr = ioport_map(smbus->base, smbus->size); - if (!smbus->ioaddr) { - error = -EBUSY; - goto out_release_region; - } - - int error = pasemi_i2c_common_probe(smbus); - if (error) - goto out_ioport_unmap; - - pci_set_drvdata(dev, smbus); - - return 0; - - out_ioport_unmap: - ioport_unmap(smbus->ioaddr); - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void pasemi_smb_remove(struct pci_dev *dev) -{ - struct pasemi_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(>adapter); - ioport_unmap(smbus->ioaddr); - release_region(smbus->base, smbus->size); - kfree(smbus); -} - -static const struct pci_device_id pasemi_smb_ids[] = { - { PCI_DEVICE(0x1959, 0xa003) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, pasemi_smb_ids); - -static struct pci_driver pasemi_smb_driver = { - .name = "i2c-pasemi", - .id_table = pasemi_smb_ids, - .probe = pasemi_smb_probe, - .remove = pasemi_smb_remove, -}; - -module_pci_driver(pasemi_smb_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson "); -MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver"); diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h new file mode 100644 index ..7acc33de6ce1 --- /dev/null +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include +#include +#include +#include +#include +#include +#include +#include + +struct pasemi_smbus { + struct device *dev; + struct i2c_adapter adapter; + void __iomem*ioaddr; + unsigned longbase; + int size; +}; + +int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git
[PATCH 10/10] i2c: pasemi: Set enable bit for Apple variant
Some later revisions after the original PASemi I2C controller introduce what likely is an enable bit to the CTL register. Without setting it the actual i2c transmission is never started. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi-core.c | 8 drivers/i2c/busses/i2c-pasemi-core.h | 3 +++ drivers/i2c/busses/i2c-pasemi-pci.c | 6 ++ 3 files changed, 17 insertions(+) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 0ec65263fd08..b52a65beda99 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -22,6 +22,7 @@ #define REG_MRXFIFO0x04 #define REG_SMSTA 0x14 #define REG_CTL0x1c +#define REG_REV0x28 /* Register defs */ #define MTXFIFO_READ 0x0400 @@ -37,6 +38,7 @@ #define CTL_MRR0x0400 #define CTL_MTR0x0200 +#define CTL_EN 0x0800 #define CTL_CLK_M 0x00ff static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) @@ -60,6 +62,9 @@ static void pasemi_reset(struct pasemi_smbus *smbus) { u32 val = (CTL_MTR | CTL_MRR | (smbus->clk_div & CTL_CLK_M)); + if (smbus->hw_rev >= 6) + val |= CTL_EN; + reg_write(smbus, REG_CTL, val); } @@ -335,6 +340,9 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = smbus->dev; + if (smbus->hw_rev != PASEMI_HW_REV_PCI) + smbus->hw_rev = reg_read(smbus, REG_REV); + pasemi_reset(smbus); error = devm_i2c_add_adapter(smbus->dev, >adapter); diff --git a/drivers/i2c/busses/i2c-pasemi-core.h b/drivers/i2c/busses/i2c-pasemi-core.h index aca4e2da9089..4655124a37f3 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.h +++ b/drivers/i2c/busses/i2c-pasemi-core.h @@ -8,11 +8,14 @@ #include #include +#define PASEMI_HW_REV_PCI -1 + struct pasemi_smbus { struct device *dev; struct i2c_adapter adapter; void __iomem*ioaddr; unsigned int clk_div; + int hw_rev; }; int pasemi_i2c_common_probe(struct pasemi_smbus *smbus); diff --git a/drivers/i2c/busses/i2c-pasemi-pci.c b/drivers/i2c/busses/i2c-pasemi-pci.c index c1b8901110c0..2b7be35421bc 100644 --- a/drivers/i2c/busses/i2c-pasemi-pci.c +++ b/drivers/i2c/busses/i2c-pasemi-pci.c @@ -42,6 +42,12 @@ static int pasemi_smb_pci_probe(struct pci_dev *dev, size = pci_resource_len(dev, 0); smbus->clk_div = CLK_100K_DIV; + /* +* The original PASemi PCI controllers don't have a register for +* their HW revision. +*/ + smbus->hw_rev = PASEMI_HW_REV_PCI; + if (!devm_request_region(>dev, base, size, pasemi_smb_pci_driver.name)) return -EBUSY; -- 2.25.1
[PATCH 06/10] i2c: pasemi: Move common reset code to own function
Split out common reset call to its own function so that we can later add support for selecting the clock frequency and an additional enable bit found in newer revisions. Signed-off-by: Sven Peter --- drivers/i2c/busses/i2c-pasemi-core.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-pasemi-core.c b/drivers/i2c/busses/i2c-pasemi-core.c index 3eda5e375fa2..7c6715f5dbb8 100644 --- a/drivers/i2c/busses/i2c-pasemi-core.c +++ b/drivers/i2c/busses/i2c-pasemi-core.c @@ -61,6 +61,12 @@ static inline int reg_read(struct pasemi_smbus *smbus, int reg) #define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg)) #define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO) +static void pasemi_reset(struct pasemi_smbus *smbus) +{ + reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | + (CLK_100K_DIV & CTL_CLK_M))); +} + static void pasemi_smb_clear(struct pasemi_smbus *smbus) { unsigned int status; @@ -135,8 +141,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter, return 0; reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); return err; } @@ -302,8 +307,7 @@ static int pasemi_smb_xfer(struct i2c_adapter *adapter, return 0; reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); return err; } @@ -335,8 +339,7 @@ int pasemi_i2c_common_probe(struct pasemi_smbus *smbus) /* set up the sysfs linkage to our parent device */ smbus->adapter.dev.parent = smbus->dev; - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); + pasemi_reset(smbus); error = i2c_add_adapter(>adapter); if (error) -- 2.25.1
[PATCH 00/10] Add Apple M1 support to PASemi i2c driver
Hi, This series adds support for the I2C controller found on Apple Silicon Macs which has quite a bit of history: Apple bought P.A. Semi in 2008 and it looks like a part of its legacy continues to live on in the M1. This controller has actually been used since at least the iPhone 4S and hasn't changed much since then. Essentially, there are only a few differences that matter: - The controller no longer is a PCI device - Starting at some iPhone an additional bit in one register must be set in order to start transmissions. - The reference clock and hence the clock dividers are different In order to add support for a platform device I first replaced PCI-specific bits and split out the PCI driver to its own file. Then I added support to make the clock divider configurable and converted the driver to use managed device resources to make it a bit simpler. The Apple and PASemi driver will never be compiled in the same kernel since the Apple one will run on arm64 while the original PASemi driver will only be useful on powerpc. I've thus followed the octeon (mips)/thunderx(arm64) approach to do the split: I created a -core.c file which contains the shared logic and just compile that one for both the PASemi and the new Apple driver. Now unfortunately I don't have access to any old PASemi hardware and cannot confirm that my changes haven't broken anything for those. I believe Hector was in contact with Olof a few months ago who said that he might still have an old machine on which he could test this. I'd very much appreciate if he (or anyone else for that matter :-)) could give this series a quick test on the old PASemi machines. Best, Sven Sven Peter (10): dt-bindings: i2c: Add Apple I2C controller bindings i2c: pasemi: Use io{read,write}32 i2c: pasemi: Remove usage of pci_dev i2c: pasemi: Split off common probing code i2c: pasemi: Split pci driver to its own file i2c: pasemi: Move common reset code to own function i2c: pasemi: Allow to configure bus frequency i2c: pasemi: Refactor _probe to use devm_* i2c: pasemi: Add Apple platform driver i2c: pasemi: Set enable bit for Apple variant .../devicetree/bindings/i2c/apple,i2c.yaml| 61 + MAINTAINERS | 2 + drivers/i2c/busses/Kconfig| 11 ++ drivers/i2c/busses/Makefile | 3 + drivers/i2c/busses/i2c-pasemi-apple.c | 122 ++ .../{i2c-pasemi.c => i2c-pasemi-core.c} | 114 +--- drivers/i2c/busses/i2c-pasemi-core.h | 21 +++ drivers/i2c/busses/i2c-pasemi-pci.c | 85 8 files changed, 334 insertions(+), 85 deletions(-) create mode 100644 Documentation/devicetree/bindings/i2c/apple,i2c.yaml create mode 100644 drivers/i2c/busses/i2c-pasemi-apple.c rename drivers/i2c/busses/{i2c-pasemi.c => i2c-pasemi-core.c} (77%) create mode 100644 drivers/i2c/busses/i2c-pasemi-core.h create mode 100644 drivers/i2c/busses/i2c-pasemi-pci.c -- 2.25.1
Add Apple M1 support to PASemi i2c driver
Hi Sven, Thanks a lot for your nice explanation of the history of the PASemi i2c driver. We are using Nemo boards with 64-bit dual-core PWRficient PA6T-1682M CPUs (A-EON AmigaOne X1000). [1] The RC2 of kernel 5.15 works without any problems on our Nemo boards. [2] Could you please post all your patches merged in one patch? It's easier for me to apply one patch. Thanks, Christian [1] https://en.wikipedia.org/wiki/AmigaOne_X1000 [2] https://forum.hyperion-entertainment.com/viewtopic.php?p=54056#p54056
Re: [PATCH] powerpc:85xx: fix timebase sync issue when CONFIG_HOTPLUG_CPU=n
On 2021/9/26 10:51, Xiaoming Ni wrote: When CONFIG_SMP=y, timebase synchronization is required when the second kernel is started. arch/powerpc/kernel/smp.c: int __cpu_up(unsigned int cpu, struct task_struct *tidle) { ... if (smp_ops->give_timebase) smp_ops->give_timebase(); ... } void start_secondary(void *unused) { ... if (smp_ops->take_timebase) smp_ops->take_timebase(); ... } When CONFIG_HOTPLUG_CPU=n and CONFIG_KEXEC_CORE=n, smp_85xx_ops.give_timebase is NULL, smp_85xx_ops.take_timebase is NULL, As a result, the timebase is not synchronized. Timebase synchronization does not depend on CONFIG_HOTPLUG_CPU. Fixes: 56f1ba280719 ("powerpc/mpc85xx: refactor the PM operations") Cc: sta...@vger.kernel.org #v4.6 Signed-off-by: Xiaoming Ni --- arch/powerpc/platforms/85xx/Makefile | 2 +- arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c | 4 arch/powerpc/platforms/85xx/smp.c| 9 - 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 60e4e97a929d..71ce1f6b6966 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -3,7 +3,7 @@ # Makefile for the PowerPC 85xx linux kernel. # obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_FSL_PMC)+= mpc85xx_pm_ops.o +obj-$(CONFIG_SMP) += mpc85xx_pm_ops.o obj-y += common.o diff --git a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c index 7c0133f558d0..a5656b3e9701 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_pm_ops.c @@ -17,6 +17,7 @@ static struct ccsr_guts __iomem *guts; +#ifdef CONFIG_FSL_PMC static void mpc85xx_irq_mask(int cpu) { @@ -49,6 +50,7 @@ static void mpc85xx_cpu_up_prepare(int cpu) { } +#endif static void mpc85xx_freeze_time_base(bool freeze) { @@ -76,10 +78,12 @@ static const struct of_device_id mpc85xx_smp_guts_ids[] = { static const struct fsl_pm_ops mpc85xx_pm_ops = { .freeze_time_base = mpc85xx_freeze_time_base, +#ifdef CONFIG_FSL_PMC .irq_mask = mpc85xx_irq_mask, .irq_unmask = mpc85xx_irq_unmask, .cpu_die = mpc85xx_cpu_die, .cpu_up_prepare = mpc85xx_cpu_up_prepare, +#endif }; int __init mpc85xx_setup_pmc(void) diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index c6df294054fe..349298cd9671 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c @@ -40,7 +40,6 @@ struct epapr_spin_table { u32 pir; }; -#ifdef CONFIG_HOTPLUG_CPU static u64 timebase; static int tb_req; static int tb_valid; @@ -112,6 +111,7 @@ static void mpc85xx_take_timebase(void) local_irq_restore(flags); } +#ifdef CONFIG_HOTPLUG_CPU static void smp_85xx_cpu_offline_self(void) { unsigned int cpu = smp_processor_id(); @@ -499,17 +499,16 @@ void __init mpc85xx_smp_init(void) #ifdef CONFIG_FSL_CORENET_RCPM fsl_rcpm_init(); #endif - -#ifdef CONFIG_FSL_PMC - mpc85xx_setup_pmc(); #endif + mpc85xx_setup_pmc(); if (qoriq_pm_ops) { smp_85xx_ops.give_timebase = mpc85xx_give_timebase; smp_85xx_ops.take_timebase = mpc85xx_take_timebase; +#ifdef CONFIG_HOTPLUG_CPU smp_85xx_ops.cpu_offline_self = smp_85xx_cpu_offline_self; smp_85xx_ops.cpu_die = qoriq_cpu_kill; - } #endif + } smp_ops = _85xx_ops; #ifdef CONFIG_KEXEC_CORE I found inconsistent time values on different CPUs on my mpc8572 and used this patch to fix it. But today I found out in ppc64 testing that this patch causes the system to trigger oops in the function mpc85xx_freeze_time_base(): the variable "guts" is a null pointer. I'm sorry to bother you. I'll fix it and resend v2 later, Thanks Xiaoming Ni
[PATCH v3 4/9] sections: Move is_kernel_inittext() into sections.h
The is_kernel_inittext() and init_kernel_text() are with same functionality, let's just keep is_kernel_inittext() and move it into sections.h, then update all the callers. Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Arnd Bergmann Cc: x...@kernel.org Signed-off-by: Kefeng Wang --- arch/x86/kernel/unwind_orc.c | 2 +- include/asm-generic/sections.h | 14 ++ include/linux/kallsyms.h | 8 include/linux/kernel.h | 1 - kernel/extable.c | 12 ++-- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c index a1202536fc57..d92ec2ced059 100644 --- a/arch/x86/kernel/unwind_orc.c +++ b/arch/x86/kernel/unwind_orc.c @@ -175,7 +175,7 @@ static struct orc_entry *orc_find(unsigned long ip) } /* vmlinux .init slow lookup: */ - if (init_kernel_text(ip)) + if (is_kernel_inittext(ip)) return __orc_find(__start_orc_unwind_ip, __start_orc_unwind, __stop_orc_unwind_ip - __start_orc_unwind_ip, ip); diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 24780c0f40b1..811583ca8bd0 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -172,4 +172,18 @@ static inline bool is_kernel_rodata(unsigned long addr) addr < (unsigned long)__end_rodata; } +/** + * is_kernel_inittext - checks if the pointer address is located in the + * .init.text section + * + * @addr: address to check + * + * Returns: true if the address is located in .init.text, false otherwise. + */ +static inline bool is_kernel_inittext(unsigned long addr) +{ + return addr >= (unsigned long)_sinittext && + addr < (unsigned long)_einittext; +} + #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index b016c62f30a6..8a9d329c927c 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -24,14 +24,6 @@ struct cred; struct module; -static inline int is_kernel_inittext(unsigned long addr) -{ - if (addr >= (unsigned long)_sinittext - && addr < (unsigned long)_einittext) - return 1; - return 0; -} - static inline int is_kernel_text(unsigned long addr) { if ((addr >= (unsigned long)_stext && addr < (unsigned long)_etext)) diff --git a/include/linux/kernel.h b/include/linux/kernel.h index e5a9af8a4e20..445d0dceefb8 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -229,7 +229,6 @@ extern bool parse_option_str(const char *str, const char *option); extern char *next_arg(char *args, char **param, char **val); extern int core_kernel_text(unsigned long addr); -extern int init_kernel_text(unsigned long addr); extern int __kernel_text_address(unsigned long addr); extern int kernel_text_address(unsigned long addr); extern int func_ptr_is_kernel_text(void *ptr); diff --git a/kernel/extable.c b/kernel/extable.c index da26203841d4..98ca627ac5ef 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -62,14 +62,6 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr) return e; } -int init_kernel_text(unsigned long addr) -{ - if (addr >= (unsigned long)_sinittext && - addr < (unsigned long)_einittext) - return 1; - return 0; -} - int notrace core_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_stext && @@ -77,7 +69,7 @@ int notrace core_kernel_text(unsigned long addr) return 1; if (system_state < SYSTEM_RUNNING && - init_kernel_text(addr)) + is_kernel_inittext(addr)) return 1; return 0; } @@ -94,7 +86,7 @@ int __kernel_text_address(unsigned long addr) * Since we are after the module-symbols check, there's * no danger of address overlap: */ - if (init_kernel_text(addr)) + if (is_kernel_inittext(addr)) return 1; return 0; } -- 2.26.2
[PATCH v3 3/9] sections: Move and rename core_kernel_data() to is_kernel_core_data()
Move core_kernel_data() into sections.h and rename it to is_kernel_core_data(), also make it return bool value, then update all the callers. Cc: Arnd Bergmann Cc: Steven Rostedt Cc: Ingo Molnar Cc: "David S. Miller" Signed-off-by: Kefeng Wang --- include/asm-generic/sections.h | 16 include/linux/kernel.h | 1 - kernel/extable.c | 18 -- kernel/trace/ftrace.c | 2 +- net/sysctl_net.c | 2 +- 5 files changed, 18 insertions(+), 21 deletions(-) diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 817309e289db..24780c0f40b1 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -142,6 +142,22 @@ static inline bool init_section_intersects(void *virt, size_t size) return memory_intersects(__init_begin, __init_end, virt, size); } +/** + * is_kernel_core_data - checks if the pointer address is located in the + * .data section + * + * @addr: address to check + * + * Returns: true if the address is located in .data, false otherwise. + * Note: On some archs it may return true for core RODATA, and false + * for others. But will always be true for core RW data. + */ +static inline bool is_kernel_core_data(unsigned long addr) +{ + return addr >= (unsigned long)_sdata && + addr < (unsigned long)_edata; +} + /** * is_kernel_rodata - checks if the pointer address is located in the *.rodata section diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 2776423a587e..e5a9af8a4e20 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -230,7 +230,6 @@ extern char *next_arg(char *args, char **param, char **val); extern int core_kernel_text(unsigned long addr); extern int init_kernel_text(unsigned long addr); -extern int core_kernel_data(unsigned long addr); extern int __kernel_text_address(unsigned long addr); extern int kernel_text_address(unsigned long addr); extern int func_ptr_is_kernel_text(void *ptr); diff --git a/kernel/extable.c b/kernel/extable.c index b0ea5eb0c3b4..da26203841d4 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -82,24 +82,6 @@ int notrace core_kernel_text(unsigned long addr) return 0; } -/** - * core_kernel_data - tell if addr points to kernel data - * @addr: address to test - * - * Returns true if @addr passed in is from the core kernel data - * section. - * - * Note: On some archs it may return true for core RODATA, and false - * for others. But will always be true for core RW data. - */ -int core_kernel_data(unsigned long addr) -{ - if (addr >= (unsigned long)_sdata && - addr < (unsigned long)_edata) - return 1; - return 0; -} - int __kernel_text_address(unsigned long addr) { if (kernel_text_address(addr)) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 7efbc8aaf7f6..f15badf31f52 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -323,7 +323,7 @@ int __register_ftrace_function(struct ftrace_ops *ops) if (!ftrace_enabled && (ops->flags & FTRACE_OPS_FL_PERMANENT)) return -EBUSY; - if (!core_kernel_data((unsigned long)ops)) + if (!is_kernel_core_data((unsigned long)ops)) ops->flags |= FTRACE_OPS_FL_DYNAMIC; add_ftrace_ops(_ops_list, ops); diff --git a/net/sysctl_net.c b/net/sysctl_net.c index f6cb0d4d114c..4b45ed631eb8 100644 --- a/net/sysctl_net.c +++ b/net/sysctl_net.c @@ -144,7 +144,7 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path, addr = (unsigned long)ent->data; if (is_module_address(addr)) where = "module"; - else if (core_kernel_data(addr)) + else if (is_kernel_core_data(addr)) where = "kernel"; else continue; -- 2.26.2
[PATCH v3 6/9] sections: Provide internal __is_kernel() and __is_kernel_text() helper
An internal __is_kernel() helper which only check the kernel address ranges, and an internal __is_kernel_text() helper which only check text section ranges. Signed-off-by: Kefeng Wang --- include/asm-generic/sections.h | 29 + include/linux/kallsyms.h | 4 ++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index 811583ca8bd0..a7abeadddc7a 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -186,4 +186,33 @@ static inline bool is_kernel_inittext(unsigned long addr) addr < (unsigned long)_einittext; } +/** + * __is_kernel_text - checks if the pointer address is located in the + *.text section + * + * @addr: address to check + * + * Returns: true if the address is located in .text, false otherwise. + * Note: an internal helper, only check the range of _stext to _etext. + */ +static inline bool __is_kernel_text(unsigned long addr) +{ + return addr >= (unsigned long)_stext && + addr < (unsigned long)_etext; +} + +/** + * __is_kernel - checks if the pointer address is located in the kernel range + * + * @addr: address to check + * + * Returns: true if the address is located in the kernel range, false otherwise. + * Note: an internal helper, only check the range of _stext to _end. + */ +static inline bool __is_kernel(unsigned long addr) +{ + return addr >= (unsigned long)_stext && + addr < (unsigned long)_end; +} + #endif /* _ASM_GENERIC_SECTIONS_H_ */ diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 8a9d329c927c..5fb17dd4b6fa 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -26,14 +26,14 @@ struct module; static inline int is_kernel_text(unsigned long addr) { - if ((addr >= (unsigned long)_stext && addr < (unsigned long)_etext)) + if (__is_kernel_text(addr)) return 1; return in_gate_area_no_mm(addr); } static inline int is_kernel(unsigned long addr) { - if (addr >= (unsigned long)_stext && addr < (unsigned long)_end) + if (__is_kernel(addr)) return 1; return in_gate_area_no_mm(addr); } -- 2.26.2
[PATCH v3 9/9] powerpc/mm: Use is_kernel_text() and is_kernel_inittext() helper
Use is_kernel_text() and is_kernel_inittext() helper to simplify code, also drop etext, _stext, _sinittext, _einittext declaration which already declared in section.h. Cc: Michael Ellerman Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Kefeng Wang --- arch/powerpc/mm/pgtable_32.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index dcf5ecca19d9..13c798308c2e 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c @@ -33,8 +33,6 @@ #include -extern char etext[], _stext[], _sinittext[], _einittext[]; - static u8 early_fixmap_pagetable[FIXMAP_PTE_SIZE] __page_aligned_data; notrace void __init early_ioremap_init(void) @@ -104,14 +102,13 @@ static void __init __mapin_ram_chunk(unsigned long offset, unsigned long top) { unsigned long v, s; phys_addr_t p; - int ktext; + bool ktext; s = offset; v = PAGE_OFFSET + s; p = memstart_addr + s; for (; s < top; s += PAGE_SIZE) { - ktext = ((char *)v >= _stext && (char *)v < etext) || - ((char *)v >= _sinittext && (char *)v < _einittext); + ktext = (is_kernel_text(v) || is_kernel_inittext(v)); map_kernel_page(v, p, ktext ? PAGE_KERNEL_TEXT : PAGE_KERNEL); v += PAGE_SIZE; p += PAGE_SIZE; -- 2.26.2
[PATCH v3 8/9] extable: Use is_kernel_text() helper
The core_kernel_text() should check the gate area, as it is part of kernel text range. Cc: Steven Rostedt Signed-off-by: Kefeng Wang --- kernel/extable.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel/extable.c b/kernel/extable.c index 98ca627ac5ef..0ba383d850ff 100644 --- a/kernel/extable.c +++ b/kernel/extable.c @@ -64,8 +64,7 @@ const struct exception_table_entry *search_exception_tables(unsigned long addr) int notrace core_kernel_text(unsigned long addr) { - if (addr >= (unsigned long)_stext && - addr < (unsigned long)_etext) + if (is_kernel_text(addr)) return 1; if (system_state < SYSTEM_RUNNING && -- 2.26.2
[PATCH v3 7/9] mm: kasan: Use is_kernel() helper
Directly use is_kernel() helper in kernel_or_module_addr(). Cc: Andrey Ryabinin Cc: Alexander Potapenko Cc: Andrey Konovalov Cc: Dmitry Vyukov Signed-off-by: Kefeng Wang --- mm/kasan/report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/kasan/report.c b/mm/kasan/report.c index 3239fd8f8747..1c955e1c98d5 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c @@ -226,7 +226,7 @@ static void describe_object(struct kmem_cache *cache, void *object, static inline bool kernel_or_module_addr(const void *addr) { - if (addr >= (void *)_stext && addr < (void *)_end) + if (is_kernel((unsigned long)addr)) return true; if (is_module_address((unsigned long)addr)) return true; -- 2.26.2
[PATCH v3 0/9] sections: Unify kernel sections range check and use
There are three head files(kallsyms.h, kernel.h and sections.h) which include the kernel sections range check, let's make some cleanup and unify them. 1. cleanup arch specific text/data check and fix address boundary check in kallsyms.h 2. make all the basic/core kernel range check function into sections.h 3. update all the callers, and use the helper in sections.h to simplify the code After this series, we have 5 APIs about kernel sections range check in sections.h * is_kernel_rodata() --- already in sections.h * is_kernel_core_data()--- come from core_kernel_data() in kernel.h * is_kernel_inittext() --- come from kernel.h and kallsyms.h * __is_kernel_text() --- add new internal helper * __is_kernel()--- add new internal helper Note: For the last two helpers, people should not use directly, consider to use corresponding function in kallsyms.h. v3: - Add Steven's RB to patch2 - Introduce two internal helper, then use is_kernel_text() in core_kernel_text() and is_kernel() in kernel_or_module_addr() suggested by Steven v2: https://lore.kernel.org/linux-arch/20210728081320.20394-1-wangkefeng.w...@huawei.com/ - add ACK/RW to patch2, and drop inappropriate fix tag - keep 'core' to check kernel data, suggestted by Steven Rostedt , rename is_kernel_data() to is_kernel_core_data() - drop patch8 which is merged - drop patch9 which is resend independently v1: https://lore.kernel.org/linux-arch/20210626073439.150586-1-wangkefeng.w...@huawei.com Cc: linuxppc-dev@lists.ozlabs.org Cc: linux-a...@vger.kernel.org Cc: b...@vger.kernel.org Kefeng Wang (9): kallsyms: Remove arch specific text and data check kallsyms: Fix address-checks for kernel related range sections: Move and rename core_kernel_data() to is_kernel_core_data() sections: Move is_kernel_inittext() into sections.h x86: mm: Rename __is_kernel_text() to is_x86_32_kernel_text() sections: Provide internal __is_kernel() and __is_kernel_text() helper mm: kasan: Use is_kernel() helper extable: Use is_kernel_text() helper powerpc/mm: Use is_kernel_text() and is_kernel_inittext() helper arch/powerpc/mm/pgtable_32.c | 7 +--- arch/x86/kernel/unwind_orc.c | 2 +- arch/x86/mm/init_32.c | 14 +++ include/asm-generic/sections.h | 75 ++ include/linux/kallsyms.h | 13 +- include/linux/kernel.h | 2 - kernel/extable.c | 33 ++- kernel/locking/lockdep.c | 3 -- kernel/trace/ftrace.c | 2 +- mm/kasan/report.c | 2 +- net/sysctl_net.c | 2 +- 11 files changed, 75 insertions(+), 80 deletions(-) -- 2.26.2
[PATCH v3 2/9] kallsyms: Fix address-checks for kernel related range
The is_kernel_inittext/is_kernel_text/is_kernel function should not include the end address(the labels _einittext, _etext and _end) when check the address range, the issue exists since Linux v2.6.12. Cc: Arnd Bergmann Cc: Sergey Senozhatsky Cc: Petr Mladek Reviewed-by: Petr Mladek Reviewed-by: Steven Rostedt (VMware) Acked-by: Sergey Senozhatsky Signed-off-by: Kefeng Wang --- include/linux/kallsyms.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 2a241e3f063f..b016c62f30a6 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -27,21 +27,21 @@ struct module; static inline int is_kernel_inittext(unsigned long addr) { if (addr >= (unsigned long)_sinittext - && addr <= (unsigned long)_einittext) + && addr < (unsigned long)_einittext) return 1; return 0; } static inline int is_kernel_text(unsigned long addr) { - if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)) + if ((addr >= (unsigned long)_stext && addr < (unsigned long)_etext)) return 1; return in_gate_area_no_mm(addr); } static inline int is_kernel(unsigned long addr) { - if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) + if (addr >= (unsigned long)_stext && addr < (unsigned long)_end) return 1; return in_gate_area_no_mm(addr); } -- 2.26.2
[PATCH v3 1/9] kallsyms: Remove arch specific text and data check
After commit 4ba66a976072 ("arch: remove blackfin port"), no need arch-specific text/data check. Cc: Arnd Bergmann Signed-off-by: Kefeng Wang --- include/asm-generic/sections.h | 16 include/linux/kallsyms.h | 3 +-- kernel/locking/lockdep.c | 3 --- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/include/asm-generic/sections.h b/include/asm-generic/sections.h index d16302d3eb59..817309e289db 100644 --- a/include/asm-generic/sections.h +++ b/include/asm-generic/sections.h @@ -64,22 +64,6 @@ extern __visible const void __nosave_begin, __nosave_end; #define dereference_kernel_function_descriptor(p) ((void *)(p)) #endif -/* random extra sections (if any). Override - * in asm/sections.h */ -#ifndef arch_is_kernel_text -static inline int arch_is_kernel_text(unsigned long addr) -{ - return 0; -} -#endif - -#ifndef arch_is_kernel_data -static inline int arch_is_kernel_data(unsigned long addr) -{ - return 0; -} -#endif - /* * Check if an address is part of freed initmem. This is needed on architectures * with virt == phys kernel mapping, for code that wants to check if an address diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 6851c2313cad..2a241e3f063f 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -34,8 +34,7 @@ static inline int is_kernel_inittext(unsigned long addr) static inline int is_kernel_text(unsigned long addr) { - if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) || - arch_is_kernel_text(addr)) + if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)) return 1; return in_gate_area_no_mm(addr); } diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 7096384dc60f..dcdbcee391cd 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -803,9 +803,6 @@ static int static_obj(const void *obj) if ((addr >= start) && (addr < end)) return 1; - if (arch_is_kernel_data(addr)) - return 1; - /* * in-kernel percpu var? */ -- 2.26.2
[PATCH v3 5/9] x86: mm: Rename __is_kernel_text() to is_x86_32_kernel_text()
Commit b56cd05c55a1 ("x86/mm: Rename is_kernel_text to __is_kernel_text"), add '__' prefix not to get in conflict with existing is_kernel_text() in . We will add __is_kernel_text() for the basic kernel text range check in the next patch, so use private is_x86_32_kernel_text() naming for x86 special check. Cc: Ingo Molnar Cc: Borislav Petkov Cc: x...@kernel.org Signed-off-by: Kefeng Wang --- arch/x86/mm/init_32.c | 14 +- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index bd90b8fe81e4..523743ee9dea 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -238,11 +238,7 @@ page_table_range_init(unsigned long start, unsigned long end, pgd_t *pgd_base) } } -/* - * The already defines is_kernel_text, - * using '__' prefix not to get in conflict. - */ -static inline int __is_kernel_text(unsigned long addr) +static inline int is_x86_32_kernel_text(unsigned long addr) { if (addr >= (unsigned long)_text && addr <= (unsigned long)__init_end) return 1; @@ -333,8 +329,8 @@ kernel_physical_mapping_init(unsigned long start, addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1; - if (__is_kernel_text(addr) || - __is_kernel_text(addr2)) + if (is_x86_32_kernel_text(addr) || + is_x86_32_kernel_text(addr2)) prot = PAGE_KERNEL_LARGE_EXEC; pages_2m++; @@ -359,7 +355,7 @@ kernel_physical_mapping_init(unsigned long start, */ pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR); - if (__is_kernel_text(addr)) + if (is_x86_32_kernel_text(addr)) prot = PAGE_KERNEL_EXEC; pages_4k++; @@ -820,7 +816,7 @@ static void mark_nxdata_nx(void) */ unsigned long start = PFN_ALIGN(_etext); /* -* This comes from __is_kernel_text upper limit. Also HPAGE where used: +* This comes from is_x86_32_kernel_text upper limit. Also HPAGE where used: */ unsigned long size = (((unsigned long)__init_end + HPAGE_SIZE) & HPAGE_MASK) - start; -- 2.26.2
[PATCH v2] ibmveth: Use dma_alloc_coherent() instead of kmalloc/dma_map_single()
Replacing kmalloc/kfree/dma_map_single/dma_unmap_single() with dma_alloc_coherent/dma_free_coherent() helps to reduce code size, and simplify the code, and coherent DMA will not clear the cache every time. Signed-off-by: Cai Huoqing --- v1->v2: Remove extra change in Kconfig drivers/net/ethernet/ibm/ibmveth.c | 25 + 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 3d9b4f99d357..3aedb680adb8 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -605,17 +605,13 @@ static int ibmveth_open(struct net_device *netdev) } rc = -ENOMEM; - adapter->bounce_buffer = - kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); - if (!adapter->bounce_buffer) - goto out_free_irq; - adapter->bounce_buffer_dma = - dma_map_single(>vdev->dev, adapter->bounce_buffer, - netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); - if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) { - netdev_err(netdev, "unable to map bounce buffer\n"); - goto out_free_bounce_buffer; + adapter->bounce_buffer = dma_alloc_coherent(>vdev->dev, + netdev->mtu + IBMVETH_BUFF_OH, + >bounce_buffer_dma, GFP_KERNEL); + if (!adapter->bounce_buffer) { + netdev_err(netdev, "unable to alloc bounce buffer\n"); + goto out_free_irq; } netdev_dbg(netdev, "initial replenish cycle\n"); @@ -627,8 +623,6 @@ static int ibmveth_open(struct net_device *netdev) return 0; -out_free_bounce_buffer: - kfree(adapter->bounce_buffer); out_free_irq: free_irq(netdev->irq, netdev); out_free_buffer_pools: @@ -702,10 +696,9 @@ static int ibmveth_close(struct net_device *netdev) ibmveth_free_buffer_pool(adapter, >rx_buff_pool[i]); - dma_unmap_single(>vdev->dev, adapter->bounce_buffer_dma, -adapter->netdev->mtu + IBMVETH_BUFF_OH, -DMA_BIDIRECTIONAL); - kfree(adapter->bounce_buffer); + dma_free_coherent(>vdev->dev, + adapter->netdev->mtu + IBMVETH_BUFF_OH, + adapter->bounce_buffer, adapter->bounce_buffer_dma); netdev_dbg(netdev, "close complete\n"); -- 2.25.1
[PATCH] ibmveth: Use dma_alloc_coherent() instead of kmalloc/dma_map_single()
Replacing kmalloc/kfree/dma_map_single/dma_unmap_single() with dma_alloc_coherent/dma_free_coherent() helps to reduce code size, and simplify the code, and coherent DMA will not clear the cache every time. Signed-off-by: Cai Huoqing --- drivers/net/ethernet/ibm/Kconfig | 4 ++-- drivers/net/ethernet/ibm/ibmveth.c | 25 + 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/ibm/Kconfig b/drivers/net/ethernet/ibm/Kconfig index c0c112d95b89..926c0642784d 100644 --- a/drivers/net/ethernet/ibm/Kconfig +++ b/drivers/net/ethernet/ibm/Kconfig @@ -19,7 +19,7 @@ if NET_VENDOR_IBM config IBMVETH tristate "IBM LAN Virtual Ethernet support" - depends on PPC_PSERIES + depends on PPC_PSERIES || COMPILE_TEST help This driver supports virtual ethernet adapters on newer IBM iSeries and pSeries systems. @@ -40,7 +40,7 @@ config EHEA config IBMVNIC tristate "IBM Virtual NIC support" - depends on PPC_PSERIES + depends on PPC_PSERIES || COMPILE_TEST help This driver supports Virtual NIC adapters on IBM i and IBM System p systems. diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 3d9b4f99d357..3aedb680adb8 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -605,17 +605,13 @@ static int ibmveth_open(struct net_device *netdev) } rc = -ENOMEM; - adapter->bounce_buffer = - kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL); - if (!adapter->bounce_buffer) - goto out_free_irq; - adapter->bounce_buffer_dma = - dma_map_single(>vdev->dev, adapter->bounce_buffer, - netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL); - if (dma_mapping_error(dev, adapter->bounce_buffer_dma)) { - netdev_err(netdev, "unable to map bounce buffer\n"); - goto out_free_bounce_buffer; + adapter->bounce_buffer = dma_alloc_coherent(>vdev->dev, + netdev->mtu + IBMVETH_BUFF_OH, + >bounce_buffer_dma, GFP_KERNEL); + if (!adapter->bounce_buffer) { + netdev_err(netdev, "unable to alloc bounce buffer\n"); + goto out_free_irq; } netdev_dbg(netdev, "initial replenish cycle\n"); @@ -627,8 +623,6 @@ static int ibmveth_open(struct net_device *netdev) return 0; -out_free_bounce_buffer: - kfree(adapter->bounce_buffer); out_free_irq: free_irq(netdev->irq, netdev); out_free_buffer_pools: @@ -702,10 +696,9 @@ static int ibmveth_close(struct net_device *netdev) ibmveth_free_buffer_pool(adapter, >rx_buff_pool[i]); - dma_unmap_single(>vdev->dev, adapter->bounce_buffer_dma, -adapter->netdev->mtu + IBMVETH_BUFF_OH, -DMA_BIDIRECTIONAL); - kfree(adapter->bounce_buffer); + dma_free_coherent(>vdev->dev, + adapter->netdev->mtu + IBMVETH_BUFF_OH, + adapter->bounce_buffer, adapter->bounce_buffer_dma); netdev_dbg(netdev, "close complete\n"); -- 2.25.1