aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmfmac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c315
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/commonring.c19
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/commonring.h3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/core.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/debug.c50
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.c1
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/feature.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.c50
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h79
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c12
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/p2p.c203
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/pcie.c16
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/sdio.c6
14 files changed, 403 insertions, 360 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 71779b9e4bbe..410a6645d316 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -988,6 +988,7 @@ static void brcmf_sdiod_freezer_detach(struct brcmf_sdio_dev *sdiodev)
988 988
989static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) 989static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev)
990{ 990{
991 sdiodev->state = BRCMF_SDIOD_DOWN;
991 if (sdiodev->bus) { 992 if (sdiodev->bus) {
992 brcmf_sdio_remove(sdiodev->bus); 993 brcmf_sdio_remove(sdiodev->bus);
993 sdiodev->bus = NULL; 994 sdiodev->bus = NULL;
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}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
index 26c65872dae3..7b0e52195a85 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
@@ -223,8 +223,6 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
223void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, 223void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
224 u16 *n_items) 224 u16 *n_items)
225{ 225{
226 void *ret_addr;
227
228 if (commonring->cr_update_wptr) 226 if (commonring->cr_update_wptr)
229 commonring->cr_update_wptr(commonring->cr_ctx); 227 commonring->cr_update_wptr(commonring->cr_ctx);
230 228
@@ -235,19 +233,18 @@ void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
235 if (*n_items == 0) 233 if (*n_items == 0)
236 return NULL; 234 return NULL;
237 235
238 ret_addr = commonring->buf_addr + 236 return commonring->buf_addr +
239 (commonring->r_ptr * commonring->item_len); 237 (commonring->r_ptr * commonring->item_len);
240
241 commonring->r_ptr += *n_items;
242 if (commonring->r_ptr == commonring->depth)
243 commonring->r_ptr = 0;
244
245 return ret_addr;
246} 238}
247 239
248 240
249int brcmf_commonring_read_complete(struct brcmf_commonring *commonring) 241int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
242 u16 n_items)
250{ 243{
244 commonring->r_ptr += n_items;
245 if (commonring->r_ptr == commonring->depth)
246 commonring->r_ptr = 0;
247
251 if (commonring->cr_write_rptr) 248 if (commonring->cr_write_rptr)
252 return commonring->cr_write_rptr(commonring->cr_ctx); 249 return commonring->cr_write_rptr(commonring->cr_ctx);
253 250
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
index 3d404016a92e..b85033611c8d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.h
@@ -62,7 +62,8 @@ void brcmf_commonring_write_cancel(struct brcmf_commonring *commonring,
62 u16 n_items); 62 u16 n_items);
63void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, 63void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring,
64 u16 *n_items); 64 u16 *n_items);
65int brcmf_commonring_read_complete(struct brcmf_commonring *commonring); 65int brcmf_commonring_read_complete(struct brcmf_commonring *commonring,
66 u16 n_items);
66 67
67#define brcmf_commonring_n_items(commonring) (commonring->depth) 68#define brcmf_commonring_n_items(commonring) (commonring->depth)
68#define brcmf_commonring_len_item(commonring) (commonring->item_len) 69#define brcmf_commonring_len_item(commonring) (commonring->item_len)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index f8f47dcfa886..fe9d3fbf5fe2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -867,8 +867,6 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
867 } 867 }
868 /* unregister will take care of freeing it */ 868 /* unregister will take care of freeing it */
869 unregister_netdev(ifp->ndev); 869 unregister_netdev(ifp->ndev);
870 } else {
871 kfree(ifp);
872 } 870 }
873} 871}
874 872
@@ -1100,6 +1098,8 @@ void brcmf_detach(struct device *dev)
1100 1098
1101 /* stop firmware event handling */ 1099 /* stop firmware event handling */
1102 brcmf_fweh_detach(drvr); 1100 brcmf_fweh_detach(drvr);
1101 if (drvr->config)
1102 brcmf_p2p_detach(&drvr->config->p2p);
1103 1103
1104 brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN); 1104 brcmf_bus_change_state(bus_if, BRCMF_BUS_DOWN);
1105 1105
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
index 9b473d50b005..2d6d00553858 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c
@@ -41,15 +41,6 @@ void brcmf_debugfs_exit(void)
41 root_folder = NULL; 41 root_folder = NULL;
42} 42}
43 43
44static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
45{
46 struct brcmf_bus *bus = dev_get_drvdata(seq->private);
47
48 seq_printf(seq, "chip: %x(%u) rev %u\n",
49 bus->chip, bus->chip, bus->chiprev);
50 return 0;
51}
52
53int brcmf_debugfs_attach(struct brcmf_pub *drvr) 44int brcmf_debugfs_attach(struct brcmf_pub *drvr)
54{ 45{
55 struct device *dev = drvr->bus_if->dev; 46 struct device *dev = drvr->bus_if->dev;
@@ -58,7 +49,6 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
58 return -ENODEV; 49 return -ENODEV;
59 50
60 drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); 51 drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
61 brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
62 52
63 return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); 53 return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
64} 54}
@@ -74,44 +64,12 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
74 return drvr->dbgfs_dir; 64 return drvr->dbgfs_dir;
75} 65}
76 66
77struct brcmf_debugfs_entry {
78 int (*read)(struct seq_file *seq, void *data);
79 struct brcmf_pub *drvr;
80};
81
82static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
83{
84 struct brcmf_debugfs_entry *entry = inode->i_private;
85
86 return single_open(f, entry->read, entry->drvr->bus_if->dev);
87}
88
89static const struct file_operations brcmf_debugfs_def_ops = {
90 .owner = THIS_MODULE,
91 .open = brcmf_debugfs_entry_open,
92 .release = single_release,
93 .read = seq_read,
94 .llseek = seq_lseek
95};
96
97int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, 67int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
98 int (*read_fn)(struct seq_file *seq, void *data)) 68 int (*read_fn)(struct seq_file *seq, void *data))
99{ 69{
100 struct dentry *dentry = drvr->dbgfs_dir; 70 struct dentry *e;
101 struct brcmf_debugfs_entry *entry;
102
103 if (IS_ERR_OR_NULL(dentry))
104 return -ENOENT;
105
106 entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
107 if (!entry)
108 return -ENOMEM;
109
110 entry->read = read_fn;
111 entry->drvr = drvr;
112
113 dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
114 &brcmf_debugfs_def_ops);
115 71
116 return PTR_ERR_OR_ZERO(dentry); 72 e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn,
73 drvr->dbgfs_dir, read_fn);
74 return PTR_ERR_OR_ZERO(e);
117} 75}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
index 2c5fad3a3aa2..1e94e94e01dc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -129,6 +129,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
129 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl"); 129 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
130 if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) 130 if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
131 brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); 131 brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
132 brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
132 133
133 /* set chip related quirks */ 134 /* set chip related quirks */
134 switch (drvr->bus_if->chip) { 135 switch (drvr->bus_if->chip) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
index 546962525cd2..6b381f799f22 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
@@ -23,12 +23,14 @@
23 * MCHAN: multi-channel for concurrent P2P. 23 * MCHAN: multi-channel for concurrent P2P.
24 * PNO: preferred network offload. 24 * PNO: preferred network offload.
25 * WOWL: Wake-On-WLAN. 25 * WOWL: Wake-On-WLAN.
26 * P2P: peer-to-peer
26 */ 27 */
27#define BRCMF_FEAT_LIST \ 28#define BRCMF_FEAT_LIST \
28 BRCMF_FEAT_DEF(MBSS) \ 29 BRCMF_FEAT_DEF(MBSS) \
29 BRCMF_FEAT_DEF(MCHAN) \ 30 BRCMF_FEAT_DEF(MCHAN) \
30 BRCMF_FEAT_DEF(PNO) \ 31 BRCMF_FEAT_DEF(PNO) \
31 BRCMF_FEAT_DEF(WOWL) 32 BRCMF_FEAT_DEF(WOWL) \
33 BRCMF_FEAT_DEF(P2P)
32/* 34/*
33 * Quirks: 35 * Quirks:
34 * 36 *
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 7ae6461df932..743f16b6a072 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -43,7 +43,7 @@ enum nvram_parser_state {
43 * struct nvram_parser - internal info for parser. 43 * struct nvram_parser - internal info for parser.
44 * 44 *
45 * @state: current parser state. 45 * @state: current parser state.
46 * @fwnv: input buffer being parsed. 46 * @data: input buffer being parsed.
47 * @nvram: output buffer with parse result. 47 * @nvram: output buffer with parse result.
48 * @nvram_len: lenght of parse result. 48 * @nvram_len: lenght of parse result.
49 * @line: current line. 49 * @line: current line.
@@ -55,7 +55,7 @@ enum nvram_parser_state {
55 */ 55 */
56struct nvram_parser { 56struct nvram_parser {
57 enum nvram_parser_state state; 57 enum nvram_parser_state state;
58 const struct firmware *fwnv; 58 const u8 *data;
59 u8 *nvram; 59 u8 *nvram;
60 u32 nvram_len; 60 u32 nvram_len;
61 u32 line; 61 u32 line;
@@ -91,7 +91,7 @@ static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
91{ 91{
92 char c; 92 char c;
93 93
94 c = nvp->fwnv->data[nvp->pos]; 94 c = nvp->data[nvp->pos];
95 if (c == '\n') 95 if (c == '\n')
96 return COMMENT; 96 return COMMENT;
97 if (is_whitespace(c)) 97 if (is_whitespace(c))
@@ -115,16 +115,16 @@ static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
115 enum nvram_parser_state st = nvp->state; 115 enum nvram_parser_state st = nvp->state;
116 char c; 116 char c;
117 117
118 c = nvp->fwnv->data[nvp->pos]; 118 c = nvp->data[nvp->pos];
119 if (c == '=') { 119 if (c == '=') {
120 /* ignore RAW1 by treating as comment */ 120 /* ignore RAW1 by treating as comment */
121 if (strncmp(&nvp->fwnv->data[nvp->entry], "RAW1", 4) == 0) 121 if (strncmp(&nvp->data[nvp->entry], "RAW1", 4) == 0)
122 st = COMMENT; 122 st = COMMENT;
123 else 123 else
124 st = VALUE; 124 st = VALUE;
125 if (strncmp(&nvp->fwnv->data[nvp->entry], "devpath", 7) == 0) 125 if (strncmp(&nvp->data[nvp->entry], "devpath", 7) == 0)
126 nvp->multi_dev_v1 = true; 126 nvp->multi_dev_v1 = true;
127 if (strncmp(&nvp->fwnv->data[nvp->entry], "pcie/", 5) == 0) 127 if (strncmp(&nvp->data[nvp->entry], "pcie/", 5) == 0)
128 nvp->multi_dev_v2 = true; 128 nvp->multi_dev_v2 = true;
129 } else if (!is_nvram_char(c) || c == ' ') { 129 } else if (!is_nvram_char(c) || c == ' ') {
130 brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n", 130 brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
@@ -145,11 +145,11 @@ brcmf_nvram_handle_value(struct nvram_parser *nvp)
145 char *ekv; 145 char *ekv;
146 u32 cplen; 146 u32 cplen;
147 147
148 c = nvp->fwnv->data[nvp->pos]; 148 c = nvp->data[nvp->pos];
149 if (!is_nvram_char(c)) { 149 if (!is_nvram_char(c)) {
150 /* key,value pair complete */ 150 /* key,value pair complete */
151 ekv = (u8 *)&nvp->fwnv->data[nvp->pos]; 151 ekv = (u8 *)&nvp->data[nvp->pos];
152 skv = (u8 *)&nvp->fwnv->data[nvp->entry]; 152 skv = (u8 *)&nvp->data[nvp->entry];
153 cplen = ekv - skv; 153 cplen = ekv - skv;
154 if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE) 154 if (nvp->nvram_len + cplen + 1 >= BRCMF_FW_MAX_NVRAM_SIZE)
155 return END; 155 return END;
@@ -170,7 +170,7 @@ brcmf_nvram_handle_comment(struct nvram_parser *nvp)
170{ 170{
171 char *eoc, *sol; 171 char *eoc, *sol;
172 172
173 sol = (char *)&nvp->fwnv->data[nvp->pos]; 173 sol = (char *)&nvp->data[nvp->pos];
174 eoc = strchr(sol, '\n'); 174 eoc = strchr(sol, '\n');
175 if (!eoc) { 175 if (!eoc) {
176 eoc = strchr(sol, '\0'); 176 eoc = strchr(sol, '\0');
@@ -201,17 +201,17 @@ static enum nvram_parser_state
201}; 201};
202 202
203static int brcmf_init_nvram_parser(struct nvram_parser *nvp, 203static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
204 const struct firmware *nv) 204 const u8 *data, size_t data_len)
205{ 205{
206 size_t size; 206 size_t size;
207 207
208 memset(nvp, 0, sizeof(*nvp)); 208 memset(nvp, 0, sizeof(*nvp));
209 nvp->fwnv = nv; 209 nvp->data = data;
210 /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */ 210 /* Limit size to MAX_NVRAM_SIZE, some files contain lot of comment */
211 if (nv->size > BRCMF_FW_MAX_NVRAM_SIZE) 211 if (data_len > BRCMF_FW_MAX_NVRAM_SIZE)
212 size = BRCMF_FW_MAX_NVRAM_SIZE; 212 size = BRCMF_FW_MAX_NVRAM_SIZE;
213 else 213 else
214 size = nv->size; 214 size = data_len;
215 /* Alloc for extra 0 byte + roundup by 4 + length field */ 215 /* Alloc for extra 0 byte + roundup by 4 + length field */
216 size += 1 + 3 + sizeof(u32); 216 size += 1 + 3 + sizeof(u32);
217 nvp->nvram = kzalloc(size, GFP_KERNEL); 217 nvp->nvram = kzalloc(size, GFP_KERNEL);
@@ -232,6 +232,8 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
232 u16 bus_nr) 232 u16 bus_nr)
233{ 233{
234 /* Device path with a leading '=' key-value separator */ 234 /* Device path with a leading '=' key-value separator */
235 char pci_path[] = "=pci/?/?";
236 size_t pci_len;
235 char pcie_path[] = "=pcie/?/?"; 237 char pcie_path[] = "=pcie/?/?";
236 size_t pcie_len; 238 size_t pcie_len;
237 239
@@ -251,6 +253,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
251 /* First search for the devpathX and see if it is the configuration 253 /* First search for the devpathX and see if it is the configuration
252 * for domain_nr/bus_nr. Search complete nvp 254 * for domain_nr/bus_nr. Search complete nvp
253 */ 255 */
256 snprintf(pci_path, sizeof(pci_path), "=pci/%d/%d", domain_nr,
257 bus_nr);
258 pci_len = strlen(pci_path);
254 snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr, 259 snprintf(pcie_path, sizeof(pcie_path), "=pcie/%d/%d", domain_nr,
255 bus_nr); 260 bus_nr);
256 pcie_len = strlen(pcie_path); 261 pcie_len = strlen(pcie_path);
@@ -260,8 +265,9 @@ static void brcmf_fw_strip_multi_v1(struct nvram_parser *nvp, u16 domain_nr,
260 /* Format: devpathX=pcie/Y/Z/ 265 /* Format: devpathX=pcie/Y/Z/
261 * Y = domain_nr, Z = bus_nr, X = virtual ID 266 * Y = domain_nr, Z = bus_nr, X = virtual ID
262 */ 267 */
263 if ((strncmp(&nvp->nvram[i], "devpath", 7) == 0) && 268 if (strncmp(&nvp->nvram[i], "devpath", 7) == 0 &&
264 (strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len) == 0)) { 269 (!strncmp(&nvp->nvram[i + 8], pci_path, pci_len) ||
270 !strncmp(&nvp->nvram[i + 8], pcie_path, pcie_len))) {
265 id = nvp->nvram[i + 7] - '0'; 271 id = nvp->nvram[i + 7] - '0';
266 found = true; 272 found = true;
267 break; 273 break;
@@ -356,18 +362,18 @@ fail:
356 * and converts newlines to NULs. Shortens buffer as needed and pads with NULs. 362 * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
357 * End of buffer is completed with token identifying length of buffer. 363 * End of buffer is completed with token identifying length of buffer.
358 */ 364 */
359static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length, 365static void *brcmf_fw_nvram_strip(const u8 *data, size_t data_len,
360 u16 domain_nr, u16 bus_nr) 366 u32 *new_length, u16 domain_nr, u16 bus_nr)
361{ 367{
362 struct nvram_parser nvp; 368 struct nvram_parser nvp;
363 u32 pad; 369 u32 pad;
364 u32 token; 370 u32 token;
365 __le32 token_le; 371 __le32 token_le;
366 372
367 if (brcmf_init_nvram_parser(&nvp, nv) < 0) 373 if (brcmf_init_nvram_parser(&nvp, data, data_len) < 0)
368 return NULL; 374 return NULL;
369 375
370 while (nvp.pos < nv->size) { 376 while (nvp.pos < data_len) {
371 nvp.state = nv_parser_states[nvp.state](&nvp); 377 nvp.state = nv_parser_states[nvp.state](&nvp);
372 if (nvp.state == END) 378 if (nvp.state == END)
373 break; 379 break;
@@ -426,7 +432,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
426 goto fail; 432 goto fail;
427 433
428 if (fw) { 434 if (fw) {
429 nvram = brcmf_fw_nvram_strip(fw, &nvram_length, 435 nvram = brcmf_fw_nvram_strip(fw->data, fw->size, &nvram_length,
430 fwctx->domain_nr, fwctx->bus_nr); 436 fwctx->domain_nr, fwctx->bus_nr);
431 release_firmware(fw); 437 release_firmware(fw);
432 if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) 438 if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 374920965108..297911f38fa0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -32,7 +32,11 @@
32#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ 32#define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
33#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 33#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
34 34
35#define BRCMF_STA_ASSOC 0x10 /* Associated */ 35#define BRCMF_STA_WME 0x00000002 /* WMM association */
36#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
37#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
38#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
39#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
36 40
37/* size of brcmf_scan_params not including variable length array */ 41/* size of brcmf_scan_params not including variable length array */
38#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 42#define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
@@ -113,6 +117,7 @@
113#define BRCMF_WOWL_MAXPATTERNSIZE 128 117#define BRCMF_WOWL_MAXPATTERNSIZE 128
114 118
115#define BRCMF_COUNTRY_BUF_SZ 4 119#define BRCMF_COUNTRY_BUF_SZ 4
120#define BRCMF_ANT_MAX 4
116 121
117/* join preference types for join_pref iovar */ 122/* join preference types for join_pref iovar */
118enum brcmf_join_pref_types { 123enum brcmf_join_pref_types {
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le {
456}; 461};
457 462
458struct brcmf_sta_info_le { 463struct brcmf_sta_info_le {
459 __le16 ver; /* version of this struct */ 464 __le16 ver; /* version of this struct */
460 __le16 len; /* length in bytes of this structure */ 465 __le16 len; /* length in bytes of this structure */
461 __le16 cap; /* sta's advertised capabilities */ 466 __le16 cap; /* sta's advertised capabilities */
462 __le32 flags; /* flags defined below */ 467 __le32 flags; /* flags defined below */
463 __le32 idle; /* time since data pkt rx'd from sta */ 468 __le32 idle; /* time since data pkt rx'd from sta */
464 u8 ea[ETH_ALEN]; /* Station address */ 469 u8 ea[ETH_ALEN]; /* Station address */
465 __le32 count; /* # rates in this set */ 470 __le32 count; /* # rates in this set */
466 u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ 471 u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */
467 /* w/hi bit set if basic */ 472 /* w/hi bit set if basic */
468 __le32 in; /* seconds elapsed since associated */ 473 __le32 in; /* seconds elapsed since associated */
469 __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ 474 __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
470 __le32 tx_pkts; /* # of packets transmitted */ 475 __le32 tx_pkts; /* # of packets transmitted */
471 __le32 tx_failures; /* # of packets failed */ 476 __le32 tx_failures; /* # of packets failed */
472 __le32 rx_ucast_pkts; /* # of unicast packets received */ 477 __le32 rx_ucast_pkts; /* # of unicast packets received */
473 __le32 rx_mcast_pkts; /* # of multicast packets received */ 478 __le32 rx_mcast_pkts; /* # of multicast packets received */
474 __le32 tx_rate; /* Rate of last successful tx frame */ 479 __le32 tx_rate; /* Rate of last successful tx frame */
475 __le32 rx_rate; /* Rate of last successful rx frame */ 480 __le32 rx_rate; /* Rate of last successful rx frame */
476 __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ 481 __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
477 __le32 rx_decrypt_failures; /* # of packet decrypted failed */ 482 __le32 rx_decrypt_failures; /* # of packet decrypted failed */
483 __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
484 __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
485 __le32 tx_mcast_pkts; /* # of mcast pkts txed */
486 __le64 tx_tot_bytes; /* data bytes txed (ucast + mcast) */
487 __le64 rx_tot_bytes; /* data bytes recvd (ucast + mcast) */
488 __le64 tx_ucast_bytes; /* data bytes txed (ucast) */
489 __le64 tx_mcast_bytes; /* # data bytes txed (mcast) */
490 __le64 rx_ucast_bytes; /* data bytes recvd (ucast) */
491 __le64 rx_mcast_bytes; /* data bytes recvd (mcast) */
492 s8 rssi[BRCMF_ANT_MAX]; /* per antenna rssi */
493 s8 nf[BRCMF_ANT_MAX]; /* per antenna noise floor */
494 __le16 aid; /* association ID */
495 __le16 ht_capabilities; /* advertised ht caps */
496 __le16 vht_flags; /* converted vht flags */
497 __le32 tx_pkts_retry_cnt; /* # of frames where a retry was
498 * exhausted.
499 */
500 __le32 tx_pkts_retry_exhausted; /* # of user frames where a retry
501 * was exhausted
502 */
503 s8 rx_lastpkt_rssi[BRCMF_ANT_MAX]; /* Per antenna RSSI of last
504 * received data frame.
505 */
506 /* TX WLAN retry/failure statistics:
507 * Separated for host requested frames and locally generated frames.
508 * Include unicast frame only where the retries/failures can be counted.
509 */
510 __le32 tx_pkts_total; /* # user frames sent successfully */
511 __le32 tx_pkts_retries; /* # user frames retries */
512 __le32 tx_pkts_fw_total; /* # FW generated sent successfully */
513 __le32 tx_pkts_fw_retries; /* # retries for FW generated frames */
514 __le32 tx_pkts_fw_retry_exhausted; /* # FW generated where a retry
515 * was exhausted
516 */
517 __le32 rx_pkts_retried; /* # rx with retry bit set */
518 __le32 tx_rate_fallback; /* lowest fallback TX rate */
478}; 519};
479 520
480struct brcmf_chanspec_list { 521struct brcmf_chanspec_list {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 1b47de067d25..898c3801e658 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -75,6 +75,8 @@
75 75
76#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96 76#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
77#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32 77#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
78#define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS 48
79
78 80
79struct msgbuf_common_hdr { 81struct msgbuf_common_hdr {
80 u8 msgtype; 82 u8 msgtype;
@@ -1257,19 +1259,27 @@ static void brcmf_msgbuf_process_rx(struct brcmf_msgbuf *msgbuf,
1257{ 1259{
1258 void *buf; 1260 void *buf;
1259 u16 count; 1261 u16 count;
1262 u16 processed;
1260 1263
1261again: 1264again:
1262 buf = brcmf_commonring_get_read_ptr(commonring, &count); 1265 buf = brcmf_commonring_get_read_ptr(commonring, &count);
1263 if (buf == NULL) 1266 if (buf == NULL)
1264 return; 1267 return;
1265 1268
1269 processed = 0;
1266 while (count) { 1270 while (count) {
1267 brcmf_msgbuf_process_msgtype(msgbuf, 1271 brcmf_msgbuf_process_msgtype(msgbuf,
1268 buf + msgbuf->rx_dataoffset); 1272 buf + msgbuf->rx_dataoffset);
1269 buf += brcmf_commonring_len_item(commonring); 1273 buf += brcmf_commonring_len_item(commonring);
1274 processed++;
1275 if (processed == BRCMF_MSGBUF_UPDATE_RX_PTR_THRS) {
1276 brcmf_commonring_read_complete(commonring, processed);
1277 processed = 0;
1278 }
1270 count--; 1279 count--;
1271 } 1280 }
1272 brcmf_commonring_read_complete(commonring); 1281 if (processed)
1282 brcmf_commonring_read_complete(commonring, processed);
1273 1283
1274 if (commonring->r_ptr == 0) 1284 if (commonring->r_ptr == 0)
1275 goto again; 1285 goto again;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index 710fbe570eb2..a9ba775a24c1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -16,6 +16,7 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/netdevice.h> 17#include <linux/netdevice.h>
18#include <linux/etherdevice.h> 18#include <linux/etherdevice.h>
19#include <linux/rtnetlink.h>
19#include <net/cfg80211.h> 20#include <net/cfg80211.h>
20 21
21#include <brcmu_wifi.h> 22#include <brcmu_wifi.h>
@@ -1908,105 +1909,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
1908 1909
1909 1910
1910/** 1911/**
1911 * brcmf_p2p_attach() - attach for P2P.
1912 *
1913 * @cfg: driver private data for cfg80211 interface.
1914 */
1915s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
1916{
1917 struct brcmf_if *pri_ifp;
1918 struct brcmf_if *p2p_ifp;
1919 struct brcmf_cfg80211_vif *p2p_vif;
1920 struct brcmf_p2p_info *p2p;
1921 struct brcmf_pub *drvr;
1922 s32 bssidx;
1923 s32 err = 0;
1924
1925 p2p = &cfg->p2p;
1926 p2p->cfg = cfg;
1927
1928 drvr = cfg->pub;
1929
1930 pri_ifp = drvr->iflist[0];
1931 p2p_ifp = drvr->iflist[1];
1932
1933 p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
1934
1935 if (p2p_ifp) {
1936 p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
1937 false);
1938 if (IS_ERR(p2p_vif)) {
1939 brcmf_err("could not create discovery vif\n");
1940 err = -ENOMEM;
1941 goto exit;
1942 }
1943
1944 p2p_vif->ifp = p2p_ifp;
1945 p2p_ifp->vif = p2p_vif;
1946 p2p_vif->wdev.netdev = p2p_ifp->ndev;
1947 p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
1948 SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
1949
1950 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
1951
1952 brcmf_p2p_generate_bss_mac(p2p, NULL);
1953 memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
1954 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
1955
1956 /* Initialize P2P Discovery in the firmware */
1957 err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
1958 if (err < 0) {
1959 brcmf_err("set p2p_disc error\n");
1960 brcmf_free_vif(p2p_vif);
1961 goto exit;
1962 }
1963 /* obtain bsscfg index for P2P discovery */
1964 err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
1965 if (err < 0) {
1966 brcmf_err("retrieving discover bsscfg index failed\n");
1967 brcmf_free_vif(p2p_vif);
1968 goto exit;
1969 }
1970 /* Verify that firmware uses same bssidx as driver !! */
1971 if (p2p_ifp->bssidx != bssidx) {
1972 brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
1973 bssidx, p2p_ifp->bssidx);
1974 brcmf_free_vif(p2p_vif);
1975 goto exit;
1976 }
1977
1978 init_completion(&p2p->send_af_done);
1979 INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
1980 init_completion(&p2p->afx_hdl.act_frm_scan);
1981 init_completion(&p2p->wait_next_af);
1982 }
1983exit:
1984 return err;
1985}
1986
1987
1988/**
1989 * brcmf_p2p_detach() - detach P2P.
1990 *
1991 * @p2p: P2P specific data.
1992 */
1993void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
1994{
1995 struct brcmf_cfg80211_vif *vif;
1996
1997 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
1998 if (vif != NULL) {
1999 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
2000 brcmf_p2p_deinit_discovery(p2p);
2001 /* remove discovery interface */
2002 brcmf_free_vif(vif);
2003 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
2004 }
2005 /* just set it all to zero */
2006 memset(p2p, 0, sizeof(*p2p));
2007}
2008
2009/**
2010 * brcmf_p2p_get_current_chanspec() - Get current operation channel. 1912 * brcmf_p2p_get_current_chanspec() - Get current operation channel.
2011 * 1913 *
2012 * @p2p: P2P specific data. 1914 * @p2p: P2P specific data.
@@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
2238{ 2140{
2239 cfg80211_unregister_wdev(&vif->wdev); 2141 cfg80211_unregister_wdev(&vif->wdev);
2240 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; 2142 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
2143 brcmf_remove_interface(vif->ifp->drvr, vif->ifp->bssidx);
2241 brcmf_free_vif(vif); 2144 brcmf_free_vif(vif);
2242} 2145}
2243 2146
@@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
2364 break; 2267 break;
2365 2268
2366 case NL80211_IFTYPE_P2P_DEVICE: 2269 case NL80211_IFTYPE_P2P_DEVICE:
2270 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
2271 brcmf_p2p_deinit_discovery(p2p);
2367 brcmf_p2p_delete_p2pdev(p2p, vif); 2272 brcmf_p2p_delete_p2pdev(p2p, vif);
2368 return 0; 2273 return 0;
2369 default: 2274 default:
@@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
2425 clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state); 2330 clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
2426 mutex_unlock(&cfg->usr_sync); 2331 mutex_unlock(&cfg->usr_sync);
2427} 2332}
2333
2334/**
2335 * brcmf_p2p_attach() - attach for P2P.
2336 *
2337 * @cfg: driver private data for cfg80211 interface.
2338 */
2339s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
2340{
2341 struct brcmf_if *pri_ifp;
2342 struct brcmf_if *p2p_ifp;
2343 struct brcmf_cfg80211_vif *p2p_vif;
2344 struct brcmf_p2p_info *p2p;
2345 struct brcmf_pub *drvr;
2346 s32 bssidx;
2347 s32 err = 0;
2348
2349 p2p = &cfg->p2p;
2350 p2p->cfg = cfg;
2351
2352 drvr = cfg->pub;
2353
2354 pri_ifp = drvr->iflist[0];
2355 p2p_ifp = drvr->iflist[1];
2356
2357 p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
2358
2359 if (p2p_ifp) {
2360 p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
2361 false);
2362 if (IS_ERR(p2p_vif)) {
2363 brcmf_err("could not create discovery vif\n");
2364 err = -ENOMEM;
2365 goto exit;
2366 }
2367
2368 p2p_vif->ifp = p2p_ifp;
2369 p2p_ifp->vif = p2p_vif;
2370 p2p_vif->wdev.netdev = p2p_ifp->ndev;
2371 p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
2372 SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
2373
2374 p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
2375
2376 brcmf_p2p_generate_bss_mac(p2p, NULL);
2377 memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
2378 brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
2379
2380 /* Initialize P2P Discovery in the firmware */
2381 err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
2382 if (err < 0) {
2383 brcmf_err("set p2p_disc error\n");
2384 brcmf_free_vif(p2p_vif);
2385 goto exit;
2386 }
2387 /* obtain bsscfg index for P2P discovery */
2388 err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
2389 if (err < 0) {
2390 brcmf_err("retrieving discover bsscfg index failed\n");
2391 brcmf_free_vif(p2p_vif);
2392 goto exit;
2393 }
2394 /* Verify that firmware uses same bssidx as driver !! */
2395 if (p2p_ifp->bssidx != bssidx) {
2396 brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
2397 bssidx, p2p_ifp->bssidx);
2398 brcmf_free_vif(p2p_vif);
2399 goto exit;
2400 }
2401
2402 init_completion(&p2p->send_af_done);
2403 INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
2404 init_completion(&p2p->afx_hdl.act_frm_scan);
2405 init_completion(&p2p->wait_next_af);
2406 }
2407exit:
2408 return err;
2409}
2410
2411/**
2412 * brcmf_p2p_detach() - detach P2P.
2413 *
2414 * @p2p: P2P specific data.
2415 */
2416void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
2417{
2418 struct brcmf_cfg80211_vif *vif;
2419
2420 vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
2421 if (vif != NULL) {
2422 brcmf_p2p_cancel_remain_on_channel(vif->ifp);
2423 brcmf_p2p_deinit_discovery(p2p);
2424 /* remove discovery interface */
2425 rtnl_lock();
2426 brcmf_p2p_delete_p2pdev(p2p, vif);
2427 rtnl_unlock();
2428 }
2429 /* just set it all to zero */
2430 memset(p2p, 0, sizeof(*p2p));
2431}
2432
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
index 37a2624d7bba..3a98c4306d1d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -1629,20 +1629,7 @@ static void brcmf_pcie_buscore_write32(void *ctx, u32 addr, u32 value)
1629 1629
1630static int brcmf_pcie_buscoreprep(void *ctx) 1630static int brcmf_pcie_buscoreprep(void *ctx)
1631{ 1631{
1632 struct brcmf_pciedev_info *devinfo = (struct brcmf_pciedev_info *)ctx; 1632 return brcmf_pcie_get_resource(ctx);
1633 int err;
1634
1635 err = brcmf_pcie_get_resource(devinfo);
1636 if (err == 0) {
1637 /* Set CC watchdog to reset all the cores on the chip to bring
1638 * back dongle to a sane state.
1639 */
1640 brcmf_pcie_buscore_write32(ctx, CORE_CC_REG(SI_ENUM_BASE,
1641 watchdog), 4);
1642 msleep(100);
1643 }
1644
1645 return err;
1646} 1633}
1647 1634
1648 1635
@@ -1824,6 +1811,7 @@ brcmf_pcie_remove(struct pci_dev *pdev)
1824 brcmf_pcie_intr_disable(devinfo); 1811 brcmf_pcie_intr_disable(devinfo);
1825 1812
1826 brcmf_detach(&pdev->dev); 1813 brcmf_detach(&pdev->dev);
1814 brcmf_pcie_reset_device(devinfo);
1827 1815
1828 kfree(bus->bus_priv.pcie); 1816 kfree(bus->bus_priv.pcie);
1829 kfree(bus->msgbuf->flowrings); 1817 kfree(bus->msgbuf->flowrings);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
index bf7a8b1ad914..d36f5f3d931b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
@@ -2820,6 +2820,8 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
2820 struct brcmf_sdio *bus = sdiodev->bus; 2820 struct brcmf_sdio *bus = sdiodev->bus;
2821 2821
2822 brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len); 2822 brcmf_dbg(TRACE, "Enter: pkt: data %p len %d\n", pkt->data, pkt->len);
2823 if (sdiodev->state != BRCMF_SDIOD_DATA)
2824 return -EIO;
2823 2825
2824 /* Add space for the header */ 2826 /* Add space for the header */
2825 skb_push(pkt, bus->tx_hdrlen); 2827 skb_push(pkt, bus->tx_hdrlen);
@@ -2948,6 +2950,8 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
2948 int ret; 2950 int ret;
2949 2951
2950 brcmf_dbg(TRACE, "Enter\n"); 2952 brcmf_dbg(TRACE, "Enter\n");
2953 if (sdiodev->state != BRCMF_SDIOD_DATA)
2954 return -EIO;
2951 2955
2952 /* Send from dpc */ 2956 /* Send from dpc */
2953 bus->ctrl_frame_buf = msg; 2957 bus->ctrl_frame_buf = msg;
@@ -3238,6 +3242,8 @@ brcmf_sdio_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
3238 struct brcmf_sdio *bus = sdiodev->bus; 3242 struct brcmf_sdio *bus = sdiodev->bus;
3239 3243
3240 brcmf_dbg(TRACE, "Enter\n"); 3244 brcmf_dbg(TRACE, "Enter\n");
3245 if (sdiodev->state != BRCMF_SDIOD_DATA)
3246 return -EIO;
3241 3247
3242 /* Wait until control frame is available */ 3248 /* Wait until control frame is available */
3243 timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending); 3249 timeleft = brcmf_sdio_dcmd_resp_wait(bus, &bus->rxlen, &pending);