for (int i = 0; i < 4; i++)
priv->mirror_group_ports[i] = -1;
- /* Initialize hash table for L3 routing */
- rhltable_init(&priv->routes, &otto_l3_route_ht_params);
-
- /* Register netevent notifier callback to catch notifications about neighboring
- * changes to update nexthop entries for L3 routing.
- */
- priv->ne_nb.notifier_call = otto_l3_netevent_notifier;
- if (register_netevent_notifier(&priv->ne_nb)) {
- priv->ne_nb.notifier_call = NULL;
- dev_err(dev, "Failed to register netevent notifier\n");
- goto err_register_ne_nb;
- }
-
- priv->fib_nb.notifier_call = otto_l3_fib_notifier;
-
- /* Register Forwarding Information Base notifier to offload routes where
- * possible
- * Only FIBs pointing to our own netdevs are programmed into
- * the device, so no need to pass a callback.
- */
- err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL);
+ err = otto_l3_probe(dev, priv);
if (err)
- goto err_register_fib_nb;
+ goto err_register_l3;
/* TODO: put this into l2_setup() */
switch (soc_info.family) {
return 0;
-err_register_fib_nb:
- unregister_netevent_notifier(&priv->ne_nb);
-err_register_ne_nb:
+err_register_l3:
dsa_switch_shutdown(priv->ds);
err_register_switch:
destroy_workqueue(priv->wq);
* work items to avoid them still accessing the DSA structures
* when they are getting shut down.
*/
- unregister_fib_notifier(&init_net, &priv->fib_nb);
- unregister_netevent_notifier(&priv->ne_nb);
+ otto_l3_remove(priv);
cancel_delayed_work_sync(&priv->counters_work);
dsa_switch_shutdown(priv->ds);
/* Called with rcu_read_lock() */
-int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr)
+static int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr)
{
struct fib_notifier_info *info = ptr;
struct rtl838x_switch_priv *priv;
kfree(net_work);
}
-int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr)
+static int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr)
{
struct rtl838x_switch_priv *priv;
struct net_device *dev;
return NOTIFY_DONE;
}
+
+void otto_l3_remove(struct rtl838x_switch_priv *priv)
+{
+ if (priv->ne_nb.notifier_call) {
+ unregister_netevent_notifier(&priv->ne_nb);
+ priv->ne_nb.notifier_call = NULL;
+ }
+ if (priv->fib_nb.notifier_call) {
+ unregister_fib_notifier(&init_net, &priv->fib_nb);
+ priv->fib_nb.notifier_call = NULL;
+ }
+}
+
+int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv)
+{
+ int err;
+
+ /* Initialize hash table for L3 routing */
+ rhltable_init(&priv->routes, &otto_l3_route_ht_params);
+
+ /*
+ * Register netevent notifier callback to catch notifications about neighboring changes
+ * to update nexthop entries for L3 routing.
+ */
+ priv->ne_nb.notifier_call = otto_l3_netevent_notifier;
+ err = register_netevent_notifier(&priv->ne_nb);
+ if (err) {
+ priv->ne_nb.notifier_call = NULL;
+ return dev_err_probe(dev, err, "Failed to register netevent notifier\n");
+ }
+
+ /*
+ * Register Forwarding Information Base notifier to offload routes where possible. Only
+ * FIBs pointing to our own netdevs are programmed into the device, so no need to pass a
+ * callback.
+ */
+ priv->fib_nb.notifier_call = otto_l3_fib_notifier;
+ err = register_fib_notifier(&init_net, &priv->fib_nb, NULL, NULL);
+ if (err) {
+ priv->fib_nb.notifier_call = NULL;
+ otto_l3_remove(priv);
+ return dev_err_probe(dev, err, "Failed to register fib event notifier\n");
+ }
+
+ return 0;
+}
.head_offset = offsetof(struct otto_l3_route, linkage),
};
-int otto_l3_fib_notifier(struct notifier_block *this, unsigned long event, void *ptr);
-int otto_l3_netevent_notifier(struct notifier_block *this, unsigned long event, void *ptr);
+int otto_l3_probe(struct device *dev, struct rtl838x_switch_priv *priv);
+void otto_l3_remove(struct rtl838x_switch_priv *priv);
#endif /* _OTTO_L3_H */