mac802154: add ifname change notifier
[deliverable/linux.git] / net / mac802154 / iface.c
index c0b96cf525d6695b18464eb960bb382a15ce3904..ec92b48d1b0bfa40a7fafc148ff6f1d0bd9d3a1f 100644 (file)
@@ -63,6 +63,8 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
        int err = -ENOIOCTLCMD;
 
+       ASSERT_RTNL();
+
        spin_lock_bh(&sdata->mib_lock);
 
        switch (cmd) {
@@ -87,6 +89,11 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
        }
        case SIOCSIFADDR:
+               if (netif_running(dev)) {
+                       spin_unlock_bh(&sdata->mib_lock);
+                       return -EBUSY;
+               }
+
                dev_warn(&dev->dev,
                         "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
                if (sa->family != AF_IEEE802154 ||
@@ -404,6 +411,7 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type)
 
        /* set some type-dependent values */
        sdata->vif.type = type;
+       sdata->wpan_dev.iftype = type;
 
        get_random_bytes(&wpan_dev->bsn, 1);
        get_random_bytes(&wpan_dev->dsn, 1);
@@ -415,12 +423,14 @@ ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata, int type)
        /* for compatibility, actual default is 3 */
        wpan_dev->frame_retries = -1;
 
-       ieee802154_be64_to_le64(&wpan_dev->extended_addr, sdata->dev->dev_addr);
        wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
        wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
 
        switch (type) {
        case IEEE802154_DEV_WPAN:
+               ieee802154_be64_to_le64(&wpan_dev->extended_addr,
+                                       sdata->dev->dev_addr);
+
                sdata->dev->header_ops = &mac802154_header_ops;
                sdata->dev->destructor = mac802154_wpan_free;
                sdata->dev->netdev_ops = &mac802154_wpan_ops;
@@ -525,3 +535,51 @@ void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
        synchronize_rcu();
        unregister_netdevice(sdata->dev);
 }
+
+void ieee802154_remove_interfaces(struct ieee802154_local *local)
+{
+       struct ieee802154_sub_if_data *sdata, *tmp;
+
+       mutex_lock(&local->iflist_mtx);
+       list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+               list_del(&sdata->list);
+
+               unregister_netdevice(sdata->dev);
+       }
+       mutex_unlock(&local->iflist_mtx);
+}
+
+static int netdev_notify(struct notifier_block *nb,
+                        unsigned long state, void *ptr)
+{
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct ieee802154_sub_if_data *sdata;
+
+       if (state != NETDEV_CHANGENAME)
+               return NOTIFY_DONE;
+
+       if (!dev->ieee802154_ptr || !dev->ieee802154_ptr->wpan_phy)
+               return NOTIFY_DONE;
+
+       if (dev->ieee802154_ptr->wpan_phy->privid != mac802154_wpan_phy_privid)
+               return NOTIFY_DONE;
+
+       sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+       memcpy(sdata->name, dev->name, IFNAMSIZ);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block mac802154_netdev_notifier = {
+       .notifier_call = netdev_notify,
+};
+
+int ieee802154_iface_init(void)
+{
+       return register_netdevice_notifier(&mac802154_netdev_notifier);
+}
+
+void ieee802154_iface_exit(void)
+{
+       unregister_netdevice_notifier(&mac802154_netdev_notifier);
+}
This page took 0.044724 seconds and 5 git commands to generate.