aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/rionet.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/rionet.c')
-rw-r--r--drivers/net/rionet.c152
1 files changed, 102 insertions, 50 deletions
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index f994fa1fde2f..c15d9581dd56 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -63,6 +63,7 @@ struct rionet_private {
63 spinlock_t lock; 63 spinlock_t lock;
64 spinlock_t tx_lock; 64 spinlock_t tx_lock;
65 u32 msg_enable; 65 u32 msg_enable;
66 bool open;
66}; 67};
67 68
68struct rionet_peer { 69struct rionet_peer {
@@ -74,6 +75,7 @@ struct rionet_peer {
74struct rionet_net { 75struct rionet_net {
75 struct net_device *ndev; 76 struct net_device *ndev;
76 struct list_head peers; 77 struct list_head peers;
78 spinlock_t lock; /* net info access lock */
77 struct rio_dev **active; 79 struct rio_dev **active;
78 int nact; /* number of active peers */ 80 int nact; /* number of active peers */
79}; 81};
@@ -235,26 +237,32 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
235 struct net_device *ndev = dev_id; 237 struct net_device *ndev = dev_id;
236 struct rionet_private *rnet = netdev_priv(ndev); 238 struct rionet_private *rnet = netdev_priv(ndev);
237 struct rionet_peer *peer; 239 struct rionet_peer *peer;
240 unsigned char netid = rnet->mport->id;
238 241
239 if (netif_msg_intr(rnet)) 242 if (netif_msg_intr(rnet))
240 printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x", 243 printk(KERN_INFO "%s: doorbell sid %4.4x tid %4.4x info %4.4x",
241 DRV_NAME, sid, tid, info); 244 DRV_NAME, sid, tid, info);
242 if (info == RIONET_DOORBELL_JOIN) { 245 if (info == RIONET_DOORBELL_JOIN) {
243 if (!nets[rnet->mport->id].active[sid]) { 246 if (!nets[netid].active[sid]) {
244 list_for_each_entry(peer, 247 spin_lock(&nets[netid].lock);
245 &nets[rnet->mport->id].peers, node) { 248 list_for_each_entry(peer, &nets[netid].peers, node) {
246 if (peer->rdev->destid == sid) { 249 if (peer->rdev->destid == sid) {
247 nets[rnet->mport->id].active[sid] = 250 nets[netid].active[sid] = peer->rdev;
248 peer->rdev; 251 nets[netid].nact++;
249 nets[rnet->mport->id].nact++;
250 } 252 }
251 } 253 }
254 spin_unlock(&nets[netid].lock);
255
252 rio_mport_send_doorbell(mport, sid, 256 rio_mport_send_doorbell(mport, sid,
253 RIONET_DOORBELL_JOIN); 257 RIONET_DOORBELL_JOIN);
254 } 258 }
255 } else if (info == RIONET_DOORBELL_LEAVE) { 259 } else if (info == RIONET_DOORBELL_LEAVE) {
256 nets[rnet->mport->id].active[sid] = NULL; 260 spin_lock(&nets[netid].lock);
257 nets[rnet->mport->id].nact--; 261 if (nets[netid].active[sid]) {
262 nets[netid].active[sid] = NULL;
263 nets[netid].nact--;
264 }
265 spin_unlock(&nets[netid].lock);
258 } else { 266 } else {
259 if (netif_msg_intr(rnet)) 267 if (netif_msg_intr(rnet))
260 printk(KERN_WARNING "%s: unhandled doorbell\n", 268 printk(KERN_WARNING "%s: unhandled doorbell\n",
@@ -308,8 +316,10 @@ static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbo
308static int rionet_open(struct net_device *ndev) 316static int rionet_open(struct net_device *ndev)
309{ 317{
310 int i, rc = 0; 318 int i, rc = 0;
311 struct rionet_peer *peer, *tmp; 319 struct rionet_peer *peer;
312 struct rionet_private *rnet = netdev_priv(ndev); 320 struct rionet_private *rnet = netdev_priv(ndev);
321 unsigned char netid = rnet->mport->id;
322 unsigned long flags;
313 323
314 if (netif_msg_ifup(rnet)) 324 if (netif_msg_ifup(rnet))
315 printk(KERN_INFO "%s: open\n", DRV_NAME); 325 printk(KERN_INFO "%s: open\n", DRV_NAME);
@@ -348,20 +358,13 @@ static int rionet_open(struct net_device *ndev)
348 netif_carrier_on(ndev); 358 netif_carrier_on(ndev);
349 netif_start_queue(ndev); 359 netif_start_queue(ndev);
350 360
351 list_for_each_entry_safe(peer, tmp, 361 spin_lock_irqsave(&nets[netid].lock, flags);
352 &nets[rnet->mport->id].peers, node) { 362 list_for_each_entry(peer, &nets[netid].peers, node) {
353 if (!(peer->res = rio_request_outb_dbell(peer->rdev,
354 RIONET_DOORBELL_JOIN,
355 RIONET_DOORBELL_LEAVE)))
356 {
357 printk(KERN_ERR "%s: error requesting doorbells\n",
358 DRV_NAME);
359 continue;
360 }
361
362 /* Send a join message */ 363 /* Send a join message */
363 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN); 364 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
364 } 365 }
366 spin_unlock_irqrestore(&nets[netid].lock, flags);
367 rnet->open = true;
365 368
366 out: 369 out:
367 return rc; 370 return rc;
@@ -370,7 +373,9 @@ static int rionet_open(struct net_device *ndev)
370static int rionet_close(struct net_device *ndev) 373static int rionet_close(struct net_device *ndev)
371{ 374{
372 struct rionet_private *rnet = netdev_priv(ndev); 375 struct rionet_private *rnet = netdev_priv(ndev);
373 struct rionet_peer *peer, *tmp; 376 struct rionet_peer *peer;
377 unsigned char netid = rnet->mport->id;
378 unsigned long flags;
374 int i; 379 int i;
375 380
376 if (netif_msg_ifup(rnet)) 381 if (netif_msg_ifup(rnet))
@@ -378,18 +383,21 @@ static int rionet_close(struct net_device *ndev)
378 383
379 netif_stop_queue(ndev); 384 netif_stop_queue(ndev);
380 netif_carrier_off(ndev); 385 netif_carrier_off(ndev);
386 rnet->open = false;
381 387
382 for (i = 0; i < RIONET_RX_RING_SIZE; i++) 388 for (i = 0; i < RIONET_RX_RING_SIZE; i++)
383 kfree_skb(rnet->rx_skb[i]); 389 kfree_skb(rnet->rx_skb[i]);
384 390
385 list_for_each_entry_safe(peer, tmp, 391 spin_lock_irqsave(&nets[netid].lock, flags);
386 &nets[rnet->mport->id].peers, node) { 392 list_for_each_entry(peer, &nets[netid].peers, node) {
387 if (nets[rnet->mport->id].active[peer->rdev->destid]) { 393 if (nets[netid].active[peer->rdev->destid]) {
388 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE); 394 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_LEAVE);
389 nets[rnet->mport->id].active[peer->rdev->destid] = NULL; 395 nets[netid].active[peer->rdev->destid] = NULL;
390 } 396 }
391 rio_release_outb_dbell(peer->rdev, peer->res); 397 if (peer->res)
398 rio_release_outb_dbell(peer->rdev, peer->res);
392 } 399 }
400 spin_unlock_irqrestore(&nets[netid].lock, flags);
393 401
394 rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN, 402 rio_release_inb_dbell(rnet->mport, RIONET_DOORBELL_JOIN,
395 RIONET_DOORBELL_LEAVE); 403 RIONET_DOORBELL_LEAVE);
@@ -403,22 +411,38 @@ static void rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
403{ 411{
404 struct rio_dev *rdev = to_rio_dev(dev); 412 struct rio_dev *rdev = to_rio_dev(dev);
405 unsigned char netid = rdev->net->hport->id; 413 unsigned char netid = rdev->net->hport->id;
406 struct rionet_peer *peer, *tmp; 414 struct rionet_peer *peer;
415 int state, found = 0;
416 unsigned long flags;
407 417
408 if (dev_rionet_capable(rdev)) { 418 if (!dev_rionet_capable(rdev))
409 list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { 419 return;
410 if (peer->rdev == rdev) { 420
411 if (nets[netid].active[rdev->destid]) { 421 spin_lock_irqsave(&nets[netid].lock, flags);
412 nets[netid].active[rdev->destid] = NULL; 422 list_for_each_entry(peer, &nets[netid].peers, node) {
413 nets[netid].nact--; 423 if (peer->rdev == rdev) {
424 list_del(&peer->node);
425 if (nets[netid].active[rdev->destid]) {
426 state = atomic_read(&rdev->state);
427 if (state != RIO_DEVICE_GONE &&
428 state != RIO_DEVICE_INITIALIZING) {
429 rio_send_doorbell(rdev,
430 RIONET_DOORBELL_LEAVE);
414 } 431 }
415 432 nets[netid].active[rdev->destid] = NULL;
416 list_del(&peer->node); 433 nets[netid].nact--;
417 kfree(peer);
418 break;
419 } 434 }
435 found = 1;
436 break;
420 } 437 }
421 } 438 }
439 spin_unlock_irqrestore(&nets[netid].lock, flags);
440
441 if (found) {
442 if (peer->res)
443 rio_release_outb_dbell(rdev, peer->res);
444 kfree(peer);
445 }
422} 446}
423 447
424static void rionet_get_drvinfo(struct net_device *ndev, 448static void rionet_get_drvinfo(struct net_device *ndev,
@@ -492,6 +516,7 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
492 /* Set up private area */ 516 /* Set up private area */
493 rnet = netdev_priv(ndev); 517 rnet = netdev_priv(ndev);
494 rnet->mport = mport; 518 rnet->mport = mport;
519 rnet->open = false;
495 520
496 /* Set the default MAC address */ 521 /* Set the default MAC address */
497 device_id = rio_local_get_device_id(mport); 522 device_id = rio_local_get_device_id(mport);
@@ -514,8 +539,11 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
514 rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL; 539 rnet->msg_enable = RIONET_DEFAULT_MSGLEVEL;
515 540
516 rc = register_netdev(ndev); 541 rc = register_netdev(ndev);
517 if (rc != 0) 542 if (rc != 0) {
543 free_pages((unsigned long)nets[mport->id].active,
544 get_order(rionet_active_bytes));
518 goto out; 545 goto out;
546 }
519 547
520 printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s\n", 548 printk(KERN_INFO "%s: %s %s Version %s, MAC %pM, %s\n",
521 ndev->name, 549 ndev->name,
@@ -529,8 +557,6 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
529 return rc; 557 return rc;
530} 558}
531 559
532static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
533
534static int rionet_add_dev(struct device *dev, struct subsys_interface *sif) 560static int rionet_add_dev(struct device *dev, struct subsys_interface *sif)
535{ 561{
536 int rc = -ENODEV; 562 int rc = -ENODEV;
@@ -539,19 +565,16 @@ static int rionet_add_dev(struct device *dev, struct subsys_interface *sif)
539 struct net_device *ndev = NULL; 565 struct net_device *ndev = NULL;
540 struct rio_dev *rdev = to_rio_dev(dev); 566 struct rio_dev *rdev = to_rio_dev(dev);
541 unsigned char netid = rdev->net->hport->id; 567 unsigned char netid = rdev->net->hport->id;
542 int oldnet;
543 568
544 if (netid >= RIONET_MAX_NETS) 569 if (netid >= RIONET_MAX_NETS)
545 return rc; 570 return rc;
546 571
547 oldnet = test_and_set_bit(netid, net_table);
548
549 /* 572 /*
550 * If first time through this net, make sure local device is rionet 573 * If first time through this net, make sure local device is rionet
551 * capable and setup netdev (this step will be skipped in later probes 574 * capable and setup netdev (this step will be skipped in later probes
552 * on the same net). 575 * on the same net).
553 */ 576 */
554 if (!oldnet) { 577 if (!nets[netid].ndev) {
555 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, 578 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR,
556 &lsrc_ops); 579 &lsrc_ops);
557 rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR, 580 rio_local_read_config_32(rdev->net->hport, RIO_DST_OPS_CAR,
@@ -569,30 +592,56 @@ static int rionet_add_dev(struct device *dev, struct subsys_interface *sif)
569 rc = -ENOMEM; 592 rc = -ENOMEM;
570 goto out; 593 goto out;
571 } 594 }
572 nets[netid].ndev = ndev; 595
573 rc = rionet_setup_netdev(rdev->net->hport, ndev); 596 rc = rionet_setup_netdev(rdev->net->hport, ndev);
574 if (rc) { 597 if (rc) {
575 printk(KERN_ERR "%s: failed to setup netdev (rc=%d)\n", 598 printk(KERN_ERR "%s: failed to setup netdev (rc=%d)\n",
576 DRV_NAME, rc); 599 DRV_NAME, rc);
600 free_netdev(ndev);
577 goto out; 601 goto out;
578 } 602 }
579 603
580 INIT_LIST_HEAD(&nets[netid].peers); 604 INIT_LIST_HEAD(&nets[netid].peers);
605 spin_lock_init(&nets[netid].lock);
581 nets[netid].nact = 0; 606 nets[netid].nact = 0;
582 } else if (nets[netid].ndev == NULL) 607 nets[netid].ndev = ndev;
583 goto out; 608 }
584 609
585 /* 610 /*
586 * If the remote device has mailbox/doorbell capabilities, 611 * If the remote device has mailbox/doorbell capabilities,
587 * add it to the peer list. 612 * add it to the peer list.
588 */ 613 */
589 if (dev_rionet_capable(rdev)) { 614 if (dev_rionet_capable(rdev)) {
590 if (!(peer = kmalloc(sizeof(struct rionet_peer), GFP_KERNEL))) { 615 struct rionet_private *rnet;
616 unsigned long flags;
617
618 rnet = netdev_priv(nets[netid].ndev);
619
620 peer = kzalloc(sizeof(*peer), GFP_KERNEL);
621 if (!peer) {
591 rc = -ENOMEM; 622 rc = -ENOMEM;
592 goto out; 623 goto out;
593 } 624 }
594 peer->rdev = rdev; 625 peer->rdev = rdev;
626 peer->res = rio_request_outb_dbell(peer->rdev,
627 RIONET_DOORBELL_JOIN,
628 RIONET_DOORBELL_LEAVE);
629 if (!peer->res) {
630 pr_err("%s: error requesting doorbells\n", DRV_NAME);
631 kfree(peer);
632 rc = -ENOMEM;
633 goto out;
634 }
635
636 spin_lock_irqsave(&nets[netid].lock, flags);
595 list_add_tail(&peer->node, &nets[netid].peers); 637 list_add_tail(&peer->node, &nets[netid].peers);
638 spin_unlock_irqrestore(&nets[netid].lock, flags);
639 pr_debug("%s: %s add peer %s\n",
640 DRV_NAME, __func__, rio_name(rdev));
641
642 /* If netdev is already opened, send join request to new peer */
643 if (rnet->open)
644 rio_send_doorbell(peer->rdev, RIONET_DOORBELL_JOIN);
596 } 645 }
597 646
598 return 0; 647 return 0;
@@ -603,7 +652,8 @@ out:
603static int rionet_shutdown(struct notifier_block *nb, unsigned long code, 652static int rionet_shutdown(struct notifier_block *nb, unsigned long code,
604 void *unused) 653 void *unused)
605{ 654{
606 struct rionet_peer *peer, *tmp; 655 struct rionet_peer *peer;
656 unsigned long flags;
607 int i; 657 int i;
608 658
609 pr_debug("%s: %s\n", DRV_NAME, __func__); 659 pr_debug("%s: %s\n", DRV_NAME, __func__);
@@ -612,13 +662,15 @@ static int rionet_shutdown(struct notifier_block *nb, unsigned long code,
612 if (!nets[i].ndev) 662 if (!nets[i].ndev)
613 continue; 663 continue;
614 664
615 list_for_each_entry_safe(peer, tmp, &nets[i].peers, node) { 665 spin_lock_irqsave(&nets[i].lock, flags);
666 list_for_each_entry(peer, &nets[i].peers, node) {
616 if (nets[i].active[peer->rdev->destid]) { 667 if (nets[i].active[peer->rdev->destid]) {
617 rio_send_doorbell(peer->rdev, 668 rio_send_doorbell(peer->rdev,
618 RIONET_DOORBELL_LEAVE); 669 RIONET_DOORBELL_LEAVE);
619 nets[i].active[peer->rdev->destid] = NULL; 670 nets[i].active[peer->rdev->destid] = NULL;
620 } 671 }
621 } 672 }
673 spin_unlock_irqrestore(&nets[i].lock, flags);
622 } 674 }
623 675
624 return NOTIFY_DONE; 676 return NOTIFY_DONE;