aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Ott <alan@signal11.us>2012-09-01 01:57:07 -0400
committerDavid S. Miller <davem@tempietto.lan>2012-09-01 22:48:02 -0400
commita2dc375e12334b3d8f787a48b2fb6172ccfb80ae (patch)
tree82caa348d85c5470deec9e4505695a9e58f99601
parenta437d2744b0a4e5f405f6b9be284eb9e0a2d7741 (diff)
6lowpan: handle NETDEV_UNREGISTER event
Before, it was impossible to remove a wpan device which had lowpan attached to it. Signed-off-by: Alan Ott <alan@signal11.us> Signed-off-by: David S. Miller <davem@tempietto.lan>
-rw-r--r--net/ieee802154/6lowpan.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index b28ec790c7c..d5291113584 100644
--- a/net/ieee802154/6lowpan.c
+++ b/net/ieee802154/6lowpan.c
@@ -1063,12 +1063,6 @@ out:
1063 return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK); 1063 return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK);
1064} 1064}
1065 1065
1066static void lowpan_dev_free(struct net_device *dev)
1067{
1068 dev_put(lowpan_dev_info(dev)->real_dev);
1069 free_netdev(dev);
1070}
1071
1072static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) 1066static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
1073{ 1067{
1074 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; 1068 struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
@@ -1118,7 +1112,7 @@ static void lowpan_setup(struct net_device *dev)
1118 dev->netdev_ops = &lowpan_netdev_ops; 1112 dev->netdev_ops = &lowpan_netdev_ops;
1119 dev->header_ops = &lowpan_header_ops; 1113 dev->header_ops = &lowpan_header_ops;
1120 dev->ml_priv = &lowpan_mlme; 1114 dev->ml_priv = &lowpan_mlme;
1121 dev->destructor = lowpan_dev_free; 1115 dev->destructor = free_netdev;
1122} 1116}
1123 1117
1124static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) 1118static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1244,6 +1238,34 @@ static inline void __init lowpan_netlink_fini(void)
1244 rtnl_link_unregister(&lowpan_link_ops); 1238 rtnl_link_unregister(&lowpan_link_ops);
1245} 1239}
1246 1240
1241static int lowpan_device_event(struct notifier_block *unused,
1242 unsigned long event,
1243 void *ptr)
1244{
1245 struct net_device *dev = ptr;
1246 LIST_HEAD(del_list);
1247 struct lowpan_dev_record *entry, *tmp;
1248
1249 if (dev->type != ARPHRD_IEEE802154)
1250 goto out;
1251
1252 if (event == NETDEV_UNREGISTER) {
1253 list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
1254 if (lowpan_dev_info(entry->ldev)->real_dev == dev)
1255 lowpan_dellink(entry->ldev, &del_list);
1256 }
1257
1258 unregister_netdevice_many(&del_list);
1259 };
1260
1261out:
1262 return NOTIFY_DONE;
1263}
1264
1265static struct notifier_block lowpan_dev_notifier = {
1266 .notifier_call = lowpan_device_event,
1267};
1268
1247static struct packet_type lowpan_packet_type = { 1269static struct packet_type lowpan_packet_type = {
1248 .type = __constant_htons(ETH_P_IEEE802154), 1270 .type = __constant_htons(ETH_P_IEEE802154),
1249 .func = lowpan_rcv, 1271 .func = lowpan_rcv,
@@ -1258,6 +1280,12 @@ static int __init lowpan_init_module(void)
1258 goto out; 1280 goto out;
1259 1281
1260 dev_add_pack(&lowpan_packet_type); 1282 dev_add_pack(&lowpan_packet_type);
1283
1284 err = register_netdevice_notifier(&lowpan_dev_notifier);
1285 if (err < 0) {
1286 dev_remove_pack(&lowpan_packet_type);
1287 lowpan_netlink_fini();
1288 }
1261out: 1289out:
1262 return err; 1290 return err;
1263} 1291}
@@ -1270,6 +1298,8 @@ static void __exit lowpan_cleanup_module(void)
1270 1298
1271 dev_remove_pack(&lowpan_packet_type); 1299 dev_remove_pack(&lowpan_packet_type);
1272 1300
1301 unregister_netdevice_notifier(&lowpan_dev_notifier);
1302
1273 /* Now 6lowpan packet_type is removed, so no new fragments are 1303 /* Now 6lowpan packet_type is removed, so no new fragments are
1274 * expected on RX, therefore that's the time to clean incomplete 1304 * expected on RX, therefore that's the time to clean incomplete
1275 * fragments. 1305 * fragments.