aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Durrant <paul.durrant@citrix.com>2013-10-08 09:22:56 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-04 07:31:01 -0500
commitf495ddc46f97dd0054ff2d5d3c7493d59f7511fb (patch)
tree71b6bfbe823d668d396022505eeb15c358751153
parentb9396c4c9e7f499b1dd8080e901c88705f2efa99 (diff)
xen-netback: Don't destroy the netdev until the vif is shut down
[ upstream commit id: 279f438e36c0a70b23b86d2090aeec50155034a9 ] Without this patch, if a frontend cycles through states Closing and Closed (which Windows frontends need to do) then the netdev will be destroyed and requires re-invocation of hotplug scripts to restore state before the frontend can move to Connected. Thus when udev is not in use the backend gets stuck in InitWait. With this patch, the netdev is left alone whilst the backend is still online and is only de-registered and freed just prior to destroying the vif (which is also nicely symmetrical with the netdev allocation and registration being done during probe) so no re-invocation of hotplug scripts is required. Signed-off-by: Paul Durrant <paul.durrant@citrix.com> Cc: David Vrabel <david.vrabel@citrix.com> Cc: Wei Liu <wei.liu2@citrix.com> Cc: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/net/xen-netback/common.h1
-rw-r--r--drivers/net/xen-netback/interface.c12
-rw-r--r--drivers/net/xen-netback/xenbus.c17
3 files changed, 23 insertions, 7 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h
index 9d7f1723dd8f..1a285083d24a 100644
--- a/drivers/net/xen-netback/common.h
+++ b/drivers/net/xen-netback/common.h
@@ -115,6 +115,7 @@ struct xenvif *xenvif_alloc(struct device *parent,
115int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, 115int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
116 unsigned long rx_ring_ref, unsigned int evtchn); 116 unsigned long rx_ring_ref, unsigned int evtchn);
117void xenvif_disconnect(struct xenvif *vif); 117void xenvif_disconnect(struct xenvif *vif);
118void xenvif_free(struct xenvif *vif);
118 119
119void xenvif_get(struct xenvif *vif); 120void xenvif_get(struct xenvif *vif);
120void xenvif_put(struct xenvif *vif); 121void xenvif_put(struct xenvif *vif);
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index d98414168485..3a294c2528d5 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -304,6 +304,9 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
304 } 304 }
305 305
306 netdev_dbg(dev, "Successfully created xenvif\n"); 306 netdev_dbg(dev, "Successfully created xenvif\n");
307
308 __module_get(THIS_MODULE);
309
307 return vif; 310 return vif;
308} 311}
309 312
@@ -369,9 +372,14 @@ void xenvif_disconnect(struct xenvif *vif)
369 if (vif->irq) 372 if (vif->irq)
370 unbind_from_irqhandler(vif->irq, vif); 373 unbind_from_irqhandler(vif->irq, vif);
371 374
372 unregister_netdev(vif->dev);
373
374 xen_netbk_unmap_frontend_rings(vif); 375 xen_netbk_unmap_frontend_rings(vif);
376}
377
378void xenvif_free(struct xenvif *vif)
379{
380 unregister_netdev(vif->dev);
375 381
376 free_netdev(vif->dev); 382 free_netdev(vif->dev);
383
384 module_put(THIS_MODULE);
377} 385}
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 410018c4c528..abe24ff000f0 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -42,7 +42,7 @@ static int netback_remove(struct xenbus_device *dev)
42 if (be->vif) { 42 if (be->vif) {
43 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); 43 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
44 xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); 44 xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
45 xenvif_disconnect(be->vif); 45 xenvif_free(be->vif);
46 be->vif = NULL; 46 be->vif = NULL;
47 } 47 }
48 kfree(be); 48 kfree(be);
@@ -203,9 +203,18 @@ static void disconnect_backend(struct xenbus_device *dev)
203{ 203{
204 struct backend_info *be = dev_get_drvdata(&dev->dev); 204 struct backend_info *be = dev_get_drvdata(&dev->dev);
205 205
206 if (be->vif)
207 xenvif_disconnect(be->vif);
208}
209
210static void destroy_backend(struct xenbus_device *dev)
211{
212 struct backend_info *be = dev_get_drvdata(&dev->dev);
213
206 if (be->vif) { 214 if (be->vif) {
215 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
207 xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); 216 xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
208 xenvif_disconnect(be->vif); 217 xenvif_free(be->vif);
209 be->vif = NULL; 218 be->vif = NULL;
210 } 219 }
211} 220}
@@ -237,14 +246,11 @@ static void frontend_changed(struct xenbus_device *dev,
237 case XenbusStateConnected: 246 case XenbusStateConnected:
238 if (dev->state == XenbusStateConnected) 247 if (dev->state == XenbusStateConnected)
239 break; 248 break;
240 backend_create_xenvif(be);
241 if (be->vif) 249 if (be->vif)
242 connect(be); 250 connect(be);
243 break; 251 break;
244 252
245 case XenbusStateClosing: 253 case XenbusStateClosing:
246 if (be->vif)
247 kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
248 disconnect_backend(dev); 254 disconnect_backend(dev);
249 xenbus_switch_state(dev, XenbusStateClosing); 255 xenbus_switch_state(dev, XenbusStateClosing);
250 break; 256 break;
@@ -253,6 +259,7 @@ static void frontend_changed(struct xenbus_device *dev,
253 xenbus_switch_state(dev, XenbusStateClosed); 259 xenbus_switch_state(dev, XenbusStateClosed);
254 if (xenbus_dev_is_online(dev)) 260 if (xenbus_dev_is_online(dev))
255 break; 261 break;
262 destroy_backend(dev);
256 /* fall through if not online */ 263 /* fall through if not online */
257 case XenbusStateUnknown: 264 case XenbusStateUnknown:
258 device_unregister(&dev->dev); 265 device_unregister(&dev->dev);