diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac')
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 315 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/commonring.c | 19 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/commonring.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/core.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/debug.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/feature.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/feature.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/firmware.c | 50 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | 79 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/p2p.c | 203 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/pcie.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/sdio.c | 6 |
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 | ||
989 | static int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev) | 989 | static 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 | ||
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 | } |
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, | |||
223 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, | 223 | void *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 | ||
249 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring) | 241 | int 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); |
63 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, | 63 | void *brcmf_commonring_get_read_ptr(struct brcmf_commonring *commonring, |
64 | u16 *n_items); | 64 | u16 *n_items); |
65 | int brcmf_commonring_read_complete(struct brcmf_commonring *commonring); | 65 | int 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 | ||
44 | static 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 | |||
53 | int brcmf_debugfs_attach(struct brcmf_pub *drvr) | 44 | int 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 | ||
77 | struct brcmf_debugfs_entry { | ||
78 | int (*read)(struct seq_file *seq, void *data); | ||
79 | struct brcmf_pub *drvr; | ||
80 | }; | ||
81 | |||
82 | static 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 | |||
89 | static 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 | |||
97 | int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, | 67 | int 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 | */ |
56 | struct nvram_parser { | 56 | struct 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 | ||
203 | static int brcmf_init_nvram_parser(struct nvram_parser *nvp, | 203 | static 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 | */ |
359 | static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length, | 365 | static 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 */ |
118 | enum brcmf_join_pref_types { | 123 | enum brcmf_join_pref_types { |
@@ -456,25 +461,61 @@ struct brcmf_channel_info_le { | |||
456 | }; | 461 | }; |
457 | 462 | ||
458 | struct brcmf_sta_info_le { | 463 | struct 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 | ||
480 | struct brcmf_chanspec_list { | 521 | struct 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 | ||
79 | struct msgbuf_common_hdr { | 81 | struct 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 | ||
1261 | again: | 1264 | again: |
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 | */ | ||
1915 | s32 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 | } | ||
1983 | exit: | ||
1984 | return err; | ||
1985 | } | ||
1986 | |||
1987 | |||
1988 | /** | ||
1989 | * brcmf_p2p_detach() - detach P2P. | ||
1990 | * | ||
1991 | * @p2p: P2P specific data. | ||
1992 | */ | ||
1993 | void 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 | */ | ||
2339 | s32 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 | } | ||
2407 | exit: | ||
2408 | return err; | ||
2409 | } | ||
2410 | |||
2411 | /** | ||
2412 | * brcmf_p2p_detach() - detach P2P. | ||
2413 | * | ||
2414 | * @p2p: P2P specific data. | ||
2415 | */ | ||
2416 | void 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 | ||
1630 | static int brcmf_pcie_buscoreprep(void *ctx) | 1630 | static 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); |