mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 11:11:45 -04:00
usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop
This patch fixes an issue introduced by patch:
72c973d usb: gadget: add usb_endpoint_descriptor to struct usb_ep
Without this patch we see a kworker taking 100% CPU, after this sequence:
- Connect gadget to a windows host
- load g_ether
- ifconfig up <ip>; ifconfig down; ifconfig up
- ping <windows host>
The "ifconfig down" results in calling eth_stop(), which will call
usb_ep_disable() and, if the carrier is still ok, usb_ep_enable():
usb_ep_disable(link->in_ep);
usb_ep_disable(link->out_ep);
if (netif_carrier_ok(net)) {
usb_ep_enable(link->in_ep);
usb_ep_enable(link->out_ep);
}
The ep should stay enabled, but will not, as ep_disable set the desc
pointer to NULL, therefore the subsequent ep_enable will fail. This leads
to permanent rescheduling of the eth_work() worker as usb_ep_queue()
(called by the worker) will fail due to the unconfigured endpoint.
We fix this issue by saving the ep descriptors and re-assign them before
usb_ep_enable().
Cc: Tatyana Brokhman <[email protected]>
Signed-off-by: Michael Grzeschik <[email protected]>
Signed-off-by: Marc Kleine-Budde <[email protected]>
Cc: stable <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
parent
ecc8a0cdca
commit
b1b552a69b
1 changed files with 6 additions and 0 deletions
|
|
@ -669,6 +669,8 @@ static int eth_stop(struct net_device *net)
|
|||
spin_lock_irqsave(&dev->lock, flags);
|
||||
if (dev->port_usb) {
|
||||
struct gether *link = dev->port_usb;
|
||||
const struct usb_endpoint_descriptor *in;
|
||||
const struct usb_endpoint_descriptor *out;
|
||||
|
||||
if (link->close)
|
||||
link->close(link);
|
||||
|
|
@ -682,10 +684,14 @@ static int eth_stop(struct net_device *net)
|
|||
* their own pace; the network stack can handle old packets.
|
||||
* For the moment we leave this here, since it works.
|
||||
*/
|
||||
in = link->in_ep->desc;
|
||||
out = link->out_ep->desc;
|
||||
usb_ep_disable(link->in_ep);
|
||||
usb_ep_disable(link->out_ep);
|
||||
if (netif_carrier_ok(net)) {
|
||||
DBG(dev, "host still using in/out endpoints\n");
|
||||
link->in_ep->desc = in;
|
||||
link->out_ep->desc = out;
|
||||
usb_ep_enable(link->in_ep);
|
||||
usb_ep_enable(link->out_ep);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue