[PATCH] phy: phy-brcm-usb-init: Fix power down USB 3.0 PHY when XHCI reenabled
Unset is required to enable USB 3.0 PHY when XHCI reenabled in response to setting PHY3_IDDQ_OVERRIDE in uninit(). Fixes: cd6f769fdea7 ("phy: phy-brcm-usb-init: Power down USB 3.0 PHY when XHCI disabled") Signed-off-by: Jaedon Shin --- drivers/phy/broadcom/phy-brcm-usb-init.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index 1b7febc43da9..29d2c3b1913a 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -962,6 +962,10 @@ void brcm_usb_init_xhci(struct brcm_usb_init_params *params) { void __iomem *ctrl = params->ctrl_regs; + USB_CTRL_UNSET(ctrl, USB30_PCTL, PHY3_IDDQ_OVERRIDE); + /* 1 millisecond - for USB clocks to settle down */ + usleep_range(1000, 2000); + if (BRCM_ID(params->family_id) == 0x7366) { /* * The PHY3_SOFT_RESETB bits default to the wrong state. -- 2.17.1
[PATCH] phy: phy-brcm-usb-init: Fix power down USB 3.0 PHY when XHCI reenabled
Unset is required to enable USB 3.0 PHY when XHCI reenabled in response to setting PHY3_IDDQ_OVERRIDE in uninit(). Fixes: cd6f769fdea7 ("phy: phy-brcm-usb-init: Power down USB 3.0 PHY when XHCI disabled") Signed-off-by: Jaedon Shin --- drivers/phy/broadcom/phy-brcm-usb-init.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/phy/broadcom/phy-brcm-usb-init.c b/drivers/phy/broadcom/phy-brcm-usb-init.c index 1b7febc43da9..29d2c3b1913a 100644 --- a/drivers/phy/broadcom/phy-brcm-usb-init.c +++ b/drivers/phy/broadcom/phy-brcm-usb-init.c @@ -962,6 +962,10 @@ void brcm_usb_init_xhci(struct brcm_usb_init_params *params) { void __iomem *ctrl = params->ctrl_regs; + USB_CTRL_UNSET(ctrl, USB30_PCTL, PHY3_IDDQ_OVERRIDE); + /* 1 millisecond - for USB clocks to settle down */ + usleep_range(1000, 2000); + if (BRCM_ID(params->family_id) == 0x7366) { /* * The PHY3_SOFT_RESETB bits default to the wrong state. -- 2.17.1
[PATCH] irqchip: Remove hashed address printing
Since commit ad67b74d2469 ("printk: hash addresses printed with %p") pointers are being hashed when printed. Displaying the virtual memory at bootup time is not helpful. so delete the prints. Signed-off-by: Jaedon Shin <jaedon.s...@gmail.com> --- drivers/irqchip/irq-bcm7038-l1.c | 3 --- drivers/irqchip/irq-bcm7120-l2.c | 3 --- drivers/irqchip/irq-brcmstb-l2.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 55cfb986225b..faf734ff4cf3 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -339,9 +339,6 @@ int __init bcm7038_l1_of_init(struct device_node *dn, goto out_unmap; } - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", - intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); - return 0; out_unmap: diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 983640eba418..8968e5e93fcb 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c @@ -318,9 +318,6 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, } } - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", - intc_name, data->map_base[0], data->num_parent_irqs); - return 0; out_free_domain: diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 691d20eb0bec..0e65f609352e 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -262,9 +262,6 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, ct->chip.irq_set_wake = irq_gc_set_wake; } - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", - base, parent_irq); - return 0; out_free_domain: -- 2.16.1
[PATCH] irqchip: Remove hashed address printing
Since commit ad67b74d2469 ("printk: hash addresses printed with %p") pointers are being hashed when printed. Displaying the virtual memory at bootup time is not helpful. so delete the prints. Signed-off-by: Jaedon Shin --- drivers/irqchip/irq-bcm7038-l1.c | 3 --- drivers/irqchip/irq-bcm7120-l2.c | 3 --- drivers/irqchip/irq-brcmstb-l2.c | 3 --- 3 files changed, 9 deletions(-) diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 55cfb986225b..faf734ff4cf3 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -339,9 +339,6 @@ int __init bcm7038_l1_of_init(struct device_node *dn, goto out_unmap; } - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", - intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); - return 0; out_unmap: diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 983640eba418..8968e5e93fcb 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c @@ -318,9 +318,6 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, } } - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", - intc_name, data->map_base[0], data->num_parent_irqs); - return 0; out_free_domain: diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 691d20eb0bec..0e65f609352e 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -262,9 +262,6 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, ct->chip.irq_set_wake = irq_gc_set_wake; } - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", - base, parent_irq); - return 0; out_free_domain: -- 2.16.1
Re: [PATCH] irqchip: Use %px to print pointer value
> On 10 Feb 2018, at 1:04 AM, Marc Zyngier <marc.zyng...@arm.com> wrote: > > On 09/02/18 15:54, Florian Fainelli wrote: >> On February 9, 2018 12:51:33 AM PST, Marc Zyngier <marc.zyng...@arm.com> >> wrote: >>> On 09/02/18 02:10, Jaedon Shin wrote: >>>> Since commit ad67b74d2469 ("printk: hash addresses printed with %p") >>>> pointers printed with %p are hashed. Use %px instead of %p to print >>>> pointer value. >>>> >>>> Signed-off-by: Jaedon Shin <jaedon.s...@gmail.com> >>>> --- >>>> drivers/irqchip/irq-bcm7038-l1.c | 2 +- >>>> drivers/irqchip/irq-bcm7120-l2.c | 2 +- >>>> drivers/irqchip/irq-brcmstb-l2.c | 2 +- >>>> 3 files changed, 3 insertions(+), 3 deletions(-) >>>> >>>> diff --git a/drivers/irqchip/irq-bcm7038-l1.c >>> b/drivers/irqchip/irq-bcm7038-l1.c >>>> index 55cfb986225b..f604c1d89b3b 100644 >>>> --- a/drivers/irqchip/irq-bcm7038-l1.c >>>> +++ b/drivers/irqchip/irq-bcm7038-l1.c >>>> @@ -339,7 +339,7 @@ int __init bcm7038_l1_of_init(struct device_node >>> *dn, >>>>goto out_unmap; >>>>} >>>> >>>> - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", >>>> + pr_info("registered BCM7038 L1 intc (mem: 0x%px, IRQs: %d)\n", >>>>intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); >>>> >>>>return 0; >>>> diff --git a/drivers/irqchip/irq-bcm7120-l2.c >>> b/drivers/irqchip/irq-bcm7120-l2.c >>>> index 983640eba418..1cc4dd1d584a 100644 >>>> --- a/drivers/irqchip/irq-bcm7120-l2.c >>>> +++ b/drivers/irqchip/irq-bcm7120-l2.c >>>> @@ -318,7 +318,7 @@ static int __init bcm7120_l2_intc_probe(struct >>> device_node *dn, >>>>} >>>>} >>>> >>>> - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", >>>> + pr_info("registered %s intc (mem: 0x%px, parent IRQ(s): %d)\n", >>>>intc_name, data->map_base[0], data->num_parent_irqs); >>>> >>>>return 0; >>>> diff --git a/drivers/irqchip/irq-brcmstb-l2.c >>> b/drivers/irqchip/irq-brcmstb-l2.c >>>> index 691d20eb0bec..6760edeeb666 100644 >>>> --- a/drivers/irqchip/irq-brcmstb-l2.c >>>> +++ b/drivers/irqchip/irq-brcmstb-l2.c >>>> @@ -262,7 +262,7 @@ static int __init brcmstb_l2_intc_of_init(struct >>> device_node *np, >>>>ct->chip.irq_set_wake = irq_gc_set_wake; >>>>} >>>> >>>> - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", >>>> + pr_info("registered L2 intc (mem: 0x%px, parent irq: %d)\n", >>>>base, parent_irq); >>>> >>>>return 0; >>>> >>> >>> Why is that something useful to do? This just tells you where the >>> device >>> is mapped in the VA space, and I doubt that's a useful information, >>> hashed pointers or not. Am I missing something obvious? >> >> No you are right there is not much value in printing the register >> virtual address (sometimes there is e.g: on MIPS) either we fix the >> prints to show the physical address of the base register or we could >> possibly drop the prints entirely. > > Displaying the PA can be useful if you have several identical blocks in > your system and you want to be able to identify them. Given that there > is probably only one of these controllers per system, the address is > pretty pointless. > > If you send me a patch removing the prints, I'll queue it. > > Thanks, > > M. > -- > Jazz is not dead. It just smells funny... I'll submit a new one to drop the entire print. Thanks, Jaedon
Re: [PATCH] irqchip: Use %px to print pointer value
> On 10 Feb 2018, at 1:04 AM, Marc Zyngier wrote: > > On 09/02/18 15:54, Florian Fainelli wrote: >> On February 9, 2018 12:51:33 AM PST, Marc Zyngier >> wrote: >>> On 09/02/18 02:10, Jaedon Shin wrote: >>>> Since commit ad67b74d2469 ("printk: hash addresses printed with %p") >>>> pointers printed with %p are hashed. Use %px instead of %p to print >>>> pointer value. >>>> >>>> Signed-off-by: Jaedon Shin >>>> --- >>>> drivers/irqchip/irq-bcm7038-l1.c | 2 +- >>>> drivers/irqchip/irq-bcm7120-l2.c | 2 +- >>>> drivers/irqchip/irq-brcmstb-l2.c | 2 +- >>>> 3 files changed, 3 insertions(+), 3 deletions(-) >>>> >>>> diff --git a/drivers/irqchip/irq-bcm7038-l1.c >>> b/drivers/irqchip/irq-bcm7038-l1.c >>>> index 55cfb986225b..f604c1d89b3b 100644 >>>> --- a/drivers/irqchip/irq-bcm7038-l1.c >>>> +++ b/drivers/irqchip/irq-bcm7038-l1.c >>>> @@ -339,7 +339,7 @@ int __init bcm7038_l1_of_init(struct device_node >>> *dn, >>>>goto out_unmap; >>>>} >>>> >>>> - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", >>>> + pr_info("registered BCM7038 L1 intc (mem: 0x%px, IRQs: %d)\n", >>>>intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); >>>> >>>>return 0; >>>> diff --git a/drivers/irqchip/irq-bcm7120-l2.c >>> b/drivers/irqchip/irq-bcm7120-l2.c >>>> index 983640eba418..1cc4dd1d584a 100644 >>>> --- a/drivers/irqchip/irq-bcm7120-l2.c >>>> +++ b/drivers/irqchip/irq-bcm7120-l2.c >>>> @@ -318,7 +318,7 @@ static int __init bcm7120_l2_intc_probe(struct >>> device_node *dn, >>>>} >>>>} >>>> >>>> - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", >>>> + pr_info("registered %s intc (mem: 0x%px, parent IRQ(s): %d)\n", >>>>intc_name, data->map_base[0], data->num_parent_irqs); >>>> >>>>return 0; >>>> diff --git a/drivers/irqchip/irq-brcmstb-l2.c >>> b/drivers/irqchip/irq-brcmstb-l2.c >>>> index 691d20eb0bec..6760edeeb666 100644 >>>> --- a/drivers/irqchip/irq-brcmstb-l2.c >>>> +++ b/drivers/irqchip/irq-brcmstb-l2.c >>>> @@ -262,7 +262,7 @@ static int __init brcmstb_l2_intc_of_init(struct >>> device_node *np, >>>>ct->chip.irq_set_wake = irq_gc_set_wake; >>>>} >>>> >>>> - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", >>>> + pr_info("registered L2 intc (mem: 0x%px, parent irq: %d)\n", >>>>base, parent_irq); >>>> >>>>return 0; >>>> >>> >>> Why is that something useful to do? This just tells you where the >>> device >>> is mapped in the VA space, and I doubt that's a useful information, >>> hashed pointers or not. Am I missing something obvious? >> >> No you are right there is not much value in printing the register >> virtual address (sometimes there is e.g: on MIPS) either we fix the >> prints to show the physical address of the base register or we could >> possibly drop the prints entirely. > > Displaying the PA can be useful if you have several identical blocks in > your system and you want to be able to identify them. Given that there > is probably only one of these controllers per system, the address is > pretty pointless. > > If you send me a patch removing the prints, I'll queue it. > > Thanks, > > M. > -- > Jazz is not dead. It just smells funny... I'll submit a new one to drop the entire print. Thanks, Jaedon
[PATCH] irqchip: Use %px to print pointer value
Since commit ad67b74d2469 ("printk: hash addresses printed with %p") pointers printed with %p are hashed. Use %px instead of %p to print pointer value. Signed-off-by: Jaedon Shin <jaedon.s...@gmail.com> --- drivers/irqchip/irq-bcm7038-l1.c | 2 +- drivers/irqchip/irq-bcm7120-l2.c | 2 +- drivers/irqchip/irq-brcmstb-l2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 55cfb986225b..f604c1d89b3b 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -339,7 +339,7 @@ int __init bcm7038_l1_of_init(struct device_node *dn, goto out_unmap; } - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", + pr_info("registered BCM7038 L1 intc (mem: 0x%px, IRQs: %d)\n", intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); return 0; diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 983640eba418..1cc4dd1d584a 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c @@ -318,7 +318,7 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, } } - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", + pr_info("registered %s intc (mem: 0x%px, parent IRQ(s): %d)\n", intc_name, data->map_base[0], data->num_parent_irqs); return 0; diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 691d20eb0bec..6760edeeb666 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -262,7 +262,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, ct->chip.irq_set_wake = irq_gc_set_wake; } - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", + pr_info("registered L2 intc (mem: 0x%px, parent irq: %d)\n", base, parent_irq); return 0; -- 2.16.1
[PATCH] irqchip: Use %px to print pointer value
Since commit ad67b74d2469 ("printk: hash addresses printed with %p") pointers printed with %p are hashed. Use %px instead of %p to print pointer value. Signed-off-by: Jaedon Shin --- drivers/irqchip/irq-bcm7038-l1.c | 2 +- drivers/irqchip/irq-bcm7120-l2.c | 2 +- drivers/irqchip/irq-brcmstb-l2.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c index 55cfb986225b..f604c1d89b3b 100644 --- a/drivers/irqchip/irq-bcm7038-l1.c +++ b/drivers/irqchip/irq-bcm7038-l1.c @@ -339,7 +339,7 @@ int __init bcm7038_l1_of_init(struct device_node *dn, goto out_unmap; } - pr_info("registered BCM7038 L1 intc (mem: 0x%p, IRQs: %d)\n", + pr_info("registered BCM7038 L1 intc (mem: 0x%px, IRQs: %d)\n", intc->cpus[0]->map_base, IRQS_PER_WORD * intc->n_words); return 0; diff --git a/drivers/irqchip/irq-bcm7120-l2.c b/drivers/irqchip/irq-bcm7120-l2.c index 983640eba418..1cc4dd1d584a 100644 --- a/drivers/irqchip/irq-bcm7120-l2.c +++ b/drivers/irqchip/irq-bcm7120-l2.c @@ -318,7 +318,7 @@ static int __init bcm7120_l2_intc_probe(struct device_node *dn, } } - pr_info("registered %s intc (mem: 0x%p, parent IRQ(s): %d)\n", + pr_info("registered %s intc (mem: 0x%px, parent IRQ(s): %d)\n", intc_name, data->map_base[0], data->num_parent_irqs); return 0; diff --git a/drivers/irqchip/irq-brcmstb-l2.c b/drivers/irqchip/irq-brcmstb-l2.c index 691d20eb0bec..6760edeeb666 100644 --- a/drivers/irqchip/irq-brcmstb-l2.c +++ b/drivers/irqchip/irq-brcmstb-l2.c @@ -262,7 +262,7 @@ static int __init brcmstb_l2_intc_of_init(struct device_node *np, ct->chip.irq_set_wake = irq_gc_set_wake; } - pr_info("registered L2 intc (mem: 0x%p, parent irq: %d)\n", + pr_info("registered L2 intc (mem: 0x%px, parent irq: %d)\n", base, parent_irq); return 0; -- 2.16.1
[PATCH RESEND] media: dmxdev: fix possible race condition
This patch fixes race condition between dvb_dmxdev_buffer_read and dvb_demux_io_ioctl. There are race conditions executing DMX_ADD_PID or DMX_REMOVE_PID in the dvb_demux_ioctl when dvb_demux_read is waiting for the data by wait_event_interruptible. So, this fixes to sleep with acquired mutex and splits dvb_dmxdev_buffer_read into dvb_dvr_read. Signed-off-by: Jaedon Shin --- drivers/media/dvb-core/dmxdev.c | 94 - 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index abff803ad69a..c2564b0e389b 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -57,10 +57,11 @@ static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, return dvb_ringbuffer_write(buf, src, len); } -static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, +static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_filter *dmxdevfilter, int non_blocking, char __user *buf, size_t count, loff_t *ppos) { + struct dvb_ringbuffer *src = >buffer; size_t todo; ssize_t avail; ssize_t ret = 0; @@ -75,16 +76,21 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, } for (todo = count; todo > 0; todo -= ret) { - if (non_blocking && dvb_ringbuffer_empty(src)) { - ret = -EWOULDBLOCK; - break; - } + if (dvb_ringbuffer_empty(src)) { + mutex_unlock(>mutex); - ret = wait_event_interruptible(src->queue, - !dvb_ringbuffer_empty(src) || - (src->error != 0)); - if (ret < 0) - break; + if (non_blocking) + return -EWOULDBLOCK; + + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || + (src->error != 0)); + if (ret < 0) + return ret; + + if (mutex_lock_interruptible(>mutex)) + return -ERESTARTSYS; + } if (src->error) { ret = src->error; @@ -242,13 +248,63 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, { struct dvb_device *dvbdev = file->private_data; struct dmxdev *dmxdev = dvbdev->priv; + struct dvb_ringbuffer *src = >dvr_buffer; + size_t todo; + ssize_t avail; + ssize_t ret = 0; - if (dmxdev->exit) + if (mutex_lock_interruptible(>mutex)) + return -ERESTARTSYS; + + if (dmxdev->exit) { + mutex_unlock(>mutex); return -ENODEV; + } + + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + mutex_unlock(>mutex); + return ret; + } + + for (todo = count; todo > 0; todo -= ret) { + if (dvb_ringbuffer_empty(src)) { + mutex_unlock(>mutex); - return dvb_dmxdev_buffer_read(>dvr_buffer, - file->f_flags & O_NONBLOCK, - buf, count, ppos); + if (file->f_flags & O_NONBLOCK) + return -EWOULDBLOCK; + + ret = wait_event_interruptible(src->queue, + !dvb_ringbuffer_empty(src) || + (src->error != 0)); + if (ret < 0) + return ret; + + if (mutex_lock_interruptible(>mutex)) + return -ERESTARTSYS; + } + + if (src->error) { + ret = src->error; + dvb_ringbuffer_flush(src); + break; + } + + avail = dvb_ringbuffer_avail(src); + if (avail > todo) + avail = todo; + + ret = dvb_ringbuffer_read_user(src, buf, avail); + if (ret < 0) + break; + + buf += ret; + } + + mutex_unlock(>mutex); + + return (count - todo) ? (count - todo) : ret; } static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, @@ -283,7 +339,6 @@ static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, return 0; } - static inline void dvb_dmxdev_filter_state_set(struct
[PATCH RESEND] media: dmxdev: fix possible race condition
This patch fixes race condition between dvb_dmxdev_buffer_read and dvb_demux_io_ioctl. There are race conditions executing DMX_ADD_PID or DMX_REMOVE_PID in the dvb_demux_ioctl when dvb_demux_read is waiting for the data by wait_event_interruptible. So, this fixes to sleep with acquired mutex and splits dvb_dmxdev_buffer_read into dvb_dvr_read. Signed-off-by: Jaedon Shin jaedon.s...@gmail.com --- drivers/media/dvb-core/dmxdev.c | 94 - 1 file changed, 75 insertions(+), 19 deletions(-) diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c index abff803ad69a..c2564b0e389b 100644 --- a/drivers/media/dvb-core/dmxdev.c +++ b/drivers/media/dvb-core/dmxdev.c @@ -57,10 +57,11 @@ static int dvb_dmxdev_buffer_write(struct dvb_ringbuffer *buf, return dvb_ringbuffer_write(buf, src, len); } -static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, +static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_filter *dmxdevfilter, int non_blocking, char __user *buf, size_t count, loff_t *ppos) { + struct dvb_ringbuffer *src = dmxdevfilter-buffer; size_t todo; ssize_t avail; ssize_t ret = 0; @@ -75,16 +76,21 @@ static ssize_t dvb_dmxdev_buffer_read(struct dvb_ringbuffer *src, } for (todo = count; todo 0; todo -= ret) { - if (non_blocking dvb_ringbuffer_empty(src)) { - ret = -EWOULDBLOCK; - break; - } + if (dvb_ringbuffer_empty(src)) { + mutex_unlock(dmxdevfilter-mutex); - ret = wait_event_interruptible(src-queue, - !dvb_ringbuffer_empty(src) || - (src-error != 0)); - if (ret 0) - break; + if (non_blocking) + return -EWOULDBLOCK; + + ret = wait_event_interruptible(src-queue, + !dvb_ringbuffer_empty(src) || + (src-error != 0)); + if (ret 0) + return ret; + + if (mutex_lock_interruptible(dmxdevfilter-mutex)) + return -ERESTARTSYS; + } if (src-error) { ret = src-error; @@ -242,13 +248,63 @@ static ssize_t dvb_dvr_read(struct file *file, char __user *buf, size_t count, { struct dvb_device *dvbdev = file-private_data; struct dmxdev *dmxdev = dvbdev-priv; + struct dvb_ringbuffer *src = dmxdev-dvr_buffer; + size_t todo; + ssize_t avail; + ssize_t ret = 0; - if (dmxdev-exit) + if (mutex_lock_interruptible(dmxdev-mutex)) + return -ERESTARTSYS; + + if (dmxdev-exit) { + mutex_unlock(dmxdev-mutex); return -ENODEV; + } + + if (src-error) { + ret = src-error; + dvb_ringbuffer_flush(src); + mutex_unlock(dmxdev-mutex); + return ret; + } + + for (todo = count; todo 0; todo -= ret) { + if (dvb_ringbuffer_empty(src)) { + mutex_unlock(dmxdev-mutex); - return dvb_dmxdev_buffer_read(dmxdev-dvr_buffer, - file-f_flags O_NONBLOCK, - buf, count, ppos); + if (file-f_flags O_NONBLOCK) + return -EWOULDBLOCK; + + ret = wait_event_interruptible(src-queue, + !dvb_ringbuffer_empty(src) || + (src-error != 0)); + if (ret 0) + return ret; + + if (mutex_lock_interruptible(dmxdev-mutex)) + return -ERESTARTSYS; + } + + if (src-error) { + ret = src-error; + dvb_ringbuffer_flush(src); + break; + } + + avail = dvb_ringbuffer_avail(src); + if (avail todo) + avail = todo; + + ret = dvb_ringbuffer_read_user(src, buf, avail); + if (ret 0) + break; + + buf += ret; + } + + mutex_unlock(dmxdev-mutex); + + return (count - todo) ? (count - todo) : ret; } static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, @@ -283,7 +339,6 @@ static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev, return 0; } - static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter
[PATCH v3] net: bcmgenet: fix throughtput regression
This patch adds bcmgenet_tx_poll for the tx_rings. This can reduce the interrupt load and send xmit in network stack on time. This also separated for the completion of tx_ring16 from bcmgenet_poll. The bcmgenet_tx_reclaim of tx_ring[{0,1,2,3}] operative by an interrupt is to be not more than a certain number TxBDs. It is caused by too slowly reclaiming the transmitted skb. Therefore, performance degradation of xmit after 605ad7f ("tcp: refine TSO autosizing"). Signed-off-by: Jaedon Shin Signed-off-by: Florian Fainelli --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 111 +++-- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 + 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index ff83c46b..d2979ac 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -971,13 +971,14 @@ static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, } /* Unlocked version of the reclaim routine */ -static void __bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); int last_tx_cn, last_c_index, num_tx_bds; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; + unsigned int pkts_compl = 0; unsigned int bds_compl; unsigned int c_index; @@ -1005,6 +1006,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = ring->cbs + last_c_index; bds_compl = 0; if (tx_cb_ptr->skb) { + pkts_compl++; bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1; dev->stats.tx_bytes += tx_cb_ptr->skb->len; dma_unmap_single(>dev, @@ -1028,23 +1030,45 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, last_c_index &= (num_tx_bds - 1); } - if (ring->free_bds > (MAX_SKB_FRAGS + 1)) - ring->int_disable(priv, ring); - - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); + if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { + if (netif_tx_queue_stopped(txq)) + netif_tx_wake_queue(txq); + } ring->c_index = c_index; + + return pkts_compl; } -static void bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { + unsigned int released; unsigned long flags; spin_lock_irqsave(>lock, flags); - __bcmgenet_tx_reclaim(dev, ring); + released = __bcmgenet_tx_reclaim(dev, ring); spin_unlock_irqrestore(>lock, flags); + + return released; +} + +static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmgenet_tx_ring *ring = + container_of(napi, struct bcmgenet_tx_ring, napi); + unsigned int work_done = 0; + + work_done = bcmgenet_tx_reclaim(ring->priv->dev, ring); + + if (work_done == 0) { + napi_complete(napi); + ring->int_enable(ring->priv, ring); + + return 0; + } + + return budget; } static void bcmgenet_tx_reclaim_all(struct net_device *dev) @@ -1302,10 +1326,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) bcmgenet_tdma_ring_writel(priv, ring->index, ring->prod_index, TDMA_PROD_INDEX); - if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) { + if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); - ring->int_enable(priv, ring); - } out: spin_unlock_irqrestore(>lock, flags); @@ -1621,6 +1643,7 @@ static int init_umac(struct bcmgenet_priv *priv) struct device *kdev = >pdev->dev; int ret; u32 reg, cpu_mask_clear; + int index; dev_dbg(>pdev->dev, "bcmgenet: init_umac\n"); @@ -1647,7 +1670,7 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intr_disable(priv); - cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE; + cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__); @@ -1674,6 +1697,10 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); + for (index = 0; index < priv->hw_params->tx_queues; index++) + bcm
[PATCH v2] net: bcmgenet: fix throughtput regression
This patch adds bcmgenet_tx_poll for all active tx_rings. It can reduce the interrupt load and send xmit in upper network stack on time. The bcmgenet_tx_reclaim of tx_ring[{0,1,2,3}] process only under 18 descriptors is to late reclaiming transmitted skb. Therefore, performance degradation of xmit after 605ad7f ("tcp: refine TSO autosizing"). Signed-off-by: Jaedon Shin --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 111 +++-- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 + 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index ff83c46b..d18bea1 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -971,13 +971,14 @@ static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, } /* Unlocked version of the reclaim routine */ -static void __bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); int last_tx_cn, last_c_index, num_tx_bds; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; + unsigned int pkts_compl = 0; unsigned int bds_compl; unsigned int c_index; @@ -1005,6 +1006,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = ring->cbs + last_c_index; bds_compl = 0; if (tx_cb_ptr->skb) { + pkts_compl++; bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1; dev->stats.tx_bytes += tx_cb_ptr->skb->len; dma_unmap_single(>dev, @@ -1028,23 +1030,45 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, last_c_index &= (num_tx_bds - 1); } - if (ring->free_bds > (MAX_SKB_FRAGS + 1)) - ring->int_disable(priv, ring); - - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); + if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { + if (netif_tx_queue_stopped(txq)) + netif_tx_wake_queue(txq); + } ring->c_index = c_index; + + return pkts_compl; } -static void bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { + unsigned int released; unsigned long flags; spin_lock_irqsave(>lock, flags); - __bcmgenet_tx_reclaim(dev, ring); + released = __bcmgenet_tx_reclaim(dev, ring); spin_unlock_irqrestore(>lock, flags); + + return released; +} + +static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmgenet_tx_ring *ring = + container_of(napi, struct bcmgenet_tx_ring, napi); + unsigned int work_done = 0; + + work_done = bcmgenet_tx_reclaim(ring->priv->dev, ring); + + if (work_done == 0) { + napi_complete(napi); + ring->int_enable(ring->priv, ring); + + return 0; + } + + return budget; } static void bcmgenet_tx_reclaim_all(struct net_device *dev) @@ -1302,10 +1326,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) bcmgenet_tdma_ring_writel(priv, ring->index, ring->prod_index, TDMA_PROD_INDEX); - if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) { + if (ring->free_bds <= (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); - ring->int_enable(priv, ring); - } out: spin_unlock_irqrestore(>lock, flags); @@ -1647,7 +1669,7 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intr_disable(priv); - cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE; + cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; dev_dbg(kdev, "%s:Enabling RXDMA_BDONE interrupt\n", __func__); @@ -1693,6 +1715,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, unsigned int first_bd; spin_lock_init(>lock); + ring->priv = priv; + netif_napi_add(priv->dev, >napi, bcmgenet_tx_poll, 64); ring->index = index; if (index == DESC_INDEX) { ring->queue = 0; @@ -1738,6 +1762,17 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, TDMA_WRITE_PTR); bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1, DMA_END_ADDR); + + napi_enable(>napi); +} + +static void bcmgenet_fini_t
[PATCH v3] net: bcmgenet: fix throughtput regression
This patch adds bcmgenet_tx_poll for the tx_rings. This can reduce the interrupt load and send xmit in network stack on time. This also separated for the completion of tx_ring16 from bcmgenet_poll. The bcmgenet_tx_reclaim of tx_ring[{0,1,2,3}] operative by an interrupt is to be not more than a certain number TxBDs. It is caused by too slowly reclaiming the transmitted skb. Therefore, performance degradation of xmit after 605ad7f (tcp: refine TSO autosizing). Signed-off-by: Jaedon Shin jaedon.s...@gmail.com Signed-off-by: Florian Fainelli f.faine...@gmail.com --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 111 +++-- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 + 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index ff83c46b..d2979ac 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -971,13 +971,14 @@ static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, } /* Unlocked version of the reclaim routine */ -static void __bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); int last_tx_cn, last_c_index, num_tx_bds; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; + unsigned int pkts_compl = 0; unsigned int bds_compl; unsigned int c_index; @@ -1005,6 +1006,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = ring-cbs + last_c_index; bds_compl = 0; if (tx_cb_ptr-skb) { + pkts_compl++; bds_compl = skb_shinfo(tx_cb_ptr-skb)-nr_frags + 1; dev-stats.tx_bytes += tx_cb_ptr-skb-len; dma_unmap_single(dev-dev, @@ -1028,23 +1030,45 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, last_c_index = (num_tx_bds - 1); } - if (ring-free_bds (MAX_SKB_FRAGS + 1)) - ring-int_disable(priv, ring); - - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); + if (ring-free_bds (MAX_SKB_FRAGS + 1)) { + if (netif_tx_queue_stopped(txq)) + netif_tx_wake_queue(txq); + } ring-c_index = c_index; + + return pkts_compl; } -static void bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { + unsigned int released; unsigned long flags; spin_lock_irqsave(ring-lock, flags); - __bcmgenet_tx_reclaim(dev, ring); + released = __bcmgenet_tx_reclaim(dev, ring); spin_unlock_irqrestore(ring-lock, flags); + + return released; +} + +static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmgenet_tx_ring *ring = + container_of(napi, struct bcmgenet_tx_ring, napi); + unsigned int work_done = 0; + + work_done = bcmgenet_tx_reclaim(ring-priv-dev, ring); + + if (work_done == 0) { + napi_complete(napi); + ring-int_enable(ring-priv, ring); + + return 0; + } + + return budget; } static void bcmgenet_tx_reclaim_all(struct net_device *dev) @@ -1302,10 +1326,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) bcmgenet_tdma_ring_writel(priv, ring-index, ring-prod_index, TDMA_PROD_INDEX); - if (ring-free_bds = (MAX_SKB_FRAGS + 1)) { + if (ring-free_bds = (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); - ring-int_enable(priv, ring); - } out: spin_unlock_irqrestore(ring-lock, flags); @@ -1621,6 +1643,7 @@ static int init_umac(struct bcmgenet_priv *priv) struct device *kdev = priv-pdev-dev; int ret; u32 reg, cpu_mask_clear; + int index; dev_dbg(priv-pdev-dev, bcmgenet: init_umac\n); @@ -1647,7 +1670,7 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intr_disable(priv); - cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE; + cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; dev_dbg(kdev, %s:Enabling RXDMA_BDONE interrupt\n, __func__); @@ -1674,6 +1697,10 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intrl2_0_writel(priv, cpu_mask_clear, INTRL2_CPU_MASK_CLEAR); + for (index = 0; index priv-hw_params-tx_queues; index++) + bcmgenet_intrl2_1_writel(priv, (1 index), +INTRL2_CPU_MASK_CLEAR); + /* Enable rx
[PATCH v2] net: bcmgenet: fix throughtput regression
This patch adds bcmgenet_tx_poll for all active tx_rings. It can reduce the interrupt load and send xmit in upper network stack on time. The bcmgenet_tx_reclaim of tx_ring[{0,1,2,3}] process only under 18 descriptors is to late reclaiming transmitted skb. Therefore, performance degradation of xmit after 605ad7f (tcp: refine TSO autosizing). Signed-off-by: Jaedon Shin jaedon.s...@gmail.com --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 111 +++-- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 + 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index ff83c46b..d18bea1 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -971,13 +971,14 @@ static inline void bcmgenet_tx_ring_int_disable(struct bcmgenet_priv *priv, } /* Unlocked version of the reclaim routine */ -static void __bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); int last_tx_cn, last_c_index, num_tx_bds; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; + unsigned int pkts_compl = 0; unsigned int bds_compl; unsigned int c_index; @@ -1005,6 +1006,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = ring-cbs + last_c_index; bds_compl = 0; if (tx_cb_ptr-skb) { + pkts_compl++; bds_compl = skb_shinfo(tx_cb_ptr-skb)-nr_frags + 1; dev-stats.tx_bytes += tx_cb_ptr-skb-len; dma_unmap_single(dev-dev, @@ -1028,23 +1030,45 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, last_c_index = (num_tx_bds - 1); } - if (ring-free_bds (MAX_SKB_FRAGS + 1)) - ring-int_disable(priv, ring); - - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); + if (ring-free_bds (MAX_SKB_FRAGS + 1)) { + if (netif_tx_queue_stopped(txq)) + netif_tx_wake_queue(txq); + } ring-c_index = c_index; + + return pkts_compl; } -static void bcmgenet_tx_reclaim(struct net_device *dev, +static unsigned int bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { + unsigned int released; unsigned long flags; spin_lock_irqsave(ring-lock, flags); - __bcmgenet_tx_reclaim(dev, ring); + released = __bcmgenet_tx_reclaim(dev, ring); spin_unlock_irqrestore(ring-lock, flags); + + return released; +} + +static int bcmgenet_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmgenet_tx_ring *ring = + container_of(napi, struct bcmgenet_tx_ring, napi); + unsigned int work_done = 0; + + work_done = bcmgenet_tx_reclaim(ring-priv-dev, ring); + + if (work_done == 0) { + napi_complete(napi); + ring-int_enable(ring-priv, ring); + + return 0; + } + + return budget; } static void bcmgenet_tx_reclaim_all(struct net_device *dev) @@ -1302,10 +1326,8 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) bcmgenet_tdma_ring_writel(priv, ring-index, ring-prod_index, TDMA_PROD_INDEX); - if (ring-free_bds = (MAX_SKB_FRAGS + 1)) { + if (ring-free_bds = (MAX_SKB_FRAGS + 1)) netif_tx_stop_queue(txq); - ring-int_enable(priv, ring); - } out: spin_unlock_irqrestore(ring-lock, flags); @@ -1647,7 +1669,7 @@ static int init_umac(struct bcmgenet_priv *priv) bcmgenet_intr_disable(priv); - cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE; + cpu_mask_clear = UMAC_IRQ_RXDMA_BDONE | UMAC_IRQ_TXDMA_BDONE; dev_dbg(kdev, %s:Enabling RXDMA_BDONE interrupt\n, __func__); @@ -1693,6 +1715,8 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, unsigned int first_bd; spin_lock_init(ring-lock); + ring-priv = priv; + netif_napi_add(priv-dev, ring-napi, bcmgenet_tx_poll, 64); ring-index = index; if (index == DESC_INDEX) { ring-queue = 0; @@ -1738,6 +1762,17 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, TDMA_WRITE_PTR); bcmgenet_tdma_ring_writel(priv, index, end_ptr * words_per_bd - 1, DMA_END_ADDR); + + napi_enable(ring-napi); +} + +static void bcmgenet_fini_tx_ring(struct bcmgenet_priv *priv, + unsigned int index) +{ + struct