Commit 2fb717ec3ec76b0ca4cee9c4d802ce551750413d

Authored by Alexandre Bounine
Committed by Linus Torvalds
1 parent 005842efd1

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>

Showing 1 changed file with 70 additions and 63 deletions Side-by-side Diff

drivers/net/rionet.c
... ... @@ -26,7 +26,7 @@
26 26 #include <linux/ethtool.h>
27 27  
28 28 #define DRV_NAME "rionet"
29   -#define DRV_VERSION "0.2"
  29 +#define DRV_VERSION "0.3"
30 30 #define DRV_AUTHOR "Matt Porter <mporter@kernel.crashing.org>"
31 31 #define DRV_DESC "Ethernet over RapidIO"
32 32  
33 33  
... ... @@ -47,9 +47,8 @@
47 47  
48 48 #define RIONET_TX_RING_SIZE CONFIG_RIONET_TX_SIZE
49 49 #define RIONET_RX_RING_SIZE CONFIG_RIONET_RX_SIZE
  50 +#define RIONET_MAX_NETS 8
50 51  
51   -static LIST_HEAD(rionet_peers);
52   -
53 52 struct rionet_private {
54 53 struct rio_mport *mport;
55 54 struct sk_buff *rx_skb[RIONET_RX_RING_SIZE];
56 55  
... ... @@ -69,17 +68,14 @@
69 68 struct resource *res;
70 69 };
71 70  
72   -static int rionet_check = 0;
73   -static int rionet_capable = 1;
  71 +struct rionet_net {
  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   -/*
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   - */
81   -static struct rio_dev **rionet_active;
82   -static int nact; /* total number of active rionet peers */
  78 +static struct rionet_net nets[RIONET_MAX_NETS];
83 79  
84 80 #define is_rionet_capable(src_ops, dst_ops) \
85 81 ((src_ops & RIO_SRC_OPS_DATA_MSG) && \
... ... @@ -185,7 +181,7 @@
185 181 }
186 182  
187 183 if (is_multicast_ether_addr(eth->h_dest))
188   - add_num = nact;
  184 + add_num = nets[rnet->mport->id].nact;
189 185  
190 186 if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) {
191 187 netif_stop_queue(ndev);
192 188  
193 189  
194 190  
... ... @@ -197,19 +193,21 @@
197 193  
198 194 if (is_multicast_ether_addr(eth->h_dest)) {
199 195 int count = 0;
  196 +
200 197 for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size);
201 198 i++)
202   - if (rionet_active[i]) {
  199 + if (nets[rnet->mport->id].active[i]) {
203 200 rionet_queue_tx_msg(skb, ndev,
204   - rionet_active[i]);
  201 + nets[rnet->mport->id].active[i]);
205 202 if (count)
206 203 atomic_inc(&skb->users);
207 204 count++;
208 205 }
209 206 } else if (RIONET_MAC_MATCH(eth->h_dest)) {
210 207 destid = RIONET_GET_DESTID(eth->h_dest);
211   - if (rionet_active[destid])
212   - rionet_queue_tx_msg(skb, ndev, rionet_active[destid]);
  208 + if (nets[rnet->mport->id].active[destid])
  209 + rionet_queue_tx_msg(skb, ndev,
  210 + nets[rnet->mport->id].active[destid]);
213 211 }
214 212  
215 213 spin_unlock_irqrestore(&rnet->tx_lock, flags);
216 214  
217 215  
... ... @@ -228,19 +226,21 @@
228 226 printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
229 227 DRV_NAME, sid, tid, info);
230 228 if (info == RIONET_DOORBELL_JOIN) {
231   - if (!rionet_active[sid]) {
232   - list_for_each_entry(peer, &rionet_peers, node) {
  229 + if (!nets[rnet->mport->id].active[sid]) {
  230 + list_for_each_entry(peer,
  231 + &nets[rnet->mport->id].peers, node) {
233 232 if (peer->rdev->destid == sid) {
234   - rionet_active[sid] = peer->rdev;
235   - nact++;
  233 + nets[rnet->mport->id].active[sid] =
  234 + peer->rdev;
  235 + nets[rnet->mport->id].nact++;
236 236 }
237 237 }
238 238 rio_mport_send_doorbell(mport, sid,
239 239 RIONET_DOORBELL_JOIN);
240 240 }
241 241 } else if (info == RIONET_DOORBELL_LEAVE) {
242   - rionet_active[sid] = NULL;
243   - nact--;
  242 + nets[rnet->mport->id].active[sid] = NULL;
  243 + nets[rnet->mport->id].nact--;
244 244 } else {
245 245 if (netif_msg_intr(rnet))
246 246 printk(KERN_WARNING "%s: unhandled doorbell\n",
... ... @@ -334,7 +334,8 @@
334 334 netif_carrier_on(ndev);
335 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 339 if (!(peer->res = rio_request_outb_dbell(peer->rdev,
339 340 RIONET_DOORBELL_JOIN,
340 341 RIONET_DOORBELL_LEAVE)))
... ... @@ -359,7 +360,7 @@
359 360 int i;
360 361  
361 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 365 netif_stop_queue(ndev);
365 366 netif_carrier_off(ndev);
366 367  
... ... @@ -367,10 +368,11 @@
367 368 for (i = 0; i < RIONET_RX_RING_SIZE; i++)
368 369 kfree_skb(rnet->rx_skb[i]);
369 370  
370   - list_for_each_entry_safe(peer, tmp, &rionet_peers, node) {
371   - if (rionet_active[peer->rdev->destid]) {
  371 + list_for_each_entry_safe(peer, tmp,
  372 + &nets[rnet->mport->id].peers, node) {
  373 + if (nets[rnet->mport->id].active[peer->rdev->destid]) {
372 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 377 rio_release_outb_dbell(peer->rdev, peer->res);
376 378 }
377 379  
378 380  
379 381  
380 382  
... ... @@ -386,17 +388,21 @@
386 388 static void rionet_remove(struct rio_dev *rdev)
387 389 {
388 390 struct net_device *ndev = rio_get_drvdata(rdev);
  391 + unsigned char netid = rdev->net->hport->id;
389 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 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 401 list_del(&peer->node);
398 402 kfree(peer);
399 403 }
  404 +
  405 + free_netdev(ndev);
400 406 }
401 407  
402 408 static void rionet_get_drvinfo(struct net_device *ndev,
403 409  
... ... @@ -448,13 +454,13 @@
448 454 const size_t rionet_active_bytes = sizeof(void *) *
449 455 RIO_MAX_ROUTE_ENTRIES(mport->sys_size);
450 456  
451   - rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
452   - get_order(rionet_active_bytes));
453   - if (!rionet_active) {
  457 + nets[mport->id].active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
  458 + get_order(rionet_active_bytes));
  459 + if (!nets[mport->id].active) {
454 460 rc = -ENOMEM;
455 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 465 /* Set up private area */
460 466 rnet = netdev_priv(ndev);
461 467  
462 468  
463 469  
464 470  
465 471  
466 472  
467 473  
468 474  
469 475  
470 476  
... ... @@ -483,61 +489,62 @@
483 489 if (rc != 0)
484 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 493 ndev->name,
488 494 DRV_NAME,
489 495 DRV_DESC,
490 496 DRV_VERSION,
491   - ndev->dev_addr);
  497 + ndev->dev_addr,
  498 + mport->name);
492 499  
493 500 out:
494 501 return rc;
495 502 }
496 503  
497   -/*
498   - * XXX Make multi-net safe
499   - */
  504 +static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
  505 +
500 506 static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
501 507 {
502 508 int rc = -ENODEV;
503 509 u32 lsrc_ops, ldst_ops;
504 510 struct rionet_peer *peer;
505 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 */
508   - if (!rionet_capable)
509   - goto out;
  515 + if (netid >= RIONET_MAX_NETS)
  516 + return rc;
510 517  
511   - /* Allocate our net_device structure */
512   - ndev = alloc_etherdev(sizeof(struct rionet_private));
513   - if (ndev == NULL) {
514   - rc = -ENOMEM;
515   - goto out;
516   - }
  518 + oldnet = test_and_set_bit(netid, net_table);
517 519  
518 520 /*
519 521 * First time through, make sure local device is rionet
520   - * capable, setup netdev, and set flags so this is skipped
521   - * on later probes
  522 + * capable, setup netdev (will be skipped on later probes)
522 523 */
523   - if (!rionet_check) {
  524 + if (!oldnet) {
524 525 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
525 526 &lsrc_ops);
526 527 rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
527 528 &ldst_ops);
528 529 if (!is_rionet_capable(lsrc_ops, ldst_ops)) {
529 530 printk(KERN_ERR
530   - "%s: local device is not network capable\n",
531   - DRV_NAME);
532   - rionet_check = 1;
533   - rionet_capable = 0;
  531 + "%s: local device %s is not network capable\n",
  532 + DRV_NAME, rdev->net->hport->name);
534 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 543 rc = rionet_setup_netdev(rdev->net->hport, ndev);
538   - rionet_check = 1;
539   - nact = 0;
540   - }
  544 + INIT_LIST_HEAD(&nets[netid].peers);
  545 + nets[netid].nact = 0;
  546 + } else if (nets[netid].ndev == NULL)
  547 + goto out;
541 548  
542 549 /*
543 550 * If the remote device has mailbox/doorbell capabilities,
544 551  
... ... @@ -549,10 +556,10 @@
549 556 goto out;
550 557 }
551 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 564 out:
558 565 return rc;