aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2016-03-22 17:26:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-22 18:36:02 -0400
commitf41e2472ba115275438161fd72d40b2448963658 (patch)
tree671ad8bd4da5a02fcc49e1833df664adee6cbba2
parente3dd8cd4778ebc75c654f73d8673281078c81ed9 (diff)
rapidio/rionet: add shutdown event handling
Add shutdown notification handler which terminates active connections with remote RapidIO nodes. This prevents remote nodes from sending packets to the powered off node and eliminates hardware error events on remote nodes. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Aurelien Jacquiot <a-jacquiot@ti.com> Cc: Andre van Herk <andre.van.herk@prodrive-technologies.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/net/rionet.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index d3d6e35a30e0..f994fa1fde2f 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -24,6 +24,7 @@
24#include <linux/skbuff.h> 24#include <linux/skbuff.h>
25#include <linux/crc32.h> 25#include <linux/crc32.h>
26#include <linux/ethtool.h> 26#include <linux/ethtool.h>
27#include <linux/reboot.h>
27 28
28#define DRV_NAME "rionet" 29#define DRV_NAME "rionet"
29#define DRV_VERSION "0.3" 30#define DRV_VERSION "0.3"
@@ -599,6 +600,30 @@ out:
599 return rc; 600 return rc;
600} 601}
601 602
603static int rionet_shutdown(struct notifier_block *nb, unsigned long code,
604 void *unused)
605{
606 struct rionet_peer *peer, *tmp;
607 int i;
608
609 pr_debug("%s: %s\n", DRV_NAME, __func__);
610
611 for (i = 0; i < RIONET_MAX_NETS; i++) {
612 if (!nets[i].ndev)
613 continue;
614
615 list_for_each_entry_safe(peer, tmp, &nets[i].peers, node) {
616 if (nets[i].active[peer->rdev->destid]) {
617 rio_send_doorbell(peer->rdev,
618 RIONET_DOORBELL_LEAVE);
619 nets[i].active[peer->rdev->destid] = NULL;
620 }
621 }
622 }
623
624 return NOTIFY_DONE;
625}
626
602#ifdef MODULE 627#ifdef MODULE
603static struct rio_device_id rionet_id_table[] = { 628static struct rio_device_id rionet_id_table[] = {
604 {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}, 629 {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)},
@@ -615,8 +640,20 @@ static struct subsys_interface rionet_interface = {
615 .remove_dev = rionet_remove_dev, 640 .remove_dev = rionet_remove_dev,
616}; 641};
617 642
643static struct notifier_block rionet_notifier = {
644 .notifier_call = rionet_shutdown,
645};
646
618static int __init rionet_init(void) 647static int __init rionet_init(void)
619{ 648{
649 int ret;
650
651 ret = register_reboot_notifier(&rionet_notifier);
652 if (ret) {
653 pr_err("%s: failed to register reboot notifier (err=%d)\n",
654 DRV_NAME, ret);
655 return ret;
656 }
620 return subsys_interface_register(&rionet_interface); 657 return subsys_interface_register(&rionet_interface);
621} 658}
622 659
@@ -648,6 +685,7 @@ static void __exit rionet_exit(void)
648 } 685 }
649 } 686 }
650 687
688 unregister_reboot_notifier(&rionet_notifier);
651 subsys_interface_unregister(&rionet_interface); 689 subsys_interface_unregister(&rionet_interface);
652} 690}
653 691