aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee802154/6lowpan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee802154/6lowpan.c')
-rw-r--r--net/ieee802154/6lowpan.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c
index 6a095225148e..6d42c17af96b 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[])
@@ -1133,6 +1127,8 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[])
1133static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, 1127static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
1134 struct packet_type *pt, struct net_device *orig_dev) 1128 struct packet_type *pt, struct net_device *orig_dev)
1135{ 1129{
1130 struct sk_buff *local_skb;
1131
1136 if (!netif_running(dev)) 1132 if (!netif_running(dev))
1137 goto drop; 1133 goto drop;
1138 1134
@@ -1144,7 +1140,12 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev,
1144 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ 1140 case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
1145 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ 1141 case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
1146 case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ 1142 case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
1147 lowpan_process_data(skb); 1143 local_skb = skb_clone(skb, GFP_ATOMIC);
1144 if (!local_skb)
1145 goto drop;
1146 lowpan_process_data(local_skb);
1147
1148 kfree_skb(skb);
1148 break; 1149 break;
1149 default: 1150 default:
1150 break; 1151 break;
@@ -1237,6 +1238,34 @@ static inline void __init lowpan_netlink_fini(void)
1237 rtnl_link_unregister(&lowpan_link_ops); 1238 rtnl_link_unregister(&lowpan_link_ops);
1238} 1239}
1239 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
1240static struct packet_type lowpan_packet_type = { 1269static struct packet_type lowpan_packet_type = {
1241 .type = __constant_htons(ETH_P_IEEE802154), 1270 .type = __constant_htons(ETH_P_IEEE802154),
1242 .func = lowpan_rcv, 1271 .func = lowpan_rcv,
@@ -1251,6 +1280,12 @@ static int __init lowpan_init_module(void)
1251 goto out; 1280 goto out;
1252 1281
1253 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 }
1254out: 1289out:
1255 return err; 1290 return err;
1256} 1291}
@@ -1263,6 +1298,8 @@ static void __exit lowpan_cleanup_module(void)
1263 1298
1264 dev_remove_pack(&lowpan_packet_type); 1299 dev_remove_pack(&lowpan_packet_type);
1265 1300
1301 unregister_netdevice_notifier(&lowpan_dev_notifier);
1302
1266 /* Now 6lowpan packet_type is removed, so no new fragments are 1303 /* Now 6lowpan packet_type is removed, so no new fragments are
1267 * expected on RX, therefore that's the time to clean incomplete 1304 * expected on RX, therefore that's the time to clean incomplete
1268 * fragments. 1305 * fragments.