Merge branch 'acpi-pmic'
[cascardo/linux.git] / net / wireless / nl80211.c
index 056a730..7d72283 100644 (file)
@@ -103,7 +103,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
                if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
                        continue;
 
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        if (have_ifidx && wdev->netdev &&
                            wdev->netdev->ifindex == ifidx) {
                                result = wdev;
@@ -149,7 +149,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
                tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
                if (tmp) {
                        /* make sure wdev exists */
-                       list_for_each_entry(wdev, &tmp->wdev_list, list) {
+                       list_for_each_entry(wdev, &tmp->wiphy.wdev_list, list) {
                                if (wdev->identifier != (u32)wdev_id)
                                        continue;
                                found = true;
@@ -402,6 +402,8 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        [NL80211_ATTR_SCHED_SCAN_DELAY] = { .type = NLA_U32 },
        [NL80211_ATTR_REG_INDOOR] = { .type = NLA_FLAG },
        [NL80211_ATTR_PBSS] = { .type = NLA_FLAG },
+       [NL80211_ATTR_BSS_SELECT] = { .type = NLA_NESTED },
+       [NL80211_ATTR_STA_SUPPORT_P2P_PS] = { .type = NLA_U8 },
 };
 
 /* policy for the key attributes */
@@ -486,6 +488,15 @@ nl80211_plan_policy[NL80211_SCHED_SCAN_PLAN_MAX + 1] = {
        [NL80211_SCHED_SCAN_PLAN_ITERATIONS] = { .type = NLA_U32 },
 };
 
+static const struct nla_policy
+nl80211_bss_select_policy[NL80211_BSS_SELECT_ATTR_MAX + 1] = {
+       [NL80211_BSS_SELECT_ATTR_RSSI] = { .type = NLA_FLAG },
+       [NL80211_BSS_SELECT_ATTR_BAND_PREF] = { .type = NLA_U32 },
+       [NL80211_BSS_SELECT_ATTR_RSSI_ADJUST] = {
+               .len = sizeof(struct nl80211_bss_select_rssi_adjust)
+       },
+};
+
 static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                                     struct netlink_callback *cb,
                                     struct cfg80211_registered_device **rdev,
@@ -524,7 +535,7 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
                *rdev = wiphy_to_rdev(wiphy);
                *wdev = NULL;
 
-               list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+               list_for_each_entry(tmp, &(*rdev)->wiphy.wdev_list, list) {
                        if (tmp->identifier == cb->args[1]) {
                                *wdev = tmp;
                                break;
@@ -1266,7 +1277,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
        struct nlattr *nl_bands, *nl_band;
        struct nlattr *nl_freqs, *nl_freq;
        struct nlattr *nl_cmds;
-       enum ieee80211_band band;
+       enum nl80211_band band;
        struct ieee80211_channel *chan;
        int i;
        const struct ieee80211_txrx_stypes *mgmt_stypes =
@@ -1399,7 +1410,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                        goto nla_put_failure;
 
                for (band = state->band_start;
-                    band < IEEE80211_NUM_BANDS; band++) {
+                    band < NUM_NL80211_BANDS; band++) {
                        struct ieee80211_supported_band *sband;
 
                        sband = rdev->wiphy.bands[band];
@@ -1461,7 +1472,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                }
                nla_nest_end(msg, nl_bands);
 
-               if (band < IEEE80211_NUM_BANDS)
+               if (band < NUM_NL80211_BANDS)
                        state->band_start = band + 1;
                else
                        state->band_start = 0;
@@ -1731,6 +1742,25 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
                            rdev->wiphy.ext_features))
                        goto nla_put_failure;
 
+               if (rdev->wiphy.bss_select_support) {
+                       struct nlattr *nested;
+                       u32 bss_select_support = rdev->wiphy.bss_select_support;
+
+                       nested = nla_nest_start(msg, NL80211_ATTR_BSS_SELECT);
+                       if (!nested)
+                               goto nla_put_failure;
+
+                       i = 0;
+                       while (bss_select_support) {
+                               if ((bss_select_support & 1) &&
+                                   nla_put_flag(msg, i))
+                                       goto nla_put_failure;
+                               i++;
+                               bss_select_support >>= 1;
+                       }
+                       nla_nest_end(msg, nested);
+               }
+
                /* done */
                state->split_start = 0;
                break;
@@ -2399,7 +2429,8 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD) ||
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) ||
            nla_put_u32(msg, NL80211_ATTR_GENERATION,
                        rdev->devlist_generation ^
@@ -2459,7 +2490,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
                }
                if_idx = 0;
 
-               list_for_each_entry(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                        if (if_idx < if_start) {
                                if_idx++;
                                continue;
@@ -2731,7 +2762,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
                spin_lock_init(&wdev->mgmt_registrations_lock);
 
                wdev->identifier = ++rdev->wdev_id;
-               list_add_rcu(&wdev->list, &rdev->wdev_list);
+               list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list);
                rdev->devlist_generation++;
                break;
        default:
@@ -3267,7 +3298,7 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
        struct wireless_dev *wdev;
        bool ret = false;
 
-       list_for_each_entry(wdev, &rdev->wdev_list, list) {
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
                if (wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO)
                        continue;
@@ -3456,16 +3487,16 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
                params.smps_mode = NL80211_SMPS_OFF;
        }
 
+       params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
+       if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
+               return -EOPNOTSUPP;
+
        if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
                params.acl = parse_acl_data(&rdev->wiphy, info);
                if (IS_ERR(params.acl))
                        return PTR_ERR(params.acl);
        }
 
-       params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
-       if (params.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ])
-               return -EOPNOTSUPP;
-
        wdev_lock(wdev);
        err = rdev_start_ap(rdev, dev, &params);
        if (!err) {
@@ -3724,11 +3755,18 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
                goto nla_put_failure;
 
 #define PUT_SINFO(attr, memb, type) do {                               \
-       if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) &&           \
+       BUILD_BUG_ON(sizeof(type) == sizeof(u64));                      \
+       if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) &&      \
            nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr,            \
                             sinfo->memb))                              \
                goto nla_put_failure;                                   \
        } while (0)
