[<prev] [next>] [day] [month] [year] [list]
Message-Id: <200812191121.22860.oliver@neukum.org>
Date: Fri, 19 Dec 2008 11:21:21 +0100
From: Oliver Neukum <oliver@...kum.org>
To: ajb@...eresystems.co.uk, "Greg Kroah-Hartman" <greg@...ah.com>,
Denis Joseph Barrow <D.Barow@...ion.com>,
linux-usb@...r.kernel.org, netdev@...r.kernel.org
Subject: hso has a very nice race between hard_start_xmit and resume
Hi,
this one is beautiful. The hso driver has a race condition between
hard_start_xmit and resume, caused by using a workqueue. It starts here:
static int hso_net_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct hso_net *odev = netdev_priv(net);
int result;
/* Tell the kernel, "No more frames 'til we are done with this one." */
netif_stop_queue(net);
if (hso_get_activity(odev->parent) == -EAGAIN) {
here's the window
odev->skb_tx_buf = skb;
return 0;
}
hso_get_activity() schedules work which will call usb_autopm_get_interface.
It may run any time after that. In particular it may run before
odev->skb_tx_buf is set. If that happens resume will not submit
mux_bulk_tx_buf. Thus netif_start_queue() will not be called from
write_bulk_callback. Later on a timeout will strike which will do nothing
because the URB has never been submitted.
This will need some interesting locking because you cannot assume that
the driver's usb_autopm_get_interface will cause resume to run. Somebody
may be running lsusb causing an earlier resumption. So simply setting
odev->skb_tx_buf before you call hso_get_activity does not solve the problem.
Regards
Oliver
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists