Skip to content

Commit

Permalink
xen/netfront: fix waiting for xenbus state change
Browse files Browse the repository at this point in the history
commit 8edfe2e992b75aee3da9316e9697c531194c2f53 upstream.

Commit 822fb18a82aba ("xen-netfront: wait xenbus state change when load
module manually") added a new wait queue to wait on for a state change
when the module is loaded manually. Unfortunately there is no wakeup
anywhere to stop that waiting.

Instead of introducing a new wait queue rename the existing
module_unload_q to module_wq and use it for both purposes (loading and
unloading).

As any state change of the backend might be intended to stop waiting
do the wake_up_all() in any case when netback_changed() is called.

Fixes: 822fb18a82aba ("xen-netfront: wait xenbus state change when load module manually")
Cc: <stable@vger.kernel.org> TinkerBoard#4.18
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
jgross1 authored and gregkh committed Sep 26, 2018
1 parent 1cd01db commit a739cb3
Showing 1 changed file with 10 additions and 14 deletions.
24 changes: 10 additions & 14 deletions drivers/net/xen-netfront.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ struct netfront_cb {
/* IRQ name is queue name with "-tx" or "-rx" appended */
#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)

static DECLARE_WAIT_QUEUE_HEAD(module_load_q);
static DECLARE_WAIT_QUEUE_HEAD(module_unload_q);
static DECLARE_WAIT_QUEUE_HEAD(module_wq);

struct netfront_stats {
u64 packets;
Expand Down Expand Up @@ -1336,11 +1335,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
netif_carrier_off(netdev);

xenbus_switch_state(dev, XenbusStateInitialising);
wait_event(module_load_q,
xenbus_read_driver_state(dev->otherend) !=
XenbusStateClosed &&
xenbus_read_driver_state(dev->otherend) !=
XenbusStateUnknown);
wait_event(module_wq,
xenbus_read_driver_state(dev->otherend) !=
XenbusStateClosed &&
xenbus_read_driver_state(dev->otherend) !=
XenbusStateUnknown);
return netdev;

exit:
Expand Down Expand Up @@ -2025,15 +2024,14 @@ static void netback_changed(struct xenbus_device *dev,

dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));

wake_up_all(&module_wq);

switch (backend_state) {
case XenbusStateInitialising:
case XenbusStateInitialised:
case XenbusStateReconfiguring:
case XenbusStateReconfigured:
break;

case XenbusStateUnknown:
wake_up_all(&module_unload_q);
break;

case XenbusStateInitWait:
Expand All @@ -2049,12 +2047,10 @@ static void netback_changed(struct xenbus_device *dev,
break;

case XenbusStateClosed:
wake_up_all(&module_unload_q);
if (dev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
wake_up_all(&module_unload_q);
xenbus_frontend_closed(dev);
break;
}
Expand Down Expand Up @@ -2162,14 +2158,14 @@ static int xennet_remove(struct xenbus_device *dev)

if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
xenbus_switch_state(dev, XenbusStateClosing);
wait_event(module_unload_q,
wait_event(module_wq,
xenbus_read_driver_state(dev->otherend) ==
XenbusStateClosing ||
xenbus_read_driver_state(dev->otherend) ==
XenbusStateUnknown);

xenbus_switch_state(dev, XenbusStateClosed);
wait_event(module_unload_q,
wait_event(module_wq,
xenbus_read_driver_state(dev->otherend) ==
XenbusStateClosed ||
xenbus_read_driver_state(dev->otherend) ==
Expand Down

0 comments on commit a739cb3

Please sign in to comment.