+#define PUT_SINFO_U64(attr, memb) do {                                 \
+       if (sinfo->filled & (1ULL << NL80211_STA_INFO_ ## attr) &&      \
+           nla_put_u64_64bit(msg, NL80211_STA_INFO_ ## attr,           \
+                             sinfo->memb, NL80211_STA_INFO_PAD))       \
+               goto nla_put_failure;                                   \
+       } while (0)
 
        PUT_SINFO(CONNECTED_TIME, connected_time, u32);
        PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
@@ -3745,11 +3783,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
                        (u32)sinfo->tx_bytes))
                goto nla_put_failure;
 
-       PUT_SINFO(RX_BYTES64, rx_bytes, u64);
-       PUT_SINFO(TX_BYTES64, tx_bytes, u64);
+       PUT_SINFO_U64(RX_BYTES64, rx_bytes);
+       PUT_SINFO_U64(TX_BYTES64, tx_bytes);
        PUT_SINFO(LLID, llid, u16);
        PUT_SINFO(PLID, plid, u16);
        PUT_SINFO(PLINK_STATE, plink_state, u8);
+       PUT_SINFO_U64(RX_DURATION, rx_duration);
 
        switch (rdev->wiphy.signal_type) {
        case CFG80211_SIGNAL_TYPE_MBM:
@@ -3817,12 +3856,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
                    &sinfo->sta_flags))
                goto nla_put_failure;
 
-       PUT_SINFO(T_OFFSET, t_offset, u64);
-       PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64);
-       PUT_SINFO(BEACON_RX, rx_beacon, u64);
+       PUT_SINFO_U64(T_OFFSET, t_offset);
+       PUT_SINFO_U64(RX_DROP_MISC, rx_dropped_misc);
+       PUT_SINFO_U64(BEACON_RX, rx_beacon);
        PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
 
 #undef PUT_SINFO
+#undef PUT_SINFO_U64
 
        if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
                struct nlattr *tidsattr;
@@ -3845,19 +3885,19 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
                        if (!tidattr)
                                goto nla_put_failure;
 
-#define PUT_TIDVAL(attr, memb, type) do {                              \
+#define PUT_TIDVAL_U64(attr, memb) do {                                        \
        if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) &&       \
-           nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr,           \
-                            tidstats->memb))                           \
+           nla_put_u64_64bit(msg, NL80211_TID_STATS_ ## attr,          \
+                             tidstats->memb, NL80211_TID_STATS_PAD))   \
                goto nla_put_failure;                                   \
        } while (0)
 
