aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2013-12-10 23:45:42 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-11 00:17:43 -0500
commit6e967adf798ae5066488fd0c2b2466d06c642f23 (patch)
tree5087be7329e5f2fd83c0f92e5cade64fd3c0d545
parent37cb0620073cb64101d9307931c135c70b2e3f04 (diff)
tipc: relocate common functions from media to bearer
Currently, registering a TIPC stack handler in the network device layer is done twice, once for Ethernet (eth_media) and Infiniband (ib_media) repectively. But, as this registration is not media specific, we can avoid some code duplication by moving the registering function to the generic bearer layer, to the file bearer.c, and call it only once. The same is true for the network device event notifier. As a side effect, the two workqueues we are using for for setting up/ cleaning up media can now be eliminated. Furthermore, the array for storing the specific media type structs, media_array[], can be entirely deleted. Note that the eth_started and ib_started flags were removed during the code relocation. There is now only one call to bearer_setup and bearer_cleanup, and these can logically not race against each other. Despite its size, this cleanup work incurs no functional changes in TIPC. In particular, it should be noted that the sequence ordering of received packets is unaffected by this change, since packet reception never was subject to any work queue handling in the first place. Signed-off-by: Ying Xue <ying.xue@windriver.com> Cc: Patrick McHardy <kaber@trash.net> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com> Reviewed-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/tipc/bearer.c105
-rw-r--r--net/tipc/bearer.h11
-rw-r--r--net/tipc/core.c8
-rw-r--r--net/tipc/eth_media.c199
-rw-r--r--net/tipc/ib_media.c192
5 files changed, 114 insertions, 401 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 2411bac2b8f9..e95e0b91ef30 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -367,7 +367,7 @@ exit:
367/** 367/**
368 * tipc_reset_bearer - Reset all links established over this bearer 368 * tipc_reset_bearer - Reset all links established over this bearer
369 */ 369 */
370int tipc_reset_bearer(struct tipc_bearer *b_ptr) 370static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
371{ 371{
372 struct tipc_link *l_ptr; 372 struct tipc_link *l_ptr;
373 struct tipc_link *temp_l_ptr; 373 struct tipc_link *temp_l_ptr;
@@ -432,7 +432,110 @@ int tipc_disable_bearer(const char *name)
432 return res; 432 return res;
433} 433}
434 434
435/**
436 * tipc_l2_rcv_msg - handle incoming TIPC message from an interface
437 * @buf: the received packet
438 * @dev: the net device that the packet was received on
439 * @pt: the packet_type structure which was used to register this handler
440 * @orig_dev: the original receive net device in case the device is a bond
441 *
442 * Accept only packets explicitly sent to this node, or broadcast packets;
443 * ignores packets sent using interface multicast, and traffic sent to other
444 * nodes (which can happen if interface is running in promiscuous mode).
445 */
446static int tipc_l2_rcv_msg(struct sk_buff *buf, struct net_device *dev,
447 struct packet_type *pt, struct net_device *orig_dev)
448{
449 struct tipc_bearer *b_ptr;
450
451 if (!net_eq(dev_net(dev), &init_net)) {
452 kfree_skb(buf);
453 return NET_RX_DROP;
454 }
455
456 rcu_read_lock();
457 b_ptr = rcu_dereference(dev->tipc_ptr);
458 if (likely(b_ptr)) {
459 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
460 buf->next = NULL;
461 tipc_recv_msg(buf, b_ptr);
462 rcu_read_unlock();
463 return NET_RX_SUCCESS;
464 }
465 }
466 rcu_read_unlock();
467
468 kfree_skb(buf);
469 return NET_RX_DROP;
470}
471
472/**
473 * tipc_l2_device_event - handle device events from network device
474 * @nb: the context of the notification
475 * @evt: the type of event
476 * @ptr: the net device that the event was on
477 *
478 * This function is called by the Ethernet driver in case of link
479 * change event.
480 */
481static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
482 void *ptr)
483{
484 struct tipc_bearer *b_ptr;
485 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
435 486
487 if (!net_eq(dev_net(dev), &init_net))
488 return NOTIFY_DONE;
489
490 rcu_read_lock();
491 b_ptr = rcu_dereference(dev->tipc_ptr);
492 if (!b_ptr) {
493 rcu_read_unlock();
494 return NOTIFY_DONE;
495 }
496
497 b_ptr->mtu = dev->mtu;
498
499 switch (evt) {
500 case NETDEV_CHANGE:
501 if (netif_carrier_ok(dev))
502 break;
503 case NETDEV_DOWN:
504 case NETDEV_CHANGEMTU:
505 case NETDEV_CHANGEADDR:
506 tipc_reset_bearer(b_ptr);
507 break;
508 case NETDEV_UNREGISTER:
509 case NETDEV_CHANGENAME:
510 tipc_disable_bearer(b_ptr->name);
511 break;
512 }
513 rcu_read_unlock();
514
515 return NOTIFY_OK;
516}
517
518static struct packet_type tipc_packet_type __read_mostly = {
519 .type = __constant_htons(ETH_P_TIPC),
520 .func = tipc_l2_rcv_msg,
521};
522
523static struct notifier_block notifier = {
524 .notifier_call = tipc_l2_device_event,
525 .priority = 0,
526};
527
528int tipc_bearer_setup(void)
529{
530 dev_add_pack(&tipc_packet_type);
531 return register_netdevice_notifier(&notifier);
532}
533
534void tipc_bearer_cleanup(void)
535{
536 unregister_netdevice_notifier(&notifier);
537 dev_remove_pack(&tipc_packet_type);
538}
436 539
437void tipc_bearer_stop(void) 540void tipc_bearer_stop(void)
438{ 541{
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h
index 91b8d8b92373..0974c2f2bbe5 100644
--- a/net/tipc/bearer.h
+++ b/net/tipc/bearer.h
@@ -162,25 +162,16 @@ extern struct tipc_bearer tipc_bearers[];
162 162
163void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr); 163void tipc_recv_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr);
164 164
165int tipc_reset_bearer(struct tipc_bearer *b_ptr);
166
167int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority); 165int tipc_enable_bearer(const char *bearer_name, u32 disc_domain, u32 priority);
168int tipc_disable_bearer(const char *name); 166int tipc_disable_bearer(const char *name);
169 167
170/* 168/*
171 * Routines made available to TIPC by supported media types 169 * Routines made available to TIPC by supported media types
172 */ 170 */
173int tipc_eth_media_start(void);
174void tipc_eth_media_stop(void);
175extern struct tipc_media eth_media_info; 171extern struct tipc_media eth_media_info;
176 172
177#ifdef CONFIG_TIPC_MEDIA_IB 173#ifdef CONFIG_TIPC_MEDIA_IB
178int tipc_ib_media_start(void);
179void tipc_ib_media_stop(void);
180extern struct tipc_media ib_media_info; 174extern struct tipc_media ib_media_info;
181#else
182static inline int tipc_ib_media_start(void) { return 0; }
183static inline void tipc_ib_media_stop(void) { return; }
184#endif 175#endif
185 176
186int tipc_media_set_priority(const char *name, u32 new_value); 177int tipc_media_set_priority(const char *name, u32 new_value);
@@ -194,6 +185,8 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
194struct tipc_bearer *tipc_bearer_find(const char *name); 185struct tipc_bearer *tipc_bearer_find(const char *name);
195struct tipc_bearer *tipc_bearer_find_interface(const char *if_name); 186struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
196struct tipc_media *tipc_media_find(const char *name); 187struct tipc_media *tipc_media_find(const char *name);
188int tipc_bearer_setup(void);
189void tipc_bearer_cleanup(void);
197void tipc_bearer_stop(void); 190void tipc_bearer_stop(void);
198 191
199/** 192/**
diff --git a/net/tipc/core.c b/net/tipc/core.c
index fd4eeeaa972a..68977c423022 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -82,8 +82,7 @@ struct sk_buff *tipc_buf_acquire(u32 size)
82static void tipc_core_stop_net(void) 82static void tipc_core_stop_net(void)
83{ 83{
84 tipc_net_stop(); 84 tipc_net_stop();
85 tipc_eth_media_stop(); 85 tipc_bearer_cleanup();
86 tipc_ib_media_stop();
87} 86}
88 87
89/** 88/**
@@ -94,10 +93,7 @@ int tipc_core_start_net(unsigned long addr)
94 int res; 93 int res;
95 94
96 tipc_net_start(addr); 95 tipc_net_start(addr);
97 res = tipc_eth_media_start(); 96 res = tipc_bearer_setup();
98 if (res < 0)
99 goto err;
100 res = tipc_ib_media_start();
101 if (res < 0) 97 if (res < 0)
102 goto err; 98 goto err;
103 return res; 99 return res;
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c
index c5f685dee15b..f28f7160adba 100644
--- a/net/tipc/eth_media.c
+++ b/net/tipc/eth_media.c
@@ -37,49 +37,9 @@
37#include "core.h" 37#include "core.h"
38#include "bearer.h" 38#include "bearer.h"
39 39
40#define MAX_ETH_MEDIA MAX_BEARERS
41
42#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */ 40#define ETH_ADDR_OFFSET 4 /* message header offset of MAC address */
43 41
44/** 42/**
45 * struct eth_media - Ethernet bearer data structure
46 * @bearer: ptr to associated "generic" bearer structure
47 * @dev: ptr to associated Ethernet network device
48 * @tipc_packet_type: used in binding TIPC to Ethernet driver
49 * @setup: work item used when enabling bearer
50 * @cleanup: work item used when disabling bearer
51 */
52struct eth_media {
53 struct tipc_bearer *bearer;
54 struct net_device *dev;
55 struct packet_type tipc_packet_type;
56 struct work_struct setup;
57 struct work_struct cleanup;
58};
59
60
61static struct eth_media eth_media_array[MAX_ETH_MEDIA];
62static int eth_started;
63
64static int recv_notification(struct notifier_block *nb, unsigned long evt,
65 void *dv);
66static int recv_msg(struct sk_buff *buf, struct net_device *dev,
67 struct packet_type *pt, struct net_device *orig_dev);
68
69/*
70 * Network device notifier info
71 */
72static struct notifier_block notifier = {
73 .notifier_call = recv_notification,
74 .priority = 0
75};
76
77static struct packet_type tipc_packet_type __read_mostly = {
78 .type = __constant_htons(ETH_P_TIPC),
79 .func = recv_msg,
80};
81
82/**
83 * eth_media_addr_set - initialize Ethernet media address structure 43 * eth_media_addr_set - initialize Ethernet media address structure
84 * 44 *
85 * Media-dependent "value" field stores MAC address in first 6 bytes 45 * Media-dependent "value" field stores MAC address in first 6 bytes
@@ -101,16 +61,14 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
101 struct tipc_media_addr *dest) 61 struct tipc_media_addr *dest)
102{ 62{
103 struct sk_buff *clone; 63 struct sk_buff *clone;
104 struct net_device *dev;
105 int delta; 64 int delta;
65 struct net_device *dev = tb_ptr->dev;
106 66
107 clone = skb_clone(buf, GFP_ATOMIC); 67 clone = skb_clone(buf, GFP_ATOMIC);
108 if (!clone) 68 if (!clone)
109 return 0; 69 return 0;
110 70
111 dev = ((struct eth_media *)(tb_ptr->usr_handle))->dev;
112 delta = dev->hard_header_len - skb_headroom(buf); 71 delta = dev->hard_header_len - skb_headroom(buf);
113
114 if ((delta > 0) && 72 if ((delta > 0) &&
115 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { 73 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
116 kfree_skb(clone); 74 kfree_skb(clone);
@@ -127,79 +85,21 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
127} 85}
128 86
129/** 87/**
130 * recv_msg - handle incoming TIPC message from an Ethernet interface
131 *
132 * Accept only packets explicitly sent to this node, or broadcast packets;
133 * ignores packets sent using Ethernet multicast, and traffic sent to other
134 * nodes (which can happen if interface is running in promiscuous mode).
135 */
136static int recv_msg(struct sk_buff *buf, struct net_device *dev,
137 struct packet_type *pt, struct net_device *orig_dev)
138{
139 struct tipc_bearer *b_ptr;
140
141 if (!net_eq(dev_net(dev), &init_net)) {
142 kfree_skb(buf);
143 return NET_RX_DROP;
144 }
145
146 rcu_read_lock();
147 b_ptr = rcu_dereference(dev->tipc_ptr);
148 if (likely(b_ptr)) {
149 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
150 buf->next = NULL;
151 tipc_recv_msg(buf, b_ptr);
152 rcu_read_unlock();
153 return NET_RX_SUCCESS;
154 }
155 }
156 rcu_read_unlock();
157
158 kfree_skb(buf);
159 return NET_RX_DROP;
160}
161
162/**
163 * setup_media - setup association between Ethernet bearer and interface
164 */
165static void setup_media(struct work_struct *work)
166{
167 dev_add_pack(&tipc_packet_type);
168}
169
170/**
171 * enable_media - attach TIPC bearer to an Ethernet interface 88 * enable_media - attach TIPC bearer to an Ethernet interface
172 */ 89 */
173static int enable_media(struct tipc_bearer *tb_ptr) 90static int enable_media(struct tipc_bearer *tb_ptr)
174{ 91{
175 struct net_device *dev; 92 struct net_device *dev;
176 struct eth_media *eb_ptr = &eth_media_array[0];
177 struct eth_media *stop = &eth_media_array[MAX_ETH_MEDIA];
178 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; 93 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
179 int pending_dev = 0;
180
181 /* Find unused Ethernet bearer structure */
182 while (eb_ptr->dev) {
183 if (!eb_ptr->bearer)
184 pending_dev++;
185 if (++eb_ptr == stop)
186 return pending_dev ? -EAGAIN : -EDQUOT;
187 }
188 94
189 /* Find device with specified name */ 95 /* Find device with specified name */
190 dev = dev_get_by_name(&init_net, driver_name); 96 dev = dev_get_by_name(&init_net, driver_name);
191 if (!dev) 97 if (!dev)
192 return -ENODEV; 98 return -ENODEV;
193 99
194 /* Create Ethernet bearer for device */
195 eb_ptr->dev = dev;
196 INIT_WORK(&eb_ptr->setup, setup_media);
197 schedule_work(&eb_ptr->setup);
198
199 /* Associate TIPC bearer with Ethernet bearer */ 100 /* Associate TIPC bearer with Ethernet bearer */
200 tb_ptr->dev = dev; 101 tb_ptr->dev = dev;
201 eb_ptr->bearer = tb_ptr; 102 tb_ptr->usr_handle = NULL;
202 tb_ptr->usr_handle = (void *)eb_ptr;
203 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); 103 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
204 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN); 104 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, ETH_ALEN);
205 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH; 105 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_ETH;
@@ -211,21 +111,6 @@ static int enable_media(struct tipc_bearer *tb_ptr)
211} 111}
212 112
213/** 113/**
214 * cleanup_media - break association between Ethernet bearer and interface
215 *
216 * This routine must be invoked from a work queue because it can sleep.
217 */
218static void cleanup_media(struct work_struct *work)
219{
220 struct eth_media *eb_ptr =
221 container_of(work, struct eth_media, cleanup);
222
223 dev_remove_pack(&tipc_packet_type);
224 dev_put(eb_ptr->dev);
225 eb_ptr->dev = NULL;
226}
227
228/**
229 * disable_media - detach TIPC bearer from an Ethernet interface 114 * disable_media - detach TIPC bearer from an Ethernet interface
230 * 115 *
231 * Mark Ethernet bearer as inactive so that incoming buffers are thrown away, 116 * Mark Ethernet bearer as inactive so that incoming buffers are thrown away,
@@ -234,55 +119,8 @@ static void cleanup_media(struct work_struct *work)
234 */ 119 */
235static void disable_media(struct tipc_bearer *tb_ptr) 120static void disable_media(struct tipc_bearer *tb_ptr)
236{ 121{
237 struct eth_media *eb_ptr = (struct eth_media *)tb_ptr->usr_handle;
238
239 eb_ptr->bearer = NULL;
240 INIT_WORK(&eb_ptr->cleanup, cleanup_media);
241 schedule_work(&eb_ptr->cleanup);
242 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL); 122 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL);
243} 123 dev_put(tb_ptr->dev);
244
245/**
246 * recv_notification - handle device updates from OS
247 *
248 * Change the state of the Ethernet bearer (if any) associated with the
249 * specified device.
250 */
251static int recv_notification(struct notifier_block *nb, unsigned long evt,
252 void *ptr)
253{
254 struct tipc_bearer *b_ptr;
255 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
256
257 if (!net_eq(dev_net(dev), &init_net))
258 return NOTIFY_DONE;
259
260 rcu_read_lock();
261 b_ptr = rcu_dereference(dev->tipc_ptr);
262 if (!b_ptr) {
263 rcu_read_unlock();
264 return NOTIFY_DONE; /* bearer had been disabled */
265 }
266
267 b_ptr->mtu = dev->mtu;
268
269 switch (evt) {
270 case NETDEV_CHANGE:
271 if (netif_carrier_ok(dev))
272 break;
273 case NETDEV_DOWN:
274 case NETDEV_CHANGEMTU:
275 case NETDEV_CHANGEADDR:
276 tipc_reset_bearer(b_ptr);
277 break;
278 case NETDEV_UNREGISTER:
279 case NETDEV_CHANGENAME:
280 tipc_disable_bearer(b_ptr->name);
281 break;
282 }
283 rcu_read_unlock();
284
285 return NOTIFY_OK;
286} 124}
287 125
288/** 126/**
@@ -338,34 +176,3 @@ struct tipc_media eth_media_info = {
338 .name = "eth" 176 .name = "eth"
339}; 177};
340 178
341/**
342 * tipc_eth_media_start - activate Ethernet bearer support
343 *
344 * Register Ethernet media type with TIPC bearer code. Also register
345 * with OS for notifications about device state changes.
346 */
347int tipc_eth_media_start(void)
348{
349 int res;
350
351 if (eth_started)
352 return -EINVAL;
353
354 res = register_netdevice_notifier(&notifier);
355 if (!res)
356 eth_started = 1;
357 return res;
358}
359
360/**
361 * tipc_eth_media_stop - deactivate Ethernet bearer support
362 */
363void tipc_eth_media_stop(void)
364{
365 if (!eth_started)
366 return;
367
368 flush_scheduled_work();
369 unregister_netdevice_notifier(&notifier);
370 eth_started = 0;
371}
diff --git a/net/tipc/ib_media.c b/net/tipc/ib_media.c
index 9fdf03cd672b..62d91aeda058 100644
--- a/net/tipc/ib_media.c
+++ b/net/tipc/ib_media.c
@@ -42,34 +42,6 @@
42#include "core.h" 42#include "core.h"
43#include "bearer.h" 43#include "bearer.h"
44 44
45#define MAX_IB_MEDIA MAX_BEARERS
46
47/**
48 * struct ib_media - Infiniband media data structure
49 * @bearer: ptr to associated "generic" bearer structure
50 * @dev: ptr to associated Infiniband network device
51 * @tipc_packet_type: used in binding TIPC to Infiniband driver
52 * @cleanup: work item used when disabling bearer
53 */
54
55struct ib_media {
56 struct tipc_bearer *bearer;
57 struct net_device *dev;
58 struct packet_type tipc_packet_type;
59 struct work_struct setup;
60 struct work_struct cleanup;
61};
62
63static struct ib_media ib_media_array[MAX_IB_MEDIA];
64static int ib_started;
65static int recv_msg(struct sk_buff *buf, struct net_device *dev,
66 struct packet_type *pt, struct net_device *orig_dev);
67
68static struct packet_type tipc_packet_type __read_mostly = {
69 .type = __constant_htons(ETH_P_TIPC),
70 .func = recv_msg,
71};
72
73/** 45/**
74 * ib_media_addr_set - initialize Infiniband media address structure 46 * ib_media_addr_set - initialize Infiniband media address structure
75 * 47 *
@@ -92,16 +64,14 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
92 struct tipc_media_addr *dest) 64 struct tipc_media_addr *dest)
93{ 65{
94 struct sk_buff *clone; 66 struct sk_buff *clone;
95 struct net_device *dev;
96 int delta; 67 int delta;
68 struct net_device *dev = tb_ptr->dev;
97 69
98 clone = skb_clone(buf, GFP_ATOMIC); 70 clone = skb_clone(buf, GFP_ATOMIC);
99 if (!clone) 71 if (!clone)
100 return 0; 72 return 0;
101 73
102 dev = ((struct ib_media *)(tb_ptr->usr_handle))->dev;
103 delta = dev->hard_header_len - skb_headroom(buf); 74 delta = dev->hard_header_len - skb_headroom(buf);
104
105 if ((delta > 0) && 75 if ((delta > 0) &&
106 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { 76 pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) {
107 kfree_skb(clone); 77 kfree_skb(clone);
@@ -118,79 +88,21 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr,
118} 88}
119 89
120/** 90/**
121 * recv_msg - handle incoming TIPC message from an InfiniBand interface
122 *
123 * Accept only packets explicitly sent to this node, or broadcast packets;
124 * ignores packets sent using InfiniBand multicast, and traffic sent to other
125 * nodes (which can happen if interface is running in promiscuous mode).
126 */
127static int recv_msg(struct sk_buff *buf, struct net_device *dev,
128 struct packet_type *pt, struct net_device *orig_dev)
129{
130 struct tipc_bearer *b_ptr;
131
132 if (!net_eq(dev_net(dev), &init_net)) {
133 kfree_skb(buf);
134 return NET_RX_DROP;
135 }
136
137 rcu_read_lock();
138 b_ptr = rcu_dereference(dev->tipc_ptr);
139 if (likely(b_ptr)) {
140 if (likely(buf->pkt_type <= PACKET_BROADCAST)) {
141 buf->next = NULL;
142 tipc_recv_msg(buf, b_ptr);
143 rcu_read_unlock();
144 return NET_RX_SUCCESS;
145 }
146 }
147 rcu_read_unlock();
148
149 kfree_skb(buf);
150 return NET_RX_DROP;
151}
152
153/**
154 * setup_bearer - setup association between InfiniBand bearer and interface
155 */
156static void setup_media(struct work_struct *work)
157{
158 dev_add_pack(&tipc_packet_type);
159}
160
161/**
162 * enable_media - attach TIPC bearer to an InfiniBand interface 91 * enable_media - attach TIPC bearer to an InfiniBand interface
163 */ 92 */
164static int enable_media(struct tipc_bearer *tb_ptr) 93static int enable_media(struct tipc_bearer *tb_ptr)
165{ 94{
166 struct net_device *dev; 95 struct net_device *dev;
167 struct ib_media *ib_ptr = &ib_media_array[0];
168 struct ib_media *stop = &ib_media_array[MAX_IB_MEDIA];
169 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; 96 char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1;
170 int pending_dev = 0;
171
172 /* Find unused InfiniBand bearer structure */
173 while (ib_ptr->dev) {
174 if (!ib_ptr->bearer)
175 pending_dev++;
176 if (++ib_ptr == stop)
177 return pending_dev ? -EAGAIN : -EDQUOT;
178 }
179 97
180 /* Find device with specified name */ 98 /* Find device with specified name */
181 dev = dev_get_by_name(&init_net, driver_name); 99 dev = dev_get_by_name(&init_net, driver_name);
182 if (!dev) 100 if (!dev)
183 return -ENODEV; 101 return -ENODEV;
184 102
185 /* Create InfiniBand bearer for device */
186 ib_ptr->dev = dev;
187 INIT_WORK(&ib_ptr->setup, setup_media);
188 schedule_work(&ib_ptr->setup);
189
190 /* Associate TIPC bearer with InfiniBand bearer */ 103 /* Associate TIPC bearer with InfiniBand bearer */
191 tb_ptr->dev = dev; 104 tb_ptr->dev = dev;
192 ib_ptr->bearer = tb_ptr; 105 tb_ptr->usr_handle = NULL;
193 tb_ptr->usr_handle = (void *)ib_ptr;
194 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value)); 106 memset(tb_ptr->bcast_addr.value, 0, sizeof(tb_ptr->bcast_addr.value));
195 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN); 107 memcpy(tb_ptr->bcast_addr.value, dev->broadcast, INFINIBAND_ALEN);
196 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB; 108 tb_ptr->bcast_addr.media_id = TIPC_MEDIA_TYPE_IB;
@@ -202,21 +114,6 @@ static int enable_media(struct tipc_bearer *tb_ptr)
202} 114}
203 115
204/** 116/**
205 * cleanup_bearer - break association between InfiniBand bearer and interface
206 *
207 * This routine must be invoked from a work queue because it can sleep.
208 */
209static void cleanup_bearer(struct work_struct *work)
210{
211 struct ib_media *ib_ptr =
212 container_of(work, struct ib_media, cleanup);
213
214 dev_remove_pack(&tipc_packet_type);
215 dev_put(ib_ptr->dev);
216 ib_ptr->dev = NULL;
217}
218
219/**
220 * disable_media - detach TIPC bearer from an InfiniBand interface 117 * disable_media - detach TIPC bearer from an InfiniBand interface
221 * 118 *
222 * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away, 119 * Mark InfiniBand bearer as inactive so that incoming buffers are thrown away,
@@ -225,63 +122,11 @@ static void cleanup_bearer(struct work_struct *work)
225 */ 122 */
226static void disable_media(struct tipc_bearer *tb_ptr) 123static void disable_media(struct tipc_bearer *tb_ptr)
227{ 124{
228 struct ib_media *ib_ptr = (struct ib_media *)tb_ptr->usr_handle;
229
230 ib_ptr->bearer = NULL;
231 INIT_WORK(&ib_ptr->cleanup, cleanup_bearer);
232 schedule_work(&ib_ptr->cleanup);
233 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL); 125 RCU_INIT_POINTER(tb_ptr->dev->tipc_ptr, NULL);
126 dev_put(tb_ptr->dev);
234} 127}
235 128
236/** 129/**
237 * recv_notification - handle device updates from OS
238 *
239 * Change the state of the InfiniBand bearer (if any) associated with the
240 * specified device.
241 */
242static int recv_notification(struct notifier_block *nb, unsigned long evt,
243 void *ptr)
244{
245 struct tipc_bearer *b_ptr;
246 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
247
248 if (!net_eq(dev_net(dev), &init_net))
249 return NOTIFY_DONE;
250
251 rcu_read_lock();
252 b_ptr = rcu_dereference(dev->tipc_ptr);
253 if (!b_ptr) {
254 rcu_read_unlock();
255 return NOTIFY_DONE; /* bearer had been disabled */
256 }
257
258 b_ptr->mtu = dev->mtu;
259
260 switch (evt) {
261 case NETDEV_CHANGE:
262 if (netif_carrier_ok(dev))
263 break;
264 case NETDEV_DOWN:
265 case NETDEV_CHANGEMTU:
266 case NETDEV_CHANGEADDR:
267 tipc_reset_bearer(b_ptr);
268 break;
269 case NETDEV_UNREGISTER:
270 case NETDEV_CHANGENAME:
271 tipc_disable_bearer(b_ptr->name);
272 break;
273 }
274 rcu_read_unlock();
275
276 return NOTIFY_OK;
277}
278
279static struct notifier_block notifier = {
280 .notifier_call = recv_notification,
281 .priority = 0,
282};
283
284/**
285 * ib_addr2str - convert InfiniBand address to string 130 * ib_addr2str - convert InfiniBand address to string
286 */ 131 */
287static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size) 132static int ib_addr2str(struct tipc_media_addr *a, char *str_buf, int str_size)
@@ -332,34 +177,3 @@ struct tipc_media ib_media_info = {
332 .name = "ib" 177 .name = "ib"
333}; 178};
334 179
335/**
336 * tipc_ib_media_start - activate InfiniBand bearer support
337 *
338 * Register InfiniBand media type with TIPC bearer code. Also register
339 * with OS for notifications about device state changes.
340 */
341int tipc_ib_media_start(void)
342{
343 int res;
344
345 if (ib_started)
346 return -EINVAL;
347
348 res = register_netdevice_notifier(&notifier);
349 if (!res)
350 ib_started = 1;
351 return res;
352}
353
354/**
355 * tipc_ib_media_stop - deactivate InfiniBand bearer support
356 */
357void tipc_ib_media_stop(void)
358{
359 if (!ib_started)
360 return;
361
362 flush_scheduled_work();
363 unregister_netdevice_notifier(&notifier);
364 ib_started = 0;
365}