Skip to content

Commit

Permalink
WAN: HDLC: Call notifiers before and after changing device type
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andrew Lunn authored and David S. Miller committed Dec 5, 2015
1 parent ff35164 commit 2f8364a
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 3 deletions.
19 changes: 17 additions & 2 deletions drivers/net/wan/hdlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -306,6 +319,8 @@ void detach_hdlc_protocol(struct net_device *dev)
kfree(hdlc->state);
hdlc->state = NULL;
hdlc_setup_dev(dev);

return 0;
}


Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_cisco.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,7 @@ static int cisco_ioctl(struct net_device *dev, struct ifreq *ifr)
spin_lock_init(&state(hdlc)->lock);
dev->header_ops = &cisco_header_ops;
dev->type = ARPHRD_CISCO;
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
netif_dormant_on(dev);
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_fr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1240,6 +1240,7 @@ static int fr_ioctl(struct net_device *dev, struct ifreq *ifr)
}
memcpy(&state(hdlc)->settings, &new_settings, size);
dev->type = ARPHRD_FRAD;
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
return 0;

case IF_PROTO_FR_ADD_PVC:
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_ppp.c
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
dev->hard_header_len = sizeof(struct hdlc_header);
dev->header_ops = &ppp_header_ops;
dev->type = ARPHRD_PPP;
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
netif_dormant_on(dev);
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_raw.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ static int raw_ioctl(struct net_device *dev, struct ifreq *ifr)
return result;
memcpy(hdlc->state, &new_settings, size);
dev->type = ARPHRD_RAWHDLC;
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
netif_dormant_off(dev);
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_raw_eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
ether_setup(dev);
dev->tx_queue_len = old_qlen;
eth_hw_addr_random(dev);
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
netif_dormant_off(dev);
return 0;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/wan/hdlc_x25.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
if ((result = attach_hdlc_protocol(dev, &proto, 0)))
return result;
dev->type = ARPHRD_X25;
call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, dev);
netif_dormant_off(dev);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion include/linux/hdlc.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ netdev_tx_t hdlc_start_xmit(struct sk_buff *skb, struct net_device *dev);
int attach_hdlc_protocol(struct net_device *dev, struct hdlc_proto *proto,
size_t size);
/* May be used by hardware driver to gain control over HDLC device */
void detach_hdlc_protocol(struct net_device *dev);
int detach_hdlc_protocol(struct net_device *dev);

static __inline__ __be16 hdlc_type_trans(struct sk_buff *skb,
struct net_device *dev)
Expand Down

0 comments on commit 2f8364a

Please sign in to comment.