-                       PUT_TIDVAL(RX_MSDU, rx_msdu, u64);
-                       PUT_TIDVAL(TX_MSDU, tx_msdu, u64);
-                       PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64);
-                       PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64);
+                       PUT_TIDVAL_U64(RX_MSDU, rx_msdu);
+                       PUT_TIDVAL_U64(TX_MSDU, tx_msdu);
+                       PUT_TIDVAL_U64(TX_MSDU_RETRIES, tx_msdu_retries);
+                       PUT_TIDVAL_U64(TX_MSDU_FAILED, tx_msdu_failed);
 
-#undef PUT_TIDVAL
+#undef PUT_TIDVAL_U64
                        nla_nest_end(msg, tidattr);
                }
 
@@ -3977,6 +4017,10 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
            statype != CFG80211_STA_AP_CLIENT_UNASSOC)
                return -EINVAL;
 
+       if (params->support_p2p_ps != -1 &&
+           statype != CFG80211_STA_AP_CLIENT_UNASSOC)
+               return -EINVAL;
+
        if (params->aid &&
            !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
            statype != CFG80211_STA_AP_CLIENT_UNASSOC)
@@ -4270,6 +4314,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
        else
                params.listen_interval = -1;
 
+       if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
+               u8 tmp;
+
+               tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
+               if (tmp >= NUM_NL80211_P2P_PS_STATUS)
+                       return -EINVAL;
+
+               params.support_p2p_ps = tmp;
+       } else {
+               params.support_p2p_ps = -1;
+       }
+
        if (!info->attrs[NL80211_ATTR_MAC])
                return -EINVAL;
 
@@ -4393,6 +4449,23 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
        params.listen_interval =
                nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
 
+       if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
+               u8 tmp;
+
+               tmp = nla_get_u8(info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]);
+               if (tmp >= NUM_NL80211_P2P_PS_STATUS)
+                       return -EINVAL;
+
+               params.support_p2p_ps = tmp;
+       } else {
+               /*
+                * if not specified, assume it's supported for P2P GO interface,
+                * and is NOT supported for AP interface
+                */
+               params.support_p2p_ps =
+                       dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO;
+       }
+
        if (info->attrs[NL80211_ATTR_PEER_AID])
                params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);
        else
@@ -5758,6 +5831,73 @@ static int validate_scan_freqs(struct nlattr *freqs)
        return n_channels;
 }
 
+static bool is_band_valid(struct wiphy *wiphy, enum nl80211_band b)
+{
+       return b < NUM_NL80211_BANDS && wiphy->bands[b];
+}
+
+static int parse_bss_select(struct nlattr *nla, struct wiphy *wiphy,
+                           struct cfg80211_bss_selection *bss_select)
+{
+       struct nlattr *attr[NL80211_BSS_SELECT_ATTR_MAX + 1];
+       struct nlattr *nest;
+       int err;
+       bool found = false;
+       int i;
+
+       /* only process one nested attribute */
+       nest = nla_data(nla);
+       if (!nla_ok(nest, nla_len(nest)))
+               return -EINVAL;
+
+       err = nla_parse(attr, NL80211_BSS_SELECT_ATTR_MAX, nla_data(nest),
+                       nla_len(nest), nl80211_bss_select_policy);
+       if (err)
+               return err;
+
+       /* only one attribute may be given */
+       for (i = 0; i <= NL80211_BSS_SELECT_ATTR_MAX; i++) {
+               if (attr[i]) {
+                       if (found)
+                               return -EINVAL;
+                       found = true;
+               }
+       }
+
+       bss_select->behaviour = __NL80211_BSS_SELECT_ATTR_INVALID;
+
+       if (attr[NL80211_BSS_SELECT_ATTR_RSSI])
+               bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI;
+
+       if (attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]) {
+               bss_select->behaviour = NL80211_BSS_SELECT_ATTR_BAND_PREF;
+               bss_select->param.band_pref =
+                       nla_get_u32(attr[NL80211_BSS_SELECT_ATTR_BAND_PREF]);
+               if (!is_band_valid(wiphy, bss_select->param.band_pref))
+                       return -EINVAL;
+       }
+
+       if (attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]) {
+               struct nl80211_bss_select_rssi_adjust *adj_param;
+
+               adj_param = nla_data(attr[NL80211_BSS_SELECT_ATTR_RSSI_ADJUST]);
+               bss_select->behaviour = NL80211_BSS_SELECT_ATTR_RSSI_ADJUST;
+               bss_select->param.adjust.band = adj_param->band;
+               bss_select->param.adjust.delta = adj_param->delta;
+               if (!is_band_valid(wiphy, bss_select->param.adjust.band))
+                       return -EINVAL;
+       }
+
+       /* user-space did not provide behaviour attribute */
+       if (bss_select->behaviour == __NL80211_BSS_SELECT_ATTR_INVALID)
+               return -EINVAL;
+
+       if (!(wiphy->bss_select_support & BIT(bss_select->behaviour)))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int nl80211_parse_random_mac(struct nlattr **attrs,
                                    u8 *mac_addr, u8 *mac_addr_mask)
 {
@@ -5888,10 +6028,10 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                        i++;
                }
        } else {
-               enum ieee80211_band band;
+               enum nl80211_band band;
 
                /* all channels */
-               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               for (band = 0; band < NUM_NL80211_BANDS; band++) {
                        int j;
                        if (!wiphy->bands[band])
                                continue;
@@ -5936,7 +6076,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                       request->ie_len);
        }
 
