Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Andrew Lunn and committed by
David S. Miller
2f8364a2 ff351644

+24 -3
+17 -2
drivers/net/wan/hdlc.c
··· 276 276 int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, 277 277 size_t size) 278 278 { 279 - detach_hdlc_protocol(dev); 279 + int err; 280 + 281 + err = detach_hdlc_protocol(dev); 282 + if (err) 283 + return err; 280 284 281 285 if (!try_module_get(proto->module)) 282 286 return -ENOSYS; ··· 293 289 } 294 290 } 295 291 dev_to_hdlc(dev)->proto = proto; 292 + 296 293 return 0; 297 294 } 298 295 299 296 300 - void detach_hdlc_protocol(struct net_device *dev) 297 + int detach_hdlc_protocol(struct net_device *dev) 301 298 { 302 299 hdlc_device *hdlc = dev_to_hdlc(dev); 300 + int err; 303 301 304 302 if (hdlc->proto) { 303 + err = call_netdevice_notifiers(NETDEV_PRE_TYPE_CHANGE, dev); 304 + err = notifier_to_errno(err); 305 + if (err) { 306 + netdev_err(dev, "Refused to change device type\n"); 307 + return err; 308 + } 309 + 305 310 if (hdlc->proto->detach) 306 311 hdlc->proto->detach(dev); 307 312 module_put(hdlc->proto->module); ··· 319 306 kfree(hdlc->state); 320 307 hdlc->state = NULL; 321 308 hdlc_setup_dev(dev); 309 + 310 + return 0; 322 311 } 323 312 324 313
+1
drivers/net/wan/hdlc_cisco.c
··· 378 378 spin_lock_init(&state(hdlc)->lock); 379 379 dev->header_ops = &cisco_header_ops; 380 380 dev->type = ARPHRD_CISCO; 381 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 381 382 netif_dormant_on(dev); 382 383 return 0; 383 384 }
+1
drivers/net/wan/hdlc_fr.c
··· 1240 1240 } 1241 1241 memcpy(&state(hdlc)->settings, &new_settings, size); 1242 1242 dev->type = ARPHRD_FRAD; 1243 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 1243 1244 return 0; 1244 1245 1245 1246 case IF_PROTO_FR_ADD_PVC:
+1
drivers/net/wan/hdlc_ppp.c
··· 687 687 dev->hard_header_len = sizeof(struct hdlc_header); 688 688 dev->header_ops = &ppp_header_ops; 689 689 dev->type = ARPHRD_PPP; 690 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 690 691 netif_dormant_on(dev); 691 692 return 0; 692 693 }
+1
drivers/net/wan/hdlc_raw.c
··· 84 84 return result; 85 85 memcpy(hdlc->state, &new_settings, size); 86 86 dev->type = ARPHRD_RAWHDLC; 87 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 87 88 netif_dormant_off(dev); 88 89 return 0; 89 90 }
+1
drivers/net/wan/hdlc_raw_eth.c
··· 102 102 ether_setup(dev); 103 103 dev->tx_queue_len = old_qlen; 104 104 eth_hw_addr_random(dev); 105 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 105 106 netif_dormant_off(dev); 106 107 return 0; 107 108 }
+1
drivers/net/wan/hdlc_x25.c
··· 213 213 if ((result = attach_hdlc_protocol(dev, &proto, 0))) 214 214 return result; 215 215 dev->type = ARPHRD_X25; 216 + call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev); 216 217 netif_dormant_off(dev); 217 218 return 0; 218 219 }
+1 -1
include/linux/hdlc.h
··· 101 101 int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto, 102 102 size_t size); 103 103 /* May be used by hardware driver to gain control over HDLC device */ 104 - void detach_hdlc_protocol(struct net_device *dev); 104 + int detach_hdlc_protocol(struct net_device *dev); 105 105 106 106 static __inline__ __be16 hdlc_type_trans(struct sk_buff *skb, 107 107 struct net_device *dev)