diff --git a/[refs] b/[refs] index ac0f25b2a926..7b30234f0266 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c88d0dc1cc0182358ce1ae6f457dace34539eb12 +refs/heads/master: c9f7a8ab7792b48259af6e94706a5d02dd74caef diff --git a/trunk/arch/arm/mach-omap2/board-omap3evm.c b/trunk/arch/arm/mach-omap2/board-omap3evm.c index a4ca63ba7faa..3985f35aee06 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3evm.c +++ b/trunk/arch/arm/mach-omap2/board-omap3evm.c @@ -309,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] = { .gpio_wp = 63, .deferred = true, }, -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA { .name = "wl1271", .mmc = 2, @@ -450,7 +450,7 @@ static struct regulator_init_data omap3evm_vio = { .consumer_supplies = omap3evm_vio_supply, }; -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA #define OMAP3EVM_WLAN_PMENA_GPIO (150) #define OMAP3EVM_WLAN_IRQ_GPIO (149) @@ -563,7 +563,7 @@ static struct omap_board_mux omap35x_board_mux[] __initdata = { OMAP_PIN_OFF_NONE), OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_NONE), -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA /* WLAN IRQ - GPIO 149 */ OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), @@ -601,7 +601,7 @@ static struct omap_board_mux omap36x_board_mux[] __initdata = { OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE), -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA /* WLAN IRQ - GPIO 149 */ OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), @@ -637,7 +637,7 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = { static void __init omap3_evm_wl12xx_init(void) { -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA int ret; /* WL12xx WLAN Init */ diff --git a/trunk/drivers/bcma/driver_chipcommon_nflash.c b/trunk/drivers/bcma/driver_chipcommon_nflash.c index 19fafcf78840..dbda91e4dff5 100644 --- a/trunk/drivers/bcma/driver_chipcommon_nflash.c +++ b/trunk/drivers/bcma/driver_chipcommon_nflash.c @@ -5,11 +5,11 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include "bcma_private.h" - #include #include +#include "bcma_private.h" + struct platform_device bcma_nflash_dev = { .name = "bcma_nflash", .num_resources = 0, diff --git a/trunk/drivers/bcma/driver_chipcommon_sflash.c b/trunk/drivers/bcma/driver_chipcommon_sflash.c index e6ed4fe5dced..1e694db4532d 100644 --- a/trunk/drivers/bcma/driver_chipcommon_sflash.c +++ b/trunk/drivers/bcma/driver_chipcommon_sflash.c @@ -5,11 +5,11 @@ * Licensed under the GNU/GPL. See COPYING for details. */ -#include "bcma_private.h" - #include #include +#include "bcma_private.h" + static struct resource bcma_sflash_resource = { .name = "bcma_sflash", .start = BCMA_SOC_FLASH2, diff --git a/trunk/drivers/net/wireless/ath/ath5k/phy.c b/trunk/drivers/net/wireless/ath/ath5k/phy.c index a78afa98c650..ab363f34b4df 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/phy.c +++ b/trunk/drivers/net/wireless/ath/ath5k/phy.c @@ -1613,10 +1613,6 @@ ath5k_hw_update_noise_floor(struct ath5k_hw *ah) ah->ah_cal_mask |= AR5K_CALIBRATION_NF; ee_mode = ath5k_eeprom_mode_from_channel(ah->ah_current_channel); - if (WARN_ON(ee_mode < 0)) { - ah->ah_cal_mask &= ~AR5K_CALIBRATION_NF; - return; - } /* completed NF calibration, test threshold */ nf = ath5k_hw_read_measured_noise_floor(ah); diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c index e2d8b2cf19eb..4084b1076286 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reset.c +++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c @@ -985,8 +985,6 @@ ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, return; ee_mode = ath5k_eeprom_mode_from_channel(channel); - if (WARN_ON(ee_mode < 0)) - return; /* Adjust power delta for channel 14 */ if (channel->center_freq == 2484) diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index a29f04e30830..4225cca0f198 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -767,7 +767,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", nw_type & ADHOC_CREATOR ? "creator" : "joiner"); cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); - cfg80211_put_bss(ar->wiphy, bss); + cfg80211_put_bss(bss); return; } @@ -778,7 +778,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, assoc_req_ie, assoc_req_len, assoc_resp_ie, assoc_resp_len, WLAN_STATUS_SUCCESS, GFP_KERNEL); - cfg80211_put_bss(ar->wiphy, bss); + cfg80211_put_bss(bss); } else if (vif->sme_state == SME_CONNECTED) { /* inform roam event to cfg80211 */ cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, @@ -1778,14 +1778,14 @@ static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev, if (vif->target_stats.rx_byte) { sinfo->rx_bytes = vif->target_stats.rx_byte; - sinfo->filled |= STATION_INFO_RX_BYTES64; + sinfo->filled |= STATION_INFO_RX_BYTES; sinfo->rx_packets = vif->target_stats.rx_pkt; sinfo->filled |= STATION_INFO_RX_PACKETS; } if (vif->target_stats.tx_byte) { sinfo->tx_bytes = vif->target_stats.tx_byte; - sinfo->filled |= STATION_INFO_TX_BYTES64; + sinfo->filled |= STATION_INFO_TX_BYTES; sinfo->tx_packets = vif->target_stats.tx_pkt; sinfo->filled |= STATION_INFO_TX_PACKETS; } diff --git a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c index d366cf105c7c..998f8b0f62fd 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1108,7 +1108,7 @@ static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len, kfree(mgmt); if (bss == NULL) return -ENOMEM; - cfg80211_put_bss(ar->wiphy, bss); + cfg80211_put_bss(bss); /* * Firmware doesn't return any event when scheduled scan has diff --git a/trunk/drivers/net/wireless/ath/ath9k/Kconfig b/trunk/drivers/net/wireless/ath/ath9k/Kconfig index 17507dc8a1e7..7647ed6b73d7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath9k/Kconfig @@ -58,7 +58,6 @@ config ATH9K_DEBUGFS bool "Atheros ath9k debugging" depends on ATH9K select MAC80211_DEBUGFS - select RELAY ---help--- Say Y, if you need access to ath9k's statistics for interrupts, rate control, etc. diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index a56b2416e2f9..67df8644fef6 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -319,8 +319,6 @@ struct ath_rx { struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; struct sk_buff *frag; - - u32 ampdu_ref; }; int ath_startrecv(struct ath_softc *sc); @@ -389,7 +387,6 @@ struct ath_beacon_config { u16 bmiss_timeout; u8 dtim_count; bool enable_beacon; - bool ibss_creator; }; struct ath_beacon { @@ -872,7 +869,7 @@ enum ath_fft_sample_type { struct fft_sample_tlv { u8 type; /* see ath_fft_sample */ - __be16 length; + u16 length; /* type dependent data follows */ } __packed; @@ -881,15 +878,15 @@ struct fft_sample_ht20 { u8 max_exp; - __be16 freq; + u16 freq; s8 rssi; s8 noise; - __be16 max_magnitude; + u16 max_magnitude; u8 max_index; u8 bitmap_weight; - __be64 tsf; + u64 tsf; u8 data[SPECTRAL_HT20_NUM_BINS]; } __packed; diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 5f05c26d1ec4..dd3771954bd7 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -407,17 +407,12 @@ void ath9k_beacon_tasklet(unsigned long data) } } -/* - * Both nexttbtt and intval have to be in usecs. - */ -static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, - u32 intval, bool reset_tsf) +static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval) { struct ath_hw *ah = sc->sc_ah; ath9k_hw_disable_interrupts(ah); - if (reset_tsf) - ath9k_hw_reset_tsf(ah); + ath9k_hw_reset_tsf(ah); ath9k_beaconq_config(sc); ath9k_hw_beaconinit(ah, nexttbtt, intval); sc->beacon.bmisscnt = 0; @@ -447,12 +442,10 @@ static void ath9k_beacon_config_ap(struct ath_softc *sc, else ah->imask &= ~ATH9K_INT_SWBA; - ath_dbg(common, BEACON, - "AP (%s) nexttbtt: %u intval: %u conf_intval: %u\n", - (conf->enable_beacon) ? "Enable" : "Disable", + ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n", nexttbtt, intval, conf->beacon_interval); - ath9k_beacon_init(sc, nexttbtt, intval, true); + ath9k_beacon_init(sc, nexttbtt, intval); } /* @@ -593,45 +586,17 @@ static void ath9k_beacon_config_adhoc(struct ath_softc *sc, ath9k_reset_beacon_status(sc); intval = TU_TO_USEC(conf->beacon_interval); - - if (conf->ibss_creator) { - nexttbtt = intval; - } else { - u32 tbtt, offset, tsftu; - u64 tsf; - - /* - * Pull nexttbtt forward to reflect the current - * sync'd TSF. - */ - tsf = ath9k_hw_gettsf64(ah); - tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; - offset = tsftu % conf->beacon_interval; - tbtt = tsftu - offset; - if (offset) - tbtt += conf->beacon_interval; - - nexttbtt = TU_TO_USEC(tbtt); - } + nexttbtt = intval; if (conf->enable_beacon) ah->imask |= ATH9K_INT_SWBA; else ah->imask &= ~ATH9K_INT_SWBA; - ath_dbg(common, BEACON, - "IBSS (%s) nexttbtt: %u intval: %u conf_intval: %u\n", - (conf->enable_beacon) ? "Enable" : "Disable", + ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n", nexttbtt, intval, conf->beacon_interval); - ath9k_beacon_init(sc, nexttbtt, intval, conf->ibss_creator); - - /* - * Set the global 'beacon has been configured' flag for the - * joiner case in IBSS mode. - */ - if (!conf->ibss_creator && conf->enable_beacon) - set_bit(SC_OP_BEACONS, &sc->sc_flags); + ath9k_beacon_init(sc, nexttbtt, intval); } bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) @@ -674,7 +639,6 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc, cur_conf->dtim_period = bss_conf->dtim_period; cur_conf->listen_interval = 1; cur_conf->dtim_count = 1; - cur_conf->ibss_creator = bss_conf->ibss_creator; cur_conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; @@ -702,59 +666,34 @@ void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif, { struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - unsigned long flags; - bool skip_beacon = false; if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) { ath9k_cache_beacon_config(sc, bss_conf); ath9k_set_beacon(sc); set_bit(SC_OP_BEACONS, &sc->sc_flags); - return; - - } - - /* - * Take care of multiple interfaces when - * enabling/disabling SWBA. - */ - if (changed & BSS_CHANGED_BEACON_ENABLED) { - if (!bss_conf->enable_beacon && - (sc->nbcnvifs <= 1)) { - cur_conf->enable_beacon = false; - } else if (bss_conf->enable_beacon) { - cur_conf->enable_beacon = true; - ath9k_cache_beacon_config(sc, bss_conf); - } - } - - /* - * Configure the HW beacon registers only when we have a valid - * beacon interval. - */ - if (cur_conf->beacon_interval) { + } else { /* - * If we are joining an existing IBSS network, start beaconing - * only after a TSF-sync has taken place. Ensure that this - * happens by setting the appropriate flags. + * Take care of multiple interfaces when + * enabling/disabling SWBA. */ - if ((changed & BSS_CHANGED_IBSS) && !bss_conf->ibss_creator && - bss_conf->enable_beacon) { - spin_lock_irqsave(&sc->sc_pm_lock, flags); - sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); - skip_beacon = true; - } else { - ath9k_set_beacon(sc); + if (changed & BSS_CHANGED_BEACON_ENABLED) { + if (!bss_conf->enable_beacon && + (sc->nbcnvifs <= 1)) { + cur_conf->enable_beacon = false; + } else if (bss_conf->enable_beacon) { + cur_conf->enable_beacon = true; + ath9k_cache_beacon_config(sc, bss_conf); + } } - /* - * Do not set the SC_OP_BEACONS flag for IBSS joiner mode - * here, it is done in ath9k_beacon_config_adhoc(). - */ - if (cur_conf->enable_beacon && !skip_beacon) - set_bit(SC_OP_BEACONS, &sc->sc_flags); - else - clear_bit(SC_OP_BEACONS, &sc->sc_flags); + if (cur_conf->beacon_interval) { + ath9k_set_beacon(sc); + + if (cur_conf->enable_beacon) + set_bit(SC_OP_BEACONS, &sc->sc_flags); + else + clear_bit(SC_OP_BEACONS, &sc->sc_flags); + } } } diff --git a/trunk/drivers/net/wireless/ath/ath9k/init.c b/trunk/drivers/net/wireless/ath/ath9k/init.c index af932c9444de..c7d116c2c615 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/init.c +++ b/trunk/drivers/net/wireless/ath/ath9k/init.c @@ -922,7 +922,7 @@ static void ath9k_deinit_softc(struct ath_softc *sc) ath9k_eeprom_release(sc); - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { + if (sc->rfs_chan_spec_scan) { relay_close(sc->rfs_chan_spec_scan); sc->rfs_chan_spec_scan = NULL; } diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index 6e66f9c6782b..5432f1247e2e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -320,25 +320,28 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, struct ieee80211_vif *vif) { struct ath_node *an; + u8 density; an = (struct ath_node *)sta->drv_priv; an->sc = sc; an->sta = sta; an->vif = vif; - ath_tx_node_init(sc, an); - - if (sta->ht_cap.ht_supported) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { + ath_tx_node_init(sc, an); an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); - an->mpdudensity = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); + density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); + an->mpdudensity = density; } } static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) { struct ath_node *an = (struct ath_node *)sta->drv_priv; - ath_tx_node_cleanup(sc, an); + + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) + ath_tx_node_cleanup(sc, an); } void ath9k_tasklet(unsigned long data) diff --git a/trunk/drivers/net/wireless/ath/ath9k/mci.c b/trunk/drivers/net/wireless/ath/ath9k/mci.c index 815bee21c19a..d2074334ec9b 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/mci.c +++ b/trunk/drivers/net/wireless/ath/ath9k/mci.c @@ -474,6 +474,8 @@ void ath_mci_cleanup(struct ath_softc *sc) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_hw *ah = sc->sc_ah; + struct ath_mci_coex *mci = &sc->mci_coex; + struct ath_mci_buf *buf = &mci->sched_buf; ar9003_mci_cleanup(ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index ee156e543147..2af6f19d2d2a 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -533,7 +533,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) if (sc->ps_flags & PS_BEACON_SYNC) { sc->ps_flags &= ~PS_BEACON_SYNC; ath_dbg(common, PS, - "Reconfigure beacon timers based on synchronized timestamp\n"); + "Reconfigure Beacon timers based on timestamp from the AP\n"); ath9k_set_beacon(sc); } @@ -1016,20 +1016,18 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common, rxs->flag &= ~RX_FLAG_DECRYPTED; } -#ifdef CONFIG_ATH9K_DEBUGFS static s8 fix_rssi_inv_only(u8 rssi_val) { if (rssi_val == 128) rssi_val = 0; return (s8) rssi_val; } -#endif /* returns 1 if this was a spectral frame, even if not handled. */ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf) { -#ifdef CONFIG_ATH9K_DEBUGFS +#ifdef CONFIG_ATH_DEBUG struct ath_hw *ah = sc->sc_ah; u8 bins[SPECTRAL_HT20_NUM_BINS]; u8 *vdata = (u8 *)hdr; @@ -1038,7 +1036,6 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, struct ath_ht20_mag_info *mag_info; int len = rs->rs_datalen; int dc_pos; - u16 length, max_magnitude; /* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer * via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT @@ -1066,8 +1063,8 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, return 1; fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20; - length = sizeof(fft_sample) - sizeof(fft_sample.tlv); - fft_sample.tlv.length = __cpu_to_be16(length); + fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv); + fft_sample.tlv.length = __cpu_to_be16(fft_sample.tlv.length); fft_sample.freq = __cpu_to_be16(ah->curchan->chan->center_freq); fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0); @@ -1113,8 +1110,8 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, memcpy(fft_sample.data, bins, SPECTRAL_HT20_NUM_BINS); fft_sample.max_exp = mag_info->max_exp & 0xf; - max_magnitude = spectral_max_magnitude(mag_info->all_bins); - fft_sample.max_magnitude = __cpu_to_be16(max_magnitude); + fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins); + fft_sample.max_magnitude = __cpu_to_be16(fft_sample.max_magnitude); fft_sample.max_index = spectral_max_index(mag_info->all_bins); fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins); fft_sample.tsf = __cpu_to_be64(tsf); @@ -1126,24 +1123,6 @@ static int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, #endif } -static void ath9k_apply_ampdu_details(struct ath_softc *sc, - struct ath_rx_status *rs, struct ieee80211_rx_status *rxs) -{ - if (rs->rs_isaggr) { - rxs->flag |= RX_FLAG_AMPDU_DETAILS | RX_FLAG_AMPDU_LAST_KNOWN; - - rxs->ampdu_reference = sc->rx.ampdu_ref; - - if (!rs->rs_moreaggr) { - rxs->flag |= RX_FLAG_AMPDU_IS_LAST; - sc->rx.ampdu_ref++; - } - - if (rs->rs_flags & ATH9K_RX_DELIM_CRC_PRE) - rxs->flag |= RX_FLAG_AMPDU_DELIM_CRC_ERROR; - } -} - int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) { struct ath_buf *bf; @@ -1350,8 +1329,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if ((ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) && sc->ant_rx == 3) ath_ant_comb_scan(sc, &rs); - ath9k_apply_ampdu_details(sc, &rs, rxs); - ieee80211_rx(hw, skb); requeue_drop_frag: diff --git a/trunk/drivers/net/wireless/ath/ath9k/xmit.c b/trunk/drivers/net/wireless/ath/ath9k/xmit.c index 89a64411b82e..feacaafee959 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/xmit.c +++ b/trunk/drivers/net/wireless/ath/ath9k/xmit.c @@ -1233,7 +1233,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, * in HT IBSS when a beacon with HT-info is received after the station * has already been added. */ - if (sta->ht_cap.ht_supported) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + sta->ht_cap.ampdu_factor); density = ath9k_parse_mpdudensity(sta->ht_cap.ampdu_density); @@ -1904,7 +1904,8 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, struct ath_buf *bf; u8 tidno; - if (txctl->an && ieee80211_is_data_qos(hdr->frame_control)) { + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an && + ieee80211_is_data_qos(hdr->frame_control)) { tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(txctl->an, tidno); diff --git a/trunk/drivers/net/wireless/ath/carl9170/main.c b/trunk/drivers/net/wireless/ath/carl9170/main.c index f293b3ff4756..ef82751722e0 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/main.c +++ b/trunk/drivers/net/wireless/ath/carl9170/main.c @@ -1853,7 +1853,7 @@ void *carl9170_alloc(size_t priv_size) IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SIGNAL_DBM; if (!modparam_noht) { diff --git a/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c b/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c index 9ecc1968262c..002851fceb2f 100644 --- a/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -341,7 +341,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, } out: - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); return rc; } diff --git a/trunk/drivers/net/wireless/ath/wil6210/wmi.c b/trunk/drivers/net/wireless/ath/wil6210/wmi.c index 79d608caa903..0b70e17cd1fb 100644 --- a/trunk/drivers/net/wireless/ath/wil6210/wmi.c +++ b/trunk/drivers/net/wireless/ath/wil6210/wmi.c @@ -338,7 +338,7 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) if (bss) { wil_dbg_wmi(wil, "Added BSS %pM\n", rx_mgmt_frame->bssid); - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); } else { wil_err(wil, "cfg80211_inform_bss() failed\n"); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 756e19fc2795..1a6661a9f008 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -26,7 +26,6 @@ brcmfmac-objs += \ wl_cfg80211.o \ fwil.o \ fweh.o \ - p2p.o \ dhd_cdc.o \ dhd_common.o \ dhd_linux.o @@ -38,4 +37,4 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ usb.o brcmfmac-$(CONFIG_BRCMDBG) += \ - dhd_dbg.o + dhd_dbg.o \ No newline at end of file diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index ef6f23be6d32..a2f32fb990fa 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -72,7 +72,6 @@ #define BRCMF_C_SET_WSEC 134 #define BRCMF_C_GET_PHY_NOISE 135 #define BRCMF_C_GET_BSS_INFO 136 -#define BRCMF_C_SET_SCB_TIMEOUT 158 #define BRCMF_C_GET_PHYLIST 180 #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 @@ -150,7 +149,6 @@ #define BRCMF_E_REASON_MINTXRATE 9 #define BRCMF_E_REASON_TXFAIL 10 -#define BRCMF_E_REASON_LINK_BSSCFG_DIS 4 #define BRCMF_E_REASON_FAST_ROAM_FAILED 5 #define BRCMF_E_REASON_DIRECTED_ROAM 6 #define BRCMF_E_REASON_TSPEC_REJECTED 7 @@ -377,28 +375,6 @@ struct brcmf_join_params { struct brcmf_assoc_params_le params_le; }; -/* scan params for extended join */ -struct brcmf_join_scan_params_le { - u8 scan_type; /* 0 use default, active or passive scan */ - __le32 nprobes; /* -1 use default, nr of probes per channel */ - __le32 active_time; /* -1 use default, dwell time per channel for - * active scanning - */ - __le32 passive_time; /* -1 use default, dwell time per channel - * for passive scanning - */ - __le32 home_time; /* -1 use default, dwell time for the home - * channel between channel scans - */ -}; - -/* extended join params */ -struct brcmf_ext_join_params_le { - struct brcmf_ssid_le ssid_le; /* {0, ""}: wildcard scan */ - struct brcmf_join_scan_params_le scan_le; - struct brcmf_assoc_params_le assoc_le; -}; - struct brcmf_wsec_key { u32 index; /* key index */ u32 len; /* key length */ @@ -475,19 +451,6 @@ struct brcmf_sta_info_le { __le32 rx_decrypt_failures; /* # of packet decrypted failed */ }; -/* - * WLC_E_PROBRESP_MSG - * WLC_E_P2P_PROBREQ_MSG - * WLC_E_ACTION_FRAME_RX - */ -struct brcmf_rx_mgmt_data { - __be16 version; - __be16 chanspec; - __be32 rssi; - __be32 mactime; - __be32 rate; -}; - /* Bus independent dongle command */ struct brcmf_dcmd { uint cmd; /* common dongle cmd definition */ @@ -526,6 +489,9 @@ struct brcmf_pub { struct mutex proto_block; unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; + atomic_t pend_8021x_cnt; + wait_queue_head_t pend_8021x_wait; + struct brcmf_fweh_info fweh; #ifdef DEBUG struct dentry *dbgfs_dir; @@ -549,11 +515,9 @@ struct brcmf_cfg80211_vif; * @vif: points to cfg80211 specific interface information. * @ndev: associated network device. * @stats: interface specific network statistics. - * @ifidx: interface index in device firmware. + * @idx: interface index in device firmware. * @bssidx: index of bss associated with this interface. * @mac_addr: assigned mac address. - * @pend_8021x_cnt: tracks outstanding number of 802.1x frames. - * @pend_8021x_wait: used for signalling change in count. */ struct brcmf_if { struct brcmf_pub *drvr; @@ -562,11 +526,9 @@ struct brcmf_if { struct net_device_stats stats; struct work_struct setmacaddr_work; struct work_struct multicast_work; - int ifidx; + int idx; s32 bssidx; u8 mac_addr[ETH_ALEN]; - atomic_t pend_8021x_cnt; - wait_queue_head_t pend_8021x_wait; }; @@ -585,10 +547,9 @@ extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, struct sk_buff *rxp); -extern int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); -extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, - s32 ifidx, char *name, u8 *mac_addr); -extern void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx); -extern u32 brcmf_get_chip_info(struct brcmf_if *ifp); +extern int brcmf_net_attach(struct brcmf_if *ifp); +extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, + s32 bssidx, char *name, u8 *mac_addr); +extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); #endif /* _BRCMF_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index ad25c3408b59..64c38f4226a3 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -24,6 +24,18 @@ enum brcmf_bus_state { BRCMF_BUS_DATA /* Ready for frame transfers */ }; +struct dngl_stats { + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* packets dropped by dongle */ + unsigned long tx_dropped; /* packets dropped by dongle */ + unsigned long multicast; /* multicast packets received */ +}; + struct brcmf_bus_dcmd { char *name; char *param; @@ -60,12 +72,11 @@ struct brcmf_bus_ops { * @drvr: public driver information. * @state: operational state of the bus interface. * @maxctl: maximum size for rxctl request message. + * @drvr_up: indicates driver up/down status. * @tx_realloc: number of tx packets realloced for headroom. * @dstats: dongle-based statistical data. * @align: alignment requirement for the bus. * @dcmd_list: bus/device specific dongle initialization commands. - * @chip: device identifier of the dongle chip. - * @chiprev: revision of the dongle chip. */ struct brcmf_bus { union { @@ -76,10 +87,10 @@ struct brcmf_bus { struct brcmf_pub *drvr; enum brcmf_bus_state state; uint maxctl; + bool drvr_up; unsigned long tx_realloc; + struct dngl_stats dstats; u8 align; - u32 chip; - u32 chiprev; struct list_head dcmd_list; struct brcmf_bus_ops *ops; diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a2354d951dd7..bb454cdab29d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -303,14 +303,6 @@ int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx, brcmf_err("rx data ifnum out of range (%d)\n", *ifidx); return -EBADE; } - /* The ifidx is the idx to map to matching netdev/ifp. When receiving - * events this is easy because it contains the bssidx which maps - * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. - * bssidx 1 is used for p2p0 and no data can be received or - * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 - */ - if (*ifidx) - (*ifidx)++; if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index 6e3846ca88be..e3326a58bdb1 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -26,8 +26,6 @@ #include "dhd_bus.h" #include "dhd_proto.h" #include "dhd_dbg.h" -#include "fwil_types.h" -#include "p2p.h" #include "wl_cfg80211.h" #include "fwil.h" @@ -42,12 +40,6 @@ MODULE_LICENSE("Dual BSD/GPL"); int brcmf_msg_level; module_param(brcmf_msg_level, int, 0); -/* P2P0 enable */ -static int brcmf_p2p_enable; -#ifdef CONFIG_BRCMDBG -module_param_named(p2pon, brcmf_p2p_enable, int, 0); -MODULE_PARM_DESC(p2pon, "enable p2p management functionality"); -#endif char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) { @@ -78,10 +70,9 @@ static void _brcmf_set_multicast_list(struct work_struct *work) u32 buflen; s32 err; - ifp = container_of(work, struct brcmf_if, multicast_work); - - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(TRACE, "enter\n"); + ifp = container_of(work, struct brcmf_if, multicast_work); ndev = ifp->ndev; /* Determine initial value of allmulti flag */ @@ -138,10 +129,9 @@ _brcmf_set_mac_address(struct work_struct *work) struct brcmf_if *ifp; s32 err; - ifp = container_of(work, struct brcmf_if, setmacaddr_work); - - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(TRACE, "enter\n"); + ifp = container_of(work, struct brcmf_if, setmacaddr_work); err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr, ETH_ALEN); if (err < 0) { @@ -178,7 +168,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, struct brcmf_pub *drvr = ifp->drvr; struct ethhdr *eh; - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(TRACE, "Enter\n"); /* Can the device send data? */ if (drvr->bus_if->state != BRCMF_BUS_DATA) { @@ -189,8 +179,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } - if (!drvr->iflist[ifp->bssidx]) { - brcmf_err("bad ifidx %d\n", ifp->bssidx); + if (!drvr->iflist[ifp->idx]) { + brcmf_err("bad ifidx %d\n", ifp->idx); netif_stop_queue(ndev); dev_kfree_skb(skb); ret = -ENODEV; @@ -202,14 +192,14 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, struct sk_buff *skb2; brcmf_dbg(INFO, "%s: insufficient headroom\n", - brcmf_ifname(drvr, ifp->bssidx)); + brcmf_ifname(drvr, ifp->idx)); drvr->bus_if->tx_realloc++; skb2 = skb_realloc_headroom(skb, drvr->hdrlen); dev_kfree_skb(skb); skb = skb2; if (skb == NULL) { brcmf_err("%s: skb_realloc_headroom failed\n", - brcmf_ifname(drvr, ifp->bssidx)); + brcmf_ifname(drvr, ifp->idx)); ret = -ENOMEM; goto done; } @@ -227,21 +217,19 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, if (is_multicast_ether_addr(eh->h_dest)) drvr->tx_multicast++; if (ntohs(eh->h_proto) == ETH_P_PAE) - atomic_inc(&ifp->pend_8021x_cnt); + atomic_inc(&drvr->pend_8021x_cnt); /* If the protocol uses a data header, apply it */ - brcmf_proto_hdrpush(drvr, ifp->ifidx, skb); + brcmf_proto_hdrpush(drvr, ifp->idx, skb); /* Use bus module to send data frame */ ret = brcmf_bus_txdata(drvr->bus_if, skb); done: - if (ret) { - ifp->stats.tx_dropped++; - } else { - ifp->stats.tx_packets++; - ifp->stats.tx_bytes += skb->len; - } + if (ret) + drvr->bus_if->dstats.tx_dropped++; + else + drvr->bus_if->dstats.tx_packets++; /* Return ok: we always eat the packet */ return NETDEV_TX_OK; @@ -282,13 +270,12 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) skb_queue_walk_safe(skb_list, skb, pnext) { skb_unlink(skb, skb_list); - /* process and remove protocol-specific header */ + /* process and remove protocol-specific header + */ ret = brcmf_proto_hdrpull(drvr, &ifidx, skb); - ifp = drvr->iflist[ifidx]; - - if (ret || !ifp || !ifp->ndev) { - if ((ret != -ENODATA) && ifp) - ifp->stats.rx_errors++; + if (ret < 0) { + if (ret != -ENODATA) + bus_if->dstats.rx_errors++; brcmu_pkt_buf_free_skb(skb); continue; } @@ -308,11 +295,21 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) eth = skb->data; len = skb->len; + ifp = drvr->iflist[ifidx]; + if (ifp == NULL) + ifp = drvr->iflist[0]; + + if (!ifp || !ifp->ndev || + ifp->ndev->reg_state != NETREG_REGISTERED) { + brcmu_pkt_buf_free_skb(skb); + continue; + } + skb->dev = ifp->ndev; skb->protocol = eth_type_trans(skb, skb->dev); if (skb->pkt_type == PACKET_MULTICAST) - ifp->stats.multicast++; + bus_if->dstats.multicast++; skb->data = eth; skb->len = len; @@ -328,13 +325,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list) ifp->ndev->last_rx = jiffies; } - if (!(ifp->ndev->flags & IFF_UP)) { - brcmu_pkt_buf_free_skb(skb); - continue; - } - - ifp->stats.rx_bytes += skb->len; - ifp->stats.rx_packets++; + bus_if->dstats.rx_bytes += skb->len; + bus_if->dstats.rx_packets++; /* Local count */ if (in_interrupt()) netif_rx(skb); @@ -356,31 +348,36 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success) u16 type; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; - struct brcmf_if *ifp; brcmf_proto_hdrpull(drvr, &ifidx, txp); - ifp = drvr->iflist[ifidx]; - if (!ifp) - return; - eh = (struct ethhdr *)(txp->data); type = ntohs(eh->h_proto); if (type == ETH_P_PAE) { - atomic_dec(&ifp->pend_8021x_cnt); - if (waitqueue_active(&ifp->pend_8021x_wait)) - wake_up(&ifp->pend_8021x_wait); + atomic_dec(&drvr->pend_8021x_cnt); + if (waitqueue_active(&drvr->pend_8021x_wait)) + wake_up(&drvr->pend_8021x_wait); } - if (!success) - ifp->stats.tx_errors++; } static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_bus *bus_if = ifp->drvr->bus_if; + + brcmf_dbg(TRACE, "Enter\n"); - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + /* Copy dongle stats to net device stats */ + ifp->stats.rx_packets = bus_if->dstats.rx_packets; + ifp->stats.tx_packets = bus_if->dstats.tx_packets; + ifp->stats.rx_bytes = bus_if->dstats.rx_bytes; + ifp->stats.tx_bytes = bus_if->dstats.tx_bytes; + ifp->stats.rx_errors = bus_if->dstats.rx_errors; + ifp->stats.tx_errors = bus_if->dstats.tx_errors; + ifp->stats.rx_dropped = bus_if->dstats.rx_dropped; + ifp->stats.tx_dropped = bus_if->dstats.tx_dropped; + ifp->stats.multicast = bus_if->dstats.multicast; return &ifp->stats; } @@ -432,7 +429,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) u32 toe_cmpnt, csum_dir; int ret; - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(TRACE, "Enter\n"); /* all ethtool calls start with a cmd word */ if (copy_from_user(&cmd, uaddr, sizeof(u32))) @@ -455,7 +452,13 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr) sprintf(info.driver, "dhd"); strcpy(info.version, BRCMF_VERSION_STR); } - /* report dongle driver type */ + + /* otherwise, require dongle to be up */ + else if (!drvr->bus_if->drvr_up) { + brcmf_err("dongle is not up\n"); + return -ENODEV; + } + /* finally, report dongle driver type */ else sprintf(info.driver, "wl"); @@ -529,9 +532,9 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; - brcmf_dbg(TRACE, "Enter, idx=%d, cmd=0x%04x\n", ifp->bssidx, cmd); + brcmf_dbg(TRACE, "ifidx %d, cmd 0x%04x\n", ifp->idx, cmd); - if (!drvr->iflist[ifp->bssidx]) + if (!drvr->iflist[ifp->idx]) return -1; if (cmd == SIOCETHTOOL) @@ -543,12 +546,17 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, static int brcmf_netdev_stop(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; + + brcmf_dbg(TRACE, "Enter\n"); - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + if (drvr->bus_if->drvr_up == 0) + return 0; brcmf_cfg80211_down(ndev); /* Set state and stop OS transmissions */ + drvr->bus_if->drvr_up = false; netif_stop_queue(ndev); return 0; @@ -562,7 +570,7 @@ static int brcmf_netdev_open(struct net_device *ndev) u32 toe_ol; s32 ret = 0; - brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); + brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); /* If bus is not ready, can't continue */ if (bus_if->state != BRCMF_BUS_DATA) { @@ -570,7 +578,9 @@ static int brcmf_netdev_open(struct net_device *ndev) return -EAGAIN; } - atomic_set(&ifp->pend_8021x_cnt, 0); + atomic_set(&drvr->pend_8021x_cnt, 0); + + memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN); /* Get current TOE mode from dongle */ if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0 @@ -581,6 +591,7 @@ static int brcmf_netdev_open(struct net_device *ndev) /* Allow transmit calls */ netif_start_queue(ndev); + drvr->bus_if->drvr_up = true; if (brcmf_cfg80211_up(ndev)) { brcmf_err("failed to bring up cfg80211\n"); return -1; @@ -599,18 +610,29 @@ static const struct net_device_ops brcmf_netdev_ops_pri = { .ndo_set_rx_mode = brcmf_netdev_set_multicast_list }; -int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) +static const struct net_device_ops brcmf_netdev_ops_virt = { + .ndo_open = brcmf_cfg80211_up, + .ndo_stop = brcmf_cfg80211_down, + .ndo_get_stats = brcmf_netdev_get_stats, + .ndo_do_ioctl = brcmf_netdev_ioctl_entry, + .ndo_start_xmit = brcmf_netdev_start_xmit, + .ndo_set_mac_address = brcmf_netdev_set_mac_address, + .ndo_set_rx_mode = brcmf_netdev_set_multicast_list +}; + +int brcmf_net_attach(struct brcmf_if *ifp) { struct brcmf_pub *drvr = ifp->drvr; struct net_device *ndev; - s32 err; - brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx, - ifp->mac_addr); + brcmf_dbg(TRACE, "ifidx %d mac %pM\n", ifp->idx, ifp->mac_addr); ndev = ifp->ndev; /* set appropriate operations */ - ndev->netdev_ops = &brcmf_netdev_ops_pri; + if (!ifp->idx) + ndev->netdev_ops = &brcmf_netdev_ops_pri; + else + ndev->netdev_ops = &brcmf_netdev_ops_virt; ndev->hard_header_len = ETH_HLEN + drvr->hdrlen; ndev->ethtool_ops = &brcmf_ethtool_ops; @@ -621,14 +643,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) /* set the mac address */ memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); - INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address); - INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list); - - if (rtnl_locked) - err = register_netdevice(ndev); - else - err = register_netdev(ndev); - if (err != 0) { + if (register_netdev(ndev) != 0) { brcmf_err("couldn't register the net device\n"); goto fail; } @@ -642,78 +657,16 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) return -EBADE; } -static int brcmf_net_p2p_open(struct net_device *ndev) -{ - brcmf_dbg(TRACE, "Enter\n"); - - return brcmf_cfg80211_up(ndev); -} - -static int brcmf_net_p2p_stop(struct net_device *ndev) -{ - brcmf_dbg(TRACE, "Enter\n"); - - return brcmf_cfg80211_down(ndev); -} - -static int brcmf_net_p2p_do_ioctl(struct net_device *ndev, - struct ifreq *ifr, int cmd) -{ - brcmf_dbg(TRACE, "Enter\n"); - return 0; -} - -static netdev_tx_t brcmf_net_p2p_start_xmit(struct sk_buff *skb, - struct net_device *ndev) -{ - if (skb) - dev_kfree_skb_any(skb); - - return NETDEV_TX_OK; -} - -static const struct net_device_ops brcmf_netdev_ops_p2p = { - .ndo_open = brcmf_net_p2p_open, - .ndo_stop = brcmf_net_p2p_stop, - .ndo_do_ioctl = brcmf_net_p2p_do_ioctl, - .ndo_start_xmit = brcmf_net_p2p_start_xmit -}; - -static int brcmf_net_p2p_attach(struct brcmf_if *ifp) -{ - struct net_device *ndev; - - brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx, - ifp->mac_addr); - ndev = ifp->ndev; - - ndev->netdev_ops = &brcmf_netdev_ops_p2p; - - /* set the mac address */ - memcpy(ndev->dev_addr, ifp->mac_addr, ETH_ALEN); - - if (register_netdev(ndev) != 0) { - brcmf_err("couldn't register the p2p net device\n"); - goto fail; - } - - brcmf_dbg(INFO, "%s: Broadcom Dongle Host Driver\n", ndev->name); - - return 0; - -fail: - return -EBADE; -} - -struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, - char *name, u8 *mac_addr) +struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx, s32 bssidx, + char *name, u8 *addr_mask) { struct brcmf_if *ifp; struct net_device *ndev; + int i; - brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx); + brcmf_dbg(TRACE, "idx %d\n", ifidx); - ifp = drvr->iflist[bssidx]; + ifp = drvr->iflist[ifidx]; /* * Delete the existing interface before overwriting it * in case we missed the BRCMF_E_IF_DEL event. @@ -725,7 +678,7 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, netif_stop_queue(ifp->ndev); unregister_netdev(ifp->ndev); free_netdev(ifp->ndev); - drvr->iflist[bssidx] = NULL; + drvr->iflist[ifidx] = NULL; } else { brcmf_err("ignore IF event\n"); return ERR_PTR(-EINVAL); @@ -742,15 +695,16 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ifp = netdev_priv(ndev); ifp->ndev = ndev; ifp->drvr = drvr; - drvr->iflist[bssidx] = ifp; - ifp->ifidx = ifidx; + drvr->iflist[ifidx] = ifp; + ifp->idx = ifidx; ifp->bssidx = bssidx; + INIT_WORK(&ifp->setmacaddr_work, _brcmf_set_mac_address); + INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list); - init_waitqueue_head(&ifp->pend_8021x_wait); - - if (mac_addr != NULL) - memcpy(ifp->mac_addr, mac_addr, ETH_ALEN); + if (addr_mask != NULL) + for (i = 0; i < ETH_ALEN; i++) + ifp->mac_addr[i] = drvr->mac[i] ^ addr_mask[i]; brcmf_dbg(TRACE, " ==== pid:%x, if:%s (%pM) created ===\n", current->pid, ifp->ndev->name, ifp->mac_addr); @@ -758,18 +712,19 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, return ifp; } -void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) +void brcmf_del_if(struct brcmf_pub *drvr, int ifidx) { struct brcmf_if *ifp; - ifp = drvr->iflist[bssidx]; + brcmf_dbg(TRACE, "idx %d\n", ifidx); + + ifp = drvr->iflist[ifidx]; if (!ifp) { - brcmf_err("Null interface, idx=%d\n", bssidx); + brcmf_err("Null interface\n"); return; } - brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); if (ifp->ndev) { - if (bssidx == 0) { + if (ifidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { rtnl_lock(); brcmf_netdev_stop(ifp->ndev); @@ -779,14 +734,12 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) netif_stop_queue(ifp->ndev); } - if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { - cancel_work_sync(&ifp->setmacaddr_work); - cancel_work_sync(&ifp->multicast_work); - } + cancel_work_sync(&ifp->setmacaddr_work); + cancel_work_sync(&ifp->multicast_work); unregister_netdev(ifp->ndev); - drvr->iflist[bssidx] = NULL; - if (bssidx == 0) + drvr->iflist[ifidx] = NULL; + if (ifidx == 0) brcmf_cfg80211_detach(drvr->config); free_netdev(ifp->ndev); } @@ -826,6 +779,8 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev) INIT_LIST_HEAD(&drvr->bus_if->dcmd_list); + init_waitqueue_head(&drvr->pend_8021x_wait); + return ret; fail: @@ -840,7 +795,6 @@ int brcmf_bus_start(struct device *dev) struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; struct brcmf_if *ifp; - struct brcmf_if *p2p_ifp; brcmf_dbg(TRACE, "\n"); @@ -856,13 +810,6 @@ int brcmf_bus_start(struct device *dev) if (IS_ERR(ifp)) return PTR_ERR(ifp); - if (brcmf_p2p_enable) - p2p_ifp = brcmf_add_if(drvr, 1, 0, "p2p%d", NULL); - else - p2p_ifp = NULL; - if (IS_ERR(p2p_ifp)) - p2p_ifp = NULL; - /* signal bus ready */ bus_if->state = BRCMF_BUS_DATA; @@ -881,22 +828,16 @@ int brcmf_bus_start(struct device *dev) if (ret < 0) goto fail; - ret = brcmf_net_attach(ifp, false); + ret = brcmf_net_attach(ifp); fail: if (ret < 0) { brcmf_err("failed: %d\n", ret); if (drvr->config) brcmf_cfg80211_detach(drvr->config); - free_netdev(ifp->ndev); + free_netdev(drvr->iflist[0]->ndev); drvr->iflist[0] = NULL; - if (p2p_ifp) { - free_netdev(p2p_ifp->ndev); - drvr->iflist[1] = NULL; - } return ret; } - if ((brcmf_p2p_enable) && (p2p_ifp)) - brcmf_net_p2p_attach(p2p_ifp); return 0; } @@ -922,13 +863,12 @@ void brcmf_dev_reset(struct device *dev) if (drvr == NULL) return; - if (drvr->iflist[0]) - brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1); + brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1); } void brcmf_detach(struct device *dev) { - s32 i; + int i; struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_pub *drvr = bus_if->drvr; @@ -955,18 +895,19 @@ void brcmf_detach(struct device *dev) kfree(drvr); } -static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp) +static int brcmf_get_pend_8021x_cnt(struct brcmf_pub *drvr) { - return atomic_read(&ifp->pend_8021x_cnt); + return atomic_read(&drvr->pend_8021x_cnt); } int brcmf_netdev_wait_pend8021x(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; int err; - err = wait_event_timeout(ifp->pend_8021x_wait, - !brcmf_get_pend_8021x_cnt(ifp), + err = wait_event_timeout(drvr->pend_8021x_wait, + !brcmf_get_pend_8021x_cnt(drvr), msecs_to_jiffies(MAX_WAIT_FOR_8021X_TX)); WARN_ON(!err); @@ -974,16 +915,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) return !err; } -/* - * return chip id and rev of the device encoded in u32. - */ -u32 brcmf_get_chip_info(struct brcmf_if *ifp) -{ - struct brcmf_bus *bus = ifp->drvr->bus_if; - - return bus->chip << 4 | bus->chiprev; -} - static void brcmf_driver_init(struct work_struct *work) { brcmf_debugfs_init(); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 35817631ea06..7fef9b5ba003 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -1096,6 +1096,7 @@ static int brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL && type != BRCMF_SDIO_FT_SUPER) { brcmf_err("HW header length too long\n"); + bus->sdiodev->bus_if->dstats.rx_errors++; bus->sdcnt.rx_toolong++; brcmf_sdbrcm_rxfail(bus, false, false); rd->len = 0; @@ -1297,6 +1298,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) if (errcode < 0) { brcmf_err("glom read of %d bytes failed: %d\n", dlen, errcode); + bus->sdiodev->bus_if->dstats.rx_errors++; sdio_claim_host(bus->sdiodev->func[1]); if (bus->glomerr++ < 3) { @@ -1476,6 +1478,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) if ((rdlen + BRCMF_FIRSTREAD) > bus->sdiodev->bus_if->maxctl) { brcmf_err("%d-byte control read exceeds %d-byte buffer\n", rdlen, bus->sdiodev->bus_if->maxctl); + bus->sdiodev->bus_if->dstats.rx_errors++; brcmf_sdbrcm_rxfail(bus, false, false); goto done; } @@ -1483,6 +1486,7 @@ brcmf_sdbrcm_read_control(struct brcmf_sdio *bus, u8 *hdr, uint len, uint doff) if ((len - doff) > bus->sdiodev->bus_if->maxctl) { brcmf_err("%d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", len, len - doff, bus->sdiodev->bus_if->maxctl); + bus->sdiodev->bus_if->dstats.rx_errors++; bus->sdcnt.rx_toolong++; brcmf_sdbrcm_rxfail(bus, false, false); goto done; @@ -1630,6 +1634,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) if (!pkt) { /* Give up on data, request rtx of events */ brcmf_err("brcmu_pkt_buf_get_skb failed\n"); + bus->sdiodev->bus_if->dstats.rx_dropped++; brcmf_sdbrcm_rxfail(bus, false, RETRYCHAN(rd->channel)); sdio_release_host(bus->sdiodev->func[1]); @@ -1647,6 +1652,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) brcmf_err("read %d bytes from channel %d failed: %d\n", rd->len, rd->channel, sdret); brcmu_pkt_buf_free_skb(pkt); + bus->sdiodev->bus_if->dstats.rx_errors++; sdio_claim_host(bus->sdiodev->func[1]); brcmf_sdbrcm_rxfail(bus, true, RETRYCHAN(rd->channel)); @@ -1934,6 +1940,10 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) datalen = pkt->len - SDPCM_HDRLEN; ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); + if (ret) + bus->sdiodev->bus_if->dstats.tx_errors++; + else + bus->sdiodev->bus_if->dstats.tx_bytes += datalen; /* In poll mode, need to check for other events */ if (!bus->intr && cnt) { @@ -1952,7 +1962,8 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) } /* Deflow-control stack if needed */ - if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) && + if (bus->sdiodev->bus_if->drvr_up && + (bus->sdiodev->bus_if->state == BRCMF_BUS_DATA) && bus->txoff && (pktq_len(&bus->txq) < TXLOW)) { bus->txoff = false; brcmf_txflowblock(bus->sdiodev->dev, false); @@ -2699,10 +2710,9 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, * address of sdpcm_shared structure */ sdio_claim_host(bus->sdiodev->func[1]); - brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); rv = brcmf_sdbrcm_membytes(bus, false, shaddr, (u8 *)&addr_le, 4); - sdio_release_host(bus->sdiodev->func[1]); + sdio_claim_host(bus->sdiodev->func[1]); if (rv < 0) return rv; @@ -2721,8 +2731,10 @@ static int brcmf_sdio_readshared(struct brcmf_sdio *bus, } /* Read hndrte_shared structure */ + sdio_claim_host(bus->sdiodev->func[1]); rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&sh_le, sizeof(struct sdpcm_shared_le)); + sdio_release_host(bus->sdiodev->func[1]); if (rv < 0) return rv; @@ -2824,12 +2836,14 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh, if ((sh->flags & SDPCM_SHARED_TRAP) == 0) return 0; + sdio_claim_host(bus->sdiodev->func[1]); error = brcmf_sdbrcm_membytes(bus, false, sh->trap_addr, (u8 *)&tr, sizeof(struct brcmf_trap_info)); if (error < 0) return error; nbytes = brcmf_sdio_dump_console(bus, sh, data, count); + sdio_release_host(bus->sdiodev->func[1]); if (nbytes < 0) return nbytes; @@ -3294,6 +3308,9 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) { int ret; + if (bus->sdiodev->bus_if->drvr_up) + return -EISCONN; + ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, &bus->sdiodev->func[2]->dev); if (ret) { @@ -3924,8 +3941,6 @@ void *brcmf_sdbrcm_probe(u32 regsva, struct brcmf_sdio_dev *sdiodev) /* Assign bus interface call back */ bus->sdiodev->bus_if->dev = bus->sdiodev->dev; bus->sdiodev->bus_if->ops = &brcmf_sdio_bus_ops; - bus->sdiodev->bus_if->chip = bus->ci->chip; - bus->sdiodev->bus_if->chiprev = bus->ci->chiprev; /* Attach to the brcmf/OS/network interface */ ret = brcmf_attach(SDPCM_RESERVE, bus->sdiodev->dev); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index e9d6f91a1f2b..ba0b22512f12 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -189,24 +189,24 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, return; } - ifp = drvr->iflist[ifevent->bssidx]; + ifp = drvr->iflist[ifevent->ifidx]; if (ifevent->action == BRCMF_E_IF_ADD) { brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, emsg->addr); - ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, + ifp = brcmf_add_if(drvr, ifevent->ifidx, ifevent->bssidx, emsg->ifname, emsg->addr); if (IS_ERR(ifp)) return; if (!drvr->fweh.evt_handler[BRCMF_E_IF]) - err = brcmf_net_attach(ifp, false); + err = brcmf_net_attach(ifp); } err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); if (ifevent->action == BRCMF_E_IF_DEL) - brcmf_del_if(drvr, ifevent->bssidx); + brcmf_del_if(drvr, ifevent->ifidx); } /** @@ -250,6 +250,8 @@ static void brcmf_fweh_event_worker(struct work_struct *work) drvr = container_of(fweh, struct brcmf_pub, fweh); while ((event = brcmf_fweh_dequeue_event(fweh))) { + ifp = drvr->iflist[event->ifidx]; + brcmf_dbg(EVENT, "event %s (%u) ifidx %u bsscfg %u addr %pM\n", brcmf_fweh_event_name(event->code), event->code, event->emsg.ifidx, event->emsg.bsscfgidx, @@ -281,7 +283,6 @@ static void brcmf_fweh_event_worker(struct work_struct *work) goto event_free; } - ifp = drvr->iflist[emsg.bsscfgidx]; err = brcmf_fweh_call_event_handler(ifp, event->code, &emsg, event->data); if (err) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index 8c39b51dcccf..36901f76a3b5 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -83,7 +83,6 @@ struct brcmf_event; BRCMF_ENUM_DEF(MULTICAST_DECODE_ERROR, 51) \ BRCMF_ENUM_DEF(TRACE, 52) \ BRCMF_ENUM_DEF(IF, 54) \ - BRCMF_ENUM_DEF(P2P_DISC_LISTEN_COMPLETE, 55) \ BRCMF_ENUM_DEF(RSSI, 56) \ BRCMF_ENUM_DEF(PFN_SCAN_COMPLETE, 57) \ BRCMF_ENUM_DEF(EXTLOG_MSG, 58) \ @@ -97,11 +96,8 @@ struct brcmf_event; BRCMF_ENUM_DEF(DFS_AP_RESUME, 66) \ BRCMF_ENUM_DEF(ESCAN_RESULT, 69) \ BRCMF_ENUM_DEF(ACTION_FRAME_OFF_CHAN_COMPLETE, 70) \ - BRCMF_ENUM_DEF(PROBERESP_MSG, 71) \ - BRCMF_ENUM_DEF(P2P_PROBEREQ_MSG, 72) \ BRCMF_ENUM_DEF(DCS_REQUEST, 73) \ - BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) \ - BRCMF_ENUM_DEF(ACTION_FRAME_RX, 75) + BRCMF_ENUM_DEF(FIFO_CREDIT_MAP, 74) #define BRCMF_ENUM_DEF(id, val) \ BRCMF_E_##id = (val), diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index 8d1def935b8d..d8d8b6549dc5 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil.c @@ -45,10 +45,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) if (data != NULL) len = min_t(uint, len, BRCMF_DCMD_MAXLEN); if (set) - err = brcmf_proto_cdc_set_dcmd(drvr, ifp->ifidx, cmd, data, - len); + err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len); else - err = brcmf_proto_cdc_query_dcmd(drvr, ifp->ifidx, cmd, data, + err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data, len); if (err >= 0) @@ -101,7 +100,6 @@ brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data) __le32 data_le = cpu_to_le32(data); mutex_lock(&ifp->drvr->proto_block); - brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data); err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true); mutex_unlock(&ifp->drvr->proto_block); @@ -118,7 +116,6 @@ brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false); mutex_unlock(&ifp->drvr->proto_block); *data = le32_to_cpu(data_le); - brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data); return err; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h deleted file mode 100644 index 0f2c83bc95dc..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - - -#ifndef FWIL_TYPES_H_ -#define FWIL_TYPES_H_ - -#include - - -#define BRCMF_FIL_ACTION_FRAME_SIZE 1800 - - -enum brcmf_fil_p2p_if_types { - BRCMF_FIL_P2P_IF_CLIENT, - BRCMF_FIL_P2P_IF_GO, - BRCMF_FIL_P2P_IF_DYNBCN_GO, - BRCMF_FIL_P2P_IF_DEV, -}; - -struct brcmf_fil_p2p_if_le { - u8 addr[ETH_ALEN]; - __le16 type; - __le16 chspec; -}; - -struct brcmf_fil_chan_info_le { - __le32 hw_channel; - __le32 target_channel; - __le32 scan_channel; -}; - -struct brcmf_fil_action_frame_le { - u8 da[ETH_ALEN]; - __le16 len; - __le32 packet_id; - u8 data[BRCMF_FIL_ACTION_FRAME_SIZE]; -}; - -struct brcmf_fil_af_params_le { - __le32 channel; - __le32 dwell_time; - u8 bssid[ETH_ALEN]; - u8 pad[2]; - struct brcmf_fil_action_frame_le action_frame; -}; - -struct brcmf_fil_bss_enable_le { - __le32 bsscfg_idx; - __le32 enable; -}; - -#endif /* FWIL_TYPES_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.c deleted file mode 100644 index 4166e642068b..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ /dev/null @@ -1,2277 +0,0 @@ -/* - * Copyright (c) 2012 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include "fwil.h" -#include "fwil_types.h" -#include "p2p.h" -#include "wl_cfg80211.h" - -/* parameters used for p2p escan */ -#define P2PAPI_SCAN_NPROBES 1 -#define P2PAPI_SCAN_DWELL_TIME_MS 80 -#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40 -#define P2PAPI_SCAN_HOME_TIME_MS 60 -#define P2PAPI_SCAN_NPROBS_TIME_MS 30 -#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100 -#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 -#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 - -#define BRCMF_P2P_WILDCARD_SSID "DIRECT-" -#define BRCMF_P2P_WILDCARD_SSID_LEN (sizeof(BRCMF_P2P_WILDCARD_SSID) - 1) - -#define SOCIAL_CHAN_1 1 -#define SOCIAL_CHAN_2 6 -#define SOCIAL_CHAN_3 11 -#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \ - (channel == SOCIAL_CHAN_2) || \ - (channel == SOCIAL_CHAN_3)) -#define SOCIAL_CHAN_CNT 3 -#define AF_PEER_SEARCH_CNT 2 - -#define BRCMF_SCB_TIMEOUT_VALUE 20 - -#define P2P_VER 9 /* P2P version: 9=WiFi P2P v1.0 */ -#define P2P_PUB_AF_CATEGORY 0x04 -#define P2P_PUB_AF_ACTION 0x09 -#define P2P_AF_CATEGORY 0x7f -#define P2P_OUI "\x50\x6F\x9A" /* P2P OUI */ -#define P2P_OUI_LEN 3 /* P2P OUI length */ - -/* Action Frame Constants */ -#define DOT11_ACTION_HDR_LEN 2 /* action frame category + action */ -#define DOT11_ACTION_CAT_OFF 0 /* category offset */ -#define DOT11_ACTION_ACT_OFF 1 /* action offset */ - -#define P2P_AF_DWELL_TIME 200 -#define P2P_AF_MIN_DWELL_TIME 100 -#define P2P_AF_MED_DWELL_TIME 400 -#define P2P_AF_LONG_DWELL_TIME 1000 -#define P2P_AF_TX_MAX_RETRY 1 -#define P2P_AF_MAX_WAIT_TIME 2000 -#define P2P_INVALID_CHANNEL -1 -#define P2P_CHANNEL_SYNC_RETRY 5 -#define P2P_AF_FRM_SCAN_MAX_WAIT 1500 -#define P2P_DEFAULT_SLEEP_TIME_VSDB 200 - -/* WiFi P2P Public Action Frame OUI Subtypes */ -#define P2P_PAF_GON_REQ 0 /* Group Owner Negotiation Req */ -#define P2P_PAF_GON_RSP 1 /* Group Owner Negotiation Rsp */ -#define P2P_PAF_GON_CONF 2 /* Group Owner Negotiation Confirm */ -#define P2P_PAF_INVITE_REQ 3 /* P2P Invitation Request */ -#define P2P_PAF_INVITE_RSP 4 /* P2P Invitation Response */ -#define P2P_PAF_DEVDIS_REQ 5 /* Device Discoverability Request */ -#define P2P_PAF_DEVDIS_RSP 6 /* Device Discoverability Response */ -#define P2P_PAF_PROVDIS_REQ 7 /* Provision Discovery Request */ -#define P2P_PAF_PROVDIS_RSP 8 /* Provision Discovery Response */ -#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ - -/* WiFi P2P Action Frame OUI Subtypes */ -#define P2P_AF_NOTICE_OF_ABSENCE 0 /* Notice of Absence */ -#define P2P_AF_PRESENCE_REQ 1 /* P2P Presence Request */ -#define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */ -#define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */ - -/* P2P Service Discovery related */ -#define P2PSD_ACTION_CATEGORY 0x04 /* Public action frame */ -#define P2PSD_ACTION_ID_GAS_IREQ 0x0a /* GAS Initial Request AF */ -#define P2PSD_ACTION_ID_GAS_IRESP 0x0b /* GAS Initial Response AF */ -#define P2PSD_ACTION_ID_GAS_CREQ 0x0c /* GAS Comback Request AF */ -#define P2PSD_ACTION_ID_GAS_CRESP 0x0d /* GAS Comback Response AF */ - -/** - * struct brcmf_p2p_disc_st_le - set discovery state in firmware. - * - * @state: requested discovery state (see enum brcmf_p2p_disc_state). - * @chspec: channel parameter for %WL_P2P_DISC_ST_LISTEN state. - * @dwell: dwell time in ms for %WL_P2P_DISC_ST_LISTEN state. - */ -struct brcmf_p2p_disc_st_le { - u8 state; - __le16 chspec; - __le16 dwell; -}; - -/** - * enum brcmf_p2p_disc_state - P2P discovery state values - * - * @WL_P2P_DISC_ST_SCAN: P2P discovery with wildcard SSID and P2P IE. - * @WL_P2P_DISC_ST_LISTEN: P2P discovery off-channel for specified time. - * @WL_P2P_DISC_ST_SEARCH: P2P discovery with P2P wildcard SSID and P2P IE. - */ -enum brcmf_p2p_disc_state { - WL_P2P_DISC_ST_SCAN, - WL_P2P_DISC_ST_LISTEN, - WL_P2P_DISC_ST_SEARCH -}; - -/** - * struct brcmf_p2p_scan_le - P2P specific scan request. - * - * @type: type of scan method requested (values: 'E' or 'S'). - * @reserved: reserved (ignored). - * @eparams: parameters used for type 'E'. - * @sparams: parameters used for type 'S'. - */ -struct brcmf_p2p_scan_le { - u8 type; - u8 reserved[3]; - union { - struct brcmf_escan_params_le eparams; - struct brcmf_scan_params_le sparams; - }; -}; - -/** - * struct brcmf_p2p_pub_act_frame - WiFi P2P Public Action Frame - * - * @category: P2P_PUB_AF_CATEGORY - * @action: P2P_PUB_AF_ACTION - * @oui[3]: P2P_OUI - * @oui_type: OUI type - P2P_VER - * @subtype: OUI subtype - P2P_TYPE_* - * @dialog_token: nonzero, identifies req/rsp transaction - * @elts[1]: Variable length information elements. - */ -struct brcmf_p2p_pub_act_frame { - u8 category; - u8 action; - u8 oui[3]; - u8 oui_type; - u8 subtype; - u8 dialog_token; - u8 elts[1]; -}; - -/** - * struct brcmf_p2p_action_frame - WiFi P2P Action Frame - * - * @category: P2P_AF_CATEGORY - * @OUI[3]: OUI - P2P_OUI - * @type: OUI Type - P2P_VER - * @subtype: OUI Subtype - P2P_AF_* - * @dialog_token: nonzero, identifies req/resp tranaction - * @elts[1]: Variable length information elements. - */ -struct brcmf_p2p_action_frame { - u8 category; - u8 oui[3]; - u8 type; - u8 subtype; - u8 dialog_token; - u8 elts[1]; -}; - -/** - * struct brcmf_p2psd_gas_pub_act_frame - Wi-Fi GAS Public Action Frame - * - * @category: 0x04 Public Action Frame - * @action: 0x6c Advertisement Protocol - * @dialog_token: nonzero, identifies req/rsp transaction - * @query_data[1]: Query Data. SD gas ireq SD gas iresp - */ -struct brcmf_p2psd_gas_pub_act_frame { - u8 category; - u8 action; - u8 dialog_token; - u8 query_data[1]; -}; - -/** - * struct brcmf_config_af_params - Action Frame Parameters for tx. - * - * @mpc_onoff: To make sure to send successfully action frame, we have to - * turn off mpc 0: off, 1: on, (-1): do nothing - * @search_channel: 1: search peer's channel to send af - * extra_listen: keep the dwell time to get af response frame. - */ -struct brcmf_config_af_params { - s32 mpc_onoff; - bool search_channel; - bool extra_listen; -}; - -/** - * brcmf_p2p_is_pub_action() - true if p2p public type frame. - * - * @frame: action frame data. - * @frame_len: length of action frame data. - * - * Determine if action frame is p2p public action type - */ -static bool brcmf_p2p_is_pub_action(void *frame, u32 frame_len) -{ - struct brcmf_p2p_pub_act_frame *pact_frm; - - if (frame == NULL) - return false; - - pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; - if (frame_len < sizeof(struct brcmf_p2p_pub_act_frame) - 1) - return false; - - if (pact_frm->category == P2P_PUB_AF_CATEGORY && - pact_frm->action == P2P_PUB_AF_ACTION && - pact_frm->oui_type == P2P_VER && - memcmp(pact_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) - return true; - - return false; -} - -/** - * brcmf_p2p_is_p2p_action() - true if p2p action type frame. - * - * @frame: action frame data. - * @frame_len: length of action frame data. - * - * Determine if action frame is p2p action type - */ -static bool brcmf_p2p_is_p2p_action(void *frame, u32 frame_len) -{ - struct brcmf_p2p_action_frame *act_frm; - - if (frame == NULL) - return false; - - act_frm = (struct brcmf_p2p_action_frame *)frame; - if (frame_len < sizeof(struct brcmf_p2p_action_frame) - 1) - return false; - - if (act_frm->category == P2P_AF_CATEGORY && - act_frm->type == P2P_VER && - memcmp(act_frm->oui, P2P_OUI, P2P_OUI_LEN) == 0) - return true; - - return false; -} - -/** - * brcmf_p2p_is_gas_action() - true if p2p gas action type frame. - * - * @frame: action frame data. - * @frame_len: length of action frame data. - * - * Determine if action frame is p2p gas action type - */ -static bool brcmf_p2p_is_gas_action(void *frame, u32 frame_len) -{ - struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; - - if (frame == NULL) - return false; - - sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame; - if (frame_len < sizeof(struct brcmf_p2psd_gas_pub_act_frame) - 1) - return false; - - if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) - return false; - - if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ || - sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP || - sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ || - sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP) - return true; - - return false; -} - -/** - * brcmf_p2p_print_actframe() - debug print routine. - * - * @tx: Received or to be transmitted - * @frame: action frame data. - * @frame_len: length of action frame data. - * - * Print information about the p2p action frame - */ - -#ifdef DEBUG - -static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) -{ - struct brcmf_p2p_pub_act_frame *pact_frm; - struct brcmf_p2p_action_frame *act_frm; - struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; - - if (!frame || frame_len <= 2) - return; - - if (brcmf_p2p_is_pub_action(frame, frame_len)) { - pact_frm = (struct brcmf_p2p_pub_act_frame *)frame; - switch (pact_frm->subtype) { - case P2P_PAF_GON_REQ: - brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Req Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_GON_RSP: - brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Rsp Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_GON_CONF: - brcmf_dbg(TRACE, "%s P2P Group Owner Negotiation Confirm Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_INVITE_REQ: - brcmf_dbg(TRACE, "%s P2P Invitation Request Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_INVITE_RSP: - brcmf_dbg(TRACE, "%s P2P Invitation Response Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_DEVDIS_REQ: - brcmf_dbg(TRACE, "%s P2P Device Discoverability Request Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_DEVDIS_RSP: - brcmf_dbg(TRACE, "%s P2P Device Discoverability Response Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_PROVDIS_REQ: - brcmf_dbg(TRACE, "%s P2P Provision Discovery Request Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_PAF_PROVDIS_RSP: - brcmf_dbg(TRACE, "%s P2P Provision Discovery Response Frame\n", - (tx) ? "TX" : "RX"); - break; - default: - brcmf_dbg(TRACE, "%s Unknown P2P Public Action Frame\n", - (tx) ? "TX" : "RX"); - break; - } - } else if (brcmf_p2p_is_p2p_action(frame, frame_len)) { - act_frm = (struct brcmf_p2p_action_frame *)frame; - switch (act_frm->subtype) { - case P2P_AF_NOTICE_OF_ABSENCE: - brcmf_dbg(TRACE, "%s P2P Notice of Absence Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_AF_PRESENCE_REQ: - brcmf_dbg(TRACE, "%s P2P Presence Request Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_AF_PRESENCE_RSP: - brcmf_dbg(TRACE, "%s P2P Presence Response Frame\n", - (tx) ? "TX" : "RX"); - break; - case P2P_AF_GO_DISC_REQ: - brcmf_dbg(TRACE, "%s P2P Discoverability Request Frame\n", - (tx) ? "TX" : "RX"); - break; - default: - brcmf_dbg(TRACE, "%s Unknown P2P Action Frame\n", - (tx) ? "TX" : "RX"); - } - - } else if (brcmf_p2p_is_gas_action(frame, frame_len)) { - sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame; - switch (sd_act_frm->action) { - case P2PSD_ACTION_ID_GAS_IREQ: - brcmf_dbg(TRACE, "%s P2P GAS Initial Request\n", - (tx) ? "TX" : "RX"); - break; - case P2PSD_ACTION_ID_GAS_IRESP: - brcmf_dbg(TRACE, "%s P2P GAS Initial Response\n", - (tx) ? "TX" : "RX"); - break; - case P2PSD_ACTION_ID_GAS_CREQ: - brcmf_dbg(TRACE, "%s P2P GAS Comback Request\n", - (tx) ? "TX" : "RX"); - break; - case P2PSD_ACTION_ID_GAS_CRESP: - brcmf_dbg(TRACE, "%s P2P GAS Comback Response\n", - (tx) ? "TX" : "RX"); - break; - default: - brcmf_dbg(TRACE, "%s Unknown P2P GAS Frame\n", - (tx) ? "TX" : "RX"); - break; - } - } -} - -#else - -static void brcmf_p2p_print_actframe(bool tx, void *frame, u32 frame_len) -{ -} - -#endif - - -/** - * brcmf_p2p_chnr_to_chspec() - convert channel number to chanspec. - * - * @channel: channel number - */ -static u16 brcmf_p2p_chnr_to_chspec(u16 channel) -{ - u16 chanspec; - - chanspec = channel & WL_CHANSPEC_CHAN_MASK; - - if (channel <= CH_MAX_2G_CHANNEL) - chanspec |= WL_CHANSPEC_BAND_2G; - else - chanspec |= WL_CHANSPEC_BAND_5G; - - chanspec |= WL_CHANSPEC_BW_20; - chanspec |= WL_CHANSPEC_CTL_SB_NONE; - - return chanspec; -} - - -/** - * brcmf_p2p_set_firmware() - prepare firmware for peer-to-peer operation. - * - * @ifp: ifp to use for iovars (primary). - * @p2p_mac: mac address to configure for p2p_da_override - */ -static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) -{ - s32 ret = 0; - - brcmf_fil_iovar_int_set(ifp, "apsta", 1); - - /* In case of COB type, firmware has default mac address - * After Initializing firmware, we have to set current mac address to - * firmware for P2P device address - */ - ret = brcmf_fil_iovar_data_set(ifp, "p2p_da_override", p2p_mac, - ETH_ALEN); - if (ret) - brcmf_err("failed to update device address ret %d\n", ret); - - return ret; -} - -/** - * brcmf_p2p_generate_bss_mac() - derive mac addresses for P2P. - * - * @p2p: P2P specific data. - * - * P2P needs mac addresses for P2P device and interface. These are - * derived from the primary net device, ie. the permanent ethernet - * address of the device. - */ -static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p) -{ - struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; - struct brcmf_if *p2p_ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; - - /* Generate the P2P Device Address. This consists of the device's - * primary MAC address with the locally administered bit set. - */ - memcpy(p2p->dev_addr, pri_ifp->mac_addr, ETH_ALEN); - p2p->dev_addr[0] |= 0x02; - memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN); - - /* Generate the P2P Interface Address. If the discovery and connection - * BSSCFGs need to simultaneously co-exist, then this address must be - * different from the P2P Device Address, but also locally administered. - */ - memcpy(p2p->int_addr, p2p->dev_addr, ETH_ALEN); - p2p->int_addr[4] ^= 0x80; -} - -/** - * brcmf_p2p_scan_is_p2p_request() - is cfg80211 scan request a P2P scan. - * - * @request: the scan request as received from cfg80211. - * - * returns true if one of the ssids in the request matches the - * P2P wildcard ssid; otherwise returns false. - */ -static bool brcmf_p2p_scan_is_p2p_request(struct cfg80211_scan_request *request) -{ - struct cfg80211_ssid *ssids = request->ssids; - int i; - - for (i = 0; i < request->n_ssids; i++) { - if (ssids[i].ssid_len != BRCMF_P2P_WILDCARD_SSID_LEN) - continue; - - brcmf_dbg(INFO, "comparing ssid \"%s\"", ssids[i].ssid); - if (!memcmp(BRCMF_P2P_WILDCARD_SSID, ssids[i].ssid, - BRCMF_P2P_WILDCARD_SSID_LEN)) - return true; - } - return false; -} - -/** - * brcmf_p2p_set_discover_state - set discover state in firmware. - * - * @ifp: low-level interface object. - * @state: discover state to set. - * @chanspec: channel parameters (for state @WL_P2P_DISC_ST_LISTEN only). - * @listen_ms: duration to listen (for state @WL_P2P_DISC_ST_LISTEN only). - */ -static s32 brcmf_p2p_set_discover_state(struct brcmf_if *ifp, u8 state, - u16 chanspec, u16 listen_ms) -{ - struct brcmf_p2p_disc_st_le discover_state; - s32 ret = 0; - brcmf_dbg(TRACE, "enter\n"); - - discover_state.state = state; - discover_state.chspec = cpu_to_le16(chanspec); - discover_state.dwell = cpu_to_le16(listen_ms); - ret = brcmf_fil_bsscfg_data_set(ifp, "p2p_state", &discover_state, - sizeof(discover_state)); - return ret; -} - -/** - * brcmf_p2p_deinit_discovery() - disable P2P device discovery. - * - * @p2p: P2P specific data. - * - * Resets the discovery state and disables it in firmware. - */ -static s32 brcmf_p2p_deinit_discovery(struct brcmf_p2p_info *p2p) -{ - struct brcmf_cfg80211_vif *vif; - - brcmf_dbg(TRACE, "enter\n"); - - /* Set the discovery state to SCAN */ - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - (void)brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0); - - /* Disable P2P discovery in the firmware */ - vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; - (void)brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 0); - - return 0; -} - -/** - * brcmf_p2p_enable_discovery() - initialize and configure discovery. - * - * @p2p: P2P specific data. - * - * Initializes the discovery device and configure the virtual interface. - */ -static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p) -{ - struct brcmf_cfg80211_vif *vif; - s32 ret = 0; - - brcmf_dbg(TRACE, "enter\n"); - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - if (!vif) { - brcmf_err("P2P config device not available\n"); - ret = -EPERM; - goto exit; - } - - if (test_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status)) { - brcmf_dbg(INFO, "P2P config device already configured\n"); - goto exit; - } - - /* Re-initialize P2P Discovery in the firmware */ - vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; - ret = brcmf_fil_iovar_int_set(vif->ifp, "p2p_disc", 1); - if (ret < 0) { - brcmf_err("set p2p_disc error\n"); - goto exit; - } - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - ret = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_SCAN, 0, 0); - if (ret < 0) { - brcmf_err("unable to set WL_P2P_DISC_ST_SCAN\n"); - goto exit; - } - - /* - * Set wsec to any non-zero value in the discovery bsscfg - * to ensure our P2P probe responses have the privacy bit - * set in the 802.11 WPA IE. Some peer devices may not - * initiate WPS with us if this bit is not set. - */ - ret = brcmf_fil_bsscfg_int_set(vif->ifp, "wsec", AES_ENABLED); - if (ret < 0) { - brcmf_err("wsec error %d\n", ret); - goto exit; - } - - set_bit(BRCMF_P2P_STATUS_ENABLED, &p2p->status); -exit: - return ret; -} - -/** - * brcmf_p2p_escan() - initiate a P2P scan. - * - * @p2p: P2P specific data. - * @num_chans: number of channels to scan. - * @chanspecs: channel parameters for @num_chans channels. - * @search_state: P2P discover state to use. - * @action: scan action to pass to firmware. - * @bss_type: type of P2P bss. - */ -static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans, - u16 chanspecs[], s32 search_state, u16 action, - enum p2p_bss_type bss_type) -{ - s32 ret = 0; - s32 memsize = offsetof(struct brcmf_p2p_scan_le, - eparams.params_le.channel_list); - s32 nprobes; - s32 active; - u32 i; - u8 *memblk; - struct brcmf_cfg80211_vif *vif; - struct brcmf_p2p_scan_le *p2p_params; - struct brcmf_scan_params_le *sparams; - struct brcmf_ssid ssid; - - memsize += num_chans * sizeof(__le16); - memblk = kzalloc(memsize, GFP_KERNEL); - if (!memblk) - return -ENOMEM; - - vif = p2p->bss_idx[bss_type].vif; - if (vif == NULL) { - brcmf_err("no vif for bss type %d\n", bss_type); - ret = -EINVAL; - goto exit; - } - - switch (search_state) { - case WL_P2P_DISC_ST_SEARCH: - /* - * If we in SEARCH STATE, we don't need to set SSID explictly - * because dongle use P2P WILDCARD internally by default - */ - /* use null ssid */ - ssid.SSID_len = 0; - memset(ssid.SSID, 0, sizeof(ssid.SSID)); - break; - case WL_P2P_DISC_ST_SCAN: - /* - * wpa_supplicant has p2p_find command with type social or - * progressive. For progressive, we need to set the ssid to - * P2P WILDCARD because we just do broadcast scan unless - * setting SSID. - */ - ssid.SSID_len = BRCMF_P2P_WILDCARD_SSID_LEN; - memcpy(ssid.SSID, BRCMF_P2P_WILDCARD_SSID, ssid.SSID_len); - break; - default: - brcmf_err(" invalid search state %d\n", search_state); - ret = -EINVAL; - goto exit; - } - - brcmf_p2p_set_discover_state(vif->ifp, search_state, 0, 0); - - /* - * set p2p scan parameters. - */ - p2p_params = (struct brcmf_p2p_scan_le *)memblk; - p2p_params->type = 'E'; - - /* determine the scan engine parameters */ - sparams = &p2p_params->eparams.params_le; - sparams->bss_type = DOT11_BSSTYPE_ANY; - if (p2p->cfg->active_scan) - sparams->scan_type = 0; - else - sparams->scan_type = 1; - - memset(&sparams->bssid, 0xFF, ETH_ALEN); - if (ssid.SSID_len) - memcpy(sparams->ssid_le.SSID, ssid.SSID, ssid.SSID_len); - sparams->ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); - sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS); - - /* - * SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan - * supported by the supplicant. - */ - if (num_chans == SOCIAL_CHAN_CNT || num_chans == (SOCIAL_CHAN_CNT + 1)) - active = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS; - else if (num_chans == AF_PEER_SEARCH_CNT) - active = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS; - else if (wl_get_vif_state_all(p2p->cfg, BRCMF_VIF_STATUS_CONNECTED)) - active = -1; - else - active = P2PAPI_SCAN_DWELL_TIME_MS; - - /* Override scan params to find a peer for a connection */ - if (num_chans == 1) { - active = WL_SCAN_CONNECT_DWELL_TIME_MS; - /* WAR to sync with presence period of VSDB GO. - * send probe request more frequently - */ - nprobes = active / WL_SCAN_JOIN_PROBE_INTERVAL_MS; - } else { - nprobes = active / P2PAPI_SCAN_NPROBS_TIME_MS; - } - - if (nprobes <= 0) - nprobes = 1; - - brcmf_dbg(INFO, "nprobes # %d, active_time %d\n", nprobes, active); - sparams->active_time = cpu_to_le32(active); - sparams->nprobes = cpu_to_le32(nprobes); - sparams->passive_time = cpu_to_le32(-1); - sparams->channel_num = cpu_to_le32(num_chans & - BRCMF_SCAN_PARAMS_COUNT_MASK); - for (i = 0; i < num_chans; i++) - sparams->channel_list[i] = cpu_to_le16(chanspecs[i]); - - /* set the escan specific parameters */ - p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); - p2p_params->eparams.action = cpu_to_le16(action); - p2p_params->eparams.sync_id = cpu_to_le16(0x1234); - /* perform p2p scan on primary device */ - ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize); - if (!ret) - set_bit(BRCMF_SCAN_STATUS_BUSY, &p2p->cfg->scan_status); -exit: - kfree(memblk); - return ret; -} - -/** - * brcmf_p2p_run_escan() - escan callback for peer-to-peer. - * - * @cfg: driver private data for cfg80211 interface. - * @ndev: net device for which scan is requested. - * @request: scan request from cfg80211. - * @action: scan action. - * - * Determines the P2P discovery state based to scan request parameters and - * validates the channels in the request. - */ -static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - struct cfg80211_scan_request *request, - u16 action) -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - s32 err = 0; - s32 search_state = WL_P2P_DISC_ST_SCAN; - struct brcmf_cfg80211_vif *vif; - struct net_device *dev = NULL; - int i, num_nodfs = 0; - u16 *chanspecs; - - brcmf_dbg(TRACE, "enter\n"); - - if (!request) { - err = -EINVAL; - goto exit; - } - - if (request->n_channels) { - chanspecs = kcalloc(request->n_channels, sizeof(*chanspecs), - GFP_KERNEL); - if (!chanspecs) { - err = -ENOMEM; - goto exit; - } - vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; - if (vif) - dev = vif->wdev.netdev; - if (request->n_channels == 3 && - request->channels[0]->hw_value == SOCIAL_CHAN_1 && - request->channels[1]->hw_value == SOCIAL_CHAN_2 && - request->channels[2]->hw_value == SOCIAL_CHAN_3) { - /* SOCIAL CHANNELS 1, 6, 11 */ - search_state = WL_P2P_DISC_ST_SEARCH; - brcmf_dbg(INFO, "P2P SEARCH PHASE START\n"); - } else if (dev != NULL && vif->mode == WL_MODE_AP) { - /* If you are already a GO, then do SEARCH only */ - brcmf_dbg(INFO, "Already a GO. Do SEARCH Only\n"); - search_state = WL_P2P_DISC_ST_SEARCH; - } else { - brcmf_dbg(INFO, "P2P SCAN STATE START\n"); - } - - /* - * no P2P scanning on passive or DFS channels. - */ - for (i = 0; i < request->n_channels; i++) { - struct ieee80211_channel *chan = request->channels[i]; - - if (chan->flags & (IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_PASSIVE_SCAN)) - continue; - - chanspecs[i] = channel_to_chanspec(chan); - brcmf_dbg(INFO, "%d: chan=%d, channel spec=%x\n", - num_nodfs, chan->hw_value, chanspecs[i]); - num_nodfs++; - } - err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state, - action, P2PAPI_BSSCFG_DEVICE); - } -exit: - if (err) - brcmf_err("error (%d)\n", err); - return err; -} - - -/** - * brcmf_p2p_find_listen_channel() - find listen channel in ie string. - * - * @ie: string of information elements. - * @ie_len: length of string. - * - * Scan ie for p2p ie and look for attribute 6 channel. If available determine - * channel and return it. - */ -static s32 brcmf_p2p_find_listen_channel(const u8 *ie, u32 ie_len) -{ - u8 channel_ie[5]; - s32 listen_channel; - s32 err; - - err = cfg80211_get_p2p_attr(ie, ie_len, - IEEE80211_P2P_ATTR_LISTEN_CHANNEL, - channel_ie, sizeof(channel_ie)); - if (err < 0) - return err; - - /* listen channel subel length format: */ - /* 3(country) + 1(op. class) + 1(chan num) */ - listen_channel = (s32)channel_ie[3 + 1]; - - if (listen_channel == SOCIAL_CHAN_1 || - listen_channel == SOCIAL_CHAN_2 || - listen_channel == SOCIAL_CHAN_3) { - brcmf_dbg(INFO, "Found my Listen Channel %d\n", listen_channel); - return listen_channel; - } - - return -EPERM; -} - - -/** - * brcmf_p2p_scan_prep() - prepare scan based on request. - * - * @wiphy: wiphy device. - * @request: scan request from cfg80211. - * @vif: vif on which scan request is to be executed. - * - * Prepare the scan appropriately for type of scan requested. Overrides the - * escan .run() callback for peer-to-peer scanning. - */ -int brcmf_p2p_scan_prep(struct wiphy *wiphy, - struct cfg80211_scan_request *request, - struct brcmf_cfg80211_vif *vif) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_p2p_info *p2p = &cfg->p2p; - int err = 0; - - if (brcmf_p2p_scan_is_p2p_request(request)) { - /* find my listen channel */ - err = brcmf_p2p_find_listen_channel(request->ie, - request->ie_len); - if (err < 0) - return err; - - p2p->afx_hdl.my_listen_chan = err; - - clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n"); - - err = brcmf_p2p_enable_discovery(p2p); - if (err) - return err; - - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - - /* override .run_escan() callback. */ - cfg->escan_info.run = brcmf_p2p_run_escan; - } - err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG, - request->ie, request->ie_len); - return err; -} - - -/** - * brcmf_p2p_discover_listen() - set firmware to discover listen state. - * - * @p2p: p2p device. - * @channel: channel nr for discover listen. - * @duration: time in ms to stay on channel. - * - */ -static s32 -brcmf_p2p_discover_listen(struct brcmf_p2p_info *p2p, u16 channel, u32 duration) -{ - struct brcmf_cfg80211_vif *vif; - s32 err = 0; - u16 chanspec; - - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - if (!vif) { - brcmf_err("Discovery is not set, so we have nothing to do\n"); - err = -EPERM; - goto exit; - } - - if (test_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status)) { - brcmf_err("Previous LISTEN is not completed yet\n"); - /* WAR: prevent cookie mismatch in wpa_supplicant return OK */ - goto exit; - } - - chanspec = brcmf_p2p_chnr_to_chspec(channel); - err = brcmf_p2p_set_discover_state(vif->ifp, WL_P2P_DISC_ST_LISTEN, - chanspec, (u16)duration); - if (!err) { - set_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, &p2p->status); - p2p->remain_on_channel_cookie++; - } -exit: - return err; -} - - -/** - * brcmf_p2p_remain_on_channel() - put device on channel and stay there. - * - * @wiphy: wiphy device. - * @channel: channel to stay on. - * @duration: time in ms to remain on channel. - * - */ -int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *channel, - unsigned int duration, u64 *cookie) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_p2p_info *p2p = &cfg->p2p; - s32 err; - u16 channel_nr; - - channel_nr = ieee80211_frequency_to_channel(channel->center_freq); - brcmf_dbg(TRACE, "Enter, channel: %d, duration ms (%d)\n", channel_nr, - duration); - - err = brcmf_p2p_enable_discovery(p2p); - if (err) - goto exit; - err = brcmf_p2p_discover_listen(p2p, channel_nr, duration); - if (err) - goto exit; - - memcpy(&p2p->remain_on_channel, channel, sizeof(*channel)); - *cookie = p2p->remain_on_channel_cookie; - cfg80211_ready_on_channel(wdev, *cookie, channel, duration, GFP_KERNEL); - -exit: - return err; -} - - -/** - * brcmf_p2p_notify_listen_complete() - p2p listen has completed. - * - * @ifp: interfac control. - * @e: event message. Not used, to make it usable for fweh event dispatcher. - * @data: payload of message. Not used. - * - */ -int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data) -{ - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct brcmf_p2p_info *p2p = &cfg->p2p; - - brcmf_dbg(TRACE, "Enter\n"); - if (test_and_clear_bit(BRCMF_P2P_STATUS_DISCOVER_LISTEN, - &p2p->status)) { - if (test_and_clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, - &p2p->status)) { - clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, - &p2p->status); - brcmf_dbg(INFO, "Listen DONE, wake up wait_next_af\n"); - complete(&p2p->wait_next_af); - } - - cfg80211_remain_on_channel_expired(&ifp->vif->wdev, - p2p->remain_on_channel_cookie, - &p2p->remain_on_channel, - GFP_KERNEL); - } - return 0; -} - - -/** - * brcmf_p2p_cancel_remain_on_channel() - cancel p2p listen state. - * - * @ifp: interfac control. - * - */ -void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp) -{ - if (!ifp) - return; - brcmf_p2p_set_discover_state(ifp, WL_P2P_DISC_ST_SCAN, 0, 0); - brcmf_p2p_notify_listen_complete(ifp, NULL, NULL); -} - - -/** - * brcmf_p2p_act_frm_search() - search function for action frame. - * - * @p2p: p2p device. - * channel: channel on which action frame is to be trasmitted. - * - * search function to reach at common channel to send action frame. When - * channel is 0 then all social channels will be used to send af - */ -static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel) -{ - s32 err; - u32 channel_cnt; - u16 *default_chan_list; - u32 i; - - brcmf_dbg(TRACE, "Enter\n"); - - if (channel) - channel_cnt = AF_PEER_SEARCH_CNT; - else - channel_cnt = SOCIAL_CHAN_CNT; - default_chan_list = kzalloc(channel_cnt * sizeof(*default_chan_list), - GFP_KERNEL); - if (default_chan_list == NULL) { - brcmf_err("channel list allocation failed\n"); - err = -ENOMEM; - goto exit; - } - if (channel) { - /* insert same channel to the chan_list */ - for (i = 0; i < channel_cnt; i++) - default_chan_list[i] = - brcmf_p2p_chnr_to_chspec(channel); - } else { - default_chan_list[0] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_1); - default_chan_list[1] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_2); - default_chan_list[2] = brcmf_p2p_chnr_to_chspec(SOCIAL_CHAN_3); - } - err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, - WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, - P2PAPI_BSSCFG_DEVICE); - kfree(default_chan_list); -exit: - return err; -} - - -/** - * brcmf_p2p_afx_handler() - afx worker thread. - * - * @work: - * - */ -static void brcmf_p2p_afx_handler(struct work_struct *work) -{ - struct afx_hdl *afx_hdl = container_of(work, struct afx_hdl, afx_work); - struct brcmf_p2p_info *p2p = container_of(afx_hdl, - struct brcmf_p2p_info, - afx_hdl); - s32 err; - - if (!afx_hdl->is_active) - return; - - if (afx_hdl->is_listen && afx_hdl->my_listen_chan) - /* 100ms ~ 300ms */ - err = brcmf_p2p_discover_listen(p2p, afx_hdl->my_listen_chan, - 100 * (1 + (random32() % 3))); - else - err = brcmf_p2p_act_frm_search(p2p, afx_hdl->peer_listen_chan); - - if (err) { - brcmf_err("ERROR occurred! value is (%d)\n", err); - if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, - &p2p->status)) - complete(&afx_hdl->act_frm_scan); - } -} - - -/** - * brcmf_p2p_af_searching_channel() - search channel. - * - * @p2p: p2p device info struct. - * - */ -static s32 brcmf_p2p_af_searching_channel(struct brcmf_p2p_info *p2p) -{ - struct afx_hdl *afx_hdl = &p2p->afx_hdl; - struct brcmf_cfg80211_vif *pri_vif; - unsigned long duration; - s32 retry; - - brcmf_dbg(TRACE, "Enter\n"); - - pri_vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; - - INIT_COMPLETION(afx_hdl->act_frm_scan); - set_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status); - afx_hdl->is_active = true; - afx_hdl->peer_chan = P2P_INVALID_CHANNEL; - - /* Loop to wait until we find a peer's channel or the - * pending action frame tx is cancelled. - */ - retry = 0; - duration = msecs_to_jiffies(P2P_AF_FRM_SCAN_MAX_WAIT); - while ((retry < P2P_CHANNEL_SYNC_RETRY) && - (afx_hdl->peer_chan == P2P_INVALID_CHANNEL)) { - afx_hdl->is_listen = false; - brcmf_dbg(TRACE, "Scheduling action frame for sending.. (%d)\n", - retry); - /* search peer on peer's listen channel */ - schedule_work(&afx_hdl->afx_work); - wait_for_completion_timeout(&afx_hdl->act_frm_scan, duration); - if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) || - (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, - &p2p->status))) - break; - - if (afx_hdl->my_listen_chan) { - brcmf_dbg(TRACE, "Scheduling listen peer, channel=%d\n", - afx_hdl->my_listen_chan); - /* listen on my listen channel */ - afx_hdl->is_listen = true; - schedule_work(&afx_hdl->afx_work); - wait_for_completion_timeout(&afx_hdl->act_frm_scan, - duration); - } - if ((afx_hdl->peer_chan != P2P_INVALID_CHANNEL) || - (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, - &p2p->status))) - break; - retry++; - - /* if sta is connected or connecting, sleep for a while before - * retry af tx or finding a peer - */ - if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &pri_vif->sme_state) || - test_bit(BRCMF_VIF_STATUS_CONNECTING, &pri_vif->sme_state)) - msleep(P2P_DEFAULT_SLEEP_TIME_VSDB); - } - - brcmf_dbg(TRACE, "Completed search/listen peer_chan=%d\n", - afx_hdl->peer_chan); - afx_hdl->is_active = false; - - clear_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status); - - return afx_hdl->peer_chan; -} - - -/** - * brcmf_p2p_scan_finding_common_channel() - was escan used for finding channel - * - * @cfg: common configuration struct. - * @bi: bss info struct, result from scan. - * - */ -bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, - struct brcmf_bss_info_le *bi) - -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct afx_hdl *afx_hdl = &p2p->afx_hdl; - u8 *ie; - s32 err; - u8 p2p_dev_addr[ETH_ALEN]; - - if (!test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status)) - return false; - - if (bi == NULL) { - brcmf_dbg(TRACE, "ACTION FRAME SCAN Done\n"); - if (afx_hdl->peer_chan == P2P_INVALID_CHANNEL) - complete(&afx_hdl->act_frm_scan); - return true; - } - - ie = ((u8 *)bi) + le16_to_cpu(bi->ie_offset); - memset(p2p_dev_addr, 0, sizeof(p2p_dev_addr)); - err = cfg80211_get_p2p_attr(ie, le32_to_cpu(bi->ie_length), - IEEE80211_P2P_ATTR_DEVICE_INFO, - p2p_dev_addr, sizeof(p2p_dev_addr)); - if (err < 0) - err = cfg80211_get_p2p_attr(ie, le32_to_cpu(bi->ie_length), - IEEE80211_P2P_ATTR_DEVICE_ID, - p2p_dev_addr, sizeof(p2p_dev_addr)); - if ((err >= 0) && - (!memcmp(p2p_dev_addr, afx_hdl->tx_dst_addr, ETH_ALEN))) { - afx_hdl->peer_chan = bi->ctl_ch ? bi->ctl_ch : - CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); - brcmf_dbg(TRACE, "ACTION FRAME SCAN : Peer %pM found, channel : %d\n", - afx_hdl->tx_dst_addr, afx_hdl->peer_chan); - complete(&afx_hdl->act_frm_scan); - } - return true; -} - -/** - * brcmf_p2p_stop_wait_next_action_frame() - finish scan if af tx complete. - * - * @cfg: common configuration struct. - * - */ -static void -brcmf_p2p_stop_wait_next_action_frame(struct brcmf_cfg80211_info *cfg) -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct net_device *ndev = cfg->escan_info.ndev; - - if (test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status) && - (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status) || - test_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status))) { - brcmf_dbg(TRACE, "*** Wake UP ** abort actframe iovar\n"); - /* if channel is not zero, "actfame" uses off channel scan. - * So abort scan for off channel completion. - */ - if (p2p->af_sent_channel) - brcmf_notify_escan_complete(cfg, ndev, true, true); - } else if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, - &p2p->status)) { - brcmf_dbg(TRACE, "*** Wake UP ** abort listen for next af frame\n"); - /* So abort scan to cancel listen */ - brcmf_notify_escan_complete(cfg, ndev, true, true); - } -} - - -/** - * brcmf_p2p_gon_req_collision() - Check if go negotiaton collission - * - * @p2p: p2p device info struct. - * - * return true if recevied action frame is to be dropped. - */ -static bool -brcmf_p2p_gon_req_collision(struct brcmf_p2p_info *p2p, u8 *mac) -{ - struct brcmf_cfg80211_info *cfg = p2p->cfg; - struct brcmf_if *ifp; - - brcmf_dbg(TRACE, "Enter\n"); - - if (!test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) || - !p2p->gon_req_action) - return false; - - brcmf_dbg(TRACE, "GO Negotiation Request COLLISION !!!\n"); - /* if sa(peer) addr is less than da(my) addr, then this device - * process peer's gon request and block to send gon req. - * if not (sa addr > da addr), - * this device will process gon request and drop gon req of peer. - */ - ifp = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->ifp; - if (memcmp(mac, ifp->mac_addr, ETH_ALEN) < 0) { - brcmf_dbg(INFO, "Block transmit gon req !!!\n"); - p2p->block_gon_req_tx = true; - /* if we are finding a common channel for sending af, - * do not scan more to block to send current gon req - */ - if (test_and_clear_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, - &p2p->status)) - complete(&p2p->afx_hdl.act_frm_scan); - if (test_and_clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, - &p2p->status)) - brcmf_p2p_stop_wait_next_action_frame(cfg); - return false; - } - - /* drop gon request of peer to process gon request by this device. */ - brcmf_dbg(INFO, "Drop received gon req !!!\n"); - - return true; -} - - -/** - * brcmf_p2p_notify_action_frame_rx() - received action frame. - * - * @ifp: interfac control. - * @e: event message. Not used, to make it usable for fweh event dispatcher. - * @data: payload of message, containing action frame data. - * - */ -int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data) -{ - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct afx_hdl *afx_hdl = &p2p->afx_hdl; - struct wireless_dev *wdev; - u32 mgmt_frame_len = e->datalen - sizeof(struct brcmf_rx_mgmt_data); - struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; - u8 *frame = (u8 *)(rxframe + 1); - struct brcmf_p2p_pub_act_frame *act_frm; - struct brcmf_p2psd_gas_pub_act_frame *sd_act_frm; - u16 chanspec = be16_to_cpu(rxframe->chanspec); - struct ieee80211_mgmt *mgmt_frame; - s32 freq; - u16 mgmt_type; - u8 action; - - /* Check if wpa_supplicant has registered for this frame */ - brcmf_dbg(INFO, "ifp->vif->mgmt_rx_reg %04x\n", ifp->vif->mgmt_rx_reg); - mgmt_type = (IEEE80211_STYPE_ACTION & IEEE80211_FCTL_STYPE) >> 4; - if ((ifp->vif->mgmt_rx_reg & BIT(mgmt_type)) == 0) - return 0; - - brcmf_p2p_print_actframe(false, frame, mgmt_frame_len); - - action = P2P_PAF_SUBTYPE_INVALID; - if (brcmf_p2p_is_pub_action(frame, mgmt_frame_len)) { - act_frm = (struct brcmf_p2p_pub_act_frame *)frame; - action = act_frm->subtype; - if ((action == P2P_PAF_GON_REQ) && - (brcmf_p2p_gon_req_collision(p2p, (u8 *)e->addr))) { - if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, - &p2p->status) && - (memcmp(afx_hdl->tx_dst_addr, e->addr, - ETH_ALEN) == 0)) { - afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); - brcmf_dbg(INFO, "GON request: Peer found, channel=%d\n", - afx_hdl->peer_chan); - complete(&afx_hdl->act_frm_scan); - } - return 0; - } - /* After complete GO Negotiation, roll back to mpc mode */ - if ((action == P2P_PAF_GON_CONF) || - (action == P2P_PAF_PROVDIS_RSP)) - brcmf_set_mpc(ifp->ndev, 1); - if (action == P2P_PAF_GON_CONF) { - brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); - clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - } - } else if (brcmf_p2p_is_gas_action(frame, mgmt_frame_len)) { - sd_act_frm = (struct brcmf_p2psd_gas_pub_act_frame *)frame; - action = sd_act_frm->action; - } - - if (test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) && - (p2p->next_af_subtype == action)) { - brcmf_dbg(TRACE, "We got a right next frame! (%d)\n", action); - clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, - &p2p->status); - /* Stop waiting for next AF. */ - brcmf_p2p_stop_wait_next_action_frame(cfg); - } - - mgmt_frame = kzalloc(offsetof(struct ieee80211_mgmt, u) + - mgmt_frame_len, GFP_KERNEL); - if (!mgmt_frame) { - brcmf_err("No memory available for action frame\n"); - return -ENOMEM; - } - memcpy(mgmt_frame->da, ifp->mac_addr, ETH_ALEN); - brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSSID, mgmt_frame->bssid, - ETH_ALEN); - memcpy(mgmt_frame->sa, e->addr, ETH_ALEN); - mgmt_frame->frame_control = cpu_to_le16(IEEE80211_STYPE_ACTION); - memcpy(&mgmt_frame->u, frame, mgmt_frame_len); - mgmt_frame_len += offsetof(struct ieee80211_mgmt, u); - - freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), - CHSPEC_IS2G(chanspec) ? - IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ); - wdev = ifp->ndev->ieee80211_ptr; - cfg80211_rx_mgmt(wdev, freq, 0, (u8 *)mgmt_frame, mgmt_frame_len, - GFP_ATOMIC); - - kfree(mgmt_frame); - return 0; -} - - -/** - * brcmf_p2p_notify_action_tx_complete() - transmit action frame complete - * - * @ifp: interfac control. - * @e: event message. Not used, to make it usable for fweh event dispatcher. - * @data: not used. - * - */ -int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data) -{ - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct brcmf_p2p_info *p2p = &cfg->p2p; - - brcmf_dbg(INFO, "Enter: event %s, status=%d\n", - e->event_code == BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE ? - "ACTION_FRAME_OFF_CHAN_COMPLETE" : "ACTION_FRAME_COMPLETE", - e->status); - - if (!test_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status)) - return 0; - - if (e->event_code == BRCMF_E_ACTION_FRAME_COMPLETE) { - if (e->status == BRCMF_E_STATUS_SUCCESS) - set_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, - &p2p->status); - else { - set_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status); - /* If there is no ack, we don't need to wait for - * WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE event - */ - brcmf_p2p_stop_wait_next_action_frame(cfg); - } - - } else { - complete(&p2p->send_af_done); - } - return 0; -} - - -/** - * brcmf_p2p_tx_action_frame() - send action frame over fil. - * - * @p2p: p2p info struct for vif. - * @af_params: action frame data/info. - * - * Send an action frame immediately without doing channel synchronization. - * - * This function waits for a completion event before returning. - * The WLC_E_ACTION_FRAME_COMPLETE event will be received when the action - * frame is transmitted. - */ -static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, - struct brcmf_fil_af_params_le *af_params) -{ - struct brcmf_cfg80211_vif *vif; - s32 err = 0; - s32 timeout = 0; - - brcmf_dbg(TRACE, "Enter\n"); - - INIT_COMPLETION(p2p->send_af_done); - clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status); - clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status); - - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params, - sizeof(*af_params)); - if (err) { - brcmf_err(" sending action frame has failed\n"); - goto exit; - } - - p2p->af_sent_channel = le32_to_cpu(af_params->channel); - p2p->af_tx_sent_jiffies = jiffies; - - timeout = wait_for_completion_timeout(&p2p->send_af_done, - msecs_to_jiffies(P2P_AF_MAX_WAIT_TIME)); - - if (test_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status)) { - brcmf_dbg(TRACE, "TX action frame operation is success\n"); - } else { - err = -EIO; - brcmf_dbg(TRACE, "TX action frame operation has failed\n"); - } - /* clear status bit for action tx */ - clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status); - clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status); - -exit: - return err; -} - - -/** - * brcmf_p2p_pub_af_tx() - public action frame tx routine. - * - * @cfg: driver private data for cfg80211 interface. - * @af_params: action frame data/info. - * @config_af_params: configuration data for action frame. - * - * routine which transmits ation frame public type. - */ -static s32 brcmf_p2p_pub_af_tx(struct brcmf_cfg80211_info *cfg, - struct brcmf_fil_af_params_le *af_params, - struct brcmf_config_af_params *config_af_params) -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_fil_action_frame_le *action_frame; - struct brcmf_p2p_pub_act_frame *act_frm; - s32 err = 0; - u16 ie_len; - - action_frame = &af_params->action_frame; - act_frm = (struct brcmf_p2p_pub_act_frame *)(action_frame->data); - - config_af_params->extra_listen = true; - - switch (act_frm->subtype) { - case P2P_PAF_GON_REQ: - brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status set\n"); - set_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - config_af_params->mpc_onoff = 0; - config_af_params->search_channel = true; - p2p->next_af_subtype = act_frm->subtype + 1; - p2p->gon_req_action = true; - /* increase dwell time to wait for RESP frame */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME); - break; - case P2P_PAF_GON_RSP: - p2p->next_af_subtype = act_frm->subtype + 1; - /* increase dwell time to wait for CONF frame */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME); - break; - case P2P_PAF_GON_CONF: - /* If we reached till GO Neg confirmation reset the filter */ - brcmf_dbg(TRACE, "P2P: GO_NEG_PHASE status cleared\n"); - clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - /* turn on mpc again if go nego is done */ - config_af_params->mpc_onoff = 1; - /* minimize dwell time */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME); - config_af_params->extra_listen = false; - break; - case P2P_PAF_INVITE_REQ: - config_af_params->search_channel = true; - p2p->next_af_subtype = act_frm->subtype + 1; - /* increase dwell time */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME); - break; - case P2P_PAF_INVITE_RSP: - /* minimize dwell time */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME); - config_af_params->extra_listen = false; - break; - case P2P_PAF_DEVDIS_REQ: - config_af_params->search_channel = true; - p2p->next_af_subtype = act_frm->subtype + 1; - /* maximize dwell time to wait for RESP frame */ - af_params->dwell_time = cpu_to_le32(P2P_AF_LONG_DWELL_TIME); - break; - case P2P_PAF_DEVDIS_RSP: - /* minimize dwell time */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MIN_DWELL_TIME); - config_af_params->extra_listen = false; - break; - case P2P_PAF_PROVDIS_REQ: - ie_len = le16_to_cpu(action_frame->len) - - offsetof(struct brcmf_p2p_pub_act_frame, elts); - if (cfg80211_get_p2p_attr(&act_frm->elts[0], ie_len, - IEEE80211_P2P_ATTR_GROUP_ID, - NULL, 0) < 0) - config_af_params->search_channel = true; - config_af_params->mpc_onoff = 0; - p2p->next_af_subtype = act_frm->subtype + 1; - /* increase dwell time to wait for RESP frame */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME); - break; - case P2P_PAF_PROVDIS_RSP: - /* wpa_supplicant send go nego req right after prov disc */ - p2p->next_af_subtype = P2P_PAF_GON_REQ; - /* increase dwell time to MED level */ - af_params->dwell_time = cpu_to_le32(P2P_AF_MED_DWELL_TIME); - config_af_params->extra_listen = false; - break; - default: - brcmf_err("Unknown p2p pub act frame subtype: %d\n", - act_frm->subtype); - err = -EINVAL; - } - return err; -} - -/** - * brcmf_p2p_send_action_frame() - send action frame . - * - * @cfg: driver private data for cfg80211 interface. - * @ndev: net device to transmit on. - * @af_params: configuration data for action frame. - */ -bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - struct brcmf_fil_af_params_le *af_params) -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_fil_action_frame_le *action_frame; - struct brcmf_config_af_params config_af_params; - struct afx_hdl *afx_hdl = &p2p->afx_hdl; - u16 action_frame_len; - bool ack = false; - u8 category; - u8 action; - s32 tx_retry; - s32 extra_listen_time; - uint delta_ms; - - action_frame = &af_params->action_frame; - action_frame_len = le16_to_cpu(action_frame->len); - - brcmf_p2p_print_actframe(true, action_frame->data, action_frame_len); - - /* Add the default dwell time. Dwell time to stay off-channel */ - /* to wait for a response action frame after transmitting an */ - /* GO Negotiation action frame */ - af_params->dwell_time = cpu_to_le32(P2P_AF_DWELL_TIME); - - category = action_frame->data[DOT11_ACTION_CAT_OFF]; - action = action_frame->data[DOT11_ACTION_ACT_OFF]; - - /* initialize variables */ - p2p->next_af_subtype = P2P_PAF_SUBTYPE_INVALID; - p2p->gon_req_action = false; - - /* config parameters */ - config_af_params.mpc_onoff = -1; - config_af_params.search_channel = false; - config_af_params.extra_listen = false; - - if (brcmf_p2p_is_pub_action(action_frame->data, action_frame_len)) { - /* p2p public action frame process */ - if (brcmf_p2p_pub_af_tx(cfg, af_params, &config_af_params)) { - /* Just send unknown subtype frame with */ - /* default parameters. */ - brcmf_err("P2P Public action frame, unknown subtype.\n"); - } - } else if (brcmf_p2p_is_gas_action(action_frame->data, - action_frame_len)) { - /* service discovery process */ - if (action == P2PSD_ACTION_ID_GAS_IREQ || - action == P2PSD_ACTION_ID_GAS_CREQ) { - /* configure service discovery query frame */ - config_af_params.search_channel = true; - - /* save next af suptype to cancel */ - /* remaining dwell time */ - p2p->next_af_subtype = action + 1; - - af_params->dwell_time = - cpu_to_le32(P2P_AF_MED_DWELL_TIME); - } else if (action == P2PSD_ACTION_ID_GAS_IRESP || - action == P2PSD_ACTION_ID_GAS_CRESP) { - /* configure service discovery response frame */ - af_params->dwell_time = - cpu_to_le32(P2P_AF_MIN_DWELL_TIME); - } else { - brcmf_err("Unknown action type: %d\n", action); - goto exit; - } - } else if (brcmf_p2p_is_p2p_action(action_frame->data, - action_frame_len)) { - /* do not configure anything. it will be */ - /* sent with a default configuration */ - } else { - brcmf_err("Unknown Frame: category 0x%x, action 0x%x\n", - category, action); - return false; - } - - /* if connecting on primary iface, sleep for a while before sending - * af tx for VSDB - */ - if (test_bit(BRCMF_VIF_STATUS_CONNECTING, - &p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->sme_state)) - msleep(50); - - /* if scan is ongoing, abort current scan. */ - if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) - brcmf_abort_scanning(cfg); - - memcpy(afx_hdl->tx_dst_addr, action_frame->da, ETH_ALEN); - - /* To make sure to send successfully action frame, turn off mpc */ - if (config_af_params.mpc_onoff == 0) - brcmf_set_mpc(ndev, 0); - - /* set status and destination address before sending af */ - if (p2p->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) { - /* set status to cancel the remained dwell time in rx process */ - set_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); - } - - p2p->af_sent_channel = 0; - set_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status); - /* validate channel and p2p ies */ - if (config_af_params.search_channel && - IS_P2P_SOCIAL_CHANNEL(le32_to_cpu(af_params->channel)) && - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif->saved_ie.probe_req_ie_len) { - afx_hdl = &p2p->afx_hdl; - afx_hdl->peer_listen_chan = le32_to_cpu(af_params->channel); - - if (brcmf_p2p_af_searching_channel(p2p) == - P2P_INVALID_CHANNEL) { - brcmf_err("Couldn't find peer's channel.\n"); - goto exit; - } - - /* Abort scan even for VSDB scenarios. Scan gets aborted in - * firmware but after the check of piggyback algorithm. To take - * care of current piggback algo, lets abort the scan here - * itself. - */ - brcmf_notify_escan_complete(cfg, ndev, true, true); - - /* update channel */ - af_params->channel = cpu_to_le32(afx_hdl->peer_chan); - } - - tx_retry = 0; - while (!p2p->block_gon_req_tx && - (ack == false) && (tx_retry < P2P_AF_TX_MAX_RETRY)) { - ack = !brcmf_p2p_tx_action_frame(p2p, af_params); - tx_retry++; - } - if (ack == false) { - brcmf_err("Failed to send Action Frame(retry %d)\n", tx_retry); - clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - } - -exit: - clear_bit(BRCMF_P2P_STATUS_SENDING_ACT_FRAME, &p2p->status); - - /* WAR: sometimes dongle does not keep the dwell time of 'actframe'. - * if we coundn't get the next action response frame and dongle does - * not keep the dwell time, go to listen state again to get next action - * response frame. - */ - if (ack && config_af_params.extra_listen && !p2p->block_gon_req_tx && - test_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status) && - p2p->af_sent_channel == afx_hdl->my_listen_chan) { - delta_ms = jiffies_to_msecs(jiffies - p2p->af_tx_sent_jiffies); - if (le32_to_cpu(af_params->dwell_time) > delta_ms) - extra_listen_time = le32_to_cpu(af_params->dwell_time) - - delta_ms; - else - extra_listen_time = 0; - if (extra_listen_time > 50) { - set_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, - &p2p->status); - brcmf_dbg(INFO, "Wait more time! actual af time:%d, calculated extra listen:%d\n", - le32_to_cpu(af_params->dwell_time), - extra_listen_time); - extra_listen_time += 100; - if (!brcmf_p2p_discover_listen(p2p, - p2p->af_sent_channel, - extra_listen_time)) { - unsigned long duration; - - extra_listen_time += 100; - duration = msecs_to_jiffies(extra_listen_time); - wait_for_completion_timeout(&p2p->wait_next_af, - duration); - } - clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, - &p2p->status); - } - } - - if (p2p->block_gon_req_tx) { - /* if ack is true, supplicant will wait more time(100ms). - * so we will return it as a success to get more time . - */ - p2p->block_gon_req_tx = false; - ack = true; - } - - clear_bit(BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, &p2p->status); - /* if all done, turn mpc on again */ - if (config_af_params.mpc_onoff == 1) - brcmf_set_mpc(ndev, 1); - - return ack; -} - -/** - * brcmf_p2p_notify_rx_mgmt_p2p_probereq() - Event handler for p2p probe req. - * - * @ifp: interface pointer for which event was received. - * @e: even message. - * @data: payload of event message (probe request). - */ -s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data) -{ - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct afx_hdl *afx_hdl = &p2p->afx_hdl; - struct wireless_dev *wdev; - struct brcmf_cfg80211_vif *vif = ifp->vif; - struct brcmf_rx_mgmt_data *rxframe = (struct brcmf_rx_mgmt_data *)data; - u16 chanspec = be16_to_cpu(rxframe->chanspec); - u8 *mgmt_frame; - u32 mgmt_frame_len; - s32 freq; - u16 mgmt_type; - - brcmf_dbg(INFO, "Enter: event %d reason %d\n", e->event_code, - e->reason); - - if (test_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status) && - (memcmp(afx_hdl->tx_dst_addr, e->addr, ETH_ALEN) == 0)) { - afx_hdl->peer_chan = CHSPEC_CHANNEL(chanspec); - brcmf_dbg(INFO, "PROBE REQUEST: Peer found, channel=%d\n", - afx_hdl->peer_chan); - complete(&afx_hdl->act_frm_scan); - } - - /* Firmware sends us two proberesponses for each idx one. At the */ - /* moment anything but bsscfgidx 0 is passed up to supplicant */ - if (e->bsscfgidx == 0) - return 0; - - /* Filter any P2P probe reqs arriving during the GO-NEG Phase */ - if (test_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status)) { - brcmf_dbg(INFO, "Filtering P2P probe_req in GO-NEG phase\n"); - return 0; - } - - /* Check if wpa_supplicant has registered for this frame */ - brcmf_dbg(INFO, "vif->mgmt_rx_reg %04x\n", vif->mgmt_rx_reg); - mgmt_type = (IEEE80211_STYPE_PROBE_REQ & IEEE80211_FCTL_STYPE) >> 4; - if ((vif->mgmt_rx_reg & BIT(mgmt_type)) == 0) - return 0; - - mgmt_frame = (u8 *)(rxframe + 1); - mgmt_frame_len = e->datalen - sizeof(*rxframe); - freq = ieee80211_channel_to_frequency(CHSPEC_CHANNEL(chanspec), - CHSPEC_IS2G(chanspec) ? - IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ); - wdev = ifp->ndev->ieee80211_ptr; - cfg80211_rx_mgmt(wdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); - - brcmf_dbg(INFO, "mgmt_frame_len (%d) , e->datalen (%d), chanspec (%04x), freq (%d)\n", - mgmt_frame_len, e->datalen, chanspec, freq); - - return 0; -} - - -/** - * brcmf_p2p_attach() - attach for P2P. - * - * @cfg: driver private data for cfg80211 interface. - */ -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg) -{ - struct brcmf_if *pri_ifp; - struct brcmf_if *p2p_ifp; - struct brcmf_cfg80211_vif *p2p_vif; - struct brcmf_p2p_info *p2p; - struct brcmf_pub *drvr; - s32 bssidx; - s32 err = 0; - - p2p = &cfg->p2p; - p2p->cfg = cfg; - - drvr = cfg->pub; - - pri_ifp = drvr->iflist[0]; - p2p_ifp = drvr->iflist[1]; - - p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif; - - if (p2p_ifp) { - p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE, - false); - if (IS_ERR(p2p_vif)) { - brcmf_err("could not create discovery vif\n"); - err = -ENOMEM; - goto exit; - } - - p2p_vif->ifp = p2p_ifp; - p2p_ifp->vif = p2p_vif; - p2p_vif->wdev.netdev = p2p_ifp->ndev; - p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev; - SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy)); - - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif; - - brcmf_p2p_generate_bss_mac(p2p); - brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr); - - /* Initialize P2P Discovery in the firmware */ - err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1); - if (err < 0) { - brcmf_err("set p2p_disc error\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* obtain bsscfg index for P2P discovery */ - err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); - if (err < 0) { - brcmf_err("retrieving discover bsscfg index failed\n"); - brcmf_free_vif(p2p_vif); - goto exit; - } - /* Verify that firmware uses same bssidx as driver !! */ - if (p2p_ifp->bssidx != bssidx) { - brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n", - bssidx, p2p_ifp->bssidx); - brcmf_free_vif(p2p_vif); - goto exit; - } - - init_completion(&p2p->send_af_done); - INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); - init_completion(&p2p->afx_hdl.act_frm_scan); - init_completion(&p2p->wait_next_af); - } -exit: - return err; -} - - -/** - * brcmf_p2p_detach() - detach P2P. - * - * @p2p: P2P specific data. - */ -void brcmf_p2p_detach(struct brcmf_p2p_info *p2p) -{ - struct brcmf_cfg80211_vif *vif; - - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - if (vif != NULL) { - brcmf_p2p_cancel_remain_on_channel(vif->ifp); - brcmf_p2p_deinit_discovery(p2p); - /* remove discovery interface */ - brcmf_free_vif(vif); - p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; - } - /* just set it all to zero */ - memset(p2p, 0, sizeof(*p2p)); -} - -/** - * brcmf_p2p_get_current_chanspec() - Get current operation channel. - * - * @p2p: P2P specific data. - * @chanspec: chanspec to be returned. - */ -static void brcmf_p2p_get_current_chanspec(struct brcmf_p2p_info *p2p, - u16 *chanspec) -{ - struct brcmf_if *ifp; - struct brcmf_fil_chan_info_le ci; - s32 err; - - ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; - - *chanspec = 11 & WL_CHANSPEC_CHAN_MASK; - - err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, &ci, sizeof(ci)); - if (!err) { - *chanspec = le32_to_cpu(ci.hw_channel) & WL_CHANSPEC_CHAN_MASK; - if (*chanspec < CH_MAX_2G_CHANNEL) - *chanspec |= WL_CHANSPEC_BAND_2G; - else - *chanspec |= WL_CHANSPEC_BAND_5G; - } - *chanspec |= WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; -} - -/** - * Change a P2P Role. - * Parameters: - * @mac: MAC address of the BSS to change a role - * Returns 0 if success. - */ -int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, - enum brcmf_fil_p2p_if_types if_type) -{ - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_cfg80211_vif *vif; - struct brcmf_fil_p2p_if_le if_request; - s32 err; - u16 chanspec; - - brcmf_dbg(TRACE, "Enter\n"); - - vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif; - if (!vif) { - brcmf_err("vif for P2PAPI_BSSCFG_PRIMARY does not exist\n"); - return -EPERM; - } - brcmf_notify_escan_complete(cfg, vif->ifp->ndev, true, true); - vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; - if (!vif) { - brcmf_err("vif for P2PAPI_BSSCFG_CONNECTION does not exist\n"); - return -EPERM; - } - brcmf_set_mpc(vif->ifp->ndev, 0); - - /* In concurrency case, STA may be already associated in a particular */ - /* channel. so retrieve the current channel of primary interface and */ - /* then start the virtual interface on that. */ - brcmf_p2p_get_current_chanspec(p2p, &chanspec); - - if_request.type = cpu_to_le16((u16)if_type); - if_request.chspec = cpu_to_le16(chanspec); - memcpy(if_request.addr, p2p->int_addr, sizeof(if_request.addr)); - - brcmf_cfg80211_arm_vif_event(cfg, vif); - err = brcmf_fil_iovar_data_set(vif->ifp, "p2p_ifupd", &if_request, - sizeof(if_request)); - if (err) { - brcmf_err("p2p_ifupd FAILED, err=%d\n", err); - brcmf_cfg80211_arm_vif_event(cfg, NULL); - return err; - } - err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_CHANGE, - msecs_to_jiffies(1500)); - brcmf_cfg80211_arm_vif_event(cfg, NULL); - if (!err) { - brcmf_err("No BRCMF_E_IF_CHANGE event received\n"); - return -EIO; - } - - err = brcmf_fil_cmd_int_set(vif->ifp, BRCMF_C_SET_SCB_TIMEOUT, - BRCMF_SCB_TIMEOUT_VALUE); - - return err; -} - -static int brcmf_p2p_request_p2p_if(struct brcmf_p2p_info *p2p, - struct brcmf_if *ifp, u8 ea[ETH_ALEN], - enum brcmf_fil_p2p_if_types iftype) -{ - struct brcmf_fil_p2p_if_le if_request; - int err; - u16 chanspec; - - /* we need a default channel */ - brcmf_p2p_get_current_chanspec(p2p, &chanspec); - - /* fill the firmware request */ - memcpy(if_request.addr, ea, ETH_ALEN); - if_request.type = cpu_to_le16((u16)iftype); - if_request.chspec = cpu_to_le16(chanspec); - - err = brcmf_fil_iovar_data_set(ifp, "p2p_ifadd", &if_request, - sizeof(if_request)); - if (err) - return err; - - return err; -} - -static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif) -{ - struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev); - struct net_device *pri_ndev = cfg_to_ndev(cfg); - struct brcmf_if *ifp = netdev_priv(pri_ndev); - u8 *addr = vif->wdev.netdev->dev_addr; - - return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN); -} - -static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif) -{ - struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev); - struct net_device *pri_ndev = cfg_to_ndev(cfg); - struct brcmf_if *ifp = netdev_priv(pri_ndev); - u8 *addr = vif->wdev.netdev->dev_addr; - - return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN); -} - -/** - * brcmf_p2p_add_vif() - create a new P2P virtual interface. - * - * @wiphy: wiphy device of new interface. - * @name: name of the new interface. - * @type: nl80211 interface type. - * @flags: TBD - * @params: TBD - */ -struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); - struct brcmf_cfg80211_vif *vif; - enum brcmf_fil_p2p_if_types iftype; - enum wl_mode mode; - int err; - - if (brcmf_cfg80211_vif_event_armed(cfg)) - return ERR_PTR(-EBUSY); - - brcmf_dbg(INFO, "adding vif \"%s\" (type=%d)\n", name, type); - - switch (type) { - case NL80211_IFTYPE_P2P_CLIENT: - iftype = BRCMF_FIL_P2P_IF_CLIENT; - mode = WL_MODE_BSS; - break; - case NL80211_IFTYPE_P2P_GO: - iftype = BRCMF_FIL_P2P_IF_GO; - mode = WL_MODE_AP; - break; - default: - return ERR_PTR(-EOPNOTSUPP); - } - - vif = brcmf_alloc_vif(cfg, type, false); - if (IS_ERR(vif)) - return (struct wireless_dev *)vif; - brcmf_cfg80211_arm_vif_event(cfg, vif); - - err = brcmf_p2p_request_p2p_if(&cfg->p2p, ifp, cfg->p2p.int_addr, - iftype); - if (err) { - brcmf_cfg80211_arm_vif_event(cfg, NULL); - goto fail; - } - - /* wait for firmware event */ - err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD, - msecs_to_jiffies(1500)); - brcmf_cfg80211_arm_vif_event(cfg, NULL); - if (!err) { - brcmf_err("timeout occurred\n"); - err = -EIO; - goto fail; - } - - /* interface created in firmware */ - ifp = vif->ifp; - if (!ifp) { - brcmf_err("no if pointer provided\n"); - err = -ENOENT; - goto fail; - } - - strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1); - err = brcmf_net_attach(ifp, true); - if (err) { - brcmf_err("Registering netdevice failed\n"); - goto fail; - } - cfg->p2p.bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = vif; - /* Disable firmware roaming for P2P interface */ - brcmf_fil_iovar_int_set(ifp, "roam_off", 1); - if (iftype == BRCMF_FIL_P2P_IF_GO) { - /* set station timeout for p2p */ - brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCB_TIMEOUT, - BRCMF_SCB_TIMEOUT_VALUE); - } - return &ifp->vif->wdev; - -fail: - brcmf_free_vif(vif); - return ERR_PTR(err); -} - -/** - * brcmf_p2p_del_vif() - delete a P2P virtual interface. - * - * @wiphy: wiphy device of interface. - * @wdev: wireless device of interface. - * - * TODO: not yet supported. - */ -int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) -{ - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct brcmf_p2p_info *p2p = &cfg->p2p; - struct brcmf_cfg80211_vif *vif; - unsigned long jiffie_timeout = msecs_to_jiffies(1500); - bool wait_for_disable = false; - int err; - - brcmf_dbg(TRACE, "delete P2P vif\n"); - vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); - - switch (vif->wdev.iftype) { - case NL80211_IFTYPE_P2P_CLIENT: - if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state)) - wait_for_disable = true; - break; - - case NL80211_IFTYPE_P2P_GO: - if (!brcmf_p2p_disable_p2p_if(vif)) - wait_for_disable = true; - break; - - case NL80211_IFTYPE_P2P_DEVICE: - default: - return -ENOTSUPP; - break; - } - - clear_bit(BRCMF_P2P_STATUS_GO_NEG_PHASE, &p2p->status); - brcmf_dbg(INFO, "P2P: GO_NEG_PHASE status cleared\n"); - - if (wait_for_disable) - wait_for_completion_timeout(&cfg->vif_disabled, - msecs_to_jiffies(500)); - - brcmf_vif_clear_mgmt_ies(vif); - - brcmf_cfg80211_arm_vif_event(cfg, vif); - err = brcmf_p2p_release_p2p_if(vif); - if (!err) { - /* wait for firmware event */ - err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL, - jiffie_timeout); - if (!err) - err = -EIO; - else - err = 0; - } - brcmf_cfg80211_arm_vif_event(cfg, NULL); - brcmf_free_vif(vif); - p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif = NULL; - - return err; -} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.h deleted file mode 100644 index 6821b26224be..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/p2p.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2012 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef WL_CFGP2P_H_ -#define WL_CFGP2P_H_ - -#include - -struct brcmf_cfg80211_info; - -/** - * enum p2p_bss_type - different type of BSS configurations. - * - * @P2PAPI_BSSCFG_PRIMARY: maps to driver's primary bsscfg. - * @P2PAPI_BSSCFG_DEVICE: maps to driver's P2P device discovery bsscfg. - * @P2PAPI_BSSCFG_CONNECTION: maps to driver's P2P connection bsscfg. - * @P2PAPI_BSSCFG_MAX: used for range checking. - */ -enum p2p_bss_type { - P2PAPI_BSSCFG_PRIMARY, /* maps to driver's primary bsscfg */ - P2PAPI_BSSCFG_DEVICE, /* maps to driver's P2P device discovery bsscfg */ - P2PAPI_BSSCFG_CONNECTION, /* maps to driver's P2P connection bsscfg */ - P2PAPI_BSSCFG_MAX -}; - -/** - * struct p2p_bss - peer-to-peer bss related information. - * - * @vif: virtual interface of this P2P bss. - * @private_data: TBD - */ -struct p2p_bss { - struct brcmf_cfg80211_vif *vif; - void *private_data; -}; - -/** - * enum brcmf_p2p_status - P2P specific dongle status. - * - * @BRCMF_P2P_STATUS_IF_ADD: peer-to-peer vif add sent to dongle. - * @BRCMF_P2P_STATUS_IF_DEL: NOT-USED? - * @BRCMF_P2P_STATUS_IF_DELETING: peer-to-peer vif delete sent to dongle. - * @BRCMF_P2P_STATUS_IF_CHANGING: peer-to-peer vif change sent to dongle. - * @BRCMF_P2P_STATUS_IF_CHANGED: peer-to-peer vif change completed on dongle. - * @BRCMF_P2P_STATUS_ACTION_TX_COMPLETED: action frame tx completed. - * @BRCMF_P2P_STATUS_ACTION_TX_NOACK: action frame tx not acked. - * @BRCMF_P2P_STATUS_GO_NEG_PHASE: P2P GO negotiation ongoing. - * @BRCMF_P2P_STATUS_DISCOVER_LISTEN: P2P listen, remaining on channel. - * @BRCMF_P2P_STATUS_SENDING_ACT_FRAME: In the process of sending action frame. - * @BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN: extra listen time for af tx. - * @BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME: waiting for action frame response. - * @BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL: search channel for AF active. - */ -enum brcmf_p2p_status { - BRCMF_P2P_STATUS_ENABLED, - BRCMF_P2P_STATUS_IF_ADD, - BRCMF_P2P_STATUS_IF_DEL, - BRCMF_P2P_STATUS_IF_DELETING, - BRCMF_P2P_STATUS_IF_CHANGING, - BRCMF_P2P_STATUS_IF_CHANGED, - BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, - BRCMF_P2P_STATUS_ACTION_TX_NOACK, - BRCMF_P2P_STATUS_GO_NEG_PHASE, - BRCMF_P2P_STATUS_DISCOVER_LISTEN, - BRCMF_P2P_STATUS_SENDING_ACT_FRAME, - BRCMF_P2P_STATUS_WAITING_NEXT_AF_LISTEN, - BRCMF_P2P_STATUS_WAITING_NEXT_ACT_FRAME, - BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL -}; - -/** - * struct afx_hdl - action frame off channel storage. - * - * @afx_work: worker thread for searching channel - * @act_frm_scan: thread synchronizing struct. - * @is_active: channel searching active. - * @peer_chan: current channel. - * @is_listen: sets mode for afx worker. - * @my_listen_chan: this peers listen channel. - * @peer_listen_chan: remote peers listen channel. - * @tx_dst_addr: mac address where tx af should be sent to. - */ -struct afx_hdl { - struct work_struct afx_work; - struct completion act_frm_scan; - bool is_active; - s32 peer_chan; - bool is_listen; - u16 my_listen_chan; - u16 peer_listen_chan; - u8 tx_dst_addr[ETH_ALEN]; -}; - -/** - * struct brcmf_p2p_info - p2p specific driver information. - * - * @cfg: driver private data for cfg80211 interface. - * @status: status of P2P (see enum brcmf_p2p_status). - * @dev_addr: P2P device address. - * @int_addr: P2P interface address. - * @bss_idx: informate for P2P bss types. - * @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state. - * @ssid: ssid for P2P GO. - * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state. - * @remain_on_channel: contains copy of struct used by cfg80211. - * @remain_on_channel_cookie: cookie counter for remain on channel cmd - * @next_af_subtype: expected action frame subtype. - * @send_af_done: indication that action frame tx is complete. - * @afx_hdl: action frame search handler info. - * @af_sent_channel: channel action frame is sent. - * @af_tx_sent_jiffies: jiffies time when af tx was transmitted. - * @wait_next_af: thread synchronizing struct. - * @gon_req_action: about to send go negotiation requets frame. - * @block_gon_req_tx: drop tx go negotiation requets frame. - */ -struct brcmf_p2p_info { - struct brcmf_cfg80211_info *cfg; - unsigned long status; - u8 dev_addr[ETH_ALEN]; - u8 int_addr[ETH_ALEN]; - struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX]; - struct timer_list listen_timer; - struct brcmf_ssid ssid; - u8 listen_channel; - struct ieee80211_channel remain_on_channel; - u32 remain_on_channel_cookie; - u8 next_af_subtype; - struct completion send_af_done; - struct afx_hdl afx_hdl; - u32 af_sent_channel; - unsigned long af_tx_sent_jiffies; - struct completion wait_next_af; - bool gon_req_action; - bool block_gon_req_tx; -}; - -s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg); -void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); -struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params); -int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev); -int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, - enum brcmf_fil_p2p_if_types if_type); -int brcmf_p2p_start_device(struct wiphy *wiphy, struct wireless_dev *wdev); -void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev); -int brcmf_p2p_scan_prep(struct wiphy *wiphy, - struct cfg80211_scan_request *request, - struct brcmf_cfg80211_vif *vif); -int brcmf_p2p_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *channel, - unsigned int duration, u64 *cookie); -int brcmf_p2p_notify_listen_complete(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data); -void brcmf_p2p_cancel_remain_on_channel(struct brcmf_if *ifp); -int brcmf_p2p_notify_action_frame_rx(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data); -int brcmf_p2p_notify_action_tx_complete(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data); -bool brcmf_p2p_send_action_frame(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - struct brcmf_fil_af_params_le *af_params); -bool brcmf_p2p_scan_finding_common_channel(struct brcmf_cfg80211_info *cfg, - struct brcmf_bss_info_le *bi); -s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, - void *data); -#endif /* WL_CFGP2P_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a55994d33763..e15630cc3889 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -421,6 +421,10 @@ static void brcmf_usb_tx_complete(struct urb *urb) brcmf_dbg(USB, "Enter, urb->status=%d, skb=%p\n", urb->status, req->skb); brcmf_usb_del_fromq(devinfo, req); + if (urb->status == 0) + devinfo->bus_pub.bus->dstats.tx_packets++; + else + devinfo->bus_pub.bus->dstats.tx_errors++; brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); @@ -447,7 +451,10 @@ static void brcmf_usb_rx_complete(struct urb *urb) req->skb = NULL; /* zero lenght packets indicate usb "failure". Do not refill */ - if (urb->status != 0 || !urb->actual_length) { + if (urb->status == 0 && urb->actual_length) { + devinfo->bus_pub.bus->dstats.rx_packets++; + } else { + devinfo->bus_pub.bus->dstats.rx_errors++; brcmu_pkt_buf_free_skb(skb); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req, NULL); return; @@ -1250,8 +1257,6 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) bus->bus_priv.usb = bus_pub; dev_set_drvdata(dev, bus); bus->ops = &brcmf_usb_bus_ops; - bus->chip = bus_pub->devid; - bus->chiprev = bus_pub->chiprev; /* Attach to the common driver interface */ ret = brcmf_attach(0, dev); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index cecc3eff72e9..62a528e8b958 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -26,8 +26,6 @@ #include #include "dhd.h" #include "dhd_dbg.h" -#include "fwil_types.h" -#include "p2p.h" #include "wl_cfg80211.h" #include "fwil.h" @@ -43,13 +41,16 @@ #define BRCMF_PNO_SCAN_COMPLETE 1 #define BRCMF_PNO_SCAN_INCOMPLETE 0 -#define BRCMF_IFACE_MAX_CNT 3 +#define BRCMF_IFACE_MAX_CNT 2 +#define TLV_LEN_OFF 1 /* length offset */ +#define TLV_HDR_LEN 2 /* header length */ +#define TLV_BODY_OFF 2 /* body offset */ +#define TLV_OUI_LEN 3 /* oui id length */ #define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ #define WPA_OUI_TYPE 1 #define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ #define WME_OUI_TYPE 2 -#define WPS_OUI_TYPE 4 #define VS_IE_FIXED_HDR_LEN 6 #define WPA_IE_VERSION_LEN 2 @@ -75,15 +76,13 @@ #define VNDR_IE_PKTFLAG_OFFSET 8 #define VNDR_IE_VSIE_OFFSET 12 #define VNDR_IE_HDR_SIZE 12 -#define VNDR_IE_PARSE_LIMIT 5 +#define VNDR_IE_BEACON_FLAG 0x1 +#define VNDR_IE_PRBRSP_FLAG 0x2 +#define MAX_VNDR_IE_NUMBER 5 #define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */ #define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */ -#define BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 -#define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 -#define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS 20 - #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) @@ -272,6 +271,13 @@ static const u32 __wl_cipher_suites[] = { WLAN_CIPHER_SUITE_AES_CMAC, }; +/* tag_ID/length/value_buffer tuple */ +struct brcmf_tlv { + u8 id; + u8 len; + u8 data[1]; +}; + /* Vendor specific ie. id = 221, oui and type defines exact ie */ struct brcmf_vs_tlv { u8 id; @@ -288,7 +294,7 @@ struct parsed_vndr_ie_info { struct parsed_vndr_ies { u32 count; - struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT]; + struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER]; }; /* Quarter dBm units to mW @@ -375,7 +381,7 @@ static u8 brcmf_mw_to_qdbm(u16 mw) return qdbm; } -u16 channel_to_chanspec(struct ieee80211_channel *ch) +static u16 channel_to_chanspec(struct ieee80211_channel *ch) { u16 chanspec; @@ -387,92 +393,19 @@ u16 channel_to_chanspec(struct ieee80211_channel *ch) else chanspec |= WL_CHANSPEC_BAND_5G; - chanspec |= WL_CHANSPEC_BW_20; - chanspec |= WL_CHANSPEC_CTL_SB_NONE; - - return chanspec; -} - -/* Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag - */ -struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) -{ - struct brcmf_tlv *elt; - int totlen; - - elt = (struct brcmf_tlv *)buf; - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= TLV_HDR_LEN) { - int len = elt->len; - - /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN))) - return elt; - - elt = (struct brcmf_tlv *)((u8 *)elt + (len + TLV_HDR_LEN)); - totlen -= (len + TLV_HDR_LEN); - } - - return NULL; -} - -/* Is any of the tlvs the expected entry? If - * not update the tlvs buffer pointer/length. - */ -static bool -brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, - u8 *oui, u32 oui_len, u8 type) -{ - /* If the contents match the OUI and the type */ - if (ie[TLV_LEN_OFF] >= oui_len + 1 && - !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) && - type == ie[TLV_BODY_OFF + oui_len]) { - return true; - } - - if (tlvs == NULL) - return false; - /* point to the next ie */ - ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN; - /* calculate the length of the rest of the buffer */ - *tlvs_len -= (int)(ie - *tlvs); - /* update the pointer to the start of the buffer */ - *tlvs = ie; - - return false; -} - -static struct brcmf_vs_tlv * -brcmf_find_wpaie(u8 *parse, u32 len) -{ - struct brcmf_tlv *ie; - - while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { - if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, - WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) - return (struct brcmf_vs_tlv *)ie; - } - return NULL; -} - -static struct brcmf_vs_tlv * -brcmf_find_wpsie(u8 *parse, u32 len) -{ - struct brcmf_tlv *ie; - - while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { - if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, - WPA_OUI, TLV_OUI_LEN, WPS_OUI_TYPE)) - return (struct brcmf_vs_tlv *)ie; + if (ch->flags & IEEE80211_CHAN_NO_HT40) { + chanspec |= WL_CHANSPEC_BW_20; + chanspec |= WL_CHANSPEC_CTL_SB_NONE; + } else { + chanspec |= WL_CHANSPEC_BW_40; + if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS) + chanspec |= WL_CHANSPEC_CTL_SB_LOWER; + else + chanspec |= WL_CHANSPEC_CTL_SB_UPPER; } - return NULL; + return chanspec; } - static void convert_key_from_CPU(struct brcmf_wsec_key *key, struct brcmf_wsec_key_le *key_le) { @@ -505,153 +438,11 @@ send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key) return err; } -static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, - const char *name, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ - brcmf_dbg(TRACE, "enter: %s type %d\n", name, type); - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - return ERR_PTR(-EOPNOTSUPP); - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return brcmf_p2p_add_vif(wiphy, name, type, flags, params); - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_P2P_DEVICE: - default: - return ERR_PTR(-EINVAL); - } -} - -void brcmf_set_mpc(struct net_device *ndev, int mpc) -{ - struct brcmf_if *ifp = netdev_priv(ndev); - s32 err = 0; - - if (check_vif_up(ifp->vif)) { - err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); - if (err) { - brcmf_err("fail to set mpc\n"); - return; - } - brcmf_dbg(INFO, "MPC : %d\n", mpc); - } -} - -s32 -brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - bool aborted, bool fw_abort) -{ - struct brcmf_scan_params_le params_le; - struct cfg80211_scan_request *scan_request; - s32 err = 0; - - brcmf_dbg(SCAN, "Enter\n"); - - /* clear scan request, because the FW abort can cause a second call */ - /* to this functon and might cause a double cfg80211_scan_done */ - scan_request = cfg->scan_request; - cfg->scan_request = NULL; - - if (timer_pending(&cfg->escan_timeout)) - del_timer_sync(&cfg->escan_timeout); - - if (fw_abort) { - /* Do a scan abort to stop the driver's scan engine */ - brcmf_dbg(SCAN, "ABORT scan in firmware\n"); - memset(¶ms_le, 0, sizeof(params_le)); - memset(params_le.bssid, 0xFF, ETH_ALEN); - params_le.bss_type = DOT11_BSSTYPE_ANY; - params_le.scan_type = 0; - params_le.channel_num = cpu_to_le32(1); - params_le.nprobes = cpu_to_le32(1); - params_le.active_time = cpu_to_le32(-1); - params_le.passive_time = cpu_to_le32(-1); - params_le.home_time = cpu_to_le32(-1); - /* Scan is aborted by setting channel_list[0] to -1 */ - params_le.channel_list[0] = cpu_to_le16(-1); - /* E-Scan (or anyother type) can be aborted by SCAN */ - err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, - ¶ms_le, sizeof(params_le)); - if (err) - brcmf_err("Scan abort failed\n"); - } - /* - * e-scan can be initiated by scheduled scan - * which takes precedence. - */ - if (cfg->sched_escan) { - brcmf_dbg(SCAN, "scheduled scan completed\n"); - cfg->sched_escan = false; - if (!aborted) - cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); - brcmf_set_mpc(ndev, 1); - } else if (scan_request) { - brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", - aborted ? "Aborted" : "Done"); - cfg80211_scan_done(scan_request, aborted); - brcmf_set_mpc(ndev, 1); - } - if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) - brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n"); - - return err; -} - -static -int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) -{ - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct net_device *ndev = wdev->netdev; - - /* vif event pending in firmware */ - if (brcmf_cfg80211_vif_event_armed(cfg)) - return -EBUSY; - - if (ndev) { - if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) && - cfg->escan_info.ndev == ndev) - brcmf_notify_escan_complete(cfg, ndev, true, - true); - - brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1); - } - - switch (wdev->iftype) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - return -EOPNOTSUPP; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return brcmf_p2p_del_vif(wiphy, wdev); - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_P2P_DEVICE: - default: - return -EINVAL; - } - return -EOPNOTSUPP; -} - static s32 brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_vif *vif = ifp->vif; s32 infra = 0; @@ -671,23 +462,10 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, infra = 0; break; case NL80211_IFTYPE_STATION: - /* Ignore change for p2p IF. Unclear why supplicant does this */ - if ((vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT) || - (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO)) { - brcmf_dbg(TRACE, "Ignoring cmd for p2p if\n"); - /* WAR: It is unexpected to get a change of VIF for P2P - * IF, but it happens. The request can not be handled - * but returning EPERM causes a crash. Returning 0 - * without setting ieee80211_ptr->iftype causes trace - * (WARN_ON) but it works with wpa_supplicant - */ - return 0; - } vif->mode = WL_MODE_BSS; infra = 1; break; case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: vif->mode = WL_MODE_AP; ap = 1; break; @@ -697,14 +475,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } if (ap) { - if (type == NL80211_IFTYPE_P2P_GO) { - brcmf_dbg(INFO, "IF Type = P2P GO\n"); - err = brcmf_p2p_ifchange(cfg, BRCMF_FIL_P2P_IF_GO); - } - if (!err) { - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); - brcmf_dbg(INFO, "IF Type = AP\n"); - } + set_bit(BRCMF_VIF_STATUS_AP_CREATING, &vif->sme_state); + brcmf_dbg(INFO, "IF Type = AP\n"); } else { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, infra); if (err) { @@ -723,6 +495,21 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, return err; } +static void brcmf_set_mpc(struct net_device *ndev, int mpc) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + s32 err = 0; + + if (check_vif_up(ifp->vif)) { + err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); + if (err) { + brcmf_err("fail to set mpc\n"); + return; + } + brcmf_dbg(INFO, "MPC : %d\n", mpc); + } +} + static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, struct cfg80211_scan_request *request) { @@ -802,6 +589,69 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK)); } +static s32 +brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, + struct net_device *ndev, + bool aborted, bool fw_abort) +{ + struct brcmf_scan_params_le params_le; + struct cfg80211_scan_request *scan_request; + s32 err = 0; + + brcmf_dbg(SCAN, "Enter\n"); + + /* clear scan request, because the FW abort can cause a second call */ + /* to this functon and might cause a double cfg80211_scan_done */ + scan_request = cfg->scan_request; + cfg->scan_request = NULL; + + if (timer_pending(&cfg->escan_timeout)) + del_timer_sync(&cfg->escan_timeout); + + if (fw_abort) { + /* Do a scan abort to stop the driver's scan engine */ + brcmf_dbg(SCAN, "ABORT scan in firmware\n"); + memset(¶ms_le, 0, sizeof(params_le)); + memset(params_le.bssid, 0xFF, ETH_ALEN); + params_le.bss_type = DOT11_BSSTYPE_ANY; + params_le.scan_type = 0; + params_le.channel_num = cpu_to_le32(1); + params_le.nprobes = cpu_to_le32(1); + params_le.active_time = cpu_to_le32(-1); + params_le.passive_time = cpu_to_le32(-1); + params_le.home_time = cpu_to_le32(-1); + /* Scan is aborted by setting channel_list[0] to -1 */ + params_le.channel_list[0] = cpu_to_le16(-1); + /* E-Scan (or anyother type) can be aborted by SCAN */ + err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, + ¶ms_le, sizeof(params_le)); + if (err) + brcmf_err("Scan abort failed\n"); + } + /* + * e-scan can be initiated by scheduled scan + * which takes precedence. + */ + if (cfg->sched_escan) { + brcmf_dbg(SCAN, "scheduled scan completed\n"); + cfg->sched_escan = false; + if (!aborted) + cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); + brcmf_set_mpc(ndev, 1); + } else if (scan_request) { + brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n", + aborted ? "Aborted" : "Done"); + cfg80211_scan_done(scan_request, aborted); + brcmf_set_mpc(ndev, 1); + } + if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { + brcmf_err("Scan complete while device not scanning\n"); + return -EPERM; + } + + return err; +} + static s32 brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, struct cfg80211_scan_request *request, u16 action) @@ -853,12 +703,11 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, s32 err; u32 passive_scan; struct brcmf_scan_results *results; - struct escan_info *escan = &cfg->escan_info; brcmf_dbg(SCAN, "Enter\n"); - escan->ndev = ndev; - escan->wiphy = wiphy; - escan->escan_state = WL_ESCAN_STATE_SCANNING; + cfg->escan_info.ndev = ndev; + cfg->escan_info.wiphy = wiphy; + cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; passive_scan = cfg->active_scan ? 0 : 1; err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN, passive_scan); @@ -872,7 +721,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, results->count = 0; results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; - err = escan->run(cfg, ndev, request, WL_ESCAN_ACTION_START); + err = brcmf_run_escan(cfg, ndev, request, WL_ESCAN_ACTION_START); if (err) brcmf_set_mpc(ndev, 1); return err; @@ -909,12 +758,6 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, return -EAGAIN; } - /* If scan req comes for p2p0, send it over primary I/F */ - if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) { - ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; - ndev = ifp->ndev; - } - /* Arm scan timeout timer */ mod_timer(&cfg->escan_timeout, jiffies + WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); @@ -933,11 +776,6 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, cfg->scan_request = request; set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); if (escan_req) { - cfg->escan_info.run = brcmf_run_escan; - err = brcmf_p2p_scan_prep(wiphy, request, ifp->vif); - if (err) - goto scan_out; - err = brcmf_do_escan(cfg, wiphy, ndev, request); if (err) goto scan_out; @@ -1095,6 +933,31 @@ static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) memset(prof, 0, sizeof(*prof)); } +static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, + size_t *join_params_size) +{ + u16 chanspec = 0; + + if (ch != 0) { + if (ch <= CH_MAX_2G_CHANNEL) + chanspec |= WL_CHANSPEC_BAND_2G; + else + chanspec |= WL_CHANSPEC_BAND_5G; + + chanspec |= WL_CHANSPEC_BW_20; + chanspec |= WL_CHANSPEC_CTL_SB_NONE; + + *join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE + + sizeof(u16); + + chanspec |= (ch & WL_CHANSPEC_CHAN_MASK); + join_params->params_le.chanspec_list[0] = cpu_to_le16(chanspec); + join_params->params_le.chanspec_num = cpu_to_le32(1); + + brcmf_dbg(CONN, "channel %d, chanspec %#X\n", ch, chanspec); + } +} + static void brcmf_link_down(struct brcmf_cfg80211_vif *vif) { s32 err = 0; @@ -1125,7 +988,6 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, s32 err = 0; s32 wsec = 0; s32 bcnprd; - u16 chanspec; brcmf_dbg(TRACE, "Enter\n"); if (!check_vif_up(ifp->vif)) @@ -1229,11 +1091,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, params->chandef.chan->center_freq); if (params->channel_fixed) { /* adding chanspec */ - chanspec = channel_to_chanspec(params->chandef.chan); - join_params.params_le.chanspec_list[0] = - cpu_to_le16(chanspec); - join_params.params_le.chanspec_num = cpu_to_le32(1); - join_params_size += sizeof(join_params.params_le); + brcmf_ch_to_chanspec(cfg->channel, + &join_params, &join_params_size); } /* set channel for starter */ @@ -1296,7 +1155,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, else val = WPA_AUTH_DISABLED; brcmf_dbg(CONN, "setting wpa_auth to 0x%0x\n", val); - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wpa_auth", val); + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val); if (err) { brcmf_err("set wpa_auth failed (%d)\n", err); return err; @@ -1335,7 +1194,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, break; } - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val); + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val); if (err) { brcmf_err("set auth failed (%d)\n", err); return err; @@ -1399,12 +1258,7 @@ brcmf_set_set_cipher(struct net_device *ndev, } brcmf_dbg(CONN, "pval (%d) gval (%d)\n", pval, gval); - /* In case of privacy, but no security and WPS then simulate */ - /* setting AES. WPS-2.0 allows no security */ - if (brcmf_find_wpsie(sme->ie, sme->ie_len) && !pval && !gval && - sme->privacy) - pval = AES_ENABLED; - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "wsec", pval | gval); + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval); if (err) { brcmf_err("error (%d)\n", err); return err; @@ -1426,8 +1280,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) s32 err = 0; if (sme->crypto.n_akm_suites) { - err = brcmf_fil_bsscfg_int_get(netdev_priv(ndev), - "wpa_auth", &val); + err = brcmf_fil_iovar_int_get(netdev_priv(ndev), + "wpa_auth", &val); if (err) { brcmf_err("could not get wpa_auth (%d)\n", err); return err; @@ -1461,8 +1315,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) } brcmf_dbg(CONN, "setting wpa_auth to %d\n", val); - err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), - "wpa_auth", val); + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), + "wpa_auth", val); if (err) { brcmf_err("could not set wpa_auth (%d)\n", err); return err; @@ -1539,28 +1393,9 @@ brcmf_set_sharedkey(struct net_device *ndev, return err; } -static -enum nl80211_auth_type brcmf_war_auth_type(struct brcmf_if *ifp, - enum nl80211_auth_type type) -{ - u32 ci; - if (type == NL80211_AUTHTYPE_AUTOMATIC) { - /* shift to ignore chip revision */ - ci = brcmf_get_chip_info(ifp) >> 4; - switch (ci) { - case 43236: - brcmf_dbg(CONN, "43236 WAR: use OPEN instead of AUTO\n"); - return NL80211_AUTHTYPE_OPEN_SYSTEM; - default: - break; - } - } - return type; -} - static s32 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_connect_params *sme) + struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); @@ -1568,12 +1403,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *chan = sme->channel; struct brcmf_join_params join_params; size_t join_params_size; - struct brcmf_tlv *rsn_ie; - struct brcmf_vs_tlv *wpa_ie; - void *ie; - u32 ie_len; - struct brcmf_ext_join_params_le *ext_join_params; - u16 chanspec; + struct brcmf_ssid ssid; s32 err = 0; @@ -1586,46 +1416,15 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } - if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) { - /* A normal (non P2P) connection request setup. */ - ie = NULL; - ie_len = 0; - /* find the WPA_IE */ - wpa_ie = brcmf_find_wpaie((u8 *)sme->ie, sme->ie_len); - if (wpa_ie) { - ie = wpa_ie; - ie_len = wpa_ie->len + TLV_HDR_LEN; - } else { - /* find the RSN_IE */ - rsn_ie = brcmf_parse_tlvs((u8 *)sme->ie, sme->ie_len, - WLAN_EID_RSN); - if (rsn_ie) { - ie = rsn_ie; - ie_len = rsn_ie->len + TLV_HDR_LEN; - } - } - brcmf_fil_iovar_data_set(ifp, "wpaie", ie, ie_len); - } - - err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG, - sme->ie, sme->ie_len); - if (err) - brcmf_err("Set Assoc REQ IE Failed\n"); - else - brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n"); - set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); if (chan) { cfg->channel = ieee80211_frequency_to_channel(chan->center_freq); - chanspec = channel_to_chanspec(chan); - brcmf_dbg(CONN, "channel=%d, center_req=%d, chanspec=0x%04x\n", - cfg->channel, chan->center_freq, chanspec); - } else { + brcmf_dbg(CONN, "channel (%d), center_req (%d)\n", + cfg->channel, chan->center_freq); + } else cfg->channel = 0; - chanspec = 0; - } brcmf_dbg(INFO, "ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); @@ -1635,7 +1434,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - sme->auth_type = brcmf_war_auth_type(ifp, sme->auth_type); err = brcmf_set_auth_type(ndev, sme); if (err) { brcmf_err("wl_set_auth_type failed (%d)\n", err); @@ -1660,88 +1458,27 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - profile->ssid.SSID_len = min_t(u32, (u32)sizeof(profile->ssid.SSID), - (u32)sme->ssid_len); - memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); - if (profile->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - profile->ssid.SSID[profile->ssid.SSID_len] = 0; - brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n", profile->ssid.SSID, - profile->ssid.SSID_len); - } - - /* Join with specific BSSID and cached SSID - * If SSID is zero join based on BSSID only - */ - join_params_size = offsetof(struct brcmf_ext_join_params_le, assoc_le) + - offsetof(struct brcmf_assoc_params_le, chanspec_list); - if (cfg->channel) - join_params_size += sizeof(u16); - ext_join_params = kzalloc(join_params_size, GFP_KERNEL); - if (ext_join_params == NULL) { - err = -ENOMEM; - goto done; - } - ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); - memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, - profile->ssid.SSID_len); - /*increase dwell time to receive probe response or detect Beacon - * from target AP at a noisy air only during connect command - */ - ext_join_params->scan_le.active_time = - cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS); - ext_join_params->scan_le.passive_time = - cpu_to_le32(BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS); - /* Set up join scan parameters */ - ext_join_params->scan_le.scan_type = -1; - /* to sync with presence period of VSDB GO. - * Send probe request more frequently. Probe request will be stopped - * when it gets probe response from target AP/GO. - */ - ext_join_params->scan_le.nprobes = - cpu_to_le32(BRCMF_SCAN_JOIN_ACTIVE_DWELL_TIME_MS / - BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS); - ext_join_params->scan_le.home_time = cpu_to_le32(-1); - - if (sme->bssid) - memcpy(&ext_join_params->assoc_le.bssid, sme->bssid, ETH_ALEN); - else - memset(&ext_join_params->assoc_le.bssid, 0xFF, ETH_ALEN); - - if (cfg->channel) { - ext_join_params->assoc_le.chanspec_num = cpu_to_le32(1); - - ext_join_params->assoc_le.chanspec_list[0] = - cpu_to_le16(chanspec); - } - - err = brcmf_fil_bsscfg_data_set(ifp, "join", ext_join_params, - join_params_size); - kfree(ext_join_params); - if (!err) - /* This is it. join command worked, we are done */ - goto done; - - /* join command failed, fallback to set ssid */ memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid_le); + profile->ssid.SSID_len = min_t(u32, + sizeof(ssid.SSID), (u32)sme->ssid_len); memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len); + memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); - if (sme->bssid) - memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN); - else - memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); + memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); - if (cfg->channel) { - join_params.params_le.chanspec_list[0] = cpu_to_le16(chanspec); - join_params.params_le.chanspec_num = cpu_to_le32(1); - join_params_size += sizeof(join_params.params_le); - } + if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) + brcmf_dbg(CONN, "ssid \"%s\", len (%d)\n", + ssid.SSID, ssid.SSID_len); + + brcmf_ch_to_chanspec(cfg->channel, + &join_params, &join_params_size); err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, &join_params, join_params_size); if (err) - brcmf_err("BRCMF_C_SET_SSID failed (%d)\n", err); + brcmf_err("WLC_SET_SSID failed (%d)\n", err); done: if (err) @@ -2200,7 +1937,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, goto done; } /* Report the current tx rate */ - err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); if (err) { brcmf_err("Could not get rate (%d)\n", err); goto done; @@ -2323,7 +2060,7 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, if (!bss) return -ENOMEM; - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); return err; } @@ -2429,7 +2166,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, goto CleanUp; } - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); CleanUp: @@ -2445,10 +2182,78 @@ static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) return vif->mode == WL_MODE_IBSS; } -static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, - struct brcmf_if *ifp) +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + */ +static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) { - struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev); + struct brcmf_tlv *elt; + int totlen; + + elt = (struct brcmf_tlv *) buf; + totlen = buflen; + + /* find tagged parameter */ + while (totlen >= TLV_HDR_LEN) { + int len = elt->len; + + /* validate remaining totlen */ + if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN))) + return elt; + + elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN)); + totlen -= (len + TLV_HDR_LEN); + } + + return NULL; +} + +/* Is any of the tlvs the expected entry? If + * not update the tlvs buffer pointer/length. + */ +static bool +brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, + u8 *oui, u32 oui_len, u8 type) +{ + /* If the contents match the OUI and the type */ + if (ie[TLV_LEN_OFF] >= oui_len + 1 && + !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) && + type == ie[TLV_BODY_OFF + oui_len]) { + return true; + } + + if (tlvs == NULL) + return false; + /* point to the next ie */ + ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN; + /* calculate the length of the rest of the buffer */ + *tlvs_len -= (int)(ie - *tlvs); + /* update the pointer to the start of the buffer */ + *tlvs = ie; + + return false; +} + +static struct brcmf_vs_tlv * +brcmf_find_wpaie(u8 *parse, u32 len) +{ + struct brcmf_tlv *ie; + + while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { + if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, + WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) + return (struct brcmf_vs_tlv *)ie; + } + return NULL; +} + +static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) +{ + struct net_device *ndev = cfg_to_ndev(cfg); + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); + struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_bss_info_le *bi; struct brcmf_ssid *ssid; struct brcmf_tlv *tim; @@ -2504,7 +2309,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, return err; } -void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) +static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) { struct escan_info *escan = &cfg->escan_info; @@ -2523,7 +2328,8 @@ static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work) container_of(work, struct brcmf_cfg80211_info, escan_timeout_work); - brcmf_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true); + brcmf_notify_escan_complete(cfg, + cfg->escan_info.ndev, true, true); } static void brcmf_escan_timeout(unsigned long data) @@ -2600,6 +2406,11 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, brcmf_err("Invalid escan result (NULL pointer)\n"); goto exit; } + if (!cfg->scan_request) { + brcmf_dbg(SCAN, "result without cfg80211 request\n"); + goto exit; + } + if (le16_to_cpu(escan_result_le->bss_count) != 1) { brcmf_err("Invalid bss_count %d: ignoring\n", escan_result_le->bss_count); @@ -2607,14 +2418,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, } bss_info_le = &escan_result_le->bss_info_le; - if (brcmf_p2p_scan_finding_common_channel(cfg, bss_info_le)) - goto exit; - - if (!cfg->scan_request) { - brcmf_dbg(SCAN, "result without cfg80211 request\n"); - goto exit; - } - bi_length = le32_to_cpu(bss_info_le->length); if (bi_length != (le32_to_cpu(escan_result_le->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) { @@ -2653,8 +2456,6 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, list->count++; } else { cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (brcmf_p2p_scan_finding_common_channel(cfg, NULL)) - goto exit; if (cfg->scan_request) { cfg->bss_list = (struct brcmf_scan_results *) cfg->escan_info.escan_buf; @@ -2663,8 +2464,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, brcmf_notify_escan_complete(cfg, ndev, aborted, false); } else - brcmf_dbg(SCAN, "Ignored scan complete result 0x%x\n", - status); + brcmf_err("Unexpected scan result 0x%x\n", status); } exit: return err; @@ -3168,8 +2968,9 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) } #endif -static s32 brcmf_configure_opensecurity(struct brcmf_if *ifp) +static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) { + struct brcmf_if *ifp = netdev_priv(ndev); s32 err; /* set auth */ @@ -3428,7 +3229,7 @@ brcmf_parse_vndr_ies(const u8 *vndr_ie_buf, u32 vndr_ie_len, parsed_info->vndrie.oui[2], parsed_info->vndrie.oui_type); - if (vndr_ies->count >= VNDR_IE_PARSE_LIMIT) + if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) break; next: remaining_len -= (ie->len + TLV_HDR_LEN); @@ -3462,6 +3263,7 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) return ie_len + VNDR_IE_HDR_SIZE; } +static s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, const u8 *vndr_ie_buf, u32 vndr_ie_len) { @@ -3493,28 +3295,24 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, if (!iovar_ie_buf) return -ENOMEM; curr_ie_buf = iovar_ie_buf; - switch (pktflag) { - case BRCMF_VNDR_IE_PRBREQ_FLAG: - mgmt_ie_buf = saved_ie->probe_req_ie; - mgmt_ie_len = &saved_ie->probe_req_ie_len; - mgmt_ie_buf_len = sizeof(saved_ie->probe_req_ie); - break; - case BRCMF_VNDR_IE_PRBRSP_FLAG: - mgmt_ie_buf = saved_ie->probe_res_ie; - mgmt_ie_len = &saved_ie->probe_res_ie_len; - mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie); - break; - case BRCMF_VNDR_IE_BEACON_FLAG: - mgmt_ie_buf = saved_ie->beacon_ie; - mgmt_ie_len = &saved_ie->beacon_ie_len; - mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie); - break; - case BRCMF_VNDR_IE_ASSOCREQ_FLAG: - mgmt_ie_buf = saved_ie->assoc_req_ie; - mgmt_ie_len = &saved_ie->assoc_req_ie_len; - mgmt_ie_buf_len = sizeof(saved_ie->assoc_req_ie); - break; - default: + if (ifp->vif->mode == WL_MODE_AP) { + switch (pktflag) { + case VNDR_IE_PRBRSP_FLAG: + mgmt_ie_buf = saved_ie->probe_res_ie; + mgmt_ie_len = &saved_ie->probe_res_ie_len; + mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie); + break; + case VNDR_IE_BEACON_FLAG: + mgmt_ie_buf = saved_ie->beacon_ie; + mgmt_ie_len = &saved_ie->beacon_ie_len; + mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie); + break; + default: + err = -EPERM; + brcmf_err("not suitable type\n"); + goto exit; + } + } else { err = -EPERM; brcmf_err("not suitable type\n"); goto exit; @@ -3623,49 +3421,6 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, return err; } -s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif) -{ - s32 pktflags[] = { - BRCMF_VNDR_IE_PRBREQ_FLAG, - BRCMF_VNDR_IE_PRBRSP_FLAG, - BRCMF_VNDR_IE_BEACON_FLAG - }; - int i; - - for (i = 0; i < ARRAY_SIZE(pktflags); i++) - brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0); - - memset(&vif->saved_ie, 0, sizeof(vif->saved_ie)); - return 0; -} - -static s32 -brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif, - struct cfg80211_beacon_data *beacon) -{ - s32 err; - - /* Set Beacon IEs to FW */ - err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_BEACON_FLAG, - beacon->tail, beacon->tail_len); - if (err) { - brcmf_err("Set Beacon IE Failed\n"); - return err; - } - brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); - - /* Set Probe Response IEs to FW */ - err = brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBRSP_FLAG, - beacon->proberesp_ies, - beacon->proberesp_ies_len); - if (err) - brcmf_err("Set Probe Resp IE Failed\n"); - else - brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); - - return err; -} - static s32 brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ap_settings *settings) @@ -3678,8 +3433,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_tlv *rsn_ie; struct brcmf_vs_tlv *wpa_ie; struct brcmf_join_params join_params; - enum nl80211_iftype dev_role; - struct brcmf_fil_bss_enable_le bss_enable; + s32 bssidx = 0; brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", cfg80211_get_chandef_type(&settings->chandef), @@ -3689,7 +3443,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, settings->ssid, settings->ssid_len, settings->auth_type, settings->inactivity_timeout); - dev_role = ifp->vif->wdev.iftype; + if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) { + brcmf_err("Not in AP creation mode\n"); + return -EPERM; + } memset(&ssid_le, 0, sizeof(ssid_le)); if (settings->ssid == NULL || settings->ssid_len == 0) { @@ -3710,6 +3467,21 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, } brcmf_set_mpc(ndev, 0); + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); + if (err < 0) { + brcmf_err("BRCMF_C_DOWN error %d\n", err); + goto exit; + } + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); + if (err < 0) { + brcmf_err("SET INFRA error %d\n", err); + goto exit; + } + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); + if (err < 0) { + brcmf_err("setting AP mode failed %d\n", err); + goto exit; + } /* find the RSN_IE */ rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, @@ -3735,10 +3507,27 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, } } else { brcmf_dbg(TRACE, "No WPA(2) IEs found\n"); - brcmf_configure_opensecurity(ifp); + brcmf_configure_opensecurity(ndev, bssidx); } + /* Set Beacon IEs to FW */ + err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev), + VNDR_IE_BEACON_FLAG, + settings->beacon.tail, + settings->beacon.tail_len); + if (err) + brcmf_err("Set Beacon IE Failed\n"); + else + brcmf_dbg(TRACE, "Applied Vndr IEs for Beacon\n"); - brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon); + /* Set Probe Response IEs to FW */ + err = brcmf_vif_set_mgmt_ie(ndev_to_vif(ndev), + VNDR_IE_PRBRSP_FLAG, + settings->beacon.proberesp_ies, + settings->beacon.proberesp_ies_len); + if (err) + brcmf_err("Set Probe Resp IE Failed\n"); + else + brcmf_dbg(TRACE, "Applied Vndr IEs for Probe Resp\n"); if (settings->beacon_interval) { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, @@ -3756,61 +3545,21 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, goto exit; } } - - if (dev_role == NL80211_IFTYPE_AP) { - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); - if (err < 0) { - brcmf_err("BRCMF_C_DOWN error %d\n", err); - goto exit; - } - brcmf_fil_iovar_int_set(ifp, "apsta", 0); - } - - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); if (err < 0) { - brcmf_err("SET INFRA error %d\n", err); + brcmf_err("BRCMF_C_UP error (%d)\n", err); goto exit; } - if (dev_role == NL80211_IFTYPE_AP) { - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); - if (err < 0) { - brcmf_err("setting AP mode failed %d\n", err); - goto exit; - } - err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); - if (err < 0) { - brcmf_err("BRCMF_C_UP error (%d)\n", err); - goto exit; - } - - memset(&join_params, 0, sizeof(join_params)); - /* join parameters starts with ssid */ - memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); - /* create softap */ - err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, - &join_params, sizeof(join_params)); - if (err < 0) { - brcmf_err("SET SSID error (%d)\n", err); - goto exit; - } - brcmf_dbg(TRACE, "AP mode configuration complete\n"); - } else { - err = brcmf_fil_bsscfg_data_set(ifp, "ssid", &ssid_le, - sizeof(ssid_le)); - if (err < 0) { - brcmf_err("setting ssid failed %d\n", err); - goto exit; - } - bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); - bss_enable.enable = cpu_to_le32(1); - err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, - sizeof(bss_enable)); - if (err < 0) { - brcmf_err("bss_enable config failed %d\n", err); - goto exit; - } - brcmf_dbg(TRACE, "GO mode configuration complete\n"); + memset(&join_params, 0, sizeof(join_params)); + /* join parameters starts with ssid */ + memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); + /* create softap */ + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, + &join_params, sizeof(join_params)); + if (err < 0) { + brcmf_err("SET SSID error (%d)\n", err); + goto exit; } clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); @@ -3825,11 +3574,10 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); s32 err = -EPERM; - struct brcmf_fil_bss_enable_le bss_enable; brcmf_dbg(TRACE, "Enter\n"); - if (ifp->vif->wdev.iftype == NL80211_IFTYPE_AP) { + if (ifp->vif->mode == WL_MODE_AP) { /* Due to most likely deauths outstanding we sleep */ /* first to make sure they get processed by fw. */ msleep(400); @@ -3843,41 +3591,18 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) brcmf_err("BRCMF_C_UP error %d\n", err); goto exit; } - } else { - bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); - bss_enable.enable = cpu_to_le32(0); - err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, - sizeof(bss_enable)); - if (err < 0) - brcmf_err("bss_enable config failed %d\n", err); + brcmf_set_mpc(ndev, 1); + clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); + clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); } - brcmf_set_mpc(ndev, 1); - set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); - clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); - exit: return err; } -static s32 -brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_beacon_data *info) -{ - struct brcmf_if *ifp = netdev_priv(ndev); - s32 err; - - brcmf_dbg(TRACE, "Enter\n"); - - err = brcmf_config_ap_mgmt_ie(ifp->vif, info); - - return err; -} - static int brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scbval; struct brcmf_if *ifp = netdev_priv(ndev); s32 err; @@ -3887,8 +3612,6 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, brcmf_dbg(TRACE, "Enter %pM\n", mac); - if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) - ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; if (!check_vif_up(ifp->vif)) return -EIO; @@ -3903,147 +3626,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, return err; } - -static void -brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - struct brcmf_if *ifp = netdev_priv(wdev->netdev); - struct brcmf_cfg80211_vif *vif = ifp->vif; - u16 mgmt_type; - - brcmf_dbg(TRACE, "Enter, frame_type %04x, reg=%d\n", frame_type, reg); - - mgmt_type = (frame_type & IEEE80211_FCTL_STYPE) >> 4; - if (reg) - vif->mgmt_rx_reg |= BIT(mgmt_type); - else - vif->mgmt_rx_reg &= ~BIT(mgmt_type); -} - - -static int -brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct ieee80211_channel *chan, bool offchan, - unsigned int wait, const u8 *buf, size_t len, - bool no_cck, bool dont_wait_for_ack, u64 *cookie) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - const struct ieee80211_mgmt *mgmt; - struct brcmf_if *ifp; - struct brcmf_cfg80211_vif *vif; - s32 err = 0; - s32 ie_offset; - s32 ie_len; - struct brcmf_fil_action_frame_le *action_frame; - struct brcmf_fil_af_params_le *af_params; - bool ack; - s32 chan_nr; - - brcmf_dbg(TRACE, "Enter\n"); - - *cookie = 0; - - mgmt = (const struct ieee80211_mgmt *)buf; - - if (!ieee80211_is_mgmt(mgmt->frame_control)) { - brcmf_err("Driver only allows MGMT packet type\n"); - return -EPERM; - } - - if (ieee80211_is_probe_resp(mgmt->frame_control)) { - /* Right now the only reason to get a probe response */ - /* is for p2p listen response or for p2p GO from */ - /* wpa_supplicant. Unfortunately the probe is send */ - /* on primary ndev, while dongle wants it on the p2p */ - /* vif. Since this is only reason for a probe */ - /* response to be sent, the vif is taken from cfg. */ - /* If ever desired to send proberesp for non p2p */ - /* response then data should be checked for */ - /* "DIRECT-". Note in future supplicant will take */ - /* dedicated p2p wdev to do this and then this 'hack'*/ - /* is not needed anymore. */ - ie_offset = DOT11_MGMT_HDR_LEN + - DOT11_BCN_PRB_FIXED_LEN; - ie_len = len - ie_offset; - ifp = netdev_priv(wdev->netdev); - vif = ifp->vif; - if (vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif) - vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - err = brcmf_vif_set_mgmt_ie(vif, - BRCMF_VNDR_IE_PRBRSP_FLAG, - &buf[ie_offset], - ie_len); - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, - GFP_KERNEL); - } else if (ieee80211_is_action(mgmt->frame_control)) { - af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); - if (af_params == NULL) { - brcmf_err("unable to allocate frame\n"); - err = -ENOMEM; - goto exit; - } - action_frame = &af_params->action_frame; - /* Add the packet Id */ - action_frame->packet_id = cpu_to_le32(*cookie); - /* Add BSSID */ - memcpy(&action_frame->da[0], &mgmt->da[0], ETH_ALEN); - memcpy(&af_params->bssid[0], &mgmt->bssid[0], ETH_ALEN); - /* Add the length exepted for 802.11 header */ - action_frame->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN); - /* Add the channel */ - chan_nr = ieee80211_frequency_to_channel(chan->center_freq); - af_params->channel = cpu_to_le32(chan_nr); - - memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], - le16_to_cpu(action_frame->len)); - - brcmf_dbg(TRACE, "Action frame, cookie=%lld, len=%d, freq=%d\n", - *cookie, le16_to_cpu(action_frame->len), - chan->center_freq); - - ack = brcmf_p2p_send_action_frame(cfg, wdev->netdev, - af_params); - - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, ack, - GFP_KERNEL); - kfree(af_params); - } else { - brcmf_dbg(TRACE, "Unhandled, fc=%04x!!\n", mgmt->frame_control); - brcmf_dbg_hex_dump(true, buf, len, "payload, len=%Zu\n", len); - } - -exit: - return err; -} - - -static int -brcmf_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - u64 cookie) -{ - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct brcmf_cfg80211_vif *vif; - int err = 0; - - brcmf_dbg(TRACE, "Enter p2p listen cancel\n"); - - vif = cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif; - if (vif == NULL) { - brcmf_err("No p2p device available for probe response\n"); - err = -ENODEV; - goto exit; - } - brcmf_p2p_cancel_remain_on_channel(vif->ifp); -exit: - return err; -} - static struct cfg80211_ops wl_cfg80211_ops = { - .add_virtual_intf = brcmf_cfg80211_add_iface, - .del_virtual_intf = brcmf_cfg80211_del_iface, .change_virtual_intf = brcmf_cfg80211_change_iface, .scan = brcmf_cfg80211_scan, .set_wiphy_params = brcmf_cfg80211_set_wiphy_params, @@ -4067,43 +3650,28 @@ static struct cfg80211_ops wl_cfg80211_ops = { .flush_pmksa = brcmf_cfg80211_flush_pmksa, .start_ap = brcmf_cfg80211_start_ap, .stop_ap = brcmf_cfg80211_stop_ap, - .change_beacon = brcmf_cfg80211_change_beacon, .del_station = brcmf_cfg80211_del_station, .sched_scan_start = brcmf_cfg80211_sched_scan_start, .sched_scan_stop = brcmf_cfg80211_sched_scan_stop, - .mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register, - .mgmt_tx = brcmf_cfg80211_mgmt_tx, - .remain_on_channel = brcmf_p2p_remain_on_channel, - .cancel_remain_on_channel = brcmf_cfg80211_cancel_remain_on_channel, #ifdef CONFIG_NL80211_TESTMODE .testmode_cmd = brcmf_cfg80211_testmode #endif }; -static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type) +static s32 brcmf_mode_to_nl80211_iftype(s32 mode) { - switch (type) { - case NL80211_IFTYPE_AP_VLAN: - case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - return -ENOTSUPP; - case NL80211_IFTYPE_ADHOC: - return WL_MODE_IBSS; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - return WL_MODE_BSS; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - return WL_MODE_AP; - case NL80211_IFTYPE_P2P_DEVICE: - return WL_MODE_P2P; - case NL80211_IFTYPE_UNSPECIFIED: + s32 err = 0; + + switch (mode) { + case WL_MODE_BSS: + return NL80211_IFTYPE_STATION; + case WL_MODE_IBSS: + return NL80211_IFTYPE_ADHOC; default: - break; + return NL80211_IFTYPE_UNSPECIFIED; } - return -EINVAL; + return err; } static void brcmf_wiphy_pno_params(struct wiphy *wiphy) @@ -4115,56 +3683,6 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; } -static const struct ieee80211_iface_limit brcmf_iface_limits[] = { - { - .max = 2, - .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_DEVICE) - }, - { - .max = 1, - .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) - }, -}; -static const struct ieee80211_iface_combination brcmf_iface_combos[] = { - { - .max_interfaces = BRCMF_IFACE_MAX_CNT, - .num_different_channels = 1, /* no multi-channel for now */ - .n_limits = ARRAY_SIZE(brcmf_iface_limits), - .limits = brcmf_iface_limits - } -}; - -static const struct ieee80211_txrx_stypes -brcmf_txrx_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_STATION] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = 0xffff, - .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | - BIT(IEEE80211_STYPE_DISASSOC >> 4) | - BIT(IEEE80211_STYPE_AUTH >> 4) | - BIT(IEEE80211_STYPE_DEAUTH >> 4) | - BIT(IEEE80211_STYPE_ACTION >> 4) - } -}; - static struct wiphy *brcmf_setup_wiphy(struct device *phydev) { struct wiphy *wiphy; @@ -4177,16 +3695,10 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) } set_wiphy_dev(wiphy, phydev); wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; - wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX; wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_DEVICE); - wiphy->iface_combinations = brcmf_iface_combos; - wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); + BIT(NL80211_IFTYPE_AP); wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set * it as 11a by default. @@ -4198,11 +3710,10 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->cipher_suites = __wl_cipher_suites; wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); - wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT | - WIPHY_FLAG_OFFCHAN_TX | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; - wiphy->mgmt_stypes = brcmf_txrx_stypes; - wiphy->max_remain_on_channel_duration = 5000; + wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power + * save mode + * by default + */ brcmf_wiphy_pno_params(wiphy); err = wiphy_register(wiphy); if (err < 0) { @@ -4213,25 +3724,31 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) return wiphy; } +static struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, - enum nl80211_iftype type, - bool pm_block) + struct net_device *netdev, + s32 mode, bool pm_block) { struct brcmf_cfg80211_vif *vif; if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT) return ERR_PTR(-ENOSPC); - brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n", - sizeof(*vif)); vif = kzalloc(sizeof(*vif), GFP_KERNEL); if (!vif) return ERR_PTR(-ENOMEM); vif->wdev.wiphy = cfg->wiphy; - vif->wdev.iftype = type; + vif->wdev.netdev = netdev; + vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode); + + if (netdev) { + vif->ifp = netdev_priv(netdev); + netdev->ieee80211_ptr = &vif->wdev; + SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy)); + } - vif->mode = brcmf_nl80211_iftype_to_mode(type); + vif->mode = mode; vif->pm_block = pm_block; vif->roam_off = -1; @@ -4242,7 +3759,7 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, return vif; } -void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) +static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) { struct brcmf_cfg80211_info *cfg; struct wiphy *wiphy; @@ -4316,9 +3833,9 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) conn_info->resp_ie_len = 0; } -static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, - struct brcmf_if *ifp) +static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) { + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); struct brcmf_cfg80211_assoc_ielen_le *assoc_info; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); u32 req_len; @@ -4394,9 +3911,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, brcmf_dbg(TRACE, "Enter\n"); - brcmf_get_assoc_ies(cfg, ifp); + brcmf_get_assoc_ies(cfg); memcpy(profile->bssid, e->addr, ETH_ALEN); - brcmf_update_bss_info(cfg, ifp); + brcmf_update_bss_info(cfg); buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); if (buf == NULL) { @@ -4451,11 +3968,9 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { if (completed) { - brcmf_get_assoc_ies(cfg, ifp); + brcmf_get_assoc_ies(cfg); memcpy(profile->bssid, e->addr, ETH_ALEN); - brcmf_update_bss_info(cfg, ifp); - set_bit(BRCMF_VIF_STATUS_CONNECTED, - &ifp->vif->sme_state); + brcmf_update_bss_info(cfg); } cfg80211_connect_result(ndev, (u8 *)profile->bssid, @@ -4466,6 +3981,9 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, completed ? WLAN_STATUS_SUCCESS : WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); + if (completed) + set_bit(BRCMF_VIF_STATUS_CONNECTED, + &ifp->vif->sme_state); brcmf_dbg(CONN, "Report connect result - connection %s\n", completed ? "succeeded" : "failed"); } @@ -4478,38 +3996,38 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { - static int generation; + s32 err = 0; u32 event = e->event_code; u32 reason = e->reason; + u32 len = e->datalen; + static int generation; + struct station_info sinfo; brcmf_dbg(CONN, "event %d, reason %d\n", event, reason); - if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS && - ndev != cfg_to_ndev(cfg)) { - brcmf_dbg(CONN, "AP mode link down\n"); - complete(&cfg->vif_disabled); - return 0; - } + memset(&sinfo, 0, sizeof(sinfo)); + sinfo.filled = 0; if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && - (reason == BRCMF_E_STATUS_SUCCESS)) { - memset(&sinfo, 0, sizeof(sinfo)); + reason == BRCMF_E_STATUS_SUCCESS) { sinfo.filled = STATION_INFO_ASSOC_REQ_IES; if (!data) { brcmf_err("No IEs present in ASSOC/REASSOC_IND"); return -EINVAL; } sinfo.assoc_req_ies = data; - sinfo.assoc_req_ies_len = e->datalen; + sinfo.assoc_req_ies_len = len; generation++; sinfo.generation = generation; - cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_KERNEL); + cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC); } else if ((event == BRCMF_E_DISASSOC_IND) || (event == BRCMF_E_DEAUTH_IND) || (event == BRCMF_E_DEAUTH)) { - cfg80211_del_sta(ndev, e->addr, GFP_KERNEL); + generation++; + sinfo.generation = generation; + cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC); } - return 0; + return err; } static s32 @@ -4546,8 +4064,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp, } brcmf_link_down(ifp->vif); brcmf_init_prof(ndev_to_prof(ndev)); - if (ndev != cfg_to_ndev(cfg)) - complete(&cfg->vif_disabled); } else if (brcmf_is_nonetwork(cfg, e)) { if (brcmf_is_ibssmode(ifp->vif)) clear_bit(BRCMF_VIF_STATUS_CONNECTING, @@ -4596,57 +4112,6 @@ brcmf_notify_mic_status(struct brcmf_if *ifp, return 0; } -static s32 brcmf_notify_vif_event(struct brcmf_if *ifp, - const struct brcmf_event_msg *e, void *data) -{ - struct brcmf_cfg80211_info *cfg = ifp->drvr->config; - struct brcmf_if_event *ifevent = (struct brcmf_if_event *)data; - struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; - struct brcmf_cfg80211_vif *vif; - - brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfg %u\n", - ifevent->action, ifevent->flags, ifevent->ifidx, - ifevent->bssidx); - - mutex_lock(&event->vif_event_lock); - event->action = ifevent->action; - vif = event->vif; - - switch (ifevent->action) { - case BRCMF_E_IF_ADD: - /* waiting process may have timed out */ - if (!cfg->vif_event.vif) - return -EBADF; - - ifp->vif = vif; - vif->ifp = ifp; - vif->wdev.netdev = ifp->ndev; - ifp->ndev->ieee80211_ptr = &vif->wdev; - SET_NETDEV_DEV(ifp->ndev, wiphy_dev(cfg->wiphy)); - mutex_unlock(&event->vif_event_lock); - wake_up(&event->vif_wq); - return 0; - - case BRCMF_E_IF_DEL: - ifp->vif = NULL; - mutex_unlock(&event->vif_event_lock); - /* event may not be upon user request */ - if (brcmf_cfg80211_vif_event_armed(cfg)) - wake_up(&event->vif_wq); - return 0; - - case BRCMF_E_IF_CHANGE: - mutex_unlock(&event->vif_event_lock); - wake_up(&event->vif_wq); - return 0; - - default: - mutex_unlock(&event->vif_event_lock); - break; - } - return -EINVAL; -} - static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) { conf->frag_threshold = (u32)-1; @@ -4678,18 +4143,6 @@ static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg) brcmf_notify_connect_status); brcmf_fweh_register(cfg->pub, BRCMF_E_PFN_NET_FOUND, brcmf_notify_sched_scan_results); - brcmf_fweh_register(cfg->pub, BRCMF_E_IF, - brcmf_notify_vif_event); - brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_PROBEREQ_MSG, - brcmf_p2p_notify_rx_mgmt_p2p_probereq); - brcmf_fweh_register(cfg->pub, BRCMF_E_P2P_DISC_LISTEN_COMPLETE, - brcmf_p2p_notify_listen_complete); - brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_RX, - brcmf_p2p_notify_action_frame_rx); - brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_COMPLETE, - brcmf_p2p_notify_action_tx_complete); - brcmf_fweh_register(cfg->pub, BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE, - brcmf_p2p_notify_action_tx_complete); } static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) @@ -4745,7 +4198,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) mutex_init(&cfg->usr_sync); brcmf_init_escan(cfg); brcmf_init_conf(cfg->conf); - init_completion(&cfg->vif_disabled); + return err; } @@ -4756,12 +4209,6 @@ static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) brcmf_deinit_priv_mem(cfg); } -static void init_vif_event(struct brcmf_cfg80211_vif_event *event) -{ - init_waitqueue_head(&event->vif_wq); - mutex_init(&event->vif_event_lock); -} - struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, struct device *busdev) { @@ -4785,41 +4232,25 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, cfg = wiphy_priv(wiphy); cfg->wiphy = wiphy; cfg->pub = drvr; - init_vif_event(&cfg->vif_event); INIT_LIST_HEAD(&cfg->vif_list); - vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_STATION, false); + vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false); if (IS_ERR(vif)) { wiphy_free(wiphy); return NULL; } - vif->ifp = ifp; - vif->wdev.netdev = ndev; - ndev->ieee80211_ptr = &vif->wdev; - SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); - err = wl_init_priv(cfg); if (err) { brcmf_err("Failed to init iwm_priv (%d)\n", err); goto cfg80211_attach_out; } - ifp->vif = vif; - - err = brcmf_p2p_attach(cfg); - if (err) { - brcmf_err("P2P initilisation failed (%d)\n", err); - goto cfg80211_p2p_attach_out; - } + ifp->vif = vif; return cfg; -cfg80211_p2p_attach_out: - wl_deinit_priv(cfg); - cfg80211_attach_out: brcmf_free_vif(vif); - wiphy_free(wiphy); return NULL; } @@ -5058,57 +4489,3 @@ s32 brcmf_cfg80211_down(struct net_device *ndev) return err; } -u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state) -{ - struct brcmf_cfg80211_vif *vif; - bool result = 0; - - list_for_each_entry(vif, &cfg->vif_list, list) { - if (test_bit(state, &vif->sme_state)) - result++; - } - return result; -} - -static inline bool vif_event_equals(struct brcmf_cfg80211_vif_event *event, - u8 action) -{ - u8 evt_action; - - mutex_lock(&event->vif_event_lock); - evt_action = event->action; - mutex_unlock(&event->vif_event_lock); - return evt_action == action; -} - -void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, - struct brcmf_cfg80211_vif *vif) -{ - struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; - - mutex_lock(&event->vif_event_lock); - event->vif = vif; - event->action = 0; - mutex_unlock(&event->vif_event_lock); -} - -bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg) -{ - struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; - bool armed; - - mutex_lock(&event->vif_event_lock); - armed = event->vif != NULL; - mutex_unlock(&event->vif_event_lock); - - return armed; -} -int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, - u8 action, ulong timeout) -{ - struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; - - return wait_event_timeout(event->vif_wq, - vif_event_equals(event, action), timeout); -} - diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 8b5d4989906c..e4d9cc7a8e63 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -41,38 +41,6 @@ #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ #define IE_MAX_LEN 512 -/* IE TLV processing */ -#define TLV_LEN_OFF 1 /* length offset */ -#define TLV_HDR_LEN 2 /* header length */ -#define TLV_BODY_OFF 2 /* body offset */ -#define TLV_OUI_LEN 3 /* oui id length */ - -/* 802.11 Mgmt Packet flags */ -#define BRCMF_VNDR_IE_BEACON_FLAG 0x1 -#define BRCMF_VNDR_IE_PRBRSP_FLAG 0x2 -#define BRCMF_VNDR_IE_ASSOCRSP_FLAG 0x4 -#define BRCMF_VNDR_IE_AUTHRSP_FLAG 0x8 -#define BRCMF_VNDR_IE_PRBREQ_FLAG 0x10 -#define BRCMF_VNDR_IE_ASSOCREQ_FLAG 0x20 -/* vendor IE in IW advertisement protocol ID field */ -#define BRCMF_VNDR_IE_IWAPID_FLAG 0x40 -/* allow custom IE id */ -#define BRCMF_VNDR_IE_CUSTOM_FLAG 0x100 - -/* P2P Action Frames flags (spec ordered) */ -#define BRCMF_VNDR_IE_GONREQ_FLAG 0x001000 -#define BRCMF_VNDR_IE_GONRSP_FLAG 0x002000 -#define BRCMF_VNDR_IE_GONCFM_FLAG 0x004000 -#define BRCMF_VNDR_IE_INVREQ_FLAG 0x008000 -#define BRCMF_VNDR_IE_INVRSP_FLAG 0x010000 -#define BRCMF_VNDR_IE_DISREQ_FLAG 0x020000 -#define BRCMF_VNDR_IE_DISRSP_FLAG 0x040000 -#define BRCMF_VNDR_IE_PRDREQ_FLAG 0x080000 -#define BRCMF_VNDR_IE_PRDRSP_FLAG 0x100000 - -#define BRCMF_VNDR_IE_P2PAF_SHIFT 12 - - /** * enum brcmf_scan_status - dongle scan status * @@ -84,19 +52,11 @@ enum brcmf_scan_status { BRCMF_SCAN_STATUS_ABORT, }; -/** - * enum wl_mode - driver mode of virtual interface. - * - * @WL_MODE_BSS: connects to BSS. - * @WL_MODE_IBSS: operate as ad-hoc. - * @WL_MODE_AP: operate as access-point. - * @WL_MODE_P2P: provide P2P discovery. - */ +/* wi-fi mode */ enum wl_mode { WL_MODE_BSS, WL_MODE_IBSS, - WL_MODE_AP, - WL_MODE_P2P + WL_MODE_AP }; /* dongle configuration */ @@ -148,7 +108,6 @@ struct brcmf_cfg80211_profile { * @BRCMF_VIF_STATUS_READY: ready for operation. * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. - * @BRCMF_VIF_STATUS_DISCONNECTING: disconnect/disable in progress. * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. */ @@ -156,7 +115,6 @@ enum brcmf_vif_status { BRCMF_VIF_STATUS_READY, BRCMF_VIF_STATUS_CONNECTING, BRCMF_VIF_STATUS_CONNECTED, - BRCMF_VIF_STATUS_DISCONNECTING, BRCMF_VIF_STATUS_AP_CREATING, BRCMF_VIF_STATUS_AP_CREATED }; @@ -164,22 +122,16 @@ enum brcmf_vif_status { /** * struct vif_saved_ie - holds saved IEs for a virtual interface. * - * @probe_req_ie: IE info for probe request. * @probe_res_ie: IE info for probe response. * @beacon_ie: IE info for beacon frame. - * @probe_req_ie_len: IE info length for probe request. * @probe_res_ie_len: IE info length for probe response. * @beacon_ie_len: IE info length for beacon frame. */ struct vif_saved_ie { - u8 probe_req_ie[IE_MAX_LEN]; u8 probe_res_ie[IE_MAX_LEN]; u8 beacon_ie[IE_MAX_LEN]; - u8 assoc_req_ie[IE_MAX_LEN]; - u32 probe_req_ie_len; u32 probe_res_ie_len; u32 beacon_ie_len; - u32 assoc_req_ie_len; }; /** @@ -193,7 +145,6 @@ struct vif_saved_ie { * @sme_state: SME state using enum brcmf_vif_status bits. * @pm_block: power-management blocked. * @list: linked list. - * @mgmt_rx_reg: registered rx mgmt frame types. */ struct brcmf_cfg80211_vif { struct brcmf_if *ifp; @@ -205,7 +156,6 @@ struct brcmf_cfg80211_vif { bool pm_block; struct vif_saved_ie saved_ie; struct list_head list; - u16 mgmt_rx_reg; }; /* association inform */ @@ -239,9 +189,6 @@ struct escan_info { u8 escan_buf[WL_ESCAN_BUF_SIZE]; struct wiphy *wiphy; struct net_device *ndev; - s32 (*run)(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - struct cfg80211_scan_request *request, u16 action); }; /** @@ -325,28 +272,11 @@ struct brcmf_pno_scanresults_le { __le32 count; }; -/** - * struct brcmf_cfg80211_vif_event - virtual interface event information. - * - * @vif_wq: waitqueue awaiting interface event from firmware. - * @vif_event_lock: protects other members in this structure. - * @vif_complete: completion for net attach. - * @action: either add, change, or delete. - * @vif: virtual interface object related to the event. - */ -struct brcmf_cfg80211_vif_event { - wait_queue_head_t vif_wq; - struct mutex vif_event_lock; - u8 action; - struct brcmf_cfg80211_vif *vif; -}; - /** * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface * * @wiphy: wiphy object for cfg80211 interface. * @conf: dongle configuration. - * @p2p: peer-to-peer specific information. * @scan_request: cfg80211 scan request object. * @usr_sync: mainly for dongle up/down synchronization. * @bss_list: bss_list holding scanned ap information. @@ -374,12 +304,10 @@ struct brcmf_cfg80211_vif_event { * @escan_ioctl_buf: dongle command buffer for escan commands. * @vif_list: linked list of vif instances. * @vif_cnt: number of vif instances. - * @vif_event: vif event signalling. */ struct brcmf_cfg80211_info { struct wiphy *wiphy; struct brcmf_cfg80211_conf *conf; - struct brcmf_p2p_info p2p; struct cfg80211_scan_request *scan_request; struct mutex usr_sync; struct brcmf_scan_results *bss_list; @@ -407,21 +335,6 @@ struct brcmf_cfg80211_info { u8 *escan_ioctl_buf; struct list_head vif_list; u8 vif_cnt; - struct brcmf_cfg80211_vif_event vif_event; - struct completion vif_disabled; -}; - -/** - * struct brcmf_tlv - tag_ID/length/value_buffer tuple. - * - * @id: tag identifier. - * @len: number of bytes in value buffer. - * @data: value buffer. - */ -struct brcmf_tlv { - u8 id; - u8 len; - u8 data[1]; }; static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg) @@ -476,26 +389,4 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); -struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, - enum nl80211_iftype type, - bool pm_block); -void brcmf_free_vif(struct brcmf_cfg80211_vif *vif); - -s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag, - const u8 *vndr_ie_buf, u32 vndr_ie_len); -s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif); -struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key); -u16 channel_to_chanspec(struct ieee80211_channel *ch); -u32 wl_get_vif_state_all(struct brcmf_cfg80211_info *cfg, unsigned long state); -void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, - struct brcmf_cfg80211_vif *vif); -bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); -int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg, - u8 action, ulong timeout); -s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, - struct net_device *ndev, - bool aborted, bool fw_abort); -void brcmf_set_mpc(struct net_device *ndev, int mpc); -void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); - #endif /* _wl_cfg80211_h_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index 0985925cd3f4..c26992a60e6c 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -101,6 +101,8 @@ #define DOT11_RTS_LEN 16 #define DOT11_CTS_LEN 10 #define DOT11_BA_BITMAP_LEN 128 +#define DOT11_MIN_BEACON_PERIOD 1 +#define DOT11_MAX_BEACON_PERIOD 0xFFFF #define DOT11_MAXNUMFRAGS 16 #define DOT11_MAX_FRAG_LEN 2346 @@ -5553,7 +5555,8 @@ int brcms_c_set_rateset(struct brcms_c_info *wlc, struct brcm_rateset *rs) int brcms_c_set_beacon_period(struct brcms_c_info *wlc, u16 period) { - if (period == 0) + if (period < DOT11_MIN_BEACON_PERIOD || + period > DOT11_MAX_BEACON_PERIOD) return -EINVAL; wlc->default_bss->beacon_period = period; @@ -7405,13 +7408,9 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, struct brcms_bss_cfg *cfg, bool suspend) { - u16 *prb_resp; + u16 prb_resp[BCN_TMPL_LEN / 2]; int len = BCN_TMPL_LEN; - prb_resp = kmalloc(BCN_TMPL_LEN, GFP_ATOMIC); - if (!prb_resp) - return; - /* * write the probe response to hardware, or save in * the config structure @@ -7445,8 +7444,6 @@ brcms_c_bss_update_probe_resp(struct brcms_c_info *wlc, if (suspend) brcms_c_enable_mac(wlc); - - kfree(prb_resp); } void brcms_c_update_probe_resp(struct brcms_c_info *wlc, bool suspend) diff --git a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c index 83856d1a6101..050ce7c70d74 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c @@ -1001,12 +1001,12 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority) struct list_head *element; struct il_rx_buf *rxb; struct page *page; - dma_addr_t page_dma; unsigned long flags; gfp_t gfp_mask = priority; while (1) { spin_lock_irqsave(&rxq->lock, flags); + if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); return; @@ -1035,34 +1035,26 @@ il3945_rx_allocate(struct il_priv *il, gfp_t priority) break; } - /* Get physical address of RB/SKB */ - page_dma = - pci_map_page(il->pci_dev, page, 0, - PAGE_SIZE << il->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); - - if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) { - __free_pages(page, il->hw_params.rx_page_order); - break; - } - spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - pci_unmap_page(il->pci_dev, page_dma, - PAGE_SIZE << il->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); __free_pages(page, il->hw_params.rx_page_order); return; } - element = rxq->rx_used.next; rxb = list_entry(element, struct il_rx_buf, list); list_del(element); + spin_unlock_irqrestore(&rxq->lock, flags); rxb->page = page; - rxb->page_dma = page_dma; + /* Get physical address of RB/SKB */ + rxb->page_dma = + pci_map_page(il->pci_dev, page, 0, + PAGE_SIZE << il->hw_params.rx_page_order, + PCI_DMA_FROMDEVICE); + + spin_lock_irqsave(&rxq->lock, flags); + list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; il->alloc_rxb_page++; @@ -1292,15 +1284,8 @@ il3945_rx_handle(struct il_priv *il) pci_map_page(il->pci_dev, rxb->page, 0, PAGE_SIZE << il->hw_params. rx_page_order, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(il->pci_dev, - rxb->page_dma))) { - __il_free_pages(il, rxb->page); - rxb->page = NULL; - list_add_tail(&rxb->list, &rxq->rx_used); - } else { - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; } else list_add_tail(&rxb->list, &rxq->rx_used); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index 835662a449da..d665a3d9f08f 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -319,7 +319,6 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority) struct list_head *element; struct il_rx_buf *rxb; struct page *page; - dma_addr_t page_dma; unsigned long flags; gfp_t gfp_mask = priority; @@ -357,35 +356,33 @@ il4965_rx_allocate(struct il_priv *il, gfp_t priority) return; } - /* Get physical address of the RB */ - page_dma = - pci_map_page(il->pci_dev, page, 0, - PAGE_SIZE << il->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(il->pci_dev, page_dma))) { - __free_pages(page, il->hw_params.rx_page_order); - break; - } - spin_lock_irqsave(&rxq->lock, flags); if (list_empty(&rxq->rx_used)) { spin_unlock_irqrestore(&rxq->lock, flags); - pci_unmap_page(il->pci_dev, page_dma, - PAGE_SIZE << il->hw_params.rx_page_order, - PCI_DMA_FROMDEVICE); __free_pages(page, il->hw_params.rx_page_order); return; } - element = rxq->rx_used.next; rxb = list_entry(element, struct il_rx_buf, list); list_del(element); - BUG_ON(rxb->page); + spin_unlock_irqrestore(&rxq->lock, flags); + BUG_ON(rxb->page); rxb->page = page; - rxb->page_dma = page_dma; + /* Get physical address of the RB */ + rxb->page_dma = + pci_map_page(il->pci_dev, page, 0, + PAGE_SIZE << il->hw_params.rx_page_order, + PCI_DMA_FROMDEVICE); + /* dma address must be no more than 36 bits */ + BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36)); + /* and also 256 byte aligned! */ + BUG_ON(rxb->page_dma & DMA_BIT_MASK(8)); + + spin_lock_irqsave(&rxq->lock, flags); + list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; il->alloc_rxb_page++; @@ -728,16 +725,6 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) if (rate_n_flags & RATE_MCS_SGI_MSK) rx_status.flag |= RX_FLAG_SHORT_GI; - if (phy_res->phy_flags & RX_RES_PHY_FLAGS_AGG_MSK) { - /* We know which subframes of an A-MPDU belong - * together since we get a single PHY response - * from the firmware for all of them. - */ - - rx_status.flag |= RX_FLAG_AMPDU_DETAILS; - rx_status.ampdu_reference = il->_4965.ampdu_ref; - } - il4965_pass_packet_to_mac80211(il, header, len, ampdu_status, rxb, &rx_status); } @@ -749,7 +736,6 @@ il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb) { struct il_rx_pkt *pkt = rxb_addr(rxb); il->_4965.last_phy_res_valid = true; - il->_4965.ampdu_ref++; memcpy(&il->_4965.last_phy_res, pkt->u.raw, sizeof(struct il_rx_phy_res)); } @@ -4295,16 +4281,8 @@ il4965_rx_handle(struct il_priv *il) pci_map_page(il->pci_dev, rxb->page, 0, PAGE_SIZE << il->hw_params. rx_page_order, PCI_DMA_FROMDEVICE); - - if (unlikely(pci_dma_mapping_error(il->pci_dev, - rxb->page_dma))) { - __il_free_pages(il, rxb->page); - rxb->page = NULL; - list_add_tail(&rxb->list, &rxq->rx_used); - } else { - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; } else list_add_tail(&rxb->list, &rxq->rx_used); @@ -5733,7 +5711,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS; if (il->cfg->sku & IL_SKU_N) diff --git a/trunk/drivers/net/wireless/iwlegacy/commands.h b/trunk/drivers/net/wireless/iwlegacy/commands.h index 3b6c99400892..829d3b9aaa17 100644 --- a/trunk/drivers/net/wireless/iwlegacy/commands.h +++ b/trunk/drivers/net/wireless/iwlegacy/commands.h @@ -1136,7 +1136,6 @@ struct il_wep_cmd { #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) #define RX_RES_PHY_FLAGS_ANTENNA_MSK 0x70 #define RX_RES_PHY_FLAGS_ANTENNA_POS 4 -#define RX_RES_PHY_FLAGS_AGG_MSK cpu_to_le16(1 << 7) #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) diff --git a/trunk/drivers/net/wireless/iwlegacy/common.h b/trunk/drivers/net/wireless/iwlegacy/common.h index 96f2025d936e..37fe553b25e0 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.h +++ b/trunk/drivers/net/wireless/iwlegacy/common.h @@ -1356,7 +1356,6 @@ struct il_priv { struct { struct il_rx_phy_res last_phy_res; bool last_phy_res_valid; - u32 ampdu_ref; struct completion firmware_loading_complete; diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c index 0fccf725a2e6..c2f03ecd4bf8 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/mac80211.c @@ -145,13 +145,14 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_QUEUE_CONTROL | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | - IEEE80211_HW_WANT_MONITOR_VIF; + IEEE80211_HW_WANT_MONITOR_VIF | + IEEE80211_HW_SCAN_WHILE_IDLE; hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT; diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c b/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c index 90473c2ba1c7..d3d959db03a9 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -621,10 +621,6 @@ int iwl_mvm_rx_card_state_notif(struct iwl_mvm *mvm, (flags & CT_KILL_CARD_DISABLED) ? "Reached" : "Not reached"); - if (flags & CARD_DISABLED_MSK) - iwl_write32(mvm->trans, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - return 0; } diff --git a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c index bbb8a5b35662..a6b05a02cfd4 100644 --- a/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/trunk/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -113,7 +113,8 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_QUEUE_CONTROL | IEEE80211_HW_WANT_MONITOR_VIF | - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | + IEEE80211_HW_SCAN_WHILE_IDLE | + IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_AMPDU_AGGREGATION; diff --git a/trunk/drivers/net/wireless/libertas/cfg.c b/trunk/drivers/net/wireless/libertas/cfg.c index 61735db3b051..230f8ebbe289 100644 --- a/trunk/drivers/net/wireless/libertas/cfg.c +++ b/trunk/drivers/net/wireless/libertas/cfg.c @@ -657,7 +657,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, capa, intvl, ie, ielen, LBS_SCAN_RSSI_TO_MBM(rssi), GFP_KERNEL); - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); } } else lbs_deb_scan("scan response: missing BSS channel IE\n"); @@ -1444,7 +1444,7 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, done: if (bss) - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); return ret; } @@ -1766,7 +1766,7 @@ static void lbs_join_post(struct lbs_private *priv, params->beacon_interval, fake_ie, fake - fake_ie, 0, GFP_KERNEL); - cfg80211_put_bss(priv->wdev->wiphy, bss); + cfg80211_put_bss(bss); memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); priv->wdev->ssid_len = params->ssid_len; @@ -2011,7 +2011,7 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, if (bss) { ret = lbs_ibss_join_existing(priv, params, bss); - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); } else ret = lbs_ibss_start_new(priv, params); diff --git a/trunk/drivers/net/wireless/mwifiex/11n.c b/trunk/drivers/net/wireless/mwifiex/11n.c index 48cc46bc152f..9cd6216c61e6 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n.c +++ b/trunk/drivers/net/wireless/mwifiex/11n.c @@ -399,6 +399,45 @@ mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, return ret_len; } +/* + * This function reconfigures the Tx buffer size in firmware. + * + * This function prepares a firmware command and issues it, if + * the current Tx buffer size is different from the one requested. + * Maximum configurable Tx buffer size is limited by the HT capability + * field value. + */ +void +mwifiex_cfg_tx_buf(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc) +{ + u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; + u16 tx_buf, curr_tx_buf_size = 0; + + if (bss_desc->bcn_ht_cap) { + if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & + IEEE80211_HT_CAP_MAX_AMSDU) + max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_8K; + else + max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_4K; + } + + tx_buf = min(priv->adapter->max_tx_buf_size, max_amsdu); + + dev_dbg(priv->adapter->dev, "info: max_amsdu=%d, max_tx_buf=%d\n", + max_amsdu, priv->adapter->max_tx_buf_size); + + if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_2K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; + else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_4K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; + else if (priv->adapter->curr_tx_buf_size <= MWIFIEX_TX_DATA_BUF_SIZE_8K) + curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_8K; + if (curr_tx_buf_size != tx_buf) + mwifiex_send_cmd_async(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, &tx_buf); +} + /* * This function checks if the given pointer is valid entry of * Tx BA Stream table. diff --git a/trunk/drivers/net/wireless/mwifiex/11n.h b/trunk/drivers/net/wireless/mwifiex/11n.h index 29a4c02479d6..46006a54a656 100644 --- a/trunk/drivers/net/wireless/mwifiex/11n.h +++ b/trunk/drivers/net/wireless/mwifiex/11n.h @@ -34,6 +34,8 @@ int mwifiex_cmd_11n_cfg(struct host_cmd_ds_command *cmd, u16 cmd_action, int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc, u8 **buffer); +void mwifiex_cfg_tx_buf(struct mwifiex_private *priv, + struct mwifiex_bssdescriptor *bss_desc); void mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, struct mwifiex_ie_types_htcap *); int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, diff --git a/trunk/drivers/net/wireless/mwifiex/Kconfig b/trunk/drivers/net/wireless/mwifiex/Kconfig index 4f614aad9ded..b2e27723f801 100644 --- a/trunk/drivers/net/wireless/mwifiex/Kconfig +++ b/trunk/drivers/net/wireless/mwifiex/Kconfig @@ -20,12 +20,12 @@ config MWIFIEX_SDIO mwifiex_sdio. config MWIFIEX_PCIE - tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897" + tristate "Marvell WiFi-Ex Driver for PCIE 8766" depends on MWIFIEX && PCI select FW_LOADER ---help--- This adds support for wireless adapters based on Marvell - 8766/8897 chipsets with PCIe interface. + 8766 chipset with PCIe interface. If you choose to build it as a module, it will be called mwifiex_pcie. diff --git a/trunk/drivers/net/wireless/mwifiex/README b/trunk/drivers/net/wireless/mwifiex/README index 3d64613ebb29..b55badef4660 100644 --- a/trunk/drivers/net/wireless/mwifiex/README +++ b/trunk/drivers/net/wireless/mwifiex/README @@ -121,6 +121,7 @@ info wmm_ac_vi = wmm_ac_be = wmm_ac_bk = + max_tx_buf_size = tx_buf_size = curr_tx_buf_size = ps_mode = <0/1, CAM mode/PS mode> diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index 81c84a29308f..3a004b85b99f 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -1430,7 +1430,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) bss = cfg80211_inform_bss(priv->wdev->wiphy, chan, bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, 0, ie_buf, ie_len, 0, GFP_KERNEL); - cfg80211_put_bss(priv->wdev->wiphy, bss); + cfg80211_put_bss(bss); memcpy(priv->cfg_bssid, bss_info.bssid, ETH_ALEN); return 0; diff --git a/trunk/drivers/net/wireless/mwifiex/debugfs.c b/trunk/drivers/net/wireless/mwifiex/debugfs.c index 753b5682d53f..46e34aa65d1c 100644 --- a/trunk/drivers/net/wireless/mwifiex/debugfs.c +++ b/trunk/drivers/net/wireless/mwifiex/debugfs.c @@ -58,6 +58,8 @@ static struct mwifiex_debug_data items[] = { item_addr(packets_out[WMM_AC_BE]), 1}, {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), item_addr(packets_out[WMM_AC_BK]), 1}, + {"max_tx_buf_size", item_size(max_tx_buf_size), + item_addr(max_tx_buf_size), 1}, {"tx_buf_size", item_size(tx_buf_size), item_addr(tx_buf_size), 1}, {"curr_tx_buf_size", item_size(curr_tx_buf_size), diff --git a/trunk/drivers/net/wireless/mwifiex/init.c b/trunk/drivers/net/wireless/mwifiex/init.c index 820a19cfa562..e00b8060aff7 100644 --- a/trunk/drivers/net/wireless/mwifiex/init.c +++ b/trunk/drivers/net/wireless/mwifiex/init.c @@ -317,6 +317,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) adapter->pm_wakeup_fw_try = false; + adapter->max_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; diff --git a/trunk/drivers/net/wireless/mwifiex/ioctl.h b/trunk/drivers/net/wireless/mwifiex/ioctl.h index f3d9d0445529..6095b3e53f4e 100644 --- a/trunk/drivers/net/wireless/mwifiex/ioctl.h +++ b/trunk/drivers/net/wireless/mwifiex/ioctl.h @@ -178,6 +178,7 @@ struct mwifiex_ds_tx_ba_stream_tbl { struct mwifiex_debug_info { u32 int_counter; u32 packets_out[MAX_NUM_TID]; + u32 max_tx_buf_size; u32 tx_buf_size; u32 curr_tx_buf_size; u32 tx_tbl_num; diff --git a/trunk/drivers/net/wireless/mwifiex/join.c b/trunk/drivers/net/wireless/mwifiex/join.c index a537297866c6..f0a634d237c1 100644 --- a/trunk/drivers/net/wireless/mwifiex/join.c +++ b/trunk/drivers/net/wireless/mwifiex/join.c @@ -398,6 +398,8 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, pos = (u8 *) assoc; + mwifiex_cfg_tx_buf(priv, bss_desc); + cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); /* Save so we know which BSS Desc to use in the response handler */ diff --git a/trunk/drivers/net/wireless/mwifiex/main.h b/trunk/drivers/net/wireless/mwifiex/main.h index ac799a046eb7..51044e3ea89b 100644 --- a/trunk/drivers/net/wireless/mwifiex/main.h +++ b/trunk/drivers/net/wireless/mwifiex/main.h @@ -631,6 +631,7 @@ struct mwifiex_adapter { /* spin lock for main process */ spinlock_t main_proc_lock; u32 mwifiex_processing; + u16 max_tx_buf_size; u16 tx_buf_size; u16 curr_tx_buf_size; u32 ioport; diff --git a/trunk/drivers/net/wireless/mwifiex/pcie.c b/trunk/drivers/net/wireless/mwifiex/pcie.c index 3b9be7c185cb..df88e65595c8 100644 --- a/trunk/drivers/net/wireless/mwifiex/pcie.c +++ b/trunk/drivers/net/wireless/mwifiex/pcie.c @@ -94,13 +94,6 @@ static int mwifiex_pcie_probe(struct pci_dev *pdev, card->dev = pdev; - if (ent->driver_data) { - struct mwifiex_pcie_device *data = (void *)ent->driver_data; - card->pcie.firmware = data->firmware; - card->pcie.reg = data->reg; - card->pcie.blksz_fw_dl = data->blksz_fw_dl; - } - if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, MWIFIEX_PCIE)) { pr_err("%s failed\n", __func__); @@ -237,16 +230,13 @@ static int mwifiex_pcie_resume(struct pci_dev *pdev) return 0; } +#define PCIE_VENDOR_ID_MARVELL (0x11ab) +#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30) + static DEFINE_PCI_DEVICE_TABLE(mwifiex_ids) = { { PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - .driver_data = (unsigned long) &mwifiex_pcie8766, - }, - { - PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - .driver_data = (unsigned long) &mwifiex_pcie8897, }, {}, }; @@ -374,246 +364,12 @@ static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter) } /* - * This function initializes TX buffer ring descriptors - */ -static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - card->tx_buf_list[i] = NULL; - if (reg->pfu_enabled) { - card->txbd_ring[i] = (void *)card->txbd_ring_vbase + - (sizeof(*desc2) * i); - desc2 = card->txbd_ring[i]; - memset(desc2, 0, sizeof(*desc2)); - } else { - card->txbd_ring[i] = (void *)card->txbd_ring_vbase + - (sizeof(*desc) * i); - desc = card->txbd_ring[i]; - memset(desc, 0, sizeof(*desc)); - } - } - - return 0; -} - -/* This function initializes RX buffer ring descriptors. Each SKB is allocated - * here and after mapping PCI memory, its physical address is assigned to - * PCIE Rx buffer descriptor's physical address. - */ -static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct sk_buff *skb; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - dma_addr_t buf_pa; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - /* Allocate skb here so that firmware can DMA data from it */ - skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); - if (!skb) { - dev_err(adapter->dev, - "Unable to allocate skb for RX ring.\n"); - kfree(card->rxbd_ring_vbase); - return -ENOMEM; - } - - if (mwifiex_map_pci_memory(adapter, skb, - MWIFIEX_RX_DATA_BUF_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - MWIFIEX_SKB_PACB(skb, &buf_pa); - - dev_dbg(adapter->dev, - "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", - skb, skb->len, skb->data, (u32)buf_pa, - (u32)((u64)buf_pa >> 32)); - - card->rx_buf_list[i] = skb; - if (reg->pfu_enabled) { - card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase + - (sizeof(*desc2) * i); - desc2 = card->rxbd_ring[i]; - desc2->paddr = buf_pa; - desc2->len = (u16)skb->len; - desc2->frag_len = (u16)skb->len; - desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop; - desc2->offset = 0; - } else { - card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase + - (sizeof(*desc) * i)); - desc = card->rxbd_ring[i]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = 0; - } - } - - return 0; -} - -/* This function initializes event buffer ring descriptors. Each SKB is - * allocated here and after mapping PCI memory, its physical address is assigned - * to PCIE Rx buffer descriptor's physical address - */ -static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_evt_buf_desc *desc; - struct sk_buff *skb; - dma_addr_t buf_pa; - int i; - - for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { - /* Allocate skb here so that firmware can DMA data from it */ - skb = dev_alloc_skb(MAX_EVENT_SIZE); - if (!skb) { - dev_err(adapter->dev, - "Unable to allocate skb for EVENT buf.\n"); - kfree(card->evtbd_ring_vbase); - return -ENOMEM; - } - skb_put(skb, MAX_EVENT_SIZE); - - if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - MWIFIEX_SKB_PACB(skb, &buf_pa); - - dev_dbg(adapter->dev, - "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", - skb, skb->len, skb->data, (u32)buf_pa, - (u32)((u64)buf_pa >> 32)); - - card->evt_buf_list[i] = skb; - card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase + - (sizeof(*desc) * i)); - desc = card->evtbd_ring[i]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = 0; - } - - return 0; -} - -/* This function cleans up TX buffer rings. If any of the buffer list has valid - * SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct sk_buff *skb; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - if (reg->pfu_enabled) { - desc2 = card->txbd_ring[i]; - if (card->tx_buf_list[i]) { - skb = card->tx_buf_list[i]; - pci_unmap_single(card->dev, desc2->paddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->txbd_ring[i]; - if (card->tx_buf_list[i]) { - skb = card->tx_buf_list[i]; - pci_unmap_single(card->dev, desc->paddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc, 0, sizeof(*desc)); - } - card->tx_buf_list[i] = NULL; - } - - return; -} - -/* This function cleans up RX buffer rings. If any of the buffer list has valid - * SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - struct sk_buff *skb; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - if (reg->pfu_enabled) { - desc2 = card->rxbd_ring[i]; - if (card->rx_buf_list[i]) { - skb = card->rx_buf_list[i]; - pci_unmap_single(card->dev, desc2->paddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->rxbd_ring[i]; - if (card->rx_buf_list[i]) { - skb = card->rx_buf_list[i]; - pci_unmap_single(card->dev, desc->paddr, - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc, 0, sizeof(*desc)); - } - card->rx_buf_list[i] = NULL; - } - - return; -} - -/* This function cleans up event buffer rings. If any of the buffer list has - * valid SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_evt_buf_desc *desc; - struct sk_buff *skb; - int i; - - for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { - desc = card->evtbd_ring[i]; - if (card->evt_buf_list[i]) { - skb = card->evt_buf_list[i]; - pci_unmap_single(card->dev, desc->paddr, MAX_EVENT_SIZE, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - } - card->evt_buf_list[i] = NULL; - memset(desc, 0, sizeof(*desc)); - } - - return; -} - -/* This function creates buffer descriptor ring for TX + * This function creates buffer descriptor ring for TX */ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + int i; /* * driver maintaines the write pointer and firmware maintaines the read @@ -621,21 +377,12 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) * starts at zero with rollover bit set */ card->txbd_wrptr = 0; - - if (reg->pfu_enabled) - card->txbd_rdptr = 0; - else - card->txbd_rdptr |= reg->tx_rollover_ind; + card->txbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; /* allocate shared memory for the BD ring and divide the same in to several descriptors */ - if (reg->pfu_enabled) - card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - else - card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - + card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * + MWIFIEX_MAX_TXRX_BD; dev_dbg(adapter->dev, "info: txbd_ring: Allocating %d bytes\n", card->txbd_ring_size); card->txbd_ring_vbase = pci_alloc_consistent(card->dev, @@ -652,15 +399,40 @@ static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase, (u32)((u64)card->txbd_ring_pbase >> 32), card->txbd_ring_size); - return mwifiex_init_txq_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { + card->txbd_ring[i] = (struct mwifiex_pcie_buf_desc *) + (card->txbd_ring_vbase + + (sizeof(struct mwifiex_pcie_buf_desc) + * i)); + + card->tx_buf_list[i] = NULL; + card->txbd_ring[i]->paddr = 0; + card->txbd_ring[i]->len = 0; + card->txbd_ring[i]->flags = 0; + } + + return 0; } static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + struct sk_buff *skb; + int i; - mwifiex_cleanup_txq_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { + if (card->tx_buf_list[i]) { + skb = card->tx_buf_list[i]; + pci_unmap_single(card->dev, card->txbd_ring[i]->paddr, + skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_any(skb); + } + card->tx_buf_list[i] = NULL; + card->txbd_ring[i]->paddr = 0; + card->txbd_ring[i]->len = 0; + card->txbd_ring[i]->flags = 0; + card->txbd_ring[i] = NULL; + } if (card->txbd_ring_vbase) pci_free_consistent(card->dev, card->txbd_ring_size, @@ -668,7 +440,7 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) card->txbd_ring_pbase); card->txbd_ring_size = 0; card->txbd_wrptr = 0; - card->txbd_rdptr = 0 | reg->tx_rollover_ind; + card->txbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; card->txbd_ring_vbase = NULL; card->txbd_ring_pbase = 0; @@ -681,7 +453,9 @@ static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + struct sk_buff *skb; + int i; + dma_addr_t buf_pa; /* * driver maintaines the read pointer and firmware maintaines the write @@ -689,15 +463,10 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) * starts at zero with rollover bit set */ card->rxbd_wrptr = 0; - card->rxbd_rdptr = reg->rx_rollover_ind; - - if (reg->pfu_enabled) - card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - else - card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * - MWIFIEX_MAX_TXRX_BD; + card->rxbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; + card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * + MWIFIEX_MAX_TXRX_BD; dev_dbg(adapter->dev, "info: rxbd_ring: Allocating %d bytes\n", card->rxbd_ring_size); card->rxbd_ring_vbase = pci_alloc_consistent(card->dev, @@ -716,7 +485,39 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->rxbd_ring_pbase >> 32), card->rxbd_ring_size); - return mwifiex_init_rxq_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { + card->rxbd_ring[i] = (struct mwifiex_pcie_buf_desc *) + (card->rxbd_ring_vbase + + (sizeof(struct mwifiex_pcie_buf_desc) + * i)); + + /* Allocate skb here so that firmware can DMA data from it */ + skb = dev_alloc_skb(MWIFIEX_RX_DATA_BUF_SIZE); + if (!skb) { + dev_err(adapter->dev, + "Unable to allocate skb for RX ring.\n"); + kfree(card->rxbd_ring_vbase); + return -ENOMEM; + } + if (mwifiex_map_pci_memory(adapter, skb, + MWIFIEX_RX_DATA_BUF_SIZE, + PCI_DMA_FROMDEVICE)) + return -1; + + MWIFIEX_SKB_PACB(skb, &buf_pa); + + dev_dbg(adapter->dev, "info: RX ring: add new skb base: %p, " + "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", + skb, skb->data, (u32)buf_pa, (u32)((u64)buf_pa >> 32), + skb->len); + + card->rx_buf_list[i] = skb; + card->rxbd_ring[i]->paddr = buf_pa; + card->rxbd_ring[i]->len = (u16)skb->len; + card->rxbd_ring[i]->flags = 0; + } + + return 0; } /* @@ -725,9 +526,23 @@ static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + struct sk_buff *skb; + int i; - mwifiex_cleanup_rxq_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { + if (card->rx_buf_list[i]) { + skb = card->rx_buf_list[i]; + pci_unmap_single(card->dev, card->rxbd_ring[i]->paddr , + MWIFIEX_RX_DATA_BUF_SIZE, + PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + } + card->rx_buf_list[i] = NULL; + card->rxbd_ring[i]->paddr = 0; + card->rxbd_ring[i]->len = 0; + card->rxbd_ring[i]->flags = 0; + card->rxbd_ring[i] = NULL; + } if (card->rxbd_ring_vbase) pci_free_consistent(card->dev, card->rxbd_ring_size, @@ -735,7 +550,7 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) card->rxbd_ring_pbase); card->rxbd_ring_size = 0; card->rxbd_wrptr = 0; - card->rxbd_rdptr = 0 | reg->rx_rollover_ind; + card->rxbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; card->rxbd_ring_vbase = NULL; card->rxbd_ring_pbase = 0; @@ -748,7 +563,9 @@ static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + struct sk_buff *skb; + int i; + dma_addr_t buf_pa; /* * driver maintaines the read pointer and firmware maintaines the write @@ -756,11 +573,10 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) * starts at zero with rollover bit set */ card->evtbd_wrptr = 0; - card->evtbd_rdptr = reg->evt_rollover_ind; - - card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) * - MWIFIEX_MAX_EVT_BD; + card->evtbd_rdptr |= MWIFIEX_BD_FLAG_ROLLOVER_IND; + card->evtbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * + MWIFIEX_MAX_EVT_BD; dev_dbg(adapter->dev, "info: evtbd_ring: Allocating %d bytes\n", card->evtbd_ring_size); card->evtbd_ring_vbase = pci_alloc_consistent(card->dev, @@ -779,7 +595,39 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) (u32)((u64)card->evtbd_ring_pbase >> 32), card->evtbd_ring_size); - return mwifiex_pcie_init_evt_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { + card->evtbd_ring[i] = (struct mwifiex_pcie_buf_desc *) + (card->evtbd_ring_vbase + + (sizeof(struct mwifiex_pcie_buf_desc) + * i)); + + /* Allocate skb here so that firmware can DMA data from it */ + skb = dev_alloc_skb(MAX_EVENT_SIZE); + if (!skb) { + dev_err(adapter->dev, + "Unable to allocate skb for EVENT buf.\n"); + kfree(card->evtbd_ring_vbase); + return -ENOMEM; + } + skb_put(skb, MAX_EVENT_SIZE); + + if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, + PCI_DMA_FROMDEVICE)) + return -1; + + MWIFIEX_SKB_PACB(skb, &buf_pa); + dev_dbg(adapter->dev, "info: Evt ring: add new skb. base: %p, " + "buf_base: %p, buf_pbase: %#x:%x, buf_len: %#x\n", + skb, skb->data, (u32)buf_pa, (u32)((u64)buf_pa >> 32), + skb->len); + + card->evt_buf_list[i] = skb; + card->evtbd_ring[i]->paddr = buf_pa; + card->evtbd_ring[i]->len = (u16)skb->len; + card->evtbd_ring[i]->flags = 0; + } + + return 0; } /* @@ -788,16 +636,29 @@ static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; + struct sk_buff *skb; + int i; - mwifiex_cleanup_evt_ring(adapter); + for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { + if (card->evt_buf_list[i]) { + skb = card->evt_buf_list[i]; + pci_unmap_single(card->dev, card->evtbd_ring[i]->paddr, + MAX_EVENT_SIZE, PCI_DMA_FROMDEVICE); + dev_kfree_skb_any(skb); + } + card->evt_buf_list[i] = NULL; + card->evtbd_ring[i]->paddr = 0; + card->evtbd_ring[i]->len = 0; + card->evtbd_ring[i]->flags = 0; + card->evtbd_ring[i] = NULL; + } if (card->evtbd_ring_vbase) pci_free_consistent(card->dev, card->evtbd_ring_size, card->evtbd_ring_vbase, card->evtbd_ring_pbase); card->evtbd_wrptr = 0; - card->evtbd_rdptr = 0 | reg->evt_rollover_ind; + card->evtbd_rdptr = 0 | MWIFIEX_BD_FLAG_ROLLOVER_IND; card->evtbd_ring_size = 0; card->evtbd_ring_vbase = NULL; card->evtbd_ring_pbase = 0; @@ -910,13 +771,12 @@ static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter) static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; u32 rdptr; /* Read the TX ring read pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) { + if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { dev_err(adapter->dev, - "Flush TXBD: failed to read reg->tx_rdptr\n"); + "Flush TXBD: failed to read REG_TXBD_RDPTR\n"); return -1; } @@ -940,35 +800,31 @@ static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) */ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) { + const u32 num_tx_buffs = MWIFIEX_MAX_TXRX_BD; struct sk_buff *skb; dma_addr_t buf_pa; - u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; + u32 wrdoneidx, rdptr, unmap_count = 0; struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; if (!mwifiex_pcie_ok_to_access_hw(adapter)) mwifiex_pm_wakeup_card(adapter); /* Read the TX ring read pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) { + if (mwifiex_read_reg(adapter, REG_TXBD_RDPTR, &rdptr)) { dev_err(adapter->dev, - "SEND COMP: failed to read reg->tx_rdptr\n"); + "SEND COMP: failed to read REG_TXBD_RDPTR\n"); return -1; } dev_dbg(adapter->dev, "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n", card->txbd_rdptr, rdptr); - num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr; /* free from previous txbd_rdptr to current txbd_rdptr */ - while (((card->txbd_rdptr & reg->tx_mask) != - (rdptr & reg->tx_mask)) || - ((card->txbd_rdptr & reg->tx_rollover_ind) != - (rdptr & reg->tx_rollover_ind))) { - wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >> - reg->tx_start_ptr; + while (((card->txbd_rdptr & MWIFIEX_TXBD_MASK) != + (rdptr & MWIFIEX_TXBD_MASK)) || + ((card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != + (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { + wrdoneidx = card->txbd_rdptr & MWIFIEX_TXBD_MASK; skb = card->tx_buf_list[wrdoneidx]; if (skb) { @@ -989,38 +845,25 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) } card->tx_buf_list[wrdoneidx] = NULL; + card->txbd_ring[wrdoneidx]->paddr = 0; + card->txbd_ring[wrdoneidx]->len = 0; + card->txbd_ring[wrdoneidx]->flags = 0; + card->txbd_rdptr++; - if (reg->pfu_enabled) { - desc2 = (void *)card->txbd_ring[wrdoneidx]; - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->txbd_ring[wrdoneidx]; - memset(desc, 0, sizeof(*desc)); - } - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - card->txbd_rdptr++; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - card->txbd_rdptr += reg->ring_tx_start_ptr; - break; - } - - - if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs) + if ((card->txbd_rdptr & MWIFIEX_TXBD_MASK) == num_tx_buffs) card->txbd_rdptr = ((card->txbd_rdptr & - reg->tx_rollover_ind) ^ - reg->tx_rollover_ind); + MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ + MWIFIEX_BD_FLAG_ROLLOVER_IND); } if (unmap_count) adapter->data_sent = false; if (card->txbd_flush) { - if (((card->txbd_wrptr & reg->tx_mask) == - (card->txbd_rdptr & reg->tx_mask)) && - ((card->txbd_wrptr & reg->tx_rollover_ind) != - (card->txbd_rdptr & reg->tx_rollover_ind))) + if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) == + (card->txbd_rdptr & MWIFIEX_TXBD_MASK)) && + ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != + (card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) card->txbd_flush = 0; else mwifiex_clean_pcie_ring_buf(adapter); @@ -1040,12 +883,9 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, struct mwifiex_tx_param *tx_param) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 wrindx, num_tx_buffs, rx_val; + u32 wrindx; int ret; dma_addr_t buf_pa; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; __le16 *tmp; if (!(skb->data && skb->len)) { @@ -1057,7 +897,6 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, if (!mwifiex_pcie_ok_to_access_hw(adapter)) mwifiex_pm_wakeup_card(adapter); - num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr; dev_dbg(adapter->dev, "info: SEND DATA: \n", card->txbd_rdptr, card->txbd_wrptr); if (mwifiex_pcie_txbd_not_full(card)) { @@ -1074,46 +913,25 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, PCI_DMA_TODEVICE)) return -1; - wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; + wrindx = card->txbd_wrptr & MWIFIEX_TXBD_MASK; MWIFIEX_SKB_PACB(skb, &buf_pa); card->tx_buf_list[wrindx] = skb; + card->txbd_ring[wrindx]->paddr = buf_pa; + card->txbd_ring[wrindx]->len = (u16)skb->len; + card->txbd_ring[wrindx]->flags = MWIFIEX_BD_FLAG_FIRST_DESC | + MWIFIEX_BD_FLAG_LAST_DESC; - if (reg->pfu_enabled) { - desc2 = (void *)card->txbd_ring[wrindx]; - desc2->paddr = buf_pa; - desc2->len = (u16)skb->len; - desc2->frag_len = (u16)skb->len; - desc2->offset = 0; - desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC | - MWIFIEX_BD_FLAG_LAST_DESC; - } else { - desc = card->txbd_ring[wrindx]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC | - MWIFIEX_BD_FLAG_LAST_DESC; - } - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - card->txbd_wrptr++; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - card->txbd_wrptr += reg->ring_tx_start_ptr; - break; - } - - if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs) + if ((++card->txbd_wrptr & MWIFIEX_TXBD_MASK) == + MWIFIEX_MAX_TXRX_BD) card->txbd_wrptr = ((card->txbd_wrptr & - reg->tx_rollover_ind) ^ - reg->tx_rollover_ind); + MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ + MWIFIEX_BD_FLAG_ROLLOVER_IND); - rx_val = card->rxbd_rdptr & reg->rx_wrap_mask; - /* Write the TX ring write pointer in to reg->tx_wrptr */ - if (mwifiex_write_reg(adapter, reg->tx_wrptr, - card->txbd_wrptr | rx_val)) { + /* Write the TX ring write pointer in to REG_TXBD_WRPTR */ + if (mwifiex_write_reg(adapter, REG_TXBD_WRPTR, + card->txbd_wrptr)) { dev_err(adapter->dev, - "SEND DATA: failed to write reg->tx_wrptr\n"); + "SEND DATA: failed to write REG_TXBD_WRPTR\n"); ret = -1; goto done_unmap; } @@ -1153,11 +971,9 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, MWIFIEX_SKB_PACB(skb, &buf_pa); pci_unmap_single(card->dev, buf_pa, skb->len, PCI_DMA_TODEVICE); card->tx_buf_list[wrindx] = NULL; - if (reg->pfu_enabled) - memset(desc2, 0, sizeof(*desc2)); - else - memset(desc, 0, sizeof(*desc)); - + card->txbd_ring[wrindx]->paddr = 0; + card->txbd_ring[wrindx]->len = 0; + card->txbd_ring[wrindx]->flags = 0; return ret; } @@ -1168,35 +984,32 @@ mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 wrptr, rd_index, tx_val; + u32 wrptr, rd_index; dma_addr_t buf_pa; int ret = 0; struct sk_buff *skb_tmp = NULL; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; if (!mwifiex_pcie_ok_to_access_hw(adapter)) mwifiex_pm_wakeup_card(adapter); /* Read the RX ring Write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) { + if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { dev_err(adapter->dev, - "RECV DATA: failed to read reg->rx_wrptr\n"); + "RECV DATA: failed to read REG_TXBD_RDPTR\n"); ret = -1; goto done; } card->rxbd_wrptr = wrptr; - while (((wrptr & reg->rx_mask) != - (card->rxbd_rdptr & reg->rx_mask)) || - ((wrptr & reg->rx_rollover_ind) == - (card->rxbd_rdptr & reg->rx_rollover_ind))) { + while (((wrptr & MWIFIEX_RXBD_MASK) != + (card->rxbd_rdptr & MWIFIEX_RXBD_MASK)) || + ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) == + (card->rxbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { struct sk_buff *skb_data; u16 rx_len; __le16 pkt_len; - rd_index = card->rxbd_rdptr & reg->rx_mask; + rd_index = card->rxbd_rdptr & MWIFIEX_RXBD_MASK; skb_data = card->rx_buf_list[rd_index]; MWIFIEX_SKB_PACB(skb_data, &buf_pa); @@ -1234,44 +1047,32 @@ static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", skb_tmp, rd_index); card->rx_buf_list[rd_index] = skb_tmp; + card->rxbd_ring[rd_index]->paddr = buf_pa; + card->rxbd_ring[rd_index]->len = skb_tmp->len; + card->rxbd_ring[rd_index]->flags = 0; - if (reg->pfu_enabled) { - desc2 = (void *)card->rxbd_ring[rd_index]; - desc2->paddr = buf_pa; - desc2->len = skb_tmp->len; - desc2->frag_len = skb_tmp->len; - desc2->offset = 0; - desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop; - } else { - desc = card->rxbd_ring[rd_index]; - desc->paddr = buf_pa; - desc->len = skb_tmp->len; - desc->flags = 0; - } - - if ((++card->rxbd_rdptr & reg->rx_mask) == + if ((++card->rxbd_rdptr & MWIFIEX_RXBD_MASK) == MWIFIEX_MAX_TXRX_BD) { card->rxbd_rdptr = ((card->rxbd_rdptr & - reg->rx_rollover_ind) ^ - reg->rx_rollover_ind); + MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ + MWIFIEX_BD_FLAG_ROLLOVER_IND); } dev_dbg(adapter->dev, "info: RECV DATA: \n", card->rxbd_rdptr, wrptr); - tx_val = card->txbd_wrptr & reg->tx_wrap_mask; - /* Write the RX ring read pointer in to reg->rx_rdptr */ - if (mwifiex_write_reg(adapter, reg->rx_rdptr, - card->rxbd_rdptr | tx_val)) { + /* Write the RX ring read pointer in to REG_RXBD_RDPTR */ + if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR, + card->rxbd_rdptr)) { dev_err(adapter->dev, - "RECV DATA: failed to write reg->rx_rdptr\n"); + "RECV DATA: failed to write REG_RXBD_RDPTR\n"); ret = -1; goto done; } /* Read the RX ring Write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) { + if (mwifiex_read_reg(adapter, REG_RXBD_WRPTR, &wrptr)) { dev_err(adapter->dev, - "RECV DATA: failed to read reg->rx_wrptr\n"); + "RECV DATA: failed to read REG_TXBD_RDPTR\n"); ret = -1; goto done; } @@ -1292,7 +1093,6 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) { dma_addr_t buf_pa; struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; if (!(skb->data && skb->len)) { dev_err(adapter->dev, @@ -1306,10 +1106,9 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) MWIFIEX_SKB_PACB(skb, &buf_pa); - /* Write the lower 32bits of the physical address to low command - * address scratch register - */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) { + /* Write the lower 32bits of the physical address to scratch + * register 0 */ + if (mwifiex_write_reg(adapter, PCIE_SCRATCH_0_REG, (u32)buf_pa)) { dev_err(adapter->dev, "%s: failed to write download command to boot code.\n", __func__); @@ -1318,10 +1117,9 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) return -1; } - /* Write the upper 32bits of the physical address to high command - * address scratch register - */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_hi, + /* Write the upper 32bits of the physical address to scratch + * register 1 */ + if (mwifiex_write_reg(adapter, PCIE_SCRATCH_1_REG, (u32)((u64)buf_pa >> 32))) { dev_err(adapter->dev, "%s: failed to write download command to boot code.\n", @@ -1331,10 +1129,10 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) return -1; } - /* Write the command length to cmd_size scratch register */ - if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) { + /* Write the command length to scratch register 2 */ + if (mwifiex_write_reg(adapter, PCIE_SCRATCH_2_REG, skb->len)) { dev_err(adapter->dev, - "%s: failed to write command len to cmd_size scratch reg\n", + "%s: failed to write command len to scratch reg 2\n", __func__); pci_unmap_single(card->dev, buf_pa, MWIFIEX_UPLD_SIZE, PCI_DMA_TODEVICE); @@ -1360,14 +1158,11 @@ mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask; - /* Write the RX ring read pointer in to reg->rx_rdptr */ - if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr | - tx_wrap)) { + /* Write the RX ring read pointer in to REG_RXBD_RDPTR */ + if (mwifiex_write_reg(adapter, REG_RXBD_RDPTR, card->rxbd_rdptr | 0)) { dev_err(adapter->dev, - "RECV DATA: failed to write reg->rx_rdptr\n"); + "RECV DATA: failed to write REG_RXBD_RDPTR\n"); return -1; } return 0; @@ -1379,7 +1174,6 @@ static int mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; int ret = 0; dma_addr_t cmd_buf_pa, cmdrsp_buf_pa; u8 *payload = (u8 *)skb->data; @@ -1412,7 +1206,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) /* To send a command, the driver will: 1. Write the 64bit physical address of the data buffer to - cmd response address low + cmd response address high + SCRATCH1 + SCRATCH0 2. Ring the door bell (i.e. set the door bell interrupt) In response to door bell interrupt, the firmware will perform @@ -1424,7 +1218,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) MWIFIEX_SKB_PACB(card->cmdrsp_buf, &cmdrsp_buf_pa); /* Write the lower 32bits of the cmdrsp buffer physical address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, + if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, (u32)cmdrsp_buf_pa)) { dev_err(adapter->dev, "Failed to write download cmd to boot code.\n"); @@ -1433,7 +1227,7 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) } /* Write the upper 32bits of the cmdrsp buffer physical address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, + if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, (u32)((u64)cmdrsp_buf_pa >> 32))) { dev_err(adapter->dev, "Failed to write download cmd to boot code.\n"); @@ -1443,16 +1237,15 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) } MWIFIEX_SKB_PACB(card->cmd_buf, &cmd_buf_pa); - /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, - (u32)cmd_buf_pa)) { + /* Write the lower 32bits of the physical address to REG_CMD_ADDR_LO */ + if (mwifiex_write_reg(adapter, REG_CMD_ADDR_LO, (u32)cmd_buf_pa)) { dev_err(adapter->dev, "Failed to write download cmd to boot code.\n"); ret = -1; goto done; } - /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_hi, + /* Write the upper 32bits of the physical address to REG_CMD_ADDR_HI */ + if (mwifiex_write_reg(adapter, REG_CMD_ADDR_HI, (u32)((u64)cmd_buf_pa >> 32))) { dev_err(adapter->dev, "Failed to write download cmd to boot code.\n"); @@ -1460,11 +1253,10 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) goto done; } - /* Write the command length to reg->cmd_size */ - if (mwifiex_write_reg(adapter, reg->cmd_size, - card->cmd_buf->len)) { + /* Write the command length to REG_CMD_SIZE */ + if (mwifiex_write_reg(adapter, REG_CMD_SIZE, card->cmd_buf->len)) { dev_err(adapter->dev, - "Failed to write cmd len to reg->cmd_size\n"); + "Failed to write cmd len to REG_CMD_SIZE\n"); ret = -1; goto done; } @@ -1491,7 +1283,6 @@ mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; struct sk_buff *skb = card->cmdrsp_buf; int count = 0; u16 rx_len; @@ -1537,14 +1328,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) /* Clear the cmd-rsp buffer address in scratch registers. This will prevent firmware from writing to the same response buffer again. */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) { + if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_LO, 0)) { dev_err(adapter->dev, "cmd_done: failed to clear cmd_rsp_addr_lo\n"); return -1; } /* Write the upper 32bits of the cmdrsp buffer physical address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) { + if (mwifiex_write_reg(adapter, REG_CMDRSP_ADDR_HI, 0)) { dev_err(adapter->dev, "cmd_done: failed to clear cmd_rsp_addr_hi\n"); return -1; @@ -1589,11 +1380,9 @@ static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; u32 wrptr, event; dma_addr_t buf_pa; - struct mwifiex_evt_buf_desc *desc; if (!mwifiex_pcie_ok_to_access_hw(adapter)) mwifiex_pm_wakeup_card(adapter); @@ -1610,9 +1399,9 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) } /* Read the event ring write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) { + if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { dev_err(adapter->dev, - "EventReady: failed to read reg->evt_wrptr\n"); + "EventReady: failed to read REG_EVTBD_WRPTR\n"); return -1; } @@ -1620,8 +1409,8 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) card->evtbd_rdptr, wrptr); if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr & MWIFIEX_EVTBD_MASK)) || - ((wrptr & reg->evt_rollover_ind) == - (card->evtbd_rdptr & reg->evt_rollover_ind))) { + ((wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) == + (card->evtbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) { struct sk_buff *skb_cmd; __le16 data_len = 0; u16 evt_len; @@ -1635,8 +1424,9 @@ static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) /* Take the pointer and set it to event pointer in adapter and will return back after event handling callback */ card->evt_buf_list[rdptr] = NULL; - desc = card->evtbd_ring[rdptr]; - memset(desc, 0, sizeof(*desc)); + card->evtbd_ring[rdptr]->paddr = 0; + card->evtbd_ring[rdptr]->len = 0; + card->evtbd_ring[rdptr]->flags = 0; event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN]; adapter->event_cause = event; @@ -1672,12 +1462,10 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, struct sk_buff *skb) { struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; int ret = 0; u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; u32 wrptr; dma_addr_t buf_pa; - struct mwifiex_evt_buf_desc *desc; if (!skb) return 0; @@ -1689,9 +1477,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, } /* Read the event ring write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) { + if (mwifiex_read_reg(adapter, REG_EVTBD_WRPTR, &wrptr)) { dev_err(adapter->dev, - "event_complete: failed to read reg->evt_wrptr\n"); + "event_complete: failed to read REG_EVTBD_WRPTR\n"); return -1; } @@ -1704,10 +1492,9 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, MWIFIEX_SKB_PACB(skb, &buf_pa); card->evt_buf_list[rdptr] = skb; MWIFIEX_SKB_PACB(skb, &buf_pa); - desc = card->evtbd_ring[rdptr]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = 0; + card->evtbd_ring[rdptr]->paddr = buf_pa; + card->evtbd_ring[rdptr]->len = (u16)skb->len; + card->evtbd_ring[rdptr]->flags = 0; skb = NULL; } else { dev_dbg(adapter->dev, @@ -1717,18 +1504,17 @@ static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) { card->evtbd_rdptr = ((card->evtbd_rdptr & - reg->evt_rollover_ind) ^ - reg->evt_rollover_ind); + MWIFIEX_BD_FLAG_ROLLOVER_IND) ^ + MWIFIEX_BD_FLAG_ROLLOVER_IND); } dev_dbg(adapter->dev, "info: Updated ", card->evtbd_rdptr, wrptr); - /* Write the event ring read pointer in to reg->evt_rdptr */ - if (mwifiex_write_reg(adapter, reg->evt_rdptr, - card->evtbd_rdptr)) { + /* Write the event ring read pointer in to REG_EVTBD_RDPTR */ + if (mwifiex_write_reg(adapter, REG_EVTBD_RDPTR, card->evtbd_rdptr)) { dev_err(adapter->dev, - "event_complete: failed to read reg->evt_rdptr\n"); + "event_complete: failed to read REG_EVTBD_RDPTR\n"); return -1; } @@ -1757,7 +1543,6 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, u32 block_retry_cnt = 0; dma_addr_t buf_pa; struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; if (!firmware || !firmware_len) { dev_err(adapter->dev, @@ -1789,7 +1574,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, break; for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ret = mwifiex_read_reg(adapter, reg->cmd_size, + ret = mwifiex_read_reg(adapter, PCIE_SCRATCH_2_REG, &len); if (ret) { dev_warn(adapter->dev, @@ -1835,15 +1620,16 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, dev_dbg(adapter->dev, "."); - tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) / - card->pcie.blksz_fw_dl; + tx_blocks = (txlen + + MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD - 1) / + MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD; /* Copy payload to buffer */ memmove(skb->data, &firmware[offset], txlen); } skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len); - skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl); + skb_trim(skb, tx_blocks * MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD); /* Send the boot command to device */ if (mwifiex_pcie_send_boot_cmd(adapter, skb)) { @@ -1896,8 +1682,6 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) { int ret = 0; u32 firmware_stat, winner_status; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; u32 tries; /* Mask spurios interrupts */ @@ -1908,8 +1692,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) } dev_dbg(adapter->dev, "Setting driver ready signature\n"); - if (mwifiex_write_reg(adapter, reg->drv_rdy, - FIRMWARE_READY_PCIE)) { + if (mwifiex_write_reg(adapter, REG_DRV_READY, FIRMWARE_READY_PCIE)) { dev_err(adapter->dev, "Failed to write driver ready signature\n"); return -1; @@ -1917,7 +1700,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) /* Wait for firmware initialization event */ for (tries = 0; tries < poll_num; tries++) { - if (mwifiex_read_reg(adapter, reg->fw_status, + if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG, &firmware_stat)) ret = -1; else @@ -1934,7 +1717,7 @@ mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) } if (ret) { - if (mwifiex_read_reg(adapter, reg->fw_status, + if (mwifiex_read_reg(adapter, PCIE_SCRATCH_3_REG, &winner_status)) ret = -1; else if (!winner_status) { @@ -2278,11 +2061,10 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; struct pci_dev *pdev = card->dev; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; if (user_rmmod) { dev_dbg(adapter->dev, "Clearing driver ready signature\n"); - if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000)) + if (mwifiex_write_reg(adapter, REG_DRV_READY, 0x00000000)) dev_err(adapter->dev, "Failed to write driver not-ready signature\n"); } @@ -2320,7 +2102,7 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) } adapter->dev = &pdev->dev; - strcpy(adapter->fw_name, card->pcie.firmware); + strcpy(adapter->fw_name, PCIE8766_DEFAULT_FW_NAME); return 0; } @@ -2380,7 +2162,7 @@ static int mwifiex_pcie_init_module(void) { int ret; - pr_debug("Marvell PCIe Driver\n"); + pr_debug("Marvell 8766 PCIe Driver\n"); sema_init(&add_remove_card_sem, 1); @@ -2423,5 +2205,4 @@ MODULE_AUTHOR("Marvell International Ltd."); MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); MODULE_VERSION(PCIE_VERSION); MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME); -MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME); +MODULE_FIRMWARE("mrvl/pcie8766_uapsta.bin"); diff --git a/trunk/drivers/net/wireless/mwifiex/pcie.h b/trunk/drivers/net/wireless/mwifiex/pcie.h index 608061578b37..37eeb2ca6b29 100644 --- a/trunk/drivers/net/wireless/mwifiex/pcie.h +++ b/trunk/drivers/net/wireless/mwifiex/pcie.h @@ -29,11 +29,6 @@ #include "main.h" #define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" -#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin" - -#define PCIE_VENDOR_ID_MARVELL (0x11ab) -#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30) -#define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38) /* Constants for Buffer Descriptor (BD) rings */ #define MWIFIEX_MAX_TXRX_BD 0x20 @@ -62,8 +57,6 @@ #define PCIE_SCRATCH_10_REG 0xCE8 #define PCIE_SCRATCH_11_REG 0xCEC #define PCIE_SCRATCH_12_REG 0xCF0 -#define PCIE_RD_DATA_PTR_Q0_Q1 0xC08C -#define PCIE_WR_DATA_PTR_Q0_Q1 0xC05C #define CPU_INTR_DNLD_RDY BIT(0) #define CPU_INTR_DOOR_BELL BIT(1) @@ -82,14 +75,27 @@ #define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7) #define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0) #define MWIFIEX_BD_FLAG_LAST_DESC BIT(1) -#define MWIFIEX_BD_FLAG_SOP BIT(0) -#define MWIFIEX_BD_FLAG_EOP BIT(1) -#define MWIFIEX_BD_FLAG_XS_SOP BIT(2) -#define MWIFIEX_BD_FLAG_XS_EOP BIT(3) -#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND BIT(7) -#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND BIT(10) -#define MWIFIEX_BD_FLAG_TX_START_PTR BIT(16) -#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND BIT(26) +#define REG_CMD_ADDR_LO PCIE_SCRATCH_0_REG +#define REG_CMD_ADDR_HI PCIE_SCRATCH_1_REG +#define REG_CMD_SIZE PCIE_SCRATCH_2_REG + +#define REG_CMDRSP_ADDR_LO PCIE_SCRATCH_4_REG +#define REG_CMDRSP_ADDR_HI PCIE_SCRATCH_5_REG + +/* TX buffer description read pointer */ +#define REG_TXBD_RDPTR PCIE_SCRATCH_6_REG +/* TX buffer description write pointer */ +#define REG_TXBD_WRPTR PCIE_SCRATCH_7_REG +/* RX buffer description read pointer */ +#define REG_RXBD_RDPTR PCIE_SCRATCH_8_REG +/* RX buffer description write pointer */ +#define REG_RXBD_WRPTR PCIE_SCRATCH_9_REG +/* Event buffer description read pointer */ +#define REG_EVTBD_RDPTR PCIE_SCRATCH_10_REG +/* Event buffer description write pointer */ +#define REG_EVTBD_WRPTR PCIE_SCRATCH_11_REG +/* Driver ready signature write pointer */ +#define REG_DRV_READY PCIE_SCRATCH_12_REG /* Max retry number of command write */ #define MAX_WRITE_IOMEM_RETRY 2 @@ -98,139 +104,15 @@ /* FW awake cookie after FW ready */ #define FW_AWAKE_COOKIE (0xAA55AA55) -struct mwifiex_pcie_card_reg { - u16 cmd_addr_lo; - u16 cmd_addr_hi; - u16 fw_status; - u16 cmd_size; - u16 cmdrsp_addr_lo; - u16 cmdrsp_addr_hi; - u16 tx_rdptr; - u16 tx_wrptr; - u16 rx_rdptr; - u16 rx_wrptr; - u16 evt_rdptr; - u16 evt_wrptr; - u16 drv_rdy; - u16 tx_start_ptr; - u32 tx_mask; - u32 tx_wrap_mask; - u32 rx_mask; - u32 rx_wrap_mask; - u32 tx_rollover_ind; - u32 rx_rollover_ind; - u32 evt_rollover_ind; - u8 ring_flag_sop; - u8 ring_flag_eop; - u8 ring_flag_xs_sop; - u8 ring_flag_xs_eop; - u32 ring_tx_start_ptr; - u8 pfu_enabled; -}; - -static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { - .cmd_addr_lo = PCIE_SCRATCH_0_REG, - .cmd_addr_hi = PCIE_SCRATCH_1_REG, - .cmd_size = PCIE_SCRATCH_2_REG, - .fw_status = PCIE_SCRATCH_3_REG, - .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG, - .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG, - .tx_rdptr = PCIE_SCRATCH_6_REG, - .tx_wrptr = PCIE_SCRATCH_7_REG, - .rx_rdptr = PCIE_SCRATCH_8_REG, - .rx_wrptr = PCIE_SCRATCH_9_REG, - .evt_rdptr = PCIE_SCRATCH_10_REG, - .evt_wrptr = PCIE_SCRATCH_11_REG, - .drv_rdy = PCIE_SCRATCH_12_REG, - .tx_start_ptr = 0, - .tx_mask = MWIFIEX_TXBD_MASK, - .tx_wrap_mask = 0, - .rx_mask = MWIFIEX_RXBD_MASK, - .rx_wrap_mask = 0, - .tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .ring_flag_sop = 0, - .ring_flag_eop = 0, - .ring_flag_xs_sop = 0, - .ring_flag_xs_eop = 0, - .ring_tx_start_ptr = 0, - .pfu_enabled = 0, -}; - -static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { - .cmd_addr_lo = PCIE_SCRATCH_0_REG, - .cmd_addr_hi = PCIE_SCRATCH_1_REG, - .cmd_size = PCIE_SCRATCH_2_REG, - .fw_status = PCIE_SCRATCH_3_REG, - .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG, - .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG, - .tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1, - .tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1, - .rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1, - .rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1, - .evt_rdptr = PCIE_SCRATCH_10_REG, - .evt_wrptr = PCIE_SCRATCH_11_REG, - .drv_rdy = PCIE_SCRATCH_12_REG, - .tx_start_ptr = 16, - .tx_mask = 0x03FF0000, - .tx_wrap_mask = 0x07FF0000, - .rx_mask = 0x000003FF, - .rx_wrap_mask = 0x000007FF, - .tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND, - .rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND, - .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND, - .ring_flag_sop = MWIFIEX_BD_FLAG_SOP, - .ring_flag_eop = MWIFIEX_BD_FLAG_EOP, - .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP, - .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP, - .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, - .pfu_enabled = 1, -}; - -struct mwifiex_pcie_device { - const char *firmware; - const struct mwifiex_pcie_card_reg *reg; - u16 blksz_fw_dl; -}; - -static const struct mwifiex_pcie_device mwifiex_pcie8766 = { - .firmware = PCIE8766_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_8766, - .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, -}; - -static const struct mwifiex_pcie_device mwifiex_pcie8897 = { - .firmware = PCIE8897_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_8897, - .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, -}; - -struct mwifiex_evt_buf_desc { - u64 paddr; - u16 len; - u16 flags; -} __packed; - struct mwifiex_pcie_buf_desc { u64 paddr; u16 len; u16 flags; } __packed; -struct mwifiex_pfu_buf_desc { - u16 flags; - u16 offset; - u16 frag_len; - u16 len; - u64 paddr; - u32 reserved; -} __packed; - struct pcie_service_card { struct pci_dev *dev; struct mwifiex_adapter *adapter; - struct mwifiex_pcie_device pcie; u8 txbd_flush; u32 txbd_wrptr; @@ -238,7 +120,7 @@ struct pcie_service_card { u32 txbd_ring_size; u8 *txbd_ring_vbase; dma_addr_t txbd_ring_pbase; - void *txbd_ring[MWIFIEX_MAX_TXRX_BD]; + struct mwifiex_pcie_buf_desc *txbd_ring[MWIFIEX_MAX_TXRX_BD]; struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD]; u32 rxbd_wrptr; @@ -246,7 +128,7 @@ struct pcie_service_card { u32 rxbd_ring_size; u8 *rxbd_ring_vbase; dma_addr_t rxbd_ring_pbase; - void *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; + struct mwifiex_pcie_buf_desc *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD]; u32 evtbd_wrptr; @@ -254,7 +136,7 @@ struct pcie_service_card { u32 evtbd_ring_size; u8 *evtbd_ring_vbase; dma_addr_t evtbd_ring_pbase; - void *evtbd_ring[MWIFIEX_MAX_EVT_BD]; + struct mwifiex_pcie_buf_desc *evtbd_ring[MWIFIEX_MAX_EVT_BD]; struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD]; struct sk_buff *cmd_buf; @@ -268,24 +150,11 @@ struct pcie_service_card { static inline int mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr) { - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - if (((card->txbd_wrptr & reg->tx_mask) == - (rdptr & reg->tx_mask)) && - ((card->txbd_wrptr & reg->tx_rollover_ind) != - (rdptr & reg->tx_rollover_ind))) - return 1; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - if (((card->txbd_wrptr & reg->tx_mask) == - (rdptr & reg->tx_mask)) && - ((card->txbd_wrptr & reg->tx_rollover_ind) == - (rdptr & reg->tx_rollover_ind))) - return 1; - break; - } + if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) == + (rdptr & MWIFIEX_TXBD_MASK)) && + ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != + (rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) + return 1; return 0; } @@ -293,24 +162,11 @@ mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr) static inline int mwifiex_pcie_txbd_not_full(struct pcie_service_card *card) { - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - if (((card->txbd_wrptr & reg->tx_mask) != - (card->txbd_rdptr & reg->tx_mask)) || - ((card->txbd_wrptr & reg->tx_rollover_ind) != - (card->txbd_rdptr & reg->tx_rollover_ind))) - return 1; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - if (((card->txbd_wrptr & reg->tx_mask) != - (card->txbd_rdptr & reg->tx_mask)) || - ((card->txbd_wrptr & reg->tx_rollover_ind) == - (card->txbd_rdptr & reg->tx_rollover_ind))) - return 1; - break; - } + if (((card->txbd_wrptr & MWIFIEX_TXBD_MASK) != + (card->txbd_rdptr & MWIFIEX_TXBD_MASK)) || + ((card->txbd_wrptr & MWIFIEX_BD_FLAG_ROLLOVER_IND) != + (card->txbd_rdptr & MWIFIEX_BD_FLAG_ROLLOVER_IND))) + return 1; return 0; } diff --git a/trunk/drivers/net/wireless/mwifiex/scan.c b/trunk/drivers/net/wireless/mwifiex/scan.c index 232492487527..9189a32b7844 100644 --- a/trunk/drivers/net/wireless/mwifiex/scan.c +++ b/trunk/drivers/net/wireless/mwifiex/scan.c @@ -1746,7 +1746,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, .mac_address, ETH_ALEN)) mwifiex_update_curr_bss_params(priv, bss); - cfg80211_put_bss(priv->wdev->wiphy, bss); + cfg80211_put_bss(bss); } } else { dev_dbg(adapter->dev, "missing BSS channel IE\n"); diff --git a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c index 847056415ac9..65c12eb3e5e7 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -935,8 +935,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, / MWIFIEX_SDIO_BLOCK_SIZE) * MWIFIEX_SDIO_BLOCK_SIZE; adapter->curr_tx_buf_size = adapter->tx_buf_size; - dev_dbg(adapter->dev, "cmd: curr_tx_buf_size=%d\n", - adapter->curr_tx_buf_size); + dev_dbg(adapter->dev, + "cmd: max_tx_buf_size=%d, tx_buf_size=%d\n", + adapter->max_tx_buf_size, adapter->tx_buf_size); if (adapter->if_ops.update_mp_end_port) adapter->if_ops.update_mp_end_port(adapter, diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index 0d018460daf9..f542bb8ccbc8 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -162,9 +162,13 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, rcu_read_lock(); ies = rcu_dereference(bss->ies); + if (WARN_ON(!ies)) { + /* should never happen */ + rcu_read_unlock(); + return -EINVAL; + } beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); beacon_ie_len = ies->len; - bss_desc->timestamp = ies->tsf; rcu_read_unlock(); if (!beacon_ie) { @@ -180,6 +184,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, bss_desc->cap_info_bitmap = bss->capability; bss_desc->bss_band = bss_priv->band; bss_desc->fw_tsf = bss_priv->fw_tsf; + bss_desc->timestamp = bss->tsf; if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n"); bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; @@ -319,7 +324,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, } if (bss) - cfg80211_put_bss(priv->adapter->wiphy, bss); + cfg80211_put_bss(bss); } else { /* Adhoc mode */ /* If the requested SSID matches current SSID, return */ @@ -349,7 +354,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, " list. Joining...\n"); ret = mwifiex_adhoc_join(priv, bss_desc); if (bss) - cfg80211_put_bss(priv->adapter->wiphy, bss); + cfg80211_put_bss(bss); } else { dev_dbg(adapter->dev, "info: Network not found in " "the list, creating adhoc with ssid = %s\n", diff --git a/trunk/drivers/net/wireless/mwifiex/util.c b/trunk/drivers/net/wireless/mwifiex/util.c index 21553976b550..0982375ba3b1 100644 --- a/trunk/drivers/net/wireless/mwifiex/util.c +++ b/trunk/drivers/net/wireless/mwifiex/util.c @@ -91,7 +91,7 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, memcpy(info->packets_out, priv->wmm.packets_out, sizeof(priv->wmm.packets_out)); - info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size; + info->max_tx_buf_size = (u32) adapter->max_tx_buf_size; info->tx_buf_size = (u32) adapter->tx_buf_size; info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv, info->rx_tbl); diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index 8186af4ed47b..2031130d860b 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -1149,6 +1149,7 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL); if (rxq->buf == NULL) { + wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n"); pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma); return -ENOMEM; } @@ -1441,6 +1442,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL); if (txq->skb == NULL) { + wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n"); pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma); return -ENOMEM; } @@ -5471,8 +5473,6 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = { { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, }, { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, }, - { PCI_VDEVICE(MARVELL, 0x2a41), .driver_data = MWL8366, }, - { PCI_VDEVICE(MARVELL, 0x2a42), .driver_data = MWL8366, }, { PCI_VDEVICE(MARVELL, 0x2a43), .driver_data = MWL8366, }, { }, }; diff --git a/trunk/drivers/net/wireless/orinoco/scan.c b/trunk/drivers/net/wireless/orinoco/scan.c index e8c5714bfd11..96e39edfec77 100644 --- a/trunk/drivers/net/wireless/orinoco/scan.c +++ b/trunk/drivers/net/wireless/orinoco/scan.c @@ -125,7 +125,7 @@ static void orinoco_add_hostscan_result(struct orinoco_private *priv, cbss = cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, capability, beacon_interval, ie_buf, ie_len, signal, GFP_KERNEL); - cfg80211_put_bss(wiphy, cbss); + cfg80211_put_bss(cbss); } void orinoco_add_extscan_result(struct orinoco_private *priv, @@ -158,7 +158,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv, cbss = cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, capability, beacon_interval, ie, ie_len, signal, GFP_KERNEL); - cfg80211_put_bss(wiphy, cbss); + cfg80211_put_bss(cbss); } void orinoco_add_hostscan_results(struct orinoco_private *priv, diff --git a/trunk/drivers/net/wireless/p54/p54usb.c b/trunk/drivers/net/wireless/p54/p54usb.c index 1f7858588919..800a16526c8e 100644 --- a/trunk/drivers/net/wireless/p54/p54usb.c +++ b/trunk/drivers/net/wireless/p54/p54usb.c @@ -84,8 +84,8 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ + {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ - {USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ diff --git a/trunk/drivers/net/wireless/rndis_wlan.c b/trunk/drivers/net/wireless/rndis_wlan.c index fe2f272689aa..abe1d039be81 100644 --- a/trunk/drivers/net/wireless/rndis_wlan.c +++ b/trunk/drivers/net/wireless/rndis_wlan.c @@ -2029,7 +2029,7 @@ static bool rndis_bss_info_update(struct usbnet *usbdev, bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, timestamp, capability, beacon_interval, ie, ie_len, signal, GFP_KERNEL); - cfg80211_put_bss(priv->wdev.wiphy, bss); + cfg80211_put_bss(bss); return (bss != NULL); } @@ -2718,7 +2718,7 @@ static void rndis_wlan_craft_connected_bss(struct usbnet *usbdev, u8 *bssid, bss = cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid, timestamp, capability, beacon_period, ie_buf, ie_len, signal, GFP_KERNEL); - cfg80211_put_bss(priv->wdev.wiphy, bss); + cfg80211_put_bss(bss); } /* diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c index 48a01aa21f1c..0e8d1705e368 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1152,7 +1152,6 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { { PCI_DEVICE(0x1814, 0x3562) }, { PCI_DEVICE(0x1814, 0x3592) }, { PCI_DEVICE(0x1814, 0x3593) }, - { PCI_DEVICE(0x1814, 0x359f) }, #endif #ifdef CONFIG_RT2800PCI_RT53XX { PCI_DEVICE(0x1814, 0x5360) }, diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c index 098613ed93fb..d6863289471b 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800usb.c @@ -968,7 +968,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c13) }, { USB_DEVICE(0x07d1, 0x3c15) }, { USB_DEVICE(0x07d1, 0x3c16) }, - { USB_DEVICE(0x07d1, 0x3c17) }, { USB_DEVICE(0x2001, 0x3c1b) }, /* Draytek */ { USB_DEVICE(0x07fa, 0x7712) }, @@ -1099,11 +1098,9 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x15a9, 0x0006) }, /* Sweex */ { USB_DEVICE(0x177f, 0x0153) }, - { USB_DEVICE(0x177f, 0x0164) }, { USB_DEVICE(0x177f, 0x0302) }, { USB_DEVICE(0x177f, 0x0313) }, { USB_DEVICE(0x177f, 0x0323) }, - { USB_DEVICE(0x177f, 0x0324) }, /* U-Media */ { USB_DEVICE(0x157e, 0x300e) }, { USB_DEVICE(0x157e, 0x3013) }, @@ -1118,7 +1115,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Zyxel */ { USB_DEVICE(0x0586, 0x3416) }, { USB_DEVICE(0x0586, 0x3418) }, - { USB_DEVICE(0x0586, 0x341a) }, { USB_DEVICE(0x0586, 0x341e) }, { USB_DEVICE(0x0586, 0x343e) }, #ifdef CONFIG_RT2800USB_RT33XX @@ -1135,9 +1131,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x148f, 0x8070) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0050) }, - /* Sweex */ - { USB_DEVICE(0x177f, 0x0163) }, - { USB_DEVICE(0x177f, 0x0165) }, #endif #ifdef CONFIG_RT2800USB_RT35XX /* Allwin */ @@ -1173,7 +1166,6 @@ static struct usb_device_id rt2800usb_device_table[] = { #ifdef CONFIG_RT2800USB_RT53XX /* Arcadyan */ { USB_DEVICE(0x043e, 0x7a12) }, - { USB_DEVICE(0x043e, 0x7a32) }, /* Azurewave */ { USB_DEVICE(0x13d3, 0x3329) }, { USB_DEVICE(0x13d3, 0x3365) }, @@ -1185,20 +1177,16 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x2001, 0x3c1e) }, /* LG innotek */ { USB_DEVICE(0x043e, 0x7a22) }, - { USB_DEVICE(0x043e, 0x7a42) }, /* Panasonic */ { USB_DEVICE(0x04da, 0x1801) }, { USB_DEVICE(0x04da, 0x1800) }, - { USB_DEVICE(0x04da, 0x23f6) }, /* Philips */ { USB_DEVICE(0x0471, 0x2104) }, - { USB_DEVICE(0x0471, 0x2126) }, - { USB_DEVICE(0x0471, 0x2180) }, - { USB_DEVICE(0x0471, 0x2181) }, - { USB_DEVICE(0x0471, 0x2182) }, /* Ralink */ { USB_DEVICE(0x148f, 0x5370) }, { USB_DEVICE(0x148f, 0x5372) }, + /* Unknown */ + { USB_DEVICE(0x04da, 0x23f6) }, #endif #ifdef CONFIG_RT2800USB_UNKNOWN /* @@ -1219,15 +1207,10 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x17a7) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, { USB_DEVICE(0x13d3, 0x3322) }, - { USB_DEVICE(0x13d3, 0x3340) }, - { USB_DEVICE(0x13d3, 0x3399) }, - { USB_DEVICE(0x13d3, 0x3400) }, - { USB_DEVICE(0x13d3, 0x3401) }, /* Belkin */ { USB_DEVICE(0x050d, 0x1003) }, /* Buffalo */ @@ -1240,17 +1223,13 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x18c5, 0x0008) }, /* D-Link */ { USB_DEVICE(0x07d1, 0x3c0b) }, + { USB_DEVICE(0x07d1, 0x3c17) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, - /* EnGenius */ - { USB_DEVICE(0x1740, 0x0600) }, - { USB_DEVICE(0x1740, 0x0602) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010) }, /* Gigabyte */ { USB_DEVICE(0x1044, 0x800c) }, - /* Hercules */ - { USB_DEVICE(0x06f8, 0xe036) }, /* Huawei */ { USB_DEVICE(0x148f, 0xf101) }, /* I-O DATA */ @@ -1277,17 +1256,13 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0df6, 0x004a) }, { USB_DEVICE(0x0df6, 0x004d) }, { USB_DEVICE(0x0df6, 0x0053) }, - { USB_DEVICE(0x0df6, 0x0069) }, - { USB_DEVICE(0x0df6, 0x006f) }, /* SMC */ { USB_DEVICE(0x083a, 0xa512) }, { USB_DEVICE(0x083a, 0xc522) }, { USB_DEVICE(0x083a, 0xd522) }, { USB_DEVICE(0x083a, 0xf511) }, - /* Sweex */ - { USB_DEVICE(0x177f, 0x0254) }, - /* TP-LINK */ - { USB_DEVICE(0xf201, 0x5370) }, + /* Zyxel */ + { USB_DEVICE(0x0586, 0x341a) }, #endif { 0, } }; diff --git a/trunk/drivers/net/wireless/rtlwifi/rc.c b/trunk/drivers/net/wireless/rtlwifi/rc.c index 6ad8bb758961..204f46c4510d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rc.c +++ b/trunk/drivers/net/wireless/rtlwifi/rc.c @@ -217,12 +217,6 @@ static void rtl_tx_status(void *ppriv, } } -static void rtl_rate_init(void *ppriv, - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ -} - static void *rtl_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { @@ -267,7 +261,6 @@ static struct rate_control_ops rtl_rate_ops = { .free = rtl_rate_free, .alloc_sta = rtl_rate_alloc_sta, .free_sta = rtl_rate_free_sta, - .rate_init = rtl_rate_init, .tx_status = rtl_tx_status, .get_rate = rtl_get_rate, }; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c index b793a659a465..1cdf5a271c9f 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c @@ -669,8 +669,7 @@ static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw u8 thermalvalue, delta, delta_lck, delta_iqk; long ele_a, ele_d, temp_cck, val_x, value32; long val_y, ele_c = 0; - u8 ofdm_index[2], ofdm_index_old[2], cck_index_old = 0; - s8 cck_index = 0; + u8 ofdm_index[2], cck_index = 0, ofdm_index_old[2], cck_index_old = 0; int i; bool is2t = IS_92C_SERIAL(rtlhal->version); s8 txpwr_level[2] = {0, 0}; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index da0e9022a99a..c31795e379f7 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -488,7 +488,7 @@ static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw, u8 *praddr; __le16 fc; u16 type, c_fc; - bool packet_matchbssid, packet_toself, packet_beacon = false; + bool packet_matchbssid, packet_toself, packet_beacon; tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 85b6bdb163c0..32ff959a0251 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -1084,7 +1084,7 @@ void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw, u8 *praddr; __le16 fc; u16 type, cpu_fc; - bool packet_matchbssid, packet_toself, packet_beacon = false; + bool packet_matchbssid, packet_toself, packet_beacon; tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; hdr = (struct ieee80211_hdr *)tmp_buf; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index a73a17bc56dd..b7e6607e6b6d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -76,7 +76,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw) GFP_KERNEL, hw, rtl_fw_cb); - return err; + return 0; } static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) @@ -285,7 +285,6 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, /* RTL8188CUS-VL */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, - {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, /* 8188 Combo for BC4 */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, @@ -364,15 +363,9 @@ static struct usb_device_id rtl8192c_usb_ids[] = { MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids); -static int rtl8192cu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg); -} - static struct usb_driver rtl8192cu_driver = { .name = "rtl8192cu", - .probe = rtl8192cu_probe, + .probe = rtl_usb_probe, .disconnect = rtl_usb_disconnect, .id_table = rtl8192c_usb_ids, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/dm.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/dm.c index 5251fb8a111e..fd8df233ff22 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/dm.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/dm.c @@ -841,9 +841,9 @@ static void rtl92d_dm_txpower_tracking_callback_thermalmeter( long ele_a = 0, ele_d, temp_cck, val_x, value32; long val_y, ele_c = 0; u8 ofdm_index[2]; - s8 cck_index = 0; + u8 cck_index = 0; u8 ofdm_index_old[2]; - s8 cck_index_old = 0; + u8 cck_index_old = 0; u8 index; int i; bool is2t = IS_92D_SINGLEPHY(rtlhal->version); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c index 35cb8f83eed4..3b71dab4f3b2 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/fw.c @@ -512,6 +512,7 @@ static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw, struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl8192_tx_ring *ring; struct rtl_tx_desc *pdesc; + u8 own; unsigned long flags; struct sk_buff *pskb = NULL; @@ -524,6 +525,7 @@ static bool _rtl8723ae_cmd_send_packet(struct ieee80211_hw *hw, spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); pdesc = &ring->desc[0]; + own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN); rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c index 68c28340f791..887d521fe690 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hal_btc.c @@ -1433,6 +1433,7 @@ static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); + u8 bt_retry_cnt; u8 bt_info_original; RT_TRACE(rtlpriv, COMP_BT_COEXIST, DBG_DMESG, "[BTCoex] Get bt info by fw!!\n"); @@ -1444,6 +1445,7 @@ static void _rtl8723ae_dm_bt_coexist_2_ant(struct ieee80211_hw *hw) "[BTCoex] c2h for btInfo not rcvd yet!!\n"); } + bt_retry_cnt = rtlhal->hal_coex_8723.bt_retry_cnt; bt_info_original = rtlhal->hal_coex_8723.c2h_bt_info_original; /* when bt inquiry or page scan, we have to set h2c 0x25 diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c index 149804816ac4..0a8c03863fb2 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c @@ -703,9 +703,11 @@ static void _rtl8723ae_hw_configure(struct ieee80211_hw *hw) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); u8 reg_bw_opmode; - u32 reg_prsr; + u32 reg_ratr, reg_prsr; reg_bw_opmode = BW_OPMODE_20MHZ; + reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | + RATE_ALL_OFDM_1SS | RATE_ALL_OFDM_2SS; reg_prsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL, 0x8); @@ -2028,7 +2030,7 @@ bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); struct rtl_phy *rtlphy = &(rtlpriv->phy); - enum rf_pwrstate e_rfpowerstate_toset; + enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate; u8 u1tmp; bool actuallyset = false; @@ -2047,6 +2049,8 @@ bool rtl8723ae_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) spin_unlock(&rtlpriv->locks.rf_ps_lock); } + cur_rfstate = ppsc->rfpwr_state; + rtl_write_byte(rtlpriv, REG_GPIO_IO_SEL_2, rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL_2)&~(BIT(1))); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index eafbb18dd48e..3d8536bb0d2b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c @@ -614,11 +614,17 @@ bool rtl8723ae_phy_config_rf_with_headerfile(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); int i; + bool rtstatus = true; u32 *radioa_array_table; - u16 radioa_arraylen; + u32 *radiob_array_table; + u16 radioa_arraylen, radiob_arraylen; radioa_arraylen = Rtl8723ERADIOA_1TARRAYLENGTH; radioa_array_table = RTL8723E_RADIOA_1TARRAY; + radiob_arraylen = RTL8723E_RADIOB_1TARRAYLENGTH; + radiob_array_table = RTL8723E_RADIOB_1TARRAY; + + rtstatus = true; switch (rfpath) { case RF90_PATH_A: @@ -1525,8 +1531,11 @@ static void _rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, 0x522, 0x550, 0x551, 0x040 }; const u32 retrycount = 2; + u32 bbvalue; if (t == 0) { + bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD); + phy_save_adda_regs(hw, adda_reg, rtlphy->adda_backup, 16); phy_save_mac_regs(hw, iqk_mac_reg, rtlphy->iqk_mac_backup); } @@ -1703,7 +1712,8 @@ void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery) long result[4][8]; u8 i, final_candidate; bool patha_ok, pathb_ok; - long reg_e94, reg_e9c, reg_ea4, reg_eb4, reg_ebc, reg_tmp = 0; + long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, + reg_ecc, reg_tmp = 0; bool is12simular, is13simular, is23simular; bool start_conttx = false, singletone = false; u32 iqk_bb_reg[10] = { @@ -1770,15 +1780,21 @@ void rtl8723ae_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery) reg_e94 = result[i][0]; reg_e9c = result[i][1]; reg_ea4 = result[i][2]; + reg_eac = result[i][3]; reg_eb4 = result[i][4]; reg_ebc = result[i][5]; + reg_ec4 = result[i][6]; + reg_ecc = result[i][7]; } if (final_candidate != 0xff) { rtlphy->reg_e94 = reg_e94 = result[final_candidate][0]; rtlphy->reg_e9c = reg_e9c = result[final_candidate][1]; reg_ea4 = result[final_candidate][2]; + reg_eac = result[final_candidate][3]; rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4]; rtlphy->reg_ebc = reg_ebc = result[final_candidate][5]; + reg_ec4 = result[final_candidate][6]; + reg_ecc = result[final_candidate][7]; patha_ok = pathb_ok = true; } else { rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index b1fd2b328abf..ce8ad12bce5b 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c @@ -244,6 +244,7 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr; u8 *tmp_buf; u8 *praddr; + u8 *psaddr; __le16 fc; u16 type; bool packet_matchbssid, packet_toself, packet_beacon = false; @@ -254,6 +255,7 @@ static void _rtl8723ae_translate_rx_signal_stuff(struct ieee80211_hw *hw, fc = hdr->frame_control; type = WLAN_FC_GET_TYPE(fc); praddr = hdr->addr1; + psaddr = ieee80211_get_SA(hdr); packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && (!compare_ether_addr(mac->bssid, diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.c b/trunk/drivers/net/wireless/rtlwifi/usb.c index 80730c72e0d6..f2ecdeb3a90d 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.c +++ b/trunk/drivers/net/wireless/rtlwifi/usb.c @@ -825,6 +825,8 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, u32 ep_num; struct urb *_urb = NULL; struct sk_buff *_skb = NULL; + struct sk_buff_head *skb_list; + struct usb_anchor *urb_list; WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl); if (unlikely(IS_USB_STOP(rtlusb))) { @@ -834,6 +836,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, return; } ep_num = rtlusb->ep_map.ep_mapping[qnum]; + skb_list = &rtlusb->tx_skb_queue[ep_num]; _skb = skb; _urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num); if (unlikely(!_urb)) { @@ -841,6 +844,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, "Can't allocate urb. Drop skb!\n"); return; } + urb_list = &rtlusb->tx_pending[ep_num]; _rtl_submit_tx_urb(hw, _urb); } @@ -937,8 +941,7 @@ static struct rtl_intf_ops rtl_usb_ops = { }; int rtl_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id, - struct rtl_hal_cfg *rtl_hal_cfg) + const struct usb_device_id *id) { int err; struct ieee80211_hw *hw = NULL; @@ -973,7 +976,7 @@ int rtl_usb_probe(struct usb_interface *intf, usb_set_intfdata(intf, hw); /* init cfg & intf_ops */ rtlpriv->rtlhal.interface = INTF_USB; - rtlpriv->cfg = rtl_hal_cfg; + rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info); rtlpriv->intf_ops = &rtl_usb_ops; rtl_dbgp_flag_init(hw); /* Init IO handler */ diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.h b/trunk/drivers/net/wireless/rtlwifi/usb.h index fb986f98d1df..5235136f6dd2 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.h +++ b/trunk/drivers/net/wireless/rtlwifi/usb.h @@ -157,8 +157,7 @@ struct rtl_usb_priv { int rtl_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id, - struct rtl_hal_cfg *rtl92cu_hal_cfg); + const struct usb_device_id *id); void rtl_usb_disconnect(struct usb_interface *intf); int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); int rtl_usb_resume(struct usb_interface *pusb_intf); diff --git a/trunk/drivers/net/wireless/rtlwifi/wifi.h b/trunk/drivers/net/wireless/rtlwifi/wifi.h index f13258a8d995..21a5f4f4a135 100644 --- a/trunk/drivers/net/wireless/rtlwifi/wifi.h +++ b/trunk/drivers/net/wireless/rtlwifi/wifi.h @@ -1702,7 +1702,7 @@ struct rtl_works { struct rtl_debug { u32 dbgp_type[DBGP_TYPE_MAX]; - int global_debuglevel; + u32 global_debuglevel; u64 global_debugcomponents; /* add for proc debug */ diff --git a/trunk/drivers/net/wireless/ti/Kconfig b/trunk/drivers/net/wireless/ti/Kconfig index cbe1e7fef61b..be800119d0a3 100644 --- a/trunk/drivers/net/wireless/ti/Kconfig +++ b/trunk/drivers/net/wireless/ti/Kconfig @@ -12,13 +12,4 @@ source "drivers/net/wireless/ti/wl18xx/Kconfig" # keep last for automatic dependencies source "drivers/net/wireless/ti/wlcore/Kconfig" - -config WILINK_PLATFORM_DATA - bool "TI WiLink platform data" - depends on WLCORE_SDIO || WL1251_SDIO - default y - ---help--- - Small platform data bit needed to pass data to the sdio modules. - - endif # WL_TI diff --git a/trunk/drivers/net/wireless/ti/Makefile b/trunk/drivers/net/wireless/ti/Makefile index af14231aeede..4d6823983c04 100644 --- a/trunk/drivers/net/wireless/ti/Makefile +++ b/trunk/drivers/net/wireless/ti/Makefile @@ -1,7 +1,5 @@ obj-$(CONFIG_WLCORE) += wlcore/ obj-$(CONFIG_WL12XX) += wl12xx/ +obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wlcore/ obj-$(CONFIG_WL1251) += wl1251/ obj-$(CONFIG_WL18XX) += wl18xx/ - -# small builtin driver bit -obj-$(CONFIG_WILINK_PLATFORM_DATA) += wilink_platform_data.o diff --git a/trunk/drivers/net/wireless/ti/wl1251/event.c b/trunk/drivers/net/wireless/ti/wl1251/event.c index 74ae8e1c2e33..5ec50a476a69 100644 --- a/trunk/drivers/net/wireless/ti/wl1251/event.c +++ b/trunk/drivers/net/wireless/ti/wl1251/event.c @@ -29,8 +29,6 @@ static int wl1251_event_scan_complete(struct wl1251 *wl, struct event_mailbox *mbox) { - int ret = 0; - wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", mbox->scheduled_scan_status, mbox->scheduled_scan_channels); @@ -39,11 +37,9 @@ static int wl1251_event_scan_complete(struct wl1251 *wl, ieee80211_scan_completed(wl->hw, false); wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); wl->scanning = false; - if (wl->hw->conf.flags & IEEE80211_CONF_IDLE) - ret = wl1251_ps_set_mode(wl, STATION_IDLE); } - return ret; + return 0; } static void wl1251_event_mbox_dump(struct event_mailbox *mbox) diff --git a/trunk/drivers/net/wireless/ti/wl1251/main.c b/trunk/drivers/net/wireless/ti/wl1251/main.c index bbbf68cf50a7..f47e8b0482ad 100644 --- a/trunk/drivers/net/wireless/ti/wl1251/main.c +++ b/trunk/drivers/net/wireless/ti/wl1251/main.c @@ -623,7 +623,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) } } - if (changed & IEEE80211_CONF_CHANGE_IDLE && !wl->scanning) { + if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (conf->flags & IEEE80211_CONF_IDLE) { ret = wl1251_ps_set_mode(wl, STATION_IDLE); if (ret < 0) @@ -895,21 +895,11 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, if (ret < 0) goto out; - if (hw->conf.flags & IEEE80211_CONF_IDLE) { - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - goto out_sleep; - ret = wl1251_join(wl, wl->bss_type, wl->channel, - wl->beacon_int, wl->dtim_period); - if (ret < 0) - goto out_sleep; - } - skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, req->ie_len); if (!skb) { ret = -ENOMEM; - goto out_idle; + goto out; } if (req->ie_len) memcpy(skb_put(skb, req->ie_len), req->ie, req->ie_len); @@ -918,11 +908,11 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, skb->len); dev_kfree_skb(skb); if (ret < 0) - goto out_idle; + goto out_sleep; ret = wl1251_cmd_trigger_scan_to(wl, 0); if (ret < 0) - goto out_idle; + goto out_sleep; wl->scanning = true; @@ -930,13 +920,9 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, req->n_channels, WL1251_SCAN_NUM_PROBES); if (ret < 0) { wl->scanning = false; - goto out_idle; + goto out_sleep; } - goto out_sleep; -out_idle: - if (hw->conf.flags & IEEE80211_CONF_IDLE) - ret = wl1251_ps_set_mode(wl, STATION_IDLE); out_sleep: wl1251_ps_elp_sleep(wl); diff --git a/trunk/drivers/net/wireless/ti/wl12xx/main.c b/trunk/drivers/net/wireless/ti/wl12xx/main.c index 09694e39bb14..3254bfc81a2a 100644 --- a/trunk/drivers/net/wireless/ti/wl12xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl12xx/main.c @@ -1703,8 +1703,7 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { static int wl12xx_setup(struct wl1271 *wl) { struct wl12xx_priv *priv = wl->priv; - struct wlcore_platdev_data *pdev_data = wl->pdev->dev.platform_data; - struct wl12xx_platform_data *pdata = pdev_data->pdata; + struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data; wl->rtable = wl12xx_rtable; wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; diff --git a/trunk/drivers/net/wireless/ti/wl18xx/conf.h b/trunk/drivers/net/wireless/ti/wl18xx/conf.h index e34302e3b51d..b5f114857191 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/conf.h +++ b/trunk/drivers/net/wireless/ti/wl18xx/conf.h @@ -23,7 +23,7 @@ #define __WL18XX_CONF_H__ #define WL18XX_CONF_MAGIC 0x10e100ca -#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0006) +#define WL18XX_CONF_VERSION (WLCORE_CONF_VERSION | 0x0005) #define WL18XX_CONF_MASK 0x0000ffff #define WL18XX_CONF_SIZE (WLCORE_CONF_SIZE + \ sizeof(struct wl18xx_priv_conf)) @@ -70,9 +70,8 @@ struct wl18xx_mac_and_phy_params { u8 pwr_limit_reference_11_abg; u8 per_chan_pwr_limit_arr_11p[NUM_OF_CHANNELS_11_P]; u8 pwr_limit_reference_11p; - u8 spare1; - u8 per_chan_bo_mode_11_abg[13]; - u8 per_chan_bo_mode_11_p[4]; + u8 spare1[9]; + u8 spare2[9]; u8 primary_clock_setting_time; u8 clock_valid_on_wake_up; u8 secondary_clock_setting_time; diff --git a/trunk/drivers/net/wireless/ti/wl18xx/main.c b/trunk/drivers/net/wireless/ti/wl18xx/main.c index a10b7a7a215a..0be1cfc17a86 100644 --- a/trunk/drivers/net/wireless/ti/wl18xx/main.c +++ b/trunk/drivers/net/wireless/ti/wl18xx/main.c @@ -547,11 +547,6 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .pwr_limit_reference_11p = 0x64, - .per_chan_bo_mode_11_abg = { 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00 }, - .per_chan_bo_mode_11_p = { 0x00, 0x00, 0x00, 0x00 }, .per_chan_pwr_limit_arr_11p = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, .psat = 0, diff --git a/trunk/drivers/net/wireless/ti/wlcore/Kconfig b/trunk/drivers/net/wireless/ti/wlcore/Kconfig index 2b832825c3d4..d7b907e67170 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/Kconfig +++ b/trunk/drivers/net/wireless/ti/wlcore/Kconfig @@ -33,3 +33,8 @@ config WLCORE_SDIO If you choose to build a module, it'll be called wlcore_sdio. Say N if unsure. + +config WL12XX_PLATFORM_DATA + bool + depends on WLCORE_SDIO != n || WL1251_SDIO != n + default y diff --git a/trunk/drivers/net/wireless/ti/wlcore/Makefile b/trunk/drivers/net/wireless/ti/wlcore/Makefile index b21398f6c3ec..d9fba9e32130 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/Makefile +++ b/trunk/drivers/net/wireless/ti/wlcore/Makefile @@ -9,4 +9,7 @@ obj-$(CONFIG_WLCORE) += wlcore.o obj-$(CONFIG_WLCORE_SPI) += wlcore_spi.o obj-$(CONFIG_WLCORE_SDIO) += wlcore_sdio.o +# small builtin driver bit +obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o + ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/ti/wlcore/boot.c b/trunk/drivers/net/wireless/ti/wlcore/boot.c index 77752b03f189..b58ae5fc1487 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/boot.c +++ b/trunk/drivers/net/wireless/ti/wlcore/boot.c @@ -84,8 +84,8 @@ static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, static int wlcore_validate_fw_ver(struct wl1271 *wl) { unsigned int *fw_ver = wl->chip.fw_ver; - unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_MULTI) ? - wl->min_mr_fw_ver : wl->min_sr_fw_ver; + unsigned int *min_ver = (wl->fw_type == WL12XX_FW_TYPE_NORMAL) ? + wl->min_sr_fw_ver : wl->min_mr_fw_ver; char min_fw_str[32] = ""; int i; diff --git a/trunk/drivers/net/wireless/ti/wlcore/cmd.c b/trunk/drivers/net/wireless/ti/wlcore/cmd.c index 6331f9e1cb39..1201aca9c89a 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/cmd.c +++ b/trunk/drivers/net/wireless/ti/wlcore/cmd.c @@ -510,12 +510,10 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->sta.hlid = wlvif->sta.hlid; cmd->sta.session = wl->session_ids[wlvif->sta.hlid]; /* - * We don't have the correct remote rates in this stage. The - * rates will be reconfigured later, after association, if the - * firmware supports ACX_PEER_CAP. Otherwise, there's nothing - * we can do, so use all supported_rates here. + * We don't have the correct remote rates in this stage. the rates + * will be reconfigured later, after authorization. */ - cmd->sta.remote_rates = cpu_to_le32(supported_rates); + cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set); wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " "basic_rate_set: 0x%x, remote_rates: 0x%x", diff --git a/trunk/drivers/net/wireless/ti/wlcore/main.c b/trunk/drivers/net/wireless/ti/wlcore/main.c index 2c2ff3e1f849..e1dfdf94d0f7 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/main.c +++ b/trunk/drivers/net/wireless/ti/wlcore/main.c @@ -2162,7 +2162,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) return 0; } -static int wl12xx_init_fw(struct wl1271 *wl) +static bool wl12xx_init_fw(struct wl1271 *wl) { int retries = WL1271_BOOT_RETRIES; bool booted = false; @@ -2228,7 +2228,7 @@ static int wl12xx_init_fw(struct wl1271 *wl) wl->state = WLCORE_STATE_ON; out: - return ret; + return booted; } static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif) @@ -2371,6 +2371,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct vif_counter_data vif_count; int ret = 0; u8 role_type; + bool booted = false; vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER | IEEE80211_VIF_SUPPORTS_CQM_RSSI; @@ -2431,9 +2432,11 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, */ memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN); - ret = wl12xx_init_fw(wl); - if (ret < 0) + booted = wl12xx_init_fw(wl); + if (!booted) { + ret = -EINVAL; goto out; + } } ret = wl12xx_cmd_role_enable(wl, vif->addr, @@ -5636,6 +5639,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_AP_LINK_PS | IEEE80211_HW_AMPDU_AGGREGATION | IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | + IEEE80211_HW_SCAN_WHILE_IDLE | IEEE80211_HW_QUEUE_CONTROL; wl->hw->wiphy->cipher_suites = cipher_suites; @@ -5962,8 +5966,7 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) { struct wl1271 *wl = context; struct platform_device *pdev = wl->pdev; - struct wlcore_platdev_data *pdev_data = pdev->dev.platform_data; - struct wl12xx_platform_data *pdata = pdev_data->pdata; + struct wl12xx_platform_data *pdata = pdev->dev.platform_data; unsigned long irqflags; int ret; @@ -5992,7 +5995,8 @@ static void wlcore_nvs_cb(const struct firmware *fw, void *context) wl->irq = platform_get_irq(pdev, 0); wl->platform_quirks = pdata->platform_quirks; - wl->if_ops = pdev_data->if_ops; + wl->set_power = pdata->set_power; + wl->if_ops = pdata->ops; if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) irqflags = IRQF_TRIGGER_RISING; diff --git a/trunk/drivers/net/wireless/ti/wlcore/sdio.c b/trunk/drivers/net/wireless/ti/wlcore/sdio.c index 29ef2492951f..d4f184e2efed 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/sdio.c +++ b/trunk/drivers/net/wireless/ti/wlcore/sdio.c @@ -217,7 +217,7 @@ static struct wl1271_if_operations sdio_ops = { static int wl1271_probe(struct sdio_func *func, const struct sdio_device_id *id) { - struct wlcore_platdev_data *pdev_data; + struct wl12xx_platform_data *wlan_data; struct wl12xx_sdio_glue *glue; struct resource res[1]; mmc_pm_flag_t mmcflags; @@ -228,16 +228,10 @@ static int wl1271_probe(struct sdio_func *func, if (func->num != 0x02) return -ENODEV; - pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL); - if (!pdev_data) - goto out; - - pdev_data->if_ops = &sdio_ops; - glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&func->dev, "can't allocate glue\n"); - goto out_free_pdev_data; + goto out; } glue->dev = &func->dev; @@ -248,9 +242,9 @@ static int wl1271_probe(struct sdio_func *func, /* Use block mode for transferring over one block size of data */ func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - pdev_data->pdata = wl12xx_get_platform_data(); - if (IS_ERR(pdev_data->pdata)) { - ret = PTR_ERR(pdev_data->pdata); + wlan_data = wl12xx_get_platform_data(); + if (IS_ERR(wlan_data)) { + ret = PTR_ERR(wlan_data); dev_err(glue->dev, "missing wlan platform data: %d\n", ret); goto out_free_glue; } @@ -260,7 +254,9 @@ static int wl1271_probe(struct sdio_func *func, dev_dbg(glue->dev, "sdio PM caps = 0x%x\n", mmcflags); if (mmcflags & MMC_PM_KEEP_POWER) - pdev_data->pdata->pwr_in_suspend = true; + wlan_data->pwr_in_suspend = true; + + wlan_data->ops = &sdio_ops; sdio_set_drvdata(func, glue); @@ -278,7 +274,7 @@ static int wl1271_probe(struct sdio_func *func, else chip_family = "wl12xx"; - glue->core = platform_device_alloc(chip_family, PLATFORM_DEVID_AUTO); + glue->core = platform_device_alloc(chip_family, -1); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device"); ret = -ENOMEM; @@ -289,7 +285,7 @@ static int wl1271_probe(struct sdio_func *func, memset(res, 0x00, sizeof(res)); - res[0].start = pdev_data->pdata->irq; + res[0].start = wlan_data->irq; res[0].flags = IORESOURCE_IRQ; res[0].name = "irq"; @@ -299,8 +295,8 @@ static int wl1271_probe(struct sdio_func *func, goto out_dev_put; } - ret = platform_device_add_data(glue->core, pdev_data, - sizeof(*pdev_data)); + ret = platform_device_add_data(glue->core, wlan_data, + sizeof(*wlan_data)); if (ret) { dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; @@ -319,9 +315,6 @@ static int wl1271_probe(struct sdio_func *func, out_free_glue: kfree(glue); -out_free_pdev_data: - kfree(pdev_data); - out: return ret; } diff --git a/trunk/drivers/net/wireless/ti/wlcore/spi.c b/trunk/drivers/net/wireless/ti/wlcore/spi.c index e26447832683..2d700b7ae14c 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/spi.c +++ b/trunk/drivers/net/wireless/ti/wlcore/spi.c @@ -327,27 +327,22 @@ static struct wl1271_if_operations spi_ops = { static int wl1271_probe(struct spi_device *spi) { struct wl12xx_spi_glue *glue; - struct wlcore_platdev_data *pdev_data; + struct wl12xx_platform_data *pdata; struct resource res[1]; int ret = -ENOMEM; - pdev_data = kzalloc(sizeof(*pdev_data), GFP_KERNEL); - if (!pdev_data) - goto out; - - pdev_data->pdata = spi->dev.platform_data; - if (!pdev_data->pdata) { + pdata = spi->dev.platform_data; + if (!pdata) { dev_err(&spi->dev, "no platform data\n"); - ret = -ENODEV; - goto out_free_pdev_data; + return -ENODEV; } - pdev_data->if_ops = &spi_ops; + pdata->ops = &spi_ops; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { dev_err(&spi->dev, "can't allocate glue\n"); - goto out_free_pdev_data; + goto out; } glue->dev = &spi->dev; @@ -364,7 +359,7 @@ static int wl1271_probe(struct spi_device *spi) goto out_free_glue; } - glue->core = platform_device_alloc("wl12xx", PLATFORM_DEVID_AUTO); + glue->core = platform_device_alloc("wl12xx", -1); if (!glue->core) { dev_err(glue->dev, "can't allocate platform_device\n"); ret = -ENOMEM; @@ -385,8 +380,7 @@ static int wl1271_probe(struct spi_device *spi) goto out_dev_put; } - ret = platform_device_add_data(glue->core, pdev_data, - sizeof(*pdev_data)); + ret = platform_device_add_data(glue->core, pdata, sizeof(*pdata)); if (ret) { dev_err(glue->dev, "can't add platform data\n"); goto out_dev_put; @@ -405,10 +399,6 @@ static int wl1271_probe(struct spi_device *spi) out_free_glue: kfree(glue); - -out_free_pdev_data: - kfree(pdev_data); - out: return ret; } diff --git a/trunk/drivers/net/wireless/ti/wilink_platform_data.c b/trunk/drivers/net/wireless/ti/wlcore/wl12xx_platform_data.c similarity index 100% rename from trunk/drivers/net/wireless/ti/wilink_platform_data.c rename to trunk/drivers/net/wireless/ti/wlcore/wl12xx_platform_data.c diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h index af9fecaefc30..ebd8c6fad7cd 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore.h @@ -183,6 +183,7 @@ struct wl1271 { struct wl1271_if_operations *if_ops; + void (*set_power)(bool enable); int irq; spinlock_t wl_lock; diff --git a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h index c845b0ef7f4b..20316ac328a2 100644 --- a/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/trunk/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -206,11 +206,6 @@ struct wl1271_if_operations { void (*set_block_size) (struct device *child, unsigned int blksz); }; -struct wlcore_platdev_data { - struct wl12xx_platform_data *pdata; - struct wl1271_if_operations *if_ops; -}; - #define MAX_NUM_KEYS 14 #define MAX_KEY_SIZE 32 diff --git a/trunk/drivers/nfc/Kconfig b/trunk/drivers/nfc/Kconfig index e57034971ccc..80c728b28828 100644 --- a/trunk/drivers/nfc/Kconfig +++ b/trunk/drivers/nfc/Kconfig @@ -27,6 +27,5 @@ config NFC_WILINK into the kernel or say M to compile it as module. source "drivers/nfc/pn544/Kconfig" -source "drivers/nfc/microread/Kconfig" endmenu diff --git a/trunk/drivers/nfc/Makefile b/trunk/drivers/nfc/Makefile index a189ada0926a..574bbc04d97a 100644 --- a/trunk/drivers/nfc/Makefile +++ b/trunk/drivers/nfc/Makefile @@ -3,7 +3,6 @@ # obj-$(CONFIG_NFC_PN544) += pn544/ -obj-$(CONFIG_NFC_MICROREAD) += microread/ obj-$(CONFIG_NFC_PN533) += pn533.o obj-$(CONFIG_NFC_WILINK) += nfcwilink.o diff --git a/trunk/drivers/nfc/microread/Kconfig b/trunk/drivers/nfc/microread/Kconfig deleted file mode 100644 index 572305be6e37..000000000000 --- a/trunk/drivers/nfc/microread/Kconfig +++ /dev/null @@ -1,35 +0,0 @@ -config NFC_MICROREAD - tristate "Inside Secure microread NFC driver" - depends on NFC_HCI - select CRC_CCITT - default n - ---help--- - This module contains the main code for Inside Secure microread - NFC chipsets. It implements the chipset HCI logic and hooks into - the NFC kernel APIs. Physical layers will register against it. - - To compile this driver as a module, choose m here. The module will - be called microread. - Say N if unsure. - -config NFC_MICROREAD_I2C - tristate "NFC Microread i2c support" - depends on NFC_MICROREAD && I2C && NFC_SHDLC - ---help--- - This module adds support for the i2c interface of adapters using - Inside microread chipsets. Select this if your platform is using - the i2c bus. - - If you choose to build a module, it'll be called microread_i2c. - Say N if unsure. - -config NFC_MICROREAD_MEI - tristate "NFC Microread MEI support" - depends on NFC_MICROREAD && INTEL_MEI_BUS_NFC - ---help--- - This module adds support for the mei interface of adapters using - Inside microread chipsets. Select this if your microread chipset - is handled by Intel's Management Engine Interface on your platform. - - If you choose to build a module, it'll be called microread_mei. - Say N if unsure. diff --git a/trunk/drivers/nfc/microread/Makefile b/trunk/drivers/nfc/microread/Makefile deleted file mode 100644 index 755c24cba253..000000000000 --- a/trunk/drivers/nfc/microread/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for Microread HCI based NFC driver -# - -microread_i2c-objs = i2c.o -microread_mei-objs = mei.o - -obj-$(CONFIG_NFC_MICROREAD) += microread.o -obj-$(CONFIG_NFC_MICROREAD_I2C) += microread_i2c.o -obj-$(CONFIG_NFC_MICROREAD_MEI) += microread_mei.o diff --git a/trunk/drivers/nfc/microread/i2c.c b/trunk/drivers/nfc/microread/i2c.c deleted file mode 100644 index 101089495bf8..000000000000 --- a/trunk/drivers/nfc/microread/i2c.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * HCI based Driver for Inside Secure microread NFC Chip - i2c layer - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "microread.h" - -#define MICROREAD_I2C_DRIVER_NAME "microread" - -#define MICROREAD_I2C_FRAME_HEADROOM 1 -#define MICROREAD_I2C_FRAME_TAILROOM 1 - -/* framing in HCI mode */ -#define MICROREAD_I2C_LLC_LEN 1 -#define MICROREAD_I2C_LLC_CRC 1 -#define MICROREAD_I2C_LLC_LEN_CRC (MICROREAD_I2C_LLC_LEN + \ - MICROREAD_I2C_LLC_CRC) -#define MICROREAD_I2C_LLC_MIN_SIZE (1 + MICROREAD_I2C_LLC_LEN_CRC) -#define MICROREAD_I2C_LLC_MAX_PAYLOAD 29 -#define MICROREAD_I2C_LLC_MAX_SIZE (MICROREAD_I2C_LLC_LEN_CRC + 1 + \ - MICROREAD_I2C_LLC_MAX_PAYLOAD) - -struct microread_i2c_phy { - struct i2c_client *i2c_dev; - struct nfc_hci_dev *hdev; - - int irq; - - int hard_fault; /* - * < 0 if hardware error occured (e.g. i2c err) - * and prevents normal operation. - */ -}; - -#define I2C_DUMP_SKB(info, skb) \ -do { \ - pr_debug("%s:\n", info); \ - print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \ - 16, 1, (skb)->data, (skb)->len, 0); \ -} while (0) - -static void microread_i2c_add_len_crc(struct sk_buff *skb) -{ - int i; - u8 crc = 0; - int len; - - len = skb->len; - *skb_push(skb, 1) = len; - - for (i = 0; i < skb->len; i++) - crc = crc ^ skb->data[i]; - - *skb_put(skb, 1) = crc; -} - -static void microread_i2c_remove_len_crc(struct sk_buff *skb) -{ - skb_pull(skb, MICROREAD_I2C_FRAME_HEADROOM); - skb_trim(skb, MICROREAD_I2C_FRAME_TAILROOM); -} - -static int check_crc(struct sk_buff *skb) -{ - int i; - u8 crc = 0; - - for (i = 0; i < skb->len - 1; i++) - crc = crc ^ skb->data[i]; - - if (crc != skb->data[skb->len-1]) { - pr_err(MICROREAD_I2C_DRIVER_NAME - ": CRC error 0x%x != 0x%x\n", - crc, skb->data[skb->len-1]); - - pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); - - return -EPERM; - } - - return 0; -} - -static int microread_i2c_enable(void *phy_id) -{ - return 0; -} - -static void microread_i2c_disable(void *phy_id) -{ - return; -} - -static int microread_i2c_write(void *phy_id, struct sk_buff *skb) -{ - int r; - struct microread_i2c_phy *phy = phy_id; - struct i2c_client *client = phy->i2c_dev; - - if (phy->hard_fault != 0) - return phy->hard_fault; - - usleep_range(3000, 6000); - - microread_i2c_add_len_crc(skb); - - I2C_DUMP_SKB("i2c frame written", skb); - - r = i2c_master_send(client, skb->data, skb->len); - - if (r == -EREMOTEIO) { /* Retry, chip was in standby */ - usleep_range(6000, 10000); - r = i2c_master_send(client, skb->data, skb->len); - } - - if (r >= 0) { - if (r != skb->len) - r = -EREMOTEIO; - else - r = 0; - } - - microread_i2c_remove_len_crc(skb); - - return r; -} - - -static int microread_i2c_read(struct microread_i2c_phy *phy, - struct sk_buff **skb) -{ - int r; - u8 len; - u8 tmp[MICROREAD_I2C_LLC_MAX_SIZE - 1]; - struct i2c_client *client = phy->i2c_dev; - - pr_debug("%s\n", __func__); - - r = i2c_master_recv(client, &len, 1); - if (r != 1) { - dev_err(&client->dev, "cannot read len byte\n"); - return -EREMOTEIO; - } - - if ((len < MICROREAD_I2C_LLC_MIN_SIZE) || - (len > MICROREAD_I2C_LLC_MAX_SIZE)) { - dev_err(&client->dev, "invalid len byte\n"); - pr_err("invalid len byte\n"); - r = -EBADMSG; - goto flush; - } - - *skb = alloc_skb(1 + len, GFP_KERNEL); - if (*skb == NULL) { - r = -ENOMEM; - goto flush; - } - - *skb_put(*skb, 1) = len; - - r = i2c_master_recv(client, skb_put(*skb, len), len); - if (r != len) { - kfree_skb(*skb); - return -EREMOTEIO; - } - - I2C_DUMP_SKB("cc frame read", *skb); - - r = check_crc(*skb); - if (r != 0) { - kfree_skb(*skb); - r = -EBADMSG; - goto flush; - } - - skb_pull(*skb, 1); - skb_trim(*skb, (*skb)->len - MICROREAD_I2C_FRAME_TAILROOM); - - usleep_range(3000, 6000); - - return 0; - -flush: - if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) - r = -EREMOTEIO; - - usleep_range(3000, 6000); - - return r; -} - -static irqreturn_t microread_i2c_irq_thread_fn(int irq, void *phy_id) -{ - struct microread_i2c_phy *phy = phy_id; - struct i2c_client *client; - struct sk_buff *skb = NULL; - int r; - - if (!phy || irq != phy->i2c_dev->irq) { - WARN_ON_ONCE(1); - return IRQ_NONE; - } - - client = phy->i2c_dev; - dev_dbg(&client->dev, "IRQ\n"); - - if (phy->hard_fault != 0) - return IRQ_HANDLED; - - r = microread_i2c_read(phy, &skb); - if (r == -EREMOTEIO) { - phy->hard_fault = r; - - nfc_hci_recv_frame(phy->hdev, NULL); - - return IRQ_HANDLED; - } else if ((r == -ENOMEM) || (r == -EBADMSG)) { - return IRQ_HANDLED; - } - - nfc_hci_recv_frame(phy->hdev, skb); - - return IRQ_HANDLED; -} - -static struct nfc_phy_ops i2c_phy_ops = { - .write = microread_i2c_write, - .enable = microread_i2c_enable, - .disable = microread_i2c_disable, -}; - -static int microread_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct microread_i2c_phy *phy; - struct microread_nfc_platform_data *pdata = - dev_get_platdata(&client->dev); - int r; - - dev_dbg(&client->dev, "client %p", client); - - if (!pdata) { - dev_err(&client->dev, "client %p: missing platform data", - client); - return -EINVAL; - } - - phy = devm_kzalloc(&client->dev, sizeof(struct microread_i2c_phy), - GFP_KERNEL); - if (!phy) { - dev_err(&client->dev, "Can't allocate microread phy"); - return -ENOMEM; - } - - i2c_set_clientdata(client, phy); - phy->i2c_dev = client; - - r = request_threaded_irq(client->irq, NULL, microread_i2c_irq_thread_fn, - IRQF_TRIGGER_RISING | IRQF_ONESHOT, - MICROREAD_I2C_DRIVER_NAME, phy); - if (r) { - dev_err(&client->dev, "Unable to register IRQ handler"); - return r; - } - - r = microread_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, - MICROREAD_I2C_FRAME_HEADROOM, - MICROREAD_I2C_FRAME_TAILROOM, - MICROREAD_I2C_LLC_MAX_PAYLOAD, &phy->hdev); - if (r < 0) - goto err_irq; - - dev_info(&client->dev, "Probed"); - - return 0; - -err_irq: - free_irq(client->irq, phy); - - return r; -} - -static int microread_i2c_remove(struct i2c_client *client) -{ - struct microread_i2c_phy *phy = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "%s\n", __func__); - - microread_remove(phy->hdev); - - free_irq(client->irq, phy); - - return 0; -} - -static struct i2c_device_id microread_i2c_id[] = { - { MICROREAD_I2C_DRIVER_NAME, 0}, - { } -}; -MODULE_DEVICE_TABLE(i2c, microread_i2c_id); - -static struct i2c_driver microread_i2c_driver = { - .driver = { - .name = MICROREAD_I2C_DRIVER_NAME, - }, - .probe = microread_i2c_probe, - .remove = microread_i2c_remove, - .id_table = microread_i2c_id, -}; - -module_i2c_driver(microread_i2c_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/trunk/drivers/nfc/microread/mei.c b/trunk/drivers/nfc/microread/mei.c deleted file mode 100644 index eef38cfd812e..000000000000 --- a/trunk/drivers/nfc/microread/mei.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * HCI based Driver for Inside Secure microread NFC Chip - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "microread.h" - -#define MICROREAD_DRIVER_NAME "microread" - -#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \ - 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c) - -struct mei_nfc_hdr { - u8 cmd; - u8 status; - u16 req_id; - u32 reserved; - u16 data_size; -} __attribute__((packed)); - -#define MEI_NFC_HEADER_SIZE 10 -#define MEI_NFC_MAX_HCI_PAYLOAD 300 -#define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) - -struct microread_mei_phy { - struct mei_device *mei_device; - struct nfc_hci_dev *hdev; - - int powered; - - int hard_fault; /* - * < 0 if hardware error occured (e.g. i2c err) - * and prevents normal operation. - */ -}; - -#define MEI_DUMP_SKB_IN(info, skb) \ -do { \ - pr_debug("%s:\n", info); \ - print_hex_dump(KERN_DEBUG, "mei in : ", DUMP_PREFIX_OFFSET, \ - 16, 1, (skb)->data, (skb)->len, 0); \ -} while (0) - -#define MEI_DUMP_SKB_OUT(info, skb) \ -do { \ - pr_debug("%s:\n", info); \ - print_hex_dump(KERN_DEBUG, "mei out: ", DUMP_PREFIX_OFFSET, \ - 16, 1, (skb)->data, (skb)->len, 0); \ -} while (0) - -static int microread_mei_enable(void *phy_id) -{ - struct microread_mei_phy *phy = phy_id; - - pr_info(DRIVER_DESC ": %s\n", __func__); - - phy->powered = 1; - - return 0; -} - -static void microread_mei_disable(void *phy_id) -{ - struct microread_mei_phy *phy = phy_id; - - pr_info(DRIVER_DESC ": %s\n", __func__); - - phy->powered = 0; -} - -/* - * Writing a frame must not return the number of written bytes. - * It must return either zero for success, or <0 for error. - * In addition, it must not alter the skb - */ -static int microread_mei_write(void *phy_id, struct sk_buff *skb) -{ - struct microread_mei_phy *phy = phy_id; - int r; - - MEI_DUMP_SKB_OUT("mei frame sent", skb); - - r = mei_send(phy->device, skb->data, skb->len); - if (r > 0) - r = 0; - - return r; -} - -static void microread_event_cb(struct mei_device *device, u32 events, - void *context) -{ - struct microread_mei_phy *phy = context; - - if (phy->hard_fault != 0) - return; - - if (events & BIT(MEI_EVENT_RX)) { - struct sk_buff *skb; - int reply_size; - - skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL); - if (!skb) - return; - - reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ); - if (reply_size < MEI_NFC_HEADER_SIZE) { - kfree(skb); - return; - } - - skb_put(skb, reply_size); - skb_pull(skb, MEI_NFC_HEADER_SIZE); - - MEI_DUMP_SKB_IN("mei frame read", skb); - - nfc_hci_recv_frame(phy->hdev, skb); - } -} - -static struct nfc_phy_ops mei_phy_ops = { - .write = microread_mei_write, - .enable = microread_mei_enable, - .disable = microread_mei_disable, -}; - -static int microread_mei_probe(struct mei_device *device, - const struct mei_id *id) -{ - struct microread_mei_phy *phy; - int r; - - pr_info("Probing NFC microread\n"); - - phy = kzalloc(sizeof(struct microread_mei_phy), GFP_KERNEL); - if (!phy) { - pr_err("Cannot allocate memory for microread mei phy.\n"); - return -ENOMEM; - } - - phy->device = device; - mei_set_clientdata(device, phy); - - r = mei_register_event_cb(device, microread_event_cb, phy); - if (r) { - pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n"); - goto err_out; - } - - r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME, - MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD, - &phy->hdev); - if (r < 0) - goto err_out; - - return 0; - -err_out: - kfree(phy); - - return r; -} - -static int microread_mei_remove(struct mei_device *device) -{ - struct microread_mei_phy *phy = mei_get_clientdata(device); - - pr_info("Removing microread\n"); - - microread_remove(phy->hdev); - - if (phy->powered) - microread_mei_disable(phy); - - kfree(phy); - - return 0; -} - -static struct mei_id microread_mei_tbl[] = { - { MICROREAD_DRIVER_NAME, MICROREAD_UUID }, - - /* required last entry */ - { } -}; - -MODULE_DEVICE_TABLE(mei, microread_mei_tbl); - -static struct mei_driver microread_driver = { - .id_table = microread_mei_tbl, - .name = MICROREAD_DRIVER_NAME, - - .probe = microread_mei_probe, - .remove = microread_mei_remove, -}; - -static int microread_mei_init(void) -{ - int r; - - pr_debug(DRIVER_DESC ": %s\n", __func__); - - r = mei_driver_register(µread_driver); - if (r) { - pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n"); - return r; - } - - return 0; -} - -static void microread_mei_exit(void) -{ - mei_driver_unregister(µread_driver); -} - -module_init(microread_mei_init); -module_exit(microread_mei_exit); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/trunk/drivers/nfc/microread/microread.c b/trunk/drivers/nfc/microread/microread.c deleted file mode 100644 index 3420d833db17..000000000000 --- a/trunk/drivers/nfc/microread/microread.c +++ /dev/null @@ -1,728 +0,0 @@ -/* - * HCI based Driver for Inside Secure microread NFC Chip - * - * Copyright (C) 2013 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "microread.h" - -/* Proprietary gates, events, commands and registers */ -/* Admin */ -#define MICROREAD_GATE_ID_ADM NFC_HCI_ADMIN_GATE -#define MICROREAD_GATE_ID_MGT 0x01 -#define MICROREAD_GATE_ID_OS 0x02 -#define MICROREAD_GATE_ID_TESTRF 0x03 -#define MICROREAD_GATE_ID_LOOPBACK NFC_HCI_LOOPBACK_GATE -#define MICROREAD_GATE_ID_IDT NFC_HCI_ID_MGMT_GATE -#define MICROREAD_GATE_ID_LMS NFC_HCI_LINK_MGMT_GATE - -/* Reader */ -#define MICROREAD_GATE_ID_MREAD_GEN 0x10 -#define MICROREAD_GATE_ID_MREAD_ISO_B NFC_HCI_RF_READER_B_GATE -#define MICROREAD_GATE_ID_MREAD_NFC_T1 0x12 -#define MICROREAD_GATE_ID_MREAD_ISO_A NFC_HCI_RF_READER_A_GATE -#define MICROREAD_GATE_ID_MREAD_NFC_T3 0x14 -#define MICROREAD_GATE_ID_MREAD_ISO_15_3 0x15 -#define MICROREAD_GATE_ID_MREAD_ISO_15_2 0x16 -#define MICROREAD_GATE_ID_MREAD_ISO_B_3 0x17 -#define MICROREAD_GATE_ID_MREAD_BPRIME 0x18 -#define MICROREAD_GATE_ID_MREAD_ISO_A_3 0x19 - -/* Card */ -#define MICROREAD_GATE_ID_MCARD_GEN 0x20 -#define MICROREAD_GATE_ID_MCARD_ISO_B 0x21 -#define MICROREAD_GATE_ID_MCARD_BPRIME 0x22 -#define MICROREAD_GATE_ID_MCARD_ISO_A 0x23 -#define MICROREAD_GATE_ID_MCARD_NFC_T3 0x24 -#define MICROREAD_GATE_ID_MCARD_ISO_15_3 0x25 -#define MICROREAD_GATE_ID_MCARD_ISO_15_2 0x26 -#define MICROREAD_GATE_ID_MCARD_ISO_B_2 0x27 -#define MICROREAD_GATE_ID_MCARD_ISO_CUSTOM 0x28 -#define MICROREAD_GATE_ID_SECURE_ELEMENT 0x2F - -/* P2P */ -#define MICROREAD_GATE_ID_P2P_GEN 0x30 -#define MICROREAD_GATE_ID_P2P_TARGET 0x31 -#define MICROREAD_PAR_P2P_TARGET_MODE 0x01 -#define MICROREAD_PAR_P2P_TARGET_GT 0x04 -#define MICROREAD_GATE_ID_P2P_INITIATOR 0x32 -#define MICROREAD_PAR_P2P_INITIATOR_GI 0x01 -#define MICROREAD_PAR_P2P_INITIATOR_GT 0x03 - -/* Those pipes are created/opened by default in the chip */ -#define MICROREAD_PIPE_ID_LMS 0x00 -#define MICROREAD_PIPE_ID_ADMIN 0x01 -#define MICROREAD_PIPE_ID_MGT 0x02 -#define MICROREAD_PIPE_ID_OS 0x03 -#define MICROREAD_PIPE_ID_HDS_LOOPBACK 0x04 -#define MICROREAD_PIPE_ID_HDS_IDT 0x05 -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B 0x08 -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_BPRIME 0x09 -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_A 0x0A -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_3 0x0B -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_15_2 0x0C -#define MICROREAD_PIPE_ID_HDS_MCARD_NFC_T3 0x0D -#define MICROREAD_PIPE_ID_HDS_MCARD_ISO_B_2 0x0E -#define MICROREAD_PIPE_ID_HDS_MCARD_CUSTOM 0x0F -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B 0x10 -#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1 0x11 -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A 0x12 -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_3 0x13 -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_15_2 0x14 -#define MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3 0x15 -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_B_3 0x16 -#define MICROREAD_PIPE_ID_HDS_MREAD_BPRIME 0x17 -#define MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3 0x18 -#define MICROREAD_PIPE_ID_HDS_MREAD_GEN 0x1B -#define MICROREAD_PIPE_ID_HDS_STACKED_ELEMENT 0x1C -#define MICROREAD_PIPE_ID_HDS_INSTANCES 0x1D -#define MICROREAD_PIPE_ID_HDS_TESTRF 0x1E -#define MICROREAD_PIPE_ID_HDS_P2P_TARGET 0x1F -#define MICROREAD_PIPE_ID_HDS_P2P_INITIATOR 0x20 - -/* Events */ -#define MICROREAD_EVT_MREAD_DISCOVERY_OCCURED NFC_HCI_EVT_TARGET_DISCOVERED -#define MICROREAD_EVT_MREAD_CARD_FOUND 0x3D -#define MICROREAD_EMCF_A_ATQA 0 -#define MICROREAD_EMCF_A_SAK 2 -#define MICROREAD_EMCF_A_LEN 3 -#define MICROREAD_EMCF_A_UID 4 -#define MICROREAD_EMCF_A3_ATQA 0 -#define MICROREAD_EMCF_A3_SAK 2 -#define MICROREAD_EMCF_A3_LEN 3 -#define MICROREAD_EMCF_A3_UID 4 -#define MICROREAD_EMCF_B_UID 0 -#define MICROREAD_EMCF_T1_ATQA 0 -#define MICROREAD_EMCF_T1_UID 4 -#define MICROREAD_EMCF_T3_UID 0 -#define MICROREAD_EVT_MREAD_DISCOVERY_START NFC_HCI_EVT_READER_REQUESTED -#define MICROREAD_EVT_MREAD_DISCOVERY_START_SOME 0x3E -#define MICROREAD_EVT_MREAD_DISCOVERY_STOP NFC_HCI_EVT_END_OPERATION -#define MICROREAD_EVT_MREAD_SIM_REQUESTS 0x3F -#define MICROREAD_EVT_MCARD_EXCHANGE NFC_HCI_EVT_TARGET_DISCOVERED -#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF 0x20 -#define MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF 0x21 -#define MICROREAD_EVT_MCARD_FIELD_ON 0x11 -#define MICROREAD_EVT_P2P_TARGET_ACTIVATED 0x13 -#define MICROREAD_EVT_P2P_TARGET_DEACTIVATED 0x12 -#define MICROREAD_EVT_MCARD_FIELD_OFF 0x14 - -/* Commands */ -#define MICROREAD_CMD_MREAD_EXCHANGE 0x10 -#define MICROREAD_CMD_MREAD_SUBSCRIBE 0x3F - -/* Hosts IDs */ -#define MICROREAD_ELT_ID_HDS NFC_HCI_TERMINAL_HOST_ID -#define MICROREAD_ELT_ID_SIM NFC_HCI_UICC_HOST_ID -#define MICROREAD_ELT_ID_SE1 0x03 -#define MICROREAD_ELT_ID_SE2 0x04 -#define MICROREAD_ELT_ID_SE3 0x05 - -static struct nfc_hci_gate microread_gates[] = { - {MICROREAD_GATE_ID_ADM, MICROREAD_PIPE_ID_ADMIN}, - {MICROREAD_GATE_ID_LOOPBACK, MICROREAD_PIPE_ID_HDS_LOOPBACK}, - {MICROREAD_GATE_ID_IDT, MICROREAD_PIPE_ID_HDS_IDT}, - {MICROREAD_GATE_ID_LMS, MICROREAD_PIPE_ID_LMS}, - {MICROREAD_GATE_ID_MREAD_ISO_B, MICROREAD_PIPE_ID_HDS_MREAD_ISO_B}, - {MICROREAD_GATE_ID_MREAD_ISO_A, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A}, - {MICROREAD_GATE_ID_MREAD_ISO_A_3, MICROREAD_PIPE_ID_HDS_MREAD_ISO_A_3}, - {MICROREAD_GATE_ID_MGT, MICROREAD_PIPE_ID_MGT}, - {MICROREAD_GATE_ID_OS, MICROREAD_PIPE_ID_OS}, - {MICROREAD_GATE_ID_MREAD_NFC_T1, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T1}, - {MICROREAD_GATE_ID_MREAD_NFC_T3, MICROREAD_PIPE_ID_HDS_MREAD_NFC_T3}, - {MICROREAD_GATE_ID_P2P_TARGET, MICROREAD_PIPE_ID_HDS_P2P_TARGET}, - {MICROREAD_GATE_ID_P2P_INITIATOR, MICROREAD_PIPE_ID_HDS_P2P_INITIATOR} -}; - -/* Largest headroom needed for outgoing custom commands */ -#define MICROREAD_CMDS_HEADROOM 2 -#define MICROREAD_CMD_TAILROOM 2 - -struct microread_info { - struct nfc_phy_ops *phy_ops; - void *phy_id; - - struct nfc_hci_dev *hdev; - - int async_cb_type; - data_exchange_cb_t async_cb; - void *async_cb_context; -}; - -static int microread_open(struct nfc_hci_dev *hdev) -{ - struct microread_info *info = nfc_hci_get_clientdata(hdev); - - return info->phy_ops->enable(info->phy_id); -} - -static void microread_close(struct nfc_hci_dev *hdev) -{ - struct microread_info *info = nfc_hci_get_clientdata(hdev); - - info->phy_ops->disable(info->phy_id); -} - -static int microread_hci_ready(struct nfc_hci_dev *hdev) -{ - int r; - u8 param[4]; - - param[0] = 0x03; - r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, - MICROREAD_CMD_MREAD_SUBSCRIBE, param, 1, NULL); - if (r) - return r; - - r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_A_3, - MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); - if (r) - return r; - - param[0] = 0x00; - param[1] = 0x03; - param[2] = 0x00; - r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_ISO_B, - MICROREAD_CMD_MREAD_SUBSCRIBE, param, 3, NULL); - if (r) - return r; - - r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T1, - MICROREAD_CMD_MREAD_SUBSCRIBE, NULL, 0, NULL); - if (r) - return r; - - param[0] = 0xFF; - param[1] = 0xFF; - param[2] = 0x00; - param[3] = 0x00; - r = nfc_hci_send_cmd(hdev, MICROREAD_GATE_ID_MREAD_NFC_T3, - MICROREAD_CMD_MREAD_SUBSCRIBE, param, 4, NULL); - - return r; -} - -static int microread_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) -{ - struct microread_info *info = nfc_hci_get_clientdata(hdev); - - return info->phy_ops->write(info->phy_id, skb); -} - -static int microread_start_poll(struct nfc_hci_dev *hdev, - u32 im_protocols, u32 tm_protocols) -{ - int r; - - u8 param[2]; - u8 mode; - - param[0] = 0x00; - param[1] = 0x00; - - if (im_protocols & NFC_PROTO_ISO14443_MASK) - param[0] |= (1 << 2); - - if (im_protocols & NFC_PROTO_ISO14443_B_MASK) - param[0] |= 1; - - if (im_protocols & NFC_PROTO_MIFARE_MASK) - param[1] |= 1; - - if (im_protocols & NFC_PROTO_JEWEL_MASK) - param[0] |= (1 << 1); - - if (im_protocols & NFC_PROTO_FELICA_MASK) - param[0] |= (1 << 5); - - if (im_protocols & NFC_PROTO_NFC_DEP_MASK) - param[1] |= (1 << 1); - - if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { - hdev->gb = nfc_get_local_general_bytes(hdev->ndev, - &hdev->gb_len); - if (hdev->gb == NULL || hdev->gb_len == 0) { - im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; - tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; - } - } - - r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, - MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); - if (r) - return r; - - mode = 0xff; - r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, - MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); - if (r) - return r; - - if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { - r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, - MICROREAD_PAR_P2P_INITIATOR_GI, - hdev->gb, hdev->gb_len); - if (r) - return r; - } - - if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { - r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, - MICROREAD_PAR_P2P_TARGET_GT, - hdev->gb, hdev->gb_len); - if (r) - return r; - - mode = 0x02; - r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, - MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); - if (r) - return r; - } - - return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_MREAD_ISO_A, - MICROREAD_EVT_MREAD_DISCOVERY_START_SOME, - param, 2); -} - -static int microread_dep_link_up(struct nfc_hci_dev *hdev, - struct nfc_target *target, u8 comm_mode, - u8 *gb, size_t gb_len) -{ - struct sk_buff *rgb_skb = NULL; - int r; - - r = nfc_hci_get_param(hdev, target->hci_reader_gate, - MICROREAD_PAR_P2P_INITIATOR_GT, &rgb_skb); - if (r < 0) - return r; - - if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { - r = -EPROTO; - goto exit; - } - - r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, - rgb_skb->len); - if (r == 0) - r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, - NFC_RF_INITIATOR); -exit: - kfree_skb(rgb_skb); - - return r; -} - -static int microread_dep_link_down(struct nfc_hci_dev *hdev) -{ - return nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_INITIATOR, - MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, 0); -} - -static int microread_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, - struct nfc_target *target) -{ - switch (gate) { - case MICROREAD_GATE_ID_P2P_INITIATOR: - target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; - break; - default: - return -EPROTO; - } - - return 0; -} - -static int microread_complete_target_discovered(struct nfc_hci_dev *hdev, - u8 gate, - struct nfc_target *target) -{ - return 0; -} - -#define MICROREAD_CB_TYPE_READER_ALL 1 - -static void microread_im_transceive_cb(void *context, struct sk_buff *skb, - int err) -{ - struct microread_info *info = context; - - switch (info->async_cb_type) { - case MICROREAD_CB_TYPE_READER_ALL: - if (err == 0) { - if (skb->len == 0) { - err = -EPROTO; - kfree_skb(skb); - info->async_cb(info->async_cb_context, NULL, - -EPROTO); - return; - } - - if (skb->data[skb->len - 1] != 0) { - err = nfc_hci_result_to_errno( - skb->data[skb->len - 1]); - kfree_skb(skb); - info->async_cb(info->async_cb_context, NULL, - err); - return; - } - - skb_trim(skb, skb->len - 1); /* RF Error ind. */ - } - info->async_cb(info->async_cb_context, skb, err); - break; - default: - if (err == 0) - kfree_skb(skb); - break; - } -} - -/* - * Returns: - * <= 0: driver handled the data exchange - * 1: driver doesn't especially handle, please do standard processing - */ -static int microread_im_transceive(struct nfc_hci_dev *hdev, - struct nfc_target *target, - struct sk_buff *skb, data_exchange_cb_t cb, - void *cb_context) -{ - struct microread_info *info = nfc_hci_get_clientdata(hdev); - u8 control_bits; - u16 crc; - - pr_info("data exchange to gate 0x%x\n", target->hci_reader_gate); - - if (target->hci_reader_gate == MICROREAD_GATE_ID_P2P_INITIATOR) { - *skb_push(skb, 1) = 0; - - return nfc_hci_send_event(hdev, target->hci_reader_gate, - MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_TO_RF, - skb->data, skb->len); - } - - switch (target->hci_reader_gate) { - case MICROREAD_GATE_ID_MREAD_ISO_A: - control_bits = 0xCB; - break; - case MICROREAD_GATE_ID_MREAD_ISO_A_3: - control_bits = 0xCB; - break; - case MICROREAD_GATE_ID_MREAD_ISO_B: - control_bits = 0xCB; - break; - case MICROREAD_GATE_ID_MREAD_NFC_T1: - control_bits = 0x1B; - - crc = crc_ccitt(0xffff, skb->data, skb->len); - crc = ~crc; - *skb_put(skb, 1) = crc & 0xff; - *skb_put(skb, 1) = crc >> 8; - break; - case MICROREAD_GATE_ID_MREAD_NFC_T3: - control_bits = 0xDB; - break; - default: - pr_info("Abort im_transceive to invalid gate 0x%x\n", - target->hci_reader_gate); - return 1; - } - - *skb_push(skb, 1) = control_bits; - - info->async_cb_type = MICROREAD_CB_TYPE_READER_ALL; - info->async_cb = cb; - info->async_cb_context = cb_context; - - return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, - MICROREAD_CMD_MREAD_EXCHANGE, - skb->data, skb->len, - microread_im_transceive_cb, info); -} - -static int microread_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) -{ - int r; - - r = nfc_hci_send_event(hdev, MICROREAD_GATE_ID_P2P_TARGET, - MICROREAD_EVT_MCARD_EXCHANGE, - skb->data, skb->len); - - kfree_skb(skb); - - return r; -} - -static void microread_target_discovered(struct nfc_hci_dev *hdev, u8 gate, - struct sk_buff *skb) -{ - struct nfc_target *targets; - int r = 0; - - pr_info("target discovered to gate 0x%x\n", gate); - - targets = kzalloc(sizeof(struct nfc_target), GFP_KERNEL); - if (targets == NULL) { - r = -ENOMEM; - goto exit; - } - - targets->hci_reader_gate = gate; - - switch (gate) { - case MICROREAD_GATE_ID_MREAD_ISO_A: - targets->supported_protocols = - nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A_SAK]); - targets->sens_res = - be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A_ATQA]); - targets->sel_res = skb->data[MICROREAD_EMCF_A_SAK]; - memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A_UID], - skb->data[MICROREAD_EMCF_A_LEN]); - targets->nfcid1_len = skb->data[MICROREAD_EMCF_A_LEN]; - break; - case MICROREAD_GATE_ID_MREAD_ISO_A_3: - targets->supported_protocols = - nfc_hci_sak_to_protocol(skb->data[MICROREAD_EMCF_A3_SAK]); - targets->sens_res = - be16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_A3_ATQA]); - targets->sel_res = skb->data[MICROREAD_EMCF_A3_SAK]; - memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_A3_UID], - skb->data[MICROREAD_EMCF_A3_LEN]); - targets->nfcid1_len = skb->data[MICROREAD_EMCF_A3_LEN]; - break; - case MICROREAD_GATE_ID_MREAD_ISO_B: - targets->supported_protocols = NFC_PROTO_ISO14443_B_MASK; - memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_B_UID], 4); - targets->nfcid1_len = 4; - break; - case MICROREAD_GATE_ID_MREAD_NFC_T1: - targets->supported_protocols = NFC_PROTO_JEWEL_MASK; - targets->sens_res = - le16_to_cpu(*(u16 *)&skb->data[MICROREAD_EMCF_T1_ATQA]); - memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T1_UID], 4); - targets->nfcid1_len = 4; - break; - case MICROREAD_GATE_ID_MREAD_NFC_T3: - targets->supported_protocols = NFC_PROTO_FELICA_MASK; - memcpy(targets->nfcid1, &skb->data[MICROREAD_EMCF_T3_UID], 8); - targets->nfcid1_len = 8; - break; - default: - pr_info("discard target discovered to gate 0x%x\n", gate); - goto exit_free; - } - - r = nfc_targets_found(hdev->ndev, targets, 1); - -exit_free: - kfree(targets); - -exit: - kfree_skb(skb); - - if (r) - pr_err("Failed to handle discovered target err=%d", r); -} - -static int microread_event_received(struct nfc_hci_dev *hdev, u8 gate, - u8 event, struct sk_buff *skb) -{ - int r; - u8 mode; - - pr_info("Microread received event 0x%x to gate 0x%x\n", event, gate); - - switch (event) { - case MICROREAD_EVT_MREAD_CARD_FOUND: - microread_target_discovered(hdev, gate, skb); - return 0; - - case MICROREAD_EVT_P2P_INITIATOR_EXCHANGE_FROM_RF: - if (skb->len < 1) { - kfree_skb(skb); - return -EPROTO; - } - - if (skb->data[skb->len - 1]) { - kfree_skb(skb); - return -EIO; - } - - skb_trim(skb, skb->len - 1); - - r = nfc_tm_data_received(hdev->ndev, skb); - break; - - case MICROREAD_EVT_MCARD_FIELD_ON: - case MICROREAD_EVT_MCARD_FIELD_OFF: - kfree_skb(skb); - return 0; - - case MICROREAD_EVT_P2P_TARGET_ACTIVATED: - r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, - NFC_COMM_PASSIVE, skb->data, - skb->len); - - kfree_skb(skb); - break; - - case MICROREAD_EVT_MCARD_EXCHANGE: - if (skb->len < 1) { - kfree_skb(skb); - return -EPROTO; - } - - if (skb->data[skb->len-1]) { - kfree_skb(skb); - return -EIO; - } - - skb_trim(skb, skb->len - 1); - - r = nfc_tm_data_received(hdev->ndev, skb); - break; - - case MICROREAD_EVT_P2P_TARGET_DEACTIVATED: - kfree_skb(skb); - - mode = 0xff; - r = nfc_hci_set_param(hdev, MICROREAD_GATE_ID_P2P_TARGET, - MICROREAD_PAR_P2P_TARGET_MODE, &mode, 1); - if (r) - break; - - r = nfc_hci_send_event(hdev, gate, - MICROREAD_EVT_MREAD_DISCOVERY_STOP, NULL, - 0); - break; - - default: - return 1; - } - - return r; -} - -static struct nfc_hci_ops microread_hci_ops = { - .open = microread_open, - .close = microread_close, - .hci_ready = microread_hci_ready, - .xmit = microread_xmit, - .start_poll = microread_start_poll, - .dep_link_up = microread_dep_link_up, - .dep_link_down = microread_dep_link_down, - .target_from_gate = microread_target_from_gate, - .complete_target_discovered = microread_complete_target_discovered, - .im_transceive = microread_im_transceive, - .tm_send = microread_tm_send, - .check_presence = NULL, - .event_received = microread_event_received, -}; - -int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, - int phy_headroom, int phy_tailroom, int phy_payload, - struct nfc_hci_dev **hdev) -{ - struct microread_info *info; - unsigned long quirks = 0; - u32 protocols, se; - struct nfc_hci_init_data init_data; - int r; - - info = kzalloc(sizeof(struct microread_info), GFP_KERNEL); - if (!info) { - pr_err("Cannot allocate memory for microread_info.\n"); - r = -ENOMEM; - goto err_info_alloc; - } - - info->phy_ops = phy_ops; - info->phy_id = phy_id; - - init_data.gate_count = ARRAY_SIZE(microread_gates); - memcpy(init_data.gates, microread_gates, sizeof(microread_gates)); - - strcpy(init_data.session_id, "MICROREA"); - - set_bit(NFC_HCI_QUIRK_SHORT_CLEAR, &quirks); - - protocols = NFC_PROTO_JEWEL_MASK | - NFC_PROTO_MIFARE_MASK | - NFC_PROTO_FELICA_MASK | - NFC_PROTO_ISO14443_MASK | - NFC_PROTO_ISO14443_B_MASK | - NFC_PROTO_NFC_DEP_MASK; - - se = NFC_SE_UICC | NFC_SE_EMBEDDED; - - info->hdev = nfc_hci_allocate_device(µread_hci_ops, &init_data, - quirks, protocols, se, llc_name, - phy_headroom + - MICROREAD_CMDS_HEADROOM, - phy_tailroom + - MICROREAD_CMD_TAILROOM, - phy_payload); - if (!info->hdev) { - pr_err("Cannot allocate nfc hdev.\n"); - r = -ENOMEM; - goto err_alloc_hdev; - } - - nfc_hci_set_clientdata(info->hdev, info); - - r = nfc_hci_register_device(info->hdev); - if (r) - goto err_regdev; - - *hdev = info->hdev; - - return 0; - -err_regdev: - nfc_hci_free_device(info->hdev); - -err_alloc_hdev: - kfree(info); - -err_info_alloc: - return r; -} -EXPORT_SYMBOL(microread_probe); - -void microread_remove(struct nfc_hci_dev *hdev) -{ - struct microread_info *info = nfc_hci_get_clientdata(hdev); - - nfc_hci_unregister_device(hdev); - nfc_hci_free_device(hdev); - kfree(info); -} -EXPORT_SYMBOL(microread_remove); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/trunk/drivers/nfc/microread/microread.h b/trunk/drivers/nfc/microread/microread.h deleted file mode 100644 index 64b447a1c5bf..000000000000 --- a/trunk/drivers/nfc/microread/microread.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2011 - 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the - * Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef __LOCAL_MICROREAD_H_ -#define __LOCAL_MICROREAD_H_ - -#include - -#define DRIVER_DESC "NFC driver for microread" - -int microread_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, - int phy_headroom, int phy_tailroom, int phy_payload, - struct nfc_hci_dev **hdev); - -void microread_remove(struct nfc_hci_dev *hdev); - -#endif /* __LOCAL_MICROREAD_H_ */ diff --git a/trunk/drivers/nfc/pn533.c b/trunk/drivers/nfc/pn533.c index f0f6763d67ae..f696318cfb51 100644 --- a/trunk/drivers/nfc/pn533.c +++ b/trunk/drivers/nfc/pn533.c @@ -219,7 +219,7 @@ struct pn533_poll_modulations { u8 len; }; -static const struct pn533_poll_modulations poll_mod[] = { +const struct pn533_poll_modulations poll_mod[] = { [PN533_POLL_MOD_106KBPS_A] = { .data = { .maxtg = 1, @@ -485,7 +485,7 @@ static u8 pn533_get_cmd_code(void *frame) return PN533_FRAME_CMD(f); } -static struct pn533_frame_ops pn533_std_frame_ops = { +struct pn533_frame_ops pn533_std_frame_ops = { .tx_frame_init = pn533_tx_frame_init, .tx_frame_finish = pn533_tx_frame_finish, .tx_update_payload_len = pn533_tx_update_payload_len, @@ -532,6 +532,7 @@ static void pn533_recv_response(struct urb *urb) urb->status); dev->wq_in_error = urb->status; goto sched_wq; + break; case -ESHUTDOWN: default: nfc_dev_err(&dev->interface->dev, @@ -588,6 +589,7 @@ static void pn533_recv_ack(struct urb *urb) urb->status); dev->wq_in_error = urb->status; goto sched_wq; + break; case -ESHUTDOWN: default: nfc_dev_err(&dev->interface->dev, @@ -1378,7 +1380,7 @@ static struct sk_buff *pn533_alloc_poll_tg_frame(struct pn533 *dev) return NULL; /* DEP support only */ - *skb_put(skb, 1) = PN533_INIT_TARGET_DEP; + *skb_put(skb, 1) |= PN533_INIT_TARGET_DEP; /* MIFARE params */ memcpy(skb_put(skb, 6), mifare_params, 6); diff --git a/trunk/drivers/staging/wlan-ng/cfg80211.c b/trunk/drivers/staging/wlan-ng/cfg80211.c index a233f64ca22f..18c06a59c091 100644 --- a/trunk/drivers/staging/wlan-ng/cfg80211.c +++ b/trunk/drivers/staging/wlan-ng/cfg80211.c @@ -424,7 +424,7 @@ int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) goto exit; } - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); } if (result) diff --git a/trunk/include/linux/bcma/bcma_driver_chipcommon.h b/trunk/include/linux/bcma/bcma_driver_chipcommon.h index 6a299f416288..9a0e3fa3ca95 100644 --- a/trunk/include/linux/bcma/bcma_driver_chipcommon.h +++ b/trunk/include/linux/bcma/bcma_driver_chipcommon.h @@ -27,7 +27,7 @@ #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ -#define BCMA_CC_FLASHT_NAND 0x00000300 /* NAND flash */ +#define BCMA_CC_FLASHT_NFLASH 0x00000200 /* NAND flash */ #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ #define BCMA_PLLTYPE_NONE 0x00000000 diff --git a/trunk/include/linux/ieee80211.h b/trunk/include/linux/ieee80211.h index 7e8a498efe6d..11c8bc87fdcb 100644 --- a/trunk/include/linux/ieee80211.h +++ b/trunk/include/linux/ieee80211.h @@ -151,11 +151,6 @@ /* Mesh Control 802.11s */ #define IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT 0x0100 -/* Mesh Power Save Level */ -#define IEEE80211_QOS_CTL_MESH_PS_LEVEL 0x0200 -/* Mesh Receiver Service Period Initiated */ -#define IEEE80211_QOS_CTL_RSPI 0x0400 - /* U-APSD queue for WMM IEs sent by AP */ #define IEEE80211_WMM_IE_AP_QOSINFO_UAPSD (1<<7) #define IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK 0x0f @@ -680,14 +675,11 @@ struct ieee80211_meshconf_ie { * @IEEE80211_MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs * @IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure * is ongoing - * @IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL: STA is in deep sleep mode or has - * neighbors in deep sleep mode */ enum mesh_config_capab_flags { IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS = 0x01, IEEE80211_MESHCONF_CAPAB_FORWARDING = 0x08, IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING = 0x20, - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL = 0x40, }; /** diff --git a/trunk/include/linux/platform_data/microread.h b/trunk/include/linux/platform_data/microread.h deleted file mode 100644 index cfda59b226ee..000000000000 --- a/trunk/include/linux/platform_data/microread.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Driver include for the PN544 NFC chip. - * - * Copyright (C) 2011 Tieto Poland - * Copyright (C) 2012 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _MICROREAD_H -#define _MICROREAD_H - -#include - -#define MICROREAD_DRIVER_NAME "microread" - -/* board config platform data for microread */ -struct microread_nfc_platform_data { - unsigned int rst_gpio; - unsigned int irq_gpio; - unsigned int ioh_gpio; -}; - -#endif /* _MICROREAD_H */ diff --git a/trunk/include/linux/wl12xx.h b/trunk/include/linux/wl12xx.h index a54fe82e704b..0d6373195d32 100644 --- a/trunk/include/linux/wl12xx.h +++ b/trunk/include/linux/wl12xx.h @@ -24,8 +24,6 @@ #ifndef _LINUX_WL12XX_H #define _LINUX_WL12XX_H -#include - /* Reference clock values */ enum { WL12XX_REFCLOCK_19 = 0, /* 19.2 MHz */ @@ -57,17 +55,17 @@ struct wl12xx_platform_data { int board_tcxo_clock; unsigned long platform_quirks; bool pwr_in_suspend; + + struct wl1271_if_operations *ops; }; /* Platform does not support level trigger interrupts */ #define WL12XX_PLATFORM_QUIRK_EDGE_IRQ BIT(0) -#ifdef CONFIG_WILINK_PLATFORM_DATA +#ifdef CONFIG_WL12XX_PLATFORM_DATA int wl12xx_set_platform_data(const struct wl12xx_platform_data *data); -struct wl12xx_platform_data *wl12xx_get_platform_data(void); - #else static inline @@ -76,12 +74,8 @@ int wl12xx_set_platform_data(const struct wl12xx_platform_data *data) return -ENOSYS; } -static inline -struct wl12xx_platform_data *wl12xx_get_platform_data(void) -{ - return ERR_PTR(-ENODATA); -} - #endif +struct wl12xx_platform_data *wl12xx_get_platform_data(void); + #endif diff --git a/trunk/include/net/bluetooth/hci_core.h b/trunk/include/net/bluetooth/hci_core.h index 90cf75afcb02..bcf8ffe2a843 100644 --- a/trunk/include/net/bluetooth/hci_core.h +++ b/trunk/include/net/bluetooth/hci_core.h @@ -86,7 +86,6 @@ struct bdaddr_list { struct bt_uuid { struct list_head list; u8 uuid[16]; - u8 size; u8 svc_hint; }; diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 77686ca28948..36e076e374d2 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -535,7 +535,7 @@ struct mac_address { * struct cfg80211_acl_data - Access control list data * * @acl_policy: ACL policy to be applied on the station's - * entry specified by mac_addr + entry specified by mac_addr * @n_acl_entries: Number of MAC address entries passed * @mac_addrs: List of MAC addresses of stations to be used for ACL */ @@ -666,16 +666,14 @@ struct station_parameters { * @STATION_INFO_INACTIVE_TIME: @inactive_time filled * @STATION_INFO_RX_BYTES: @rx_bytes filled * @STATION_INFO_TX_BYTES: @tx_bytes filled - * @STATION_INFO_RX_BYTES64: @rx_bytes filled with 64-bit value - * @STATION_INFO_TX_BYTES64: @tx_bytes filled with 64-bit value * @STATION_INFO_LLID: @llid filled * @STATION_INFO_PLID: @plid filled * @STATION_INFO_PLINK_STATE: @plink_state filled * @STATION_INFO_SIGNAL: @signal filled * @STATION_INFO_TX_BITRATE: @txrate fields are filled * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) - * @STATION_INFO_RX_PACKETS: @rx_packets filled with 32-bit value - * @STATION_INFO_TX_PACKETS: @tx_packets filled with 32-bit value + * @STATION_INFO_RX_PACKETS: @rx_packets filled + * @STATION_INFO_TX_PACKETS: @tx_packets filled * @STATION_INFO_TX_RETRIES: @tx_retries filled * @STATION_INFO_TX_FAILED: @tx_failed filled * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled @@ -716,8 +714,6 @@ enum station_info_flags { STATION_INFO_LOCAL_PM = 1<<21, STATION_INFO_PEER_PM = 1<<22, STATION_INFO_NONPEER_PM = 1<<23, - STATION_INFO_RX_BYTES64 = 1<<24, - STATION_INFO_TX_BYTES64 = 1<<25, }; /** @@ -839,8 +835,8 @@ struct station_info { u32 filled; u32 connected_time; u32 inactive_time; - u64 rx_bytes; - u64 tx_bytes; + u32 rx_bytes; + u32 tx_bytes; u16 llid; u16 plid; u8 plink_state; @@ -1226,7 +1222,6 @@ struct cfg80211_match_set { * @n_match_sets: number of match sets * @wiphy: the wiphy this was for * @dev: the interface - * @scan_start: start time of the scheduled scan * @channels: channels to scan * @rssi_thold: don't report scan results below this threshold (in s32 dBm) */ @@ -1266,13 +1261,11 @@ enum cfg80211_signal_type { /** * struct cfg80211_bss_ie_data - BSS entry IE data - * @tsf: TSF contained in the frame that carried these IEs * @rcu_head: internal use, for freeing * @len: length of the IEs * @data: IE data */ struct cfg80211_bss_ies { - u64 tsf; struct rcu_head rcu_head; int len; u8 data[]; @@ -1286,32 +1279,29 @@ struct cfg80211_bss_ies { * * @channel: channel this BSS is on * @bssid: BSSID of the BSS + * @tsf: timestamp of last received update * @beacon_interval: the beacon interval as from the frame * @capability: the capability field in host byte order - * @ies: the information elements (Note that there is no guarantee that these - * are well-formed!); this is a pointer to either the beacon_ies or - * proberesp_ies depending on whether Probe Response frame has been - * received. It is always non-%NULL. + * @ies: the information elements (Note that there + * is no guarantee that these are well-formed!); this is a pointer to + * either the beacon_ies or proberesp_ies depending on whether Probe + * Response frame has been received * @beacon_ies: the information elements from the last Beacon frame - * (implementation note: if @hidden_beacon_bss is set this struct doesn't - * own the beacon_ies, but they're just pointers to the ones from the - * @hidden_beacon_bss struct) * @proberesp_ies: the information elements from the last Probe Response frame - * @hidden_beacon_bss: in case this BSS struct represents a probe response from - * a BSS that hides the SSID in its beacon, this points to the BSS struct - * that holds the beacon data. @beacon_ies is still valid, of course, and - * points to the same data as hidden_beacon_bss->beacon_ies in that case. * @signal: signal strength value (type depends on the wiphy's signal_type) + * @free_priv: function pointer to free private data * @priv: private area for driver use, has at least wiphy->bss_priv_size bytes */ struct cfg80211_bss { + u64 tsf; + struct ieee80211_channel *channel; const struct cfg80211_bss_ies __rcu *ies; const struct cfg80211_bss_ies __rcu *beacon_ies; const struct cfg80211_bss_ies __rcu *proberesp_ies; - struct cfg80211_bss *hidden_beacon_bss; + void (*free_priv)(struct cfg80211_bss *bss); s32 signal; @@ -1413,8 +1403,6 @@ struct cfg80211_assoc_request { * @ie: Extra IEs to add to Deauthentication frame or %NULL * @ie_len: Length of ie buffer in octets * @reason_code: The reason code for the deauthentication - * @local_state_change: if set, change local state only and - * do not set a deauth frame */ struct cfg80211_deauth_request { const u8 *bssid; @@ -1608,32 +1596,6 @@ struct cfg80211_wowlan { int n_patterns; }; -/** - * struct cfg80211_wowlan_wakeup - wakeup report - * @disconnect: woke up by getting disconnected - * @magic_pkt: woke up by receiving magic packet - * @gtk_rekey_failure: woke up by GTK rekey failure - * @eap_identity_req: woke up by EAP identity request packet - * @four_way_handshake: woke up by 4-way handshake - * @rfkill_release: woke up by rfkill being released - * @pattern_idx: pattern that caused wakeup, -1 if not due to pattern - * @packet_present_len: copied wakeup packet data - * @packet_len: original wakeup packet length - * @packet: The packet causing the wakeup, if any. - * @packet_80211: For pattern match, magic packet and other data - * frame triggers an 802.3 frame should be reported, for - * disconnect due to deauth 802.11 frame. This indicates which - * it is. - */ -struct cfg80211_wowlan_wakeup { - bool disconnect, magic_pkt, gtk_rekey_failure, - eap_identity_req, four_way_handshake, - rfkill_release, packet_80211; - s32 pattern_idx; - u32 packet_present_len, packet_len; - const void *packet; -}; - /** * struct cfg80211_gtk_rekey_data - rekey data * @kek: key encryption key @@ -2640,6 +2602,7 @@ struct cfg80211_cached_keys; * the user-set AP, monitor and WDS channel * @preset_chan: (private) Used by the internal configuration code to * track the channel to be used for AP later + * @preset_chantype: (private) the corresponding channel type * @bssid: (private) Used by the internal configuration code * @ssid: (private) Used by the internal configuration code * @ssid_len: (private) Used by the internal configuration code @@ -3174,23 +3137,25 @@ cfg80211_get_ibss(struct wiphy *wiphy, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); } +struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg); /** * cfg80211_ref_bss - reference BSS struct - * @wiphy: the wiphy this BSS struct belongs to * @bss: the BSS struct to reference * * Increments the refcount of the given BSS struct. */ -void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); +void cfg80211_ref_bss(struct cfg80211_bss *bss); /** * cfg80211_put_bss - unref BSS struct - * @wiphy: the wiphy this BSS struct belongs to * @bss: the BSS struct * * Decrements the refcount of the given BSS struct. */ -void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); +void cfg80211_put_bss(struct cfg80211_bss *bss); /** * cfg80211_unlink_bss - unlink BSS from internal data structures @@ -3887,21 +3852,6 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len, enum ieee80211_p2p_attr_id attr, u8 *buf, unsigned int bufsize); -/** - * cfg80211_report_wowlan_wakeup - report wakeup from WoWLAN - * @wdev: the wireless device reporting the wakeup - * @wakeup: the wakeup report - * @gfp: allocation flags - * - * This function reports that the given device woke up. If it - * caused the wakeup, report the reason(s), otherwise you may - * pass %NULL as the @wakeup parameter to advertise that something - * else caused the wakeup. - */ -void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp); - /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/trunk/include/net/mac80211.h b/trunk/include/net/mac80211.h index 0eaa9092364b..5c98d654fc75 100644 --- a/trunk/include/net/mac80211.h +++ b/trunk/include/net/mac80211.h @@ -208,8 +208,6 @@ struct ieee80211_chanctx_conf { * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS) * changed (currently only in P2P client mode, GO mode will be later) - * @BSS_CHANGED_DTIM_PERIOD: the DTIM period value was changed (set when - * it becomes valid, managed mode only) */ enum ieee80211_bss_change { BSS_CHANGED_ASSOC = 1<<0, @@ -232,7 +230,6 @@ enum ieee80211_bss_change { BSS_CHANGED_PS = 1<<17, BSS_CHANGED_TXPOWER = 1<<18, BSS_CHANGED_P2P_PS = 1<<19, - BSS_CHANGED_DTIM_PERIOD = 1<<20, /* when adding here, make sure to change ieee80211_reconfig */ }; @@ -274,19 +271,13 @@ enum ieee80211_rssi_event { * if the hardware cannot handle this it must set the * IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag * @dtim_period: num of beacons before the next DTIM, for beaconing, - * valid in station mode only if after the driver was notified - * with the %BSS_CHANGED_DTIM_PERIOD flag, will be non-zero then. + * valid in station mode only while @assoc is true and if also + * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf + * @ps_dtim_period) * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old - * as it may have been received during scanning long ago). If the - * HW flag %IEEE80211_HW_TIMING_BEACON_ONLY is set, then this can - * only come from a beacon, but might not become valid until after - * association when a beacon is received (which is notified with the - * %BSS_CHANGED_DTIM flag.) + * as it may have been received during scanning long ago) * @sync_device_ts: the device timestamp corresponding to the sync_tsf, * the driver/device can use this to calculate synchronisation - * (see @sync_tsf) - * @sync_dtim_count: Only valid when %IEEE80211_HW_TIMING_BEACON_ONLY - * is requested, see @sync_tsf/@sync_device_ts. * @beacon_int: beacon interval * @assoc_capability: capabilities taken from assoc resp * @basic_rates: bitmap of basic rates, each bit stands for an @@ -338,7 +329,6 @@ struct ieee80211_bss_conf { u16 assoc_capability; u64 sync_tsf; u32 sync_device_ts; - u8 sync_dtim_count; u32 basic_rates; int mcast_rate[IEEE80211_NUM_BANDS]; u16 ht_operation_mode; @@ -399,9 +389,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: internal to mac80211, can be * set by rate control algorithms to indicate probe rate, will * be cleared for fragmented frames (except on the last fragment) - * @IEEE80211_TX_INTFL_OFFCHAN_TX_OK: Internal to mac80211. Used to indicate - * that a frame can be transmitted while the queues are stopped for - * off-channel operation. * @IEEE80211_TX_INTFL_NEED_TXPROCESSING: completely internal to mac80211, * used to indicate that a pending frame requires TX processing before * it can be sent out. @@ -419,9 +406,6 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted * after TX status because the destination was asleep, it must not * be modified again (no seqno assignment, crypto, etc.) - * @IEEE80211_TX_INTFL_MLME_CONN_TX: This frame was transmitted by the MLME - * code for connection establishment, this indicates that its status - * should kick the MLME state machine. * @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211 * MLME command (internal to mac80211 to figure out whether to send TX * status to user space) @@ -467,14 +451,13 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_AMPDU = BIT(10), IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(11), IEEE80211_TX_CTL_RATE_CTRL_PROBE = BIT(12), - IEEE80211_TX_INTFL_OFFCHAN_TX_OK = BIT(13), IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14), IEEE80211_TX_INTFL_RETRIED = BIT(15), IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), IEEE80211_TX_CTL_NO_PS_BUFFER = BIT(17), IEEE80211_TX_CTL_MORE_FRAMES = BIT(18), IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19), - IEEE80211_TX_INTFL_MLME_CONN_TX = BIT(20), + /* hole at 20, use later */ IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21), IEEE80211_TX_CTL_LDPC = BIT(22), IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24), @@ -1345,9 +1328,9 @@ struct ieee80211_tx_control { * When this flag is set, signaling beacon-loss will cause an immediate * change to disassociated state. * - * @IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC: - * This device needs to get data from beacon before association (i.e. - * dtim_period). + * @IEEE80211_HW_NEED_DTIM_PERIOD: + * This device needs to know the DTIM period for the BSS before + * associating. * * @IEEE80211_HW_SUPPORTS_PER_STA_GTK: The device's crypto engine supports * per-station GTKs as used by IBSS RSN or during fast transition. If @@ -1367,6 +1350,10 @@ struct ieee80211_tx_control { * setup strictly in HW. mac80211 should not attempt to do this in * software. * + * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while + * being idle (i.e. mac80211 doesn't have to go idle-off during the + * the scan). + * * @IEEE80211_HW_WANT_MONITOR_VIF: The driver would like to be informed of * a virtual monitor interface when monitor interfaces are the only * active interfaces. @@ -1380,8 +1367,9 @@ struct ieee80211_tx_control { * P2P Interface. This will be honoured even if more than one interface * is supported. * - * @IEEE80211_HW_TIMING_BEACON_ONLY: Use sync timing from beacon frames - * only, to allow getting TBTT of a DTIM beacon. + * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session + * should be tear down once BAR frame will not be acked. + * */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1391,7 +1379,7 @@ enum ieee80211_hw_flags { IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE = 1<<4, IEEE80211_HW_SIGNAL_UNSPEC = 1<<5, IEEE80211_HW_SIGNAL_DBM = 1<<6, - IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC = 1<<7, + IEEE80211_HW_NEED_DTIM_PERIOD = 1<<7, IEEE80211_HW_SPECTRUM_MGMT = 1<<8, IEEE80211_HW_AMPDU_AGGREGATION = 1<<9, IEEE80211_HW_SUPPORTS_PS = 1<<10, @@ -1408,8 +1396,9 @@ enum ieee80211_hw_flags { IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, IEEE80211_HW_AP_LINK_PS = 1<<22, IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, + IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24, IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25, - IEEE80211_HW_TIMING_BEACON_ONLY = 1<<26, + IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26, }; /** @@ -1694,6 +1683,15 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS * enabled whenever user has enabled powersave. * + * Some hardware need to toggle a single shared antenna between WLAN and + * Bluetooth to facilitate co-existence. These types of hardware set + * limitations on the use of host controlled dynamic powersave whenever there + * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the + * driver may request temporarily going into full power save, in order to + * enable toggling the antenna between BT and WLAN. If the driver requests + * disabling dynamic powersave, the @dynamic_ps_timeout value will be + * temporarily set to zero until the driver re-enables dynamic powersave. + * * Driver informs U-APSD client support by enabling * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS @@ -2169,18 +2167,6 @@ enum ieee80211_rate_control_changed { * MAC address of the device going away. * Hence, this callback must be implemented. It can sleep. * - * @add_interface_debugfs: Drivers can use this callback to add debugfs files - * when a vif is added to mac80211. This callback and - * @remove_interface_debugfs should be within a CONFIG_MAC80211_DEBUGFS - * conditional. @remove_interface_debugfs must be provided for cleanup. - * This callback can sleep. - * - * @remove_interface_debugfs: Remove the debugfs files which were added using - * @add_interface_debugfs. This callback must remove all debugfs entries - * that were added because mac80211 only removes interface debugfs when the - * interface is destroyed, not when it is removed from the driver. - * This callback can sleep. - * * @config: Handler for configuration requests. IEEE 802.11 code calls this * function to change hardware configuration, e.g., channel. * This function should never fail but returns a negative error code @@ -2594,12 +2580,6 @@ struct ieee80211_ops { struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir); - void (*add_interface_debugfs)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct dentry *dir); - void (*remove_interface_debugfs)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct dentry *dir); #endif void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum sta_notify_cmd, struct ieee80211_sta *sta); @@ -3897,8 +3877,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); * When beacon filtering is enabled with %IEEE80211_VIF_BEACON_FILTER, and * %IEEE80211_CONF_PS and %IEEE80211_HW_CONNECTION_MONITOR are set, the driver * needs to inform if the connection to the AP has been lost. - * The function may also be called if the connection needs to be terminated - * for some other reason, even if %IEEE80211_HW_CONNECTION_MONITOR isn't set. * * This function will cause immediate change to disassociated state, * without connection recovery attempts. @@ -3928,6 +3906,36 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif); */ void ieee80211_resume_disconnect(struct ieee80211_vif *vif); +/** + * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * + * Some hardware require full power save to manage simultaneous BT traffic + * on the WLAN frequency. Full PSM is required periodically, whenever there are + * burst of BT traffic. The hardware gets information of BT traffic via + * hardware co-existence lines, and consequentially requests mac80211 to + * (temporarily) enter full psm. + * This function will only temporarily disable dynamic PS, not enable PSM if + * it was not already enabled. + * The driver must make sure to re-enable dynamic PS using + * ieee80211_enable_dyn_ps() if the driver has disabled it. + * + */ +void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif); + +/** + * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled + * + * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * + * This function restores dynamic PS after being temporarily disabled via + * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must + * be coupled with an eventual call to this function. + * + */ +void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif); + /** * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring * rssi threshold triggered @@ -4203,16 +4211,4 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); */ int ieee80211_ave_rssi(struct ieee80211_vif *vif); -/** - * ieee80211_report_wowlan_wakeup - report WoWLAN wakeup - * @vif: virtual interface - * @wakeup: wakeup reason(s) - * @gfp: allocation flags - * - * See cfg80211_report_wowlan_wakeup(). - */ -void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp); - #endif /* MAC80211_H */ diff --git a/trunk/include/uapi/linux/nl80211.h b/trunk/include/uapi/linux/nl80211.h index 9a2ecdc4136c..5b7dbc1ea966 100644 --- a/trunk/include/uapi/linux/nl80211.h +++ b/trunk/include/uapi/linux/nl80211.h @@ -513,12 +513,6 @@ * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For * more background information, see * http://wireless.kernel.org/en/users/Documentation/WoWLAN. - * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification - * from the driver reporting the wakeup reason. In this case, the - * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason - * for the wakeup, if it was caused by wireless. If it is not present - * in the wakeup notification, the wireless device didn't cause the - * wakeup but reports that it was woken up. * * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver * the necessary information for supporting GTK rekey offload. This @@ -1857,8 +1851,6 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @NL80211_STA_INFO_RX_BYTES64: total received bytes (u64, from this station) - * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (u64, to this station) * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute * containing info as possible, see &enum nl80211_rate_info @@ -1911,8 +1903,6 @@ enum nl80211_sta_info { NL80211_STA_INFO_LOCAL_PM, NL80211_STA_INFO_PEER_PM, NL80211_STA_INFO_NONPEER_PM, - NL80211_STA_INFO_RX_BYTES64, - NL80211_STA_INFO_TX_BYTES64, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -2957,10 +2947,6 @@ struct nl80211_wowlan_pattern_support { * * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute * carrying a &struct nl80211_wowlan_pattern_support. - * - * When reporting wakeup. it is a u32 attribute containing the 0-based - * index of the pattern that caused the wakeup, in the patterns passed - * to the kernel when configuring. * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be * used when setting, used only to indicate that GTK rekeying is supported * by the device (flag) @@ -2971,25 +2957,8 @@ struct nl80211_wowlan_pattern_support { * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released * (on devices that have rfkill in the device) (flag) - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains - * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame - * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN - * attribute contains the original length. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11 - * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 - * attribute if the packet was truncated somewhere. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the - * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may - * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute - * contains the original length. - * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3 - * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 - * attribute if the packet was truncated somewhere. * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number - * - * These nested attributes are used to configure the wakeup triggers and - * to report the wakeup reason(s). */ enum nl80211_wowlan_triggers { __NL80211_WOWLAN_TRIG_INVALID, @@ -3002,10 +2971,6 @@ enum nl80211_wowlan_triggers { NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, NL80211_WOWLAN_TRIG_RFKILL_RELEASE, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023, - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN, /* keep last */ NUM_NL80211_WOWLAN_TRIG, diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 22e77a786545..d13ce99b410a 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -1183,10 +1183,14 @@ static void hci_discov_off(struct work_struct *work) int hci_uuids_clear(struct hci_dev *hdev) { - struct bt_uuid *uuid, *tmp; + struct list_head *p, *n; + + list_for_each_safe(p, n, &hdev->uuids) { + struct bt_uuid *uuid; - list_for_each_entry_safe(uuid, tmp, &hdev->uuids, list) { - list_del(&uuid->list); + uuid = list_entry(p, struct bt_uuid, list); + + list_del(p); kfree(uuid); } diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 477726a63512..0a4fd642d4b9 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -3988,6 +3988,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) void *ptr = &skb->data[1]; s8 rssi; + hci_dev_lock(hdev); + while (num_reports--) { struct hci_ev_le_advertising_info *ev = ptr; @@ -3997,6 +3999,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) ptr += sizeof(*ev) + ev->length + 1; } + + hci_dev_unlock(hdev); } static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) diff --git a/trunk/net/bluetooth/mgmt.c b/trunk/net/bluetooth/mgmt.c index 39395c7144aa..e7f944f52ff2 100644 --- a/trunk/net/bluetooth/mgmt.c +++ b/trunk/net/bluetooth/mgmt.c @@ -35,7 +35,7 @@ bool enable_hs; #define MGMT_VERSION 1 -#define MGMT_REVISION 3 +#define MGMT_REVISION 2 static const u16 mgmt_commands[] = { MGMT_OP_READ_INDEX_LIST, @@ -435,117 +435,35 @@ static u32 get_current_settings(struct hci_dev *hdev) #define PNP_INFO_SVCLASS_ID 0x1200 -static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) -{ - u8 *ptr = data, *uuids_start = NULL; - struct bt_uuid *uuid; - - if (len < 4) - return ptr; - - list_for_each_entry(uuid, &hdev->uuids, list) { - u16 uuid16; - - if (uuid->size != 16) - continue; - - uuid16 = get_unaligned_le16(&uuid->uuid[12]); - if (uuid16 < 0x1100) - continue; - - if (uuid16 == PNP_INFO_SVCLASS_ID) - continue; - - if (!uuids_start) { - uuids_start = ptr; - uuids_start[0] = 1; - uuids_start[1] = EIR_UUID16_ALL; - ptr += 2; - } - - /* Stop if not enough space to put next UUID */ - if ((ptr - data) + sizeof(u16) > len) { - uuids_start[1] = EIR_UUID16_SOME; - break; - } - - *ptr++ = (uuid16 & 0x00ff); - *ptr++ = (uuid16 & 0xff00) >> 8; - uuids_start[0] += sizeof(uuid16); - } - - return ptr; -} +static u8 bluetooth_base_uuid[] = { + 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; -static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) +static u16 get_uuid16(u8 *uuid128) { - u8 *ptr = data, *uuids_start = NULL; - struct bt_uuid *uuid; - - if (len < 6) - return ptr; - - list_for_each_entry(uuid, &hdev->uuids, list) { - if (uuid->size != 32) - continue; - - if (!uuids_start) { - uuids_start = ptr; - uuids_start[0] = 1; - uuids_start[1] = EIR_UUID32_ALL; - ptr += 2; - } - - /* Stop if not enough space to put next UUID */ - if ((ptr - data) + sizeof(u32) > len) { - uuids_start[1] = EIR_UUID32_SOME; - break; - } + u32 val; + int i; - memcpy(ptr, &uuid->uuid[12], sizeof(u32)); - ptr += sizeof(u32); - uuids_start[0] += sizeof(u32); + for (i = 0; i < 12; i++) { + if (bluetooth_base_uuid[i] != uuid128[i]) + return 0; } - return ptr; -} - -static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) -{ - u8 *ptr = data, *uuids_start = NULL; - struct bt_uuid *uuid; - - if (len < 18) - return ptr; - - list_for_each_entry(uuid, &hdev->uuids, list) { - if (uuid->size != 128) - continue; - - if (!uuids_start) { - uuids_start = ptr; - uuids_start[0] = 1; - uuids_start[1] = EIR_UUID128_ALL; - ptr += 2; - } - - /* Stop if not enough space to put next UUID */ - if ((ptr - data) + 16 > len) { - uuids_start[1] = EIR_UUID128_SOME; - break; - } - - memcpy(ptr, uuid->uuid, 16); - ptr += 16; - uuids_start[0] += 16; - } + val = get_unaligned_le32(&uuid128[12]); + if (val > 0xffff) + return 0; - return ptr; + return (u16) val; } static void create_eir(struct hci_dev *hdev, u8 *data) { u8 *ptr = data; + u16 eir_len = 0; + u16 uuid16_list[HCI_MAX_EIR_LENGTH / sizeof(u16)]; + int i, truncated = 0; + struct bt_uuid *uuid; size_t name_len; name_len = strlen(hdev->dev_name); @@ -563,6 +481,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) memcpy(ptr + 2, hdev->dev_name, name_len); + eir_len += (name_len + 2); ptr += (name_len + 2); } @@ -571,6 +490,7 @@ static void create_eir(struct hci_dev *hdev, u8 *data) ptr[1] = EIR_TX_POWER; ptr[2] = (u8) hdev->inq_tx_power; + eir_len += 3; ptr += 3; } @@ -583,12 +503,60 @@ static void create_eir(struct hci_dev *hdev, u8 *data) put_unaligned_le16(hdev->devid_product, ptr + 6); put_unaligned_le16(hdev->devid_version, ptr + 8); + eir_len += 10; ptr += 10; } - ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); - ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); - ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data)); + memset(uuid16_list, 0, sizeof(uuid16_list)); + + /* Group all UUID16 types */ + list_for_each_entry(uuid, &hdev->uuids, list) { + u16 uuid16; + + uuid16 = get_uuid16(uuid->uuid); + if (uuid16 == 0) + return; + + if (uuid16 < 0x1100) + continue; + + if (uuid16 == PNP_INFO_SVCLASS_ID) + continue; + + /* Stop if not enough space to put next UUID */ + if (eir_len + 2 + sizeof(u16) > HCI_MAX_EIR_LENGTH) { + truncated = 1; + break; + } + + /* Check for duplicates */ + for (i = 0; uuid16_list[i] != 0; i++) + if (uuid16_list[i] == uuid16) + break; + + if (uuid16_list[i] == 0) { + uuid16_list[i] = uuid16; + eir_len += sizeof(u16); + } + } + + if (uuid16_list[0] != 0) { + u8 *length = ptr; + + /* EIR Data type */ + ptr[1] = truncated ? EIR_UUID16_SOME : EIR_UUID16_ALL; + + ptr += 2; + eir_len += 2; + + for (i = 0; uuid16_list[i] != 0; i++) { + *ptr++ = (uuid16_list[i] & 0x00ff); + *ptr++ = (uuid16_list[i] & 0xff00) >> 8; + } + + /* EIR Data length */ + *length = (i * sizeof(u16)) + 1; + } } static int update_eir(struct hci_dev *hdev) @@ -760,9 +728,13 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, void *data), void *data) { - struct pending_cmd *cmd, *tmp; + struct list_head *p, *n; + + list_for_each_safe(p, n, &hdev->mgmt_pending) { + struct pending_cmd *cmd; + + cmd = list_entry(p, struct pending_cmd, list); - list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) { if (opcode > 0 && cmd->opcode != opcode) continue; @@ -1332,25 +1304,6 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) return err; } -static const u8 bluetooth_base_uuid[] = { - 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, - 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -static u8 get_uuid_size(const u8 *uuid) -{ - u32 val; - - if (memcmp(uuid, bluetooth_base_uuid, 12)) - return 128; - - val = get_unaligned_le32(&uuid[12]); - if (val > 0xffff) - return 32; - - return 16; -} - static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_cp_add_uuid *cp = data; @@ -1376,9 +1329,8 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) memcpy(uuid->uuid, cp->uuid, 16); uuid->svc_hint = cp->svc_hint; - uuid->size = get_uuid_size(cp->uuid); - list_add_tail(&uuid->list, &hdev->uuids); + list_add(&uuid->list, &hdev->uuids); err = update_class(hdev); if (err < 0) @@ -1422,7 +1374,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, { struct mgmt_cp_remove_uuid *cp = data; struct pending_cmd *cmd; - struct bt_uuid *match, *tmp; + struct list_head *p, *n; u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int err, found; @@ -1450,7 +1402,9 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, found = 0; - list_for_each_entry_safe(match, tmp, &hdev->uuids, list) { + list_for_each_safe(p, n, &hdev->uuids) { + struct bt_uuid *match = list_entry(p, struct bt_uuid, list); + if (memcmp(match->uuid, cp->uuid, 16) != 0) continue; @@ -3069,8 +3023,6 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); if (powered) { - u8 link_sec; - if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && !lmp_host_ssp_capable(hdev)) { u8 ssp = 1; @@ -3094,11 +3046,6 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) sizeof(cp), &cp); } - link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); - if (link_sec != test_bit(HCI_AUTH, &hdev->flags)) - hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, - sizeof(link_sec), &link_sec); - if (lmp_bredr_capable(hdev)) { set_bredr_scan(hdev); update_class(hdev); diff --git a/trunk/net/bluetooth/sco.c b/trunk/net/bluetooth/sco.c index b5178d62064e..57f250c20e39 100644 --- a/trunk/net/bluetooth/sco.c +++ b/trunk/net/bluetooth/sco.c @@ -900,6 +900,8 @@ static void sco_conn_ready(struct sco_conn *conn) BT_DBG("conn %p", conn); + sco_conn_lock(conn); + if (sk) { sco_sock_clear_timer(sk); bh_lock_sock(sk); @@ -907,13 +909,9 @@ static void sco_conn_ready(struct sco_conn *conn) sk->sk_state_change(sk); bh_unlock_sock(sk); } else { - sco_conn_lock(conn); - parent = sco_get_sock_listen(conn->src); - if (!parent) { - sco_conn_unlock(conn); - return; - } + if (!parent) + goto done; bh_lock_sock(parent); @@ -921,8 +919,7 @@ static void sco_conn_ready(struct sco_conn *conn) BTPROTO_SCO, GFP_ATOMIC); if (!sk) { bh_unlock_sock(parent); - sco_conn_unlock(conn); - return; + goto done; } sco_sock_init(sk, parent); @@ -942,9 +939,10 @@ static void sco_conn_ready(struct sco_conn *conn) parent->sk_data_ready(parent, 1); bh_unlock_sock(parent); - - sco_conn_unlock(conn); } + +done: + sco_conn_unlock(conn); } /* ----- SCO interface with lower layer (HCI) ----- */ diff --git a/trunk/net/mac80211/Kconfig b/trunk/net/mac80211/Kconfig index 0ecf947ad378..b4ecf267a34b 100644 --- a/trunk/net/mac80211/Kconfig +++ b/trunk/net/mac80211/Kconfig @@ -258,17 +258,6 @@ config MAC80211_MESH_SYNC_DEBUG Do not select this option. -config MAC80211_MESH_PS_DEBUG - bool "Verbose mesh powersave debugging" - depends on MAC80211_DEBUG_MENU - depends on MAC80211_MESH - ---help--- - Selecting this option causes mac80211 to print out very verbose mesh - powersave debugging messages (when mac80211 is taking part in a - mesh network). - - Do not select this option. - config MAC80211_TDLS_DEBUG bool "Verbose TDLS debugging" depends on MAC80211_DEBUG_MENU diff --git a/trunk/net/mac80211/Makefile b/trunk/net/mac80211/Makefile index 9d7d840aac6d..4911202334d9 100644 --- a/trunk/net/mac80211/Makefile +++ b/trunk/net/mac80211/Makefile @@ -39,8 +39,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ mesh_pathtbl.o \ mesh_plink.o \ mesh_hwmp.o \ - mesh_sync.o \ - mesh_ps.o + mesh_sync.o mac80211-$(CONFIG_PM) += pm.o diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index e3dec80cf617..661b878bd19c 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -492,10 +492,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) #ifdef CONFIG_MAC80211_MESH sinfo->filled |= STATION_INFO_LLID | STATION_INFO_PLID | - STATION_INFO_PLINK_STATE | - STATION_INFO_LOCAL_PM | - STATION_INFO_PEER_PM | - STATION_INFO_NONPEER_PM; + STATION_INFO_PLINK_STATE; sinfo->llid = le16_to_cpu(sta->llid); sinfo->plid = le16_to_cpu(sta->plid); @@ -504,9 +501,6 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->filled |= STATION_INFO_T_OFFSET; sinfo->t_offset = sta->t_offset; } - sinfo->local_pm = sta->local_pm; - sinfo->peer_pm = sta->peer_pm; - sinfo->nonpeer_pm = sta->nonpeer_pm; #endif } @@ -933,7 +927,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, IEEE80211_CHANCTX_SHARED); if (err) return err; - ieee80211_vif_copy_chanctx_to_vlans(sdata, false); /* * Apply control port protocol, this allows us to @@ -1048,7 +1041,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf); skb_queue_purge(&sdata->u.ap.ps.bc_buf); - ieee80211_vif_copy_chanctx_to_vlans(sdata, true); ieee80211_vif_release_channel(sdata); return 0; @@ -1270,10 +1262,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, changed = mesh_plink_inc_estab_count( sdata); sta->plink_state = params->plink_state; - - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - sdata->u.mesh.mshcfg.power_mode); break; case NL80211_PLINK_LISTEN: case NL80211_PLINK_BLOCKED: @@ -1285,9 +1273,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, changed = mesh_plink_dec_estab_count( sdata); sta->plink_state = params->plink_state; - - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_local_status_update(sdata); break; default: /* nothing */ @@ -1304,9 +1289,6 @@ static int sta_apply_parameters(struct ieee80211_local *local, break; } } - - if (params->local_pm) - ieee80211_mps_set_sta_local_pm(sta, params->local_pm); #endif } @@ -1795,15 +1777,6 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy, if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask)) conf->dot11MeshHWMPconfirmationInterval = nconf->dot11MeshHWMPconfirmationInterval; - if (_chg_mesh_attr(NL80211_MESHCONF_POWER_MODE, mask)) { - conf->power_mode = nconf->power_mode; - ieee80211_mps_local_status_update(sdata); - } - if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask)) { - conf->dot11MeshAwakeWindowDuration = - nconf->dot11MeshAwakeWindowDuration; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); - } return 0; } @@ -2749,8 +2722,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, goto out_unlock; } - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN | - IEEE80211_TX_INTFL_OFFCHAN_TX_OK; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_TX_OFFCHAN; if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) IEEE80211_SKB_CB(skb)->hw_queue = local->hw.offchannel_tx_hw_queue; diff --git a/trunk/net/mac80211/chan.c b/trunk/net/mac80211/chan.c index 038f249966d6..1bfe0a8b19d2 100644 --- a/trunk/net/mac80211/chan.c +++ b/trunk/net/mac80211/chan.c @@ -91,10 +91,6 @@ ieee80211_new_chanctx(struct ieee80211_local *local, list_add_rcu(&ctx->list, &local->chanctx_list); - mutex_lock(&local->mtx); - ieee80211_recalc_idle(local); - mutex_unlock(&local->mtx); - return ctx; } @@ -114,10 +110,6 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, list_del_rcu(&ctx->list); kfree_rcu(ctx, rcu_head); - - mutex_lock(&local->mtx); - ieee80211_recalc_idle(local); - mutex_unlock(&local->mtx); } static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, @@ -136,8 +128,6 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, ctx->refcount++; ieee80211_recalc_txpower(sdata); - sdata->vif.bss_conf.idle = false; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); return 0; } @@ -185,9 +175,6 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, ctx->refcount--; rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); - sdata->vif.bss_conf.idle = true; - ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); - drv_unassign_vif_chanctx(local, sdata, ctx); if (ctx->refcount > 0) { @@ -211,6 +198,15 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) ctx = container_of(conf, struct ieee80211_chanctx, conf); + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan; + + /* for the VLAN list */ + ASSERT_RTNL(); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + rcu_assign_pointer(vlan->vif.chanctx_conf, NULL); + } + ieee80211_unassign_vif_chanctx(sdata, ctx); if (ctx->refcount == 0) ieee80211_free_chanctx(local, ctx); @@ -330,6 +326,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, goto out; } + if (sdata->vif.type == NL80211_IFTYPE_AP) { + struct ieee80211_sub_if_data *vlan; + + /* for the VLAN list */ + ASSERT_RTNL(); + list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) + rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf); + } + ieee80211_recalc_smps_chanctx(local, ctx); out: mutex_unlock(&local->chanctx_mtx); @@ -364,40 +369,6 @@ void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata) mutex_unlock(&local->chanctx_mtx); } -void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, - bool clear) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_sub_if_data *vlan; - struct ieee80211_chanctx_conf *conf; - - ASSERT_RTNL(); - - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP)) - return; - - mutex_lock(&local->chanctx_mtx); - - /* - * Check that conf exists, even when clearing this function - * must be called with the AP's channel context still there - * as it would otherwise cause VLANs to have an invalid - * channel context pointer for a while, possibly pointing - * to a channel context that has already been freed. - */ - conf = rcu_dereference_protected(sdata->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - WARN_ON(!conf); - - if (clear) - conf = NULL; - - list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) - rcu_assign_pointer(vlan->vif.chanctx_conf, conf); - - mutex_unlock(&local->chanctx_mtx); -} - void ieee80211_iter_chan_contexts_atomic( struct ieee80211_hw *hw, void (*iter)(struct ieee80211_hw *hw, diff --git a/trunk/net/mac80211/debug.h b/trunk/net/mac80211/debug.h index 4ccc5ed6237d..8f383a576016 100644 --- a/trunk/net/mac80211/debug.h +++ b/trunk/net/mac80211/debug.h @@ -44,12 +44,6 @@ #define MAC80211_MESH_SYNC_DEBUG 0 #endif -#ifdef CONFIG_MAC80211_MESH_PS_DEBUG -#define MAC80211_MESH_PS_DEBUG 1 -#else -#define MAC80211_MESH_PS_DEBUG 0 -#endif - #ifdef CONFIG_MAC80211_TDLS_DEBUG #define MAC80211_TDLS_DEBUG 1 #else @@ -157,10 +151,6 @@ do { \ _sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \ sdata, fmt, ##__VA_ARGS__) -#define mps_dbg(sdata, fmt, ...) \ - _sdata_dbg(MAC80211_MESH_PS_DEBUG, \ - sdata, fmt, ##__VA_ARGS__) - #define tdls_dbg(sdata, fmt, ...) \ _sdata_dbg(MAC80211_TDLS_DEBUG, \ sdata, fmt, ##__VA_ARGS__) diff --git a/trunk/net/mac80211/debugfs.c b/trunk/net/mac80211/debugfs.c index b0e32d628114..466f4b45dd94 100644 --- a/trunk/net/mac80211/debugfs.c +++ b/trunk/net/mac80211/debugfs.c @@ -121,8 +121,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n"); if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) sf += snprintf(buf + sf, mxln - sf, "SIGNAL_DBM\n"); - if (local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC) - sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_BEFORE_ASSOC\n"); + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) + sf += snprintf(buf + sf, mxln - sf, "NEED_DTIM_PERIOD\n"); if (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT) sf += snprintf(buf + sf, mxln - sf, "SPECTRUM_MGMT\n"); if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) @@ -151,6 +151,8 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf, sf += snprintf(buf + sf, mxln - sf, "AP_LINK_PS\n"); if (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW) sf += snprintf(buf + sf, mxln - sf, "TX_AMPDU_SETUP_IN_HW\n"); + if (local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE) + sf += snprintf(buf + sf, mxln - sf, "SCAN_WHILE_IDLE\n"); rv = simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); kfree(buf); diff --git a/trunk/net/mac80211/debugfs_netdev.c b/trunk/net/mac80211/debugfs_netdev.c index 059bbb82e84f..cbde5cc49a40 100644 --- a/trunk/net/mac80211/debugfs_netdev.c +++ b/trunk/net/mac80211/debugfs_netdev.c @@ -515,9 +515,6 @@ IEEE80211_IF_FILE(dot11MeshHWMProotInterval, u.mesh.mshcfg.dot11MeshHWMProotInterval, DEC); IEEE80211_IF_FILE(dot11MeshHWMPconfirmationInterval, u.mesh.mshcfg.dot11MeshHWMPconfirmationInterval, DEC); -IEEE80211_IF_FILE(power_mode, u.mesh.mshcfg.power_mode, DEC); -IEEE80211_IF_FILE(dot11MeshAwakeWindowDuration, - u.mesh.mshcfg.dot11MeshAwakeWindowDuration, DEC); #endif #define DEBUGFS_ADD_MODE(name, mode) \ @@ -623,8 +620,6 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata) MESHPARAMS_ADD(dot11MeshHWMPactivePathToRootTimeout); MESHPARAMS_ADD(dot11MeshHWMProotInterval); MESHPARAMS_ADD(dot11MeshHWMPconfirmationInterval); - MESHPARAMS_ADD(power_mode); - MESHPARAMS_ADD(dot11MeshAwakeWindowDuration); #undef MESHPARAMS_ADD } #endif diff --git a/trunk/net/mac80211/debugfs_sta.c b/trunk/net/mac80211/debugfs_sta.c index c7591f73dbc3..6fb1168b9f16 100644 --- a/trunk/net/mac80211/debugfs_sta.c +++ b/trunk/net/mac80211/debugfs_sta.c @@ -65,7 +65,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : "" int res = scnprintf(buf, sizeof(buf), - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", TEST(AUTH), TEST(ASSOC), TEST(PS_STA), TEST(PS_DRIVER), TEST(AUTHORIZED), TEST(SHORT_PREAMBLE), @@ -74,8 +74,7 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf, TEST(UAPSD), TEST(SP), TEST(TDLS_PEER), TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT), TEST(INSERTED), TEST(RATE_CONTROL), - TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER), - TEST(MPSP_RECIPIENT)); + TEST(TOFFSET_KNOWN)); #undef TEST return simple_read_from_buffer(userbuf, count, ppos, buf, res); } diff --git a/trunk/net/mac80211/driver-ops.h b/trunk/net/mac80211/driver-ops.h index 2b08b9982d06..434b3c4f31b5 100644 --- a/trunk/net/mac80211/driver-ops.h +++ b/trunk/net/mac80211/driver-ops.h @@ -528,43 +528,6 @@ static inline void drv_sta_remove_debugfs(struct ieee80211_local *local, local->ops->sta_remove_debugfs(&local->hw, &sdata->vif, sta, dir); } - -static inline -void drv_add_interface_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) -{ - might_sleep(); - - check_sdata_in_driver(sdata); - - if (!local->ops->add_interface_debugfs) - return; - - local->ops->add_interface_debugfs(&local->hw, &sdata->vif, - sdata->debugfs.dir); -} - -static inline -void drv_remove_interface_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) -{ - might_sleep(); - - check_sdata_in_driver(sdata); - - if (!local->ops->remove_interface_debugfs) - return; - - local->ops->remove_interface_debugfs(&local->hw, &sdata->vif, - sdata->debugfs.dir); -} -#else -static inline -void drv_add_interface_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) {} -static inline -void drv_remove_interface_debugfs(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata) {} #endif static inline __must_check diff --git a/trunk/net/mac80211/ibss.c b/trunk/net/mac80211/ibss.c index 2db1f2b90bfe..b4b866f41919 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -228,7 +228,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, mgmt, skb->len, 0, GFP_KERNEL); - cfg80211_put_bss(local->hw.wiphy, bss); + cfg80211_put_bss(bss); netif_carrier_on(sdata->dev); cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); } @@ -242,8 +242,6 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, u32 basic_rates; int i, j; u16 beacon_int = cbss->beacon_interval; - const struct cfg80211_bss_ies *ies; - u64 tsf; lockdep_assert_held(&sdata->u.ibss.mtx); @@ -267,17 +265,13 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, } } - rcu_read_lock(); - ies = rcu_dereference(cbss->ies); - tsf = ies->tsf; - rcu_read_unlock(); - __ieee80211_sta_join_ibss(sdata, cbss->bssid, beacon_int, cbss->channel, basic_rates, cbss->capability, - tsf, false); + cbss->tsf, + false); } static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, @@ -308,7 +302,7 @@ static struct sta_info *ieee80211_ibss_finish_sta(struct sta_info *sta, "TX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=1)\n", sdata->vif.addr, addr, sdata->u.ibss.bssid); ieee80211_send_auth(sdata, 1, WLAN_AUTH_OPEN, 0, NULL, 0, - addr, sdata->u.ibss.bssid, NULL, 0, 0, 0); + addr, sdata->u.ibss.bssid, NULL, 0, 0); } return sta; } @@ -428,7 +422,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, * has actually implemented this. */ ieee80211_send_auth(sdata, 2, WLAN_AUTH_OPEN, 0, NULL, 0, - mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0, 0); + mgmt->sa, sdata->u.ibss.bssid, NULL, 0, 0); } static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, @@ -541,8 +535,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, cbss = container_of((void *)bss, struct cfg80211_bss, priv); - /* same for beacon and probe response */ - beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); + /* was just updated in ieee80211_bss_info_update */ + beacon_timestamp = cbss->tsf; /* check if we need to merge IBSS */ @@ -1108,6 +1102,10 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, mutex_unlock(&sdata->u.ibss.mtx); + mutex_lock(&sdata->local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); + /* * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is * reserved, but an HT STA shall protect HT transmissions as though @@ -1161,7 +1159,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) if (cbss) { cfg80211_unlink_bss(local->hw.wiphy, cbss); - cfg80211_put_bss(local->hw.wiphy, cbss); + cfg80211_put_bss(cbss); } } @@ -1205,5 +1203,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_unlock(&sdata->u.ibss.mtx); + mutex_lock(&local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&local->mtx); + return 0; } diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 76cdcfcd614c..5fba867d9e2e 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -86,11 +86,23 @@ struct ieee80211_fragment_entry { struct ieee80211_bss { - u32 device_ts_beacon, device_ts_presp; + /* don't want to look up all the time */ + size_t ssid_len; + u8 ssid[IEEE80211_MAX_SSID_LEN]; + + u32 device_ts; bool wmm_used; bool uapsd_supported; + unsigned long last_probe_resp; + +#ifdef CONFIG_MAC80211_MESH + u8 *mesh_id; + size_t mesh_id_len; + u8 *mesh_cfg; +#endif + #define IEEE80211_MAX_SUPP_RATES 32 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; size_t supp_rates_len; @@ -141,6 +153,31 @@ enum ieee80211_bss_valid_data_flags { IEEE80211_BSS_VALID_ERP = BIT(3) }; +static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_cfg; +#endif + return NULL; +} + +static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_id; +#endif + return NULL; +} + +static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) +{ +#ifdef CONFIG_MAC80211_MESH + return bss->mesh_id_len; +#endif + return 0; +} + + typedef unsigned __bitwise__ ieee80211_tx_result; #define TX_CONTINUE ((__force ieee80211_tx_result) 0u) #define TX_DROP ((__force ieee80211_tx_result) 1u) @@ -362,7 +399,8 @@ struct ieee80211_mgd_assoc_data { u8 ssid_len; u8 supp_rates_len; bool wmm, uapsd; - bool have_beacon, need_beacon; + bool have_beacon; + bool sent_assoc; bool synced; u8 ap_ht_param; @@ -387,7 +425,6 @@ struct ieee80211_if_managed { unsigned long probe_timeout; int probe_send_count; bool nullfunc_failed; - bool connection_loss; struct mutex mtx; struct cfg80211_bss *associated; @@ -412,10 +449,6 @@ struct ieee80211_if_managed { bool beacon_crc_valid; u32 beacon_crc; - bool status_acked; - bool status_received; - __le16 status_fc; - enum { IEEE80211_MFP_DISABLED, IEEE80211_MFP_OPTIONAL, @@ -590,11 +623,6 @@ struct ieee80211_if_mesh { s64 sync_offset_clockdrift_max; spinlock_t sync_offset_lock; bool adjusting_tbtt; - /* mesh power save */ - enum nl80211_mesh_power_mode nonpeer_pm; - int ps_peers_light_sleep; - int ps_peers_deep_sleep; - struct ps_data ps; }; #ifdef CONFIG_MAC80211_MESH @@ -689,6 +717,9 @@ struct ieee80211_sub_if_data { char name[IFNAMSIZ]; + /* to detect idle changes */ + bool old_idle; + /* Fragment table for host-based reassembly */ struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; unsigned int fragment_next; @@ -809,7 +840,6 @@ enum queue_stop_reason { IEEE80211_QUEUE_STOP_REASON_AGGREGATION, IEEE80211_QUEUE_STOP_REASON_SUSPEND, IEEE80211_QUEUE_STOP_REASON_SKB_ADD, - IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, }; #ifdef CONFIG_MAC80211_LEDS @@ -956,7 +986,14 @@ struct ieee80211_local { struct sk_buff_head skb_queue; struct sk_buff_head skb_queue_unreliable; - spinlock_t rx_path_lock; + /* + * Internal FIFO queue which is shared between multiple rx path + * stages. Its main task is to provide a serialization mechanism, + * so all rx handlers can enjoy having exclusive access to their + * private data structures. + */ + struct sk_buff_head rx_skb_queue; + bool running_rx_handler; /* protected by rx_skb_queue.lock */ /* Station data */ /* @@ -1097,6 +1134,8 @@ struct ieee80211_local { * this will override whatever chosen by mac80211 internally. */ int dynamic_ps_forced_timeout; + int dynamic_ps_user_timeout; + bool disable_dynamic_ps; int user_power_level; /* in dBm, for all interfaces */ @@ -1179,7 +1218,6 @@ struct ieee802_11_elems { struct ieee80211_meshconf_ie *mesh_config; u8 *mesh_id; u8 *peering; - __le16 *awake_window; u8 *preq; u8 *prep; u8 *perr; @@ -1280,8 +1318,6 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata); void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); -void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, - __le16 fc, bool acked); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); @@ -1542,8 +1578,7 @@ static inline void ieee80211_add_pending_skbs(struct ieee80211_local *local, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u16 status, u8 *extra, size_t extra_len, const u8 *bssid, - const u8 *da, const u8 *key, u8 key_len, u8 key_idx, - u32 tx_flags); + const u8 *da, const u8 *key, u8 key_len, u8 key_idx); void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, const u8 *bssid, u16 stype, u16 reason, bool send_frame, u8 *frame_buf); @@ -1560,7 +1595,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, u32 tx_flags, + u32 ratemask, bool directed, bool no_cck, struct ieee80211_channel *channel, bool scan); void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, @@ -1601,8 +1636,6 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, enum ieee80211_chanctx_mode mode); void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); -void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, - bool clear); void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, struct ieee80211_chanctx *chanctx); diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index 40ff0307d089..0a36dc6346bb 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -78,7 +78,8 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); } -static u32 ieee80211_idle_off(struct ieee80211_local *local) +static u32 ieee80211_idle_off(struct ieee80211_local *local, + const char *reason) { if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) return 0; @@ -98,45 +99,110 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) return IEEE80211_CONF_CHANGE_IDLE; } -void ieee80211_recalc_idle(struct ieee80211_local *local) +static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) { - bool working = false, scanning, active; + struct ieee80211_sub_if_data *sdata; + int count = 0; + bool working = false, scanning = false; unsigned int led_trig_start = 0, led_trig_stop = 0; struct ieee80211_roc_work *roc; - u32 change; +#ifdef CONFIG_PROVE_LOCKING + WARN_ON(debug_locks && !lockdep_rtnl_is_held() && + !lockdep_is_held(&local->iflist_mtx)); +#endif lockdep_assert_held(&local->mtx); - active = !list_empty(&local->chanctx_list); + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) { + sdata->vif.bss_conf.idle = true; + continue; + } + + sdata->old_idle = sdata->vif.bss_conf.idle; + + /* do not count disabled managed interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_STATION && + !sdata->u.mgd.associated && + !sdata->u.mgd.auth_data && + !sdata->u.mgd.assoc_data) { + sdata->vif.bss_conf.idle = true; + continue; + } + /* do not count unused IBSS interfaces */ + if (sdata->vif.type == NL80211_IFTYPE_ADHOC && + !sdata->u.ibss.ssid_len) { + sdata->vif.bss_conf.idle = true; + continue; + } + + if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) + continue; + + /* count everything else */ + sdata->vif.bss_conf.idle = false; + count++; + } if (!local->ops->remain_on_channel) { list_for_each_entry(roc, &local->roc_list, list) { working = true; - break; + roc->sdata->vif.bss_conf.idle = false; } } - scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || - test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); + sdata = rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx)); + if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { + scanning = true; + sdata->vif.bss_conf.idle = false; + } + + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN || + sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) + continue; + if (sdata->old_idle == sdata->vif.bss_conf.idle) + continue; + if (!ieee80211_sdata_running(sdata)) + continue; + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); + } if (working || scanning) led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; else led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; - if (active) + if (count) led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; else led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); - if (working || scanning || active) - change = ieee80211_idle_off(local); + if (working) + return ieee80211_idle_off(local, "working"); + if (scanning) + return ieee80211_idle_off(local, "scanning"); + if (!count) + return ieee80211_idle_on(local); else - change = ieee80211_idle_on(local); - if (change) - ieee80211_hw_config(local, change); + return ieee80211_idle_off(local, "in use"); + + return 0; +} + +void ieee80211_recalc_idle(struct ieee80211_local *local) +{ + u32 chg; + + mutex_lock(&local->iflist_mtx); + chg = __ieee80211_recalc_idle(local); + mutex_unlock(&local->iflist_mtx); + if (chg) + ieee80211_hw_config(local, chg); } static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) @@ -555,8 +621,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) goto err_del_interface; } - drv_add_interface_debugfs(local, sdata); - if (sdata->vif.type == NL80211_IFTYPE_AP) { local->fif_pspoll++; local->fif_probe_req++; @@ -630,6 +694,10 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) if (sdata->flags & IEEE80211_SDATA_PROMISC) atomic_inc(&local->iff_promiscs); + mutex_lock(&local->mtx); + hw_reconf_flags |= __ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); + if (coming_up) local->open_count++; @@ -814,14 +882,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, */ ieee80211_free_keys(sdata); - drv_remove_interface_debugfs(local, sdata); - if (going_down) drv_remove_interface(local, sdata); } sdata->bss = NULL; + mutex_lock(&local->mtx); + hw_reconf_flags |= __ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); + ieee80211_recalc_ps(local, -1); if (local->open_count == 0) { diff --git a/trunk/net/mac80211/main.c b/trunk/net/mac80211/main.c index 38b3468bc515..2bdd454e8bcf 100644 --- a/trunk/net/mac80211/main.c +++ b/trunk/net/mac80211/main.c @@ -34,6 +34,8 @@ #include "cfg.h" #include "debugfs.h" +static struct lock_class_key ieee80211_rx_skb_queue_class; + void ieee80211_configure_filter(struct ieee80211_local *local) { u64 mc; @@ -611,12 +613,21 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, mutex_init(&local->key_mtx); spin_lock_init(&local->filter_lock); - spin_lock_init(&local->rx_path_lock); spin_lock_init(&local->queue_stop_reason_lock); INIT_LIST_HEAD(&local->chanctx_list); mutex_init(&local->chanctx_mtx); + /* + * The rx_skb_queue is only accessed from tasklets, + * but other SKB queues are used from within IRQ + * context. Therefore, this one needs a different + * locking class so our direct, non-irq-safe use of + * the queue's lock doesn't throw lockdep warnings. + */ + skb_queue_head_init_class(&local->rx_skb_queue, + &ieee80211_rx_skb_queue_class); + INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); INIT_WORK(&local->restart_work, ieee80211_restart_work); @@ -696,6 +707,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) return -EINVAL; #endif + if ((hw->flags & IEEE80211_HW_SCAN_WHILE_IDLE) && !local->ops->hw_scan) + return -EINVAL; + if (!local->use_chanctx) { for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) { const struct ieee80211_iface_combination *comb; @@ -1075,6 +1089,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); skb_queue_purge(&local->skb_queue); skb_queue_purge(&local->skb_queue_unreliable); + skb_queue_purge(&local->rx_skb_queue); destroy_workqueue(local->workqueue); wiphy_unregister(local->hw.wiphy); diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 2bf0158c3f82..694e27376afa 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -149,31 +149,6 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) return changed; } -/* - * mesh_sta_cleanup - clean up any mesh sta state - * - * @sta: mesh sta to clean up. - */ -void mesh_sta_cleanup(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - u32 changed; - - /* - * maybe userspace handles peer allocation and peering, but in either - * case the beacon is still generated by the kernel and we might need - * an update. - */ - changed = mesh_accept_plinks_update(sdata); - if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { - changed |= mesh_plink_deactivate(sta); - del_timer_sync(&sta->plink_timer); - } - - if (changed) - ieee80211_bss_info_change_notify(sdata, changed); -} - int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) { int i; @@ -286,9 +261,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; *pos |= ifmsh->accepting_plinks ? IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; - /* Mesh PS mode. See IEEE802.11-2012 8.4.2.100.8 */ - *pos |= ifmsh->ps_peers_deep_sleep ? - IEEE80211_MESHCONF_CAPAB_POWER_SAVE_LEVEL : 0x00; *pos++ |= ifmsh->adjusting_tbtt ? IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; *pos++ = 0x00; @@ -314,29 +286,6 @@ mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) return 0; } -int mesh_add_awake_window_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - u8 *pos; - - /* see IEEE802.11-2012 13.14.6 */ - if (ifmsh->ps_peers_light_sleep == 0 && - ifmsh->ps_peers_deep_sleep == 0 && - ifmsh->nonpeer_pm == NL80211_MESH_POWER_ACTIVE) - return 0; - - if (skb_tailroom(skb) < 4) - return -ENOMEM; - - pos = skb_put(skb, 2 + 2); - *pos++ = WLAN_EID_MESH_AWAKE_WINDOW; - *pos++ = 2; - put_unaligned_le16(ifmsh->mshcfg.dot11MeshAwakeWindowDuration, pos); - - return 0; -} - int mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { @@ -393,6 +342,8 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) int mesh_add_ds_params_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) { + struct ieee80211_local *local = sdata->local; + struct ieee80211_supported_band *sband; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *chan; u8 *pos; @@ -409,10 +360,13 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, chan = chanctx_conf->def.chan; rcu_read_unlock(); - pos = skb_put(skb, 2 + 1); - *pos++ = WLAN_EID_DS_PARAMS; - *pos++ = 1; - *pos++ = ieee80211_frequency_to_channel(chan->center_freq); + sband = local->hw.wiphy->bands[chan->band]; + if (sband->band == IEEE80211_BAND_2GHZ) { + pos = skb_put(skb, 2 + 1); + *pos++ = WLAN_EID_DS_PARAMS; + *pos++ = 1; + *pos++ = ieee80211_frequency_to_channel(chan->center_freq); + } return 0; } @@ -675,7 +629,10 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(local, band); - ieee80211_mps_local_status_update(sdata); + if (band == IEEE80211_BAND_5GHZ) { + sdata->vif.bss_conf.use_short_slot = true; + changed |= BSS_CHANGED_ERP_SLOT; + } ieee80211_bss_info_change_notify(sdata, changed); @@ -699,10 +656,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) sta_info_flush(sdata); mesh_path_flush_by_iface(sdata); - /* free all potentially still buffered group-addressed frames */ - local->total_ps_buffered -= skb_queue_len(&ifmsh->ps.bc_buf); - skb_queue_purge(&ifmsh->ps.bc_buf); - del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); del_timer_sync(&sdata->u.mesh.mesh_path_timer); @@ -880,7 +833,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ieee80211_mesh_path_root_timer, (unsigned long) sdata); INIT_LIST_HEAD(&ifmsh->preq_queue.list); - skb_queue_head_init(&ifmsh->ps.bc_buf); spin_lock_init(&ifmsh->mesh_preq_queue_lock); spin_lock_init(&ifmsh->sync_offset_lock); diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 3b9d862744ba..aff301544c7f 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -222,8 +222,6 @@ int mesh_add_meshid_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); -int mesh_add_awake_window_ie(struct sk_buff *skb, - struct ieee80211_sub_if_data *sdata); int mesh_add_vendor_ies(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); int mesh_add_ds_params_ie(struct sk_buff *skb, @@ -244,21 +242,6 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh); const struct ieee80211_mesh_sync_ops *ieee80211_mesh_sync_ops_get(u8 method); -/* mesh power save */ -void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata); -void ieee80211_mps_set_sta_local_pm(struct sta_info *sta, - enum nl80211_mesh_power_mode pm); -void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, - struct ieee80211_hdr *hdr); -void ieee80211_mps_sta_status_update(struct sta_info *sta); -void ieee80211_mps_rx_h_sta_process(struct sta_info *sta, - struct ieee80211_hdr *hdr); -void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, - bool tx, bool acked); -void ieee80211_mps_frame_release(struct sta_info *sta, - struct ieee802_11_elems *elems); - /* Mesh paths */ int mesh_nexthop_lookup(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata); @@ -288,13 +271,12 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); void mesh_plink_broken(struct sta_info *sta); -u32 mesh_plink_deactivate(struct sta_info *sta); +void mesh_plink_deactivate(struct sta_info *sta); int mesh_plink_open(struct sta_info *sta); void mesh_plink_block(struct sta_info *sta); void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_rx_status *rx_status); -void mesh_sta_cleanup(struct sta_info *sta); /* Private interfaces */ /* Mesh tables */ diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index f0dd8742ed42..6b4603a90031 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -205,7 +205,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; skb_set_mac_header(skb, 0); skb_set_network_header(skb, 0); @@ -218,7 +217,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, info->control.vif = &sdata->vif; info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ieee80211_set_qos_hdr(sdata, skb); - ieee80211_mps_set_frame_flags(sdata, NULL, hdr); } /** @@ -1082,10 +1080,6 @@ int mesh_nexthop_resolve(struct sk_buff *skb, u8 *target_addr = hdr->addr3; int err = 0; - /* Nulls are only sent to peers for PS and should be pre-addressed */ - if (ieee80211_is_qos_nullfunc(hdr->frame_control)) - return 0; - rcu_read_lock(); err = mesh_nexthop_lookup(skb, sdata); if (!err) @@ -1157,7 +1151,6 @@ int mesh_nexthop_lookup(struct sk_buff *skb, if (next_hop) { memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sdata, next_hop, hdr); err = 0; } diff --git a/trunk/net/mac80211/mesh_pathtbl.c b/trunk/net/mac80211/mesh_pathtbl.c index d5786c3eaee2..aa749818860e 100644 --- a/trunk/net/mac80211/mesh_pathtbl.c +++ b/trunk/net/mac80211/mesh_pathtbl.c @@ -212,7 +212,6 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) hdr = (struct ieee80211_hdr *) skb->data; memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sta->sdata, sta, hdr); } spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); diff --git a/trunk/net/mac80211/mesh_plink.c b/trunk/net/mac80211/mesh_plink.c index 56c9b318a97e..81e612682bc3 100644 --- a/trunk/net/mac80211/mesh_plink.c +++ b/trunk/net/mac80211/mesh_plink.c @@ -55,66 +55,6 @@ static inline void mesh_plink_fsm_restart(struct sta_info *sta) sta->plink_retries = 0; } -/* - * mesh_set_short_slot_time - enable / disable ERP short slot time. - * - * The standard indirectly mandates mesh STAs to turn off short slot time by - * disallowing advertising this (802.11-2012 8.4.1.4), but that doesn't mean we - * can't be sneaky about it. Enable short slot time if all mesh STAs in the - * MBSS support ERP rates. - * - * Returns BSS_CHANGED_ERP_SLOT or 0 for no change. - */ -static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - enum ieee80211_band band = ieee80211_get_sdata_band(sdata); - struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; - struct sta_info *sta; - u32 erp_rates = 0, changed = 0; - int i; - bool short_slot = false; - - if (band == IEEE80211_BAND_5GHZ) { - /* (IEEE 802.11-2012 19.4.5) */ - short_slot = true; - goto out; - } else if (band != IEEE80211_BAND_2GHZ || - (band == IEEE80211_BAND_2GHZ && - local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) - goto out; - - for (i = 0; i < sband->n_bitrates; i++) - if (sband->bitrates[i].flags & IEEE80211_RATE_ERP_G) - erp_rates |= BIT(i); - - if (!erp_rates) - goto out; - - rcu_read_lock(); - list_for_each_entry_rcu(sta, &local->sta_list, list) { - if (sdata != sta->sdata || - sta->plink_state != NL80211_PLINK_ESTAB) - continue; - - short_slot = false; - if (erp_rates & sta->sta.supp_rates[band]) - short_slot = true; - else - break; - } - rcu_read_unlock(); - -out: - if (sdata->vif.bss_conf.use_short_slot != short_slot) { - sdata->vif.bss_conf.use_short_slot = short_slot; - changed = BSS_CHANGED_ERP_SLOT; - mpl_dbg(sdata, "mesh_plink %pM: ERP short slot time %d\n", - sdata->vif.addr, short_slot); - } - return changed; -} - /** * mesh_set_ht_prot_mode - set correct HT protection mode * @@ -201,9 +141,6 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) sta->plink_state = NL80211_PLINK_BLOCKED; mesh_path_flush_by_nexthop(sta); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_local_status_update(sdata); - return changed; } @@ -214,7 +151,7 @@ static u32 __mesh_plink_deactivate(struct sta_info *sta) * * All mesh paths with this peer as next hop will be flushed */ -u32 mesh_plink_deactivate(struct sta_info *sta) +void mesh_plink_deactivate(struct sta_info *sta) { struct ieee80211_sub_if_data *sdata = sta->sdata; u32 changed; @@ -227,7 +164,7 @@ u32 mesh_plink_deactivate(struct sta_info *sta) sta->reason); spin_unlock_bh(&sta->lock); - return changed; + ieee80211_bss_info_change_notify(sdata, changed); } static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, @@ -506,7 +443,6 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, rssi_threshold_check(sta, sdata)) mesh_plink_open(sta); - ieee80211_mps_frame_release(sta, elems); out: rcu_read_unlock(); } @@ -592,13 +528,6 @@ static void mesh_plink_timer(unsigned long data) #ifdef CONFIG_PM void mesh_plink_quiesce(struct sta_info *sta) { - if (!ieee80211_vif_is_mesh(&sta->sdata->vif)) - return; - - /* no kernel mesh sta timers have been initialized */ - if (sta->sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE) - return; - if (del_timer_sync(&sta->plink_timer)) sta->plink_timer_was_running = true; } @@ -644,9 +573,6 @@ int mesh_plink_open(struct sta_info *sta) "Mesh plink: starting establishment with %pM\n", sta->sta.addr); - /* set the non-peer mode to active during peering */ - ieee80211_mps_local_status_update(sdata); - return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, sta->sta.addr, llid, 0, 0); } @@ -880,10 +806,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m sta->llid = llid; mesh_plink_timer_set(sta, mshcfg->dot11MeshRetryTimeout); - - /* set the non-peer mode to active during peering */ - ieee80211_mps_local_status_update(sdata); - spin_unlock_bh(&sta->lock); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, @@ -974,12 +896,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - mshcfg->power_mode); break; default: spin_unlock_bh(&sta->lock); @@ -1013,15 +931,11 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m spin_unlock_bh(&sta->lock); changed |= mesh_plink_inc_estab_count(sdata); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", sta->sta.addr); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CONFIRM, sta->sta.addr, llid, plid, 0); - ieee80211_mps_sta_status_update(sta); - ieee80211_mps_set_sta_local_pm(sta, - mshcfg->power_mode); break; default: spin_unlock_bh(&sta->lock); @@ -1040,7 +954,6 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); spin_unlock_bh(&sta->lock); changed |= mesh_set_ht_prot_mode(sdata); - changed |= mesh_set_short_slot_time(sdata); mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, sta->sta.addr, llid, plid, reason); break; diff --git a/trunk/net/mac80211/mesh_ps.c b/trunk/net/mac80211/mesh_ps.c deleted file mode 100644 index b677962525ed..000000000000 --- a/trunk/net/mac80211/mesh_ps.c +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright 2012-2013, Marco Porsch - * Copyright 2012-2013, cozybit Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include "mesh.h" -#include "wme.h" - - -/* mesh PS management */ - -/** - * mps_qos_null_get - create pre-addressed QoS Null frame for mesh powersave - */ -static struct sk_buff *mps_qos_null_get(struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - struct ieee80211_hdr *nullfunc; /* use 4addr header */ - struct sk_buff *skb; - int size = sizeof(*nullfunc); - __le16 fc; - - skb = dev_alloc_skb(local->hw.extra_tx_headroom + size + 2); - if (!skb) - return NULL; - skb_reserve(skb, local->hw.extra_tx_headroom); - - nullfunc = (struct ieee80211_hdr *) skb_put(skb, size); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC); - ieee80211_fill_mesh_addresses(nullfunc, &fc, sta->sta.addr, - sdata->vif.addr); - nullfunc->frame_control = fc; - nullfunc->duration_id = 0; - /* no address resolution for this frame -> set addr 1 immediately */ - memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN); - memset(skb_put(skb, 2), 0, 2); /* append QoS control field */ - ieee80211_mps_set_frame_flags(sdata, sta, nullfunc); - - return skb; -} - -/** - * mps_qos_null_tx - send a QoS Null to indicate link-specific power mode - */ -static void mps_qos_null_tx(struct sta_info *sta) -{ - struct sk_buff *skb; - - skb = mps_qos_null_get(sta); - if (!skb) - return; - - mps_dbg(sta->sdata, "announcing peer-specific power mode to %pM\n", - sta->sta.addr); - - /* don't unintentionally start a MPSP */ - if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { - u8 *qc = ieee80211_get_qos_ctl((void *) skb->data); - - qc[0] |= IEEE80211_QOS_CTL_EOSP; - } - - ieee80211_tx_skb(sta->sdata, skb); -} - -/** - * ieee80211_mps_local_status_update - track status of local link-specific PMs - * - * @sdata: local mesh subif - * - * sets the non-peer power mode and triggers the driver PS (re-)configuration - */ -void ieee80211_mps_local_status_update(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct sta_info *sta; - bool peering = false; - int light_sleep_cnt = 0; - int deep_sleep_cnt = 0; - - rcu_read_lock(); - list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) { - if (sdata != sta->sdata) - continue; - - switch (sta->plink_state) { - case NL80211_PLINK_OPN_SNT: - case NL80211_PLINK_OPN_RCVD: - case NL80211_PLINK_CNF_RCVD: - peering = true; - break; - case NL80211_PLINK_ESTAB: - if (sta->local_pm == NL80211_MESH_POWER_LIGHT_SLEEP) - light_sleep_cnt++; - else if (sta->local_pm == NL80211_MESH_POWER_DEEP_SLEEP) - deep_sleep_cnt++; - break; - default: - break; - } - } - rcu_read_unlock(); - - /* - * Set non-peer mode to active during peering/scanning/authentication - * (see IEEE802.11-2012 13.14.8.3). The non-peer mesh power mode is - * deep sleep if the local STA is in light or deep sleep towards at - * least one mesh peer (see 13.14.3.1). Otherwise, set it to the - * user-configured default value. - */ - if (peering) { - mps_dbg(sdata, "setting non-peer PM to active for peering\n"); - ifmsh->nonpeer_pm = NL80211_MESH_POWER_ACTIVE; - } else if (light_sleep_cnt || deep_sleep_cnt) { - mps_dbg(sdata, "setting non-peer PM to deep sleep\n"); - ifmsh->nonpeer_pm = NL80211_MESH_POWER_DEEP_SLEEP; - } else { - mps_dbg(sdata, "setting non-peer PM to user value\n"); - ifmsh->nonpeer_pm = ifmsh->mshcfg.power_mode; - } - - ifmsh->ps_peers_light_sleep = light_sleep_cnt; - ifmsh->ps_peers_deep_sleep = deep_sleep_cnt; -} - -/** - * ieee80211_mps_set_sta_local_pm - set local PM towards a mesh STA - * - * @sta: mesh STA - * @pm: the power mode to set - */ -void ieee80211_mps_set_sta_local_pm(struct sta_info *sta, - enum nl80211_mesh_power_mode pm) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - - mps_dbg(sdata, "local STA operates in mode %d with %pM\n", - pm, sta->sta.addr); - - sta->local_pm = pm; - - /* - * announce peer-specific power mode transition - * (see IEEE802.11-2012 13.14.3.2 and 13.14.3.3) - */ - if (sta->plink_state == NL80211_PLINK_ESTAB) - mps_qos_null_tx(sta); - - ieee80211_mps_local_status_update(sdata); -} - -/** - * ieee80211_mps_set_frame_flags - set mesh PS flags in FC (and QoS Control) - * - * @sdata: local mesh subif - * @sta: mesh STA - * @hdr: 802.11 frame header - * - * see IEEE802.11-2012 8.2.4.1.7 and 8.2.4.5.11 - * - * NOTE: sta must be given when an individually-addressed QoS frame header - * is handled, for group-addressed and management frames it is not used - */ -void ieee80211_mps_set_frame_flags(struct ieee80211_sub_if_data *sdata, - struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - u8 *qc; - - if (WARN_ON(is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control) && - !sta)) - return; - - if (is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control) && - sta->plink_state == NL80211_PLINK_ESTAB) - pm = sta->local_pm; - else - pm = sdata->u.mesh.nonpeer_pm; - - if (pm == NL80211_MESH_POWER_ACTIVE) - hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_PM); - else - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - if (!ieee80211_is_data_qos(hdr->frame_control)) - return; - - qc = ieee80211_get_qos_ctl(hdr); - - if ((is_unicast_ether_addr(hdr->addr1) && - pm == NL80211_MESH_POWER_DEEP_SLEEP) || - (is_multicast_ether_addr(hdr->addr1) && - sdata->u.mesh.ps_peers_deep_sleep > 0)) - qc[1] |= (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8); - else - qc[1] &= ~(IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8); -} - -/** - * ieee80211_mps_sta_status_update - update buffering status of neighbor STA - * - * @sta: mesh STA - * - * called after change of peering status or non-peer/peer-specific power mode - */ -void ieee80211_mps_sta_status_update(struct sta_info *sta) -{ - enum nl80211_mesh_power_mode pm; - bool do_buffer; - - /* - * use peer-specific power mode if peering is established and the - * peer's power mode is known - */ - if (sta->plink_state == NL80211_PLINK_ESTAB && - sta->peer_pm != NL80211_MESH_POWER_UNKNOWN) - pm = sta->peer_pm; - else - pm = sta->nonpeer_pm; - - do_buffer = (pm != NL80211_MESH_POWER_ACTIVE); - - /* Don't let the same PS state be set twice */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) == do_buffer) - return; - - if (do_buffer) { - set_sta_flag(sta, WLAN_STA_PS_STA); - atomic_inc(&sta->sdata->u.mesh.ps.num_sta_ps); - mps_dbg(sta->sdata, "start PS buffering frames towards %pM\n", - sta->sta.addr); - } else { - ieee80211_sta_ps_deliver_wakeup(sta); - } - - /* clear the MPSP flags for non-peers or active STA */ - if (sta->plink_state != NL80211_PLINK_ESTAB) { - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - } else if (!do_buffer) { - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - } -} - -static void mps_set_sta_peer_pm(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - u8 *qc = ieee80211_get_qos_ctl(hdr); - - /* - * Test Power Management field of frame control (PW) and - * mesh power save level subfield of QoS control field (PSL) - * - * | PM | PSL| Mesh PM | - * +----+----+---------+ - * | 0 |Rsrv| Active | - * | 1 | 0 | Light | - * | 1 | 1 | Deep | - */ - if (ieee80211_has_pm(hdr->frame_control)) { - if (qc[1] & (IEEE80211_QOS_CTL_MESH_PS_LEVEL >> 8)) - pm = NL80211_MESH_POWER_DEEP_SLEEP; - else - pm = NL80211_MESH_POWER_LIGHT_SLEEP; - } else { - pm = NL80211_MESH_POWER_ACTIVE; - } - - if (sta->peer_pm == pm) - return; - - mps_dbg(sta->sdata, "STA %pM enters mode %d\n", - sta->sta.addr, pm); - - sta->peer_pm = pm; - - ieee80211_mps_sta_status_update(sta); -} - -static void mps_set_sta_nonpeer_pm(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - enum nl80211_mesh_power_mode pm; - - if (ieee80211_has_pm(hdr->frame_control)) - pm = NL80211_MESH_POWER_DEEP_SLEEP; - else - pm = NL80211_MESH_POWER_ACTIVE; - - if (sta->nonpeer_pm == pm) - return; - - mps_dbg(sta->sdata, "STA %pM sets non-peer mode to %d\n", - sta->sta.addr, pm); - - sta->nonpeer_pm = pm; - - ieee80211_mps_sta_status_update(sta); -} - -/** - * ieee80211_mps_rx_h_sta_process - frame receive handler for mesh powersave - * - * @sta: STA info that transmitted the frame - * @hdr: IEEE 802.11 (QoS) Header - */ -void ieee80211_mps_rx_h_sta_process(struct sta_info *sta, - struct ieee80211_hdr *hdr) -{ - if (is_unicast_ether_addr(hdr->addr1) && - ieee80211_is_data_qos(hdr->frame_control)) { - /* - * individually addressed QoS Data/Null frames contain - * peer link-specific PS mode towards the local STA - */ - mps_set_sta_peer_pm(sta, hdr); - - /* check for mesh Peer Service Period trigger frames */ - ieee80211_mpsp_trigger_process(ieee80211_get_qos_ctl(hdr), - sta, false, false); - } else { - /* - * can only determine non-peer PS mode - * (see IEEE802.11-2012 8.2.4.1.7) - */ - mps_set_sta_nonpeer_pm(sta, hdr); - } -} - - -/* mesh PS frame release */ - -static void mpsp_trigger_send(struct sta_info *sta, bool rspi, bool eosp) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct sk_buff *skb; - struct ieee80211_hdr *nullfunc; - struct ieee80211_tx_info *info; - u8 *qc; - - skb = mps_qos_null_get(sta); - if (!skb) - return; - - nullfunc = (struct ieee80211_hdr *) skb->data; - if (!eosp) - nullfunc->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - /* - * | RSPI | EOSP | MPSP triggering | - * +------+------+--------------------+ - * | 0 | 0 | local STA is owner | - * | 0 | 1 | no MPSP (MPSP end) | - * | 1 | 0 | both STA are owner | - * | 1 | 1 | peer STA is owner | see IEEE802.11-2012 13.14.9.2 - */ - qc = ieee80211_get_qos_ctl(nullfunc); - if (rspi) - qc[1] |= (IEEE80211_QOS_CTL_RSPI >> 8); - if (eosp) - qc[0] |= IEEE80211_QOS_CTL_EOSP; - - info = IEEE80211_SKB_CB(skb); - - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER | - IEEE80211_TX_CTL_REQ_TX_STATUS; - - mps_dbg(sdata, "sending MPSP trigger%s%s to %pM\n", - rspi ? " RSPI" : "", eosp ? " EOSP" : "", sta->sta.addr); - - ieee80211_tx_skb(sdata, skb); -} - -/** - * mpsp_qos_null_append - append QoS Null frame to MPSP skb queue if needed - * - * To properly end a mesh MPSP the last transmitted frame has to set the EOSP - * flag in the QoS Control field. In case the current tailing frame is not a - * QoS Data frame, append a QoS Null to carry the flag. - */ -static void mpsp_qos_null_append(struct sta_info *sta, - struct sk_buff_head *frames) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct sk_buff *new_skb, *skb = skb_peek_tail(frames); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info; - - if (ieee80211_is_data_qos(hdr->frame_control)) - return; - - new_skb = mps_qos_null_get(sta); - if (!new_skb) - return; - - mps_dbg(sdata, "appending QoS Null in MPSP towards %pM\n", - sta->sta.addr); - /* - * This frame has to be transmitted last. Assign lowest priority to - * make sure it cannot pass other frames when releasing multiple ACs. - */ - new_skb->priority = 1; - skb_set_queue_mapping(new_skb, IEEE80211_AC_BK); - ieee80211_set_qos_hdr(sdata, new_skb); - - info = IEEE80211_SKB_CB(new_skb); - info->control.vif = &sdata->vif; - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; - - __skb_queue_tail(frames, new_skb); -} - -/** - * mps_frame_deliver - transmit frames during mesh powersave - * - * @sta: STA info to transmit to - * @n_frames: number of frames to transmit. -1 for all - */ -static void mps_frame_deliver(struct sta_info *sta, int n_frames) -{ - struct ieee80211_sub_if_data *sdata = sta->sdata; - struct ieee80211_local *local = sdata->local; - int ac; - struct sk_buff_head frames; - struct sk_buff *skb; - bool more_data = false; - - skb_queue_head_init(&frames); - - /* collect frame(s) from buffers */ - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { - while (n_frames != 0) { - skb = skb_dequeue(&sta->tx_filtered[ac]); - if (!skb) { - skb = skb_dequeue( - &sta->ps_tx_buf[ac]); - if (skb) - local->total_ps_buffered--; - } - if (!skb) - break; - n_frames--; - __skb_queue_tail(&frames, skb); - } - - if (!skb_queue_empty(&sta->tx_filtered[ac]) || - !skb_queue_empty(&sta->ps_tx_buf[ac])) - more_data = true; - } - - /* nothing to send? -> EOSP */ - if (skb_queue_empty(&frames)) { - mpsp_trigger_send(sta, false, true); - return; - } - - /* in a MPSP make sure the last skb is a QoS Data frame */ - if (test_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mpsp_qos_null_append(sta, &frames); - - mps_dbg(sta->sdata, "sending %d frames to PS STA %pM\n", - skb_queue_len(&frames), sta->sta.addr); - - /* prepare collected frames for transmission */ - skb_queue_walk(&frames, skb) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (void *) skb->data; - - /* - * Tell TX path to send this frame even though the - * STA may still remain is PS mode after this frame - * exchange. - */ - info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; - - if (more_data || !skb_queue_is_last(&frames, skb)) - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - else - hdr->frame_control &= - cpu_to_le16(~IEEE80211_FCTL_MOREDATA); - - if (skb_queue_is_last(&frames, skb) && - ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qoshdr = ieee80211_get_qos_ctl(hdr); - - /* MPSP trigger frame ends service period */ - *qoshdr |= IEEE80211_QOS_CTL_EOSP; - info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; - } - } - - ieee80211_add_pending_skbs(local, &frames); - sta_info_recalc_tim(sta); -} - -/** - * ieee80211_mpsp_trigger_process - track status of mesh Peer Service Periods - * - * @qc: QoS Control field - * @sta: peer to start a MPSP with - * @tx: frame was transmitted by the local STA - * @acked: frame has been transmitted successfully - * - * NOTE: active mode STA may only serve as MPSP owner - */ -void ieee80211_mpsp_trigger_process(u8 *qc, struct sta_info *sta, - bool tx, bool acked) -{ - u8 rspi = qc[1] & (IEEE80211_QOS_CTL_RSPI >> 8); - u8 eosp = qc[0] & IEEE80211_QOS_CTL_EOSP; - - if (tx) { - if (rspi && acked) - set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - - if (eosp) - clear_sta_flag(sta, WLAN_STA_MPSP_OWNER); - else if (acked && - test_sta_flag(sta, WLAN_STA_PS_STA) && - !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mps_frame_deliver(sta, -1); - } else { - if (eosp) - clear_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - else if (sta->local_pm != NL80211_MESH_POWER_ACTIVE) - set_sta_flag(sta, WLAN_STA_MPSP_RECIPIENT); - - if (rspi && !test_and_set_sta_flag(sta, WLAN_STA_MPSP_OWNER)) - mps_frame_deliver(sta, -1); - } -} - -/** - * ieee80211_mps_frame_release - release buffered frames in response to beacon - * - * @sta: mesh STA - * @elems: beacon IEs - * - * For peers if we have individually-addressed frames buffered or the peer - * indicates buffered frames, send a corresponding MPSP trigger frame. Since - * we do not evaluate the awake window duration, QoS Nulls are used as MPSP - * trigger frames. If the neighbour STA is not a peer, only send single frames. - */ -void ieee80211_mps_frame_release(struct sta_info *sta, - struct ieee802_11_elems *elems) -{ - int ac, buffer_local = 0; - bool has_buffered = false; - - /* TIM map only for LLID <= IEEE80211_MAX_AID */ - if (sta->plink_state == NL80211_PLINK_ESTAB) - has_buffered = ieee80211_check_tim(elems->tim, elems->tim_len, - le16_to_cpu(sta->llid) % IEEE80211_MAX_AID); - - if (has_buffered) - mps_dbg(sta->sdata, "%pM indicates buffered frames\n", - sta->sta.addr); - - /* only transmit to PS STA with announced, non-zero awake window */ - if (test_sta_flag(sta, WLAN_STA_PS_STA) && - (!elems->awake_window || !le16_to_cpu(*elems->awake_window))) - return; - - for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) - buffer_local += skb_queue_len(&sta->ps_tx_buf[ac]) + - skb_queue_len(&sta->tx_filtered[ac]); - - if (!has_buffered && !buffer_local) - return; - - if (sta->plink_state == NL80211_PLINK_ESTAB) - mpsp_trigger_send(sta, has_buffered, !buffer_local); - else - mps_frame_deliver(sta, 1); -} diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index efb22763d56d..5913fb924b12 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -30,13 +30,11 @@ #include "rate.h" #include "led.h" -#define IEEE80211_AUTH_TIMEOUT (HZ / 5) -#define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) -#define IEEE80211_AUTH_MAX_TRIES 3 -#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) -#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) -#define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) -#define IEEE80211_ASSOC_MAX_TRIES 3 +#define IEEE80211_AUTH_TIMEOUT (HZ / 5) +#define IEEE80211_AUTH_MAX_TRIES 3 +#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) +#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) +#define IEEE80211_ASSOC_MAX_TRIES 3 static int max_nullfunc_tries = 2; module_param(max_nullfunc_tries, int, 0644); @@ -646,9 +644,6 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) drv_mgd_prepare_tx(local, sdata); IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; ieee80211_tx_skb(sdata, skb); } @@ -685,8 +680,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, if (powersave) nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | - IEEE80211_TX_INTFL_OFFCHAN_TX_OK; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL | IEEE80211_STA_CONNECTION_POLL)) IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE; @@ -952,6 +946,39 @@ static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, return 0; } +void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_local *local = sdata->local; + struct ieee80211_conf *conf = &local->hw.conf; + + WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || + !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || + (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); + + local->disable_dynamic_ps = false; + conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout; +} +EXPORT_SYMBOL(ieee80211_enable_dyn_ps); + +void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_local *local = sdata->local; + struct ieee80211_conf *conf = &local->hw.conf; + + WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || + !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || + (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); + + local->disable_dynamic_ps = true; + conf->dynamic_ps_timeout = 0; + del_timer_sync(&local->dynamic_ps_timer); + ieee80211_queue_work(&local->hw, + &local->dynamic_ps_enable_work); +} +EXPORT_SYMBOL(ieee80211_disable_dyn_ps); + /* powersave */ static void ieee80211_enable_ps(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata) @@ -1054,6 +1081,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) } if (count == 1 && ieee80211_powersave_allowed(found)) { + struct ieee80211_conf *conf = &local->hw.conf; s32 beaconint_us; if (latency < 0) @@ -1077,7 +1105,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) else timeout = 100; } - local->hw.conf.dynamic_ps_timeout = timeout; + local->dynamic_ps_user_timeout = timeout; + if (!local->disable_dynamic_ps) + conf->dynamic_ps_timeout = + local->dynamic_ps_user_timeout; if (beaconint_us > latency) { local->ps_sdata = NULL; @@ -1147,7 +1178,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) if (local->hw.conf.flags & IEEE80211_CONF_PS) return; - if (local->hw.conf.dynamic_ps_timeout > 0) { + if (!local->disable_dynamic_ps && + local->hw.conf.dynamic_ps_timeout > 0) { /* don't enter PS if TX frames are pending */ if (drv_tx_frames_pending(local)) { mod_timer(&local->dynamic_ps_timer, jiffies + @@ -1413,7 +1445,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); - if (sdata->u.mgd.assoc_data->have_beacon) { + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { /* * If the AP is buggy we may get here with no DTIM period * known, so assume it's 1 which is the only safe assumption @@ -1421,7 +1453,6 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, * probably just won't work at all. */ bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; - bss_info_changed |= BSS_CHANGED_DTIM_PERIOD; } else { bss_conf->dtim_period = 0; } @@ -1675,7 +1706,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) ssid_len = ssid[1]; ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, - 0, (u32) -1, true, 0, + 0, (u32) -1, true, false, ifmgd->associated->channel, false); rcu_read_unlock(); } @@ -1709,7 +1740,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, if (beacon) mlme_dbg_ratelimited(sdata, - "detected beacon loss from AP - probing\n"); + "detected beacon loss from AP - sending probe request\n"); ieee80211_cqm_rssi_notify(&sdata->vif, NL80211_CQM_RSSI_BEACON_LOSS_EVENT, GFP_KERNEL); @@ -1790,9 +1821,11 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, } EXPORT_SYMBOL(ieee80211_ap_probereq_get); -static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) +static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata, + bool transmit_frame) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; mutex_lock(&ifmgd->mtx); @@ -1803,7 +1836,7 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - true, frame_buf); + transmit_frame, frame_buf); ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; mutex_unlock(&ifmgd->mtx); @@ -1812,6 +1845,10 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) * but that's not a problem. */ cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); } static void ieee80211_beacon_connection_loss_work(struct work_struct *work) @@ -1830,10 +1867,10 @@ static void ieee80211_beacon_connection_loss_work(struct work_struct *work) rcu_read_unlock(); } - if (ifmgd->connection_loss) { + if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) { sdata_info(sdata, "Connection to AP %pM lost\n", ifmgd->bssid); - __ieee80211_disconnect(sdata); + __ieee80211_disconnect(sdata, false); } else { ieee80211_mgd_probe_ap(sdata, true); } @@ -1847,7 +1884,7 @@ static void ieee80211_csa_connection_drop_work(struct work_struct *work) ieee80211_wake_queues_by_reason(&sdata->local->hw, IEEE80211_QUEUE_STOP_REASON_CSA); - __ieee80211_disconnect(sdata); + __ieee80211_disconnect(sdata, true); } void ieee80211_beacon_loss(struct ieee80211_vif *vif) @@ -1858,7 +1895,6 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) trace_api_beacon_loss(sdata); WARN_ON(hw->flags & IEEE80211_HW_CONNECTION_MONITOR); - sdata->u.mgd.connection_loss = false; ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); } EXPORT_SYMBOL(ieee80211_beacon_loss); @@ -1870,7 +1906,7 @@ void ieee80211_connection_loss(struct ieee80211_vif *vif) trace_api_connection_loss(sdata); - sdata->u.mgd.connection_loss = true; + WARN_ON(!(hw->flags & IEEE80211_HW_CONNECTION_MONITOR)); ieee80211_queue_work(hw, &sdata->u.mgd.beacon_connection_loss_work); } EXPORT_SYMBOL(ieee80211_connection_loss); @@ -1892,7 +1928,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, ieee80211_vif_release_channel(sdata); } - cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss); + cfg80211_put_bss(auth_data->bss); kfree(auth_data); sdata->u.mgd.auth_data = NULL; } @@ -1900,11 +1936,9 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, size_t len) { - struct ieee80211_local *local = sdata->local; struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; u8 *pos; struct ieee802_11_elems elems; - u32 tx_flags = 0; pos = mgmt->u.auth.variable; ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); @@ -1912,14 +1946,11 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, return; auth_data->expected_transaction = 4; drv_mgd_prepare_tx(sdata->local, sdata); - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0, elems.challenge - 2, elems.challenge_len + 2, auth_data->bss->bssid, auth_data->bss->bssid, auth_data->key, auth_data->key_len, - auth_data->key_idx, tx_flags); + auth_data->key_idx); } static enum rx_mgmt_action __must_check @@ -2044,6 +2075,10 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); + mutex_lock(&sdata->local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); + return RX_MGMT_CFG80211_DEAUTH; } @@ -2071,6 +2106,10 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_set_disassoc(sdata, 0, 0, false, NULL); + mutex_lock(&sdata->local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); + return RX_MGMT_CFG80211_DISASSOC; } @@ -2213,7 +2252,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, if (elems.wmm_param) set_sta_flag(sta, WLAN_STA_WME); - err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); + err = sta_info_move_state(sta, IEEE80211_STA_AUTH); + if (!err) + err = sta_info_move_state(sta, IEEE80211_STA_ASSOC); if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT)) err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED); if (err) { @@ -2335,7 +2376,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ ieee80211_destroy_assoc_data(sdata, false); - cfg80211_put_bss(sdata->local->hw.wiphy, *bss); + cfg80211_put_bss(*bss); return RX_MGMT_CFG80211_ASSOC_TIMEOUT; } sdata_info(sdata, "associated\n"); @@ -2507,25 +2548,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, chan = chanctx_conf->def.chan; rcu_read_unlock(); - if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && + if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) { ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); ifmgd->assoc_data->have_beacon = true; - ifmgd->assoc_data->need_beacon = false; - if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { - sdata->vif.bss_conf.sync_tsf = - le64_to_cpu(mgmt->u.beacon.timestamp); - sdata->vif.bss_conf.sync_device_ts = - rx_status->device_timestamp; - if (elems.tim) - sdata->vif.bss_conf.sync_dtim_count = - elems.tim->dtim_count; - else - sdata->vif.bss_conf.sync_dtim_count = 0; - } + ifmgd->assoc_data->sent_assoc = false; /* continue assoc process */ ifmgd->assoc_data->timeout = jiffies; run_again(ifmgd, ifmgd->assoc_data->timeout); @@ -2600,7 +2630,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (ifmgd->flags & IEEE80211_STA_BEACON_POLL) { mlme_dbg_ratelimited(sdata, - "cancelling AP probe due to a received beacon\n"); + "cancelling probereq poll due to a received beacon\n"); mutex_lock(&local->mtx); ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; ieee80211_run_deferred_scan(local); @@ -2682,32 +2712,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, elems.wmm_param_len)) changed |= BSS_CHANGED_QOS; - /* - * If we haven't had a beacon before, tell the driver about the - * DTIM period (and beacon timing if desired) now. - */ - if (!bss_conf->dtim_period) { - /* a few bogus AP send dtim_period = 0 or no TIM IE */ - if (elems.tim) - bss_conf->dtim_period = elems.tim->dtim_period ?: 1; - else - bss_conf->dtim_period = 1; - - if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { - sdata->vif.bss_conf.sync_tsf = - le64_to_cpu(mgmt->u.beacon.timestamp); - sdata->vif.bss_conf.sync_device_ts = - rx_status->device_timestamp; - if (elems.tim) - sdata->vif.bss_conf.sync_dtim_count = - elems.tim->dtim_count; - else - sdata->vif.bss_conf.sync_dtim_count = 0; - } - - changed |= BSS_CHANGED_DTIM_PERIOD; - } - if (elems.erp_info && elems.erp_info_len >= 1) { erp_valid = true; erp_value = elems.erp_info[0]; @@ -2823,13 +2827,14 @@ static void ieee80211_sta_timer(unsigned long data) } static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 reason, bool tx) + u8 *bssid, u8 reason) { + struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, - tx, frame_buf); + false, frame_buf); mutex_unlock(&ifmgd->mtx); /* @@ -2838,6 +2843,10 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, */ cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); + mutex_lock(&ifmgd->mtx); } @@ -2846,17 +2855,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; - u32 tx_flags = 0; lockdep_assert_held(&ifmgd->mtx); if (WARN_ON_ONCE(!auth_data)) return -EINVAL; - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; - auth_data->tries++; if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { @@ -2893,8 +2897,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, auth_data->data, auth_data->data_len, auth_data->bss->bssid, - auth_data->bss->bssid, NULL, 0, 0, - tx_flags); + auth_data->bss->bssid, NULL, 0, 0); } else { const u8 *ssidie; @@ -2913,15 +2916,13 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) * will not answer to direct packet in unassociated state. */ ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], - NULL, 0, (u32) -1, true, tx_flags, + NULL, 0, (u32) -1, true, false, auth_data->bss->channel, false); rcu_read_unlock(); } - if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { - auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; - run_again(ifmgd, auth_data->timeout); - } + auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; + run_again(ifmgd, auth_data->timeout); return 0; } @@ -2952,26 +2953,12 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) IEEE80211_ASSOC_MAX_TRIES); ieee80211_send_assoc(sdata); - if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { - assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; - run_again(&sdata->u.mgd, assoc_data->timeout); - } + assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; + run_again(&sdata->u.mgd, assoc_data->timeout); return 0; } -void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, - __le16 fc, bool acked) -{ - struct ieee80211_local *local = sdata->local; - - sdata->u.mgd.status_fc = fc; - sdata->u.mgd.status_acked = acked; - sdata->u.mgd.status_received = true; - - ieee80211_queue_work(&local->hw, &sdata->work); -} - void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -2979,33 +2966,6 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) mutex_lock(&ifmgd->mtx); - if (ifmgd->status_received) { - __le16 fc = ifmgd->status_fc; - bool status_acked = ifmgd->status_acked; - - ifmgd->status_received = false; - if (ifmgd->auth_data && - (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) { - if (status_acked) { - ifmgd->auth_data->timeout = - jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->auth_data->timeout); - } else { - ifmgd->auth_data->timeout = jiffies - 1; - } - } else if (ifmgd->assoc_data && - (ieee80211_is_assoc_req(fc) || - ieee80211_is_reassoc_req(fc))) { - if (status_acked) { - ifmgd->assoc_data->timeout = - jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT; - run_again(ifmgd, ifmgd->assoc_data->timeout); - } else { - ifmgd->assoc_data->timeout = jiffies - 1; - } - } - } - if (ifmgd->auth_data && time_after(jiffies, ifmgd->auth_data->timeout)) { if (ifmgd->auth_data->done) { @@ -3030,8 +2990,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) if (ifmgd->assoc_data && time_after(jiffies, ifmgd->assoc_data->timeout)) { - if ((ifmgd->assoc_data->need_beacon && - !ifmgd->assoc_data->have_beacon) || + if (!ifmgd->assoc_data->have_beacon || ieee80211_do_assoc(sdata)) { u8 bssid[ETH_ALEN]; @@ -3074,8 +3033,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) "No ack for nullfunc frame to AP %pM, disconnecting.\n", bssid); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, - false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } else if (time_is_after_jiffies(ifmgd->probe_timeout)) run_again(ifmgd, ifmgd->probe_timeout); @@ -3084,7 +3042,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) "Failed to send nullfunc to AP %pM after %dms, disconnecting\n", bssid, probe_wait_ms); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } else if (ifmgd->probe_send_count < max_tries) { mlme_dbg(sdata, "No probe response from AP %pM after %dms, try %d/%i\n", @@ -3103,11 +3061,15 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) bssid, probe_wait_ms); ieee80211_sta_connection_lost(sdata, bssid, - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, false); + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } } mutex_unlock(&ifmgd->mtx); + + mutex_lock(&local->mtx); + ieee80211_recalc_idle(local); + mutex_unlock(&local->mtx); } static void ieee80211_sta_bcn_mon_timer(unsigned long data) @@ -3119,7 +3081,6 @@ static void ieee80211_sta_bcn_mon_timer(unsigned long data) if (local->quiescing) return; - sdata->u.mgd.connection_loss = false; ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.beacon_connection_loss_work); } @@ -3206,8 +3167,7 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) mlme_dbg(sdata, "driver requested disconnect after resume\n"); ieee80211_sta_connection_lost(sdata, ifmgd->associated->bssid, - WLAN_REASON_UNSPECIFIED, - true); + WLAN_REASON_UNSPECIFIED); mutex_unlock(&ifmgd->mtx); return; } @@ -3621,12 +3581,15 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, return -ENOMEM; } + mutex_lock(&local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&local->mtx); + if (new_sta) { u32 rates = 0, basic_rates = 0; bool have_higher_than_11mbit; int min_rate = INT_MAX, min_rate_index = -1; struct ieee80211_supported_band *sband; - const struct cfg80211_bss_ies *ies; sband = local->hw.wiphy->bands[cbss->channel->band]; @@ -3670,34 +3633,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, /* set timing information */ sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; - rcu_read_lock(); - ies = rcu_dereference(cbss->beacon_ies); - if (ies) { - const u8 *tim_ie; - - sdata->vif.bss_conf.sync_tsf = ies->tsf; - sdata->vif.bss_conf.sync_device_ts = - bss->device_ts_beacon; - tim_ie = cfg80211_find_ie(WLAN_EID_TIM, - ies->data, ies->len); - if (tim_ie && tim_ie[1] >= 2) - sdata->vif.bss_conf.sync_dtim_count = tim_ie[2]; - else - sdata->vif.bss_conf.sync_dtim_count = 0; - } else if (!(local->hw.flags & - IEEE80211_HW_TIMING_BEACON_ONLY)) { - ies = rcu_dereference(cbss->proberesp_ies); - /* must be non-NULL since beacon IEs were NULL */ - sdata->vif.bss_conf.sync_tsf = ies->tsf; - sdata->vif.bss_conf.sync_device_ts = - bss->device_ts_presp; - sdata->vif.bss_conf.sync_dtim_count = 0; - } else { - sdata->vif.bss_conf.sync_tsf = 0; - sdata->vif.bss_conf.sync_device_ts = 0; - sdata->vif.bss_conf.sync_dtim_count = 0; - } - rcu_read_unlock(); + sdata->vif.bss_conf.sync_tsf = cbss->tsf; + sdata->vif.bss_conf.sync_device_ts = bss->device_ts; /* tell driver about BSSID, basic rates and timing */ ieee80211_bss_info_change_notify(sdata, @@ -3817,7 +3754,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, } /* hold our own reference */ - cfg80211_ref_bss(local->hw.wiphy, auth_data->bss); + cfg80211_ref_bss(auth_data->bss); err = 0; goto out_unlock; @@ -3840,7 +3777,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_bss *bss = (void *)req->bss->priv; struct ieee80211_mgd_assoc_data *assoc_data; - const struct cfg80211_bss_ies *beacon_ies; struct ieee80211_supported_band *sband; const u8 *ssidie, *ht_ie, *vht_ie; int i, err; @@ -4006,45 +3942,40 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, if (err) goto err_clear; - rcu_read_lock(); - beacon_ies = rcu_dereference(req->bss->beacon_ies); - - if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC && - !beacon_ies) { - /* - * Wait up to one beacon interval ... - * should this be more if we miss one? - */ - sdata_info(sdata, "waiting for beacon from %pM\n", - ifmgd->bssid); - assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval); - assoc_data->need_beacon = true; - } else if (beacon_ies) { - const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, - beacon_ies->data, - beacon_ies->len); - u8 dtim_count = 0; - - if (tim_ie && tim_ie[1] >= sizeof(struct ieee80211_tim_ie)) { - const struct ieee80211_tim_ie *tim; - tim = (void *)(tim_ie + 2); - ifmgd->dtim_period = tim->dtim_period; - dtim_count = tim->dtim_count; - } - assoc_data->have_beacon = true; - assoc_data->timeout = jiffies; + if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + const struct cfg80211_bss_ies *beacon_ies; - if (local->hw.flags & IEEE80211_HW_TIMING_BEACON_ONLY) { - sdata->vif.bss_conf.sync_tsf = beacon_ies->tsf; - sdata->vif.bss_conf.sync_device_ts = - bss->device_ts_beacon; - sdata->vif.bss_conf.sync_dtim_count = dtim_count; + rcu_read_lock(); + beacon_ies = rcu_dereference(req->bss->beacon_ies); + if (!beacon_ies) { + /* + * Wait up to one beacon interval ... + * should this be more if we miss one? + */ + sdata_info(sdata, "waiting for beacon from %pM\n", + ifmgd->bssid); + assoc_data->timeout = + TU_TO_EXP_TIME(req->bss->beacon_interval); + } else { + const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM, + beacon_ies->data, + beacon_ies->len); + if (tim_ie && tim_ie[1] >= + sizeof(struct ieee80211_tim_ie)) { + const struct ieee80211_tim_ie *tim; + tim = (void *)(tim_ie + 2); + ifmgd->dtim_period = tim->dtim_period; + } + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; + assoc_data->timeout = jiffies; } + rcu_read_unlock(); } else { + assoc_data->have_beacon = true; + assoc_data->sent_assoc = false; assoc_data->timeout = jiffies; } - rcu_read_unlock(); - run_again(ifmgd, assoc_data->timeout); if (bss->corrupt_data) { @@ -4111,6 +4042,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, mutex_unlock(&ifmgd->mtx); out: + mutex_lock(&sdata->local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); + if (sent_frame) __cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); @@ -4151,6 +4086,10 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, __cfg80211_send_disassoc(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); + mutex_lock(&sdata->local->mtx); + ieee80211_recalc_idle(sdata->local); + mutex_unlock(&sdata->local->mtx); + return 0; } diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index cc79b4a2e821..82baf5b6ecf4 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -113,15 +113,6 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) * notify the AP about us leaving the channel and stop all * STA interfaces. */ - - /* - * Stop queues and transmit all frames queued by the driver - * before sending nullfunc to enable powersave at the AP. - */ - ieee80211_stop_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); - drv_flush(local, false); - mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) @@ -142,9 +133,12 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) sdata, BSS_CHANGED_BEACON_ENABLED); } - if (sdata->vif.type == NL80211_IFTYPE_STATION && - sdata->u.mgd.associated) - ieee80211_offchannel_ps_enable(sdata); + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { + netif_tx_stop_all_queues(sdata->dev); + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.associated) + ieee80211_offchannel_ps_enable(sdata); + } } mutex_unlock(&local->iflist_mtx); } @@ -172,6 +166,20 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) sdata->u.mgd.associated) ieee80211_offchannel_ps_disable(sdata); + if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { + /* + * This may wake up queues even though the driver + * currently has them stopped. This is not very + * likely, since the driver won't have gotten any + * (or hardly any) new packets while we weren't + * on the right channel, and even if it happens + * it will at most lead to queueing up one more + * packet per queue in mac80211 rather than on + * the interface qdisc. + */ + netif_tx_wake_all_queues(sdata->dev); + } + if (test_and_clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state)) { sdata->vif.bss_conf.enable_beacon = true; @@ -180,9 +188,6 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) } } mutex_unlock(&local->iflist_mtx); - - ieee80211_wake_queues_by_reason(&local->hw, - IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); } void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) diff --git a/trunk/net/mac80211/pm.c b/trunk/net/mac80211/pm.c index 53801d20176d..e45b83610e85 100644 --- a/trunk/net/mac80211/pm.c +++ b/trunk/net/mac80211/pm.c @@ -228,13 +228,3 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) * ieee80211_reconfig(), which is also needed for hardware * hang/firmware failure/etc. recovery. */ - -void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp) -{ - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); - - cfg80211_report_wowlan_wakeup(&sdata->wdev, wakeup, gfp); -} -EXPORT_SYMBOL(ieee80211_report_wowlan_wakeup); diff --git a/trunk/net/mac80211/rc80211_minstrel_ht.c b/trunk/net/mac80211/rc80211_minstrel_ht.c index 5bb316aff21a..9f9c453bc45d 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht.c @@ -231,6 +231,10 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) if (!mr->cur_tp) continue; + /* ignore the lowest rate of each single-stream group */ + if (!i && minstrel_mcs_groups[group].streams == 1) + continue; + if ((mr->cur_tp > cur_prob_tp && mr->probability > MINSTREL_FRAC(3, 4)) || mr->probability > cur_prob) { mg->max_prob_rate = index; diff --git a/trunk/net/mac80211/rc80211_minstrel_ht_debugfs.c b/trunk/net/mac80211/rc80211_minstrel_ht_debugfs.c index f2b7d26370f0..e788f76a1dfe 100644 --- a/trunk/net/mac80211/rc80211_minstrel_ht_debugfs.c +++ b/trunk/net/mac80211/rc80211_minstrel_ht_debugfs.c @@ -38,8 +38,8 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) file->private_data = ms; p = ms->buf; - p += sprintf(p, "type rate throughput ewma prob this prob " - "retry this succ/attempt success attempts\n"); + p += sprintf(p, "type rate throughput ewma prob this prob " + "this succ/attempt success attempts\n"); for (i = 0; i < MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS; i++) { char htmode = '2'; char gimode = 'L'; @@ -64,19 +64,18 @@ minstrel_ht_stats_open(struct inode *inode, struct file *file) *(p++) = (idx == mi->max_tp_rate) ? 'T' : ' '; *(p++) = (idx == mi->max_tp_rate2) ? 't' : ' '; *(p++) = (idx == mi->max_prob_rate) ? 'P' : ' '; - p += sprintf(p, " MCS%-2u", (minstrel_mcs_groups[i].streams - 1) * + p += sprintf(p, "MCS%-2u", (minstrel_mcs_groups[i].streams - 1) * MCS_GROUP_RATES + j); tp = mr->cur_tp / 10; prob = MINSTREL_TRUNC(mr->cur_prob * 1000); eprob = MINSTREL_TRUNC(mr->probability * 1000); - p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " - "%3u %3u(%3u) %8llu %8llu\n", + p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " + "%3u(%3u) %8llu %8llu\n", tp / 10, tp % 10, eprob / 10, eprob % 10, prob / 10, prob % 10, - mr->retry_count, mr->last_success, mr->last_attempts, (unsigned long long)mr->succ_hist, diff --git a/trunk/net/mac80211/rx.c b/trunk/net/mac80211/rx.c index b5f1bba7ffe1..a19089565c4b 100644 --- a/trunk/net/mac80211/rx.c +++ b/trunk/net/mac80211/rx.c @@ -668,9 +668,9 @@ static inline u16 seq_sub(u16 sq1, u16 sq2) static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, struct tid_ampdu_rx *tid_agg_rx, - int index, - struct sk_buff_head *frames) + int index) { + struct ieee80211_local *local = sdata->local; struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; struct ieee80211_rx_status *status; @@ -684,7 +684,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, tid_agg_rx->reorder_buf[index] = NULL; status = IEEE80211_SKB_RXCB(skb); status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; - __skb_queue_tail(frames, skb); + skb_queue_tail(&local->rx_skb_queue, skb); no_frame: tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); @@ -692,8 +692,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata, struct tid_ampdu_rx *tid_agg_rx, - u16 head_seq_num, - struct sk_buff_head *frames) + u16 head_seq_num) { int index; @@ -702,8 +701,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; - ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, - frames); + ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); } } @@ -719,8 +717,7 @@ static void ieee80211_release_reorder_frames(struct ieee80211_sub_if_data *sdata #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, - struct tid_ampdu_rx *tid_agg_rx, - struct sk_buff_head *frames) + struct tid_ampdu_rx *tid_agg_rx) { int index, j; @@ -749,8 +746,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, ht_dbg_ratelimited(sdata, "release an RX reorder frame due to timeout on earlier frames\n"); - ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, - frames); + ieee80211_release_reorder_frame(sdata, tid_agg_rx, j); /* * Increment the head seq# also for the skipped slots. @@ -760,8 +756,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, skipped = 0; } } else while (tid_agg_rx->reorder_buf[index]) { - ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, - frames); + ieee80211_release_reorder_frame(sdata, tid_agg_rx, index); index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; } @@ -793,8 +788,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, */ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata, struct tid_ampdu_rx *tid_agg_rx, - struct sk_buff *skb, - struct sk_buff_head *frames) + struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; u16 sc = le16_to_cpu(hdr->seq_ctrl); @@ -822,7 +816,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); /* release stored frames up to new head to stack */ ieee80211_release_reorder_frames(sdata, tid_agg_rx, - head_seq_num, frames); + head_seq_num); } /* Now the new frame is always in the range of the reordering buffer */ @@ -852,7 +846,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata tid_agg_rx->reorder_buf[index] = skb; tid_agg_rx->reorder_time[index] = jiffies; tid_agg_rx->stored_mpdu_num++; - ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); + ieee80211_sta_reorder_release(sdata, tid_agg_rx); out: spin_unlock(&tid_agg_rx->reorder_lock); @@ -863,8 +857,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns * true if the MPDU was buffered, false if it should be processed. */ -static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, - struct sk_buff_head *frames) +static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) { struct sk_buff *skb = rx->skb; struct ieee80211_local *local = rx->local; @@ -929,12 +922,11 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, * sure that we cannot get to it any more before doing * anything with it. */ - if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb, - frames)) + if (ieee80211_sta_manage_reorder_buf(rx->sdata, tid_agg_rx, skb)) return; dont_reorder: - __skb_queue_tail(frames, skb); + skb_queue_tail(&local->rx_skb_queue, skb); } static ieee80211_rx_result debug_noinline @@ -1460,10 +1452,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) } } - /* mesh power save support */ - if (ieee80211_vif_is_mesh(&rx->sdata->vif)) - ieee80211_mps_rx_h_sta_process(sta, hdr); - /* * Drop (qos-)data::nullfunc frames silently, since they * are used only to control station power saving mode. @@ -2102,10 +2090,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(fwd_hdr->addr1)) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_mcast); memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN); - /* update power mode indication when forwarding */ - ieee80211_mps_set_frame_flags(sdata, NULL, fwd_hdr); } else if (!mesh_nexthop_lookup(fwd_skb, sdata)) { - /* mesh power mode flags updated in mesh_nexthop_lookup */ IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_unicast); } else { /* unable to resolve next hop */ @@ -2192,7 +2177,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) } static ieee80211_rx_result debug_noinline -ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) +ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) { struct sk_buff *skb = rx->skb; struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; @@ -2231,7 +2216,7 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) spin_lock(&tid_agg_rx->reorder_lock); /* release stored frames up to start of BAR */ ieee80211_release_reorder_frames(rx->sdata, tid_agg_rx, - start_seq_num, frames); + start_seq_num); spin_unlock(&tid_agg_rx->reorder_lock); kfree_skb(skb); @@ -2816,8 +2801,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, } } -static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, - struct sk_buff_head *frames) +static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx) { ieee80211_rx_result res = RX_DROP_MONITOR; struct sk_buff *skb; @@ -2829,9 +2813,15 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, goto rxh_next; \ } while (0); - spin_lock_bh(&rx->local->rx_path_lock); + spin_lock(&rx->local->rx_skb_queue.lock); + if (rx->local->running_rx_handler) + goto unlock; + + rx->local->running_rx_handler = true; + + while ((skb = __skb_dequeue(&rx->local->rx_skb_queue))) { + spin_unlock(&rx->local->rx_skb_queue.lock); - while ((skb = __skb_dequeue(frames))) { /* * all the other fields are valid across frames * that belong to an aMPDU since they are on the @@ -2852,12 +2842,7 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, #endif CALL_RXH(ieee80211_rx_h_amsdu) CALL_RXH(ieee80211_rx_h_data) - - /* special treatment -- needs the queue */ - res = ieee80211_rx_h_ctrl(rx, frames); - if (res != RX_CONTINUE) - goto rxh_next; - + CALL_RXH(ieee80211_rx_h_ctrl); CALL_RXH(ieee80211_rx_h_mgmt_check) CALL_RXH(ieee80211_rx_h_action) CALL_RXH(ieee80211_rx_h_userspace_mgmt) @@ -2866,20 +2851,20 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx, rxh_next: ieee80211_rx_handlers_result(rx, res); - + spin_lock(&rx->local->rx_skb_queue.lock); #undef CALL_RXH } - spin_unlock_bh(&rx->local->rx_path_lock); + rx->local->running_rx_handler = false; + + unlock: + spin_unlock(&rx->local->rx_skb_queue.lock); } static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) { - struct sk_buff_head reorder_release; ieee80211_rx_result res = RX_DROP_MONITOR; - __skb_queue_head_init(&reorder_release); - #define CALL_RXH(rxh) \ do { \ res = rxh(rx); \ @@ -2889,9 +2874,9 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) CALL_RXH(ieee80211_rx_h_check) - ieee80211_rx_reorder_ampdu(rx, &reorder_release); + ieee80211_rx_reorder_ampdu(rx); - ieee80211_rx_handlers(rx, &reorder_release); + ieee80211_rx_handlers(rx); return; rxh_next: @@ -2906,7 +2891,6 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) */ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) { - struct sk_buff_head frames; struct ieee80211_rx_data rx = { .sta = sta, .sdata = sta->sdata, @@ -2922,13 +2906,11 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) if (!tid_agg_rx) return; - __skb_queue_head_init(&frames); - spin_lock(&tid_agg_rx->reorder_lock); - ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames); + ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx); spin_unlock(&tid_agg_rx->reorder_lock); - ieee80211_rx_handlers(&rx, &frames); + ieee80211_rx_handlers(&rx); } /* main receive path */ diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index 6d0b89e4aa31..607684c47d55 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -27,15 +27,22 @@ #define IEEE80211_PROBE_DELAY (HZ / 33) #define IEEE80211_CHANNEL_TIME (HZ / 33) -#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 9) +#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8) + +static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) +{ + struct ieee80211_bss *bss = (void *)cbss->priv; + + kfree(bss_mesh_id(bss)); + kfree(bss_mesh_cfg(bss)); +} void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss) { if (!bss) return; - cfg80211_put_bss(local->hw.wiphy, - container_of((void *)bss, struct cfg80211_bss, priv)); + cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); } static bool is_uapsd_supported(struct ieee802_11_elems *elems) @@ -78,12 +85,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local, if (!cbss) return NULL; + cbss->free_priv = ieee80211_rx_bss_free; bss = (void *)cbss->priv; - if (beacon) - bss->device_ts_beacon = rx_status->device_timestamp; - else - bss->device_ts_presp = rx_status->device_timestamp; + bss->device_ts = rx_status->device_timestamp; if (elems->parse_error) { if (beacon) @@ -141,6 +146,9 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->valid_data |= IEEE80211_BSS_VALID_WMM; } + if (!beacon) + bss->last_probe_resp = jiffies; + return bss; } @@ -334,9 +342,6 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) ieee80211_offchannel_stop_vifs(local); - /* ensure nullfunc is transmitted before leaving operating channel */ - drv_flush(local, false); - ieee80211_configure_filter(local); /* We need to set power level at maximum rate for scanning. */ @@ -385,11 +390,6 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, int i; struct ieee80211_sub_if_data *sdata; enum ieee80211_band band = local->hw.conf.channel->band; - u32 tx_flags; - - tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; - if (local->scan_req->no_cck) - tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; sdata = rcu_dereference_protected(local->scan_sdata, lockdep_is_held(&local->mtx)); @@ -401,7 +401,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, local->scan_req->ssids[i].ssid_len, local->scan_req->ie, local->scan_req->ie_len, local->scan_req->rates[band], false, - tx_flags, local->hw.conf.channel, true); + local->scan_req->no_cck, + local->hw.conf.channel, true); /* * After sending probe requests, wait for probe responses @@ -545,6 +546,8 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, bool associated = false; bool tx_empty = true; bool bad_latency; + bool listen_int_exceeded; + unsigned long min_beacon_int = 0; struct ieee80211_sub_if_data *sdata; struct ieee80211_channel *next_chan; enum mac80211_scan_state next_scan_state; @@ -563,6 +566,11 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, if (sdata->u.mgd.associated) { associated = true; + if (sdata->vif.bss_conf.beacon_int < + min_beacon_int || min_beacon_int == 0) + min_beacon_int = + sdata->vif.bss_conf.beacon_int; + if (!qdisc_all_tx_empty(sdata->dev)) { tx_empty = false; break; @@ -579,19 +587,34 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, * see if we can scan another channel without interfering * with the current traffic situation. * - * Keep good latency, do not stay off-channel more than 125 ms. + * Since we don't know if the AP has pending frames for us + * we can only check for our tx queues and use the current + * pm_qos requirements for rx. Hence, if no tx traffic occurs + * at all we will scan as many channels in a row as the pm_qos + * latency allows us to. Additionally we also check for the + * currently negotiated listen interval to prevent losing + * frames unnecessarily. + * + * Otherwise switch back to the operating channel. */ bad_latency = time_after(jiffies + - ieee80211_scan_get_channel_time(next_chan), - local->leave_oper_channel_time + HZ / 8); + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY))); + + listen_int_exceeded = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(min_beacon_int * 1024) * + local->hw.conf.listen_interval); if (associated && !tx_empty) { if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) next_scan_state = SCAN_ABORT; else next_scan_state = SCAN_SUSPEND; - } else if (associated && bad_latency) { + } else if (associated && (bad_latency || listen_int_exceeded)) { next_scan_state = SCAN_SUSPEND; } else { next_scan_state = SCAN_SET_CHANNEL; diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index 19db20a58e23..227233c3ff7f 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -120,8 +120,6 @@ static void cleanup_single_sta(struct sta_info *sta) if (sta->sdata->vif.type == NL80211_IFTYPE_AP || sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ps = &sdata->bss->ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else return; @@ -137,8 +135,13 @@ static void cleanup_single_sta(struct sta_info *sta) ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); } - if (ieee80211_vif_is_mesh(&sdata->vif)) - mesh_sta_cleanup(sta); +#ifdef CONFIG_MAC80211_MESH + if (ieee80211_vif_is_mesh(&sdata->vif)) { + mesh_accept_plinks_update(sdata); + mesh_plink_deactivate(sta); + del_timer_sync(&sta->plink_timer); + } +#endif cancel_work_sync(&sta->drv_unblock_wk); @@ -584,12 +587,6 @@ void sta_info_recalc_tim(struct sta_info *sta) ps = &sta->sdata->bss->ps; id = sta->sta.aid; -#ifdef CONFIG_MAC80211_MESH - } else if (ieee80211_vif_is_mesh(&sta->sdata->vif)) { - ps = &sta->sdata->u.mesh.ps; - /* TIM map only for PLID <= IEEE80211_MAX_AID */ - id = le16_to_cpu(sta->plid) % IEEE80211_MAX_AID; -#endif } else { return; } @@ -748,9 +745,8 @@ static bool sta_info_cleanup_expire_buffered(struct ieee80211_local *local, bool have_buffered = false; int ac; - /* This is only necessary for stations on BSS/MBSS interfaces */ - if (!sta->sdata->bss && - !ieee80211_vif_is_mesh(&sta->sdata->vif)) + /* This is only necessary for stations on BSS interfaces */ + if (!sta->sdata->bss) return false; for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) @@ -938,11 +934,6 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, if (time_after(jiffies, sta->last_rx + exp_time)) { sta_dbg(sta->sdata, "expiring inactive STA %pM\n", sta->sta.addr); - - if (ieee80211_vif_is_mesh(&sdata->vif) && - test_sta_flag(sta, WLAN_STA_PS_STA)) - atomic_dec(&sdata->u.mesh.ps.num_sta_ps); - WARN_ON(__sta_info_destroy(sta)); } } @@ -1001,8 +992,6 @@ static void clear_sta_ps_flags(void *_sta) if (sdata->vif.type == NL80211_IFTYPE_AP || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) ps = &sdata->bss->ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else return; diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 350578c396c0..af7d78aa5523 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -56,8 +56,6 @@ * @WLAN_STA_INSERTED: This station is inserted into the hash table. * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station. * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. - * @WLAN_STA_MPSP_OWNER: local STA is owner of a mesh Peer Service Period. - * @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP. */ enum ieee80211_sta_info_flags { WLAN_STA_AUTH, @@ -80,8 +78,6 @@ enum ieee80211_sta_info_flags { WLAN_STA_INSERTED, WLAN_STA_RATE_CONTROL, WLAN_STA_TOFFSET_KNOWN, - WLAN_STA_MPSP_OWNER, - WLAN_STA_MPSP_RECIPIENT, }; #define ADDBA_RESP_INTERVAL HZ @@ -286,9 +282,6 @@ struct sta_ampdu_mlme { * @t_offset_setpoint: reference timing offset of this sta to be used when * calculating clockdrift * @ch_width: peer's channel width - * @local_pm: local link-specific power save mode - * @peer_pm: peer-specific power save mode towards local STA - * @nonpeer_pm: STA power save mode towards non-peer neighbors * @debugfs: debug filesystem info * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver @@ -298,7 +291,6 @@ struct sta_ampdu_mlme { * @beacon_loss_count: number of times beacon loss has triggered * @supports_40mhz: tracks whether the station advertised 40 MHz support * as we overwrite its HT parameters with the currently used value - * @rcu_head: RCU head used for freeing this station struct */ struct sta_info { /* General information, mostly static */ @@ -387,10 +379,6 @@ struct sta_info { s64 t_offset; s64 t_offset_setpoint; enum nl80211_chan_width ch_width; - /* mesh power save */ - enum nl80211_mesh_power_mode local_pm; - enum nl80211_mesh_power_mode peer_pm; - enum nl80211_mesh_power_mode nonpeer_pm; #endif #ifdef CONFIG_MAC80211_DEBUGFS diff --git a/trunk/net/mac80211/status.c b/trunk/net/mac80211/status.c index 43439203f4e4..07d99578a2b1 100644 --- a/trunk/net/mac80211/status.c +++ b/trunk/net/mac80211/status.c @@ -335,8 +335,7 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, if (dropped) acked = false; - if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX | - IEEE80211_TX_INTFL_MLME_CONN_TX)) { + if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { struct ieee80211_sub_if_data *sdata = NULL; struct ieee80211_sub_if_data *iter_sdata; u64 cookie = (unsigned long)skb; @@ -358,13 +357,10 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local, sdata = rcu_dereference(local->p2p_sdata); } - if (!sdata) { + if (!sdata) skb->dev = NULL; - } else if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) { - ieee80211_mgd_conn_tx_status(sdata, hdr->frame_control, - acked); - } else if (ieee80211_is_nullfunc(hdr->frame_control) || - ieee80211_is_qos_nullfunc(hdr->frame_control)) { + else if (ieee80211_is_nullfunc(hdr->frame_control) || + ieee80211_is_qos_nullfunc(hdr->frame_control)) { cfg80211_probe_status(sdata->dev, hdr->addr1, cookie, acked, GFP_ATOMIC); } else { @@ -472,13 +468,6 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) return; } - /* mesh Peer Service Period support */ - if (ieee80211_vif_is_mesh(&sta->sdata->vif) && - ieee80211_is_data_qos(fc)) - ieee80211_mpsp_trigger_process( - ieee80211_get_qos_ctl(hdr), - sta, true, acked); - if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && (rates_idx != -1)) sta->last_tx_rate = info->status.rates[rates_idx]; @@ -513,7 +502,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) IEEE80211_BAR_CTRL_TID_INFO_MASK) >> IEEE80211_BAR_CTRL_TID_INFO_SHIFT; - ieee80211_set_bar_pending(sta, tid, ssn); + if (local->hw.flags & + IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL) + ieee80211_stop_tx_ba_session(&sta->sta, tid); + else + ieee80211_set_bar_pending(sta, tid, ssn); } } diff --git a/trunk/net/mac80211/trace.h b/trunk/net/mac80211/trace.h index 0bdd7aeb8958..6ca53d64cb28 100644 --- a/trunk/net/mac80211/trace.h +++ b/trunk/net/mac80211/trace.h @@ -36,7 +36,7 @@ __entry->control_freq = (c)->chan->center_freq; \ __entry->chan_width = (c)->width; \ __entry->center_freq1 = (c)->center_freq1; \ - __entry->center_freq2 = (c)->center_freq2; + __entry->center_freq1 = (c)->center_freq2; #define CHANDEF_PR_FMT " control:%d MHz width:%d center: %d/%d MHz" #define CHANDEF_PR_ARG __entry->control_freq, __entry->chan_width, \ __entry->center_freq1, __entry->center_freq2 @@ -340,7 +340,6 @@ TRACE_EVENT(drv_bss_info_changed, __field(u16, assoc_cap) __field(u64, sync_tsf) __field(u32, sync_device_ts) - __field(u8, sync_dtim_count) __field(u32, basic_rates) __array(int, mcast_rate, IEEE80211_NUM_BANDS) __field(u16, ht_operation_mode) @@ -380,7 +379,6 @@ TRACE_EVENT(drv_bss_info_changed, __entry->assoc_cap = info->assoc_capability; __entry->sync_tsf = info->sync_tsf; __entry->sync_device_ts = info->sync_device_ts; - __entry->sync_dtim_count = info->sync_dtim_count; __entry->basic_rates = info->basic_rates; memcpy(__entry->mcast_rate, info->mcast_rate, sizeof(__entry->mcast_rate)); diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index f476aa6a771d..a2cb6a302cc7 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -329,8 +329,6 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) if (sdata->vif.type == NL80211_IFTYPE_AP) ps = &sdata->u.ap.ps; - else if (ieee80211_vif_is_mesh(&sdata->vif)) - ps = &sdata->u.mesh.ps; else continue; @@ -374,20 +372,18 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) /* * broadcast/multicast frame * - * If any of the associated/peer stations is in power save mode, + * If any of the associated stations is in power save mode, * the frame is buffered to be sent after DTIM beacon frame. * This is done either by the hardware or us. */ - /* powersaving STAs currently only in AP/VLAN/mesh mode */ + /* powersaving STAs currently only in AP/VLAN mode */ if (tx->sdata->vif.type == NL80211_IFTYPE_AP || tx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { if (!tx->sdata->bss) return TX_CONTINUE; ps = &tx->sdata->bss->ps; - } else if (ieee80211_vif_is_mesh(&tx->sdata->vif)) { - ps = &tx->sdata->u.mesh.ps; } else { return TX_CONTINUE; } @@ -598,8 +594,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) break; } - if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED && - !ieee80211_is_deauth(hdr->frame_control))) + if (unlikely(tx->key && tx->key->flags & KEY_FLAG_TAINTED)) return TX_DROP; if (!skip_hw && tx->key && @@ -1230,21 +1225,6 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, spin_lock_irqsave(&local->queue_stop_reason_lock, flags); if (local->queue_stop_reasons[q] || (!txpending && !skb_queue_empty(&local->pending[q]))) { - if (unlikely(info->flags & - IEEE80211_TX_INTFL_OFFCHAN_TX_OK && - local->queue_stop_reasons[q] & - ~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) { - /* - * Drop off-channel frames if queues are stopped - * for any reason other than off-channel - * operation. Never queue them. - */ - spin_unlock_irqrestore( - &local->queue_stop_reason_lock, flags); - ieee80211_purge_tx_queue(&local->hw, skbs); - return true; - } - /* * Since queue is stopped, queue up frames for later * transmission from the tx-pending tasklet when the @@ -1492,14 +1472,12 @@ void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, hdr = (struct ieee80211_hdr *) skb->data; info->control.vif = &sdata->vif; - if (ieee80211_vif_is_mesh(&sdata->vif)) { - if (ieee80211_is_data(hdr->frame_control) && - is_unicast_ether_addr(hdr->addr1)) { - if (mesh_nexthop_resolve(skb, sdata)) - return; /* skb queued: don't free */ - } else { - ieee80211_mps_set_frame_flags(sdata, NULL, hdr); - } + if (ieee80211_vif_is_mesh(&sdata->vif) && + ieee80211_is_data(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1) && + mesh_nexthop_resolve(skb, sdata)) { + /* skb queued: don't free */ + return; } ieee80211_set_qos_hdr(sdata, skb); @@ -2466,14 +2444,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, 2 + /* NULL SSID */ 2 + 8 + /* supported rates */ 2 + 3 + /* DS params */ - 256 + /* TIM IE */ 2 + (IEEE80211_MAX_SUPP_RATES - 8) + 2 + sizeof(struct ieee80211_ht_cap) + 2 + sizeof(struct ieee80211_ht_operation) + 2 + sdata->u.mesh.mesh_id_len + 2 + sizeof(struct ieee80211_meshconf_ie) + - sdata->u.mesh.ie_len + - 2 + sizeof(__le16)); /* awake window */ + sdata->u.mesh.ie_len); if (!skb) goto out; @@ -2485,7 +2461,6 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, eth_broadcast_addr(mgmt->da); memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - ieee80211_mps_set_frame_flags(sdata, NULL, (void *) mgmt); mgmt->u.beacon.beacon_int = cpu_to_le16(sdata->vif.bss_conf.beacon_int); mgmt->u.beacon.capab_info |= cpu_to_le16( @@ -2499,14 +2474,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, if (ieee80211_add_srates_ie(sdata, skb, true, band) || mesh_add_ds_params_ie(skb, sdata) || - ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb) || ieee80211_add_ext_srates_ie(sdata, skb, true, band) || mesh_add_rsn_ie(skb, sdata) || mesh_add_ht_cap_ie(skb, sdata) || mesh_add_ht_oper_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) || mesh_add_meshconf_ie(skb, sdata) || - mesh_add_awake_window_ie(skb, sdata) || mesh_add_vendor_ies(skb, sdata)) { pr_err("o11s: couldn't add ies!\n"); goto out; @@ -2760,8 +2733,6 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, goto out; ps = &sdata->u.ap.ps; - } else if (ieee80211_vif_is_mesh(&sdata->vif)) { - ps = &sdata->u.mesh.ps; } else { goto out; } diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 6cb71a350edd..7519018ff71a 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -805,10 +805,6 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, elems->peering = pos; elems->peering_len = elen; break; - case WLAN_EID_MESH_AWAKE_WINDOW: - if (elen >= 2) - elems->awake_window = (void *)pos; - break; case WLAN_EID_PREQ: elems->preq = pos; elems->preq_len = elen; @@ -1034,8 +1030,7 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, u16 transaction, u16 auth_alg, u16 status, u8 *extra, size_t extra_len, const u8 *da, - const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx, - u32 tx_flags) + const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx) { struct ieee80211_local *local = sdata->local; struct sk_buff *skb; @@ -1068,8 +1063,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, WARN_ON(err); } - IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT | - tx_flags; + IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; ieee80211_tx_skb(sdata, skb); } @@ -1283,7 +1277,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, const u8 *ssid, size_t ssid_len, const u8 *ie, size_t ie_len, - u32 ratemask, bool directed, u32 tx_flags, + u32 ratemask, bool directed, bool no_cck, struct ieee80211_channel *channel, bool scan) { struct sk_buff *skb; @@ -1292,7 +1286,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ssid, ssid_len, ie, ie_len, directed); if (skb) { - IEEE80211_SKB_CB(skb)->flags |= tx_flags; + if (no_cck) + IEEE80211_SKB_CB(skb)->flags |= + IEEE80211_TX_CTL_NO_CCK_RATE; if (scan) ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); else @@ -1542,10 +1538,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) changed |= BSS_CHANGED_ASSOC | BSS_CHANGED_ARP_FILTER | BSS_CHANGED_PS; - - if (sdata->u.mgd.dtim_period) - changed |= BSS_CHANGED_DTIM_PERIOD; - mutex_lock(&sdata->u.mgd.mtx); ieee80211_bss_info_change_notify(sdata, changed); mutex_unlock(&sdata->u.mgd.mtx); diff --git a/trunk/net/mac80211/wme.c b/trunk/net/mac80211/wme.c index afba19cb6f87..906f00cd6d2f 100644 --- a/trunk/net/mac80211/wme.c +++ b/trunk/net/mac80211/wme.c @@ -191,15 +191,6 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, /* qos header is 2 bytes */ *p++ = ack_policy | tid; - if (ieee80211_vif_is_mesh(&sdata->vif)) { - /* preserve RSPI and Mesh PS Level bit */ - *p &= ((IEEE80211_QOS_CTL_RSPI | - IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8); - - /* Nulls don't have a mesh header (frame body) */ - if (!ieee80211_is_qos_nullfunc(hdr->frame_control)) - *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8); - } else { - *p = 0; - } + *p = ieee80211_vif_is_mesh(&sdata->vif) ? + (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; } diff --git a/trunk/net/nfc/llcp/llcp.c b/trunk/net/nfc/llcp/llcp.c index 746f5a2f9804..85bc75c38dea 100644 --- a/trunk/net/nfc/llcp/llcp.c +++ b/trunk/net/nfc/llcp/llcp.c @@ -549,13 +549,14 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) pr_err("No LLCP device\n"); return -ENODEV; } - if (gb_len < 3) - return -EINVAL; memset(local->remote_gb, 0, NFC_MAX_GT_LEN); memcpy(local->remote_gb, gb, gb_len); local->remote_gb_len = gb_len; + if (local->remote_gb == NULL || local->remote_gb_len == 0) + return -ENODEV; + if (memcmp(local->remote_gb, llcp_magic, 3)) { pr_err("MAC does not support LLCP\n"); return -EINVAL; diff --git a/trunk/net/wireless/core.c b/trunk/net/wireless/core.c index f0a1bbe95cff..ce827242f390 100644 --- a/trunk/net/wireless/core.c +++ b/trunk/net/wireless/core.c @@ -715,7 +715,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) kfree(reg); } list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) - cfg80211_put_bss(&rdev->wiphy, &scan->pub); + cfg80211_put_bss(&scan->pub); kfree(rdev); } diff --git a/trunk/net/wireless/core.h b/trunk/net/wireless/core.h index 37d70dc2fe82..8396f7671c8d 100644 --- a/trunk/net/wireless/core.h +++ b/trunk/net/wireless/core.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -123,10 +124,9 @@ static inline void assert_cfg80211_lock(void) struct cfg80211_internal_bss { struct list_head list; - struct list_head hidden_list; struct rb_node rbn; unsigned long ts; - unsigned long refcount; + struct kref ref; atomic_t hold; /* must be last because of priv member */ diff --git a/trunk/net/wireless/ibss.c b/trunk/net/wireless/ibss.c index d80e47194d49..9b9551e4a6f9 100644 --- a/trunk/net/wireless/ibss.c +++ b/trunk/net/wireless/ibss.c @@ -37,7 +37,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); } cfg80211_hold_bss(bss_from_pub(bss)); @@ -182,7 +182,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); } wdev->current_bss = NULL; diff --git a/trunk/net/wireless/mlme.c b/trunk/net/wireless/mlme.c index 8e6920728c43..461e692cdfec 100644 --- a/trunk/net/wireless/mlme.c +++ b/trunk/net/wireless/mlme.c @@ -58,7 +58,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, */ if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && cfg80211_sme_failed_reassoc(wdev)) { - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); goto out; } @@ -70,7 +70,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, * do not call connect_result() now because the * sme will schedule work that does it later. */ - cfg80211_put_bss(wiphy, bss); + cfg80211_put_bss(bss); goto out; } @@ -108,7 +108,7 @@ void __cfg80211_send_deauth(struct net_device *dev, if (wdev->current_bss && ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; was_current = true; } @@ -164,7 +164,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { cfg80211_sme_disassoc(dev, wdev->current_bss); cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; } else WARN_ON(1); @@ -324,7 +324,7 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, err = rdev_auth(rdev, dev, &req); out: - cfg80211_put_bss(&rdev->wiphy, req.bss); + cfg80211_put_bss(req.bss); return err; } @@ -432,7 +432,7 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, if (err) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; - cfg80211_put_bss(&rdev->wiphy, req.bss); + cfg80211_put_bss(req.bss); } return err; @@ -514,7 +514,7 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, if (wdev->sme_state != CFG80211_SME_CONNECTED) return -ENOTCONN; - if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) + if (WARN_ON(!wdev->current_bss)) return -ENOTCONN; memset(&req, 0, sizeof(req)); @@ -572,7 +572,7 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(&rdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; } } diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 93bc63eae076..b5978ab4ad7a 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -3057,22 +3057,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME, sinfo->inactive_time)) goto nla_put_failure; - if ((sinfo->filled & (STATION_INFO_RX_BYTES | - STATION_INFO_RX_BYTES64)) && + if ((sinfo->filled & STATION_INFO_RX_BYTES) && nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES, - (u32)sinfo->rx_bytes)) - goto nla_put_failure; - if ((sinfo->filled & (STATION_INFO_TX_BYTES | - NL80211_STA_INFO_TX_BYTES64)) && - nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, - (u32)sinfo->tx_bytes)) - goto nla_put_failure; - if ((sinfo->filled & STATION_INFO_RX_BYTES64) && - nla_put_u64(msg, NL80211_STA_INFO_RX_BYTES64, sinfo->rx_bytes)) goto nla_put_failure; - if ((sinfo->filled & STATION_INFO_TX_BYTES64) && - nla_put_u64(msg, NL80211_STA_INFO_TX_BYTES64, + if ((sinfo->filled & STATION_INFO_TX_BYTES) && + nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, sinfo->tx_bytes)) goto nla_put_failure; if ((sinfo->filled & STATION_INFO_LLID) && @@ -4997,7 +4987,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, const struct cfg80211_bss_ies *ies; void *hdr; struct nlattr *bss; - bool tsf = false; ASSERT_WDEV_LOCK(wdev); @@ -5021,24 +5010,22 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, rcu_read_lock(); ies = rcu_dereference(res->ies); - if (ies) { - if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) - goto fail_unlock_rcu; - tsf = true; - if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, - ies->len, ies->data)) - goto fail_unlock_rcu; + if (ies && ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, + ies->len, ies->data)) { + rcu_read_unlock(); + goto nla_put_failure; } ies = rcu_dereference(res->beacon_ies); - if (ies) { - if (!tsf && nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) - goto fail_unlock_rcu; - if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, - ies->len, ies->data)) - goto fail_unlock_rcu; + if (ies && ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, + ies->len, ies->data)) { + rcu_read_unlock(); + goto nla_put_failure; } rcu_read_unlock(); + if (res->tsf && + nla_put_u64(msg, NL80211_BSS_TSF, res->tsf)) + goto nla_put_failure; if (res->beacon_interval && nla_put_u16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval)) goto nla_put_failure; @@ -5083,8 +5070,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb, return genlmsg_end(msg, hdr); - fail_unlock_rcu: - rcu_read_unlock(); nla_put_failure: genlmsg_cancel(msg, hdr); return -EMSGSIZE; @@ -9338,103 +9323,6 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_report_obss_beacon); -#ifdef CONFIG_PM -void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup, - gfp_t gfp) -{ - struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); - struct sk_buff *msg; - void *hdr; - int err, size = 200; - - trace_cfg80211_report_wowlan_wakeup(wdev->wiphy, wdev, wakeup); - - if (wakeup) - size += wakeup->packet_present_len; - - msg = nlmsg_new(size, gfp); - if (!msg) - return; - - hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_SET_WOWLAN); - if (!hdr) - goto free_msg; - - if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || - nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) - goto free_msg; - - if (wdev->netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, - wdev->netdev->ifindex)) - goto free_msg; - - if (wakeup) { - struct nlattr *reasons; - - reasons = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); - - if (wakeup->disconnect && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) - goto free_msg; - if (wakeup->magic_pkt && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) - goto free_msg; - if (wakeup->gtk_rekey_failure && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) - goto free_msg; - if (wakeup->eap_identity_req && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) - goto free_msg; - if (wakeup->four_way_handshake && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) - goto free_msg; - if (wakeup->rfkill_release && - nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)) - goto free_msg; - - if (wakeup->pattern_idx >= 0 && - nla_put_u32(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, - wakeup->pattern_idx)) - goto free_msg; - - if (wakeup->packet) { - u32 pkt_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211; - u32 len_attr = NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN; - - if (!wakeup->packet_80211) { - pkt_attr = - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023; - len_attr = - NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN; - } - - if (wakeup->packet_len && - nla_put_u32(msg, len_attr, wakeup->packet_len)) - goto free_msg; - - if (nla_put(msg, pkt_attr, wakeup->packet_present_len, - wakeup->packet)) - goto free_msg; - } - - nla_nest_end(msg, reasons); - } - - err = genlmsg_end(msg, hdr); - if (err < 0) - goto free_msg; - - genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, - nl80211_mlme_mcgrp.id, gfp); - return; - - free_msg: - nlmsg_free(msg); -} -EXPORT_SYMBOL(cfg80211_report_wowlan_wakeup); -#endif - void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, enum nl80211_tdls_operation oper, u16 reason_code, gfp_t gfp) diff --git a/trunk/net/wireless/reg.c b/trunk/net/wireless/reg.c index 08d3da2c70ab..6ea626b30a2a 100644 --- a/trunk/net/wireless/reg.c +++ b/trunk/net/wireless/reg.c @@ -2189,15 +2189,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * However if a driver requested this specific regulatory * domain we keep it for its private use */ - if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) { - const struct ieee80211_regdomain *tmp; - - tmp = get_wiphy_regdom(request_wiphy); + if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) rcu_assign_pointer(request_wiphy->regd, rd); - rcu_free_regdom(tmp); - } else { + else kfree(rd); - } rd = NULL; diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c index b7a167984986..01592d7d4789 100644 --- a/trunk/net/wireless/scan.c +++ b/trunk/net/wireless/scan.c @@ -19,142 +19,55 @@ #include "wext-compat.h" #include "rdev-ops.h" -/** - * DOC: BSS tree/list structure - * - * At the top level, the BSS list is kept in both a list in each - * registered device (@bss_list) as well as an RB-tree for faster - * lookup. In the RB-tree, entries can be looked up using their - * channel, MESHID, MESHCONF (for MBSSes) or channel, BSSID, SSID - * for other BSSes. - * - * Due to the possibility of hidden SSIDs, there's a second level - * structure, the "hidden_list" and "hidden_beacon_bss" pointer. - * The hidden_list connects all BSSes belonging to a single AP - * that has a hidden SSID, and connects beacon and probe response - * entries. For a probe response entry for a hidden SSID, the - * hidden_beacon_bss pointer points to the BSS struct holding the - * beacon's information. - * - * Reference counting is done for all these references except for - * the hidden_list, so that a beacon BSS struct that is otherwise - * not referenced has one reference for being on the bss_list and - * one for each probe response entry that points to it using the - * hidden_beacon_bss pointer. When a BSS struct that has such a - * pointer is get/put, the refcount update is also propagated to - * the referenced struct, this ensure that it cannot get removed - * while somebody is using the probe response version. - * - * Note that the hidden_beacon_bss pointer never changes, due to - * the reference counting. Therefore, no locking is needed for - * it. - * - * Also note that the hidden_beacon_bss pointer is only relevant - * if the driver uses something other than the IEs, e.g. private - * data stored stored in the BSS struct, since the beacon IEs are - * also linked into the probe response struct. - */ - #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ) -static void bss_free(struct cfg80211_internal_bss *bss) +static void bss_release(struct kref *ref) { struct cfg80211_bss_ies *ies; + struct cfg80211_internal_bss *bss; + + bss = container_of(ref, struct cfg80211_internal_bss, ref); if (WARN_ON(atomic_read(&bss->hold))) return; + if (bss->pub.free_priv) + bss->pub.free_priv(&bss->pub); + ies = (void *)rcu_access_pointer(bss->pub.beacon_ies); - if (ies && !bss->pub.hidden_beacon_bss) + if (ies) kfree_rcu(ies, rcu_head); ies = (void *)rcu_access_pointer(bss->pub.proberesp_ies); if (ies) kfree_rcu(ies, rcu_head); - /* - * This happens when the module is removed, it doesn't - * really matter any more save for completeness - */ - if (!list_empty(&bss->hidden_list)) - list_del(&bss->hidden_list); - kfree(bss); } -static inline void bss_ref_get(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *bss) -{ - lockdep_assert_held(&dev->bss_lock); - - bss->refcount++; - if (bss->pub.hidden_beacon_bss) { - bss = container_of(bss->pub.hidden_beacon_bss, - struct cfg80211_internal_bss, - pub); - bss->refcount++; - } -} - -static inline void bss_ref_put(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *bss) -{ - lockdep_assert_held(&dev->bss_lock); - - if (bss->pub.hidden_beacon_bss) { - struct cfg80211_internal_bss *hbss; - hbss = container_of(bss->pub.hidden_beacon_bss, - struct cfg80211_internal_bss, - pub); - hbss->refcount--; - if (hbss->refcount == 0) - bss_free(hbss); - } - bss->refcount--; - if (bss->refcount == 0) - bss_free(bss); -} - -static bool __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, +/* must hold dev->bss_lock! */ +static void __cfg80211_unlink_bss(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *bss) { - lockdep_assert_held(&dev->bss_lock); - - if (!list_empty(&bss->hidden_list)) { - /* - * don't remove the beacon entry if it has - * probe responses associated with it - */ - if (!bss->pub.hidden_beacon_bss) - return false; - /* - * if it's a probe response entry break its - * link to the other entries in the group - */ - list_del_init(&bss->hidden_list); - } - list_del_init(&bss->list); rb_erase(&bss->rbn, &dev->bss_tree); - bss_ref_put(dev, bss); - return true; + kref_put(&bss->ref, bss_release); } +/* must hold dev->bss_lock! */ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, unsigned long expire_time) { struct cfg80211_internal_bss *bss, *tmp; bool expired = false; - lockdep_assert_held(&dev->bss_lock); - list_for_each_entry_safe(bss, tmp, &dev->bss_list, list) { if (atomic_read(&bss->hold)) continue; if (!time_after(expire_time, bss->ts)) continue; - if (__cfg80211_unlink_bss(dev, bss)) - expired = true; + __cfg80211_unlink_bss(dev, bss); + expired = true; } if (expired) @@ -321,16 +234,15 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, return 0; } +/* must hold dev->bss_lock! */ void cfg80211_bss_age(struct cfg80211_registered_device *dev, unsigned long age_secs) { struct cfg80211_internal_bss *bss; unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); - spin_lock_bh(&dev->bss_lock); list_for_each_entry(bss, &dev->bss_list, list) bss->ts -= age_jiffies; - spin_unlock_bh(&dev->bss_lock); } void cfg80211_bss_expire(struct cfg80211_registered_device *dev) @@ -379,6 +291,26 @@ const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type, } EXPORT_SYMBOL(cfg80211_find_vendor_ie); +static int cmp_ies(u8 num, const u8 *ies1, int len1, const u8 *ies2, int len2) +{ + const u8 *ie1 = cfg80211_find_ie(num, ies1, len1); + const u8 *ie2 = cfg80211_find_ie(num, ies2, len2); + + /* equal if both missing */ + if (!ie1 && !ie2) + return 0; + /* sort missing IE before (left of) present IE */ + if (!ie1) + return -1; + if (!ie2) + return 1; + + /* sort by length first, then by contents */ + if (ie1[1] != ie2[1]) + return ie2[1] - ie1[1]; + return memcmp(ie1 + 2, ie2 + 2, ie1[1]); +} + static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, const u8 *ssid, size_t ssid_len) { @@ -402,30 +334,109 @@ static bool is_bss(struct cfg80211_bss *a, const u8 *bssid, return memcmp(ssidie + 2, ssid, ssid_len) == 0; } -/** - * enum bss_compare_mode - BSS compare mode - * @BSS_CMP_REGULAR: regular compare mode (for insertion and normal find) - * @BSS_CMP_HIDE_ZLEN: find hidden SSID with zero-length mode - * @BSS_CMP_HIDE_NUL: find hidden SSID with NUL-ed out mode - */ -enum bss_compare_mode { - BSS_CMP_REGULAR, - BSS_CMP_HIDE_ZLEN, - BSS_CMP_HIDE_NUL, -}; +static bool is_mesh_bss(struct cfg80211_bss *a) +{ + const struct cfg80211_bss_ies *ies; + const u8 *ie; -static int cmp_bss(struct cfg80211_bss *a, - struct cfg80211_bss *b, - enum bss_compare_mode mode) + if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) + return false; + + ies = rcu_access_pointer(a->ies); + if (!ies) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); + if (!ie) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); + if (!ie) + return false; + + return true; +} + +static bool is_mesh(struct cfg80211_bss *a, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg) +{ + const struct cfg80211_bss_ies *ies; + const u8 *ie; + + if (!WLAN_CAPABILITY_IS_STA_BSS(a->capability)) + return false; + + ies = rcu_access_pointer(a->ies); + if (!ies) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_ID, ies->data, ies->len); + if (!ie) + return false; + if (ie[1] != meshidlen) + return false; + if (memcmp(ie + 2, meshid, meshidlen)) + return false; + + ie = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, ies->data, ies->len); + if (!ie) + return false; + if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) + return false; + + /* + * Ignore mesh capability (last two bytes of the IE) when + * comparing since that may differ between stations taking + * part in the same mesh. + */ + return memcmp(ie + 2, meshcfg, + sizeof(struct ieee80211_meshconf_ie) - 2) == 0; +} + +static int cmp_bss_core(struct cfg80211_bss *a, struct cfg80211_bss *b) { const struct cfg80211_bss_ies *a_ies, *b_ies; - const u8 *ie1 = NULL; - const u8 *ie2 = NULL; - int i, r; + int r; if (a->channel != b->channel) return b->channel->center_freq - a->channel->center_freq; + if (is_mesh_bss(a) && is_mesh_bss(b)) { + a_ies = rcu_access_pointer(a->ies); + if (!a_ies) + return -1; + b_ies = rcu_access_pointer(b->ies); + if (!b_ies) + return 1; + + r = cmp_ies(WLAN_EID_MESH_ID, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); + if (r) + return r; + return cmp_ies(WLAN_EID_MESH_CONFIG, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); + } + + /* + * we can't use compare_ether_addr here since we need a < > operator. + * The binary return value of compare_ether_addr isn't enough + */ + return memcmp(a->bssid, b->bssid, sizeof(a->bssid)); +} + +static int cmp_bss(struct cfg80211_bss *a, + struct cfg80211_bss *b) +{ + const struct cfg80211_bss_ies *a_ies, *b_ies; + int r; + + r = cmp_bss_core(a, b); + if (r) + return r; + a_ies = rcu_access_pointer(a->ies); if (!a_ies) return -1; @@ -433,51 +444,42 @@ static int cmp_bss(struct cfg80211_bss *a, if (!b_ies) return 1; - if (WLAN_CAPABILITY_IS_STA_BSS(a->capability)) - ie1 = cfg80211_find_ie(WLAN_EID_MESH_ID, - a_ies->data, a_ies->len); - if (WLAN_CAPABILITY_IS_STA_BSS(b->capability)) - ie2 = cfg80211_find_ie(WLAN_EID_MESH_ID, - b_ies->data, b_ies->len); - if (ie1 && ie2) { - int mesh_id_cmp; - - if (ie1[1] == ie2[1]) - mesh_id_cmp = memcmp(ie1 + 2, ie2 + 2, ie1[1]); - else - mesh_id_cmp = ie2[1] - ie1[1]; - - ie1 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, - a_ies->data, a_ies->len); - ie2 = cfg80211_find_ie(WLAN_EID_MESH_CONFIG, - b_ies->data, b_ies->len); - if (ie1 && ie2) { - if (mesh_id_cmp) - return mesh_id_cmp; - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - return memcmp(ie1 + 2, ie2 + 2, ie1[1]); - } - } + return cmp_ies(WLAN_EID_SSID, + a_ies->data, a_ies->len, + b_ies->data, b_ies->len); +} - /* - * we can't use compare_ether_addr here since we need a < > operator. - * The binary return value of compare_ether_addr isn't enough - */ - r = memcmp(a->bssid, b->bssid, sizeof(a->bssid)); +static int cmp_hidden_bss(struct cfg80211_bss *a, struct cfg80211_bss *b) +{ + const struct cfg80211_bss_ies *a_ies, *b_ies; + const u8 *ie1; + const u8 *ie2; + int i; + int r; + + r = cmp_bss_core(a, b); if (r) return r; + a_ies = rcu_access_pointer(a->ies); + if (!a_ies) + return -1; + b_ies = rcu_access_pointer(b->ies); + if (!b_ies) + return 1; + ie1 = cfg80211_find_ie(WLAN_EID_SSID, a_ies->data, a_ies->len); ie2 = cfg80211_find_ie(WLAN_EID_SSID, b_ies->data, b_ies->len); - if (!ie1 && !ie2) - return 0; - /* - * Note that with "hide_ssid", the function returns a match if - * the already-present BSS ("b") is a hidden SSID beacon for - * the new BSS ("a"). + * Key comparator must use same algorithm in any rb-tree + * search function (order is important), otherwise ordering + * of items in the tree is broken and search gives incorrect + * results. This code uses same order as cmp_ies() does. + * + * Note that due to the differring behaviour with hidden SSIDs + * this function only works when "b" is the tree element and + * "a" is the key we're looking for. */ /* sort missing IE before (left of) present IE */ @@ -486,36 +488,24 @@ static int cmp_bss(struct cfg80211_bss *a, if (!ie2) return 1; - switch (mode) { - case BSS_CMP_HIDE_ZLEN: - /* - * In ZLEN mode we assume the BSS entry we're - * looking for has a zero-length SSID. So if - * the one we're looking at right now has that, - * return 0. Otherwise, return the difference - * in length, but since we're looking for the - * 0-length it's really equivalent to returning - * the length of the one we're looking at. - * - * No content comparison is needed as we assume - * the content length is zero. - */ - return ie2[1]; - case BSS_CMP_REGULAR: - default: - /* sort by length first, then by contents */ - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - return memcmp(ie1 + 2, ie2 + 2, ie1[1]); - case BSS_CMP_HIDE_NUL: - if (ie1[1] != ie2[1]) - return ie2[1] - ie1[1]; - /* this is equivalent to memcmp(zeroes, ie2 + 2, len) */ - for (i = 0; i < ie2[1]; i++) - if (ie2[i + 2]) - return -1; + /* zero-size SSID is used as an indication of the hidden bss */ + if (!ie2[1]) return 0; - } + + /* sort by length first, then by contents */ + if (ie1[1] != ie2[1]) + return ie2[1] - ie1[1]; + + /* + * zeroed SSID ie is another indication of a hidden bss; + * if it isn't zeroed just return the regular sort value + * to find the next candidate + */ + for (i = 0; i < ie2[1]; i++) + if (ie2[i + 2]) + return memcmp(ie1 + 2, ie2 + 2, ie1[1]); + + return 0; } struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, @@ -544,7 +534,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, continue; if (is_bss(&bss->pub, bssid, ssid, ssid_len)) { res = bss; - bss_ref_get(dev, res); + kref_get(&res->ref); break; } } @@ -557,6 +547,34 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_get_bss); +struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy, + struct ieee80211_channel *channel, + const u8 *meshid, size_t meshidlen, + const u8 *meshcfg) +{ + struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); + struct cfg80211_internal_bss *bss, *res = NULL; + + spin_lock_bh(&dev->bss_lock); + + list_for_each_entry(bss, &dev->bss_list, list) { + if (channel && bss->pub.channel != channel) + continue; + if (is_mesh(&bss->pub, meshid, meshidlen, meshcfg)) { + res = bss; + kref_get(&res->ref); + break; + } + } + + spin_unlock_bh(&dev->bss_lock); + if (!res) + return NULL; + return &res->pub; +} +EXPORT_SYMBOL(cfg80211_get_mesh); + + static void rb_insert_bss(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *bss) { @@ -569,7 +587,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev, parent = *p; tbss = rb_entry(parent, struct cfg80211_internal_bss, rbn); - cmp = cmp_bss(&bss->pub, &tbss->pub, BSS_CMP_REGULAR); + cmp = cmp_bss(&bss->pub, &tbss->pub); if (WARN_ON(!cmp)) { /* will sort of leak this BSS */ @@ -588,8 +606,7 @@ static void rb_insert_bss(struct cfg80211_registered_device *dev, static struct cfg80211_internal_bss * rb_find_bss(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *res, - enum bss_compare_mode mode) + struct cfg80211_internal_bss *res) { struct rb_node *n = dev->bss_tree.rb_node; struct cfg80211_internal_bss *bss; @@ -597,7 +614,7 @@ rb_find_bss(struct cfg80211_registered_device *dev, while (n) { bss = rb_entry(n, struct cfg80211_internal_bss, rbn); - r = cmp_bss(&res->pub, &bss->pub, mode); + r = cmp_bss(&res->pub, &bss->pub); if (r == 0) return bss; @@ -610,67 +627,46 @@ rb_find_bss(struct cfg80211_registered_device *dev, return NULL; } -static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, - struct cfg80211_internal_bss *new) +static struct cfg80211_internal_bss * +rb_find_hidden_bss(struct cfg80211_registered_device *dev, + struct cfg80211_internal_bss *res) { - const struct cfg80211_bss_ies *ies; + struct rb_node *n = dev->bss_tree.rb_node; struct cfg80211_internal_bss *bss; - const u8 *ie; - int i, ssidlen; - u8 fold = 0; + int r; - ies = rcu_access_pointer(new->pub.beacon_ies); - if (WARN_ON(!ies)) - return false; + while (n) { + bss = rb_entry(n, struct cfg80211_internal_bss, rbn); + r = cmp_hidden_bss(&res->pub, &bss->pub); - ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); - if (!ie) { - /* nothing to do */ - return true; + if (r == 0) + return bss; + else if (r < 0) + n = n->rb_left; + else + n = n->rb_right; } - ssidlen = ie[1]; - for (i = 0; i < ssidlen; i++) - fold |= ie[2 + i]; + return NULL; +} - if (fold) { - /* not a hidden SSID */ - return true; - } +static void +copy_hidden_ies(struct cfg80211_internal_bss *res, + struct cfg80211_internal_bss *hidden) +{ + const struct cfg80211_bss_ies *ies; - /* This is the bad part ... */ + if (rcu_access_pointer(res->pub.beacon_ies)) + return; - list_for_each_entry(bss, &dev->bss_list, list) { - if (!ether_addr_equal(bss->pub.bssid, new->pub.bssid)) - continue; - if (bss->pub.channel != new->pub.channel) - continue; - if (rcu_access_pointer(bss->pub.beacon_ies)) - continue; - ies = rcu_access_pointer(bss->pub.ies); - if (!ies) - continue; - ie = cfg80211_find_ie(WLAN_EID_SSID, ies->data, ies->len); - if (!ie) - continue; - if (ssidlen && ie[1] != ssidlen) - continue; - /* that would be odd ... */ - if (bss->pub.beacon_ies) - continue; - if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) - continue; - if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) - list_del(&bss->hidden_list); - /* combine them */ - list_add(&bss->hidden_list, &new->hidden_list); - bss->pub.hidden_beacon_bss = &new->pub; - new->refcount += bss->refcount; - rcu_assign_pointer(bss->pub.beacon_ies, - new->pub.beacon_ies); - } + ies = rcu_access_pointer(hidden->pub.beacon_ies); + if (WARN_ON(!ies)) + return; - return true; + ies = kmemdup(ies, sizeof(*ies) + ies->len, GFP_ATOMIC); + if (unlikely(!ies)) + return; + rcu_assign_pointer(res->pub.beacon_ies, ies); } static struct cfg80211_internal_bss * @@ -691,10 +687,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, return NULL; } - found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR); + found = rb_find_bss(dev, tmp); if (found) { found->pub.beacon_interval = tmp->pub.beacon_interval; + found->pub.tsf = tmp->pub.tsf; found->pub.signal = tmp->pub.signal; found->pub.capability = tmp->pub.capability; found->ts = tmp->ts; @@ -714,45 +711,19 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); } else if (rcu_access_pointer(tmp->pub.beacon_ies)) { - const struct cfg80211_bss_ies *old; - struct cfg80211_internal_bss *bss; - - if (found->pub.hidden_beacon_bss && - !list_empty(&found->hidden_list)) { - /* - * The found BSS struct is one of the probe - * response members of a group, but we're - * receiving a beacon (beacon_ies in the tmp - * bss is used). This can only mean that the - * AP changed its beacon from not having an - * SSID to showing it, which is confusing so - * drop this information. - */ - goto drop; - } + const struct cfg80211_bss_ies *old, *ies; old = rcu_access_pointer(found->pub.beacon_ies); + ies = rcu_access_pointer(found->pub.ies); rcu_assign_pointer(found->pub.beacon_ies, tmp->pub.beacon_ies); /* Override IEs if they were from a beacon before */ - if (old == rcu_access_pointer(found->pub.ies)) + if (old == ies) rcu_assign_pointer(found->pub.ies, tmp->pub.beacon_ies); - /* Assign beacon IEs to all sub entries */ - list_for_each_entry(bss, &found->hidden_list, - hidden_list) { - const struct cfg80211_bss_ies *ies; - - ies = rcu_access_pointer(bss->pub.beacon_ies); - WARN_ON(ies != old); - - rcu_assign_pointer(bss->pub.beacon_ies, - tmp->pub.beacon_ies); - } - if (old) kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); @@ -762,6 +733,19 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, struct cfg80211_internal_bss *hidden; struct cfg80211_bss_ies *ies; + /* First check if the beacon is a probe response from + * a hidden bss. If so, copy beacon ies (with nullified + * ssid) into the probe response bss entry (with real ssid). + * It is required basically for PSM implementation + * (probe responses do not contain tim ie) */ + + /* TODO: The code is not trying to update existing probe + * response bss entries when beacon ies are + * getting changed. */ + hidden = rb_find_hidden_bss(dev, tmp); + if (hidden) + copy_hidden_ies(tmp, hidden); + /* * create a copy -- the "res" variable that is passed in * is allocated on the stack since it's not needed in the @@ -776,51 +760,21 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, ies = (void *)rcu_dereference(tmp->pub.proberesp_ies); if (ies) kfree_rcu(ies, rcu_head); - goto drop; + spin_unlock_bh(&dev->bss_lock); + return NULL; } memcpy(new, tmp, sizeof(*new)); - new->refcount = 1; - INIT_LIST_HEAD(&new->hidden_list); - - if (rcu_access_pointer(tmp->pub.proberesp_ies)) { - hidden = rb_find_bss(dev, tmp, BSS_CMP_HIDE_ZLEN); - if (!hidden) - hidden = rb_find_bss(dev, tmp, - BSS_CMP_HIDE_NUL); - if (hidden) { - new->pub.hidden_beacon_bss = &hidden->pub; - list_add(&new->hidden_list, - &hidden->hidden_list); - hidden->refcount++; - rcu_assign_pointer(new->pub.beacon_ies, - hidden->pub.beacon_ies); - } - } else { - /* - * Ok so we found a beacon, and don't have an entry. If - * it's a beacon with hidden SSID, we might be in for an - * expensive search for any probe responses that should - * be grouped with this beacon for updates ... - */ - if (!cfg80211_combine_bsses(dev, new)) { - kfree(new); - goto drop; - } - } - + kref_init(&new->ref); list_add_tail(&new->list, &dev->bss_list); rb_insert_bss(dev, new); found = new; } dev->bss_generation++; - bss_ref_get(dev, found); spin_unlock_bh(&dev->bss_lock); + kref_get(&found->ref); return found; - drop: - spin_unlock_bh(&dev->bss_lock); - return NULL; } static struct ieee80211_channel * @@ -879,6 +833,7 @@ cfg80211_inform_bss(struct wiphy *wiphy, memcpy(tmp.pub.bssid, bssid, ETH_ALEN); tmp.pub.channel = channel; tmp.pub.signal = signal; + tmp.pub.tsf = tsf; tmp.pub.beacon_interval = beacon_interval; tmp.pub.capability = capability; /* @@ -886,14 +841,16 @@ cfg80211_inform_bss(struct wiphy *wiphy, * Response frame, we need to pick one of the options and only use it * with the driver that does not provide the full Beacon/Probe Response * frame. Use Beacon frame pointer to avoid indicating that this should - * override the IEs pointer should we have received an earlier + * override the iies pointer should we have received an earlier * indication of Probe Response data. + * + * The initial buffer for the IEs is allocated with the BSS entry and + * is located after the private area. */ ies = kmalloc(sizeof(*ies) + ielen, gfp); if (!ies) return NULL; ies->len = ielen; - ies->tsf = tsf; memcpy(ies->data, ie, ielen); rcu_assign_pointer(tmp.pub.beacon_ies, ies); @@ -950,7 +907,6 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, if (!ies) return NULL; ies->len = ielen; - ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); if (ieee80211_is_probe_resp(mgmt->frame_control)) @@ -962,6 +918,7 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, memcpy(tmp.pub.bssid, mgmt->bssid, ETH_ALEN); tmp.pub.channel = channel; tmp.pub.signal = signal; + tmp.pub.tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); @@ -978,35 +935,27 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy, } EXPORT_SYMBOL(cfg80211_inform_bss_frame); -void cfg80211_ref_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) +void cfg80211_ref_bss(struct cfg80211_bss *pub) { - struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); struct cfg80211_internal_bss *bss; if (!pub) return; bss = container_of(pub, struct cfg80211_internal_bss, pub); - - spin_lock_bh(&dev->bss_lock); - bss_ref_get(dev, bss); - spin_unlock_bh(&dev->bss_lock); + kref_get(&bss->ref); } EXPORT_SYMBOL(cfg80211_ref_bss); -void cfg80211_put_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) +void cfg80211_put_bss(struct cfg80211_bss *pub) { - struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy); struct cfg80211_internal_bss *bss; if (!pub) return; bss = container_of(pub, struct cfg80211_internal_bss, pub); - - spin_lock_bh(&dev->bss_lock); - bss_ref_put(dev, bss); - spin_unlock_bh(&dev->bss_lock); + kref_put(&bss->ref, bss_release); } EXPORT_SYMBOL(cfg80211_put_bss); @@ -1022,8 +971,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) spin_lock_bh(&dev->bss_lock); if (!list_empty(&bss->list)) { - if (__cfg80211_unlink_bss(dev, bss)) - dev->bss_generation++; + __cfg80211_unlink_bss(dev, bss); + dev->bss_generation++; } spin_unlock_bh(&dev->bss_lock); } @@ -1292,10 +1241,15 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, rcu_read_lock(); ies = rcu_dereference(bss->pub.ies); - rem = ies->len; - ie = ies->data; + if (ies) { + rem = ies->len; + ie = ies->data; + } else { + rem = 0; + ie = NULL; + } - while (rem >= 2) { + while (ies && rem >= 2) { /* invalid data */ if (ie[1] > rem - 2) break; @@ -1408,7 +1362,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, if (buf) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM; - sprintf(buf, "tsf=%016llx", (unsigned long long)(ies->tsf)); + sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->pub.tsf)); iwe.u.data.length = strlen(buf); current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, buf); diff --git a/trunk/net/wireless/sme.c b/trunk/net/wireless/sme.c index f432bd3755b1..a825dfe12cf7 100644 --- a/trunk/net/wireless/sme.c +++ b/trunk/net/wireless/sme.c @@ -301,7 +301,7 @@ static void __cfg80211_sme_scan_done(struct net_device *dev) bss = cfg80211_get_conn_bss(wdev); if (bss) { - cfg80211_put_bss(&rdev->wiphy, bss); + cfg80211_put_bss(bss); } else { /* not found */ if (wdev->conn->state == CFG80211_CONN_SCAN_AGAIN) @@ -464,7 +464,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; } @@ -480,7 +480,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, kfree(wdev->connect_keys); wdev->connect_keys = NULL; wdev->ssid_len = 0; - cfg80211_put_bss(wdev->wiphy, bss); + cfg80211_put_bss(bss); return; } @@ -586,7 +586,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, } cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); wdev->current_bss = NULL; cfg80211_hold_bss(bss_from_pub(bss)); @@ -621,7 +621,7 @@ void __cfg80211_roamed(struct wireless_dev *wdev, return; out: - cfg80211_put_bss(wdev->wiphy, bss); + cfg80211_put_bss(bss); } void cfg80211_roamed(struct net_device *dev, @@ -663,7 +663,7 @@ void cfg80211_roamed_bss(struct net_device *dev, ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); if (!ev) { - cfg80211_put_bss(wdev->wiphy, bss); + cfg80211_put_bss(bss); return; } @@ -704,7 +704,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); + cfg80211_put_bss(&wdev->current_bss->pub); } wdev->current_bss = NULL; @@ -875,7 +875,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, if (bss) { wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; err = cfg80211_conn_do_work(wdev); - cfg80211_put_bss(wdev->wiphy, bss); + cfg80211_put_bss(bss); } else { /* otherwise we'll need to scan for the AP first */ err = cfg80211_conn_scan(wdev); diff --git a/trunk/net/wireless/sysfs.c b/trunk/net/wireless/sysfs.c index 73bf39f11314..9bf6d5e32166 100644 --- a/trunk/net/wireless/sysfs.c +++ b/trunk/net/wireless/sysfs.c @@ -108,7 +108,9 @@ static int wiphy_resume(struct device *dev) int ret = 0; /* Age scan results with time spent in suspend */ + spin_lock_bh(&rdev->bss_lock); cfg80211_bss_age(rdev, get_seconds() - rdev->suspend_at); + spin_unlock_bh(&rdev->bss_lock); if (rdev->ops->resume) { rtnl_lock(); diff --git a/trunk/net/wireless/trace.h b/trunk/net/wireless/trace.h index c9cafb0ea95f..8bc553199686 100644 --- a/trunk/net/wireless/trace.h +++ b/trunk/net/wireless/trace.h @@ -2333,41 +2333,6 @@ TRACE_EVENT(cfg80211_return_u32, TP_printk("ret: %u", __entry->ret) ); -TRACE_EVENT(cfg80211_report_wowlan_wakeup, - TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_wowlan_wakeup *wakeup), - TP_ARGS(wiphy, wdev, wakeup), - TP_STRUCT__entry( - WIPHY_ENTRY - WDEV_ENTRY - __field(bool, disconnect) - __field(bool, magic_pkt) - __field(bool, gtk_rekey_failure) - __field(bool, eap_identity_req) - __field(bool, four_way_handshake) - __field(bool, rfkill_release) - __field(s32, pattern_idx) - __field(u32, packet_len) - __dynamic_array(u8, packet, wakeup->packet_present_len) - ), - TP_fast_assign( - WIPHY_ASSIGN; - WDEV_ASSIGN; - __entry->disconnect = wakeup->disconnect; - __entry->magic_pkt = wakeup->magic_pkt; - __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure; - __entry->eap_identity_req = wakeup->eap_identity_req; - __entry->four_way_handshake = wakeup->four_way_handshake; - __entry->rfkill_release = wakeup->rfkill_release; - __entry->pattern_idx = wakeup->pattern_idx; - __entry->packet_len = wakeup->packet_len; - if (wakeup->packet && wakeup->packet_present_len) - memcpy(__get_dynamic_array(packet), wakeup->packet, - wakeup->packet_present_len); - ), - TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT, WIPHY_PR_ARG, WDEV_PR_ARG) -); - #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */ #undef TRACE_INCLUDE_PATH diff --git a/trunk/net/wireless/util.c b/trunk/net/wireless/util.c index 37a56ee1e1ed..d7873c7ae0ec 100644 --- a/trunk/net/wireless/util.c +++ b/trunk/net/wireless/util.c @@ -1217,10 +1217,10 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, break; case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_MONITOR: radar_required = false; break; + case NL80211_IFTYPE_P2P_DEVICE: case NUM_NL80211_IFTYPES: case NL80211_IFTYPE_UNSPECIFIED: default: