aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c315
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
2399static 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
2420static 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
2401static s32 2452static s32
2402brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, 2453brcmf_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 }
2496done: 2522done:
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
5643static 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
5664static 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};
5681static 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
5690static const struct ieee80211_txrx_stypes 5669static const struct ieee80211_txrx_stypes
5691brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { 5670brcmf_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
5698static 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
5753err:
5754 kfree(limits);
5755 kfree(combo);
5756 return -ENOMEM;
5757}
5758
5719static void brcmf_wiphy_pno_params(struct wiphy *wiphy) 5759static 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)
5746static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp) 5786static 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}