2 * Handling of a single switch chip, part of a switch fabric
4 * Copyright (c) 2017 Vivien Didelot <vivien.didelot@savoirfairelinux.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
12 #include <linux/netdevice.h>
13 #include <linux/notifier.h>
16 static int dsa_switch_bridge_join(struct dsa_switch
*ds
,
17 struct dsa_notifier_bridge_info
*info
)
19 if (ds
->index
== info
->sw_index
&& ds
->ops
->port_bridge_join
)
20 return ds
->ops
->port_bridge_join(ds
, info
->port
, info
->br
);
22 if (ds
->index
!= info
->sw_index
)
23 dev_dbg(ds
->dev
, "crosschip DSA port %d.%d bridged to %s\n",
24 info
->sw_index
, info
->port
, netdev_name(info
->br
));
29 static int dsa_switch_bridge_leave(struct dsa_switch
*ds
,
30 struct dsa_notifier_bridge_info
*info
)
32 if (ds
->index
== info
->sw_index
&& ds
->ops
->port_bridge_leave
)
33 ds
->ops
->port_bridge_leave(ds
, info
->port
, info
->br
);
35 if (ds
->index
!= info
->sw_index
)
36 dev_dbg(ds
->dev
, "crosschip DSA port %d.%d unbridged from %s\n",
37 info
->sw_index
, info
->port
, netdev_name(info
->br
));
42 static int dsa_switch_event(struct notifier_block
*nb
,
43 unsigned long event
, void *info
)
45 struct dsa_switch
*ds
= container_of(nb
, struct dsa_switch
, nb
);
49 case DSA_NOTIFIER_BRIDGE_JOIN
:
50 err
= dsa_switch_bridge_join(ds
, info
);
52 case DSA_NOTIFIER_BRIDGE_LEAVE
:
53 err
= dsa_switch_bridge_leave(ds
, info
);
60 /* Non-switchdev operations cannot be rolled back. If a DSA driver
61 * returns an error during the chained call, switch chips may be in an
65 dev_dbg(ds
->dev
, "breaking chain for DSA event %lu (%d)\n",
68 return notifier_from_errno(err
);
71 int dsa_switch_register_notifier(struct dsa_switch
*ds
)
73 ds
->nb
.notifier_call
= dsa_switch_event
;
75 return raw_notifier_chain_register(&ds
->dst
->nh
, &ds
->nb
);
78 void dsa_switch_unregister_notifier(struct dsa_switch
*ds
)
82 err
= raw_notifier_chain_unregister(&ds
->dst
->nh
, &ds
->nb
);
84 dev_err(ds
->dev
, "failed to unregister notifier (%d)\n", err
);