aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/rionet.c
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-04 20:16:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-05 14:05:23 -0400
commit2fb717ec3ec76b0ca4cee9c4d802ce551750413d (patch)
treee1641886b80194af8ad4c86b07e6be42fef5014b /drivers/net/rionet.c
parent005842efd1ac8ef455ebd28a8c713944863edc5a (diff)
rapidio/rionet: rework to support multiple RIO master ports
Make RIONET driver multi-net safe/capable by introducing per-net lists of RapidIO network peers. Rework registration of network adapters to support all available RIO master port devices. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Cc: David S. Miller <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/rionet.c')
-rw-r--r--drivers/net/rionet.c133
1 files changed, 70 insertions, 63 deletions
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 1470d3e86e3c..d8b9b1e8ee02 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -26,7 +26,7 @@
26#include <linux/ethtool.h> 26#include <linux/ethtool.h>
27 27
28#define DRV_NAME "rionet" 28#define DRV_NAME "rionet"
29#define DRV_VERSION "0.2" 29#define DRV_VERSION "0.3"
30#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>" 30#define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
31#define DRV_DESC "Ethernet over RapidIO" 31#define DRV_DESC "Ethernet over RapidIO"
32 32
@@ -47,8 +47,7 @@ MODULE_LICENSE("GPL");
47 47
48#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE 48#define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
49#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE 49#define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
50 50#define RIONET_MAX_NETS 8
51static LIST_HEAD(rionet_peers);
52 51
53struct rionet_private { 52struct rionet_private {
54 struct rio_mport *mport; 53 struct rio_mport *mport;
@@ -69,17 +68,14 @@ struct rionet_peer {
69 struct resource *res; 68 struct resource *res;
70}; 69};
71 70
72static int rionet_check = 0; 71struct rionet_net {
73static int rionet_capable = 1; 72 struct net_device *ndev;
73 struct list_head peers;
74 struct rio_dev **active;
75 int nact; /* number of active peers */
76};
74 77
75/* 78static struct rionet_net nets[RIONET_MAX_NETS];
76 * This is a fast lookup table for translating TX
77 * Ethernet packets into a destination RIO device. It
78 * could be made into a hash table to save memory depending
79 * on system trade-offs.
80 */
81static struct rio_dev **rionet_active;
82static int nact; /* total number of active rionet peers */
83 79
84#define is_rionet_capable(src_ops, dst_ops) \ 80#define is_rionet_capable(src_ops, dst_ops) \
85 ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ 81 ((src_ops & RIO_SRC_OPS_DATA_MSG) && \
@@ -185,7 +181,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
185 } 181 }
186 182
187 if (is_multicast_ether_addr(eth->h_dest)) 183 if (is_multicast_ether_addr(eth->h_dest))
188 add_num = nact; 184 add_num = nets[rnet->mport->id].nact;
189 185
190 if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { 186 if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
191 netif_stop_queue(ndev); 187 netif_stop_queue(ndev);
@@ -197,19 +193,21 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
197 193
198 if (is_multicast_ether_addr(eth->h_dest)) { 194 if (is_multicast_ether_addr(eth->h_dest)) {
199 int count = 0; 195 int count = 0;
196
200 for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); 197 for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
201 i++) 198 i++)
202 if (rionet_active[i]) { 199 if (nets[rnet->mport->id].active[i]) {
203 rionet_queue_tx_msg(skb, ndev, 200 rionet_queue_tx_msg(skb, ndev,
204 rionet_active[i]); 201 nets[rnet->mport->id].active[i]);
205 if (count) 202 if (count)
206 atomic_inc(&skb->users); 203 atomic_inc(&skb->users);
207 count++; 204 count++;
208 } 205 }
209 } else if (RIONET_MAC_MATCH(eth->h_dest)) { 206 } else if (RIONET_MAC_MATCH(eth->h_dest)) {
210 destid = RIONET_GET_DESTID(eth->h_dest); 207 destid = RIONET_GET_DESTID(eth->h_dest);
211 if (rionet_active[destid]) 208 if (nets[rnet->mport->id].active[destid])
212 rionet_queue_tx_msg(skb, ndev, rionet_active[destid]); 209 rionet_queue_tx_msg(skb, ndev,
210 nets[rnet->mport->id].active[destid]);
213 } 211 }
214 212
215 spin_unlock_irqrestore(&rnet->tx_lock, flags); 213 spin_unlock_irqrestore(&rnet->tx_lock, flags);
@@ -228,19 +226,21 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
228 printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x", 226 printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
229 DRV_NAME, sid, tid, info); 227 DRV_NAME, sid, tid, info);
230 if (info == RIONET_DOORBELL_JOIN) { 228 if (info == RIONET_DOORBELL_JOIN) {
231 if (!rionet_active[sid]) { 229 if (!nets[rnet->mport->id].active[sid]) {
232 list_for_each_entry(peer, &rionet_peers, node) { 230 list_for_each_entry(peer,
231 &nets[rnet->mport->id].peers, node) {
233 if (peer->rdev->destid == sid) { 232 if (peer->rdev->destid == sid) {
234 rionet_active[sid] = peer->rdev; 233 nets[rnet->mport->id].active[sid] =
235 nact++; 234 peer->rdev;
235 nets[rnet->mport->id].nact++;
236 } 236 }
237 } 237 }
238 rio_mport_send_doorbell(mport, sid, 238 rio_mport_send_doorbell(mport, sid,
239 RIONET_DOORBELL_JOIN); 239 RIONET_DOORBELL_JOIN);
240 } 240 }
241 } else if (info == RIONET_DOORBELL_LEAVE) { 241 } else if (info == RIONET_DOORBELL_LEAVE) {
242 rionet_active[sid] = NULL; 242 nets[rnet->mport->id].active[sid] = NULL;
243 nact--; 243 nets[rnet->mport->id].nact--;
244 } else { 244 } else {
245 if (netif_msg_intr(rnet)) 245 if (netif_msg_intr(rnet))
246 printk(KERN_WARNING "%s: unhandled doorbell\n", 246 printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -334,7 +334,8 @@ static int rionet_open(struct net_device *ndev)
334 netif_carrier_on(ndev); 334 netif_carrier_on(ndev);
335 netif_start_queue(ndev); 335 netif_start_queue(ndev);
336 336
337 list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { 337 list_for_each_entry_safe(peer, tmp,
338 &nets[rnet->mport->id].peers, node) {
338 if (!(peer->res = rio_request_outb_dbell(peer->rdev, 339 if (!(peer->res = rio_request_outb_dbell(peer->rdev,
339 RIONET_DOORBELL_JOIN, 340 RIONET_DOORBELL_JOIN,
340 RIONET_DOORBELL_LEAVE))) 341 RIONET_DOORBELL_LEAVE)))
@@ -359,7 +360,7 @@ static int rionet_close(struct net_device *ndev)
359 int i; 360 int i;
360 361
361 if (netif_msg_ifup(rnet)) 362 if (netif_msg_ifup(rnet))
362 printk(KERN_INFO "%s: close\n", DRV_NAME); 363 printk(KERN_INFO "%s: close %s\n", DRV_NAME, ndev->name);
363 364
364 netif_stop_queue(ndev); 365 netif_stop_queue(ndev);
365 netif_carrier_off(ndev); 366 netif_carrier_off(ndev);
@@ -367,10 +368,11 @@ static int rionet_close(struct net_device *ndev)
367 for (i = 0; i < RIONET_RX_RING_SIZE; i++) 368 for (i = 0; i < RIONET_RX_RING_SIZE; i++)
368 kfree_skb(rnet->rx_skb[i]); 369 kfree_skb(rnet->rx_skb[i]);
369 370
370 list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { 371 list_for_each_entry_safe(peer, tmp,
371 if (rionet_active[peer->rdev->destid]) { 372 &nets[rnet->mport->id].peers, node) {
373 if (nets[rnet->mport->id].active[peer->rdev->destid]) {
372 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE); 374 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
373 rionet_active[peer->rdev->destid] = NULL; 375 nets[rnet->mport->id].active[peer->rdev->destid] = NULL;
374 } 376 }
375 rio_release_outb_dbell(peer->rdev, peer->res); 377 rio_release_outb_dbell(peer->rdev, peer->res);
376 } 378 }
@@ -386,17 +388,21 @@ static int rionet_close(struct net_device *ndev)
386static void rionet_remove(struct rio_dev *rdev) 388static void rionet_remove(struct rio_dev *rdev)
387{ 389{
388 struct net_device *ndev = rio_get_drvdata(rdev); 390 struct net_device *ndev = rio_get_drvdata(rdev);
391 unsigned char netid = rdev->net->hport->id;
389 struct rionet_peer *peer, *tmp; 392 struct rionet_peer *peer, *tmp;
390 393
391 free_pages((unsigned long)rionet_active, get_order(sizeof(void *) *
392 RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
393 unregister_netdev(ndev); 394 unregister_netdev(ndev);
394 free_netdev(ndev);
395 395
396 list_for_each_entry_safe(peer, tmp, &rionet_peers, node) { 396 free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) *
397 RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
398 nets[netid].active = NULL;
399
400 list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) {
397 list_del(&peer->node); 401 list_del(&peer->node);
398 kfree(peer); 402 kfree(peer);
399 } 403 }
404
405 free_netdev(ndev);
400} 406}
401 407
402static void rionet_get_drvinfo(struct net_device *ndev, 408static void rionet_get_drvinfo(struct net_device *ndev,
@@ -448,13 +454,13 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
448 const size_t rionet_active_bytes = sizeof(void *) * 454 const size_t rionet_active_bytes = sizeof(void *) *
449 RIO_MAX_ROUTE_ENTRIES(mport->sys_size); 455 RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
450 456
451 rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL, 457 nets[mport->id].active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
452 get_order(rionet_active_bytes)); 458 get_order(rionet_active_bytes));
453 if (!rionet_active) { 459 if (!nets[mport->id].active) {
454 rc = -ENOMEM; 460 rc = -ENOMEM;
455 goto out; 461 goto out;
456 } 462 }
457 memset((void *)rionet_active, 0, rionet_active_bytes); 463 memset((void *)nets[mport->id].active, 0, rionet_active_bytes);
458 464
459 /* Set up private area */ 465 /* Set up private area */
460 rnet = netdev_priv(ndev); 466 rnet = netdev_priv(ndev);
@@ -483,61 +489,62 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
483 if (rc != 0) 489 if (rc != 0)
484 goto out; 490 goto out;
485 491
486 printk("%s: %s %s Version %s, MAC %pM\n", 492 printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s\n",
487 ndev->name, 493 ndev->name,
488 DRV_NAME, 494 DRV_NAME,
489 DRV_DESC, 495 DRV_DESC,
490 DRV_VERSION, 496 DRV_VERSION,
491 ndev->dev_addr); 497 ndev->dev_addr,
498 mport->name);
492 499
493 out: 500 out:
494 return rc; 501 return rc;
495} 502}
496 503
497/* 504static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
498 * XXX Make multi-net safe 505
499 */
500static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) 506static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
501{ 507{
502 int rc = -ENODEV; 508 int rc = -ENODEV;
503 u32 lsrc_ops, ldst_ops; 509 u32 lsrc_ops, ldst_ops;
504 struct rionet_peer *peer; 510 struct rionet_peer *peer;
505 struct net_device *ndev = NULL; 511 struct net_device *ndev = NULL;
512 unsigned char netid = rdev->net->hport->id;
513 int oldnet;
506 514
507 /* If local device is not rionet capable, give up quickly */ 515 if (netid >= RIONET_MAX_NETS)
508 if (!rionet_capable) 516 return rc;
509 goto out;
510 517
511 /* Allocate our net_device structure */ 518 oldnet = test_and_set_bit(netid, net_table);
512 ndev = alloc_etherdev(sizeof(struct rionet_private));
513 if (ndev == NULL) {
514 rc = -ENOMEM;
515 goto out;
516 }
517 519
518 /* 520 /*
519 * First time through, make sure local device is rionet 521 * First time through, make sure local device is rionet
520 * capable, setup netdev, and set flags so this is skipped 522 * capable, setup netdev (will be skipped on later probes)
521 * on later probes
522 */ 523 */
523 if (!rionet_check) { 524 if (!oldnet) {
524 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, 525 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
525 &lsrc_ops); 526 &lsrc_ops);
526 rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, 527 rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
527 &ldst_ops); 528 &ldst_ops);
528 if (!is_rionet_capable(lsrc_ops, ldst_ops)) { 529 if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
529 printk(KERN_ERR 530 printk(KERN_ERR
530 "%s: local device is not network capable\n", 531 "%s: local device %s is not network capable\n",
531 DRV_NAME); 532 DRV_NAME, rdev->net->hport->name);
532 rionet_check = 1;
533 rionet_capable = 0;
534 goto out; 533 goto out;
535 } 534 }
536 535
536 /* Allocate our net_device structure */
537 ndev = alloc_etherdev(sizeof(struct rionet_private));
538 if (ndev == NULL) {
539 rc = -ENOMEM;
540 goto out;
541 }
542 nets[netid].ndev = ndev;
537 rc = rionet_setup_netdev(rdev->net->hport, ndev); 543 rc = rionet_setup_netdev(rdev->net->hport, ndev);
538 rionet_check = 1; 544 INIT_LIST_HEAD(&nets[netid].peers);
539 nact = 0; 545 nets[netid].nact = 0;
540 } 546 } else if (nets[netid].ndev == NULL)
547 goto out;
541 548
542 /* 549 /*
543 * If the remote device has mailbox/doorbell capabilities, 550 * If the remote device has mailbox/doorbell capabilities,
@@ -549,10 +556,10 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
549 goto out; 556 goto out;
550 } 557 }
551 peer->rdev = rdev; 558 peer->rdev = rdev;
552 list_add_tail(&peer->node, &rionet_peers); 559 list_add_tail(&peer->node, &nets[netid].peers);
553 } 560 }
554 561
555 rio_set_drvdata(rdev, ndev); 562 rio_set_drvdata(rdev, nets[netid].ndev);
556 563
557 out: 564 out:
558 return rc; 565 return rc;