diff options
-rw-r--r-- | drivers/net/xen-netback/common.h | 1 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 19 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 20 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 5 |
4 files changed, 44 insertions, 1 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 9d7f1723dd8f..6102a6c59f4e 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -120,6 +120,7 @@ void xenvif_get(struct xenvif *vif); | |||
120 | void xenvif_put(struct xenvif *vif); | 120 | void xenvif_put(struct xenvif *vif); |
121 | 121 | ||
122 | int xenvif_xenbus_init(void); | 122 | int xenvif_xenbus_init(void); |
123 | void xenvif_xenbus_fini(void); | ||
123 | 124 | ||
124 | int xenvif_schedulable(struct xenvif *vif); | 125 | int xenvif_schedulable(struct xenvif *vif); |
125 | 126 | ||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index d98414168485..82202c2b1bd1 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -316,6 +316,8 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, | |||
316 | if (vif->irq) | 316 | if (vif->irq) |
317 | return 0; | 317 | return 0; |
318 | 318 | ||
319 | __module_get(THIS_MODULE); | ||
320 | |||
319 | err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); | 321 | err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref); |
320 | if (err < 0) | 322 | if (err < 0) |
321 | goto err; | 323 | goto err; |
@@ -343,6 +345,7 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, | |||
343 | err_unmap: | 345 | err_unmap: |
344 | xen_netbk_unmap_frontend_rings(vif); | 346 | xen_netbk_unmap_frontend_rings(vif); |
345 | err: | 347 | err: |
348 | module_put(THIS_MODULE); | ||
346 | return err; | 349 | return err; |
347 | } | 350 | } |
348 | 351 | ||
@@ -360,18 +363,32 @@ void xenvif_carrier_off(struct xenvif *vif) | |||
360 | 363 | ||
361 | void xenvif_disconnect(struct xenvif *vif) | 364 | void xenvif_disconnect(struct xenvif *vif) |
362 | { | 365 | { |
366 | /* Disconnect funtion might get called by generic framework | ||
367 | * even before vif connects, so we need to check if we really | ||
368 | * need to do a module_put. | ||
369 | */ | ||
370 | int need_module_put = 0; | ||
371 | |||
363 | if (netif_carrier_ok(vif->dev)) | 372 | if (netif_carrier_ok(vif->dev)) |
364 | xenvif_carrier_off(vif); | 373 | xenvif_carrier_off(vif); |
365 | 374 | ||
366 | atomic_dec(&vif->refcnt); | 375 | atomic_dec(&vif->refcnt); |
367 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); | 376 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); |
368 | 377 | ||
369 | if (vif->irq) | 378 | if (vif->irq) { |
370 | unbind_from_irqhandler(vif->irq, vif); | 379 | unbind_from_irqhandler(vif->irq, vif); |
380 | /* vif->irq is valid, we had a module_get in | ||
381 | * xenvif_connect. | ||
382 | */ | ||
383 | need_module_put = 1; | ||
384 | } | ||
371 | 385 | ||
372 | unregister_netdev(vif->dev); | 386 | unregister_netdev(vif->dev); |
373 | 387 | ||
374 | xen_netbk_unmap_frontend_rings(vif); | 388 | xen_netbk_unmap_frontend_rings(vif); |
375 | 389 | ||
376 | free_netdev(vif->dev); | 390 | free_netdev(vif->dev); |
391 | |||
392 | if (need_module_put) | ||
393 | module_put(THIS_MODULE); | ||
377 | } | 394 | } |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 295a9c267df4..2d9477fd900f 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -1949,5 +1949,25 @@ failed_init: | |||
1949 | 1949 | ||
1950 | module_init(netback_init); | 1950 | module_init(netback_init); |
1951 | 1951 | ||
1952 | static void __exit netback_fini(void) | ||
1953 | { | ||
1954 | int i, j; | ||
1955 | |||
1956 | xenvif_xenbus_fini(); | ||
1957 | |||
1958 | for (i = 0; i < xen_netbk_group_nr; i++) { | ||
1959 | struct xen_netbk *netbk = &xen_netbk[i]; | ||
1960 | del_timer_sync(&netbk->net_timer); | ||
1961 | kthread_stop(netbk->task); | ||
1962 | for (j = 0; j < MAX_PENDING_REQS; j++) { | ||
1963 | if (netbk->mmap_pages[i]) | ||
1964 | __free_page(netbk->mmap_pages[i]); | ||
1965 | } | ||
1966 | } | ||
1967 | |||
1968 | vfree(xen_netbk); | ||
1969 | } | ||
1970 | module_exit(netback_fini); | ||
1971 | |||
1952 | MODULE_LICENSE("Dual BSD/GPL"); | 1972 | MODULE_LICENSE("Dual BSD/GPL"); |
1953 | MODULE_ALIAS("xen-backend:vif"); | 1973 | MODULE_ALIAS("xen-backend:vif"); |
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 410018c4c528..d230c145660c 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -485,3 +485,8 @@ int xenvif_xenbus_init(void) | |||
485 | { | 485 | { |
486 | return xenbus_register_backend(&netback_driver); | 486 | return xenbus_register_backend(&netback_driver); |
487 | } | 487 | } |
488 | |||
489 | void xenvif_xenbus_fini(void) | ||
490 | { | ||
491 | return xenbus_unregister_driver(&netback_driver); | ||
492 | } | ||