-       for (i = 0; i < IEEE80211_NUM_BANDS; i++)
+       for (i = 0; i < NUM_NL80211_BANDS; i++)
                if (wiphy->bands[i])
                        request->rates[i] =
                                (1 << wiphy->bands[i]->n_bitrates) - 1;
@@ -5945,9 +6085,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                nla_for_each_nested(attr,
                                    info->attrs[NL80211_ATTR_SCAN_SUPP_RATES],
                                    tmp) {
-                       enum ieee80211_band band = nla_type(attr);
+                       enum nl80211_band band = nla_type(attr);
 
-                       if (band < 0 || band >= IEEE80211_NUM_BANDS) {
+                       if (band < 0 || band >= NUM_NL80211_BANDS) {
                                err = -EINVAL;
                                goto out_free;
                        }
@@ -5996,6 +6136,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        request->no_cck =
                nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
 
+       if (info->attrs[NL80211_ATTR_MAC])
+               memcpy(request->bssid, nla_data(info->attrs[NL80211_ATTR_MAC]),
+                      ETH_ALEN);
+       else
+               eth_broadcast_addr(request->bssid);
+
        request->wdev = wdev;
        request->wiphy = &rdev->wiphy;
        request->scan_start = jiffies;
@@ -6129,7 +6275,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
        struct cfg80211_sched_scan_request *request;
        struct nlattr *attr;
        int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i, n_plans = 0;
-       enum ieee80211_band band;
+       enum nl80211_band band;
        size_t ie_len;
        struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
        s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
@@ -6294,7 +6440,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
                }
        } else {
                /* all channels */
-               for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+               for (band = 0; band < NUM_NL80211_BANDS; band++) {
                        int j;
                        if (!wiphy->bands[band])
                                continue;
@@ -6738,7 +6884,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
        if (wdev->netdev &&
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex))
                goto nla_put_failure;
-       if (nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+       if (nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        bss = nla_nest_start(msg, NL80211_ATTR_BSS);
@@ -6759,7 +6906,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
         */
        ies = rcu_dereference(res->ies);
        if (ies) {
-               if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
+               if (nla_put_u64_64bit(msg, NL80211_BSS_TSF, ies->tsf,
+                                     NL80211_BSS_PAD))
                        goto fail_unlock_rcu;
                if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
                                        ies->len, ies->data))
@@ -6769,7 +6917,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
        /* and this pointer is always (unless driver didn't know) beacon data */
        ies = rcu_dereference(res->beacon_ies);
        if (ies && ies->from_beacon) {
-               if (nla_put_u64(msg, NL80211_BSS_BEACON_TSF, ies->tsf))
+               if (nla_put_u64_64bit(msg, NL80211_BSS_BEACON_TSF, ies->tsf,
+                                     NL80211_BSS_PAD))
                        goto fail_unlock_rcu;
                if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
                                        ies->len, ies->data))
@@ -6788,8 +6937,8 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
                goto nla_put_failure;
 
        if (intbss->ts_boottime &&
-           nla_put_u64(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
-                       intbss->ts_boottime))
+           nla_put_u64_64bit(msg, NL80211_BSS_LAST_SEEN_BOOTTIME,
+                             intbss->ts_boottime, NL80211_BSS_PAD))
                goto nla_put_failure;
 
        switch (rdev->wiphy.signal_type) {
@@ -6909,28 +7058,28 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
            nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME,
-                       survey->time))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME,
+                       survey->time, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY,
-                       survey->time_busy))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_BUSY,
+                             survey->time_busy, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
-                       survey->time_ext_busy))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
+                             survey->time_ext_busy, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME_RX) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX,
-                       survey->time_rx))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_RX,
+                             survey->time_rx, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME_TX) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX,
-                       survey->time_tx))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_TX,
+                             survey->time_tx, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
        if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
-           nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN,
-                       survey->time_scan))
+           nla_put_u64_64bit(msg, NL80211_SURVEY_INFO_TIME_SCAN,
+                             survey->time_scan, NL80211_SURVEY_INFO_PAD))
                goto nla_put_failure;
 
        nla_nest_end(msg, infoattr);
@@ -7402,14 +7551,14 @@ static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)
 
 static bool
 nl80211_parse_mcast_rate(struct cfg80211_registered_device *rdev,
-                        int mcast_rate[IEEE80211_NUM_BANDS],
+                        int mcast_rate[NUM_NL80211_BANDS],
                         int rateval)
 {
        struct wiphy *wiphy = &rdev->wiphy;
        bool found = false;
        int band, i;
 
-       for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
+       for (band = 0; band < NUM_NL80211_BANDS; band++) {
                struct ieee80211_supported_band *sband;
 
                sband = wiphy->bands[band];
@@ -7589,7 +7738,7 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
 {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
-       int mcast_rate[IEEE80211_NUM_BANDS];
+       int mcast_rate[NUM_NL80211_BANDS];
        u32 nla_rate;
        int err;
 
@@ -7650,8 +7799,8 @@ __cfg80211_alloc_vendor_skb(struct cfg80211_registered_device *rdev,
        }
 
        if (wdev) {
-               if (nla_put_u64(skb, NL80211_ATTR_WDEV,
-                               wdev_id(wdev)))
+               if (nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
+                                     wdev_id(wdev), NL80211_ATTR_PAD))
                        goto nla_put_failure;
                if (wdev->netdev &&
                    nla_put_u32(skb, NL80211_ATTR_IFINDEX,
@@ -7922,6 +8071,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                connect.mfp = NL80211_MFP_NO;
        }
 
+       if (info->attrs[NL80211_ATTR_PREV_BSSID])
+               connect.prev_bssid =
+                       nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
+
        if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
                connect.channel = nl80211_get_valid_chan(
                        wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]);
@@ -7990,13 +8143,29 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
        }
 
        connect.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
-       if (connect.pbss && !rdev->wiphy.bands[IEEE80211_BAND_60GHZ]) {
+       if (connect.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
                kzfree(connkeys);
                return -EOPNOTSUPP;
        }
 
+       if (info->attrs[NL80211_ATTR_BSS_SELECT]) {
+               /* bss selection makes no sense if bssid is set */
+               if (connect.bssid) {
+                       kzfree(connkeys);
+                       return -EINVAL;
+               }
+
+               err = parse_bss_select(info->attrs[NL80211_ATTR_BSS_SELECT],
+                                      wiphy, &connect.bss_select);
+               if (err) {
+                       kzfree(connkeys);
+                       return err;
+               }
+       }
+
        wdev_lock(dev->ieee80211_ptr);
-       err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
+       err = cfg80211_connect(rdev, dev, &connect, connkeys,
+                              connect.prev_bssid);
        wdev_unlock(dev->ieee80211_ptr);
        if (err)
                kzfree(connkeys);
@@ -8224,7 +8393,8 @@ static int nl80211_remain_on_channel(struct sk_buff *skb,
        if (err)
                goto free_msg;
 
-       if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+       if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
@@ -8394,7 +8564,7 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 
        memset(&mask, 0, sizeof(mask));
        /* Default to all rates enabled */
-       for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
+       for (i = 0; i < NUM_NL80211_BANDS; i++) {
                sband = rdev->wiphy.bands[i];
 
                if (!sband)
@@ -8418,14 +8588,14 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb,
 
        /*
         * The nested attribute uses enum nl80211_band as the index. This maps
-        * directly to the enum ieee80211_band values used in cfg80211.
+        * directly to the enum nl80211_band values used in cfg80211.
         */
        BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8);
        nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) {
-               enum ieee80211_band band = nla_type(tx_rates);
+               enum nl80211_band band = nla_type(tx_rates);
                int err;
 
-               if (band < 0 || band >= IEEE80211_NUM_BANDS)
+               if (band < 0 || band >= NUM_NL80211_BANDS)
                        return -EINVAL;
                sband = rdev->wiphy.bands[band];
                if (sband == NULL)
@@ -8636,7 +8806,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
                goto free_msg;
 
        if (msg) {
-               if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+               if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                                     NL80211_ATTR_PAD))
                        goto nla_put_failure;
 
                genlmsg_end(msg, hdr);
@@ -9922,7 +10093,8 @@ static int nl80211_probe_client(struct sk_buff *skb,
        if (err)
                goto free_msg;
 
-       if (nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+       if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
@@ -10220,7 +10392,7 @@ static int nl80211_prepare_vendor_dump(struct sk_buff *skb,
                *wdev = NULL;
 
                if (cb->args[1]) {
-                       list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
+                       list_for_each_entry(tmp, &wiphy->wdev_list, list) {
                                if (tmp->identifier == cb->args[1] - 1) {
                                        *wdev = tmp;
                                        break;
@@ -10347,8 +10519,9 @@ static int nl80211_vendor_cmd_dump(struct sk_buff *skb,
                        break;
 
                if (nla_put_u32(skb, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-                   (wdev && nla_put_u64(skb, NL80211_ATTR_WDEV,
-                                        wdev_id(wdev)))) {
+                   (wdev && nla_put_u64_64bit(skb, NL80211_ATTR_WDEV,
+                                              wdev_id(wdev),
+                                              NL80211_ATTR_PAD))) {
                        genlmsg_cancel(skb, hdr);
                        break;
                }
@@ -10590,7 +10763,7 @@ static int nl80211_tdls_channel_switch(struct sk_buff *skb,
         * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
         * specification is not defined for them.
         */
-       if (chandef.chan->band == IEEE80211_BAND_2GHZ &&
+       if (chandef.chan->band == NL80211_BAND_2GHZ &&
            chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
            chandef.width != NL80211_CHAN_WIDTH_20)
                return -EINVAL;
@@ -11555,7 +11728,8 @@ static int nl80211_send_scan_msg(struct sk_buff *msg,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                         wdev->netdev->ifindex)) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        /* ignore errors and send incomplete event anyway */
@@ -12222,11 +12396,13 @@ static void nl80211_send_remain_on_chan_event(
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                         wdev->netdev->ifindex)) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
                        NL80211_CHAN_NO_HT) ||
-           nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie))
+           nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL &&
@@ -12460,7 +12636,8 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                        netdev->ifindex)) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD) ||
            nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||
            (sig_dbm &&
             nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||
@@ -12503,9 +12680,11 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
                                   netdev->ifindex)) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD) ||
            nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||
-           nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                             NL80211_ATTR_PAD) ||
            (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
                goto nla_put_failure;
 
@@ -12885,7 +13064,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
                struct wireless_dev *wdev = netdev->ieee80211_ptr;
 
                if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
-                   nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+                   nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                                     NL80211_ATTR_PAD))
                        goto nla_put_failure;
        }
 
@@ -12930,7 +13110,8 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) ||
-           nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||
+           nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, cookie,
+                             NL80211_ATTR_PAD) ||
            (acked && nla_put_flag(msg, NL80211_ATTR_ACK)))
                goto nla_put_failure;
 
@@ -13075,7 +13256,8 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
                goto free_msg;
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD))
                goto free_msg;
 
        if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,
@@ -13231,7 +13413,7 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
                    sched_scan_req->owner_nlportid == notify->portid)
                        schedule_scan_stop = true;
 
-               list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
+               list_for_each_entry_rcu(wdev, &rdev->wiphy.wdev_list, list) {
                        cfg80211_mlme_unregister_socket(wdev, notify->portid);
 
                        if (wdev->owner_nlportid == notify->portid)
@@ -13350,7 +13532,8 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
                goto nla_put_failure;
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD))
                goto nla_put_failure;
 
        genlmsg_end(msg, hdr);
@@ -13383,7 +13566,8 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
 
        if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
            nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) ||
-           nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)))
+           nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
+                             NL80211_ATTR_PAD))
                goto out;
 
        genlmsg_end(msg, hdr);