Re: [PATCH] ata: pata_rb532: Add OF support and make COMPILE_TESTable
On Tue, Apr 20, 2021 at 07:09:26PM +0300, Sergei Shtylyov wrote: > Hello! > > On 4/20/21 5:04 PM, Thomas Bogendoerfer wrote: > > > Add OF support for switching RB532 do device tree possible. > >I couldnb't parse that. :-) no wonder ;-) I'll rephrase in v2. > > > By removing > > the not needed asm/mach-rc32434/rb.h include the driver could be > > compile tested now. > > I think it's a separte issue worth its own patch. Jens, do you want this in an extra patch ? Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH v2 2/2] dt-bindings: interrupt-controller: Add IDT 79RC3243x Interrupt Controller
Document DT bindings for IDT 79RC3243x Interrupt Controller. Signed-off-by: Thomas Bogendoerfer --- .../interrupt-controller/idt,3243x-pic.yaml | 48 +++ 1 file changed, 48 insertions(+) create mode 100644 Documentation/devicetree/bindings/interrupt-controller/idt,3243x-pic.yaml diff --git a/Documentation/devicetree/bindings/interrupt-controller/idt,3243x-pic.yaml b/Documentation/devicetree/bindings/interrupt-controller/idt,3243x-pic.yaml new file mode 100644 index ..6a1c5ac75f1a --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/idt,3243x-pic.yaml @@ -0,0 +1,48 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/idt,3243x-pic.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79RC3243x Interrupt Controller Device Tree Bindings + +maintainers: + - Thomas Bogendoerfer + +allOf: + - $ref: /schemas/interrupt-controller.yaml# + +properties: + "#interrupt-cells": +const: 1 + + compatible: +const: idt,3243x-pci + + reg: +maxItems: 1 + + interrupt-controller: true + +required: + - "#interrupt-cells" + - compatible + - reg + - interrupt-controller + +additionalProperties: false + +examples: + - | +idtpic3: interrupt-controller@3800c { +compatible = "idt,rc3243x-pic"; +reg = <0x3800c 0x0c>; + +interrupt-controller; +#interrupt-cells = <1>; + +interrupt-parent = <>; +interrupts = <3>; +}; + +... -- 2.29.2
[PATCH v2 1/2] irqchip: Add support for IDT 79rc3243x interrupt controller
IDT 79rc3243x SoCs have rather simple interrupt controllers connected to the MIPS CPU interrupt lines. Each of them has room for up to 32 interrupts. Signed-off-by: Thomas Bogendoerfer --- drivers/irqchip/Kconfig| 5 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-idt3243x.c | 124 + 3 files changed, 130 insertions(+) create mode 100644 drivers/irqchip/irq-idt3243x.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index e74fa206240a..55562b36bf3c 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -586,4 +586,9 @@ config MST_IRQ help Support MStar Interrupt Controller. +config IRQ_IDT3243X + bool + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c59b95a0532c..341891443eec 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -113,3 +113,4 @@ obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o obj-$(CONFIG_SL28CPLD_INTC)+= irq-sl28cpld.o obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o +obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o diff --git a/drivers/irqchip/irq-idt3243x.c b/drivers/irqchip/irq-idt3243x.c new file mode 100644 index ..61caf21ef46c --- /dev/null +++ b/drivers/irqchip/irq-idt3243x.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for IDT/Renesas 79RC3243x Interrupt Controller. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#define IDT_PIC_NR_IRQS32 + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +struct idt_pic_data { + void __iomem *base; + struct irq_domain *irq_domain; + struct irq_chip_generic *gc; +}; + +static void idt_irq_dispatch(struct irq_desc *desc) +{ + struct idt_pic_data *idtpic = irq_desc_get_handler_data(desc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + u32 pending, hwirq, virq; + + chained_irq_enter(host_chip, desc); + + pending = irq_reg_readl(idtpic->gc, IDT_PIC_IRQ_PEND); + pending &= ~idtpic->gc->mask_cache; + while (pending) { + hwirq = __fls(pending); + virq = irq_linear_revmap(idtpic->irq_domain, hwirq); + if (virq) + generic_handle_irq(virq); + pending &= ~(1 << hwirq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_pic_init(struct device_node *of_node, struct device_node *parent) +{ + struct irq_domain *domain; + struct idt_pic_data *idtpic; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int parent_irq; + int ret = 0; + + idtpic = kzalloc(sizeof(*idtpic), GFP_KERNEL); + if (!idtpic) { + ret = -ENOMEM; + goto out_err; + } + + parent_irq = irq_of_parse_and_map(of_node, 0); + if (!parent_irq) { + pr_err("Failed to map parent IRQ!\n"); + ret = -EINVAL; + goto out_free; + } + + idtpic->base = of_iomap(of_node, 0); + if (!idtpic->base) { + pr_err("Failed to map base address!\n"); + ret = -ENOMEM; + goto out_unmap_irq; + } + + domain = irq_domain_add_linear(of_node, IDT_PIC_NR_IRQS, + _generic_chip_ops, NULL); + if (!domain) { + pr_err("Failed to add irqdomain!\n"); + ret = -ENOMEM; + goto out_iounmap; + } + idtpic->irq_domain = domain; + + ret = irq_alloc_domain_generic_chips(domain, 32, 1, "IDTPIC", +handle_level_irq, 0, +IRQ_NOPROBE | IRQ_LEVEL, 0); + if (ret) + goto out_domain_remove; + + gc = irq_get_domain_generic_chip(domain, 0); + gc->reg_base = idtpic->base; + gc->private = idtpic; + + ct = gc->chip_types; + ct->regs.mask = IDT_PIC_IRQ_MASK; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + idtpic->gc = gc; + + /* Mask interrupts. */ + writel(0x, idtpic->base + IDT_PIC_IRQ_MASK); + gc->mask_cache = 0x; + + irq_set_chained_handler_and_data(parent_irq, +idt_irq_dispatch, idtpic); + + return 0; + +out_domain_remove: + irq_domain_remove(domain); +out_iounmap: + iounmap(idtpic->base); +out_unmap_irq: + irq_dispose_mapping(parent_irq); +
Re: [PATCH] irqchip: Add support for IDT 79rc3243x interrupt controller
On Tue, Apr 20, 2021 at 06:34:59PM +0100, Marc Zyngier wrote: > On 2021-04-20 13:34, Thomas Bogendoerfer wrote: > > IDT 79rc3243x SoCs have rather simple interrupt controllers connected > > to the MIPS CPU interrupt lines. Each of them has room for up to > > 32 interrupts. > > > > Signed-off-by: Thomas Bogendoerfer > > Is there a DT binding for this irqchip? The code looks fine, but > it'd be good if the binding was merged at the same time as the driver. I'll write one and send a v2. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH] ata: pata_rb532: Add OF support and make COMPILE_TESTable
Add OF support for switching RB532 do device tree possible. By removing the not needed asm/mach-rc32434/rb.h include the driver could be compile tested now. Signed-off-by: Thomas Bogendoerfer --- drivers/ata/Kconfig | 2 +- drivers/ata/pata_rb532_cf.c | 11 +-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 030cb32da980..53f40f92e4eb 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1139,7 +1139,7 @@ config PATA_QDI config PATA_RB532 tristate "RouterBoard 532 PATA CompactFlash support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST help This option enables support for the RouterBoard 532 PATA CompactFlash controller. diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 479c4b29b856..93d839ab9654 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -28,8 +28,6 @@ #include #include -#include - #define DRV_NAME "pata-rb532-cf" #define DRV_VERSION"0.1.0" #define DRV_DESC "PATA driver for RouterBOARD 532 Compact Flash" @@ -164,11 +162,20 @@ static int rb532_pata_driver_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id pata_rb532_match[] = { + { .compatible = "mikrotik,rb532-pata", }, + { } +}; +MODULE_DEVICE_TABLE(of, pata_rb532_match); +#endif + static struct platform_driver rb532_pata_platform_driver = { .probe = rb532_pata_driver_probe, .remove = rb532_pata_driver_remove, .driver = { .name = DRV_NAME, + .of_match_table = of_match_ptr(pata_rb532_match), }, }; -- 2.29.2
[PATCH 2/2] dt-bindings: gpio: Add devicetree binding for IDT 79RC3243x GPIO controller
Add YAML devicetree binding for IDT 79RC3243x GPIO controller Signed-off-by: Thomas Bogendoerfer --- .../bindings/gpio/gpio-idt3243x.yaml | 73 +++ 1 file changed, 73 insertions(+) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-idt3243x.yaml diff --git a/Documentation/devicetree/bindings/gpio/gpio-idt3243x.yaml b/Documentation/devicetree/bindings/gpio/gpio-idt3243x.yaml new file mode 100644 index ..346a57ef8298 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-idt3243x.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/gpio-idt3243x.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79RC32434x GPIO controller + +maintainers: + - Thomas Bogendoerfer + +properties: + compatible: +const: idt,3243x-gpio + + reg: +maxItems: 2 + + reg-names: +items: + - const: gpio + - const: pic + + gpio-controller: true + + "#gpio-cells": +const: 2 + + ngpios: +description: + Number of available gpios in a bank. +minimum: 1 +maximum: 32 + + interrupt-controller: true + + "#interrupt-cells": +const: 2 + + interrupts: +maxItems: 1 + +required: + - compatible + - reg + - reg-names + - gpio-controller + - "#gpio-cells" + - ngpios + - interrupt-controller + - "#interrupt-cells" + - interrupts + +additionalProperties: false + +examples: + - | +gpio0: interrupt-controller@5 { +compatible = "idt,3243x-gpio"; +reg = <0x5 0x14>, <0x38030 0x0c>; +reg-names = "gpio", "pic"; + +interrupt-controller; +#interrupt-cells = <2>; + +interrupt-parent = <>; +interrupts = <6>; + +gpio-controller; +#gpio-cells = <2>; + +ngpios = <14>; +}; -- 2.29.2
[PATCH 1/2] gpio: Add support for IDT 79RC3243x GPIO controller
IDT 79RC3243x SoCs integrated a gpio controller, which handles up to 32 gpios. All gpios could be used as interrupt source. Signed-off-by: Thomas Bogendoerfer --- drivers/gpio/Kconfig | 10 ++ drivers/gpio/Makefile| 1 + drivers/gpio/gpio-idt3243x.c | 210 +++ 3 files changed, 221 insertions(+) create mode 100644 drivers/gpio/gpio-idt3243x.c diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e3607ec4c2e8..6847a06ffcfe 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -770,6 +770,16 @@ config GPIO_MSC313 Say Y here to support the main GPIO block on MStar/SigmaStar ARMv7 based SoCs. +config GPIO_IDT3243X + bool "IDT 79RC3243X GPIO support" + default y if MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST + select GPIO_GENERIC + select GPIOLIB_IRQCHIP + help + Select this option to enable GPIO driver for + IDT 79RC3243X SoC devices. + endmenu menu "Port-mapped I/O GPIO drivers" diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c58a90a3c3b1..75dd9c5665c5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -67,6 +67,7 @@ obj-$(CONFIG_GPIO_HISI) += gpio-hisi.o obj-$(CONFIG_GPIO_HLWD)+= gpio-hlwd.o obj-$(CONFIG_HTC_EGPIO)+= gpio-htc-egpio.o obj-$(CONFIG_GPIO_ICH) += gpio-ich.o +obj-$(CONFIG_GPIO_IDT3243X)+= gpio-idt3243x.o obj-$(CONFIG_GPIO_IOP) += gpio-iop.o obj-$(CONFIG_GPIO_IT87)+= gpio-it87.o obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o diff --git a/drivers/gpio/gpio-idt3243x.c b/drivers/gpio/gpio-idt3243x.c new file mode 100644 index ..eaee46480268 --- /dev/null +++ b/drivers/gpio/gpio-idt3243x.c @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for IDT/Renesas 79RC3243x Interrupt Controller. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#define IDT_GPIO_NR_IRQS 32 + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +#define IDT_GPIO_DIR 0x04 +#define IDT_GPIO_DATA 0x08 +#define IDT_GPIO_ILEVEL0x0C +#define IDT_GPIO_ISTAT 0x10 + +struct idt_gpio_ctrl { + struct gpio_chip gc; + void __iomem *pic; + void __iomem *gpio; + u32 mask_cache; +}; + +static struct idt_gpio_ctrl *irq_data_to_idt_gpio(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + + return container_of(gc, struct idt_gpio_ctrl, gc); +} + +static void idt_gpio_dispatch(struct irq_desc *desc) +{ + struct gpio_chip *gc = irq_desc_get_handler_data(desc); + struct idt_gpio_ctrl *ctrl = container_of(gc, struct idt_gpio_ctrl, gc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + u32 pending, hwirq, virq; + + chained_irq_enter(host_chip, desc); + + pending = readl(ctrl->pic + IDT_PIC_IRQ_PEND); + pending &= ~ctrl->mask_cache; + while (pending) { + hwirq = __fls(pending); + virq = irq_linear_revmap(gc->irq.domain, hwirq); + if (virq) + generic_handle_irq(virq); + pending &= ~(1 << hwirq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + struct idt_gpio_ctrl *ctrl = irq_data_to_idt_gpio(d); + unsigned int sense = flow_type & IRQ_TYPE_SENSE_MASK; + u32 ilevel; + + if (sense & ~(IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) + return -EINVAL; + + ilevel = readl(ctrl->gpio + IDT_GPIO_ILEVEL); + if (sense & IRQ_TYPE_LEVEL_HIGH) + ilevel |= BIT(d->hwirq); + else if (sense & IRQ_TYPE_LEVEL_LOW) + ilevel &= ~BIT(d->hwirq); + else + return -EINVAL; + + writel(ilevel, ctrl->gpio + IDT_GPIO_ILEVEL); + return 0; +} + +static void idt_gpio_ack(struct irq_data *d) +{ + struct idt_gpio_ctrl *ctrl = irq_data_to_idt_gpio(d); + + writel(~BIT(d->hwirq), ctrl->gpio + IDT_GPIO_ISTAT); +} + +static void idt_gpio_mask(struct irq_data *d) +{ + struct idt_gpio_ctrl *ctrl = irq_data_to_idt_gpio(d); + + ctrl->mask_cache |= BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); +} + +static void idt_gpio_unmask(struct irq_data *d) +{ + struct idt_gpio_ctrl *ctrl = irq_data_to_idt_gpio(d); + + ctrl->mask_cache &= ~BIT(d->hwirq); + writel(ctrl->mask_cache, ctrl->pic + IDT_PIC_IRQ_MASK); +} + +static struct irq_chip idt_gpio_irqchip = { + .name
[PATCH] irqchip: Add support for IDT 79rc3243x interrupt controller
IDT 79rc3243x SoCs have rather simple interrupt controllers connected to the MIPS CPU interrupt lines. Each of them has room for up to 32 interrupts. Signed-off-by: Thomas Bogendoerfer --- drivers/irqchip/Kconfig| 5 ++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-idt3243x.c | 124 + 3 files changed, 130 insertions(+) create mode 100644 drivers/irqchip/irq-idt3243x.c diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index e74fa206240a..55562b36bf3c 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -586,4 +586,9 @@ config MST_IRQ help Support MStar Interrupt Controller. +config IRQ_IDT3243X + bool + select GENERIC_IRQ_CHIP + select IRQ_DOMAIN + endmenu diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c59b95a0532c..341891443eec 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -113,3 +113,4 @@ obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o obj-$(CONFIG_SL28CPLD_INTC)+= irq-sl28cpld.o obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o +obj-$(CONFIG_IRQ_IDT3243X) += irq-idt3243x.o diff --git a/drivers/irqchip/irq-idt3243x.c b/drivers/irqchip/irq-idt3243x.c new file mode 100644 index ..61caf21ef46c --- /dev/null +++ b/drivers/irqchip/irq-idt3243x.c @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Driver for IDT/Renesas 79RC3243x Interrupt Controller. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#define IDT_PIC_NR_IRQS32 + +#define IDT_PIC_IRQ_PEND 0x00 +#define IDT_PIC_IRQ_MASK 0x08 + +struct idt_pic_data { + void __iomem *base; + struct irq_domain *irq_domain; + struct irq_chip_generic *gc; +}; + +static void idt_irq_dispatch(struct irq_desc *desc) +{ + struct idt_pic_data *idtpic = irq_desc_get_handler_data(desc); + struct irq_chip *host_chip = irq_desc_get_chip(desc); + u32 pending, hwirq, virq; + + chained_irq_enter(host_chip, desc); + + pending = irq_reg_readl(idtpic->gc, IDT_PIC_IRQ_PEND); + pending &= ~idtpic->gc->mask_cache; + while (pending) { + hwirq = __fls(pending); + virq = irq_linear_revmap(idtpic->irq_domain, hwirq); + if (virq) + generic_handle_irq(virq); + pending &= ~(1 << hwirq); + } + + chained_irq_exit(host_chip, desc); +} + +static int idt_pic_init(struct device_node *of_node, struct device_node *parent) +{ + struct irq_domain *domain; + struct idt_pic_data *idtpic; + struct irq_chip_generic *gc; + struct irq_chip_type *ct; + unsigned int parent_irq; + int ret = 0; + + idtpic = kzalloc(sizeof(*idtpic), GFP_KERNEL); + if (!idtpic) { + ret = -ENOMEM; + goto out_err; + } + + parent_irq = irq_of_parse_and_map(of_node, 0); + if (!parent_irq) { + pr_err("Failed to map parent IRQ!\n"); + ret = -EINVAL; + goto out_free; + } + + idtpic->base = of_iomap(of_node, 0); + if (!idtpic->base) { + pr_err("Failed to map base address!\n"); + ret = -ENOMEM; + goto out_unmap_irq; + } + + domain = irq_domain_add_linear(of_node, IDT_PIC_NR_IRQS, + _generic_chip_ops, NULL); + if (!domain) { + pr_err("Failed to add irqdomain!\n"); + ret = -ENOMEM; + goto out_iounmap; + } + idtpic->irq_domain = domain; + + ret = irq_alloc_domain_generic_chips(domain, 32, 1, "IDTPIC", +handle_level_irq, 0, +IRQ_NOPROBE | IRQ_LEVEL, 0); + if (ret) + goto out_domain_remove; + + gc = irq_get_domain_generic_chip(domain, 0); + gc->reg_base = idtpic->base; + gc->private = idtpic; + + ct = gc->chip_types; + ct->regs.mask = IDT_PIC_IRQ_MASK; + ct->chip.irq_mask = irq_gc_mask_set_bit; + ct->chip.irq_unmask = irq_gc_mask_clr_bit; + idtpic->gc = gc; + + /* Mask interrupts. */ + writel(0x, idtpic->base + IDT_PIC_IRQ_MASK); + gc->mask_cache = 0x; + + irq_set_chained_handler_and_data(parent_irq, +idt_irq_dispatch, idtpic); + + return 0; + +out_domain_remove: + irq_domain_remove(domain); +out_iounmap: + iounmap(idtpic->base); +out_unmap_irq: + irq_dispose_mapping(parent_irq); +
Re: build failure of malta_qemu_32r6_defconfig
On Sun, Apr 18, 2021 at 12:01:36AM +0100, Sudip Mukherjee wrote: > Hi Thomas, > > On Fri, Apr 9, 2021 at 1:17 PM Thomas Bogendoerfer > wrote: > > > > On Thu, Apr 08, 2021 at 09:42:11AM +0800, YunQiang Su wrote: > > > Sudip Mukherjee 于2021年4月8日周四 上午2:26写道: > > > > > > > > Hi Thomas, > > > > > > > > I was building v5.10.28 with malta_qemu_32r6_defconfig and noticed that > > > > it fails to build, so tried next-20210407 to see if it has been fixed. > > > > But linux-next also has the issue with gcc-10. > > > > > > > > The error is: > > > > > > > > ./arch/mips/include/asm/vdso/gettimeofday.h: In function > > > > '__vdso_clock_gettime': > > > > ./arch/mips/include/asm/vdso/gettimeofday.h:103:2: error: the register > > > > 'lo' cannot be clobbered in 'asm' for the current target > > > > 103 | asm volatile( > > > > | ^~~ > > > > > > this operation try to save lo and hi register, while they are not > > > exisiting on r6. > > > We are working on figure out a patch for it. > > > > looks like there is already a patch in patchwork, which just needs > > a workup: > > > > https://patchwork.kernel.org/project/linux-mips/patch/20200801154401.4177009-1-romain.na...@gmail.com/ > > Looks like there has been no response to it since last 8 months. Do > you want me to respin it and send a proper patch? that would me fantastic and much appreciated :-) Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH v6 net-next 09/10] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 249 -- 2 files changed, 239 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index c059b4bd3f23..453d202a28c1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 19f226428f89..4878e527e3c8 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -59,18 +59,244 @@ #include #include -#include -#include -#include -#include - -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x000f +#
[PATCH v6 net-next 10/10] dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs
Add device tree bindings for ethernet controller integrated into IDT 79RC3243x SoCs. Signed-off-by: Thomas Bogendoerfer --- .../bindings/net/idt,3243x-emac.yaml | 73 +++ 1 file changed, 73 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml diff --git a/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml new file mode 100644 index ..11ffc306dd54 --- /dev/null +++ b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/idt,3243x-emac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79rc3243x Ethernet controller + +description: Ethernet controller integrated into IDT 79RC3243x family SoCs + +maintainers: + - Thomas Bogendoerfer + +allOf: + - $ref: ethernet-controller.yaml# + +properties: + compatible: +const: idt,3243x-emac + + reg: +maxItems: 3 + + reg-names: +items: + - const: emac + - const: dma_rx + - const: dma_tx + + interrupts: +items: + - description: RX interrupt + - description: TX interrupt + + interrupt-names: +items: + - const: rx + - const: tx + + clocks: +maxItems: 1 + + clock-names: +items: + - const: mdioclk + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + +ethernet@6 { +compatible = "idt,3243x-emac"; + +reg = <0x6 0x1>, + <0x4 0x14>, + <0x40014 0x14>; +reg-names = "emac", "dma_rx", "dma_tx"; + +interrupt-parent = <>; +interrupts = <0>, <1>; +interrupt-names = "rx", "tx"; + +clocks = <>; +clock-names = "mdioclk"; +}; -- 2.29.2
[PATCH v6 net-next 08/10] net: korina: Get mdio input clock via common clock framework
With device tree clock is provided via CCF. For non device tree use a maximum clock value to not overclock the PHY. The non device tree usage will go away after platform is converted to DT. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index a1f53d7753ae..19f226428f89 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -57,14 +57,13 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -146,10 +145,9 @@ struct korina_private { struct work_struct restart_task; struct net_device *dev; struct device *dmadev; + int mii_clock_freq; }; -extern unsigned int idt_cpu_freq; - static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) { return lp->td_dma + (idx * sizeof(struct dma_desc)); @@ -899,8 +897,8 @@ static int korina_init(struct net_device *dev) /* Management Clock Prescaler Divisor * Clock independent setting */ - writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, - >eth_regs->ethmcp); + writel(((lp->mii_clock_freq) / MII_CLOCK + 1) & ~1, + >eth_regs->ethmcp); writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ @@ -1060,6 +1058,7 @@ static int korina_probe(struct platform_device *pdev) u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; + struct clk *clk; void __iomem *p; int rc; @@ -1075,6 +1074,16 @@ static int korina_probe(struct platform_device *pdev) else if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr) < 0) eth_hw_addr_random(dev); + clk = devm_clk_get_optional(>dev, "mdioclk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + if (clk) { + clk_prepare_enable(clk); + lp->mii_clock_freq = clk_get_rate(clk); + } else { + lp->mii_clock_freq = 2; /* max possible input clk */ + } + lp->rx_irq = platform_get_irq_byname(pdev, "rx"); lp->tx_irq = platform_get_irq_byname(pdev, "tx"); -- 2.29.2
[PATCH v6 net-next 06/10] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 44fad9e924ca..d6dbbdd43d7c 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1055,7 +1055,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1068,8 +1068,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1123,6 +1122,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1140,9 +1141,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH v6 net-next 05/10] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 158 +- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 955fe3d3da06..44fad9e924ca 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -110,10 +110,15 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; + dma_addr_t rx_skb_dma[KORINA_NUM_RDS]; + dma_addr_t tx_skb_dma[KORINA_NUM_TDS]; + int rx_next_done; int rx_chain_head; int rx_chain_tail; @@ -138,10 +143,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -176,14 +192,17 @@ static void korina_abort_rx(struct net_device *dev) static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); - unsigned long flags; - u32 length; u32 chain_prev, chain_next; + unsigned long flags; struct dma_desc *td; + dma_addr_t ca; + u32 length; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -191,26 +210,26 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, ca)) + goto drop_packet; + + lp->tx_skb_dma[idx] = ca; + td->ca = ca; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -220,8 +239,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -232,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next;
[PATCH v6 net-next 07/10] net: korina: Add support for device tree
If there is no mac address passed via platform data try to get it via device tree and fall back to a random mac address, if all fail. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 20 +--- drivers/net/ethernet/korina.c | 32 +--- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index 5fc3c8ee4f31..04684990e28e 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -58,37 +58,27 @@ EXPORT_SYMBOL(get_latch_u5); static struct resource korina_dev0_res[] = { { - .name = "korina_regs", + .name = "emac", .start = ETH0_BASE_ADDR, .end = ETH0_BASE_ADDR + sizeof(struct eth_regs), .flags = IORESOURCE_MEM, }, { - .name = "korina_rx", + .name = "rx", .start = ETH0_DMA_RX_IRQ, .end = ETH0_DMA_RX_IRQ, .flags = IORESOURCE_IRQ }, { - .name = "korina_tx", + .name = "tx", .start = ETH0_DMA_TX_IRQ, .end = ETH0_DMA_TX_IRQ, .flags = IORESOURCE_IRQ }, { - .name = "korina_ovr", - .start = ETH0_RX_OVR_IRQ, - .end = ETH0_RX_OVR_IRQ, - .flags = IORESOURCE_IRQ - }, { - .name = "korina_und", - .start = ETH0_TX_UND_IRQ, - .end = ETH0_TX_UND_IRQ, - .flags = IORESOURCE_IRQ - }, { - .name = "korina_dma_rx", + .name = "dma_rx", .start = ETH0_RX_DMA_ADDR, .end = ETH0_RX_DMA_ADDR + DMA_CHAN_OFFSET - 1, .flags = IORESOURCE_MEM, }, { - .name = "korina_dma_tx", + .name = "dma_tx", .start = ETH0_TX_DMA_ADDR, .end = ETH0_TX_DMA_ADDR + DMA_CHAN_OFFSET - 1, .flags = IORESOURCE_MEM, diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index d6dbbdd43d7c..a1f53d7753ae 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -1068,26 +1070,29 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + if (mac_addr) + ether_addr_copy(dev->dev_addr, mac_addr); + else if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr) < 0) + eth_hw_addr_random(dev); - lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); - lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); + lp->rx_irq = platform_get_irq_byname(pdev, "rx"); + lp->tx_irq = platform_get_irq_byname(pdev, "tx"); - p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + p = devm_platform_ioremap_resource_byname(pdev, "emac"); if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); return -ENOMEM; } lp->eth_regs = p; - p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + p = devm_platform_ioremap_resource_byname(pdev, "dma_rx"); if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); return -ENOMEM; } lp->rx_dma_regs = p; - p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + p = devm_platform_ioremap_resource_byname(pdev, "dma_tx"); if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); return -ENOMEM; @@ -1148,8 +1153,21 @@ static int korina_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id korina_match[] = { + { + .compatible = "idt,3243x-emac", + }, + { } +}; +MODULE_DEVICE_TABLE(of, korina_match); +#endif + static struct platform_driver korina_driver = { - .driver.name = "korina", + .driver = { + .name = "korina", + .of_match_table = of_match_ptr(korina_match), + }, .probe = korina_probe, .remove = korina_remove, }; -- 2.29.2
[PATCH v6 net-next 04/10] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index c7abb4a8dd37..955fe3d3da06 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -142,12 +142,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -164,11 +158,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -183,18 +172,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -463,7 +440,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -840,7 +817,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH v6 net-next 03/10] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index b56de01f6bb8..c7abb4a8dd37 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -231,7 +231,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -284,7 +283,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -373,8 +371,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -453,7 +449,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -468,7 +463,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH v6 net-next 02/10] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 1b7e1c75ed9e..b56de01f6bb8 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -105,9 +105,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1044,10 +1044,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1060,36 +1060,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1119,7 +1113,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1127,20 +1122,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1148,13 +1130,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH v6 net-next 01/10] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/korina.c | 56 +++ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c059b4bd3f23 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -98,6 +98,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 + select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..1b7e1c75ed9e 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +292,48 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + u32 value; + + return readl_poll_timeout_atomic(>eth_regs->miimind, +value, value & ETH_MII_IND_BSY, +1, 1000); +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); - ret = (int)(readl(>eth_regs->miimrdd)); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; + + if (readl(>eth_regs->miimind) & ETH_MII_IND_NV) + return -EINVAL; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +659,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +885,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1108,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH v6 net-next 00/10] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up and adds support for device tree. Changes in v6: - remove korina from resource names and adapt DT binding to it - removed superfluous braces around of_get_mac_address Changes in v5: - fixed email address in binding document, which prevented sending it Changes in v4: - improve error returns in mdio_read further - added clock name and improved clk handling - fixed binding errors Changes in v3: - use readl_poll_timeout_atomic in mdio_wait - return -ETIMEDOUT, if mdio_wait failed - added DT binding and changed name to idt,3243x-emac - fixed usage of of_get_mac_address for net-next Changes in v2: - added device tree support to get rid of idt_cpu_freq - fixed compile test on 64bit archs - fixed descriptor current address handling by storing/using mapped dma addresses (dma controller modifies current address) Thomas Bogendoerfer (10): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Add support for device tree net: korina: Get mdio input clock via common clock framework net: korina: Make driver COMPILE_TESTable dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs .../bindings/net/idt,3243x-emac.yaml | 73 +++ arch/mips/rb532/devices.c | 25 +- drivers/net/ethernet/Kconfig | 3 +- drivers/net/ethernet/korina.c | 603 +- 4 files changed, 515 insertions(+), 189 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml -- 2.29.2
Re: [PATCH v5 net-next 10/10] dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs
On Fri, Apr 16, 2021 at 12:29:46PM +0300, Sergei Shtylyov wrote: > On 16.04.2021 11:52, Thomas Bogendoerfer wrote: > > > Add device tree bindings for ethernet controller integrated into > > IDT 79RC3243x SoCs. > > > > Signed-off-by: Thomas Bogendoerfer > > --- > > .../bindings/net/idt,3243x-emac.yaml | 74 +++ > > 1 file changed, 74 insertions(+) > > create mode 100644 > > Documentation/devicetree/bindings/net/idt,3243x-emac.yaml > > > > diff --git a/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml > > b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml > > new file mode 100644 > > index ..3697af5cb66f > > --- /dev/null > > +++ b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml > > @@ -0,0 +1,74 @@ > > +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause > > +%YAML 1.2 > > +--- > > +$id: http://devicetree.org/schemas/net/idt,3243x-emac.yaml# > > +$schema: http://devicetree.org/meta-schemas/core.yaml# > > + > > +title: IDT 79rc3243x Ethernet controller > > + > > +description: Ethernet controller integrated into IDT 79RC3243x family SoCs > > + > > +maintainers: > > + - Thomas Bogendoerfer > > + > > +allOf: > > + - $ref: ethernet-controller.yaml# > > + > > +properties: > > + compatible: > > +const: idt,3243x-emac > > + > > + reg: > > +maxItems: 3 > > + > > + reg-names: > > +items: > > + - const: korina_regs > > + - const: korina_dma_rx > > + - const: korina_dma_tx > > + > > + interrupts: > > +items: > > + - description: RX interrupt > > + - description: TX interrupt > > + > > + interrupt-names: > > +items: > > + - const: korina_rx > > + - const: korina_tx > > + > > + clocks: > > +maxItems: 1 > > + > > + clock-names: > > +items: > > + - const: mdioclk > > + > > +required: > > + - compatible > > + - reg > > + - reg-names > > + - interrupts > > + - interrupt-names > > + > > +additionalProperties: false > > + > > +examples: > > + - | > > + > > +ethernet@6 { > > +compatible = "idt,3243x-emac"; > > + > > +reg = <0x6 0x1>, > > + <0x4 0x14>, > > + <0x40014 0x14>; > > +reg-names = "korina_regs", > > +"korina_dma_rx", > > +"korina_dma_tx"; > > + > > +interrupts-extended = < 0>, < 1>; > >You use this prop, yet don't describe it? that's just interrupt-parent and interrupts in one statement. And since make dt_binding_check didn't complained I thought that's good this way. Rob, do I need to describe interrupts-extended as well ? I could change that to interrupt-parent/interrupts as the driver no longer uses dma under/overrun interrupts, which have a different interrupt-parent. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH v5 net-next 09/10] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 249 -- 2 files changed, 239 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index c059b4bd3f23..453d202a28c1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index e95c8d87d893..5f39a5bba531 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -59,18 +59,244 @@ #include #include -#include -#include -#include -#include - -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x000f +#
[PATCH v5 net-next 10/10] dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs
Add device tree bindings for ethernet controller integrated into IDT 79RC3243x SoCs. Signed-off-by: Thomas Bogendoerfer --- .../bindings/net/idt,3243x-emac.yaml | 74 +++ 1 file changed, 74 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml diff --git a/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml new file mode 100644 index ..3697af5cb66f --- /dev/null +++ b/Documentation/devicetree/bindings/net/idt,3243x-emac.yaml @@ -0,0 +1,74 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/idt,3243x-emac.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IDT 79rc3243x Ethernet controller + +description: Ethernet controller integrated into IDT 79RC3243x family SoCs + +maintainers: + - Thomas Bogendoerfer + +allOf: + - $ref: ethernet-controller.yaml# + +properties: + compatible: +const: idt,3243x-emac + + reg: +maxItems: 3 + + reg-names: +items: + - const: korina_regs + - const: korina_dma_rx + - const: korina_dma_tx + + interrupts: +items: + - description: RX interrupt + - description: TX interrupt + + interrupt-names: +items: + - const: korina_rx + - const: korina_tx + + clocks: +maxItems: 1 + + clock-names: +items: + - const: mdioclk + +required: + - compatible + - reg + - reg-names + - interrupts + - interrupt-names + +additionalProperties: false + +examples: + - | + +ethernet@6 { +compatible = "idt,3243x-emac"; + +reg = <0x6 0x1>, + <0x4 0x14>, + <0x40014 0x14>; +reg-names = "korina_regs", +"korina_dma_rx", +"korina_dma_tx"; + +interrupts-extended = < 0>, < 1>; +interrupt-names = "korina_rx", "korina_tx"; + +clocks = <>; +clock-names = "mdioclk"; +}; -- 2.29.2
[PATCH v5 net-next 07/10] net: korina: Add support for device tree
If there is no mac address passed via platform data try to get it via device tree and fall back to a random mac address, if all fail. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 24 ++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index d6dbbdd43d7c..cd078a5c679b 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -1068,7 +1070,12 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + if (mac_addr) { + ether_addr_copy(dev->dev_addr, mac_addr); + } else { + if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr)) + eth_hw_addr_random(dev); + } lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1148,8 +1155,21 @@ static int korina_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id korina_match[] = { + { + .compatible = "idt,3243x-emac", + }, + { } +}; +MODULE_DEVICE_TABLE(of, korina_match); +#endif + static struct platform_driver korina_driver = { - .driver.name = "korina", + .driver = { + .name = "korina", + .of_match_table = of_match_ptr(korina_match), + }, .probe = korina_probe, .remove = korina_remove, }; -- 2.29.2
[PATCH v5 net-next 06/10] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 44fad9e924ca..d6dbbdd43d7c 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1055,7 +1055,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1068,8 +1068,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1123,6 +1122,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1140,9 +1141,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH v5 net-next 08/10] net: korina: Get mdio input clock via common clock framework
With device tree clock is provided via CCF. For non device tree use a maximum clock value to not overclock the PHY. The non device tree usage will go away after platform is converted to DT. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index cd078a5c679b..e95c8d87d893 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -57,14 +57,13 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -146,10 +145,9 @@ struct korina_private { struct work_struct restart_task; struct net_device *dev; struct device *dmadev; + int mii_clock_freq; }; -extern unsigned int idt_cpu_freq; - static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) { return lp->td_dma + (idx * sizeof(struct dma_desc)); @@ -899,8 +897,8 @@ static int korina_init(struct net_device *dev) /* Management Clock Prescaler Divisor * Clock independent setting */ - writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, - >eth_regs->ethmcp); + writel(((lp->mii_clock_freq) / MII_CLOCK + 1) & ~1, + >eth_regs->ethmcp); writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ @@ -1060,6 +1058,7 @@ static int korina_probe(struct platform_device *pdev) u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; + struct clk *clk; void __iomem *p; int rc; @@ -1077,6 +1076,16 @@ static int korina_probe(struct platform_device *pdev) eth_hw_addr_random(dev); } + clk = devm_clk_get_optional(>dev, "mdioclk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + if (clk) { + clk_prepare_enable(clk); + lp->mii_clock_freq = clk_get_rate(clk); + } else { + lp->mii_clock_freq = 2; /* max possible input clk */ + } + lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); -- 2.29.2
[PATCH v5 net-next 05/10] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 158 +- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 955fe3d3da06..44fad9e924ca 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -110,10 +110,15 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; + dma_addr_t rx_skb_dma[KORINA_NUM_RDS]; + dma_addr_t tx_skb_dma[KORINA_NUM_TDS]; + int rx_next_done; int rx_chain_head; int rx_chain_tail; @@ -138,10 +143,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -176,14 +192,17 @@ static void korina_abort_rx(struct net_device *dev) static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); - unsigned long flags; - u32 length; u32 chain_prev, chain_next; + unsigned long flags; struct dma_desc *td; + dma_addr_t ca; + u32 length; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -191,26 +210,26 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, ca)) + goto drop_packet; + + lp->tx_skb_dma[idx] = ca; + td->ca = ca; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -220,8 +239,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -232,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next;
[PATCH v5 net-next 04/10] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index c7abb4a8dd37..955fe3d3da06 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -142,12 +142,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -164,11 +158,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -183,18 +172,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -463,7 +440,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -840,7 +817,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH v5 net-next 02/10] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 1b7e1c75ed9e..b56de01f6bb8 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -105,9 +105,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1044,10 +1044,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1060,36 +1060,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1119,7 +1113,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1127,20 +1122,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1148,13 +1130,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH v5 net-next 03/10] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index b56de01f6bb8..c7abb4a8dd37 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -231,7 +231,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -284,7 +283,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -373,8 +371,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -453,7 +449,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -468,7 +463,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH v5 net-next 01/10] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/korina.c | 56 +++ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c059b4bd3f23 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -98,6 +98,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 + select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..1b7e1c75ed9e 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +292,48 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + u32 value; + + return readl_poll_timeout_atomic(>eth_regs->miimind, +value, value & ETH_MII_IND_BSY, +1, 1000); +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); - ret = (int)(readl(>eth_regs->miimrdd)); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; + + if (readl(>eth_regs->miimind) & ETH_MII_IND_NV) + return -EINVAL; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +659,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +885,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1108,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH v5 net-next 00/10] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up and adds support for device tree. Changes in v5: - fixed email address in binding document, which prevented sending it Changes in v4: - improve error returns in mdio_read further - added clock name and improved clk handling - fixed bindind errors Changes in v3: - use readl_poll_timeout_atomic in mdio_wait - return -ETIMEDOUT, if mdio_wait failed - added DT binding and changed name to idt,3243x-emac - fixed usage of of_get_mac_address for net-next Changes in v2: - added device tree support to get rid of idt_cpu_freq - fixed compile test on 64bit archs - fixed descriptor current address handling by storing/using mapped dma addresses (dma controller modifies current address) Thomas Bogendoerfer (10): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Add support for device tree net: korina: Get mdio input clock via common clock framework net: korina: Make driver COMPILE_TESTable dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs .../bindings/net/idt,3243x-emac.yaml | 74 +++ arch/mips/rb532/devices.c | 5 +- drivers/net/ethernet/Kconfig | 3 +- drivers/net/ethernet/korina.c | 601 +- 4 files changed, 511 insertions(+), 172 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml -- 2.29.2
[PATCH v4 net-next 09/10] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 249 -- 2 files changed, 239 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index c059b4bd3f23..453d202a28c1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index e95c8d87d893..5f39a5bba531 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -59,18 +59,244 @@ #include #include -#include -#include -#include -#include - -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x000f +#
[PATCH v4 net-next 08/10] net: korina: Get mdio input clock via common clock framework
With device tree clock is provided via CCF. For non device tree use a maximum clock value to not overclock the PHY. The non device tree usage will go away after platform is converted to DT. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index cd078a5c679b..e95c8d87d893 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -57,14 +57,13 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -146,10 +145,9 @@ struct korina_private { struct work_struct restart_task; struct net_device *dev; struct device *dmadev; + int mii_clock_freq; }; -extern unsigned int idt_cpu_freq; - static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) { return lp->td_dma + (idx * sizeof(struct dma_desc)); @@ -899,8 +897,8 @@ static int korina_init(struct net_device *dev) /* Management Clock Prescaler Divisor * Clock independent setting */ - writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, - >eth_regs->ethmcp); + writel(((lp->mii_clock_freq) / MII_CLOCK + 1) & ~1, + >eth_regs->ethmcp); writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ @@ -1060,6 +1058,7 @@ static int korina_probe(struct platform_device *pdev) u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; + struct clk *clk; void __iomem *p; int rc; @@ -1077,6 +1076,16 @@ static int korina_probe(struct platform_device *pdev) eth_hw_addr_random(dev); } + clk = devm_clk_get_optional(>dev, "mdioclk"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + if (clk) { + clk_prepare_enable(clk); + lp->mii_clock_freq = clk_get_rate(clk); + } else { + lp->mii_clock_freq = 2; /* max possible input clk */ + } + lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); -- 2.29.2
[PATCH v4 net-next 07/10] net: korina: Add support for device tree
If there is no mac address passed via platform data try to get it via device tree and fall back to a random mac address, if all fail. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 24 ++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index d6dbbdd43d7c..cd078a5c679b 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -1068,7 +1070,12 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + if (mac_addr) { + ether_addr_copy(dev->dev_addr, mac_addr); + } else { + if (of_get_mac_address(pdev->dev.of_node, dev->dev_addr)) + eth_hw_addr_random(dev); + } lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1148,8 +1155,21 @@ static int korina_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id korina_match[] = { + { + .compatible = "idt,3243x-emac", + }, + { } +}; +MODULE_DEVICE_TABLE(of, korina_match); +#endif + static struct platform_driver korina_driver = { - .driver.name = "korina", + .driver = { + .name = "korina", + .of_match_table = of_match_ptr(korina_match), + }, .probe = korina_probe, .remove = korina_remove, }; -- 2.29.2
[PATCH v4 net-next 05/10] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 158 +- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 955fe3d3da06..44fad9e924ca 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -110,10 +110,15 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; + dma_addr_t rx_skb_dma[KORINA_NUM_RDS]; + dma_addr_t tx_skb_dma[KORINA_NUM_TDS]; + int rx_next_done; int rx_chain_head; int rx_chain_tail; @@ -138,10 +143,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -176,14 +192,17 @@ static void korina_abort_rx(struct net_device *dev) static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); - unsigned long flags; - u32 length; u32 chain_prev, chain_next; + unsigned long flags; struct dma_desc *td; + dma_addr_t ca; + u32 length; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -191,26 +210,26 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, ca)) + goto drop_packet; + + lp->tx_skb_dma[idx] = ca; + td->ca = ca; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -220,8 +239,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -232,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next;
[PATCH v4 net-next 06/10] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 44fad9e924ca..d6dbbdd43d7c 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1055,7 +1055,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1068,8 +1068,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1123,6 +1122,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1140,9 +1141,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH v4 net-next 04/10] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index c7abb4a8dd37..955fe3d3da06 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -142,12 +142,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -164,11 +158,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -183,18 +172,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -463,7 +440,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -840,7 +817,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH v4 net-next 02/10] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 1b7e1c75ed9e..b56de01f6bb8 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -105,9 +105,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1044,10 +1044,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1060,36 +1060,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1119,7 +1113,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1127,20 +1122,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1148,13 +1130,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH v4 net-next 03/10] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Reviewed-by: Andrew Lunn Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index b56de01f6bb8..c7abb4a8dd37 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -231,7 +231,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -284,7 +283,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -373,8 +371,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -453,7 +449,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -468,7 +463,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH v4 net-next 01/10] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/korina.c | 56 +++ 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c059b4bd3f23 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -98,6 +98,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 + select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..1b7e1c75ed9e 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +292,48 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + u32 value; + + return readl_poll_timeout_atomic(>eth_regs->miimind, +value, value & ETH_MII_IND_BSY, +1, 1000); +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); - ret = (int)(readl(>eth_regs->miimrdd)); + ret = korina_mdio_wait(lp); + if (ret < 0) + return ret; + + if (readl(>eth_regs->miimind) & ETH_MII_IND_NV) + return -EINVAL; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +659,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +885,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1108,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH v4 net-next 00/10] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up and adds support for device tree. Changes in v4: - improve error returns in mdio_read further - added clock name and improved clk handling - fixed bindind errors Changes in v3: - use readl_poll_timeout_atomic in mdio_wait - return -ETIMEDOUT, if mdio_wait failed - added DT binding and changed name to idt,3243x-emac - fixed usage of of_get_mac_address for net-next Changes in v2: - added device tree support to get rid of idt_cpu_freq - fixed compile test on 64bit archs - fixed descriptor current address handling by storing/using mapped dma addresses (dma controller modifies current address) Thomas Bogendoerfer (10): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Add support for device tree net: korina: Get mdio input clock via common clock framework net: korina: Make driver COMPILE_TESTable dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs .../bindings/net/idt,3243x-emac.yaml | 74 +++ arch/mips/rb532/devices.c | 5 +- drivers/net/ethernet/Kconfig | 3 +- drivers/net/ethernet/korina.c | 601 +- 4 files changed, 511 insertions(+), 172 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml -- 2.29.2
Re: [PATCH v3 net-next 07/10] net: korina: Add support for device tree
On Fri, Apr 16, 2021 at 01:49:07AM +0200, Andrew Lunn wrote: > > - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); > > + if (mac_addr) { > > + ether_addr_copy(dev->dev_addr, mac_addr); > > + } else { > > + u8 ofmac[ETH_ALEN]; > > + > > + if (of_get_mac_address(pdev->dev.of_node, ofmac) == 0) > > + ether_addr_copy(dev->dev_addr, ofmac); > > You should be able to skip the ether_addr_copy() by passing > dev->dev_addr directly to of_get_mac_address(). good point > > > + else > > + eth_hw_addr_random(dev); > > + } > > > > lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); > > lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); > > @@ -1146,8 +1157,21 @@ static int korina_remove(struct platform_device > > *pdev) > > return 0; > > } > > > > +#ifdef CONFIG_OF > > +static const struct of_device_id korina_match[] = { > > + { > > + .compatible = "idt,3243x-emac", > > You need to document this compatible somewhere under > Documentation/devicetree/binding checkpatch hinted to put it in an extra patch, it's patch 10 of this series and looking at my inbox it didn't get through :-(. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v2 0/8] MIPS: fixes for PCI legacy drivers (rt2880, rt3883)
On Tue, Apr 13, 2021 at 08:12:32PM -0700, Ilya Lipnitskiy wrote: > One major fix for rt2880-pci in the first patch - fixes breakage that > existed since v4.14. > > Other more minor fixes, cleanups, and improvements that either free up > memory, make dmesg messages clearer, or remove redundant dmesg output. > > v2: > - Do not use internal pci-rt2880 config read and write functions after > the device has been registered with the PCI subsystem to avoid races. > Use safe pci_bus_{read,write}_config_{d}word wrappers instead. > > Ilya Lipnitskiy (8): > MIPS: pci-rt2880: fix slot 0 configuration > MIPS: pci-rt2880: remove unneeded locks > MIPS: pci-rt3883: trivial: remove unused variable > MIPS: pci-rt3883: more accurate DT error messages > MIPS: pci-legacy: stop using of_pci_range_to_resource > MIPS: pci-legacy: remove redundant info messages > MIPS: pci-legacy: remove busn_resource field > MIPS: pci-legacy: use generic pci_enable_resources > > arch/mips/include/asm/pci.h | 1 - > arch/mips/pci/pci-legacy.c | 57 ++--- > arch/mips/pci/pci-rt2880.c | 50 > arch/mips/pci/pci-rt3883.c | 10 ++- > 4 files changed, 35 insertions(+), 83 deletions(-) series applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: Fix strnlen_user access check
On Thu, Apr 15, 2021 at 11:26:40PM +0200, Thomas Bogendoerfer wrote: > Commit 04324f44cb69 ("MIPS: Remove get_fs/set_fs") changed the access_ok > for strnlen_user to check the whole range, which broke some callers > of strndup_user(). Restore the old behaviour and just check the first byte. > > Fixes: 04324f44cb69 ("MIPS: Remove get_fs/set_fs") > Signed-off-by: Thomas Bogendoerfer > --- > arch/mips/include/asm/uaccess.h | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v3 net-next 06/10] net: korina: Only pass mac address via platform data
On Fri, Apr 16, 2021 at 01:30:04AM +0200, Andrew Lunn wrote: > On Thu, Apr 15, 2021 at 01:06:43AM +0200, Thomas Bogendoerfer wrote: > > Get rid of access to struct korina_device by just passing the mac > > address via platform data and use drvdata for passing netdev to remove > > function. > > > > Signed-off-by: Thomas Bogendoerfer > > --- > > arch/mips/rb532/devices.c | 5 +++-- > > drivers/net/ethernet/korina.c | 11 ++- > > 2 files changed, 9 insertions(+), 7 deletions(-) > > > > diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c > > index dd34f1b32b79..5fc3c8ee4f31 100644 > > --- a/arch/mips/rb532/devices.c > > +++ b/arch/mips/rb532/devices.c > > @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { > > .name = "korina", > > .resource = korina_dev0_res, > > .num_resources = ARRAY_SIZE(korina_dev0_res), > > + .dev = { > > + .platform_data = _dev0_data.mac, > > + } > > This is a bit unusual. Normally you define a structure in > include/linux/platform/data/koriana.h, and use that. > > What about the name? "korina0" How is that passed? this is just for transition purpose. My DT patches remove this struct completly. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH] MIPS: Fix strnlen_user access check
Commit 04324f44cb69 ("MIPS: Remove get_fs/set_fs") changed the access_ok for strnlen_user to check the whole range, which broke some callers of strndup_user(). Restore the old behaviour and just check the first byte. Fixes: 04324f44cb69 ("MIPS: Remove get_fs/set_fs") Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index ab47e597656a..783fecce65c8 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -614,8 +614,8 @@ static inline long strnlen_user(const char __user *s, long n) { long res; - if (!access_ok(s, n)) - return -0; + if (!access_ok(s, 1)) + return 0; might_fault(); __asm__ __volatile__( -- 2.29.2
[PATCH v3 net-next 09/10] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 249 -- 2 files changed, 239 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index c059b4bd3f23..453d202a28c1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 62bb691c8354..a065f111281b 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -59,18 +59,244 @@ #include #include -#include -#include -#include -#include - -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x000f +#
[PATCH v3 net-next 05/10] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 158 +- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 479142c5166f..f00ffbbdfba7 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -110,10 +110,15 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; + dma_addr_t rx_skb_dma[KORINA_NUM_RDS]; + dma_addr_t tx_skb_dma[KORINA_NUM_TDS]; + int rx_next_done; int rx_chain_head; int rx_chain_tail; @@ -138,10 +143,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -176,14 +192,17 @@ static void korina_abort_rx(struct net_device *dev) static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); - unsigned long flags; - u32 length; u32 chain_prev, chain_next; + unsigned long flags; struct dma_desc *td; + dma_addr_t ca; + u32 length; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -191,26 +210,26 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, ca)) + goto drop_packet; + + lp->tx_skb_dma[idx] = ca; + td->ca = ca; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -220,8 +239,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -232,12 +251,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next;
[PATCH v3 net-next 08/10] net: korina: Get mdio input clock via common clock framework
With device tree clock is provided via CCF. For non device tree use a maximum clock value to not overclock the PHY. The non device tree usage will go away after platform is converted to DT. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 7646ccc9d7e8..62bb691c8354 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -57,14 +57,13 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -146,10 +145,9 @@ struct korina_private { struct work_struct restart_task; struct net_device *dev; struct device *dmadev; + int mii_clock_freq; }; -extern unsigned int idt_cpu_freq; - static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) { return lp->td_dma + (idx * sizeof(struct dma_desc)); @@ -897,8 +895,8 @@ static int korina_init(struct net_device *dev) /* Management Clock Prescaler Divisor * Clock independent setting */ - writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, - >eth_regs->ethmcp); + writel(((lp->mii_clock_freq) / MII_CLOCK + 1) & ~1, + >eth_regs->ethmcp); writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ @@ -1058,6 +1056,7 @@ static int korina_probe(struct platform_device *pdev) u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; + struct clk *clk; void __iomem *p; int rc; @@ -1079,6 +1078,14 @@ static int korina_probe(struct platform_device *pdev) eth_hw_addr_random(dev); } + clk = devm_clk_get(>dev, NULL); + if (!IS_ERR(clk)) { + clk_prepare_enable(clk); + lp->mii_clock_freq = clk_get_rate(clk); + } else { + lp->mii_clock_freq = 2; /* max possible input clk */ + } + lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); -- 2.29.2
[PATCH v3 net-next 07/10] net: korina: Add support for device tree
If there is no mac address passed via platform data try to get it via device tree and fall back to a random mac address, if all fail. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 ++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 1d7dead17ac3..7646ccc9d7e8 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -1066,7 +1068,16 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + if (mac_addr) { + ether_addr_copy(dev->dev_addr, mac_addr); + } else { + u8 ofmac[ETH_ALEN]; + + if (of_get_mac_address(pdev->dev.of_node, ofmac) == 0) + ether_addr_copy(dev->dev_addr, ofmac); + else + eth_hw_addr_random(dev); + } lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1146,8 +1157,21 @@ static int korina_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id korina_match[] = { + { + .compatible = "idt,3243x-emac", + }, + { } +}; +MODULE_DEVICE_TABLE(of, korina_match); +#endif + static struct platform_driver korina_driver = { - .driver.name = "korina", + .driver = { + .name = "korina", + .of_match_table = of_match_ptr(korina_match), + }, .probe = korina_probe, .remove = korina_remove, }; -- 2.29.2
[PATCH v3 net-next 03/10] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 6bef5d590ebe..408cb2dedb95 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -231,7 +231,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -284,7 +283,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -371,8 +369,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -451,7 +447,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -466,7 +461,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH v3 net-next 06/10] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index f00ffbbdfba7..1d7dead17ac3 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1053,7 +1053,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1066,8 +1066,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1121,6 +1120,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1138,9 +1139,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH v3 net-next 04/10] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 408cb2dedb95..479142c5166f 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -142,12 +142,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -164,11 +158,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -183,18 +172,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -461,7 +438,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -838,7 +815,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH v3 net-next 02/10] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 3f6f4835a9bc..6bef5d590ebe 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -105,9 +105,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1042,10 +1042,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1058,36 +1058,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1117,7 +,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1125,20 +1120,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1146,13 +1128,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH v3 net-next 01/10] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/korina.c | 54 +++ 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c059b4bd3f23 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -98,6 +98,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 + select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..3f6f4835a9bc 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -137,7 +138,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +292,46 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + u32 value; + + return readl_poll_timeout_atomic(>eth_regs->miimind, +value, value & ETH_MII_IND_BSY, +1, 1000); +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return -ETIMEDOUT; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); + + if (korina_mdio_wait(lp)) + return -ETIMEDOUT; - ret = (int)(readl(>eth_regs->miimrdd)); + if (readl(>eth_regs->miimind) & ETH_MII_IND_NV) + return -1; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +657,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +883,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1106,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH v3 net-next 00/10] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up and adds support for device tree. Changes in v3: - fixed usage of of_get_mac_address for net-next - use readl_poll_timeout_atomic in mdio_wait - return -ETIMEDOUT, if mdio_wait fails - added DT binding and changed compatible name to idt,3243x-emac Changes in v2: - added device tree support to get rid of idt_cpu_freq - fixed compile test on 64bit archs - fixed descriptor current address handling by storing/using mapped dma addresses (dma controller modifies current address) Thomas Bogendoerfer (10): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Add support for device tree net: korina: Get mdio input clock via common clock framework net: korina: Make driver COMPILE_TESTable dt-bindings: net: korina: Add DT bindings for IDT 79RC3243x SoCs .../bindings/net/idt,3243x-emac.yaml | 82 +++ arch/mips/rb532/devices.c | 5 +- drivers/net/ethernet/Kconfig | 3 +- drivers/net/ethernet/korina.c | 601 +- 4 files changed, 519 insertions(+), 172 deletions(-) create mode 100644 Documentation/devicetree/bindings/net/idt,3243x-emac.yaml -- 2.29.2
Re: [PATCH net-next 1/7] net: korina: Fix MDIO functions
On Wed, Apr 14, 2021 at 09:36:04PM +0200, Andrew Lunn wrote: > > +static int korina_mdio_wait(struct korina_private *lp) > > +{ > > + int timeout = 1000; > > + > > + while ((readl(>eth_regs->miimind) & 1) && timeout-- > 0) > > + udelay(1); > > + > > + if (timeout <= 0) > > + return -1; > > + > > + return 0; > > Using readl_poll_timeout_atomic() would be better. I'll have a look > > > > +} > > + > > +static int korina_mdio_read(struct net_device *dev, int phy, int reg) > > { > > struct korina_private *lp = netdev_priv(dev); > > int ret; > > > > - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); > > + if (korina_mdio_wait(lp)) > > + return -1; > > This should really be -ETIMEDOUT ok. > > dev->watchdog_timeo = TX_TIMEOUT; > > netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); > > > > - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); > > lp->mii_if.dev = dev; > > - lp->mii_if.mdio_read = mdio_read; > > - lp->mii_if.mdio_write = mdio_write; > > - lp->mii_if.phy_id = lp->phy_addr; > > + lp->mii_if.mdio_read = korina_mdio_read; > > + lp->mii_if.mdio_write = korina_mdio_write; > > + lp->mii_if.phy_id = 1; > > lp->mii_if.phy_id_mask = 0x1f; > > lp->mii_if.reg_num_mask = 0x1f; > > You could also replace all the mii code with phylib. that's on my todo. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH v2 net-next 8/9] net: korina: Get mdio input clock via common clock framework
With device tree clock is provided via CCF. For non device tree use a maximum clock value to not overclock the PHY. The non device tree usage will go away after platform is converted to DT. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index c4590b2c65aa..df75dd5d1638 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -56,14 +56,13 @@ #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -145,10 +144,9 @@ struct korina_private { struct work_struct restart_task; struct net_device *dev; struct device *dmadev; + int mii_clock_freq; }; -extern unsigned int idt_cpu_freq; - static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) { return lp->td_dma + (idx * sizeof(struct dma_desc)); @@ -900,8 +898,8 @@ static int korina_init(struct net_device *dev) /* Management Clock Prescaler Divisor * Clock independent setting */ - writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, - >eth_regs->ethmcp); + writel(((lp->mii_clock_freq) / MII_CLOCK + 1) & ~1, + >eth_regs->ethmcp); writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ @@ -1061,6 +1059,7 @@ static int korina_probe(struct platform_device *pdev) const u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; + struct clk *clk; void __iomem *p; int rc; @@ -1081,6 +1080,14 @@ static int korina_probe(struct platform_device *pdev) eth_hw_addr_random(dev); } + clk = devm_clk_get(>dev, NULL); + if (!IS_ERR(clk)) { + clk_prepare_enable(clk); + lp->mii_clock_freq = clk_get_rate(clk); + } else { + lp->mii_clock_freq = 2; /* max possible input clk */ + } + lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); -- 2.29.2
[PATCH v2 net-next 6/9] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 5e0fd9058701..69c8baa87a6e 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1056,7 +1056,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1069,8 +1069,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1124,6 +1123,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1141,9 +1142,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH v2 net-next 9/9] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 249 -- 2 files changed, 239 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index c059b4bd3f23..453d202a28c1 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index df75dd5d1638..025f88ae99be 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -58,18 +58,244 @@ #include #include -#include -#include -#include -#include - -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLRT registers */ +#define ETH_CLRT_MAX_RET 0x000f +#
[PATCH v2 net-next 7/9] net: korina: Add support for device tree
If there is no mac address passed via platform data try to get it via device tree and fall back to a random mac address, if all fail. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 69c8baa87a6e..c4590b2c65aa 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include #include #include @@ -1056,7 +1058,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - u8 *mac_addr = dev_get_platdata(>dev); + const u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1069,7 +1071,15 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - memcpy(dev->dev_addr, mac_addr, ETH_ALEN); + if (mac_addr) { + ether_addr_copy(dev->dev_addr, mac_addr); + } else { + mac_addr = of_get_mac_address(pdev->dev.of_node); + if (!IS_ERR(mac_addr)) + ether_addr_copy(dev->dev_addr, mac_addr); + else + eth_hw_addr_random(dev); + } lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1149,8 +1159,21 @@ static int korina_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id korina_match[] = { + { + .compatible = "korina", + }, + { } +}; +MODULE_DEVICE_TABLE(of, korina_match); +#endif + static struct platform_driver korina_driver = { - .driver.name = "korina", + .driver = { + .name = "korina", + .of_match_table = of_match_ptr(korina_match), + }, .probe = korina_probe, .remove = korina_remove, }; -- 2.29.2
[PATCH v2 net-next 5/9] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 158 +- 1 file changed, 98 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 728c4baa3eee..5e0fd9058701 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -109,10 +109,15 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; + dma_addr_t rx_skb_dma[KORINA_NUM_RDS]; + dma_addr_t tx_skb_dma[KORINA_NUM_TDS]; + int rx_next_done; int rx_chain_head; int rx_chain_tail; @@ -137,10 +142,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -175,14 +191,17 @@ static void korina_abort_rx(struct net_device *dev) static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); - unsigned long flags; - u32 length; u32 chain_prev, chain_next; + unsigned long flags; struct dma_desc *td; + dma_addr_t ca; + u32 length; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -190,26 +209,26 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, ca)) + goto drop_packet; + + lp->tx_skb_dma[idx] = ca; + td->ca = ca; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -219,8 +238,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -231,12 +250,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next;
[PATCH v2 net-next 4/9] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index b6dcbb6d5e05..728c4baa3eee 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -141,12 +141,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -163,11 +157,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -182,18 +171,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -464,7 +441,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -841,7 +818,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH v2 net-next 3/9] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 3a454f6214b0..b6dcbb6d5e05 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -230,7 +230,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -283,7 +282,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -374,8 +372,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -454,7 +450,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -469,7 +464,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH v2 net-next 2/9] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 2266b18c1377..3a454f6214b0 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -104,9 +104,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1045,10 +1045,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1061,36 +1061,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1120,7 +1114,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1128,20 +1123,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1149,13 +1131,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH v2 net-next 1/9] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 1 + drivers/net/ethernet/korina.c | 57 +++ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c059b4bd3f23 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -98,6 +98,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" depends on MIKROTIK_RB532 + select MII help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..2266b18c1377 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -137,7 +137,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +291,50 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + int timeout = 1000; + + while ((readl(>eth_regs->miimind) & 1) && timeout-- > 0) + udelay(1); + + if (timeout <= 0) + return -1; + + return 0; +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return -1; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); - ret = (int)(readl(>eth_regs->miimrdd)); + if (korina_mdio_wait(lp)) + return -1; + + if (readl(>eth_regs->miimind) & 4) + return -1; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +660,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +886,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1109,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH v2 net-next 0/9] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up and adds support for device tree. Changes in v2: - added device tree support to get rid of idt_cpu_freq - fixed compile test on 64bit archs - fixed descriptor current address handling by storing/using mapped dma addresses (dma controller modifies current address) Thomas Bogendoerfer (9): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Add support for device tree net: korina: Get mdio input clock via common clock framework net: korina: Make driver COMPILE_TESTable arch/mips/rb532/devices.c | 5 +- drivers/net/ethernet/Kconfig | 3 +- drivers/net/ethernet/korina.c | 603 -- 3 files changed, 439 insertions(+), 172 deletions(-) -- 2.29.2
Re: [PATCH] MIPS: Fix strnlen_user access check
On Tue, Apr 13, 2021 at 04:01:13PM +, David Laight wrote: > From: Thomas Bogendoerfer > > Sent: 13 April 2021 16:19 > > > > On Tue, Apr 13, 2021 at 12:37:25PM +, David Laight wrote: > > > From: Thomas Bogendoerfer > > > > Sent: 13 April 2021 12:15 > > > ... > > > > > The __access_ok() is noted with `Ensure that the range [addr, > > > > > addr+size) > > > > > is within the process's address space`. Does the range checked by > > > > > __access_ok() on MIPS is [addr, addr+size]. So if we want to use > > > > > access_ok(s, 1), should we modify __access_ok()? Or my > > > > > misunderstanding? > > > > > > > > you are right, I'm going to apply > > > > > > > > https://patchwork.kernel.org/project/linux-mips/patch/20190209194718.1294-1-paul.bur...@mips.com/ > > > > > > > > to fix that. > > > > > > Isn't that still wrong? > > > If an application does: > > > write(fd, (void *)0x, 0); > > > it should return 0, not -1 and EFAULT/SIGSEGV. > > > > WRITE(2) Linux Programmer's Manual > > WRITE(2) > > [...] > >If count is zero and fd refers to a regular file, then write() > > may > >return a failure status if one of the errors below is detected. If > > no > >errors are detected, or error detection is not performed, 0 will > > be > >returned without causing any other effect. If count is zero and > > fd > >refers to a file other than a regular file, the results are not > > speci- > >fied. > > [...] > >EFAULT buf is outside your accessible address space. > > > > at least it's covered by the man page on my Linux system. > > Something related definitely caused grief in the setsockopt() changes. > > > > There is also the question about why this makes any difference > > > to the original problem of logging in via the graphical interface. > > > > kernel/module.c:mod->args = strndup_user(uargs, ~0UL >> 1); > > > > and strndup_user does a strnlen_user. > > That call is just gross. > Why did it work before the removal of set_fs() etc. strnlen_user just did the equivalent of access_ok(s, 0) and I copy the wrong access_ok() statement :-( > Or was there another change that affected strndup_user() ? no, just the change in strnlen_user. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH net-next 6/7] net: korina: Only pass mac address via platform data
Get rid of access to struct korina_device by just passing the mac address via platform data and use drvdata for passing netdev to remove function. Signed-off-by: Thomas Bogendoerfer --- arch/mips/rb532/devices.c | 5 +++-- drivers/net/ethernet/korina.c | 11 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index dd34f1b32b79..5fc3c8ee4f31 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -105,6 +105,9 @@ static struct platform_device korina_dev0 = { .name = "korina", .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), + .dev = { + .platform_data = _dev0_data.mac, + } }; static struct resource cf_slot0_res[] = { @@ -299,8 +302,6 @@ static int __init plat_setup_devices(void) /* set the uart clock to the current cpu frequency */ rb532_uart_res[0].uartclk = idt_cpu_freq; - dev_set_drvdata(_dev0.dev, _dev0_data); - gpiod_add_lookup_table(_slot0_gpio_table); return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 0224cd179b03..d7972965eb14 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -1045,7 +1045,7 @@ static const struct net_device_ops korina_netdev_ops = { static int korina_probe(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + u8 *mac_addr = dev_get_platdata(>dev); struct korina_private *lp; struct net_device *dev; void __iomem *p; @@ -1058,8 +1058,7 @@ static int korina_probe(struct platform_device *pdev) SET_NETDEV_DEV(dev, >dev); lp = netdev_priv(dev); - bif->dev = dev; - memcpy(dev->dev_addr, bif->mac, ETH_ALEN); + memcpy(dev->dev_addr, mac_addr, ETH_ALEN); lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); @@ -1113,6 +1112,8 @@ static int korina_probe(struct platform_device *pdev) lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; + platform_set_drvdata(pdev, dev); + rc = register_netdev(dev); if (rc < 0) { printk(KERN_ERR DRV_NAME @@ -1130,9 +1131,9 @@ static int korina_probe(struct platform_device *pdev) static int korina_remove(struct platform_device *pdev) { - struct korina_device *bif = platform_get_drvdata(pdev); + struct net_device *dev = platform_get_drvdata(pdev); - unregister_netdev(bif->dev); + unregister_netdev(dev); return 0; } -- 2.29.2
[PATCH net-next 5/7] net: korina: Use DMA API
Instead of messing with MIPS specific macros use DMA API for mapping descriptors and skbs. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 143 -- 1 file changed, 85 insertions(+), 58 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 728c4baa3eee..0224cd179b03 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -109,6 +109,8 @@ struct korina_private { struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ + dma_addr_t td_dma; + dma_addr_t rd_dma; struct sk_buff *tx_skb[KORINA_NUM_TDS]; struct sk_buff *rx_skb[KORINA_NUM_RDS]; @@ -137,10 +139,21 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; + struct device *dmadev; }; extern unsigned int idt_cpu_freq; +static dma_addr_t korina_tx_dma(struct korina_private *lp, int idx) +{ + return lp->td_dma + (idx * sizeof(struct dma_desc)); +} + +static dma_addr_t korina_rx_dma(struct korina_private *lp, int idx) +{ + return lp->rd_dma + (idx * sizeof(struct dma_desc)); +} + static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -179,10 +192,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) u32 length; u32 chain_prev, chain_next; struct dma_desc *td; + int idx; spin_lock_irqsave(>lock, flags); - td = >td_ring[lp->tx_chain_tail]; + idx = lp->tx_chain_tail; + td = >td_ring[idx]; /* stop queue when full, drop pkts if queue already full */ if (lp->tx_count >= (KORINA_NUM_TDS - 2)) { @@ -190,26 +205,23 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) if (lp->tx_count == (KORINA_NUM_TDS - 2)) netif_stop_queue(dev); - else { - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - spin_unlock_irqrestore(>lock, flags); - - return NETDEV_TX_OK; - } + else + goto drop_packet; } lp->tx_count++; - lp->tx_skb[lp->tx_chain_tail] = skb; + lp->tx_skb[idx] = skb; length = skb->len; - dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - td->ca = CPHYSADDR(skb->data); - chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; - chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; + td->ca = dma_map_single(lp->dmadev, skb->data, length, DMA_TO_DEVICE); + if (dma_mapping_error(lp->dmadev, td->ca)) + goto drop_packet; + + chain_prev = (idx - 1) & KORINA_TDS_MASK; + chain_next = (idx + 1) & KORINA_TDS_MASK; if (readl(&(lp->tx_dma_regs->dmandptr)) == 0) { if (lp->tx_chain_status == desc_empty) { @@ -219,8 +231,8 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - >tx_dma_regs->dmandptr); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; } else { @@ -231,12 +243,12 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->td_ring[chain_prev].control &= ~DMA_DESC_COF; /* Link to prev */ - lp->td_ring[chain_prev].link = CPHYSADDR(td); + lp->td_ring[chain_prev].link = korina_tx_dma(lp, idx); /* Move tail */ lp->tx_chain_tail = chain_next; /* Write to NDPTR */ - writel(CPHYSADDR(>td_ring[lp->tx_chain_head]), - &(lp->tx_dma_regs->dmandptr)); + writel(korina_tx_dma(lp, lp->tx_chain_head), + >tx_dma_regs->dmandptr); /* Move head to tail */ lp->tx_chain_head = lp->tx_chain_tail; lp->
[PATCH net-next 7/7] net: korina: Make driver COMPILE_TESTable
Move structs/defines for ethernet/dma register into driver, since they are only used for this driver and remove any MIPS specific includes. This makes it possible to COMPILE_TEST the driver. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 245 -- 2 files changed, 236 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig index ad04660b97b8..c61368968cee 100644 --- a/drivers/net/ethernet/Kconfig +++ b/drivers/net/ethernet/Kconfig @@ -97,7 +97,7 @@ config JME config KORINA tristate "Korina (IDT RC32434) Ethernet support" - depends on MIKROTIK_RB532 + depends on MIKROTIK_RB532 || COMPILE_TEST help If you have a Mikrotik RouterBoard 500 or IDT RC32434 based system say Y. Otherwise say N. diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index d7972965eb14..98aa7f007f8e 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -55,20 +55,244 @@ #include #include -#include -#include -#include -#include - -#include -#include -#include -#include - #define DRV_NAME "korina" #define DRV_VERSION"0.20" #define DRV_RELDATE"15Sep2017" +struct eth_regs { + u32 ethintfc; + u32 ethfifott; + u32 etharc; + u32 ethhash0; + u32 ethhash1; + u32 ethu0[4]; /* Reserved. */ + u32 ethpfs; + u32 ethmcp; + u32 eth_u1[10]; /* Reserved. */ + u32 ethspare; + u32 eth_u2[42]; /* Reserved. */ + u32 ethsal0; + u32 ethsah0; + u32 ethsal1; + u32 ethsah1; + u32 ethsal2; + u32 ethsah2; + u32 ethsal3; + u32 ethsah3; + u32 ethrbc; + u32 ethrpc; + u32 ethrupc; + u32 ethrfc; + u32 ethtbc; + u32 ethgpf; + u32 eth_u9[50]; /* Reserved. */ + u32 ethmac1; + u32 ethmac2; + u32 ethipgt; + u32 ethipgr; + u32 ethclrt; + u32 ethmaxf; + u32 eth_u10;/* Reserved. */ + u32 ethmtest; + u32 miimcfg; + u32 miimcmd; + u32 miimaddr; + u32 miimwtd; + u32 miimrdd; + u32 miimind; + u32 eth_u11;/* Reserved. */ + u32 eth_u12;/* Reserved. */ + u32 ethcfsa0; + u32 ethcfsa1; + u32 ethcfsa2; +}; + +/* Ethernet interrupt registers */ +#define ETH_INT_FC_EN BIT(0) +#define ETH_INT_FC_ITS BIT(1) +#define ETH_INT_FC_RIP BIT(2) +#define ETH_INT_FC_JAM BIT(3) +#define ETH_INT_FC_OVR BIT(4) +#define ETH_INT_FC_UND BIT(5) +#define ETH_INT_FC_IOC 0x00c0 + +/* Ethernet FIFO registers */ +#define ETH_FIFI_TT_TTH_BIT0 +#define ETH_FIFO_TT_TTH0x007f + +/* Ethernet ARC/multicast registers */ +#define ETH_ARC_PROBIT(0) +#define ETH_ARC_AM BIT(1) +#define ETH_ARC_AFMBIT(2) +#define ETH_ARC_AB BIT(3) + +/* Ethernet SAL registers */ +#define ETH_SAL_BYTE_5 0x00ff +#define ETH_SAL_BYTE_4 0xff00 +#define ETH_SAL_BYTE_3 0x00ff +#define ETH_SAL_BYTE_2 0xff00 + +/* Ethernet SAH registers */ +#define ETH_SAH_BYTE1 0x00ff +#define ETH_SAH_BYTE0 0xff00 + +/* Ethernet GPF register */ +#define ETH_GPF_PTV0x + +/* Ethernet PFG register */ +#define ETH_PFS_PFDBIT(0) + +/* Ethernet CFSA[0-3] registers */ +#define ETH_CFSA0_CFSA40x00ff +#define ETH_CFSA0_CFSA50xff00 +#define ETH_CFSA1_CFSA20x00ff +#define ETH_CFSA1_CFSA30xff00 +#define ETH_CFSA1_CFSA00x00ff +#define ETH_CFSA1_CFSA10xff00 + +/* Ethernet MAC1 registers */ +#define ETH_MAC1_REBIT(0) +#define ETH_MAC1_PAF BIT(1) +#define ETH_MAC1_RFC BIT(2) +#define ETH_MAC1_TFC BIT(3) +#define ETH_MAC1_LBBIT(4) +#define ETH_MAC1_MRBIT(31) + +/* Ethernet MAC2 registers */ +#define ETH_MAC2_FDBIT(0) +#define ETH_MAC2_FLC BIT(1) +#define ETH_MAC2_HFE BIT(2) +#define ETH_MAC2_DCBIT(3) +#define ETH_MAC2_CEN BIT(4) +#define ETH_MAC2_PEBIT(5) +#define ETH_MAC2_VPE BIT(6) +#define ETH_MAC2_APE BIT(7) +#define ETH_MAC2_PPE BIT(8) +#define ETH_MAC2_LPE BIT(9) +#define ETH_MAC2_NBBIT(12) +#define ETH_MAC2_BPBIT(13) +#define ETH_MAC2_EDBIT(14) + +/* Ethernet IPGT register */ +#define ETH_IPGT 0x007f + +/* Ethernet IPGR registers */ +#define ETH_IPGR_IPGR2 0x007f +#define ETH_IPGR_IPGR1 0x7f00 + +/* Ethernet CLR
[PATCH net-next 4/7] net: korina: Remove nested helpers
Remove helpers, which are only used in one call site. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 28 +++- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index b6dcbb6d5e05..728c4baa3eee 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -141,12 +141,6 @@ struct korina_private { extern unsigned int idt_cpu_freq; -static inline void korina_start_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(0, >dmandptr); - writel(dma_addr, >dmadptr); -} - static inline void korina_abort_dma(struct net_device *dev, struct dma_reg *ch) { @@ -163,11 +157,6 @@ static inline void korina_abort_dma(struct net_device *dev, writel(0, >dmandptr); } -static inline void korina_chain_dma(struct dma_reg *ch, u32 dma_addr) -{ - writel(dma_addr, >dmandptr); -} - static void korina_abort_tx(struct net_device *dev) { struct korina_private *lp = netdev_priv(dev); @@ -182,18 +171,6 @@ static void korina_abort_rx(struct net_device *dev) korina_abort_dma(dev, lp->rx_dma_regs); } -static void korina_start_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_start_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - -static void korina_chain_rx(struct korina_private *lp, - struct dma_desc *rd) -{ - korina_chain_dma(lp->rx_dma_regs, CPHYSADDR(rd)); -} - /* transmit packet */ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) { @@ -464,7 +441,7 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - korina_chain_rx(lp, rd); + writel(CPHYSADDR(rd), >rx_dma_regs->dmandptr); } return count; @@ -841,7 +818,8 @@ static int korina_init(struct net_device *dev) writel(0, >rx_dma_regs->dmas); /* Start Rx DMA */ - korina_start_rx(lp, >rd_ring[0]); + writel(0, >rx_dma_regs->dmandptr); + writel(CPHYSADDR(>rd_ring[0]), >rx_dma_regs->dmadptr); writel(readl(>tx_dma_regs->dmasm) & ~(DMA_STAT_FINI | DMA_STAT_ERR), -- 2.29.2
[PATCH net-next 3/7] net: korina: Remove not needed cache flushes
Descriptors are mapped uncached so there is no need to do any cache handling for them. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 3a454f6214b0..b6dcbb6d5e05 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -230,7 +230,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) dma_cache_wback((u32)skb->data, skb->len); /* Setup the transmit descriptor. */ - dma_cache_inv((u32) td, sizeof(*td)); td->ca = CPHYSADDR(skb->data); chain_prev = (lp->tx_chain_tail - 1) & KORINA_TDS_MASK; chain_next = (lp->tx_chain_tail + 1) & KORINA_TDS_MASK; @@ -283,7 +282,6 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) lp->tx_chain_tail = chain_next; } } - dma_cache_wback((u32) td, sizeof(*td)); netif_trans_update(dev); spin_unlock_irqrestore(>lock, flags); @@ -374,8 +372,6 @@ static int korina_rx(struct net_device *dev, int limit) u32 devcs, pkt_len, dmas; int count; - dma_cache_inv((u32)rd, sizeof(*rd)); - for (count = 0; count < limit; count++) { skb = lp->rx_skb[lp->rx_next_done]; skb_new = NULL; @@ -454,7 +450,6 @@ static int korina_rx(struct net_device *dev, int limit) ~DMA_DESC_COD; lp->rx_next_done = (lp->rx_next_done + 1) & KORINA_RDS_MASK; - dma_cache_wback((u32)rd, sizeof(*rd)); rd = >rd_ring[lp->rx_next_done]; writel(~DMA_STAT_DONE, >rx_dma_regs->dmas); } @@ -469,7 +464,6 @@ static int korina_rx(struct net_device *dev, int limit) rd->devcs = 0; skb = lp->rx_skb[lp->rx_next_done]; rd->ca = CPHYSADDR(skb->data); - dma_cache_wback((u32)rd, sizeof(*rd)); korina_chain_rx(lp, rd); } -- 2.29.2
[PATCH net-next 2/7] net: korina: Use devres functions
Simplify probe/remove code by using devm_ functions. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 64 --- 1 file changed, 21 insertions(+), 43 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 2266b18c1377..3a454f6214b0 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -104,9 +104,9 @@ enum chain_status { /* Information that need to be kept for each board. */ struct korina_private { - struct eth_regs *eth_regs; - struct dma_reg *rx_dma_regs; - struct dma_reg *tx_dma_regs; + struct eth_regs __iomem *eth_regs; + struct dma_reg __iomem *rx_dma_regs; + struct dma_reg __iomem *tx_dma_regs; struct dma_desc *td_ring; /* transmit descriptor ring */ struct dma_desc *rd_ring; /* receive descriptor ring */ @@ -1045,10 +1045,10 @@ static int korina_probe(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp; struct net_device *dev; - struct resource *r; + void __iomem *p; int rc; - dev = alloc_etherdev(sizeof(struct korina_private)); + dev = devm_alloc_etherdev(>dev, sizeof(struct korina_private)); if (!dev) return -ENOMEM; @@ -1061,36 +1061,30 @@ static int korina_probe(struct platform_device *pdev) lp->rx_irq = platform_get_irq_byname(pdev, "korina_rx"); lp->tx_irq = platform_get_irq_byname(pdev, "korina_tx"); - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_regs"); - dev->base_addr = r->start; - lp->eth_regs = ioremap(r->start, resource_size(r)); - if (!lp->eth_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_regs"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap registers\n"); - rc = -ENXIO; - goto probe_err_out; + return -ENOMEM; } + lp->eth_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_rx"); - lp->rx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->rx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_rx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_rx; + return -ENOMEM; } + lp->rx_dma_regs = p; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "korina_dma_tx"); - lp->tx_dma_regs = ioremap(r->start, resource_size(r)); - if (!lp->tx_dma_regs) { + p = devm_platform_ioremap_resource_byname(pdev, "korina_dma_tx"); + if (!p) { printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n"); - rc = -ENXIO; - goto probe_err_dma_tx; + return -ENOMEM; } + lp->tx_dma_regs = p; lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); - if (!lp->td_ring) { - rc = -ENXIO; - goto probe_err_td_ring; - } + if (!lp->td_ring) + return -ENOMEM; dma_cache_inv((unsigned long)(lp->td_ring), TD_RING_SIZE + RD_RING_SIZE); @@ -1120,7 +1114,8 @@ static int korina_probe(struct platform_device *pdev) if (rc < 0) { printk(KERN_ERR DRV_NAME ": cannot register net device: %d\n", rc); - goto probe_err_register; + kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); + return rc; } timer_setup(>media_check_timer, korina_poll_media, 0); @@ -1128,20 +1123,7 @@ static int korina_probe(struct platform_device *pdev) printk(KERN_INFO "%s: " DRV_NAME "-" DRV_VERSION " " DRV_RELDATE "\n", dev->name); -out: return rc; - -probe_err_register: - kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); -probe_err_td_ring: - iounmap(lp->tx_dma_regs); -probe_err_dma_tx: - iounmap(lp->rx_dma_regs); -probe_err_dma_rx: - iounmap(lp->eth_regs); -probe_err_out: - free_netdev(dev); - goto out; } static int korina_remove(struct platform_device *pdev) @@ -1149,13 +1131,9 @@ static int korina_remove(struct platform_device *pdev) struct korina_device *bif = platform_get_drvdata(pdev); struct korina_private *lp = netdev_priv(bif->dev); - iounmap(lp->eth_regs); - iounmap(lp->rx_dma_regs); - iounmap(lp->tx_dma_regs); kfree((struct dma_desc *)KSEG0ADDR(lp->td_ring)); unregister_netdev(bif->dev); - free_netdev(bif->dev); return 0; } -- 2.29.2
[PATCH net-next 1/7] net: korina: Fix MDIO functions
Fixed MDIO functions to work reliable and not just by accident. Signed-off-by: Thomas Bogendoerfer --- drivers/net/ethernet/korina.c | 57 +++ 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index 925161959b9b..2266b18c1377 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -137,7 +137,6 @@ struct korina_private { struct mii_if_info mii_if; struct work_struct restart_task; struct net_device *dev; - int phy_addr; }; extern unsigned int idt_cpu_freq; @@ -292,32 +291,50 @@ static int korina_send_packet(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } -static int mdio_read(struct net_device *dev, int mii_id, int reg) +static int korina_mdio_wait(struct korina_private *lp) +{ + int timeout = 1000; + + while ((readl(>eth_regs->miimind) & 1) && timeout-- > 0) + udelay(1); + + if (timeout <= 0) + return -1; + + return 0; +} + +static int korina_mdio_read(struct net_device *dev, int phy, int reg) { struct korina_private *lp = netdev_priv(dev); int ret; - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return -1; - writel(0, >eth_regs->miimcfg); - writel(0, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); + writel(1, >eth_regs->miimcmd); - ret = (int)(readl(>eth_regs->miimrdd)); + if (korina_mdio_wait(lp)) + return -1; + + if (readl(>eth_regs->miimind) & 4) + return -1; + + ret = readl(>eth_regs->miimrdd); + writel(0, >eth_regs->miimcmd); return ret; } -static void mdio_write(struct net_device *dev, int mii_id, int reg, int val) +static void korina_mdio_write(struct net_device *dev, int phy, int reg, int val) { struct korina_private *lp = netdev_priv(dev); - mii_id = ((lp->rx_irq == 0x2c ? 1 : 0) << 8); + if (korina_mdio_wait(lp)) + return; - writel(0, >eth_regs->miimcfg); - writel(1, >eth_regs->miimcmd); - writel(mii_id | reg, >eth_regs->miimaddr); - writel(ETH_MII_CMD_SCN, >eth_regs->miimcmd); + writel(0, >eth_regs->miimcmd); + writel(phy << 8 | reg, >eth_regs->miimaddr); writel(val, >eth_regs->miimwtd); } @@ -643,7 +660,7 @@ static void korina_check_media(struct net_device *dev, unsigned int init_media) { struct korina_private *lp = netdev_priv(dev); - mii_check_media(>mii_if, 0, init_media); + mii_check_media(>mii_if, 1, init_media); if (lp->mii_if.full_duplex) writel(readl(>eth_regs->ethmac2) | ETH_MAC2_FD, @@ -869,12 +886,15 @@ static int korina_init(struct net_device *dev) * Clock independent setting */ writel(((idt_cpu_freq) / MII_CLOCK + 1) & ~1, >eth_regs->ethmcp); + writel(0, >eth_regs->miimcfg); /* don't transmit until fifo contains 48b */ writel(48, >eth_regs->ethfifott); writel(ETH_MAC1_RE, >eth_regs->ethmac1); + korina_check_media(dev, 1); + napi_enable(>napi); netif_start_queue(dev); @@ -1089,11 +1109,10 @@ static int korina_probe(struct platform_device *pdev) dev->watchdog_timeo = TX_TIMEOUT; netif_napi_add(dev, >napi, korina_poll, NAPI_POLL_WEIGHT); - lp->phy_addr = (((lp->rx_irq == 0x2c? 1:0) << 8) | 0x05); lp->mii_if.dev = dev; - lp->mii_if.mdio_read = mdio_read; - lp->mii_if.mdio_write = mdio_write; - lp->mii_if.phy_id = lp->phy_addr; + lp->mii_if.mdio_read = korina_mdio_read; + lp->mii_if.mdio_write = korina_mdio_write; + lp->mii_if.phy_id = 1; lp->mii_if.phy_id_mask = 0x1f; lp->mii_if.reg_num_mask = 0x1f; -- 2.29.2
[PATCH net-next 0/7] net: Korina improvements
While converting Mikrotik RB532 support to use device tree I stumbled over the korina ethernet driver, which used way too many MIPS specific hacks. This series cleans this all up. Thomas Bogendoerfer (7): net: korina: Fix MDIO functions net: korina: Use devres functions net: korina: Remove not needed cache flushes net: korina: Remove nested helpers net: korina: Use DMA API net: korina: Only pass mac address via platform data net: korina: Make driver COMPILE_TESTable arch/mips/rb532/devices.c | 5 +- drivers/net/ethernet/Kconfig | 2 +- drivers/net/ethernet/korina.c | 542 -- 3 files changed, 386 insertions(+), 163 deletions(-) -- 2.29.2
Re: [PATCH] MIPS: Fix strnlen_user access check
On Tue, Apr 13, 2021 at 12:37:25PM +, David Laight wrote: > From: Thomas Bogendoerfer > > Sent: 13 April 2021 12:15 > ... > > > The __access_ok() is noted with `Ensure that the range [addr, addr+size) > > > is within the process's address space`. Does the range checked by > > > __access_ok() on MIPS is [addr, addr+size]. So if we want to use > > > access_ok(s, 1), should we modify __access_ok()? Or my misunderstanding? > > > > you are right, I'm going to apply > > > > https://patchwork.kernel.org/project/linux-mips/patch/20190209194718.1294-1-paul.bur...@mips.com/ > > > > to fix that. > > Isn't that still wrong? > If an application does: > write(fd, (void *)0x, 0); > it should return 0, not -1 and EFAULT/SIGSEGV. WRITE(2) Linux Programmer's Manual WRITE(2) [...] If count is zero and fd refers to a regular file, then write() may return a failure status if one of the errors below is detected. If no errors are detected, or error detection is not performed, 0 will be returned without causing any other effect. If count is zero and fd refers to a file other than a regular file, the results are not speci- fied. [...] EFAULT buf is outside your accessible address space. at least it's covered by the man page on my Linux system. > There is also the question about why this makes any difference > to the original problem of logging in via the graphical interface. kernel/module.c:mod->args = strndup_user(uargs, ~0UL >> 1); and strndup_user does a strnlen_user. > ISTM that it is very unlikely that the length passed to strnlen_user() > is long enough to take potential buffer beyond the end of user > address space. see above. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: Fix strnlen_user access check
On Tue, Apr 13, 2021 at 09:15:48AM +0800, Jinyang He wrote: > On 04/12/2021 10:27 PM, Thomas Bogendoerfer wrote: > > > diff --git a/arch/mips/include/asm/uaccess.h > > > b/arch/mips/include/asm/uaccess.h > > > index 91bc7fb..eafc99b 100644 > > > --- a/arch/mips/include/asm/uaccess.h > > > +++ b/arch/mips/include/asm/uaccess.h > > > @@ -630,8 +630,8 @@ static inline long strnlen_user(const char __user *s, > > > long n) > > > { > > > long res; > > > - if (!access_ok(s, n)) > > > - return -0; > > > + if (!access_ok(s, 1)) > > > + return 0; > > > might_fault(); > > > __asm__ __volatile__( > > that's the fix I'd like to apply. Could someone send it as a formal > > patch ? Thanks. > > > > Thomas. > > > Hi, Thomas, > > I always think it is better to use access_ok(s, 0) on MIPS. I have been > curious about the difference between access_ok(s, 0) and access_ok(s, 1) > until I saw __access_ok() on RISCV at arch/riscv/include/asm/uaccess.h > > The __access_ok() is noted with `Ensure that the range [addr, addr+size) > is within the process's address space`. Does the range checked by > __access_ok() on MIPS is [addr, addr+size]. So if we want to use > access_ok(s, 1), should we modify __access_ok()? Or my misunderstanding? you are right, I'm going to apply https://patchwork.kernel.org/project/linux-mips/patch/20190209194718.1294-1-paul.bur...@mips.com/ to fix that. > More importantly, the implementation of strnlen_user in lib/strnlen_user.c > is noted `we hit the address space limit, and we still had more characters > the caller would have wanted. That's 0.` Does it make sense? It is not > achieved on MIPS when hit __ua_limit, if only access_ok(s, 1) is used. see the comment in arch/mips/lib/strnlen_user.S * Note: for performance reasons we deliberately accept that a user may * make strlen_user and strnlen_user access the first few KSEG0 * bytes. There's nothing secret there. On 64-bit accessing beyond * the maximum is a tad hairier ... for 32bit kernels strnlen_user could possibly access KSEG0 and will find a 0 sooner or later. I don't see much problems there. For 64bit kernels strnlen_user will stop inside user space as there will be nothing mapped after __UA_LIMIT. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH -next] MIPS: Alchemy: Use DEFINE_SPINLOCK() for spinlock
On Sat, Mar 27, 2021 at 05:52:25PM +0800, Chen Lifu wrote: > From: Lifu Chen > > spinlock can be initialized automatically with DEFINE_SPINLOCK() > rather than explicitly calling spin_lock_init(). > > Reported-by: Hulk Robot > Signed-off-by: Lifu Chen > --- > arch/mips/alchemy/common/clock.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: generic: Update node names to avoid unit addresses
On Fri, Apr 09, 2021 at 12:21:28PM -0700, Nathan Chancellor wrote: > With the latest mkimage from U-Boot 2021.04, the generic defconfigs no > longer build, failing with: > > /usr/bin/mkimage: verify_header failed for FIT Image support with exit code 1 > > This is expected after the linked U-Boot commits because '@' is > forbidden in the node names due to the way that libfdt treats nodes with > the same prefix but different unit addresses. > > Switch the '@' in the node name to '-'. Drop the unit addresses from the > hash and kernel child nodes because there is only one node so they do > not need to have a number to differentiate them. > > Cc: sta...@vger.kernel.org > Link: > https://source.denx.de/u-boot/u-boot/-/commit/79af75f7776fc20b0d7eb6afe1e27c00fdb4b9b4 > Link: > https://source.denx.de/u-boot/u-boot/-/commit/3f04db891a353f4b127ed57279279f851c6b4917 > Suggested-by: Simon Glass > Signed-off-by: Nathan Chancellor > --- > arch/mips/generic/board-boston.its.S | 10 +- > arch/mips/generic/board-jaguar2.its.S | 16 > arch/mips/generic/board-luton.its.S| 8 > arch/mips/generic/board-ni169445.its.S | 10 +- > arch/mips/generic/board-ocelot.its.S | 20 ++-- > arch/mips/generic/board-serval.its.S | 8 > arch/mips/generic/board-xilfpga.its.S | 10 +- > arch/mips/generic/vmlinux.its.S| 10 +- > 8 files changed, 46 insertions(+), 46 deletions(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v3] MIPS: add support for buggy MT7621S core detection
On Wed, Apr 07, 2021 at 01:07:38PM -0700, Ilya Lipnitskiy wrote: > Most MT7621 SoCs have 2 cores, which is detected and supported properly > by CPS. > > Unfortunately, MT7621 SoC has a less common S variant with only one core. > On MT7621S, GCR_CONFIG still reports 2 cores, which leads to hangs when > starting SMP. CPULAUNCH registers can be used in that case to detect the > absence of the second core and override the GCR_CONFIG PCORES field. > > Rework a long-standing OpenWrt patch to override the value of > mips_cps_numcores on single-core MT7621 systems. > > Tested on a dual-core MT7621 device (Ubiquiti ER-X) and a single-core > MT7621 device (Netgear R6220). > > Original 4.14 OpenWrt patch: > Link: > https://git.openwrt.org/?p=openwrt/openwrt.git;a=commitdiff;h=4cdbc90a376dd0555201c1434a2081e055e9ceb7 > Current 5.10 OpenWrt patch: > Link: > https://git.openwrt.org/?p=openwrt/openwrt.git;a=blob;f=target/linux/ramips/patches-5.10/320-mt7621-core-detect-hack.patch;h=c63f0f4c1ec742e24d8480e80553863744b58f6a;hb=10267e17299806f9885d086147878f6c492cb904 > > Suggested-by: Felix Fietkau > Signed-off-by: Ilya Lipnitskiy > --- > arch/mips/include/asm/mips-cps.h | 23 ++- > 1 file changed, 22 insertions(+), 1 deletion(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: uaccess: Reduce number of nested macros
On Thu, Apr 08, 2021 at 08:14:37PM +0200, Thomas Bogendoerfer wrote: > Clean up macros even further after removal get_fs/set_fs. > > Signed-off-by: Thomas Bogendoerfer > --- > arch/mips/include/asm/uaccess.h | 157 +++- > 1 file changed, 71 insertions(+), 86 deletions(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: Fix strnlen_user access check
On Mon, Apr 12, 2021 at 11:02:19AM +0800, Tiezhu Yang wrote: > On 04/11/2021 07:04 PM, Jinyang He wrote: > > Commit 04324f44cb69 ("MIPS: Remove get_fs/set_fs") brought a problem for > > strnlen_user(). Jump out when checking access_ok() with condition that > > (s + strlen(s)) < __UA_LIMIT <= (s + n). The old __strnlen_user_asm() > > just checked (ua_limit & s) without checking (ua_limit & (s + n)). > > Therefore, find strlen form s to __UA_LIMIT - 1 in that condition. > > > > Signed-off-by: Jinyang He > > --- > > arch/mips/include/asm/uaccess.h | 11 +-- > > 1 file changed, 9 insertions(+), 2 deletions(-) > > > > diff --git a/arch/mips/include/asm/uaccess.h > > b/arch/mips/include/asm/uaccess.h > > index 91bc7fb..85ba0c8 100644 > > --- a/arch/mips/include/asm/uaccess.h > > +++ b/arch/mips/include/asm/uaccess.h > > @@ -630,8 +630,15 @@ static inline long strnlen_user(const char __user *s, > > long n) > > { > > long res; > > - if (!access_ok(s, n)) > > - return -0; > > + if (unlikely(n <= 0)) > > + return 0; > > + > > + if (!access_ok(s, n)) { > > + if (!access_ok(s, 0)) > > + return 0; > > + > > + n = __UA_LIMIT - (unsigned long)s - 1; > > + } > > might_fault(); > > __asm__ __volatile__( > > The following simple changes are OK to fix this issue? > > diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h > index 91bc7fb..eafc99b 100644 > --- a/arch/mips/include/asm/uaccess.h > +++ b/arch/mips/include/asm/uaccess.h > @@ -630,8 +630,8 @@ static inline long strnlen_user(const char __user *s, > long n) > { > long res; > - if (!access_ok(s, n)) > - return -0; > + if (!access_ok(s, 1)) > + return 0; > might_fault(); > __asm__ __volatile__( that's the fix I'd like to apply. Could someone send it as a formal patch ? Thanks. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v2 1/1] kernel.h: Split out panic and oops helpers
On Fri, Apr 09, 2021 at 01:02:50PM +0300, Andy Shevchenko wrote: > kernel.h is being used as a dump for all kinds of stuff for a long time. > Here is the attempt to start cleaning it up by splitting out panic and > oops helpers. > > There are several purposes of doing this: > - dropping dependency in bug.h > - dropping a loop by moving out panic_notifier.h > - unload kernel.h from something which has its own domain > > At the same time convert users tree-wide to use new headers, although > for the time being include new header back to kernel.h to avoid twisted > indirected includes for existing users. > > Signed-off-by: Andy Shevchenko > Reviewed-by: Bjorn Andersson > Acked-by: Mike Rapoport > Acked-by: Corey Minyard > Acked-by: Christian Brauner > Acked-by: Arnd Bergmann > Acked-by: Kees Cook > Acked-by: Wei Liu > Acked-by: Rasmus Villemoes > Signed-off-by: Andrew Morton > --- > v2: > - fixed all errors with allmodconfig on x86_64 (Andrew) > - checked with allyesconfig on x86_64 > - additionally grepped source code for panic notifier list usage >and converted all users > - elaborated commit message (Luis) > - collected given tags (incl. Andrew's SoB, see below) > > I added Andrew's SoB since part of the fixes I took from him. Andrew, > feel free to amend or tell me how you want me to do. > > arch/mips/kernel/relocate.c | 1 + > arch/mips/sgi-ip22/ip22-reset.c | 1 + > arch/mips/sgi-ip32/ip32-reset.c | 1 + Acked-by: Thomas Bogendoerfer -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: build failure of malta_qemu_32r6_defconfig
On Thu, Apr 08, 2021 at 09:42:11AM +0800, YunQiang Su wrote: > Sudip Mukherjee 于2021年4月8日周四 上午2:26写道: > > > > Hi Thomas, > > > > I was building v5.10.28 with malta_qemu_32r6_defconfig and noticed that > > it fails to build, so tried next-20210407 to see if it has been fixed. > > But linux-next also has the issue with gcc-10. > > > > The error is: > > > > ./arch/mips/include/asm/vdso/gettimeofday.h: In function > > '__vdso_clock_gettime': > > ./arch/mips/include/asm/vdso/gettimeofday.h:103:2: error: the register 'lo' > > cannot be clobbered in 'asm' for the current target > > 103 | asm volatile( > > | ^~~ > > this operation try to save lo and hi register, while they are not > exisiting on r6. > We are working on figure out a patch for it. looks like there is already a patch in patchwork, which just needs a workup: https://patchwork.kernel.org/project/linux-mips/patch/20200801154401.4177009-1-romain.na...@gmail.com/ Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: octeon: Add __raw_copy_[from|to|in]_user symbols
On Fri, Apr 09, 2021 at 11:42:46AM +0300, Sergei Shtylyov wrote: > Hello! > > On 09.04.2021 0:48, Thomas Bogendoerfer wrote: > > > Cavium Octeon has it's own memcpy implementation and also need the change > >Its. :-) applied (with typo fixed) to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH] MIPS: octeon: Add __raw_copy_[from|to|in]_user symbols
Cavium Octeon has it's own memcpy implementation and also need the change done in commit 04324f44cb69 ("MIPS: Remove get_fs/set_fs"). Fixes: 04324f44cb69 ("MIPS: Remove get_fs/set_fs") Reported-by: kernel test robot Signed-off-by: Thomas Bogendoerfer --- arch/mips/cavium-octeon/octeon-memcpy.S | 8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/mips/cavium-octeon/octeon-memcpy.S b/arch/mips/cavium-octeon/octeon-memcpy.S index 0a7c9834b81c..600d018cf354 100644 --- a/arch/mips/cavium-octeon/octeon-memcpy.S +++ b/arch/mips/cavium-octeon/octeon-memcpy.S @@ -150,8 +150,12 @@ LEAF(memcpy) /* a0=dst a1=src a2=len */ EXPORT_SYMBOL(memcpy) movev0, dst /* return value */ __memcpy: -FEXPORT(__copy_user) -EXPORT_SYMBOL(__copy_user) +FEXPORT(__raw_copy_from_user) +EXPORT_SYMBOL(__raw_copy_from_user) +FEXPORT(__raw_copy_to_user) +EXPORT_SYMBOL(__raw_copy_to_user) +FEXPORT(__raw_copy_in_user) +EXPORT_SYMBOL(__raw_copy_in_user) /* * Note: dst & src may be unaligned, len may be 0 * Temps -- 2.29.2
Re: [PATCH] MIPS: uaccess: Reduce number of nested macros
On Thu, Apr 08, 2021 at 09:46:11PM +0200, Christoph Hellwig wrote: > > +#define put_user(x, ptr) \ > > +({ \ > > + __typeof__(*(ptr)) __user *__p = (ptr); \ > > + \ > > + might_fault(); \ > > + access_ok(__p, sizeof(*__p)) ? \ > > + __put_user((x), __p) : \ > > + -EFAULT;\ > > Why not merge this into a single line, which seems a little more > readable: > > access_ok(__p, sizeof(*__p)) ? __put_user((x), __p) : -EFAULT; \ I just copied the riscv version ;-) I'll make it one line before applying. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH] MIPS: uaccess: Reduce number of nested macros
Clean up macros even further after removal get_fs/set_fs. Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/uaccess.h | 157 +++- 1 file changed, 71 insertions(+), 86 deletions(-) diff --git a/arch/mips/include/asm/uaccess.h b/arch/mips/include/asm/uaccess.h index 91bc7fb7dca1..e0dedd47e4e6 100644 --- a/arch/mips/include/asm/uaccess.h +++ b/arch/mips/include/asm/uaccess.h @@ -102,8 +102,15 @@ static inline int __access_ok(const void __user *p, unsigned long size) * * Returns zero on success, or -EFAULT on error. */ -#define put_user(x,ptr) \ - __put_user_check((x), (ptr), sizeof(*(ptr))) +#define put_user(x, ptr) \ +({ \ + __typeof__(*(ptr)) __user *__p = (ptr); \ + \ + might_fault(); \ + access_ok(__p, sizeof(*__p)) ? \ + __put_user((x), __p) : \ + -EFAULT;\ +}) /* * get_user: - Get a simple variable from user space. @@ -123,8 +130,15 @@ static inline int __access_ok(const void __user *p, unsigned long size) * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define get_user(x,ptr) \ - __get_user_check((x), (ptr), sizeof(*(ptr))) +#define get_user(x, ptr) \ +({ \ + const __typeof__(*(ptr)) __user *__p = (ptr); \ + \ + might_fault(); \ + access_ok(__p, sizeof(*__p)) ? \ + __get_user((x), __p) : \ + ((x) = 0, -EFAULT); \ +}) /* * __put_user: - Write a simple value into user space, with less checking. @@ -146,8 +160,32 @@ static inline int __access_ok(const void __user *p, unsigned long size) * * Returns zero on success, or -EFAULT on error. */ -#define __put_user(x,ptr) \ - __put_user_nocheck((x), (ptr), sizeof(*(ptr))) +#define __put_user(x, ptr) \ +({ \ + __typeof__(*(ptr)) __user *__pu_ptr = (ptr);\ + __typeof__(*(ptr)) __pu_val = (x); \ + int __pu_err = 0; \ + \ + __chk_user_ptr(__pu_ptr); \ + switch (sizeof(*__pu_ptr)) {\ + case 1: \ + __put_data_asm(user_sb, __pu_ptr); \ + break; \ + case 2: \ + __put_data_asm(user_sh, __pu_ptr); \ + break; \ + case 4: \ + __put_data_asm(user_sw, __pu_ptr); \ + break; \ + case 8: \ + __PUT_DW(user_sd, __pu_ptr);\ + break; \ + default:\ + BUILD_BUG();\ + } \ + \ + __pu_err; \ +}) /* * __get_user: - Get a simple variable from user space, with less checking. @@ -170,8 +208,31 @@ static inline int __access_ok(const void __user *p, unsigned long size) * Returns zero on success, or -EFAULT on error. * On error, the variable @x is set to zero. */ -#define __get_user(x,ptr) \ - __get_user_nocheck((x), (ptr), sizeof(*(ptr))) +#define __get_user(x, ptr) \ +({ \ + const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + int __gu_err = 0
Re: [PATCH] MIPS: Fix new sparse warning
On Wed, Apr 07, 2021 at 01:03:48AM +0200, Thomas Bogendoerfer wrote: > Commit 45deb5faeb9e ("MIPS: uaccess: Remove get_fs/set_fs call sites") > caused a few new sparse warning, fix them. > > Signed-off-by: Thomas Bogendoerfer > --- > arch/mips/kernel/access-helper.h | 7 --- > arch/mips/kernel/unaligned.c | 6 +++--- > 2 files changed, 7 insertions(+), 6 deletions(-) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
[PATCH] MIPS: Fix new sparse warning
Commit 45deb5faeb9e ("MIPS: uaccess: Remove get_fs/set_fs call sites") caused a few new sparse warning, fix them. Signed-off-by: Thomas Bogendoerfer --- arch/mips/kernel/access-helper.h | 7 --- arch/mips/kernel/unaligned.c | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/arch/mips/kernel/access-helper.h b/arch/mips/kernel/access-helper.h index dd5b502813b8..590388031503 100644 --- a/arch/mips/kernel/access-helper.h +++ b/arch/mips/kernel/access-helper.h @@ -4,15 +4,16 @@ static inline int __get_addr(unsigned long *a, unsigned long *p, bool user) { - return user ? get_user(*a, p) : get_kernel_nofault(*a, p); + return user ? get_user(*a, (unsigned long __user *)p) : + get_kernel_nofault(*a, p); } static inline int __get_inst16(u16 *i, u16 *p, bool user) { - return user ? get_user(*i, p) : get_kernel_nofault(*i, p); + return user ? get_user(*i, (u16 __user *)p) : get_kernel_nofault(*i, p); } static inline int __get_inst32(u32 *i, u32 *p, bool user) { - return user ? get_user(*i, p) : get_kernel_nofault(*i, p); + return user ? get_user(*i, (u32 __user *)p) : get_kernel_nofault(*i, p); } diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index 1f3b20a8c377..df4b708c04a9 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c @@ -109,7 +109,7 @@ static u32 unaligned_action; extern void show_registers(struct pt_regs *regs); static void emulate_load_store_insn(struct pt_regs *regs, - void __user *addr, unsigned int __user *pc) + void __user *addr, unsigned int *pc) { unsigned long origpc, orig31, value; union mips_instruction insn; @@ -1475,7 +1475,7 @@ static void emulate_load_store_MIPS16e(struct pt_regs *regs, void __user * addr) asmlinkage void do_ade(struct pt_regs *regs) { enum ctx_state prev_state; - unsigned int __user *pc; + unsigned int *pc; prev_state = exception_enter(); perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, @@ -1526,7 +1526,7 @@ asmlinkage void do_ade(struct pt_regs *regs) if (unaligned_action == UNALIGNED_ACTION_SHOW) show_registers(regs); - pc = (unsigned int __user *)exception_epc(regs); + pc = (unsigned int *)exception_epc(regs); emulate_load_store_insn(regs, (void __user *)regs->cp0_badvaddr, pc); -- 2.29.2
Re: [PATCH v4] MIPS: Add support for CONFIG_DEBUG_VIRTUAL
On Tue, Mar 30, 2021 at 08:22:07PM -0700, Florian Fainelli wrote: > Provide hooks to intercept bad usages of virt_to_phys() and > __pa_symbol() throughout the kernel. To make this possible, we need to > rename the current implement of virt_to_phys() into > __virt_to_phys_nodebug() and wrap it around depending on > CONFIG_DEBUG_VIRTUAL. > > A similar thing is needed for __pa_symbol() which is now aliased to > __phys_addr_symbol() whose implementation is either the direct return of > RELOC_HIDE or goes through the debug version. > > Signed-off-by: Florian Fainelli > --- > Changes in v4: > > - properly address sparse warning in arch/mips/kernel/vdso.c and > eliminate it entirely > > Changes in v3: > > - added missing SDPX license tag in physaddr.c > > Changes in v2: > - fixed sparse warning in arch/mips/kernel/vdso.c > > arch/mips/Kconfig| 1 + > arch/mips/include/asm/io.h | 14 - > arch/mips/include/asm/page.h | 9 +- > arch/mips/kernel/vdso.c | 5 ++-- > arch/mips/mm/Makefile| 2 ++ > arch/mips/mm/physaddr.c | 56 > 6 files changed, 83 insertions(+), 4 deletions(-) > create mode 100644 arch/mips/mm/physaddr.c applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v2 0/6] mips: bmips: fix and improve reboot nodes
On Sun, Mar 14, 2021 at 05:43:45PM +0100, Álvaro Fernández Rojas wrote: > These patches improve bmips bcm63xx device tree nodes. > > v2: add missing BCM63268 patch. > > Álvaro Fernández Rojas (6): > mips: bmips: fix syscon-reboot nodes > mips: bmips: bcm6328: populate device tree nodes > mips: bmips: bcm6358: populate device tree nodes > mips: bmips: bcm6362: populate device tree nodes > mips: bmips: bcm6368: populate device tree nodes > mips: bmips: bcm63268: populate device tree nodes > > arch/mips/boot/dts/brcm/bcm3368.dtsi | 2 +- > arch/mips/boot/dts/brcm/bcm63268.dtsi | 132 +++--- > arch/mips/boot/dts/brcm/bcm6328.dtsi | 119 --- > arch/mips/boot/dts/brcm/bcm6358.dtsi | 85 ++--- > arch/mips/boot/dts/brcm/bcm6362.dtsi | 129 ++--- > arch/mips/boot/dts/brcm/bcm6368.dtsi | 129 ++--- > 6 files changed, 530 insertions(+), 66 deletions(-) series applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v3 0/4] MIPS: Remove get_fs/set_fs
On Thu, Apr 01, 2021 at 02:56:33PM +0200, Thomas Bogendoerfer wrote: > This series replaces get_fs/set_fs and removes it from MIPS arch code. > > Changes in v3: > - use get_user/get_kernel_nofault for helper functions > > Changes in v2: > - added copy_from_kernel_nofault_allowed() for !EVA to restrict > access of __get/__put_kernel_nofault > - replaced __get_data macro by helper functions > - removed leftover set_fs calls in ftrace.c > - further cleanup uaccess.h > > Thomas Bogendoerfer (4): > MIPS: kernel: Remove not needed set_fs calls > MIPS: uaccess: Added __get/__put_kernel_nofault > MIPS: uaccess: Remove get_fs/set_fs call sites > MIPS: Remove get_fs/set_fs > > arch/mips/Kconfig | 1 - > arch/mips/include/asm/processor.h | 4 - > arch/mips/include/asm/thread_info.h | 6 - > arch/mips/include/asm/uaccess.h | 436 +++- > arch/mips/kernel/access-helper.h| 18 ++ > arch/mips/kernel/asm-offsets.c | 1 - > arch/mips/kernel/ftrace.c | 8 - > arch/mips/kernel/process.c | 2 - > arch/mips/kernel/scall32-o32.S | 4 +- > arch/mips/kernel/traps.c| 105 +++ > arch/mips/kernel/unaligned.c| 199 + > arch/mips/lib/memcpy.S | 28 +- > arch/mips/lib/memset.S | 3 - > arch/mips/lib/strncpy_user.S| 48 +-- > arch/mips/lib/strnlen_user.S| 44 +-- > arch/mips/mm/Makefile | 4 + > arch/mips/mm/maccess.c | 10 + > 17 files changed, 357 insertions(+), 564 deletions(-) > create mode 100644 arch/mips/kernel/access-helper.h > create mode 100644 arch/mips/mm/maccess.c series applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: fix memory reservation for non-usermem setups
On Sat, Apr 03, 2021 at 07:02:13PM -0700, Ilya Lipnitskiy wrote: > Hi Mike, > > On Tue, Mar 16, 2021 at 11:33 PM Mike Rapoport wrote: > > > > Hi Ilya, > > > > On Tue, Mar 16, 2021 at 10:10:09PM -0700, Ilya Lipnitskiy wrote: > > > Hi Thomas, > > > > > > On Fri, Mar 12, 2021 at 7:19 AM Thomas Bogendoerfer > > > wrote: > > > > > > > > On Sun, Mar 07, 2021 at 11:40:30AM -0800, Ilya Lipnitskiy wrote: > > > > > From: Tobias Wolf > > > > > > > > > > Commit 67a3ba25aa95 ("MIPS: Fix incorrect mem=X@Y handling") > > > > > introduced a new > > > > > issue for rt288x where "PHYS_OFFSET" is 0x0 but the calculated > > > > > "ramstart" is > > > > > not. As the prerequisite of custom memory map has been removed, this > > > > > results > > > > > in the full memory range of 0x0 - 0x800 to be marked as reserved > > > > > for this > > > > > platform. > > > > > > > > and where is the problem here ? > > > Turns out this was already attempted to be upstreamed - not clear why > > > it wasn't merged. Context: > > > https://lore.kernel.org/linux-mips/6504517.U6H5IhoIOn@loki/ > > > > > > I hope the thread above helps you understand the problem. > > > > The memory initialization was a bit different then. Do you still see the > > same problem? > Thanks for asking. I obtained a RT2880 device and gave it a try. It > hangs at boot without this patch, however selecting can you provide debug logs with memblock=debug for both good and bad kernels ? I'm curious what's the reason for failing allocation... Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH v3 0/4] MIPS: Remove get_fs/set_fs
On Tue, Apr 06, 2021 at 09:24:43AM +0200, Christoph Hellwig wrote: > Btw, there is a bunch of cleanups that would fit in nicely on top of > this: > > - remove the unused __invoke_copy_from function I've removed in the last patch before applying to mips-next. > - fold __get_user_check into get_user as it is the only caller > - fold __get_user_nocheck into __get_user as it is the only caller > - fold __put_user_check into put_user as it is the only caller > - fold __put_user_nocheck into __put_user as it is the only caller > - implement get_user in terms of __get_user to document the difference >better and to remove __get_user_common > - implement put_user in terms of __put_user to document the difference >better and to remove __get_user_common > - remove __put_user_unknown/__get_user_unknown and replace them with >BUILD_BUG_ON() I'll prepare a follow-up patch. Thank you for your cleanup hints. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH RFC] MIPS: Loongson64: Use _CACHE_UNCACHED instead of _CACHE_UNCACHED_ACCELERATED
On Tue, Apr 06, 2021 at 05:25:12PM +0800, Tiezhu Yang wrote: > Loongson64 processors have a writecombine issue that maybe failed to > write back framebuffer used with ATI Radeon or AMD GPU at times, after > commit 8a08e50cee66 ("drm: Permit video-buffers writecombine mapping > for MIPS"), there exists some errors such as blurred screen and lockup, > and so on. > > [ 60.958721] radeon :03:00.0: ring 0 stalled for more than 10079msec > [ 60.965315] radeon :03:00.0: GPU lockup (current fence id > 0x0112 last fence id 0x011d on ring 0) > [ 60.976525] radeon :03:00.0: ring 3 stalled for more than 10086msec > [ 60.983156] radeon :03:00.0: GPU lockup (current fence id > 0x0374 last fence id 0x03a8 on ring 3) > > As discussed earlier [1], it might be better to disable writecombine > on the CPU detection side because the root cause is unknown now. > > Actually, this patch is a temporary solution to just make it work well, > it is not a proper and final solution, I hope someone will have a better > solution to fix this issue in the future. > > [1] https://lore.kernel.org/patchwork/patch/1285542/ > > Signed-off-by: Tiezhu Yang > --- > > Hi Thomas, > > If you are OK with this change, could you please apply it > to mips-next? Then, no need to do this change manually every > time when update the mainline kernel. looks good to me, applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH] MIPS: ralink: rt288x: select MIPS_AUTO_PFN_OFFSET
On Sat, Apr 03, 2021 at 07:11:26PM -0700, Ilya Lipnitskiy wrote: > RT288X systems may have a non-zero ramstart causing problems with memory > reservations and boot hangs, as well as messages like: > Wasting 1048576 bytes for tracking 32768 unused pages > > Both are alleviated by selecting MIPS_AUTO_PFN_OFFSET for such > platforms. > > Tested on a Belkin F5D8235 v1 RT2880 device. > > Link: > https://lore.kernel.org/linux-mips/20180820233111.xww5232dxbuouf4n@pburton-laptop/ > > Signed-off-by: Ilya Lipnitskiy > Cc: Mike Rapoport > --- > arch/mips/ralink/Kconfig | 1 + > 1 file changed, 1 insertion(+) applied to mips-next. Thomas. -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]
Re: [PATCH 6/9] mips: netlogic: Use irq_domain_simple_ops for XLP PIC
On Tue, Apr 06, 2021 at 10:35:54AM +0100, Marc Zyngier wrote: > Use the generic irq_domain_simple_ops structure instead of > a home-grown one. > > Signed-off-by: Marc Zyngier > --- > arch/mips/netlogic/common/irq.c | 6 +- > 1 file changed, 1 insertion(+), 5 deletions(-) Acked-by: Thomas Bogendoerfer -- Crap can work. Given enough thrust pigs will fly, but it's not necessarily a good idea.[ RFC1925, 2.3 ]