]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/wireless/nl80211.c
genetlink: make netns aware
[net-next-2.6.git] / net / wireless / nl80211.c
index 0008144b354be5da0bf60577c860f998bf0ffc01..2a04beba436933c4a3a81552ccbc52bb0528b9ee 100644 (file)
@@ -29,9 +29,9 @@ static struct genl_family nl80211_fam = {
        .maxattr = NL80211_ATTR_MAX,
 };
 
-/* internal helper: get drv and dev */
-static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
-                                      struct cfg80211_registered_device **drv,
+/* internal helper: get rdev and dev */
+static int get_rdev_dev_by_info_ifindex(struct nlattr **attrs,
+                                      struct cfg80211_registered_device **rdev,
                                       struct net_device **dev)
 {
        int ifindex;
@@ -44,10 +44,10 @@ static int get_drv_dev_by_info_ifindex(struct nlattr **attrs,
        if (!*dev)
                return -ENODEV;
 
-       *drv = cfg80211_get_dev_from_ifindex(ifindex);
-       if (IS_ERR(*drv)) {
+       *rdev = cfg80211_get_dev_from_ifindex(ifindex);
+       if (IS_ERR(*rdev)) {
                dev_put(*dev);
-               return PTR_ERR(*drv);
+               return PTR_ERR(*rdev);
        }
 
        return 0;
@@ -71,6 +71,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
        [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
 
        [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
+       [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
 
        [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
                                    .len = WLAN_MAX_KEY_LEN },
@@ -377,7 +378,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
        struct cfg80211_registered_device *dev;
 
        mutex_lock(&cfg80211_mutex);
-       list_for_each_entry(dev, &cfg80211_drv_list, list) {
+       list_for_each_entry(dev, &cfg80211_rdev_list, list) {
                if (++idx <= start)
                        continue;
                if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid,
@@ -410,14 +411,14 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
        if (nl80211_send_wiphy(msg, info->snd_pid, info->snd_seq, 0, dev) < 0)
                goto out_free;
 
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
 
-       return genlmsg_unicast(msg, info->snd_pid);
+       return genlmsg_reply(msg, info);
 
  out_free:
        nlmsg_free(msg);
  out_err:
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
        return -ENOBUFS;
 }
 
@@ -459,7 +460,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
 
        mutex_lock(&cfg80211_mutex);
 
-       rdev = __cfg80211_drv_from_info(info);
+       rdev = __cfg80211_rdev_from_info(info);
        if (IS_ERR(rdev)) {
                mutex_unlock(&cfg80211_mutex);
                result = PTR_ERR(rdev);
@@ -682,7 +683,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
        struct wireless_dev *wdev;
 
        mutex_lock(&cfg80211_mutex);
-       list_for_each_entry(dev, &cfg80211_drv_list, list) {
+       list_for_each_entry(dev, &cfg80211_rdev_list, list) {
                if (wp_idx < wp_start) {
                        wp_idx++;
                        continue;
@@ -723,7 +724,7 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
        struct net_device *netdev;
        int err;
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &dev, &netdev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &dev, &netdev);
        if (err)
                return err;
 
@@ -736,15 +737,15 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
                goto out_free;
 
        dev_put(netdev);
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
 
-       return genlmsg_unicast(msg, info->snd_pid);
+       return genlmsg_reply(msg, info);
 
  out_free:
        nlmsg_free(msg);
  out_err:
        dev_put(netdev);
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
        return -ENOBUFS;
 }
 
@@ -779,7 +780,7 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
 
 static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct vif_params params;
        int err;
        enum nl80211_iftype otype, ntype;
@@ -791,7 +792,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
@@ -807,8 +808,8 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       if (!drv->ops->change_virtual_intf ||
-           !(drv->wiphy.interface_modes & (1 << ntype))) {
+       if (!rdev->ops->change_virtual_intf ||
+           !(rdev->wiphy.interface_modes & (1 << ntype))) {
                err = -EOPNOTSUPP;
                goto unlock;
        }
@@ -838,7 +839,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
        }
 
        if (change)
-               err = drv->ops->change_virtual_intf(&drv->wiphy, dev,
+               err = rdev->ops->change_virtual_intf(&rdev->wiphy, dev,
                                                    ntype, flags, &params);
        else
                err = 0;
@@ -852,7 +853,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 
  unlock:
        dev_put(dev);
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
  unlock_rtnl:
        rtnl_unlock();
        return err;
@@ -860,7 +861,7 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct vif_params params;
        int err;
        enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
@@ -879,14 +880,14 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       drv = cfg80211_get_dev_from_info(info);
-       if (IS_ERR(drv)) {
-               err = PTR_ERR(drv);
+       rdev = cfg80211_get_dev_from_info(info);
+       if (IS_ERR(rdev)) {
+               err = PTR_ERR(rdev);
                goto unlock_rtnl;
        }
 
-       if (!drv->ops->add_virtual_intf ||
-           !(drv->wiphy.interface_modes & (1 << type))) {
+       if (!rdev->ops->add_virtual_intf ||
+           !(rdev->wiphy.interface_modes & (1 << type))) {
                err = -EOPNOTSUPP;
                goto unlock;
        }
@@ -900,12 +901,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
        err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
                                  info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
                                  &flags);
-       err = drv->ops->add_virtual_intf(&drv->wiphy,
+       err = rdev->ops->add_virtual_intf(&rdev->wiphy,
                nla_data(info->attrs[NL80211_ATTR_IFNAME]),
                type, err ? NULL : &flags, &params);
 
  unlock:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
  unlock_rtnl:
        rtnl_unlock();
        return err;
@@ -913,27 +914,27 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int ifindex, err;
        struct net_device *dev;
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
        ifindex = dev->ifindex;
        dev_put(dev);
 
-       if (!drv->ops->del_virtual_intf) {
+       if (!rdev->ops->del_virtual_intf) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex);
+       err = rdev->ops->del_virtual_intf(&rdev->wiphy, ifindex);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
  unlock_rtnl:
        rtnl_unlock();
        return err;
@@ -967,7 +968,7 @@ static void get_key_callback(void *c, struct key_params *params)
 
 static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 key_idx = 0;
@@ -989,11 +990,11 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->get_key) {
+       if (!rdev->ops->get_key) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -1019,7 +1020,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        if (mac_addr)
                NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
 
-       err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr,
+       err = rdev->ops->get_key(&rdev->wiphy, dev, key_idx, mac_addr,
                                &cookie, get_key_callback);
 
        if (err)
@@ -1029,14 +1030,14 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  nla_put_failure:
        err = -ENOBUFS;
        nlmsg_free(msg);
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  unlock_rtnl:
        rtnl_unlock();
@@ -1046,7 +1047,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 key_idx;
@@ -1071,24 +1072,24 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
        if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
-               func = drv->ops->set_default_key;
+               func = rdev->ops->set_default_key;
        else
-               func = drv->ops->set_default_mgmt_key;
+               func = rdev->ops->set_default_mgmt_key;
 
        if (!func) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = func(&drv->wiphy, dev, key_idx);
+       err = func(&rdev->wiphy, dev, key_idx);
 #ifdef CONFIG_WIRELESS_EXT
        if (!err) {
-               if (func == drv->ops->set_default_key)
+               if (func == rdev->ops->set_default_key)
                        dev->ieee80211_ptr->wext.default_key = key_idx;
                else
                        dev->ieee80211_ptr->wext.default_mgmt_key = key_idx;
@@ -1096,7 +1097,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 #endif
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 
  unlock_rtnl:
@@ -1107,7 +1108,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err, i;
        struct net_device *dev;
        struct key_params params;
@@ -1142,27 +1143,27 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       for (i = 0; i < drv->wiphy.n_cipher_suites; i++)
-               if (params.cipher == drv->wiphy.cipher_suites[i])
+       for (i = 0; i < rdev->wiphy.n_cipher_suites; i++)
+               if (params.cipher == rdev->wiphy.cipher_suites[i])
                        break;
-       if (i == drv->wiphy.n_cipher_suites) {
+       if (i == rdev->wiphy.n_cipher_suites) {
                err = -EINVAL;
                goto out;
        }
 
-       if (!drv->ops->add_key) {
+       if (!rdev->ops->add_key) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, &params);
+       err = rdev->ops->add_key(&rdev->wiphy, dev, key_idx, mac_addr, &params);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  unlock_rtnl:
        rtnl_unlock();
@@ -1172,7 +1173,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 key_idx = 0;
@@ -1189,16 +1190,16 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->del_key) {
+       if (!rdev->ops->del_key) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr);
+       err = rdev->ops->del_key(&rdev->wiphy, dev, key_idx, mac_addr);
 
 #ifdef CONFIG_WIRELESS_EXT
        if (!err) {
@@ -1210,7 +1211,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
 #endif
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 
  unlock_rtnl:
@@ -1223,7 +1224,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 {
         int (*call)(struct wiphy *wiphy, struct net_device *dev,
                    struct beacon_parameters *info);
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct beacon_parameters params;
@@ -1234,7 +1235,7 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
@@ -1253,10 +1254,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
                        goto out;
                }
 
-               call = drv->ops->add_beacon;
+               call = rdev->ops->add_beacon;
                break;
        case NL80211_CMD_SET_BEACON:
-               call = drv->ops->set_beacon;
+               call = rdev->ops->set_beacon;
                break;
        default:
                WARN_ON(1);
@@ -1302,10 +1303,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = call(&drv->wiphy, dev, &params);
+       err = call(&rdev->wiphy, dev, &params);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  unlock_rtnl:
        rtnl_unlock();
@@ -1315,17 +1316,17 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->del_beacon) {
+       if (!rdev->ops->del_beacon) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -1334,10 +1335,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info)
                err = -EOPNOTSUPP;
                goto out;
        }
-       err = drv->ops->del_beacon(&drv->wiphy, dev);
+       err = rdev->ops->del_beacon(&rdev->wiphy, dev);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  unlock_rtnl:
        rtnl_unlock();
@@ -1571,7 +1572,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
        cb->args[1] = sta_idx;
        err = skb->len;
  out_err:
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
  out_rtnl:
        rtnl_unlock();
 
@@ -1580,7 +1581,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
 
 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct station_info sinfo;
@@ -1596,16 +1597,16 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->get_station) {
+       if (!rdev->ops->get_station) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo);
+       err = rdev->ops->get_station(&rdev->wiphy, dev, mac_addr, &sinfo);
        if (err)
                goto out;
 
@@ -1617,13 +1618,13 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
                                 dev, mac_addr, &sinfo) < 0)
                goto out_free;
 
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  out_free:
        nlmsg_free(msg);
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -1654,7 +1655,7 @@ static int get_vlan(struct nlattr *vlanattr,
 
 static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct station_parameters params;
@@ -1696,11 +1697,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
+       err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, &params.vlan);
        if (err)
                goto out;
 
@@ -1749,17 +1750,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto out;
 
-       if (!drv->ops->change_station) {
+       if (!rdev->ops->change_station) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, &params);
+       err = rdev->ops->change_station(&rdev->wiphy, dev, mac_addr, &params);
 
  out:
        if (params.vlan)
                dev_put(params.vlan);
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -1769,7 +1770,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct station_parameters params;
@@ -1809,11 +1810,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
+       err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], rdev, &params.vlan);
        if (err)
                goto out;
 
@@ -1849,7 +1850,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
        if (err)
                goto out;
 
-       if (!drv->ops->add_station) {
+       if (!rdev->ops->add_station) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -1859,12 +1860,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, &params);
+       err = rdev->ops->add_station(&rdev->wiphy, dev, mac_addr, &params);
 
  out:
        if (params.vlan)
                dev_put(params.vlan);
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -1874,7 +1875,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 *mac_addr = NULL;
@@ -1884,7 +1885,7 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
@@ -1895,15 +1896,15 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       if (!drv->ops->del_station) {
+       if (!rdev->ops->del_station) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->del_station(&drv->wiphy, dev, mac_addr);
+       err = rdev->ops->del_station(&rdev->wiphy, dev, mac_addr);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2034,7 +2035,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
        cb->args[1] = path_idx;
        err = skb->len;
  out_err:
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
  out_rtnl:
        rtnl_unlock();
 
@@ -2043,7 +2044,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
 
 static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct mpath_info pinfo;
@@ -2060,11 +2061,11 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->get_mpath) {
+       if (!rdev->ops->get_mpath) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2074,7 +2075,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo);
+       err = rdev->ops->get_mpath(&rdev->wiphy, dev, dst, next_hop, &pinfo);
        if (err)
                goto out;
 
@@ -2086,13 +2087,13 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
                                 dev, dst, next_hop, &pinfo) < 0)
                goto out_free;
 
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  out_free:
        nlmsg_free(msg);
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2102,7 +2103,7 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 *dst = NULL;
@@ -2119,11 +2120,11 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->change_mpath) {
+       if (!rdev->ops->change_mpath) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2138,10 +2139,10 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop);
+       err = rdev->ops->change_mpath(&rdev->wiphy, dev, dst, next_hop);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2150,7 +2151,7 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info)
 }
 static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 *dst = NULL;
@@ -2167,11 +2168,11 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->add_mpath) {
+       if (!rdev->ops->add_mpath) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2186,10 +2187,10 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop);
+       err = rdev->ops->add_mpath(&rdev->wiphy, dev, dst, next_hop);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2199,7 +2200,7 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        u8 *dst = NULL;
@@ -2209,19 +2210,19 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->del_mpath) {
+       if (!rdev->ops->del_mpath) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
-       err = drv->ops->del_mpath(&drv->wiphy, dev, dst);
+       err = rdev->ops->del_mpath(&rdev->wiphy, dev, dst);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2231,7 +2232,7 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info)
 
 static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        int err;
        struct net_device *dev;
        struct bss_parameters params;
@@ -2260,11 +2261,11 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->change_bss) {
+       if (!rdev->ops->change_bss) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2274,10 +2275,10 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = drv->ops->change_bss(&drv->wiphy, dev, &params);
+       err = rdev->ops->change_bss(&rdev->wiphy, dev, &params);
 
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2368,7 +2369,7 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
 static int nl80211_get_mesh_params(struct sk_buff *skb,
        struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct mesh_config cur_params;
        int err;
        struct net_device *dev;
@@ -2379,17 +2380,17 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
        rtnl_lock();
 
        /* Look up our device */
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->get_mesh_params) {
+       if (!rdev->ops->get_mesh_params) {
                err = -EOPNOTSUPP;
                goto out;
        }
 
        /* Get the mesh params */
-       err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params);
+       err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
        if (err)
                goto out;
 
@@ -2435,7 +2436,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
                        cur_params.dot11MeshHWMPnetDiameterTraversalTime);
        nla_nest_end(msg, pinfoattr);
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
  nla_put_failure:
@@ -2443,7 +2444,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
        err = -EMSGSIZE;
  out:
        /* Cleanup */
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2481,7 +2482,7 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
 {
        int err;
        u32 mask;
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        struct mesh_config cfg;
        struct nlattr *tb[NL80211_MESHCONF_ATTR_MAX + 1];
@@ -2496,11 +2497,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       if (!drv->ops->set_mesh_params) {
+       if (!rdev->ops->set_mesh_params) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2545,11 +2546,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
                        nla_get_u16);
 
        /* Apply changes */
-       err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask);
+       err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
 
  out:
        /* cleanup */
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -2623,7 +2624,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
        nla_nest_end(msg, nl_reg_rules);
 
        genlmsg_end(msg, hdr);
