[PATCH] phy: phy-brcm-usb-init: Fix power down USB 3.0 PHY when XHCI reenabled

2018-06-08 Thread Jaedon Shin
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

2018-06-08 Thread Jaedon Shin
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

2018-02-11 Thread Jaedon Shin
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

2018-02-11 Thread Jaedon Shin
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

2018-02-09 Thread Jaedon Shin


> 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

2018-02-09 Thread Jaedon Shin


> 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

2018-02-08 Thread Jaedon Shin
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

2018-02-08 Thread Jaedon Shin
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

2015-03-24 Thread Jaedon Shin
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

2015-03-24 Thread Jaedon Shin
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

2015-02-27 Thread Jaedon Shin
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

2015-02-27 Thread Jaedon Shin
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

2015-02-27 Thread Jaedon Shin
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

2015-02-27 Thread Jaedon Shin
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