summaryrefslogtreecommitdiffstats
path: root/drivers/net/wan/hdlc.c
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2015-12-03 21:12:31 +0100
committerDavid S. Miller <davem@davemloft.net>2015-12-05 23:41:42 +0100
commit2f8364a291e8adde25c93f97a76abbcaf4b1ed3f (patch)
tree7b7e3de286880cf4938c00803df3a1ec32d22997 /drivers/net/wan/hdlc.c
parentWAN: HDLC: Detach protocol before unregistering device (diff)
downloadlinux-2f8364a291e8adde25c93f97a76abbcaf4b1ed3f.tar.xz
linux-2f8364a291e8adde25c93f97a76abbcaf4b1ed3f.zip
WAN: HDLC: Call notifiers before and after changing device type
An HDLC device can change type when the protocol driver is changed. Calling the notifier change allows potential users of the interface know about this planned change, and even block it. After the change has occurred, send a second notification to users can evaluate the new device type etc. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wan/hdlc.c')
-rw-r--r--drivers/net/wan/hdlc.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/net/wan/hdlc.c b/drivers/net/wan/hdlc.c
index 2a6595b4ae15..9bd4aa8083ce 100644
--- a/drivers/net/wan/hdlc.c
+++ b/drivers/net/wan/hdlc.c
@@ -276,7 +276,11 @@ void unregister_hdlc_device(struct net_device *dev)
int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
size_t size)
{
- detach_hdlc_protocol(dev);
+ int err;
+
+ err = detach_hdlc_protocol(dev);
+ if (err)
+ return err;
if (!try_module_get(proto->module))
return -ENOSYS;
@@ -289,15 +293,24 @@ int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
}
}
dev_to_hdlc(dev)->proto = proto;
+
return 0;
}
-void detach_hdlc_protocol(struct net_device *dev)
+int detach_hdlc_protocol(struct net_device *dev)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
+ int err;
if (hdlc->proto) {
+ err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev);
+ err = notifier_to_errno(err);
+ if (err) {
+ netdev_err(dev, "Refused to change device type\n");
+ return err;
+ }
+
if (hdlc->proto->detach)
hdlc->proto->detach(dev);
module_put(hdlc->proto->module);
@@ -306,6 +319,8 @@ void detach_hdlc_protocol(struct net_device *dev)
kfree(hdlc->state);
hdlc->state = NULL;
hdlc_setup_dev(dev);
+
+ return 0;
}