-       err = genlmsg_unicast(msg, info->snd_pid);
+       err = genlmsg_reply(msg, info);
        goto out;
 
 nla_put_failure:
@@ -2736,7 +2737,7 @@ static int validate_scan_freqs(struct nlattr *freqs)
 
 static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        struct cfg80211_scan_request *request;
        struct cfg80211_ssid *ssid;
@@ -2752,13 +2753,13 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto out_rtnl;
 
-       wiphy = &drv->wiphy;
+       wiphy = &rdev->wiphy;
 
-       if (!drv->ops->scan) {
+       if (!rdev->ops->scan) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -2768,7 +2769,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       if (drv->scan_req) {
+       if (rdev->scan_req) {
                err = -EBUSY;
                goto out;
        }
@@ -2875,21 +2876,21 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        }
 
        request->ifidx = dev->ifindex;
-       request->wiphy = &drv->wiphy;
+       request->wiphy = &rdev->wiphy;
 
-       drv->scan_req = request;
-       err = drv->ops->scan(&drv->wiphy, dev, request);
+       rdev->scan_req = request;
+       err = rdev->ops->scan(&rdev->wiphy, dev, request);
 
        if (!err)
-               nl80211_send_scan_start(drv, dev);
+               nl80211_send_scan_start(rdev, dev);
 
  out_free:
        if (err) {
-               drv->scan_req = NULL;
+               rdev->scan_req = NULL;
                kfree(request);
        }
  out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
  out_rtnl:
        rtnl_unlock();
@@ -3006,7 +3007,7 @@ static int nl80211_dump_scan(struct sk_buff *skb,
 
        cb->args[1] = idx;
        err = skb->len;
-       cfg80211_put_dev(dev);
+       cfg80211_unlock_rdev(dev);
  out_put_netdev:
        dev_put(netdev);
 
@@ -3042,11 +3043,12 @@ static bool nl80211_valid_cipher_suite(u32 cipher)
 
 static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
-       struct cfg80211_auth_request req;
-       struct wiphy *wiphy;
-       int err;
+       struct ieee80211_channel *chan;
+       const u8 *bssid, *ssid, *ie = NULL;
+       int err, ssid_len, ie_len = 0;
+       enum nl80211_auth_type auth_type;
 
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
@@ -3057,13 +3059,19 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
        if (!info->attrs[NL80211_ATTR_AUTH_TYPE])
                return -EINVAL;
 
+       if (!info->attrs[NL80211_ATTR_SSID])
+               return -EINVAL;
+
+       if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+               return -EINVAL;
+
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->auth) {
+       if (!rdev->ops->auth) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3078,41 +3086,33 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
-       memset(&req, 0, sizeof(req));
-
-       req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
-       if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
-               req.chan = ieee80211_get_channel(
-                       wiphy,
-                       nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-               if (!req.chan) {
-                       err = -EINVAL;
-                       goto out;
-               }
+       bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
+       chan = ieee80211_get_channel(&rdev->wiphy,
+               nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+       if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
+               err = -EINVAL;
+               goto out;
        }
 
-       if (info->attrs[NL80211_ATTR_SSID]) {
-               req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
-               req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
-       }
+       ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+       ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
 
        if (info->attrs[NL80211_ATTR_IE]) {
-               req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
-               req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+               ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
 
-       req.auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
-       if (!nl80211_valid_auth_type(req.auth_type)) {
+       auth_type = nla_get_u32(info->attrs[NL80211_ATTR_AUTH_TYPE]);
+       if (!nl80211_valid_auth_type(auth_type)) {
                err = -EINVAL;
                goto out;
        }
 
-       err = drv->ops->auth(&drv->wiphy, dev, &req);
+       err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
+                                ssid, ssid_len, ie, ie_len);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3120,7 +3120,8 @@ unlock_rtnl:
 }
 
 static int nl80211_crypto_settings(struct genl_info *info,
-                                  struct cfg80211_crypto_settings *settings)
+                                  struct cfg80211_crypto_settings *settings,
+                                  int cipher_limit)
 {
        settings->control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
 
@@ -3135,7 +3136,7 @@ static int nl80211_crypto_settings(struct genl_info *info,
                if (len % sizeof(u32))
                        return -EINVAL;
 
-               if (settings->n_ciphers_pairwise > NL80211_MAX_NR_CIPHER_SUITES)
+               if (settings->n_ciphers_pairwise > cipher_limit)
                        return -EINVAL;
 
                memcpy(settings->ciphers_pairwise, data, len);
@@ -3183,26 +3184,29 @@ static int nl80211_crypto_settings(struct genl_info *info,
 
 static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
-       struct cfg80211_assoc_request req;
-       struct wiphy *wiphy;
-       int err;
+       struct cfg80211_crypto_settings crypto;
+       struct ieee80211_channel *chan;
+       const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
+       int err, ssid_len, ie_len = 0;
+       bool use_mfp = false;
 
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
 
        if (!info->attrs[NL80211_ATTR_MAC] ||
-           !info->attrs[NL80211_ATTR_SSID])
+           !info->attrs[NL80211_ATTR_SSID] ||
+           !info->attrs[NL80211_ATTR_WIPHY_FREQ])
                return -EINVAL;
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->assoc) {
+       if (!rdev->ops->assoc) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3217,46 +3221,45 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
-       memset(&req, 0, sizeof(req));
+       bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
-       if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
-               req.chan = ieee80211_get_channel(
-                       wiphy,
-                       nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
-               if (!req.chan) {
-                       err = -EINVAL;
-                       goto out;
-               }
+       chan = ieee80211_get_channel(&rdev->wiphy,
+               nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
+       if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) {
+               err = -EINVAL;
+               goto out;
        }
 
-       req.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
-       req.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+       ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
+       ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
 
        if (info->attrs[NL80211_ATTR_IE]) {
-               req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
-               req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+               ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
 
        if (info->attrs[NL80211_ATTR_USE_MFP]) {
-               enum nl80211_mfp use_mfp =
+               enum nl80211_mfp mfp =
                        nla_get_u32(info->attrs[NL80211_ATTR_USE_MFP]);
-               if (use_mfp == NL80211_MFP_REQUIRED)
-                       req.use_mfp = true;
-               else if (use_mfp != NL80211_MFP_NO) {
+               if (mfp == NL80211_MFP_REQUIRED)
+                       use_mfp = true;
+               else if (mfp != NL80211_MFP_NO) {
                        err = -EINVAL;
                        goto out;
                }
        }
 
-       err = nl80211_crypto_settings(info, &req.crypto);
+       if (info->attrs[NL80211_ATTR_PREV_BSSID])
+               prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
+
+       err = nl80211_crypto_settings(info, &crypto, 1);
        if (!err)
-               err = drv->ops->assoc(&drv->wiphy, dev, &req);
+               err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
+                                         ssid, ssid_len, ie, ie_len, use_mfp,
+                                         &crypto);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3265,11 +3268,11 @@ unlock_rtnl:
 
 static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
-       struct cfg80211_deauth_request req;
-       struct wiphy *wiphy;
-       int err;
+       const u8 *ie = NULL, *bssid;
+       int err, ie_len = 0;
+       u16 reason_code;
 
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
@@ -3282,11 +3285,11 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->deauth) {
+       if (!rdev->ops->deauth) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3301,27 +3304,24 @@ static int nl80211_deauthenticate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
-       memset(&req, 0, sizeof(req));
-
-       req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+       bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
-       if (req.reason_code == 0) {
+       reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+       if (reason_code == 0) {
                /* Reason Code 0 is reserved */
                err = -EINVAL;
                goto out;
        }
 
        if (info->attrs[NL80211_ATTR_IE]) {
-               req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
-               req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+               ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
 
-       err = drv->ops->deauth(&drv->wiphy, dev, &req);
+       err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3330,11 +3330,11 @@ unlock_rtnl:
 
 static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
-       struct cfg80211_disassoc_request req;
-       struct wiphy *wiphy;
-       int err;
+       const u8 *ie = NULL, *bssid;
+       int err, ie_len = 0;
+       u16 reason_code;
 
        if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
                return -EINVAL;
@@ -3347,11 +3347,11 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->disassoc) {
+       if (!rdev->ops->disassoc) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3366,27 +3366,24 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
-       memset(&req, 0, sizeof(req));
-
-       req.peer_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
+       bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
 
-       req.reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
-       if (req.reason_code == 0) {
+       reason_code = nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
+       if (reason_code == 0) {
                /* Reason Code 0 is reserved */
                err = -EINVAL;
                goto out;
        }
 
        if (info->attrs[NL80211_ATTR_IE]) {
-               req.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
-               req.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+               ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+               ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        }
 
-       err = drv->ops->disassoc(&drv->wiphy, dev, &req);
+       err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3395,7 +3392,7 @@ unlock_rtnl:
 
 static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        struct cfg80211_ibss_params ibss;
        struct wiphy *wiphy;
@@ -3422,11 +3419,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->join_ibss) {
+       if (!rdev->ops->join_ibss) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3441,7 +3438,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
+       wiphy = &rdev->wiphy;
 
        if (info->attrs[NL80211_ATTR_MAC])
                ibss.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
@@ -3464,10 +3461,10 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
 
        ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
 
-       err = cfg80211_join_ibss(drv, dev, &ibss);
+       err = cfg80211_join_ibss(rdev, dev, &ibss);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3476,17 +3473,17 @@ unlock_rtnl:
 
 static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        int err;
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
-       if (!drv->ops->leave_ibss) {
+       if (!rdev->ops->leave_ibss) {
                err = -EOPNOTSUPP;
                goto out;
        }
@@ -3501,10 +3498,10 @@ static int nl80211_leave_ibss(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = cfg80211_leave_ibss(drv, dev, false);
+       err = cfg80211_leave_ibss(rdev, dev, false);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3541,7 +3538,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
                rdev->testmode_info = NULL;
        }
 
-       cfg80211_put_dev(rdev);
+       cfg80211_unlock_rdev(rdev);
 
  unlock_rtnl:
        rtnl_unlock();
@@ -3635,7 +3632,7 @@ EXPORT_SYMBOL(cfg80211_testmode_event);
 
 static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        struct cfg80211_connect_params connect;
        struct wiphy *wiphy;
@@ -3660,12 +3657,13 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
 
        connect.privacy = info->attrs[NL80211_ATTR_PRIVACY];
 
-       err = nl80211_crypto_settings(info, &connect.crypto);
+       err = nl80211_crypto_settings(info, &connect.crypto,
+                                     NL80211_MAX_NR_CIPHER_SUITES);
        if (err)
                return err;
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
@@ -3679,7 +3677,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       wiphy = &drv->wiphy;
+       wiphy = &rdev->wiphy;
 
        connect.bssid = NULL;
        connect.channel = NULL;
@@ -3706,10 +3704,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
-       err = cfg80211_connect(drv, dev, &connect);
+       err = cfg80211_connect(rdev, dev, &connect);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -3718,7 +3716,7 @@ unlock_rtnl:
 
 static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
 {
-       struct cfg80211_registered_device *drv;
+       struct cfg80211_registered_device *rdev;
        struct net_device *dev;
        int err;
        u16 reason;
@@ -3733,7 +3731,7 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
 
        rtnl_lock();
 
-       err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
+       err = get_rdev_dev_by_info_ifindex(info->attrs, &rdev, &dev);
        if (err)
                goto unlock_rtnl;
 
@@ -3747,10 +3745,10 @@ static int nl80211_disconnect(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       err = cfg80211_disconnect(drv, dev, reason, true);
+       err = cfg80211_disconnect(rdev, dev, reason, true);
 
 out:
-       cfg80211_put_dev(drv);
+       cfg80211_unlock_rdev(rdev);
        dev_put(dev);
 unlock_rtnl:
        rtnl_unlock();
@@ -4031,6 +4029,8 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
        struct nlattr *nest;
        int i;
 
+       ASSERT_RDEV_LOCK(rdev);
+
        if (WARN_ON(!req))
                return 0;
 
@@ -4393,12 +4393,12 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
 
 void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                               struct net_device *netdev, u16 reason,
-                              u8 *ie, size_t ie_len, bool from_ap, gfp_t gfp)
+                              const u8 *ie, size_t ie_len, bool from_ap)
 {
        struct sk_buff *msg;
        void *hdr;
 
-       msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+       msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!msg)
                return;
 
@@ -4422,7 +4422,7 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                return;
        }
 
-       genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
+       genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL);
        return;
 
  nla_put_failure: