aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/eth_media.c
diff options
context:
space:
mode:
authorAllan Stephens <allan.stephens@windriver.com>2011-10-19 15:18:11 -0400
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-12-27 11:33:42 -0500
commit64b32f7e38627a325c825087318c09075a5edc42 (patch)
tree2e093df7217fdc197467e05623c4e9bf712462a6 /net/tipc/eth_media.c
parent8c12118db77dce5a7abf1a0e87af56592fdd7c09 (diff)
tipc: Do timely cleanup of disabled Ethernet bearer resources
Modifies Ethernet bearer disable logic to break the association between the bearer and its device driver at the time the bearer is disabled, rather than when the TIPC module is unloaded. This allows the array entry used by the disabled bearer to be re-used if the same bearer (or a different one) is subsequently enabled. Signed-off-by: Allan Stephens <allan.stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Diffstat (limited to 'net/tipc/eth_media.c')
-rw-r--r--net/tipc/eth_media.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index 23bf67b1f010..236155c67aa0 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -46,12 +46,14 @@
46 * @bearer: ptr to associated "generic" bearer structure 46 * @bearer: ptr to associated "generic" bearer structure
47 * @dev: ptr to associated Ethernet network device 47 * @dev: ptr to associated Ethernet network device
48 * @tipc_packet_type: used in binding TIPC to Ethernet driver 48 * @tipc_packet_type: used in binding TIPC to Ethernet driver
49 * @cleanup: work item used when disabling bearer
49 */ 50 */
50 51
51struct eth_bearer { 52struct eth_bearer {
52 struct tipc_bearer *bearer; 53 struct tipc_bearer *bearer;
53 struct net_device *dev; 54 struct net_device *dev;
54 struct packet_type tipc_packet_type; 55 struct packet_type tipc_packet_type;
56 struct work_struct cleanup;
55}; 57};
56 58
57static struct media eth_media_info; 59static struct media eth_media_info;
@@ -192,16 +194,36 @@ static int enable_bearer(struct tipc_bearer *tb_ptr)
192} 194}
193 195
194/** 196/**
197 * cleanup_bearer - break association between Ethernet bearer and interface
198 *
199 * This routine must be invoked from a work queue because it can sleep.
200 */
201
202static void cleanup_bearer(struct work_struct *work)
203{
204 struct eth_bearer *eb_ptr =
205 container_of(work, struct eth_bearer, cleanup);
206
207 dev_remove_pack(&eb_ptr->tipc_packet_type);
208 dev_put(eb_ptr->dev);
209 eb_ptr->dev = NULL;
210}
211
212/**
195 * disable_bearer - detach TIPC bearer from an Ethernet interface 213 * disable_bearer - detach TIPC bearer from an Ethernet interface
196 * 214 *
197 * We really should do dev_remove_pack() here, but this function can not be 215 * Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
198 * called at tasklet level. => Use eth_bearer->bearer as a flag to throw away 216 * then get worker thread to complete bearer cleanup. (Can't do cleanup
199 * incoming buffers, & postpone dev_remove_pack() to eth_media_stop() on exit. 217 * here because cleanup code needs to sleep and caller holds spinlocks.)
200 */ 218 */
201 219
202static void disable_bearer(struct tipc_bearer *tb_ptr) 220static void disable_bearer(struct tipc_bearer *tb_ptr)
203{ 221{
204 ((struct eth_bearer *)tb_ptr->usr_handle)->bearer = NULL; 222 struct eth_bearer *eb_ptr = (struct eth_bearer *)tb_ptr->usr_handle;
223
224 eb_ptr->bearer = NULL;
225 INIT_WORK(&eb_ptr->cleanup, cleanup_bearer);
226 schedule_work(&eb_ptr->cleanup);
205} 227}
206 228
207/** 229/**
@@ -369,18 +391,11 @@ int tipc_eth_media_start(void)
369 391
370void tipc_eth_media_stop(void) 392void tipc_eth_media_stop(void)
371{ 393{
372 int i;
373
374 if (!eth_started) 394 if (!eth_started)
375 return; 395 return;
376 396
397 flush_scheduled_work();
377 unregister_netdevice_notifier(&notifier); 398 unregister_netdevice_notifier(&notifier);
378 for (i = 0; i < MAX_ETH_BEARERS ; i++) {
379 if (eth_bearers[i].dev) {
380 dev_remove_pack(&eth_bearers[i].tipc_packet_type);
381 dev_put(eth_bearers[i].dev);
382 }
383 }
384 memset(&eth_bearers, 0, sizeof(eth_bearers)); 399 memset(&eth_bearers, 0, sizeof(eth_bearers));
385 eth_started = 0; 400 eth_started = 0;
386} 401}