diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 315 |
1 files changed, 171 insertions, 144 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index e10fa67010c0..d86d1f1f1c91 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
@@ -52,8 +52,6 @@ | |||
52 | #define BRCMF_PNO_SCAN_COMPLETE 1 | 52 | #define BRCMF_PNO_SCAN_COMPLETE 1 |
53 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | 53 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 |
54 | 54 | ||
55 | #define BRCMF_IFACE_MAX_CNT 3 | ||
56 | |||
57 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ | 55 | #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ |
58 | #define WPA_OUI_TYPE 1 | 56 | #define WPA_OUI_TYPE 1 |
59 | #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ | 57 | #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ |
@@ -2398,27 +2396,80 @@ brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp) | |||
2398 | brcmf_err("set wsec error (%d)\n", err); | 2396 | brcmf_err("set wsec error (%d)\n", err); |
2399 | } | 2397 | } |
2400 | 2398 | ||
2399 | static void brcmf_convert_sta_flags(u32 fw_sta_flags, struct station_info *si) | ||
2400 | { | ||
2401 | struct nl80211_sta_flag_update *sfu; | ||
2402 | |||
2403 | brcmf_dbg(TRACE, "flags %08x\n", fw_sta_flags); | ||
2404 | si->filled |= BIT(NL80211_STA_INFO_STA_FLAGS); | ||
2405 | sfu = &si->sta_flags; | ||
2406 | sfu->mask = BIT(NL80211_STA_FLAG_WME) | | ||
2407 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
2408 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
2409 | BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
2410 | if (fw_sta_flags & BRCMF_STA_WME) | ||
2411 | sfu->set |= BIT(NL80211_STA_FLAG_WME); | ||
2412 | if (fw_sta_flags & BRCMF_STA_AUTHE) | ||
2413 | sfu->set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
2414 | if (fw_sta_flags & BRCMF_STA_ASSOC) | ||
2415 | sfu->set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
2416 | if (fw_sta_flags & BRCMF_STA_AUTHO) | ||
2417 | sfu->set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
2418 | } | ||
2419 | |||
2420 | static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) | ||
2421 | { | ||
2422 | struct { | ||
2423 | __le32 len; | ||
2424 | struct brcmf_bss_info_le bss_le; | ||
2425 | } *buf; | ||
2426 | u16 capability; | ||
2427 | int err; | ||
2428 | |||
2429 | buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); | ||
2430 | if (!buf) | ||
2431 | return; | ||
2432 | |||
2433 | buf->len = cpu_to_le32(WL_BSS_INFO_MAX); | ||
2434 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, buf, | ||
2435 | WL_BSS_INFO_MAX); | ||
2436 | if (err) { | ||
2437 | brcmf_err("Failed to get bss info (%d)\n", err); | ||
2438 | return; | ||
2439 | } | ||
2440 | si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); | ||
2441 | si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); | ||
2442 | si->bss_param.dtim_period = buf->bss_le.dtim_period; | ||
2443 | capability = le16_to_cpu(buf->bss_le.capability); | ||
2444 | if (capability & IEEE80211_HT_STBC_PARAM_DUAL_CTS_PROT) | ||
2445 | si->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
2446 | if (capability & WLAN_CAPABILITY_SHORT_PREAMBLE) | ||
2447 | si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
2448 | if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) | ||
2449 | si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
2450 | } | ||
2451 | |||
2401 | static s32 | 2452 | static s32 |
2402 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | 2453 | brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, |
2403 | const u8 *mac, struct station_info *sinfo) | 2454 | const u8 *mac, struct station_info *sinfo) |
2404 | { | 2455 | { |
2405 | struct brcmf_if *ifp = netdev_priv(ndev); | 2456 | struct brcmf_if *ifp = netdev_priv(ndev); |
2406 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
2407 | struct brcmf_scb_val_le scb_val; | ||
2408 | int rssi; | ||
2409 | s32 rate; | ||
2410 | s32 err = 0; | 2457 | s32 err = 0; |
2411 | u8 *bssid = profile->bssid; | ||
2412 | struct brcmf_sta_info_le sta_info_le; | 2458 | struct brcmf_sta_info_le sta_info_le; |
2413 | u32 beacon_period; | 2459 | u32 sta_flags; |
2414 | u32 dtim_period; | 2460 | u32 is_tdls_peer; |
2415 | 2461 | ||
2416 | brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); | 2462 | brcmf_dbg(TRACE, "Enter, MAC %pM\n", mac); |
2417 | if (!check_vif_up(ifp->vif)) | 2463 | if (!check_vif_up(ifp->vif)) |
2418 | return -EIO; | 2464 | return -EIO; |
2419 | 2465 | ||
2420 | if (brcmf_is_apmode(ifp->vif)) { | 2466 | memset(&sta_info_le, 0, sizeof(sta_info_le)); |
2421 | memcpy(&sta_info_le, mac, ETH_ALEN); | 2467 | memcpy(&sta_info_le, mac, ETH_ALEN); |
2468 | err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info", | ||
2469 | &sta_info_le, | ||
2470 | sizeof(sta_info_le)); | ||
2471 | is_tdls_peer = !err; | ||
2472 | if (err) { | ||
2422 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", | 2473 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", |
2423 | &sta_info_le, | 2474 | &sta_info_le, |
2424 | sizeof(sta_info_le)); | 2475 | sizeof(sta_info_le)); |
@@ -2426,73 +2477,48 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2426 | brcmf_err("GET STA INFO failed, %d\n", err); | 2477 | brcmf_err("GET STA INFO failed, %d\n", err); |
2427 | goto done; | 2478 | goto done; |
2428 | } | 2479 | } |
2429 | sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); | 2480 | } |
2430 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; | 2481 | brcmf_dbg(TRACE, "version %d\n", le16_to_cpu(sta_info_le.ver)); |
2431 | if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { | 2482 | sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME); |
2432 | sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); | 2483 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; |
2433 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); | 2484 | sta_flags = le32_to_cpu(sta_info_le.flags); |
2434 | } | 2485 | brcmf_convert_sta_flags(sta_flags, sinfo); |
2435 | brcmf_dbg(TRACE, "STA idle time : %d ms, connected time :%d sec\n", | 2486 | sinfo->sta_flags.mask |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
2436 | sinfo->inactive_time, sinfo->connected_time); | 2487 | if (is_tdls_peer) |
2437 | } else if (ifp->vif->wdev.iftype == NL80211_IFTYPE_STATION) { | 2488 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); |
2438 | if (memcmp(mac, bssid, ETH_ALEN)) { | 2489 | else |
2439 | brcmf_err("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", | 2490 | sinfo->sta_flags.set &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); |
2440 | mac, bssid); | 2491 | if (sta_flags & BRCMF_STA_ASSOC) { |
2441 | err = -ENOENT; | 2492 | sinfo->filled |= BIT(NL80211_STA_INFO_CONNECTED_TIME); |
2442 | goto done; | 2493 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); |
2443 | } | 2494 | brcmf_fill_bss_param(ifp, sinfo); |
2444 | /* Report the current tx rate */ | 2495 | } |
2445 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); | 2496 | if (sta_flags & BRCMF_STA_SCBSTATS) { |
2446 | if (err) { | 2497 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); |
2447 | brcmf_err("Could not get rate (%d)\n", err); | 2498 | sinfo->tx_failed = le32_to_cpu(sta_info_le.tx_failures); |
2448 | goto done; | 2499 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); |
2449 | } else { | 2500 | sinfo->tx_packets = le32_to_cpu(sta_info_le.tx_pkts); |
2501 | sinfo->tx_packets += le32_to_cpu(sta_info_le.tx_mcast_pkts); | ||
2502 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); | ||
2503 | sinfo->rx_packets = le32_to_cpu(sta_info_le.rx_ucast_pkts); | ||
2504 | sinfo->rx_packets += le32_to_cpu(sta_info_le.rx_mcast_pkts); | ||
2505 | if (sinfo->tx_packets) { | ||
2450 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); | 2506 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); |
2451 | sinfo->txrate.legacy = rate * 5; | 2507 | sinfo->txrate.legacy = le32_to_cpu(sta_info_le.tx_rate); |
2452 | brcmf_dbg(CONN, "Rate %d Mbps\n", rate / 2); | 2508 | sinfo->txrate.legacy /= 100; |
2453 | } | 2509 | } |
2454 | 2510 | if (sinfo->rx_packets) { | |
2455 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, | 2511 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BITRATE); |
2456 | &ifp->vif->sme_state)) { | 2512 | sinfo->rxrate.legacy = le32_to_cpu(sta_info_le.rx_rate); |
2457 | memset(&scb_val, 0, sizeof(scb_val)); | 2513 | sinfo->rxrate.legacy /= 100; |
2458 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, | ||
2459 | &scb_val, sizeof(scb_val)); | ||
2460 | if (err) { | ||
2461 | brcmf_err("Could not get rssi (%d)\n", err); | ||
2462 | goto done; | ||
2463 | } else { | ||
2464 | rssi = le32_to_cpu(scb_val.val); | ||
2465 | sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); | ||
2466 | sinfo->signal = rssi; | ||
2467 | brcmf_dbg(CONN, "RSSI %d dBm\n", rssi); | ||
2468 | } | ||
2469 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_BCNPRD, | ||
2470 | &beacon_period); | ||
2471 | if (err) { | ||
2472 | brcmf_err("Could not get beacon period (%d)\n", | ||
2473 | err); | ||
2474 | goto done; | ||
2475 | } else { | ||
2476 | sinfo->bss_param.beacon_interval = | ||
2477 | beacon_period; | ||
2478 | brcmf_dbg(CONN, "Beacon peroid %d\n", | ||
2479 | beacon_period); | ||
2480 | } | ||
2481 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_DTIMPRD, | ||
2482 | &dtim_period); | ||
2483 | if (err) { | ||
2484 | brcmf_err("Could not get DTIM period (%d)\n", | ||
2485 | err); | ||
2486 | goto done; | ||
2487 | } else { | ||
2488 | sinfo->bss_param.dtim_period = dtim_period; | ||
2489 | brcmf_dbg(CONN, "DTIM peroid %d\n", | ||
2490 | dtim_period); | ||
2491 | } | ||
2492 | sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); | ||
2493 | } | 2514 | } |
2494 | } else | 2515 | if (le16_to_cpu(sta_info_le.ver) >= 4) { |
2495 | err = -EPERM; | 2516 | sinfo->filled |= BIT(NL80211_STA_INFO_TX_BYTES); |
2517 | sinfo->tx_bytes = le64_to_cpu(sta_info_le.tx_tot_bytes); | ||
2518 | sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES); | ||
2519 | sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); | ||
2520 | } | ||
2521 | } | ||
2496 | done: | 2522 | done: |
2497 | brcmf_dbg(TRACE, "Exit\n"); | 2523 | brcmf_dbg(TRACE, "Exit\n"); |
2498 | return err; | 2524 | return err; |
@@ -5640,53 +5666,6 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy) | |||
5640 | return 0; | 5666 | return 0; |
5641 | } | 5667 | } |
5642 | 5668 | ||
5643 | static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = { | ||
5644 | { | ||
5645 | .max = 1, | ||
5646 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5647 | BIT(NL80211_IFTYPE_ADHOC) | ||
5648 | }, | ||
5649 | { | ||
5650 | .max = 4, | ||
5651 | .types = BIT(NL80211_IFTYPE_AP) | ||
5652 | }, | ||
5653 | { | ||
5654 | .max = 1, | ||
5655 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5656 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5657 | }, | ||
5658 | { | ||
5659 | .max = 1, | ||
5660 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5661 | } | ||
5662 | }; | ||
5663 | |||
5664 | static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = { | ||
5665 | { | ||
5666 | .max = 2, | ||
5667 | .types = BIT(NL80211_IFTYPE_STATION) | | ||
5668 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5669 | BIT(NL80211_IFTYPE_AP) | ||
5670 | }, | ||
5671 | { | ||
5672 | .max = 1, | ||
5673 | .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5674 | BIT(NL80211_IFTYPE_P2P_GO) | ||
5675 | }, | ||
5676 | { | ||
5677 | .max = 1, | ||
5678 | .types = BIT(NL80211_IFTYPE_P2P_DEVICE) | ||
5679 | } | ||
5680 | }; | ||
5681 | static struct ieee80211_iface_combination brcmf_iface_combos[] = { | ||
5682 | { | ||
5683 | .max_interfaces = BRCMF_IFACE_MAX_CNT, | ||
5684 | .num_different_channels = 1, | ||
5685 | .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss), | ||
5686 | .limits = brcmf_iface_limits_sbss, | ||
5687 | } | ||
5688 | }; | ||
5689 | |||
5690 | static const struct ieee80211_txrx_stypes | 5669 | static const struct ieee80211_txrx_stypes |
5691 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | 5670 | brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { |
5692 | [NL80211_IFTYPE_STATION] = { | 5671 | [NL80211_IFTYPE_STATION] = { |
@@ -5716,6 +5695,67 @@ brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { | |||
5716 | } | 5695 | } |
5717 | }; | 5696 | }; |
5718 | 5697 | ||
5698 | static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) | ||
5699 | { | ||
5700 | struct ieee80211_iface_combination *combo = NULL; | ||
5701 | struct ieee80211_iface_limit *limits = NULL; | ||
5702 | int i = 0, max_iface_cnt; | ||
5703 | |||
5704 | combo = kzalloc(sizeof(*combo), GFP_KERNEL); | ||
5705 | if (!combo) | ||
5706 | goto err; | ||
5707 | |||
5708 | limits = kzalloc(sizeof(*limits) * 4, GFP_KERNEL); | ||
5709 | if (!limits) | ||
5710 | goto err; | ||
5711 | |||
5712 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
5713 | BIT(NL80211_IFTYPE_ADHOC) | | ||
5714 | BIT(NL80211_IFTYPE_AP); | ||
5715 | |||
5716 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5717 | combo->num_different_channels = 2; | ||
5718 | else | ||
5719 | combo->num_different_channels = 1; | ||
5720 | |||
5721 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { | ||
5722 | limits[i].max = 1; | ||
5723 | limits[i++].types = BIT(NL80211_IFTYPE_STATION); | ||
5724 | limits[i].max = 4; | ||
5725 | limits[i++].types = BIT(NL80211_IFTYPE_AP); | ||
5726 | max_iface_cnt = 5; | ||
5727 | } else { | ||
5728 | limits[i].max = 2; | ||
5729 | limits[i++].types = BIT(NL80211_IFTYPE_STATION) | | ||
5730 | BIT(NL80211_IFTYPE_AP); | ||
5731 | max_iface_cnt = 2; | ||
5732 | } | ||
5733 | |||
5734 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P)) { | ||
5735 | wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5736 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5737 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5738 | limits[i].max = 1; | ||
5739 | limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | | ||
5740 | BIT(NL80211_IFTYPE_P2P_GO); | ||
5741 | limits[i].max = 1; | ||
5742 | limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5743 | max_iface_cnt += 2; | ||
5744 | } | ||
5745 | combo->max_interfaces = max_iface_cnt; | ||
5746 | combo->limits = limits; | ||
5747 | combo->n_limits = i; | ||
5748 | |||
5749 | wiphy->iface_combinations = combo; | ||
5750 | wiphy->n_iface_combinations = 1; | ||
5751 | return 0; | ||
5752 | |||
5753 | err: | ||
5754 | kfree(limits); | ||
5755 | kfree(combo); | ||
5756 | return -ENOMEM; | ||
5757 | } | ||
5758 | |||
5719 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | 5759 | static void brcmf_wiphy_pno_params(struct wiphy *wiphy) |
5720 | { | 5760 | { |
5721 | /* scheduled scan settings */ | 5761 | /* scheduled scan settings */ |
@@ -5746,7 +5786,6 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy) | |||
5746 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | 5786 | static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) |
5747 | { | 5787 | { |
5748 | struct ieee80211_supported_band *band; | 5788 | struct ieee80211_supported_band *band; |
5749 | struct ieee80211_iface_combination ifc_combo; | ||
5750 | __le32 bandlist[3]; | 5789 | __le32 bandlist[3]; |
5751 | u32 n_bands; | 5790 | u32 n_bands; |
5752 | int err, i; | 5791 | int err, i; |
@@ -5754,24 +5793,11 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) | |||
5754 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | 5793 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; |
5755 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; | 5794 | wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; |
5756 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | 5795 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; |
5757 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 5796 | |
5758 | BIT(NL80211_IFTYPE_ADHOC) | | 5797 | err = brcmf_setup_ifmodes(wiphy, ifp); |
5759 | BIT(NL80211_IFTYPE_AP) | | 5798 | if (err) |
5760 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 5799 | return err; |
5761 | BIT(NL80211_IFTYPE_P2P_GO) | | 5800 | |
5762 | BIT(NL80211_IFTYPE_P2P_DEVICE); | ||
5763 | /* need VSDB firmware feature for concurrent channels */ | ||
5764 | ifc_combo = brcmf_iface_combos[0]; | ||
5765 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) | ||
5766 | ifc_combo.num_different_channels = 2; | ||
5767 | if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) { | ||
5768 | ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss), | ||
5769 | ifc_combo.limits = brcmf_iface_limits_mbss; | ||
5770 | } | ||
5771 | wiphy->iface_combinations = kmemdup(&ifc_combo, | ||
5772 | sizeof(ifc_combo), | ||
5773 | GFP_KERNEL); | ||
5774 | wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); | ||
5775 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 5801 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
5776 | wiphy->cipher_suites = __wl_cipher_suites; | 5802 | wiphy->cipher_suites = __wl_cipher_suites; |
5777 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 5803 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
@@ -6036,6 +6062,8 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) | |||
6036 | if (!wiphy) | 6062 | if (!wiphy) |
6037 | return; | 6063 | return; |
6038 | 6064 | ||
6065 | if (wiphy->iface_combinations) | ||
6066 | kfree(wiphy->iface_combinations->limits); | ||
6039 | kfree(wiphy->iface_combinations); | 6067 | kfree(wiphy->iface_combinations); |
6040 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { | 6068 | if (wiphy->bands[IEEE80211_BAND_2GHZ]) { |
6041 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); | 6069 | kfree(wiphy->bands[IEEE80211_BAND_2GHZ]->channels); |
@@ -6071,6 +6099,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, | |||
6071 | brcmf_err("Could not allocate wiphy device\n"); | 6099 | brcmf_err("Could not allocate wiphy device\n"); |
6072 | return NULL; | 6100 | return NULL; |
6073 | } | 6101 | } |
6102 | memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN); | ||
6074 | set_wiphy_dev(wiphy, busdev); | 6103 | set_wiphy_dev(wiphy, busdev); |
6075 | 6104 | ||
6076 | cfg = wiphy_priv(wiphy); | 6105 | cfg = wiphy_priv(wiphy); |
@@ -6178,10 +6207,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | |||
6178 | if (!cfg) | 6207 | if (!cfg) |
6179 | return; | 6208 | return; |
6180 | 6209 | ||
6181 | WARN_ON(!list_empty(&cfg->vif_list)); | ||
6182 | wiphy_unregister(cfg->wiphy); | ||
6183 | brcmf_btcoex_detach(cfg); | 6210 | brcmf_btcoex_detach(cfg); |
6184 | brcmf_p2p_detach(&cfg->p2p); | 6211 | wiphy_unregister(cfg->wiphy); |
6185 | wl_deinit_priv(cfg); | 6212 | wl_deinit_priv(cfg); |
6186 | brcmf_free_wiphy(cfg->wiphy); | 6213 | brcmf_free_wiphy(cfg->wiphy); |
6187 | } | 6214 | } |