usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop
authorMichael Grzeschik <m.grzeschik@pengutronix.de>
Wed, 8 Aug 2012 09:48:10 +0000 (11:48 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 26 Aug 2012 22:00:45 +0000 (15:00 -0700)
commit4cfb77e8eeddabbca1173a0a704c4065c62c4d05
tree06192e73fe8e1a45e6dc1dd61059e5cd9906faa9
parent4893ce51af5c2ccdfabf8f7d34dd28cf84a8a06e
usb: gadget: u_ether: fix kworker 100% CPU issue with still used interfaces in eth_stop

commit b1b552a69b8805e7e338074a9e8b670b4a795218 upstream.

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 <tlinder@codeaurora.org>
Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/u_ether.c