diff --git a/[refs] b/[refs] index d0fa29442d01..e3cb300bdd32 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cb73e2b9ed1240398c773eec3c976edd99baf5b9 +refs/heads/master: ae023b2795d36f0f077e157428eb7eafa29ee412 diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 16c3506da16c..4e2a1f67a1fc 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1353,14 +1353,6 @@ W: http://wireless.kernel.org/en/users/Drivers/ath9k S: Supported F: drivers/net/wireless/ath/ath9k/ -WILOCITY WIL6210 WIRELESS DRIVER -M: Vladimir Kondratiev -L: linux-wireless@vger.kernel.org -L: wil6210@qca.qualcomm.com -S: Supported -W: http://wireless.kernel.org/en/users/Drivers/wil6210 -F: drivers/net/wireless/ath/wil6210/ - CARL9170 LINUX COMMUNITY WIRELESS DRIVER M: Christian Lamparter L: linux-wireless@vger.kernel.org diff --git a/trunk/drivers/bcma/Kconfig b/trunk/drivers/bcma/Kconfig index 8b4221cfd118..d7b56a88c9f4 100644 --- a/trunk/drivers/bcma/Kconfig +++ b/trunk/drivers/bcma/Kconfig @@ -67,7 +67,8 @@ config BCMA_DRIVER_GMAC_CMN config BCMA_DRIVER_GPIO bool "BCMA GPIO driver" - depends on BCMA && GPIOLIB + depends on BCMA + select GPIOLIB help Driver to provide access to the GPIO pins of the bcma bus. diff --git a/trunk/drivers/bcma/driver_chipcommon_sflash.c b/trunk/drivers/bcma/driver_chipcommon_sflash.c index 1e694db4532d..63e688393825 100644 --- a/trunk/drivers/bcma/driver_chipcommon_sflash.c +++ b/trunk/drivers/bcma/driver_chipcommon_sflash.c @@ -35,7 +35,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { { "M25P40", 0x12, 0x10000, 8, }, { "M25P16", 0x14, 0x10000, 32, }, - { "M25P32", 0x15, 0x10000, 64, }, + { "M25P32", 0x14, 0x10000, 64, }, { "M25P64", 0x16, 0x10000, 128, }, { "M25FL128", 0x17, 0x10000, 256, }, { 0 }, diff --git a/trunk/drivers/bluetooth/ath3k.c b/trunk/drivers/bluetooth/ath3k.c index 33c9a44a9678..b00000e8aef6 100644 --- a/trunk/drivers/bluetooth/ath3k.c +++ b/trunk/drivers/bluetooth/ath3k.c @@ -77,15 +77,10 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x04CA, 0x3005) }, - { USB_DEVICE(0x04CA, 0x3006) }, - { USB_DEVICE(0x04CA, 0x3008) }, { USB_DEVICE(0x13d3, 0x3362) }, { USB_DEVICE(0x0CF3, 0xE004) }, { USB_DEVICE(0x0930, 0x0219) }, { USB_DEVICE(0x0489, 0xe057) }, - { USB_DEVICE(0x13d3, 0x3393) }, - { USB_DEVICE(0x0489, 0xe04e) }, - { USB_DEVICE(0x0489, 0xe056) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -109,15 +104,10 @@ static struct usb_device_id ath3k_blist_tbl[] = { { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU22 with sflash firmware */ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, diff --git a/trunk/drivers/bluetooth/btusb.c b/trunk/drivers/bluetooth/btusb.c index 7e351e345476..a1d4ede5b892 100644 --- a/trunk/drivers/bluetooth/btusb.c +++ b/trunk/drivers/bluetooth/btusb.c @@ -135,15 +135,10 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, - { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/trunk/drivers/net/wireless/ath/Kconfig b/trunk/drivers/net/wireless/ath/Kconfig index 2c02b4e84094..1a67a4f829fe 100644 --- a/trunk/drivers/net/wireless/ath/Kconfig +++ b/trunk/drivers/net/wireless/ath/Kconfig @@ -30,6 +30,5 @@ source "drivers/net/wireless/ath/ath9k/Kconfig" source "drivers/net/wireless/ath/carl9170/Kconfig" source "drivers/net/wireless/ath/ath6kl/Kconfig" source "drivers/net/wireless/ath/ar5523/Kconfig" -source "drivers/net/wireless/ath/wil6210/Kconfig" endif diff --git a/trunk/drivers/net/wireless/ath/Makefile b/trunk/drivers/net/wireless/ath/Makefile index 97b964ded2be..1e18621326dc 100644 --- a/trunk/drivers/net/wireless/ath/Makefile +++ b/trunk/drivers/net/wireless/ath/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_ATH9K_HW) += ath9k/ obj-$(CONFIG_CARL9170) += carl9170/ obj-$(CONFIG_ATH6KL) += ath6kl/ obj-$(CONFIG_AR5523) += ar5523/ -obj-$(CONFIG_WIL6210) += wil6210/ obj-$(CONFIG_ATH_COMMON) += ath.o diff --git a/trunk/drivers/net/wireless/ath/ath9k/Kconfig b/trunk/drivers/net/wireless/ath/ath9k/Kconfig index 7647ed6b73d7..5fc15bf8be09 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/Kconfig +++ b/trunk/drivers/net/wireless/ath/ath9k/Kconfig @@ -2,7 +2,6 @@ config ATH9K_HW tristate config ATH9K_COMMON tristate - select ATH_COMMON config ATH9K_DFS_DEBUGFS def_bool y depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED @@ -18,6 +17,7 @@ config ATH9K_BTCOEX_SUPPORT config ATH9K tristate "Atheros 802.11n wireless cards support" depends on MAC80211 + select ATH_COMMON select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS @@ -56,8 +56,7 @@ config ATH9K_AHB config ATH9K_DEBUGFS bool "Atheros ath9k debugging" - depends on ATH9K - select MAC80211_DEBUGFS + depends on ATH9K && DEBUG_FS ---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/ar9003_calib.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 56317b0fb6b6..8b0d8dcd7625 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -976,8 +976,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, AR_PHY_CL_TAB_1, AR_PHY_CL_TAB_2 }; - ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); - if (rtt) { if (!ar9003_hw_rtt_restore(ah, chan)) run_rtt_cal = true; diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 59bf5f31e212..74fd3977feeb 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -544,7 +544,7 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah) ar9340Common_rx_gain_table_1p0); else if (AR_SREV_9485_11(ah)) INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9485_common_rx_gain_1_1); + ar9485Common_wo_xlna_rx_gain_1_1); else if (AR_SREV_9550(ah)) { INIT_INI_ARRAY(&ah->iniModesRxGain, ar955x_1p0_common_rx_gain_table); diff --git a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 3afc24bde6d6..ce19c09fa8e8 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/trunk/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -586,19 +586,32 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, ath9k_hw_synth_delay(ah, chan, synthDelay); } -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { - if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5) + switch (rx) { + case 0x5: REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, AR_PHY_SWAP_ALT_CHAIN); - - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); + case 0x3: + case 0x1: + case 0x2: + case 0x7: + REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); + REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); + break; + default: + break; + } if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) - tx = 3; + REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); + else + REG_WRITE(ah, AR_SELFGEN_MASK, tx); - REG_WRITE(ah, AR_SELFGEN_MASK, tx); + if (tx == 0x5) { + REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, + AR_PHY_SWAP_ALT_CHAIN); + } } /* diff --git a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h index 42794c546a40..86e26a19efda 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/trunk/drivers/net/wireless/ath/ath9k/ath9k.h @@ -317,6 +317,7 @@ struct ath_rx { u32 *rxlink; u32 num_pkts; unsigned int rxfilter; + spinlock_t rxbuflock; struct list_head rxbuf; struct ath_descdma rxdma; struct ath_buf *rx_bufptr; @@ -327,6 +328,7 @@ struct ath_rx { int ath_startrecv(struct ath_softc *sc); bool ath_stoprecv(struct ath_softc *sc); +void ath_flushrecv(struct ath_softc *sc); u32 ath_calcrxfilter(struct ath_softc *sc); int ath_rx_init(struct ath_softc *sc, int nbufs); void ath_rx_cleanup(struct ath_softc *sc); @@ -644,6 +646,7 @@ void ath_ant_comb_update(struct ath_softc *sc); enum sc_op_flags { SC_OP_INVALID, SC_OP_BEACONS, + SC_OP_RXFLUSH, SC_OP_ANI_RUN, SC_OP_PRIM_STA_VIF, SC_OP_HW_RESET, diff --git a/trunk/drivers/net/wireless/ath/ath9k/beacon.c b/trunk/drivers/net/wireless/ath/ath9k/beacon.c index 2ca355e94da6..531fffd801a3 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/beacon.c +++ b/trunk/drivers/net/wireless/ath/ath9k/beacon.c @@ -147,7 +147,6 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; - bf->bf_mpdu = NULL; } skb = ieee80211_beacon_get(hw, vif); @@ -360,6 +359,7 @@ void ath9k_beacon_tasklet(unsigned long data) return; bf = ath9k_beacon_generate(sc->hw, vif); + WARN_ON(!bf); if (sc->beacon.bmisscnt != 0) { ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.c b/trunk/drivers/net/wireless/ath/ath9k/debug.c index e585fc827c50..13ff9edc2401 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.c +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.c @@ -861,6 +861,7 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, RXS_ERR("RX-LENGTH-ERR", rx_len_err); RXS_ERR("RX-OOM-ERR", rx_oom_err); RXS_ERR("RX-RATE-ERR", rx_rate_err); + RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); diff --git a/trunk/drivers/net/wireless/ath/ath9k/debug.h b/trunk/drivers/net/wireless/ath/ath9k/debug.h index 6df2ab62dcb7..375c3b46411e 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/debug.h +++ b/trunk/drivers/net/wireless/ath/ath9k/debug.h @@ -216,6 +216,7 @@ struct ath_tx_stats { * @rx_oom_err: No. of frames dropped due to OOM issues. * @rx_rate_err: No. of frames dropped due to rate errors. * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. + * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. * @rx_beacons: No. of beacons received. * @rx_frags: No. of rx-fragements received. */ @@ -234,6 +235,7 @@ struct ath_rx_stats { u32 rx_oom_err; u32 rx_rate_err; u32 rx_too_many_frags_err; + u32 rx_drop_rxflush; u32 rx_beacons; u32 rx_frags; }; diff --git a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c index aac4a406a513..4a9570dfba72 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/trunk/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -344,8 +344,6 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); - } else { - kfree_skb(skb); } } diff --git a/trunk/drivers/net/wireless/ath/ath9k/hw.h b/trunk/drivers/net/wireless/ath/ath9k/hw.h index 9d26fc56ca56..7f1a8e91c908 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/hw.h +++ b/trunk/drivers/net/wireless/ath/ath9k/hw.h @@ -1066,7 +1066,6 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); int ar9003_paprd_init_table(struct ath_hw *ah); bool ar9003_paprd_is_done(struct ath_hw *ah); bool ar9003_is_paprd_enabled(struct ath_hw *ah); -void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); /* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index dd91f8fdc01c..be30a9af1528 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc) ath_start_ani(sc); } -static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx) +static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) { struct ath_hw *ah = sc->sc_ah; bool ret = true; @@ -202,6 +202,14 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx) if (!ath_drain_all_txq(sc, retry_tx)) ret = false; + if (!flush) { + if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_rx_tasklet(sc, 1, true); + ath_rx_tasklet(sc, 1, false); + } else { + ath_flushrecv(sc); + } + return ret; } @@ -254,11 +262,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_cal_data *caldata = NULL; bool fastcc = true; + bool flush = false; int r; __ath_cancel_work(sc); - tasklet_disable(&sc->intr_tq); spin_lock_bh(&sc->sc_pcu_lock); if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { @@ -268,10 +276,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, if (!hchan) { fastcc = false; + flush = true; hchan = ah->curchan; } - if (!ath_prepare_reset(sc, retry_tx)) + if (!ath_prepare_reset(sc, retry_tx, flush)) fastcc = false; ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", @@ -293,8 +302,6 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, out: spin_unlock_bh(&sc->sc_pcu_lock); - tasklet_enable(&sc->intr_tq); - return r; } @@ -797,7 +804,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) ath9k_hw_cfg_gpio_input(ah, ah->led_pin); } - ath_prepare_reset(sc, false); + ath_prepare_reset(sc, false, true); if (sc->rx.frag) { dev_kfree_skb_any(sc->rx.frag); @@ -1826,9 +1833,6 @@ static u32 fill_chainmask(u32 cap, u32 new) static bool validate_antenna_mask(struct ath_hw *ah, u32 val) { - if (AR_SREV_9300_20_OR_LATER(ah)) - return true; - switch (val & 0x7) { case 0x1: case 0x3: diff --git a/trunk/drivers/net/wireless/ath/ath9k/recv.c b/trunk/drivers/net/wireless/ath/ath9k/recv.c index 90752f246970..d4df98a938bf 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/recv.c +++ b/trunk/drivers/net/wireless/ath/ath9k/recv.c @@ -254,6 +254,8 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) static void ath_edma_start_recv(struct ath_softc *sc) { + spin_lock_bh(&sc->rx.rxbuflock); + ath9k_hw_rxena(sc->sc_ah); ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, @@ -265,6 +267,8 @@ static void ath_edma_start_recv(struct ath_softc *sc) ath_opmode_init(sc); ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); + + spin_unlock_bh(&sc->rx.rxbuflock); } static void ath_edma_stop_recv(struct ath_softc *sc) @@ -281,6 +285,8 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) int error = 0; spin_lock_init(&sc->sc_pcu_lock); + spin_lock_init(&sc->rx.rxbuflock); + clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + sc->sc_ah->caps.rx_status_len; @@ -441,6 +447,7 @@ int ath_startrecv(struct ath_softc *sc) return 0; } + spin_lock_bh(&sc->rx.rxbuflock); if (list_empty(&sc->rx.rxbuf)) goto start_recv; @@ -461,14 +468,9 @@ int ath_startrecv(struct ath_softc *sc) ath_opmode_init(sc); ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); - return 0; -} + spin_unlock_bh(&sc->rx.rxbuflock); -static void ath_flushrecv(struct ath_softc *sc) -{ - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ath_rx_tasklet(sc, 1, true); - ath_rx_tasklet(sc, 1, false); + return 0; } bool ath_stoprecv(struct ath_softc *sc) @@ -476,16 +478,16 @@ bool ath_stoprecv(struct ath_softc *sc) struct ath_hw *ah = sc->sc_ah; bool stopped, reset = false; + spin_lock_bh(&sc->rx.rxbuflock); ath9k_hw_abortpcurecv(ah); ath9k_hw_setrxfilter(ah, 0); stopped = ath9k_hw_stopdmarecv(ah, &reset); - ath_flushrecv(sc); - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) ath_edma_stop_recv(sc); else sc->rx.rxlink = NULL; + spin_unlock_bh(&sc->rx.rxbuflock); if (!(ah->ah_flags & AH_UNPLUGGED) && unlikely(!stopped)) { @@ -497,6 +499,15 @@ bool ath_stoprecv(struct ath_softc *sc) return stopped && !reset; } +void ath_flushrecv(struct ath_softc *sc) +{ + set_bit(SC_OP_RXFLUSH, &sc->sc_flags); + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) + ath_rx_tasklet(sc, 1, true); + ath_rx_tasklet(sc, 1, false); + clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); +} + static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) { /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ @@ -733,7 +744,6 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, return NULL; } - list_del(&bf->list); if (!bf->bf_mpdu) return bf; @@ -1049,12 +1059,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) dma_type = DMA_FROM_DEVICE; qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; + spin_lock_bh(&sc->rx.rxbuflock); tsf = ath9k_hw_gettsf64(ah); tsf_lower = tsf & 0xffffffff; do { bool decrypt_error = false; + /* If handling rx interrupt and flush is in progress => exit */ + if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) + break; memset(&rs, 0, sizeof(rs)); if (edma) @@ -1097,6 +1111,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath_debug_stat_rx(sc, &rs); + /* + * If we're asked to flush receive queue, directly + * chain it back at the queue without processing it. + */ + if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { + RX_STAT_INC(rx_drop_rxflush); + goto requeue_drop_frag; + } + memset(rxs, 0, sizeof(struct ieee80211_rx_status)); rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; @@ -1231,18 +1254,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) sc->rx.frag = NULL; } requeue: - list_add_tail(&bf->list, &sc->rx.rxbuf); - if (flush) - continue; - if (edma) { + list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); } else { + list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); - ath9k_hw_rxena(ah); + if (!flush) + ath9k_hw_rxena(ah); } } while (1); + spin_unlock_bh(&sc->rx.rxbuflock); + if (!(ah->imask & ATH9K_INT_RXEOL)) { ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); ath9k_hw_set_interrupts(ah); diff --git a/trunk/drivers/net/wireless/ath/carl9170/fw.c b/trunk/drivers/net/wireless/ath/carl9170/fw.c index 63fd9af3fd39..aaebecd19e59 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/fw.c +++ b/trunk/drivers/net/wireless/ath/carl9170/fw.c @@ -336,12 +336,8 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len) if (SUPP(CARL9170FW_WLANTX_CAB)) { if_comb_types |= BIT(NL80211_IFTYPE_AP) | + BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_P2P_GO); - -#ifdef CONFIG_MAC80211_MESH - if_comb_types |= - BIT(NL80211_IFTYPE_MESH_POINT); -#endif /* CONFIG_MAC80211_MESH */ } } diff --git a/trunk/drivers/net/wireless/ath/wil6210/Kconfig b/trunk/drivers/net/wireless/ath/wil6210/Kconfig deleted file mode 100644 index bac3d98a0cfb..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -config WIL6210 - tristate "Wilocity 60g WiFi card wil6210 support" - depends on CFG80211 - depends on PCI - default n - ---help--- - This module adds support for wireless adapter based on - wil6210 chip by Wilocity. It supports operation on the - 60 GHz band, covered by the IEEE802.11ad standard. - - http://wireless.kernel.org/en/users/Drivers/wil6210 - - If you choose to build it as a module, it will be called - wil6210 - -config WIL6210_ISR_COR - bool "Use Clear-On-Read mode for ISR registers for wil6210" - depends on WIL6210 - default y - ---help--- - ISR registers on wil6210 chip may operate in either - COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. - For production code, use COR (say y); is default since - it saves extra target transaction; - For ISR debug, use W1C (say n); is allows to monitor ISR - registers with debugfs. If COR were used, ISR would - self-clear when accessed for debug purposes, it makes - such monitoring impossible. - Say y unless you debug interrupts diff --git a/trunk/drivers/net/wireless/ath/wil6210/Makefile b/trunk/drivers/net/wireless/ath/wil6210/Makefile deleted file mode 100644 index 9396dc9fe3c5..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -obj-$(CONFIG_WIL6210) += wil6210.o - -wil6210-objs := main.o -wil6210-objs += netdev.o -wil6210-objs += cfg80211.o -wil6210-objs += pcie_bus.o -wil6210-objs += debugfs.o -wil6210-objs += wmi.o -wil6210-objs += interrupt.o -wil6210-objs += txrx.o - -subdir-ccflags-y += -Werror -subdir-ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c b/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c deleted file mode 100644 index 116f4e807ae1..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/cfg80211.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 - -#include "wil6210.h" -#include "wmi.h" - -#define CHAN60G(_channel, _flags) { \ - .band = IEEE80211_BAND_60GHZ, \ - .center_freq = 56160 + (2160 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 40, \ -} - -static struct ieee80211_channel wil_60ghz_channels[] = { - CHAN60G(1, 0), - CHAN60G(2, 0), - CHAN60G(3, 0), -/* channel 4 not supported yet */ -}; - -static struct ieee80211_supported_band wil_band_60ghz = { - .channels = wil_60ghz_channels, - .n_channels = ARRAY_SIZE(wil_60ghz_channels), - .ht_cap = { - .ht_supported = true, - .cap = 0, /* TODO */ - .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ - .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ - .mcs = { - /* MCS 1..12 - SC PHY */ - .rx_mask = {0xfe, 0x1f}, /* 1..12 */ - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ - }, - }, -}; - -static const struct ieee80211_txrx_stypes -wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_AP] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) - }, -}; - -static const u32 wil_cipher_suites[] = { - WLAN_CIPHER_SUITE_GCMP, -}; - -int wil_iftype_nl2wmi(enum nl80211_iftype type) -{ - static const struct { - enum nl80211_iftype nl; - enum wmi_network_type wmi; - } __nl2wmi[] = { - {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, - {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, - {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, - {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, - {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, - {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ - }; - uint i; - - for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { - if (__nl2wmi[i].nl == type) - return __nl2wmi[i].wmi; - } - - return -EOPNOTSUPP; -} - -static int wil_cfg80211_get_station(struct wiphy *wiphy, - struct net_device *ndev, - u8 *mac, struct station_info *sinfo) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - int rc; - struct wmi_notify_req_cmd cmd = { - .cid = 0, - .interval_usec = 0, - }; - - if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) - return -ENOENT; - - /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ - rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), - WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); - if (rc) - return rc; - - sinfo->generation = wil->sinfo_gen; - - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; - sinfo->txrate.mcs = wil->stats.bf_mcs; - sinfo->filled |= STATION_INFO_RX_BITRATE; - sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; - sinfo->rxrate.mcs = wil->stats.last_mcs_rx; - - if (test_bit(wil_status_fwconnected, &wil->status)) { - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = 12; /* TODO: provide real value */ - } - - return 0; -} - -static int wil_cfg80211_change_iface(struct wiphy *wiphy, - struct net_device *ndev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; - - switch (type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - break; - case NL80211_IFTYPE_MONITOR: - if (flags) - wil->monitor_flags = *flags; - else - wil->monitor_flags = 0; - - break; - default: - return -EOPNOTSUPP; - } - - wdev->iftype = type; - - return 0; -} - -static int wil_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; - struct { - struct wmi_start_scan_cmd cmd; - u16 chnl[4]; - } __packed cmd; - uint i, n; - - if (wil->scan_request) { - wil_err(wil, "Already scanning\n"); - return -EAGAIN; - } - - /* check we are client side */ - switch (wdev->iftype) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - break; - default: - return -EOPNOTSUPP; - - } - - /* FW don't support scan after connection attempt */ - if (test_bit(wil_status_dontscan, &wil->status)) { - wil_err(wil, "Scan after connect attempt not supported\n"); - return -EBUSY; - } - - wil->scan_request = request; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd.num_channels = 0; - n = min(request->n_channels, 4U); - for (i = 0; i < n; i++) { - int ch = request->channels[i]->hw_value; - if (ch == 0) { - wil_err(wil, - "Scan requested for unknown frequency %dMhz\n", - request->channels[i]->center_freq); - continue; - } - /* 0-based channel indexes */ - cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; - wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, - request->channels[i]->center_freq); - } - - return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + - cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); -} - -static int wil_cfg80211_connect(struct wiphy *wiphy, - struct net_device *ndev, - struct cfg80211_connect_params *sme) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct cfg80211_bss *bss; - struct wmi_connect_cmd conn; - const u8 *ssid_eid; - const u8 *rsn_eid; - int ch; - int rc = 0; - - bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, - sme->ssid, sme->ssid_len, - WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - if (!bss) { - wil_err(wil, "Unable to find BSS\n"); - return -ENOENT; - } - - ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); - if (!ssid_eid) { - wil_err(wil, "No SSID\n"); - rc = -ENOENT; - goto out; - } - - rsn_eid = sme->ie ? - cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : - NULL; - if (rsn_eid) { - if (sme->ie_len > WMI_MAX_IE_LEN) { - rc = -ERANGE; - wil_err(wil, "IE too large (%td bytes)\n", - sme->ie_len); - goto out; - } - /* - * For secure assoc, send: - * (1) WMI_DELETE_CIPHER_KEY_CMD - * (2) WMI_SET_APPIE_CMD - */ - rc = wmi_del_cipher_key(wil, 0, bss->bssid); - if (rc) { - wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); - goto out; - } - /* WMI_SET_APPIE_CMD */ - rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); - if (rc) { - wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); - goto out; - } - } - - /* WMI_CONNECT_CMD */ - memset(&conn, 0, sizeof(conn)); - switch (bss->capability & 0x03) { - case WLAN_CAPABILITY_DMG_TYPE_AP: - conn.network_type = WMI_NETTYPE_INFRA; - break; - case WLAN_CAPABILITY_DMG_TYPE_PBSS: - conn.network_type = WMI_NETTYPE_P2P; - break; - default: - wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", - bss->capability); - goto out; - } - if (rsn_eid) { - conn.dot11_auth_mode = WMI_AUTH11_SHARED; - conn.auth_mode = WMI_AUTH_WPA2_PSK; - conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; - conn.pairwise_crypto_len = 16; - } else { - conn.dot11_auth_mode = WMI_AUTH11_OPEN; - conn.auth_mode = WMI_AUTH_NONE; - } - - conn.ssid_len = min_t(u8, ssid_eid[1], 32); - memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); - - ch = bss->channel->hw_value; - if (ch == 0) { - wil_err(wil, "BSS at unknown frequency %dMhz\n", - bss->channel->center_freq); - rc = -EOPNOTSUPP; - goto out; - } - conn.channel = ch - 1; - - memcpy(conn.bssid, bss->bssid, 6); - memcpy(conn.dst_mac, bss->bssid, 6); - /* - * FW don't support scan after connection attempt - */ - set_bit(wil_status_dontscan, &wil->status); - - rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); - if (rc == 0) { - /* Connect can take lots of time */ - mod_timer(&wil->connect_timer, - jiffies + msecs_to_jiffies(2000)); - } - - out: - cfg80211_put_bss(bss); - - return rc; -} - -static int wil_cfg80211_disconnect(struct wiphy *wiphy, - struct net_device *ndev, - u16 reason_code) -{ - int rc; - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - - rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); - - return rc; -} - -static int wil_cfg80211_set_channel(struct wiphy *wiphy, - struct cfg80211_chan_def *chandef) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = wil->wdev; - - wdev->preset_chandef = *chandef; - - return 0; -} - -static int wil_cfg80211_add_key(struct wiphy *wiphy, - struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr, - struct key_params *params) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - - /* group key is not used */ - if (!pairwise) - return 0; - - return wmi_add_cipher_key(wil, key_index, mac_addr, - params->key_len, params->key); -} - -static int wil_cfg80211_del_key(struct wiphy *wiphy, - struct net_device *ndev, - u8 key_index, bool pairwise, - const u8 *mac_addr) -{ - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - - /* group key is not used */ - if (!pairwise) - return 0; - - return wmi_del_cipher_key(wil, key_index, mac_addr); -} - -/* Need to be present or wiphy_new() will WARN */ -static int wil_cfg80211_set_default_key(struct wiphy *wiphy, - struct net_device *ndev, - u8 key_index, bool unicast, - bool multicast) -{ - return 0; -} - -static int wil_cfg80211_start_ap(struct wiphy *wiphy, - struct net_device *ndev, - struct cfg80211_ap_settings *info) -{ - int rc = 0; - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = ndev->ieee80211_ptr; - struct ieee80211_channel *channel = info->chandef.chan; - struct cfg80211_beacon_data *bcon = &info->beacon; - u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); - - if (!channel) { - wil_err(wil, "AP: No channel???\n"); - return -EINVAL; - } - - wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, - channel->center_freq, info->privacy ? "secure" : "open"); - print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, - info->ssid, info->ssid_len); - - rc = wil_reset(wil); - if (rc) - return rc; - - rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); - if (rc) - return rc; - - rc = wmi_set_channel(wil, channel->hw_value); - if (rc) - return rc; - - /* MAC address - pre-requisite for other commands */ - wmi_set_mac_address(wil, ndev->dev_addr); - - /* IE's */ - /* bcon 'head IE's are not relevant for 60g band */ - wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, - bcon->beacon_ies); - wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, - bcon->proberesp_ies); - wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, - bcon->assocresp_ies); - - wil->secure_pcp = info->privacy; - - rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); - if (rc) - return rc; - - /* Rx VRING. After MAC and beacon */ - rc = wil_rx_init(wil); - - netif_carrier_on(ndev); - - return rc; -} - -static int wil_cfg80211_stop_ap(struct wiphy *wiphy, - struct net_device *ndev) -{ - int rc = 0; - struct wil6210_priv *wil = wiphy_to_wil(wiphy); - struct wireless_dev *wdev = ndev->ieee80211_ptr; - u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); - - /* To stop beaconing, set BI to 0 */ - rc = wmi_set_bcon(wil, 0, wmi_nettype); - - return rc; -} - -static struct cfg80211_ops wil_cfg80211_ops = { - .scan = wil_cfg80211_scan, - .connect = wil_cfg80211_connect, - .disconnect = wil_cfg80211_disconnect, - .change_virtual_intf = wil_cfg80211_change_iface, - .get_station = wil_cfg80211_get_station, - .set_monitor_channel = wil_cfg80211_set_channel, - .add_key = wil_cfg80211_add_key, - .del_key = wil_cfg80211_del_key, - .set_default_key = wil_cfg80211_set_default_key, - /* AP mode */ - .start_ap = wil_cfg80211_start_ap, - .stop_ap = wil_cfg80211_stop_ap, -}; - -static void wil_wiphy_init(struct wiphy *wiphy) -{ - /* TODO: set real value */ - wiphy->max_scan_ssids = 10; - wiphy->max_num_pmkids = 0 /* TODO: */; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MONITOR); - /* TODO: enable P2P when integrated with supplicant: - * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) - */ - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", - __func__, wiphy->flags); - wiphy->probe_resp_offload = - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - - wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; - - /* TODO: figure this out */ - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->cipher_suites = wil_cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); - wiphy->mgmt_stypes = wil_mgmt_stypes; -} - -struct wireless_dev *wil_cfg80211_init(struct device *dev) -{ - int rc = 0; - struct wireless_dev *wdev; - - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) - return ERR_PTR(-ENOMEM); - - wdev->wiphy = wiphy_new(&wil_cfg80211_ops, - sizeof(struct wil6210_priv)); - if (!wdev->wiphy) { - rc = -ENOMEM; - goto out; - } - - set_wiphy_dev(wdev->wiphy, dev); - wil_wiphy_init(wdev->wiphy); - - rc = wiphy_register(wdev->wiphy); - if (rc < 0) - goto out_failed_reg; - - return wdev; - -out_failed_reg: - wiphy_free(wdev->wiphy); -out: - kfree(wdev); - - return ERR_PTR(rc); -} - -void wil_wdev_free(struct wil6210_priv *wil) -{ - struct wireless_dev *wdev = wil_to_wdev(wil); - - if (!wdev) - return; - - wiphy_unregister(wdev->wiphy); - wiphy_free(wdev->wiphy); - kfree(wdev); -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/trunk/drivers/net/wireless/ath/wil6210/dbg_hexdump.h deleted file mode 100644 index 6a315ba5aa7d..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/dbg_hexdump.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef WIL_DBG_HEXDUMP_H_ -#define WIL_DBG_HEXDUMP_H_ - -#if defined(CONFIG_DYNAMIC_DEBUG) -#define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) \ -do { \ - DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ - __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ - if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ - print_hex_dump(KERN_DEBUG, prefix_str, \ - prefix_type, rowsize, groupsize, \ - buf, len, ascii); \ -} while (0) - -#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) \ - wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) - -#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ - wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) -#else /* defined(CONFIG_DYNAMIC_DEBUG) */ -#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) \ - print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) -#endif /* defined(CONFIG_DYNAMIC_DEBUG) */ - -#endif /* WIL_DBG_HEXDUMP_H_ */ diff --git a/trunk/drivers/net/wireless/ath/wil6210/debugfs.c b/trunk/drivers/net/wireless/ath/wil6210/debugfs.c deleted file mode 100644 index 65fc9683bfd8..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/debugfs.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" -#include "txrx.h" - -/* Nasty hack. Better have per device instances */ -static u32 mem_addr; -static u32 dbg_txdesc_index; - -static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, - const char *name, struct vring *vring) -{ - void __iomem *x = wmi_addr(wil, vring->hwtail); - - seq_printf(s, "VRING %s = {\n", name); - seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); - seq_printf(s, " va = 0x%p\n", vring->va); - seq_printf(s, " size = %d\n", vring->size); - seq_printf(s, " swtail = %d\n", vring->swtail); - seq_printf(s, " swhead = %d\n", vring->swhead); - seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); - if (x) - seq_printf(s, "0x%08x\n", ioread32(x)); - else - seq_printf(s, "???\n"); - - if (vring->va && (vring->size < 1025)) { - uint i; - for (i = 0; i < vring->size; i++) { - volatile struct vring_tx_desc *d = &vring->va[i].tx; - if ((i % 64) == 0 && (i != 0)) - seq_printf(s, "\n"); - seq_printf(s, "%s", (d->dma.status & BIT(0)) ? - "S" : (vring->ctx[i] ? "H" : "h")); - } - seq_printf(s, "\n"); - } - seq_printf(s, "}\n"); -} - -static int wil_vring_debugfs_show(struct seq_file *s, void *data) -{ - uint i; - struct wil6210_priv *wil = s->private; - - wil_print_vring(s, wil, "rx", &wil->vring_rx); - - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { - struct vring *vring = &(wil->vring_tx[i]); - if (vring->va) { - char name[10]; - snprintf(name, sizeof(name), "tx_%2d", i); - wil_print_vring(s, wil, name, vring); - } - } - - return 0; -} - -static int wil_vring_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_vring_debugfs_show, inode->i_private); -} - -static const struct file_operations fops_vring = { - .open = wil_vring_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -static void wil_print_ring(struct seq_file *s, const char *prefix, - void __iomem *off) -{ - struct wil6210_priv *wil = s->private; - struct wil6210_mbox_ring r; - int rsize; - uint i; - - wil_memcpy_fromio_32(&r, off, sizeof(r)); - wil_mbox_ring_le2cpus(&r); - /* - * we just read memory block from NIC. This memory may be - * garbage. Check validity before using it. - */ - rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); - - seq_printf(s, "ring %s = {\n", prefix); - seq_printf(s, " base = 0x%08x\n", r.base); - seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); - seq_printf(s, " tail = 0x%08x\n", r.tail); - seq_printf(s, " head = 0x%08x\n", r.head); - seq_printf(s, " entry size = %d\n", r.entry_size); - - if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { - seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", - sizeof(struct wil6210_mbox_ring_desc)); - goto out; - } - - if (!wmi_addr(wil, r.base) || - !wmi_addr(wil, r.tail) || - !wmi_addr(wil, r.head)) { - seq_printf(s, " ??? pointers are garbage?\n"); - goto out; - } - - for (i = 0; i < rsize; i++) { - struct wil6210_mbox_ring_desc d; - struct wil6210_mbox_hdr hdr; - size_t delta = i * sizeof(d); - void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; - - wil_memcpy_fromio_32(&d, x, sizeof(d)); - - seq_printf(s, " [%2x] %s %s%s 0x%08x", i, - d.sync ? "F" : "E", - (r.tail - r.base == delta) ? "t" : " ", - (r.head - r.base == delta) ? "h" : " ", - le32_to_cpu(d.addr)); - if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { - u16 len = le16_to_cpu(hdr.len); - seq_printf(s, " -> %04x %04x %04x %02x\n", - le16_to_cpu(hdr.seq), len, - le16_to_cpu(hdr.type), hdr.flags); - if (len <= MAX_MBOXITEM_SIZE) { - int n = 0; - unsigned char printbuf[16 * 3 + 2]; - unsigned char databuf[MAX_MBOXITEM_SIZE]; - void __iomem *src = wmi_buffer(wil, d.addr) + - sizeof(struct wil6210_mbox_hdr); - /* - * No need to check @src for validity - - * we already validated @d.addr while - * reading header - */ - wil_memcpy_fromio_32(databuf, src, len); - while (n < len) { - int l = min(len - n, 16); - hex_dump_to_buffer(databuf + n, l, - 16, 1, printbuf, - sizeof(printbuf), - false); - seq_printf(s, " : %s\n", printbuf); - n += l; - } - } - } else { - seq_printf(s, "\n"); - } - } - out: - seq_printf(s, "}\n"); -} - -static int wil_mbox_debugfs_show(struct seq_file *s, void *data) -{ - struct wil6210_priv *wil = s->private; - - wil_print_ring(s, "tx", wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, tx)); - wil_print_ring(s, "rx", wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, rx)); - - return 0; -} - -static int wil_mbox_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_mbox_debugfs_show, inode->i_private); -} - -static const struct file_operations fops_mbox = { - .open = wil_mbox_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -static int wil_debugfs_iomem_x32_set(void *data, u64 val) -{ - iowrite32(val, (void __iomem *)data); - wmb(); /* make sure write propagated to HW */ - - return 0; -} - -static int wil_debugfs_iomem_x32_get(void *data, u64 *val) -{ - *val = ioread32((void __iomem *)data); - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, - wil_debugfs_iomem_x32_set, "0x%08llx\n"); - -static struct dentry *wil_debugfs_create_iomem_x32(const char *name, - mode_t mode, - struct dentry *parent, - void __iomem *value) -{ - return debugfs_create_file(name, mode, parent, (void * __force)value, - &fops_iomem_x32); -} - -static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, - const char *name, - struct dentry *parent, u32 off) -{ - struct dentry *d = debugfs_create_dir(name, parent); - - if (IS_ERR_OR_NULL(d)) - return -ENODEV; - - wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, - wil->csr + off); - wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, - wil->csr + off + 4); - wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, - wil->csr + off + 8); - wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, - wil->csr + off + 12); - wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, - wil->csr + off + 16); - wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, - wil->csr + off + 20); - wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, - wil->csr + off + 24); - - return 0; -} - -static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, - struct dentry *parent) -{ - struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); - - if (IS_ERR_OR_NULL(d)) - return -ENODEV; - - wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); - wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); - wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); - - return 0; -} - -static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, - struct dentry *parent) -{ - struct dentry *d = debugfs_create_dir("ITR_CNT", parent); - - if (IS_ERR_OR_NULL(d)) - return -ENODEV; - - wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); - wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_ITR_CNT_DATA)); - wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + - HOSTADDR(RGF_DMA_ITR_CNT_CRL)); - - return 0; -} - -static int wil_memread_debugfs_show(struct seq_file *s, void *data) -{ - struct wil6210_priv *wil = s->private; - void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); - - if (a) - seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); - else - seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); - - return 0; -} - -static int wil_memread_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_memread_debugfs_show, inode->i_private); -} - -static const struct file_operations fops_memread = { - .open = wil_memread_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -static int wil_default_open(struct inode *inode, struct file *file) -{ - if (inode->i_private) - file->private_data = inode->i_private; - - return 0; -} - -static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - enum { max_count = 4096 }; - struct debugfs_blob_wrapper *blob = file->private_data; - loff_t pos = *ppos; - size_t available = blob->size; - void *buf; - size_t ret; - - if (pos < 0) - return -EINVAL; - - if (pos >= available || !count) - return 0; - - if (count > available - pos) - count = available - pos; - if (count > max_count) - count = max_count; - - buf = kmalloc(count, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + - pos, count); - - ret = copy_to_user(user_buf, buf, count); - kfree(buf); - if (ret == count) - return -EFAULT; - - count -= ret; - *ppos = pos + count; - - return count; -} - -static const struct file_operations fops_ioblob = { - .read = wil_read_file_ioblob, - .open = wil_default_open, - .llseek = default_llseek, -}; - -static -struct dentry *wil_debugfs_create_ioblob(const char *name, - mode_t mode, - struct dentry *parent, - struct debugfs_blob_wrapper *blob) -{ - return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); -} -/*---reset---*/ -static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, - size_t len, loff_t *ppos) -{ - struct wil6210_priv *wil = file->private_data; - struct net_device *ndev = wil_to_ndev(wil); - - /** - * BUG: - * this code does NOT sync device state with the rest of system - * use with care, debug only!!! - */ - rtnl_lock(); - dev_close(ndev); - ndev->flags &= ~IFF_UP; - rtnl_unlock(); - wil_reset(wil); - - return len; -} - -static const struct file_operations fops_reset = { - .write = wil_write_file_reset, - .open = wil_default_open, -}; -/*---------Tx descriptor------------*/ - -static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) -{ - struct wil6210_priv *wil = s->private; - struct vring *vring = &(wil->vring_tx[0]); - - if (!vring->va) { - seq_printf(s, "No Tx VRING\n"); - return 0; - } - - if (dbg_txdesc_index < vring->size) { - volatile struct vring_tx_desc *d = - &(vring->va[dbg_txdesc_index].tx); - volatile u32 *u = (volatile u32 *)d; - struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; - - seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); - seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", - u[0], u[1], u[2], u[3]); - seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", - u[4], u[5], u[6], u[7]); - seq_printf(s, " SKB = %p\n", skb); - - if (skb) { - unsigned char printbuf[16 * 3 + 2]; - int i = 0; - int len = skb_headlen(skb); - void *p = skb->data; - - seq_printf(s, " len = %d\n", len); - - while (i < len) { - int l = min(len - i, 16); - hex_dump_to_buffer(p + i, l, 16, 1, printbuf, - sizeof(printbuf), false); - seq_printf(s, " : %s\n", printbuf); - i += l; - } - } - seq_printf(s, "}\n"); - } else { - seq_printf(s, "TxDesc index (%d) >= size (%d)\n", - dbg_txdesc_index, vring->size); - } - - return 0; -} - -static int wil_txdesc_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_txdesc_debugfs_show, inode->i_private); -} - -static const struct file_operations fops_txdesc = { - .open = wil_txdesc_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; - -/*---------beamforming------------*/ -static int wil_bf_debugfs_show(struct seq_file *s, void *data) -{ - struct wil6210_priv *wil = s->private; - seq_printf(s, - "TSF : 0x%016llx\n" - "TxMCS : %d\n" - "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", - wil->stats.tsf, wil->stats.bf_mcs, - wil->stats.my_rx_sector, wil->stats.my_tx_sector, - wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); - return 0; -} - -static int wil_bf_seq_open(struct inode *inode, struct file *file) -{ - return single_open(file, wil_bf_debugfs_show, inode->i_private); -} - -static const struct file_operations fops_bf = { - .open = wil_bf_seq_open, - .release = single_release, - .read = seq_read, - .llseek = seq_lseek, -}; -/*---------SSID------------*/ -static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wil6210_priv *wil = file->private_data; - struct wireless_dev *wdev = wil_to_wdev(wil); - - return simple_read_from_buffer(user_buf, count, ppos, - wdev->ssid, wdev->ssid_len); -} - -static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct wil6210_priv *wil = file->private_data; - struct wireless_dev *wdev = wil_to_wdev(wil); - struct net_device *ndev = wil_to_ndev(wil); - - if (*ppos != 0) { - wil_err(wil, "Unable to set SSID substring from [%d]\n", - (int)*ppos); - return -EINVAL; - } - - if (count > sizeof(wdev->ssid)) { - wil_err(wil, "SSID too long, len = %d\n", (int)count); - return -EINVAL; - } - if (netif_running(ndev)) { - wil_err(wil, "Unable to change SSID on running interface\n"); - return -EINVAL; - } - - wdev->ssid_len = count; - return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, - buf, count); -} - -static const struct file_operations fops_ssid = { - .read = wil_read_file_ssid, - .write = wil_write_file_ssid, - .open = wil_default_open, -}; - -/*----------------*/ -int wil6210_debugfs_init(struct wil6210_priv *wil) -{ - struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, - wil_to_wiphy(wil)->debugfsdir); - - if (IS_ERR_OR_NULL(dbg)) - return -ENODEV; - - debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); - debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); - debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); - debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, - &dbg_txdesc_index); - debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); - debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); - debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, - &wil->secure_pcp); - - wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, - HOSTADDR(RGF_USER_USER_ICR)); - wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, - HOSTADDR(RGF_DMA_EP_TX_ICR)); - wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, - HOSTADDR(RGF_DMA_EP_RX_ICR)); - wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, - HOSTADDR(RGF_DMA_EP_MISC_ICR)); - wil6210_debugfs_create_pseudo_ISR(wil, dbg); - wil6210_debugfs_create_ITR_CNT(wil, dbg); - - debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); - debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); - - debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); - - wil->rgf_blob.data = (void * __force)wil->csr + 0; - wil->rgf_blob.size = 0xa000; - wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); - - wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; - wil->fw_code_blob.size = 0x40000; - wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, - &wil->fw_code_blob); - - wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; - wil->fw_data_blob.size = 0x8000; - wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, - &wil->fw_data_blob); - - wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; - wil->fw_peri_blob.size = 0x18000; - wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, - &wil->fw_peri_blob); - - wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; - wil->uc_code_blob.size = 0x10000; - wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, - &wil->uc_code_blob); - - wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; - wil->uc_data_blob.size = 0x4000; - wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, - &wil->uc_data_blob); - - return 0; -} - -void wil6210_debugfs_remove(struct wil6210_priv *wil) -{ - debugfs_remove_recursive(wil->debug); - wil->debug = NULL; -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/interrupt.c b/trunk/drivers/net/wireless/ath/wil6210/interrupt.c deleted file mode 100644 index 38049da71049..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/interrupt.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" - -/** - * Theory of operation: - * - * There is ISR pseudo-cause register, - * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE - * Its bits represents OR'ed bits from 3 real ISR registers: - * TX, RX, and MISC. - * - * Registers may be configured to either "write 1 to clear" or - * "clear on read" mode - * - * When handling interrupt, one have to mask/unmask interrupts for the - * real ISR registers, or hardware may malfunction. - * - */ - -#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) -#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE -#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ - BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) -#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) - -#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ - BIT_DMA_PSEUDO_CAUSE_TX | \ - BIT_DMA_PSEUDO_CAUSE_MISC)) - -#if defined(CONFIG_WIL6210_ISR_COR) -/* configure to Clear-On-Read mode */ -#define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) - -static inline void wil_icr_clear(u32 x, void __iomem *addr) -{ - -} -#else /* defined(CONFIG_WIL6210_ISR_COR) */ -/* configure to Write-1-to-Clear mode */ -#define WIL_ICR_ICC_VALUE (0UL) - -static inline void wil_icr_clear(u32 x, void __iomem *addr) -{ - iowrite32(x, addr); -} -#endif /* defined(CONFIG_WIL6210_ISR_COR) */ - -static inline u32 wil_ioread32_and_clear(void __iomem *addr) -{ - u32 x = ioread32(addr); - - wil_icr_clear(x, addr); - - return x; -} - -static void wil6210_mask_irq_tx(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IRQ_DISABLE, wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, IMS)); -} - -static void wil6210_mask_irq_rx(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IRQ_DISABLE, wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, IMS)); -} - -static void wil6210_mask_irq_misc(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IRQ_DISABLE, wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, IMS)); -} - -static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) -{ - wil_dbg_IRQ(wil, "%s()\n", __func__); - - iowrite32(WIL6210_IRQ_DISABLE, wil->csr + - HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); - - clear_bit(wil_status_irqen, &wil->status); -} - -static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IMC_TX, wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, IMC)); -} - -static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IMC_RX, wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, IMC)); -} - -static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) -{ - iowrite32(WIL6210_IMC_MISC, wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, IMC)); -} - -static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) -{ - wil_dbg_IRQ(wil, "%s()\n", __func__); - - set_bit(wil_status_irqen, &wil->status); - - iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + - HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); -} - -void wil6210_disable_irq(struct wil6210_priv *wil) -{ - wil_dbg_IRQ(wil, "%s()\n", __func__); - - wil6210_mask_irq_tx(wil); - wil6210_mask_irq_rx(wil); - wil6210_mask_irq_misc(wil); - wil6210_mask_irq_pseudo(wil); -} - -void wil6210_enable_irq(struct wil6210_priv *wil) -{ - wil_dbg_IRQ(wil, "%s()\n", __func__); - - iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, ICC)); - iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, ICC)); - iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, ICC)); - - wil6210_unmask_irq_pseudo(wil); - wil6210_unmask_irq_tx(wil); - wil6210_unmask_irq_rx(wil); - wil6210_unmask_irq_misc(wil); -} - -static irqreturn_t wil6210_irq_rx(int irq, void *cookie) -{ - struct wil6210_priv *wil = cookie; - u32 isr = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, ICR)); - - wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); - - if (!isr) { - wil_err(wil, "spurious IRQ: RX\n"); - return IRQ_NONE; - } - - wil6210_mask_irq_rx(wil); - - if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { - wil_dbg_IRQ(wil, "RX done\n"); - isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; - wil_rx_handle(wil); - } - - if (isr) - wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); - - wil6210_unmask_irq_rx(wil); - - return IRQ_HANDLED; -} - -static irqreturn_t wil6210_irq_tx(int irq, void *cookie) -{ - struct wil6210_priv *wil = cookie; - u32 isr = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, ICR)); - - wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); - - if (!isr) { - wil_err(wil, "spurious IRQ: TX\n"); - return IRQ_NONE; - } - - wil6210_mask_irq_tx(wil); - - if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { - uint i; - wil_dbg_IRQ(wil, "TX done\n"); - isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; - for (i = 0; i < 24; i++) { - u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); - if (isr & mask) { - isr &= ~mask; - wil_dbg_IRQ(wil, "TX done(%i)\n", i); - wil_tx_complete(wil, i); - } - } - } - - if (isr) - wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); - - wil6210_unmask_irq_tx(wil); - - return IRQ_HANDLED; -} - -static irqreturn_t wil6210_irq_misc(int irq, void *cookie) -{ - struct wil6210_priv *wil = cookie; - u32 isr = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, ICR)); - - wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); - - if (!isr) { - wil_err(wil, "spurious IRQ: MISC\n"); - return IRQ_NONE; - } - - wil6210_mask_irq_misc(wil); - - if (isr & ISR_MISC_FW_READY) { - wil_dbg_IRQ(wil, "IRQ: FW ready\n"); - /** - * Actual FW ready indicated by the - * WMI_FW_READY_EVENTID - */ - isr &= ~ISR_MISC_FW_READY; - } - - wil->isr_misc = isr; - - if (isr) { - return IRQ_WAKE_THREAD; - } else { - wil6210_unmask_irq_misc(wil); - return IRQ_HANDLED; - } -} - -static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) -{ - struct wil6210_priv *wil = cookie; - u32 isr = wil->isr_misc; - - wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); - - if (isr & ISR_MISC_MBOX_EVT) { - wil_dbg_IRQ(wil, "MBOX event\n"); - wmi_recv_cmd(wil); - isr &= ~ISR_MISC_MBOX_EVT; - } - - if (isr) - wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); - - wil->isr_misc = 0; - - wil6210_unmask_irq_misc(wil); - - return IRQ_HANDLED; -} - -/** - * thread IRQ handler - */ -static irqreturn_t wil6210_thread_irq(int irq, void *cookie) -{ - struct wil6210_priv *wil = cookie; - - wil_dbg_IRQ(wil, "Thread IRQ\n"); - /* Discover real IRQ cause */ - if (wil->isr_misc) - wil6210_irq_misc_thread(irq, cookie); - - wil6210_unmask_irq_pseudo(wil); - - return IRQ_HANDLED; -} - -/* DEBUG - * There is subtle bug in hardware that causes IRQ to raise when it should be - * masked. It is quite rare and hard to debug. - * - * Catch irq issue if it happens and print all I can. - */ -static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) -{ - if (!test_bit(wil_status_irqen, &wil->status)) { - u32 icm_rx = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, ICM)); - u32 icr_rx = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, ICR)); - u32 imv_rx = ioread32(wil->csr + - HOSTADDR(RGF_DMA_EP_RX_ICR) + - offsetof(struct RGF_ICR, IMV)); - u32 icm_tx = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, ICM)); - u32 icr_tx = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, ICR)); - u32 imv_tx = ioread32(wil->csr + - HOSTADDR(RGF_DMA_EP_TX_ICR) + - offsetof(struct RGF_ICR, IMV)); - u32 icm_misc = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, ICM)); - u32 icr_misc = wil_ioread32_and_clear(wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, ICR)); - u32 imv_misc = ioread32(wil->csr + - HOSTADDR(RGF_DMA_EP_MISC_ICR) + - offsetof(struct RGF_ICR, IMV)); - wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" - "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" - "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" - "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", - pseudo_cause, - icm_rx, icr_rx, imv_rx, - icm_tx, icr_tx, imv_tx, - icm_misc, icr_misc, imv_misc); - - return -EINVAL; - } - - return 0; -} - -static irqreturn_t wil6210_hardirq(int irq, void *cookie) -{ - irqreturn_t rc = IRQ_HANDLED; - struct wil6210_priv *wil = cookie; - u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); - - /** - * pseudo_cause is Clear-On-Read, no need to ACK - */ - if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) - return IRQ_NONE; - - /* FIXME: IRQ mask debug */ - if (wil6210_debug_irq_mask(wil, pseudo_cause)) - return IRQ_NONE; - - wil6210_mask_irq_pseudo(wil); - - /* Discover real IRQ cause - * There are 2 possible phases for every IRQ: - * - hard IRQ handler called right here - * - threaded handler called later - * - * Hard IRQ handler reads and clears ISR. - * - * If threaded handler requested, hard IRQ handler - * returns IRQ_WAKE_THREAD and saves ISR register value - * for the threaded handler use. - * - * voting for wake thread - need at least 1 vote - */ - if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && - (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) - rc = IRQ_WAKE_THREAD; - - if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && - (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) - rc = IRQ_WAKE_THREAD; - - if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && - (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) - rc = IRQ_WAKE_THREAD; - - /* if thread is requested, it will unmask IRQ */ - if (rc != IRQ_WAKE_THREAD) - wil6210_unmask_irq_pseudo(wil); - - wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); - - return rc; -} - -static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) -{ - int rc; - /* - * IRQ's are in the following order: - * - Tx - * - Rx - * - Misc - */ - - rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, - WIL_NAME"_tx", wil); - if (rc) - return rc; - - rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, - WIL_NAME"_rx", wil); - if (rc) - goto free0; - - rc = request_threaded_irq(irq + 2, wil6210_irq_misc, - wil6210_irq_misc_thread, - IRQF_SHARED, WIL_NAME"_misc", wil); - if (rc) - goto free1; - - return 0; - /* error branch */ -free1: - free_irq(irq + 1, wil); -free0: - free_irq(irq, wil); - - return rc; -} - -int wil6210_init_irq(struct wil6210_priv *wil, int irq) -{ - int rc; - if (wil->n_msi == 3) - rc = wil6210_request_3msi(wil, irq); - else - rc = request_threaded_irq(irq, wil6210_hardirq, - wil6210_thread_irq, - wil->n_msi ? 0 : IRQF_SHARED, - WIL_NAME, wil); - if (rc) - return rc; - - wil6210_enable_irq(wil); - - return 0; -} - -void wil6210_fini_irq(struct wil6210_priv *wil, int irq) -{ - wil6210_disable_irq(wil); - free_irq(irq, wil); - if (wil->n_msi == 3) { - free_irq(irq + 1, wil); - free_irq(irq + 2, wil); - } -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/main.c b/trunk/drivers/net/wireless/ath/wil6210/main.c deleted file mode 100644 index 95fcd361322b..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/main.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" - -/* - * Due to a hardware issue, - * one has to read/write to/from NIC in 32-bit chunks; - * regular memcpy_fromio and siblings will - * not work on 64-bit platform - it uses 64-bit transactions - * - * Force 32-bit transactions to enable NIC on 64-bit platforms - * - * To avoid byte swap on big endian host, __raw_{read|write}l - * should be used - {read|write}l would swap bytes to provide - * little endian on PCI value in host endianness. - */ -void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, - size_t count) -{ - u32 *d = dst; - const volatile u32 __iomem *s = src; - - /* size_t is unsigned, if (count%4 != 0) it will wrap */ - for (count += 4; count > 4; count -= 4) - *d++ = __raw_readl(s++); -} - -void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, - size_t count) -{ - volatile u32 __iomem *d = dst; - const u32 *s = src; - - for (count += 4; count > 4; count -= 4) - __raw_writel(*s++, d++); -} - -static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) -{ - uint i; - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; - - wil_dbg(wil, "%s()\n", __func__); - - wil_link_off(wil); - clear_bit(wil_status_fwconnected, &wil->status); - - switch (wdev->sme_state) { - case CFG80211_SME_CONNECTED: - cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, - NULL, 0, GFP_KERNEL); - break; - case CFG80211_SME_CONNECTING: - cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - break; - default: - ; - } - - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) - wil_vring_fini_tx(wil, i); -} - -static void wil_disconnect_worker(struct work_struct *work) -{ - struct wil6210_priv *wil = container_of(work, - struct wil6210_priv, disconnect_worker); - - _wil6210_disconnect(wil, NULL); -} - -static void wil_connect_timer_fn(ulong x) -{ - struct wil6210_priv *wil = (void *)x; - - wil_dbg(wil, "Connect timeout\n"); - - /* reschedule to thread context - disconnect won't - * run from atomic context - */ - schedule_work(&wil->disconnect_worker); -} - -int wil_priv_init(struct wil6210_priv *wil) -{ - wil_dbg(wil, "%s()\n", __func__); - - mutex_init(&wil->mutex); - mutex_init(&wil->wmi_mutex); - - init_completion(&wil->wmi_ready); - - wil->pending_connect_cid = -1; - setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); - - INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); - INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); - INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); - - INIT_LIST_HEAD(&wil->pending_wmi_ev); - spin_lock_init(&wil->wmi_ev_lock); - - wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); - if (!wil->wmi_wq) - return -EAGAIN; - - wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); - if (!wil->wmi_wq_conn) { - destroy_workqueue(wil->wmi_wq); - return -EAGAIN; - } - - /* make shadow copy of registers that should not change on run time */ - wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, - sizeof(struct wil6210_mbox_ctl)); - wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); - wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); - - return 0; -} - -void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) -{ - del_timer_sync(&wil->connect_timer); - _wil6210_disconnect(wil, bssid); -} - -void wil_priv_deinit(struct wil6210_priv *wil) -{ - cancel_work_sync(&wil->disconnect_worker); - wil6210_disconnect(wil, NULL); - wmi_event_flush(wil); - destroy_workqueue(wil->wmi_wq_conn); - destroy_workqueue(wil->wmi_wq); -} - -static void wil_target_reset(struct wil6210_priv *wil) -{ - wil_dbg(wil, "Resetting...\n"); - - /* register write */ -#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) - /* register set = read, OR, write */ -#define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ - wil->csr + HOSTADDR(a)) - - /* hpal_perst_from_pad_src_n_mask */ - S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); - /* car_perst_rst_src_n_mask */ - S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); - - W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ - W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ - - msleep(100); - - W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); - - msleep(100); - - W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); - - W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); - W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); - - msleep(2000); - - W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ - - msleep(2000); - - wil_dbg(wil, "Reset completed\n"); - -#undef W -#undef S -} - -void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) -{ - le32_to_cpus(&r->base); - le16_to_cpus(&r->entry_size); - le16_to_cpus(&r->size); - le32_to_cpus(&r->tail); - le32_to_cpus(&r->head); -} - -static int wil_wait_for_fw_ready(struct wil6210_priv *wil) -{ - ulong to = msecs_to_jiffies(1000); - ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); - if (0 == left) { - wil_err(wil, "Firmware not ready\n"); - return -ETIME; - } else { - wil_dbg(wil, "FW ready after %d ms\n", - jiffies_to_msecs(to-left)); - } - return 0; -} - -/* - * We reset all the structures, and we reset the UMAC. - * After calling this routine, you're expected to reload - * the firmware. - */ -int wil_reset(struct wil6210_priv *wil) -{ - int rc; - - cancel_work_sync(&wil->disconnect_worker); - wil6210_disconnect(wil, NULL); - - wmi_event_flush(wil); - - flush_workqueue(wil->wmi_wq); - flush_workqueue(wil->wmi_wq_conn); - - wil6210_disable_irq(wil); - wil->status = 0; - - /* TODO: put MAC in reset */ - wil_target_reset(wil); - - /* init after reset */ - wil->pending_connect_cid = -1; - INIT_COMPLETION(wil->wmi_ready); - - /* make shadow copy of registers that should not change on run time */ - wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, - sizeof(struct wil6210_mbox_ctl)); - wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); - wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); - - /* TODO: release MAC reset */ - wil6210_enable_irq(wil); - - /* we just started MAC, wait for FW ready */ - rc = wil_wait_for_fw_ready(wil); - - return rc; -} - - -void wil_link_on(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - - wil_dbg(wil, "%s()\n", __func__); - - netif_carrier_on(ndev); - netif_tx_wake_all_queues(ndev); -} - -void wil_link_off(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - - wil_dbg(wil, "%s()\n", __func__); - - netif_tx_stop_all_queues(ndev); - netif_carrier_off(ndev); -} - -static int __wil_up(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; - struct ieee80211_channel *channel = wdev->preset_chandef.chan; - int rc; - int bi; - u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); - - rc = wil_reset(wil); - if (rc) - return rc; - - /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ - wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); - switch (wdev->iftype) { - case NL80211_IFTYPE_STATION: - wil_dbg(wil, "type: STATION\n"); - bi = 0; - ndev->type = ARPHRD_ETHER; - break; - case NL80211_IFTYPE_AP: - wil_dbg(wil, "type: AP\n"); - bi = 100; - ndev->type = ARPHRD_ETHER; - break; - case NL80211_IFTYPE_P2P_CLIENT: - wil_dbg(wil, "type: P2P_CLIENT\n"); - bi = 0; - ndev->type = ARPHRD_ETHER; - break; - case NL80211_IFTYPE_P2P_GO: - wil_dbg(wil, "type: P2P_GO\n"); - bi = 100; - ndev->type = ARPHRD_ETHER; - break; - case NL80211_IFTYPE_MONITOR: - wil_dbg(wil, "type: Monitor\n"); - bi = 0; - ndev->type = ARPHRD_IEEE80211_RADIOTAP; - /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ - break; - default: - return -EOPNOTSUPP; - } - - /* Apply profile in the following order: */ - /* SSID and channel for the AP */ - switch (wdev->iftype) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_P2P_GO: - if (wdev->ssid_len == 0) { - wil_err(wil, "SSID not set\n"); - return -EINVAL; - } - wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); - if (channel) - wmi_set_channel(wil, channel->hw_value); - break; - default: - ; - } - - /* MAC address - pre-requisite for other commands */ - wmi_set_mac_address(wil, ndev->dev_addr); - - /* Set up beaconing if required. */ - rc = wmi_set_bcon(wil, bi, wmi_nettype); - if (rc) - return rc; - - /* Rx VRING. After MAC and beacon */ - wil_rx_init(wil); - - return 0; -} - -int wil_up(struct wil6210_priv *wil) -{ - int rc; - - mutex_lock(&wil->mutex); - rc = __wil_up(wil); - mutex_unlock(&wil->mutex); - - return rc; -} - -static int __wil_down(struct wil6210_priv *wil) -{ - if (wil->scan_request) { - cfg80211_scan_done(wil->scan_request, true); - wil->scan_request = NULL; - } - - wil6210_disconnect(wil, NULL); - wil_rx_fini(wil); - - return 0; -} - -int wil_down(struct wil6210_priv *wil) -{ - int rc; - - mutex_lock(&wil->mutex); - rc = __wil_down(wil); - mutex_unlock(&wil->mutex); - - return rc; -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/netdev.c b/trunk/drivers/net/wireless/ath/wil6210/netdev.c deleted file mode 100644 index 3068b5cb53a7..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/netdev.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" - -static int wil_open(struct net_device *ndev) -{ - struct wil6210_priv *wil = ndev_to_wil(ndev); - - return wil_up(wil); -} - -static int wil_stop(struct net_device *ndev) -{ - struct wil6210_priv *wil = ndev_to_wil(ndev); - - return wil_down(wil); -} - -/* - * AC to queue mapping - * - * AC_VO -> queue 3 - * AC_VI -> queue 2 - * AC_BE -> queue 1 - * AC_BK -> queue 0 - */ -static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) -{ - static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; - struct wil6210_priv *wil = ndev_to_wil(ndev); - u16 rc; - - skb->priority = cfg80211_classify8021d(skb); - - rc = wil_1d_to_queue[skb->priority]; - - wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, - (int)rc); - - return rc; -} - -static const struct net_device_ops wil_netdev_ops = { - .ndo_open = wil_open, - .ndo_stop = wil_stop, - .ndo_start_xmit = wil_start_xmit, - .ndo_select_queue = wil_select_queue, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -void *wil_if_alloc(struct device *dev, void __iomem *csr) -{ - struct net_device *ndev; - struct wireless_dev *wdev; - struct wil6210_priv *wil; - struct ieee80211_channel *ch; - int rc = 0; - - wdev = wil_cfg80211_init(dev); - if (IS_ERR(wdev)) { - dev_err(dev, "wil_cfg80211_init failed\n"); - return wdev; - } - - wil = wdev_to_wil(wdev); - wil->csr = csr; - wil->wdev = wdev; - - rc = wil_priv_init(wil); - if (rc) { - dev_err(dev, "wil_priv_init failed\n"); - goto out_wdev; - } - - wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ - /* default monitor channel */ - ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; - cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); - - ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); - if (!ndev) { - dev_err(dev, "alloc_netdev_mqs failed\n"); - rc = -ENOMEM; - goto out_priv; - } - - ndev->netdev_ops = &wil_netdev_ops; - ndev->ieee80211_ptr = wdev; - SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); - wdev->netdev = ndev; - - wil_link_off(wil); - - return wil; - - out_priv: - wil_priv_deinit(wil); - - out_wdev: - wil_wdev_free(wil); - - return ERR_PTR(rc); -} - -void wil_if_free(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - if (!ndev) - return; - - free_netdev(ndev); - wil_priv_deinit(wil); - wil_wdev_free(wil); -} - -int wil_if_add(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - int rc; - - rc = register_netdev(ndev); - if (rc < 0) { - dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); - return rc; - } - - wil_link_off(wil); - - return 0; -} - -void wil_if_remove(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - - unregister_netdev(ndev); -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/pcie_bus.c b/trunk/drivers/net/wireless/ath/wil6210/pcie_bus.c deleted file mode 100644 index 0fc83edd6bad..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" - -static int use_msi = 1; -module_param(use_msi, int, S_IRUGO); -MODULE_PARM_DESC(use_msi, - " Use MSI interrupt: " - "0 - don't, 1 - (default) - single, or 3"); - -/* Bus ops */ -static int wil_if_pcie_enable(struct wil6210_priv *wil) -{ - struct pci_dev *pdev = wil->pdev; - int rc; - - pci_set_master(pdev); - - /* - * how many MSI interrupts to request? - */ - switch (use_msi) { - case 3: - case 1: - case 0: - break; - default: - wil_err(wil, "Invalid use_msi=%d, default to 1\n", - use_msi); - use_msi = 1; - } - wil->n_msi = use_msi; - if (wil->n_msi) { - wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); - rc = pci_enable_msi_block(pdev, wil->n_msi); - if (rc && (wil->n_msi == 3)) { - wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); - wil->n_msi = 1; - rc = pci_enable_msi_block(pdev, wil->n_msi); - } - if (rc) { - wil_err(wil, "pci_enable_msi failed, use INTx\n"); - wil->n_msi = 0; - } - } else { - wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); - } - - rc = wil6210_init_irq(wil, pdev->irq); - if (rc) - goto stop_master; - - /* need reset here to obtain MAC */ - rc = wil_reset(wil); - if (rc) - goto release_irq; - - return 0; - - release_irq: - wil6210_fini_irq(wil, pdev->irq); - /* safe to call if no MSI */ - pci_disable_msi(pdev); - stop_master: - pci_clear_master(pdev); - return rc; -} - -static int wil_if_pcie_disable(struct wil6210_priv *wil) -{ - struct pci_dev *pdev = wil->pdev; - - pci_clear_master(pdev); - /* disable and release IRQ */ - wil6210_fini_irq(wil, pdev->irq); - /* safe to call if no MSI */ - pci_disable_msi(pdev); - /* TODO: disable HW */ - - return 0; -} - -static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct wil6210_priv *wil; - struct device *dev = &pdev->dev; - void __iomem *csr; - int rc; - - /* check HW */ - dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", - (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); - - if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { - dev_err(&pdev->dev, "Not " WIL_NAME "? " - "BAR0 size is %lu while expecting %lu\n", - (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); - return -ENODEV; - } - - rc = pci_enable_device(pdev); - if (rc) { - dev_err(&pdev->dev, "pci_enable_device failed\n"); - return -ENODEV; - } - /* rollback to err_disable_pdev */ - - rc = pci_request_region(pdev, 0, WIL_NAME); - if (rc) { - dev_err(&pdev->dev, "pci_request_region failed\n"); - goto err_disable_pdev; - } - /* rollback to err_release_reg */ - - csr = pci_ioremap_bar(pdev, 0); - if (!csr) { - dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); - rc = -ENODEV; - goto err_release_reg; - } - /* rollback to err_iounmap */ - dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); - - wil = wil_if_alloc(dev, csr); - if (IS_ERR(wil)) { - rc = (int)PTR_ERR(wil); - dev_err(dev, "wil_if_alloc failed: %d\n", rc); - goto err_iounmap; - } - /* rollback to if_free */ - - pci_set_drvdata(pdev, wil); - wil->pdev = pdev; - - /* FW should raise IRQ when ready */ - rc = wil_if_pcie_enable(wil); - if (rc) { - wil_err(wil, "Enable device failed\n"); - goto if_free; - } - /* rollback to bus_disable */ - - rc = wil_if_add(wil); - if (rc) { - wil_err(wil, "wil_if_add failed: %d\n", rc); - goto bus_disable; - } - - wil6210_debugfs_init(wil); - - /* check FW is alive */ - wmi_echo(wil); - - return 0; - - bus_disable: - wil_if_pcie_disable(wil); - if_free: - wil_if_free(wil); - err_iounmap: - pci_iounmap(pdev, csr); - err_release_reg: - pci_release_region(pdev, 0); - err_disable_pdev: - pci_disable_device(pdev); - - return rc; -} - -static void wil_pcie_remove(struct pci_dev *pdev) -{ - struct wil6210_priv *wil = pci_get_drvdata(pdev); - - wil6210_debugfs_remove(wil); - wil_if_pcie_disable(wil); - wil_if_remove(wil); - wil_if_free(wil); - pci_iounmap(pdev, wil->csr); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); -} - -static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { - { PCI_DEVICE(0x1ae9, 0x0301) }, - { /* end: all zeroes */ }, -}; -MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); - -static struct pci_driver wil6210_driver = { - .probe = wil_pcie_probe, - .remove = wil_pcie_remove, - .id_table = wil6210_pcie_ids, - .name = WIL_NAME, -}; - -module_pci_driver(wil6210_driver); - -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_AUTHOR("Qualcomm Atheros "); -MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); diff --git a/trunk/drivers/net/wireless/ath/wil6210/txrx.c b/trunk/drivers/net/wireless/ath/wil6210/txrx.c deleted file mode 100644 index f29c294413cf..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/txrx.c +++ /dev/null @@ -1,871 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" -#include "wmi.h" -#include "txrx.h" - -static bool rtap_include_phy_info; -module_param(rtap_include_phy_info, bool, S_IRUGO); -MODULE_PARM_DESC(rtap_include_phy_info, - " Include PHY info in the radiotap header, default - no"); - -static inline int wil_vring_is_empty(struct vring *vring) -{ - return vring->swhead == vring->swtail; -} - -static inline u32 wil_vring_next_tail(struct vring *vring) -{ - return (vring->swtail + 1) % vring->size; -} - -static inline void wil_vring_advance_head(struct vring *vring, int n) -{ - vring->swhead = (vring->swhead + n) % vring->size; -} - -static inline int wil_vring_is_full(struct vring *vring) -{ - return wil_vring_next_tail(vring) == vring->swhead; -} -/* - * Available space in Tx Vring - */ -static inline int wil_vring_avail_tx(struct vring *vring) -{ - u32 swhead = vring->swhead; - u32 swtail = vring->swtail; - int used = (vring->size + swhead - swtail) % vring->size; - - return vring->size - used - 1; -} - -static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) -{ - struct device *dev = wil_to_dev(wil); - size_t sz = vring->size * sizeof(vring->va[0]); - uint i; - - BUILD_BUG_ON(sizeof(vring->va[0]) != 32); - - vring->swhead = 0; - vring->swtail = 0; - vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); - if (!vring->ctx) { - wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", - vring->size); - vring->va = NULL; - return -ENOMEM; - } - /* - * vring->va should be aligned on its size rounded up to power of 2 - * This is granted by the dma_alloc_coherent - */ - vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); - if (!vring->va) { - wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", - vring->size); - kfree(vring->ctx); - vring->ctx = NULL; - return -ENOMEM; - } - /* initially, all descriptors are SW owned - * For Tx and Rx, ownership bit is at the same location, thus - * we can use any - */ - for (i = 0; i < vring->size; i++) { - volatile struct vring_tx_desc *d = &(vring->va[i].tx); - d->dma.status = TX_DMA_STATUS_DU; - } - - wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, - vring->va, (unsigned long long)vring->pa, vring->ctx); - - return 0; -} - -static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, - int tx) -{ - struct device *dev = wil_to_dev(wil); - size_t sz = vring->size * sizeof(vring->va[0]); - - while (!wil_vring_is_empty(vring)) { - if (tx) { - volatile struct vring_tx_desc *d = - &vring->va[vring->swtail].tx; - dma_addr_t pa = d->dma.addr_low | - ((u64)d->dma.addr_high << 32); - struct sk_buff *skb = vring->ctx[vring->swtail]; - if (skb) { - dma_unmap_single(dev, pa, d->dma.length, - DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - vring->ctx[vring->swtail] = NULL; - } else { - dma_unmap_page(dev, pa, d->dma.length, - DMA_TO_DEVICE); - } - vring->swtail = wil_vring_next_tail(vring); - } else { /* rx */ - volatile struct vring_rx_desc *d = - &vring->va[vring->swtail].rx; - dma_addr_t pa = d->dma.addr_low | - ((u64)d->dma.addr_high << 32); - struct sk_buff *skb = vring->ctx[vring->swhead]; - dma_unmap_single(dev, pa, d->dma.length, - DMA_FROM_DEVICE); - kfree_skb(skb); - wil_vring_advance_head(vring, 1); - } - } - dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); - kfree(vring->ctx); - vring->pa = 0; - vring->va = NULL; - vring->ctx = NULL; -} - -/** - * Allocate one skb for Rx VRING - * - * Safe to call from IRQ - */ -static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, - u32 i, int headroom) -{ - struct device *dev = wil_to_dev(wil); - unsigned int sz = RX_BUF_LEN; - volatile struct vring_rx_desc *d = &(vring->va[i].rx); - dma_addr_t pa; - - /* TODO align */ - struct sk_buff *skb = dev_alloc_skb(sz + headroom); - if (unlikely(!skb)) - return -ENOMEM; - - skb_reserve(skb, headroom); - skb_put(skb, sz); - - pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(dev, pa))) { - kfree_skb(skb); - return -ENOMEM; - } - - d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; - d->dma.addr_low = lower_32_bits(pa); - d->dma.addr_high = (u16)upper_32_bits(pa); - /* ip_length don't care */ - /* b11 don't care */ - /* error don't care */ - d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ - d->dma.length = sz; - vring->ctx[i] = skb; - - return 0; -} - -/** - * Adds radiotap header - * - * Any error indicated as "Bad FCS" - * - * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: - * - Rx descriptor: 32 bytes - * - Phy info - */ -static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, - struct sk_buff *skb, - volatile struct vring_rx_desc *d) -{ - struct wireless_dev *wdev = wil->wdev; - struct wil6210_rtap { - struct ieee80211_radiotap_header rthdr; - /* fields should be in the order of bits in rthdr.it_present */ - /* flags */ - u8 flags; - /* channel */ - __le16 chnl_freq __aligned(2); - __le16 chnl_flags; - /* MCS */ - u8 mcs_present; - u8 mcs_flags; - u8 mcs_index; - } __packed; - struct wil6210_rtap_vendor { - struct wil6210_rtap rtap; - /* vendor */ - u8 vendor_oui[3] __aligned(2); - u8 vendor_ns; - __le16 vendor_skip; - u8 vendor_data[0]; - } __packed; - struct wil6210_rtap_vendor *rtap_vendor; - int rtap_len = sizeof(struct wil6210_rtap); - int phy_length = 0; /* phy info header size, bytes */ - static char phy_data[128]; - struct ieee80211_channel *ch = wdev->preset_chandef.chan; - - if (rtap_include_phy_info) { - rtap_len = sizeof(*rtap_vendor) + sizeof(*d); - /* calculate additional length */ - if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { - /** - * PHY info starts from 8-byte boundary - * there are 8-byte lines, last line may be partially - * written (HW bug), thus FW configures for last line - * to be excessive. Driver skips this last line. - */ - int len = min_t(int, 8 + sizeof(phy_data), - wil_rxdesc_phy_length(d)); - if (len > 8) { - void *p = skb_tail_pointer(skb); - void *pa = PTR_ALIGN(p, 8); - if (skb_tailroom(skb) >= len + (pa - p)) { - phy_length = len - 8; - memcpy(phy_data, pa, phy_length); - } - } - } - rtap_len += phy_length; - } - - if (skb_headroom(skb) < rtap_len && - pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { - wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); - return; - } - - rtap_vendor = (void *)skb_push(skb, rtap_len); - memset(rtap_vendor, 0, rtap_len); - - rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; - rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); - rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_MCS)); - if (d->dma.status & RX_DMA_STATUS_ERROR) - rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; - - rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); - rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); - - rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; - rtap_vendor->rtap.mcs_flags = 0; - rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); - - if (rtap_include_phy_info) { - rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << - IEEE80211_RADIOTAP_VENDOR_NAMESPACE); - /* OUI for Wilocity 04:ce:14 */ - rtap_vendor->vendor_oui[0] = 0x04; - rtap_vendor->vendor_oui[1] = 0xce; - rtap_vendor->vendor_oui[2] = 0x14; - rtap_vendor->vendor_ns = 1; - /* Rx descriptor + PHY data */ - rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + - phy_length); - memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); - memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, - phy_length); - } -} - -/* - * Fast swap in place between 2 registers - */ -static void wil_swap_u16(u16 *a, u16 *b) -{ - *a ^= *b; - *b ^= *a; - *a ^= *b; -} - -static void wil_swap_ethaddr(void *data) -{ - struct ethhdr *eth = data; - u16 *s = (u16 *)eth->h_source; - u16 *d = (u16 *)eth->h_dest; - - wil_swap_u16(s++, d++); - wil_swap_u16(s++, d++); - wil_swap_u16(s, d); -} - -/** - * reap 1 frame from @swhead - * - * Safe to call from IRQ - */ -static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, - struct vring *vring) -{ - struct device *dev = wil_to_dev(wil); - struct net_device *ndev = wil_to_ndev(wil); - volatile struct vring_rx_desc *d; - struct sk_buff *skb; - dma_addr_t pa; - unsigned int sz = RX_BUF_LEN; - u8 ftype; - u8 ds_bits; - - if (wil_vring_is_empty(vring)) - return NULL; - - d = &(vring->va[vring->swhead].rx); - if (!(d->dma.status & RX_DMA_STATUS_DU)) { - /* it is not error, we just reached end of Rx done area */ - return NULL; - } - - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); - skb = vring->ctx[vring->swhead]; - dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); - skb_trim(skb, d->dma.length); - - wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); - - /* use radiotap header only if required */ - if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) - wil_rx_add_radiotap_header(wil, skb, d); - - wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); - wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, - (const void *)d, sizeof(*d), false); - - wil_vring_advance_head(vring, 1); - - /* no extra checks if in sniffer mode */ - if (ndev->type != ARPHRD_ETHER) - return skb; - /* - * Non-data frames may be delivered through Rx DMA channel (ex: BAR) - * Driver should recognize it by frame type, that is found - * in Rx descriptor. If type is not data, it is 802.11 frame as is - */ - ftype = wil_rxdesc_ftype(d) << 2; - if (ftype != IEEE80211_FTYPE_DATA) { - wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); - /* TODO: process it */ - kfree_skb(skb); - return NULL; - } - - if (skb->len < ETH_HLEN) { - wil_err(wil, "Short frame, len = %d\n", skb->len); - /* TODO: process it (i.e. BAR) */ - kfree_skb(skb); - return NULL; - } - - ds_bits = wil_rxdesc_ds_bits(d); - if (ds_bits == 1) { - /* - * HW bug - in ToDS mode, i.e. Rx on AP side, - * addresses get swapped - */ - wil_swap_ethaddr(skb->data); - } - - return skb; -} - -/** - * allocate and fill up to @count buffers in rx ring - * buffers posted at @swtail - */ -static int wil_rx_refill(struct wil6210_priv *wil, int count) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct vring *v = &wil->vring_rx; - u32 next_tail; - int rc = 0; - int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? - WIL6210_RTAP_SIZE : 0; - - for (; next_tail = wil_vring_next_tail(v), - (next_tail != v->swhead) && (count-- > 0); - v->swtail = next_tail) { - rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); - if (rc) { - wil_err(wil, "Error %d in wil_rx_refill[%d]\n", - rc, v->swtail); - break; - } - } - iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); - - return rc; -} - -/* - * Pass Rx packet to the netif. Update statistics. - */ -static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) -{ - int rc; - unsigned int len = skb->len; - - if (in_interrupt()) - rc = netif_rx(skb); - else - rc = netif_rx_ni(skb); - - if (likely(rc == NET_RX_SUCCESS)) { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += len; - - } else { - ndev->stats.rx_dropped++; - } -} - -/** - * Proceed all completed skb's from Rx VRING - * - * Safe to call from IRQ - */ -void wil_rx_handle(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct vring *v = &wil->vring_rx; - struct sk_buff *skb; - - if (!v->va) { - wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); - return; - } - wil_dbg_TXRX(wil, "%s()\n", __func__); - while (NULL != (skb = wil_vring_reap_rx(wil, v))) { - wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, - skb->data, skb_headlen(skb), false); - - skb_orphan(skb); - - if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { - skb->dev = ndev; - skb_reset_mac_header(skb); - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_802_2); - - } else { - skb->protocol = eth_type_trans(skb, ndev); - } - - wil_netif_rx_any(skb, ndev); - } - wil_rx_refill(wil, v->size); -} - -int wil_rx_init(struct wil6210_priv *wil) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; - struct vring *vring = &wil->vring_rx; - int rc; - struct wmi_cfg_rx_chain_cmd cmd = { - .action = WMI_RX_CHAIN_ADD, - .rx_sw_ring = { - .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), - }, - .mid = 0, /* TODO - what is it? */ - .decap_trans_type = WMI_DECAP_TYPE_802_3, - }; - struct { - struct wil6210_mbox_hdr_wmi wmi; - struct wmi_cfg_rx_chain_done_event evt; - } __packed evt; - - vring->size = WIL6210_RX_RING_SIZE; - rc = wil_vring_alloc(wil, vring); - if (rc) - return rc; - - cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); - cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); - if (wdev->iftype == NL80211_IFTYPE_MONITOR) { - struct ieee80211_channel *ch = wdev->preset_chandef.chan; - - cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); - if (ch) - cmd.sniffer_cfg.channel = ch->hw_value - 1; - cmd.sniffer_cfg.phy_info_mode = - cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); - cmd.sniffer_cfg.phy_support = - cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) - ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); - } - /* typical time for secure PCP is 840ms */ - rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), - WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); - if (rc) - goto err_free; - - vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); - - wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", - le32_to_cpu(evt.evt.status), vring->hwtail); - - rc = wil_rx_refill(wil, vring->size); - if (rc) - goto err_free; - - return 0; - err_free: - wil_vring_free(wil, vring, 0); - - return rc; -} - -void wil_rx_fini(struct wil6210_priv *wil) -{ - struct vring *vring = &wil->vring_rx; - - if (vring->va) { - int rc; - struct wmi_cfg_rx_chain_cmd cmd = { - .action = cpu_to_le32(WMI_RX_CHAIN_DEL), - .rx_sw_ring = { - .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), - }, - }; - struct { - struct wil6210_mbox_hdr_wmi wmi; - struct wmi_cfg_rx_chain_done_event cfg; - } __packed wmi_rx_cfg_reply; - - rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), - WMI_CFG_RX_CHAIN_DONE_EVENTID, - &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), - 100); - wil_vring_free(wil, vring, 0); - } -} - -int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, - int cid, int tid) -{ - int rc; - struct wmi_vring_cfg_cmd cmd = { - .action = cpu_to_le32(WMI_VRING_CMD_ADD), - .vring_cfg = { - .tx_sw_ring = { - .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), - }, - .ringid = id, - .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), - .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, - .mac_ctrl = 0, - .to_resolution = 0, - .agg_max_wsize = 16, - .schd_params = { - .priority = cpu_to_le16(0), - .timeslot_us = cpu_to_le16(0xfff), - }, - }, - }; - struct { - struct wil6210_mbox_hdr_wmi wmi; - struct wmi_vring_cfg_done_event cmd; - } __packed reply; - struct vring *vring = &wil->vring_tx[id]; - - if (vring->va) { - wil_err(wil, "Tx ring [%d] already allocated\n", id); - rc = -EINVAL; - goto out; - } - - vring->size = size; - rc = wil_vring_alloc(wil, vring); - if (rc) - goto out; - - cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); - cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); - - rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), - WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); - if (rc) - goto out_free; - - if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { - wil_err(wil, "Tx config failed, status 0x%02x\n", - reply.cmd.status); - goto out_free; - } - vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); - - return 0; - out_free: - wil_vring_free(wil, vring, 1); - out: - - return rc; -} - -void wil_vring_fini_tx(struct wil6210_priv *wil, int id) -{ - struct vring *vring = &wil->vring_tx[id]; - - if (!vring->va) - return; - - wil_vring_free(wil, vring, 1); -} - -static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, - struct sk_buff *skb) -{ - struct vring *v = &wil->vring_tx[0]; - - if (v->va) - return v; - - return NULL; -} - -static int wil_tx_desc_map(volatile struct vring_tx_desc *d, - dma_addr_t pa, u32 len) -{ - d->dma.addr_low = lower_32_bits(pa); - d->dma.addr_high = (u16)upper_32_bits(pa); - d->dma.ip_length = 0; - /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ - d->dma.b11 = 0/*14 | BIT(7)*/; - d->dma.error = 0; - d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ - d->dma.length = len; - d->dma.d0 = 0; - d->mac.d[0] = 0; - d->mac.d[1] = 0; - d->mac.d[2] = 0; - d->mac.ucode_cmd = 0; - /* use dst index 0 */ - d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | - (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); - /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ - d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | - (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); - - return 0; -} - -static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, - struct sk_buff *skb) -{ - struct device *dev = wil_to_dev(wil); - volatile struct vring_tx_desc *d; - u32 swhead = vring->swhead; - int avail = wil_vring_avail_tx(vring); - int nr_frags = skb_shinfo(skb)->nr_frags; - uint f; - int vring_index = vring - wil->vring_tx; - uint i = swhead; - dma_addr_t pa; - - wil_dbg_TXRX(wil, "%s()\n", __func__); - - if (avail < vring->size/8) - netif_tx_stop_all_queues(wil_to_ndev(wil)); - if (avail < 1 + nr_frags) { - wil_err(wil, "Tx ring full. No space for %d fragments\n", - 1 + nr_frags); - return -ENOMEM; - } - d = &(vring->va[i].tx); - - /* FIXME FW can accept only unicast frames for the peer */ - memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); - - pa = dma_map_single(dev, skb->data, - skb_headlen(skb), DMA_TO_DEVICE); - - wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), - skb->data, (unsigned long long)pa); - wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, - skb->data, skb_headlen(skb), false); - - if (unlikely(dma_mapping_error(dev, pa))) - return -EINVAL; - /* 1-st segment */ - wil_tx_desc_map(d, pa, skb_headlen(skb)); - d->mac.d[2] |= ((nr_frags + 1) << - MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); - /* middle segments */ - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[f]; - int len = skb_frag_size(frag); - i = (swhead + f + 1) % vring->size; - d = &(vring->va[i].tx); - pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), - DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(dev, pa))) - goto dma_error; - wil_tx_desc_map(d, pa, len); - vring->ctx[i] = NULL; - } - /* for the last seg only */ - d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); - d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ - d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); - d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); - - wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, - (const void *)d, sizeof(*d), false); - - /* advance swhead */ - wil_vring_advance_head(vring, nr_frags + 1); - wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); - iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); - /* hold reference to skb - * to prevent skb release before accounting - * in case of immediate "tx done" - */ - vring->ctx[i] = skb_get(skb); - - return 0; - dma_error: - /* unmap what we have mapped */ - /* Note: increment @f to operate with positive index */ - for (f++; f > 0; f--) { - i = (swhead + f) % vring->size; - d = &(vring->va[i].tx); - d->dma.status = TX_DMA_STATUS_DU; - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); - if (vring->ctx[i]) - dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); - else - dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); - } - - return -EINVAL; -} - - -netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) -{ - struct wil6210_priv *wil = ndev_to_wil(ndev); - struct vring *vring; - int rc; - - wil_dbg_TXRX(wil, "%s()\n", __func__); - if (!test_bit(wil_status_fwready, &wil->status)) { - wil_err(wil, "FW not ready\n"); - goto drop; - } - if (!test_bit(wil_status_fwconnected, &wil->status)) { - wil_err(wil, "FW not connected\n"); - goto drop; - } - if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { - wil_err(wil, "Xmit in monitor mode not supported\n"); - goto drop; - } - if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { - rc = wmi_tx_eapol(wil, skb); - } else { - /* find vring */ - vring = wil_find_tx_vring(wil, skb); - if (!vring) { - wil_err(wil, "No Tx VRING available\n"); - goto drop; - } - /* set up vring entry */ - rc = wil_tx_vring(wil, vring, skb); - } - switch (rc) { - case 0: - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - case -ENOMEM: - return NETDEV_TX_BUSY; - default: - ; /* goto drop; */ - break; - } - drop: - netif_tx_stop_all_queues(ndev); - ndev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - - return NET_XMIT_DROP; -} - -/** - * Clean up transmitted skb's from the Tx VRING - * - * Safe to call from IRQ - */ -void wil_tx_complete(struct wil6210_priv *wil, int ringid) -{ - struct device *dev = wil_to_dev(wil); - struct vring *vring = &wil->vring_tx[ringid]; - - if (!vring->va) { - wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); - return; - } - - wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); - - while (!wil_vring_is_empty(vring)) { - volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; - dma_addr_t pa; - struct sk_buff *skb; - if (!(d->dma.status & TX_DMA_STATUS_DU)) - break; - - wil_dbg_TXRX(wil, - "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", - vring->swtail, d->dma.length, d->dma.status, - d->dma.error); - wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, - (const void *)d, sizeof(*d), false); - - pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); - skb = vring->ctx[vring->swtail]; - if (skb) { - dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - vring->ctx[vring->swtail] = NULL; - } else { - dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); - } - d->dma.addr_low = 0; - d->dma.addr_high = 0; - d->dma.length = 0; - d->dma.status = TX_DMA_STATUS_DU; - vring->swtail = wil_vring_next_tail(vring); - } - if (wil_vring_avail_tx(vring) > vring->size/4) - netif_tx_wake_all_queues(wil_to_ndev(wil)); -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/txrx.h b/trunk/drivers/net/wireless/ath/wil6210/txrx.h deleted file mode 100644 index 45a61f597c5c..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/txrx.h +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 WIL6210_TXRX_H -#define WIL6210_TXRX_H - -#define BUF_SW_OWNED (1) -#define BUF_HW_OWNED (0) - -/* size of max. Rx packet */ -#define RX_BUF_LEN (2048) -#define TX_BUF_LEN (2048) -/* how many bytes to reserve for rtap header? */ -#define WIL6210_RTAP_SIZE (128) - -/* Tx/Rx path */ -/* - * Tx descriptor - MAC part - * [dword 0] - * bit 0.. 9 : lifetime_expiry_value:10 - * bit 10 : interrup_en:1 - * bit 11 : status_en:1 - * bit 12..13 : txss_override:2 - * bit 14 : timestamp_insertion:1 - * bit 15 : duration_preserve:1 - * bit 16..21 : reserved0:6 - * bit 22..26 : mcs_index:5 - * bit 27 : mcs_en:1 - * bit 28..29 : reserved1:2 - * bit 30 : reserved2:1 - * bit 31 : sn_preserved:1 - * [dword 1] - * bit 0.. 3 : pkt_mode:4 - * bit 4 : pkt_mode_en:1 - * bit 5.. 7 : reserved0:3 - * bit 8..13 : reserved1:6 - * bit 14 : reserved2:1 - * bit 15 : ack_policy_en:1 - * bit 16..19 : dst_index:4 - * bit 20 : dst_index_en:1 - * bit 21..22 : ack_policy:2 - * bit 23 : lifetime_en:1 - * bit 24..30 : max_retry:7 - * bit 31 : max_retry_en:1 - * [dword 2] - * bit 0.. 7 : num_of_descriptors:8 - * bit 8..17 : reserved:10 - * bit 18..19 : l2_translation_type:2 - * bit 20 : snap_hdr_insertion_en:1 - * bit 21 : vlan_removal_en:1 - * bit 22..31 : reserved0:10 - * [dword 3] - * bit 0.. 31: ucode_cmd:32 - */ -struct vring_tx_mac { - u32 d[3]; - u32 ucode_cmd; -} __packed; - -/* TX MAC Dword 0 */ -#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 -#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 -#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF - -#define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 -#define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 -#define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 - -#define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 -#define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 -#define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 - -#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 -#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 -#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 - -#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 -#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 -#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 - -#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 -#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 -#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 - -#define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 -#define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 -#define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 - -#define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 -#define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 -#define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 - -#define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 -#define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 -#define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 - -/* TX MAC Dword 1 */ -#define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 -#define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 -#define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF - -#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 -#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 -#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 - -#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 -#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 -#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 - -#define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 -#define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 -#define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 - -#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 -#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 -#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 - -#define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 -#define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 -#define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 - -#define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 -#define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 -#define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 - -#define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 -#define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 -#define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 - -#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 -#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 -#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 - -/* TX MAC Dword 2 */ -#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 -#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 -#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF - -#define MAC_CFG_DESC_TX_2_RESERVED_POS 8 -#define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 -#define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 - -#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 -#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 -#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 - -#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 -#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 -#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 - -#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 -#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 -#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 - -/* TX MAC Dword 3 */ -#define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 -#define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 -#define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF - -/* TX DMA Dword 0 */ -#define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 -#define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 -#define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF - -#define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 -#define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 -#define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 - -#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 -#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 -#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 - -#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 -#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 -#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 - -#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 -#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 -#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 - -#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 -#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 -#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 - -#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 -#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 -#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 - -#define DMA_CFG_DESC_TX_0_QID_POS 16 -#define DMA_CFG_DESC_TX_0_QID_LEN 5 -#define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 - -#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 -#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 -#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 - -#define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 -#define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 -#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 - - -#define TX_DMA_STATUS_DU BIT(0) - -struct vring_tx_dma { - u32 d0; - u32 addr_low; - u16 addr_high; - u8 ip_length; - u8 b11; /* 0..6: mac_length; 7:ip_version */ - u8 error; /* 0..2: err; 3..7: reserved; */ - u8 status; /* 0: used; 1..7; reserved */ - u16 length; -} __packed; - -/* - * Rx descriptor - MAC part - * [dword 0] - * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field - * bit 4.. 6 : connection_id:3 :The Source index that was found during - * Parsing the TA. This field is used to define the source of the packet - * bit 7 : reserved:1 - * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) - * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type - * (management, data, control and extension) - * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype - * bit 16..27 : seq_number:12 The received Sequence number field - * bit 28..31 : extended:4 extended subtype - * [dword 1] - * bit 0.. 3 : reserved - * bit 4.. 5 : key_id:2 - * bit 6 : decrypt_bypass:1 - * bit 7 : security:1 - * bit 8.. 9 : ds_bits:2 - * bit 10 : a_msdu_present:1 from qos header - * bit 11 : a_msdu_type:1 from qos header - * bit 12 : a_mpdu:1 part of AMPDU aggregation - * bit 13 : broadcast:1 - * bit 14 : mutlicast:1 - * bit 15 : reserved:1 - * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet - * is received from - * bit 21..24 : mcs:4 - * bit 25..28 : mic_icr:4 - * bit 29..31 : reserved:3 - * [dword 2] - * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received - * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version - * bit 4 : fc_order:1 The FC Control (b15) -Order - * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field - * bit 8 : esop:1 The QoS (b4) ESOP field - * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field - * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field - * bit 15 : qos_ac_constraint:1 - * bit 16..31 : pn_15_0:16 low 2 bytes of PN - * [dword 3] - * bit 0..31 : pn_47_16:32 high 4 bytes of PN - */ -struct vring_rx_mac { - u32 d0; - u32 d1; - u16 w4; - u16 pn_15_0; - u32 pn_47_16; -} __packed; - -/* - * Rx descriptor - DMA part - * [dword 0] - * bit 0.. 7 : l4_length:8 layer 4 length - * bit 8.. 9 : reserved:2 - * bit 10 : cmd_dma_it:1 - * bit 11..15 : reserved:5 - * bit 16..29 : phy_info_length:14 - * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field - * [dword 1] - * bit 0..31 : addr_low:32 The payload buffer low address - * [dword 2] - * bit 0..15 : addr_high:16 The payload buffer high address - * bit 16..23 : ip_length:8 - * bit 24..30 : mac_length:7 - * bit 31 : ip_version:1 - * [dword 3] - * [byte 12] error - * [byte 13] status - * bit 0 : du:1 - * bit 1 : eop:1 - * bit 2 : error:1 - * bit 3 : mi:1 - * bit 4 : l3_identified:1 - * bit 5 : l4_identified:1 - * bit 6 : phy_info_included:1 - * bit 7 : reserved:1 - * [word 7] length - * - */ - -#define RX_DMA_D0_CMD_DMA_IT BIT(10) - -#define RX_DMA_STATUS_DU BIT(0) -#define RX_DMA_STATUS_ERROR BIT(2) -#define RX_DMA_STATUS_PHY_INFO BIT(6) - -struct vring_rx_dma { - u32 d0; - u32 addr_low; - u16 addr_high; - u8 ip_length; - u8 b11; - u8 error; - u8 status; - u16 length; -} __packed; - -struct vring_tx_desc { - struct vring_tx_mac mac; - struct vring_tx_dma dma; -} __packed; - -struct vring_rx_desc { - struct vring_rx_mac mac; - struct vring_rx_dma dma; -} __packed; - -union vring_desc { - struct vring_tx_desc tx; - struct vring_rx_desc rx; -} __packed; - -static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) -{ - return WIL_GET_BITS(d->dma.d0, 16, 29); -} - -static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) -{ - return WIL_GET_BITS(d->mac.d1, 21, 24); -} - -static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) -{ - return WIL_GET_BITS(d->mac.d1, 8, 9); -} - -static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) -{ - return WIL_GET_BITS(d->mac.d0, 10, 11); -} - -#endif /* WIL6210_TXRX_H */ diff --git a/trunk/drivers/net/wireless/ath/wil6210/wil6210.h b/trunk/drivers/net/wireless/ath/wil6210/wil6210.h deleted file mode 100644 index 9bcfffa4006c..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/wil6210.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 __WIL6210_H__ -#define __WIL6210_H__ - -#include -#include -#include - -#include "dbg_hexdump.h" - -#define WIL_NAME "wil6210" - -/** - * extract bits [@b0:@b1] (inclusive) from the value @x - * it should be @b0 <= @b1, or result is incorrect - */ -static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) -{ - return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); -} - -#define WIL6210_MEM_SIZE (2*1024*1024UL) - -#define WIL6210_TX_QUEUES (4) - -#define WIL6210_RX_RING_SIZE (128) -#define WIL6210_TX_RING_SIZE (128) -#define WIL6210_MAX_TX_RINGS (24) - -/* Hardware definitions begin */ - -/* - * Mapping - * RGF File | Host addr | FW addr - * | | - * user_rgf | 0x000000 | 0x880000 - * dma_rgf | 0x001000 | 0x881000 - * pcie_rgf | 0x002000 | 0x882000 - * | | - */ - -/* Where various structures placed in host address space */ -#define WIL6210_FW_HOST_OFF (0x880000UL) - -#define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) - -/* - * Interrupt control registers block - * - * each interrupt controlled by the same bit in all registers - */ -struct RGF_ICR { - u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ - u32 ICR; /* Cause, W1C/COR depending on ICC */ - u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ - u32 ICS; /* Cause Set, WO */ - u32 IMV; /* Mask, RW+S/C */ - u32 IMS; /* Mask Set, write 1 to set */ - u32 IMC; /* Mask Clear, write 1 to clear */ -} __packed; - -/* registers - FW addresses */ -#define RGF_USER_USER_SCRATCH_PAD (0x8802bc) -#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ - #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) -#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) -#define RGF_USER_MAC_CPU_0 (0x8801fc) -#define RGF_USER_USER_CPU_0 (0x8801e0) -#define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) -#define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) -#define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) -#define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) - -#define RGF_DMA_PSEUDO_CAUSE (0x881c68) -#define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) -#define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) - #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) - #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) - #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) - -#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ - #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) - #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ -#define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ - #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) -#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ - #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) - #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) - #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) - #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) - -/* Interrupt moderation control */ -#define RGF_DMA_ITR_CNT_TRSH (0x881c5c) -#define RGF_DMA_ITR_CNT_DATA (0x881c60) -#define RGF_DMA_ITR_CNT_CRL (0x881C64) - #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) - #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) - #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) - #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) - #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) - -/* popular locations */ -#define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) -#define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ - offsetof(struct RGF_ICR, ICS)) -#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 - -/* ISR register bits */ -#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 -#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 - -/* Hardware definitions end */ - -struct wil6210_mbox_ring { - u32 base; - u16 entry_size; /* max. size of mbox entry, incl. all headers */ - u16 size; - u32 tail; - u32 head; -} __packed; - -struct wil6210_mbox_ring_desc { - __le32 sync; - __le32 addr; -} __packed; - -/* at HOST_OFF_WIL6210_MBOX_CTL */ -struct wil6210_mbox_ctl { - struct wil6210_mbox_ring tx; - struct wil6210_mbox_ring rx; -} __packed; - -struct wil6210_mbox_hdr { - __le16 seq; - __le16 len; /* payload, bytes after this header */ - __le16 type; - u8 flags; - u8 reserved; -} __packed; - -#define WIL_MBOX_HDR_TYPE_WMI (0) - -/* max. value for wil6210_mbox_hdr.len */ -#define MAX_MBOXITEM_SIZE (240) - -struct wil6210_mbox_hdr_wmi { - u8 reserved0[2]; - __le16 id; - __le16 info1; /* bits [0..3] - device_id, rest - unused */ - u8 reserved1[2]; -} __packed; - -struct pending_wmi_event { - struct list_head list; - struct { - struct wil6210_mbox_hdr hdr; - struct wil6210_mbox_hdr_wmi wmi; - u8 data[0]; - } __packed event; -}; - -union vring_desc; - -struct vring { - dma_addr_t pa; - volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ - u16 size; /* number of vring_desc elements */ - u32 swtail; - u32 swhead; - u32 hwtail; /* write here to inform hw */ - void **ctx; /* void *ctx[size] - software context */ -}; - -enum { /* for wil6210_priv.status */ - wil_status_fwready = 0, - wil_status_fwconnected, - wil_status_dontscan, - wil_status_irqen, /* FIXME: interrupts enabled - for debug */ -}; - -struct pci_dev; - -struct wil6210_stats { - u64 tsf; - u32 snr; - u16 last_mcs_rx; - u16 bf_mcs; /* last BF, used for Tx */ - u16 my_rx_sector; - u16 my_tx_sector; - u16 peer_rx_sector; - u16 peer_tx_sector; -}; - -struct wil6210_priv { - struct pci_dev *pdev; - int n_msi; - struct wireless_dev *wdev; - void __iomem *csr; - ulong status; - /* profile */ - u32 monitor_flags; - u32 secure_pcp; /* create secure PCP? */ - int sinfo_gen; - /* cached ISR registers */ - u32 isr_misc; - /* mailbox related */ - struct mutex wmi_mutex; - struct wil6210_mbox_ctl mbox_ctl; - struct completion wmi_ready; - u16 wmi_seq; - u16 reply_id; /**< wait for this WMI event */ - void *reply_buf; - u16 reply_size; - struct workqueue_struct *wmi_wq; /* for deferred calls */ - struct work_struct wmi_event_worker; - struct workqueue_struct *wmi_wq_conn; /* for connect worker */ - struct work_struct wmi_connect_worker; - struct work_struct disconnect_worker; - struct timer_list connect_timer; - int pending_connect_cid; - struct list_head pending_wmi_ev; - /* - * protect pending_wmi_ev - * - fill in IRQ from wil6210_irq_misc, - * - consumed in thread by wmi_event_worker - */ - spinlock_t wmi_ev_lock; - /* DMA related */ - struct vring vring_rx; - struct vring vring_tx[WIL6210_MAX_TX_RINGS]; - u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; - /* scan */ - struct cfg80211_scan_request *scan_request; - - struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ - /* statistics */ - struct wil6210_stats stats; - /* debugfs */ - struct dentry *debug; - struct debugfs_blob_wrapper fw_code_blob; - struct debugfs_blob_wrapper fw_data_blob; - struct debugfs_blob_wrapper fw_peri_blob; - struct debugfs_blob_wrapper uc_code_blob; - struct debugfs_blob_wrapper uc_data_blob; - struct debugfs_blob_wrapper rgf_blob; -}; - -#define wil_to_wiphy(i) (i->wdev->wiphy) -#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) -#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) -#define wil_to_wdev(i) (i->wdev) -#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) -#define wil_to_ndev(i) (wil_to_wdev(i)->netdev) -#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) - -#define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) -#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) -#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) - -#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) -#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) -#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) - -#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) \ - wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ - prefix_type, rowsize, \ - groupsize, buf, len, ascii) - -#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ - groupsize, buf, len, ascii) \ - wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ - prefix_type, rowsize, \ - groupsize, buf, len, ascii) - -void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, - size_t count); -void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, - size_t count); - -void *wil_if_alloc(struct device *dev, void __iomem *csr); -void wil_if_free(struct wil6210_priv *wil); -int wil_if_add(struct wil6210_priv *wil); -void wil_if_remove(struct wil6210_priv *wil); -int wil_priv_init(struct wil6210_priv *wil); -void wil_priv_deinit(struct wil6210_priv *wil); -int wil_reset(struct wil6210_priv *wil); -void wil_link_on(struct wil6210_priv *wil); -void wil_link_off(struct wil6210_priv *wil); -int wil_up(struct wil6210_priv *wil); -int wil_down(struct wil6210_priv *wil); -void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); - -void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); -void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); -int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, - struct wil6210_mbox_hdr *hdr); -int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); -void wmi_recv_cmd(struct wil6210_priv *wil); -int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec); -void wmi_connect_worker(struct work_struct *work); -void wmi_event_worker(struct work_struct *work); -void wmi_event_flush(struct wil6210_priv *wil); -int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); -int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); -int wmi_set_channel(struct wil6210_priv *wil, int channel); -int wmi_get_channel(struct wil6210_priv *wil, int *channel); -int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); -int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, - const void *mac_addr); -int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, - const void *mac_addr, int key_len, const void *key); -int wmi_echo(struct wil6210_priv *wil); -int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); - -int wil6210_init_irq(struct wil6210_priv *wil, int irq); -void wil6210_fini_irq(struct wil6210_priv *wil, int irq); -void wil6210_disable_irq(struct wil6210_priv *wil); -void wil6210_enable_irq(struct wil6210_priv *wil); - -int wil6210_debugfs_init(struct wil6210_priv *wil); -void wil6210_debugfs_remove(struct wil6210_priv *wil); - -struct wireless_dev *wil_cfg80211_init(struct device *dev); -void wil_wdev_free(struct wil6210_priv *wil); - -int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); -int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); -void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); - -int wil_rx_init(struct wil6210_priv *wil); -void wil_rx_fini(struct wil6210_priv *wil); - -/* TX API */ -int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, - int cid, int tid); -void wil_vring_fini_tx(struct wil6210_priv *wil, int id); - -netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); -void wil_tx_complete(struct wil6210_priv *wil, int ringid); - -/* RX API */ -void wil_rx_handle(struct wil6210_priv *wil); - -int wil_iftype_nl2wmi(enum nl80211_iftype type); - -#endif /* __WIL6210_H__ */ diff --git a/trunk/drivers/net/wireless/ath/wil6210/wmi.c b/trunk/drivers/net/wireless/ath/wil6210/wmi.c deleted file mode 100644 index 12915f6e7617..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/wmi.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * - * 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 "wil6210.h" -#include "wmi.h" - -/** - * WMI event receiving - theory of operations - * - * When firmware about to report WMI event, it fills memory area - * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for - * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. - * - * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the - * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up - * and handles events within the @wmi_event_worker. Every event get detached - * from list, processed and deleted. - * - * Purpose for this mechanism is to release IRQ thread; otherwise, - * if WMI event handling involves another WMI command flow, this 2-nd flow - * won't be completed because of blocked IRQ thread. - */ - -/** - * Addressing - theory of operations - * - * There are several buses present on the WIL6210 card. - * Same memory areas are visible at different address on - * the different busses. There are 3 main bus masters: - * - MAC CPU (ucode) - * - User CPU (firmware) - * - AHB (host) - * - * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing - * AHB addresses starting from 0x880000 - * - * Internally, firmware uses addresses that allows faster access but - * are invisible from the host. To read from these addresses, alternative - * AHB address must be used. - * - * Memory mapping - * Linker address PCI/Host address - * 0x880000 .. 0xa80000 2Mb BAR0 - * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM - * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH - */ - -/** - * @fw_mapping provides memory remapping table - */ -static const struct { - u32 from; /* linker address - from, inclusive */ - u32 to; /* linker address - to, exclusive */ - u32 host; /* PCI/Host address - BAR0 + 0x880000 */ -} fw_mapping[] = { - {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ - {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ - {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ - {0x880000, 0x88a000, 0x880000}, /* various RGF */ - {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ - /* - * 920000..930000 ucode code RAM - * 930000..932000 ucode data RAM - */ -}; - -/** - * return AHB address for given firmware/ucode internal (linker) address - * @x - internal address - * If address have no valid AHB mapping, return 0 - */ -static u32 wmi_addr_remap(u32 x) -{ - uint i; - - for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { - if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) - return x + fw_mapping[i].host - fw_mapping[i].from; - } - - return 0; -} - -/** - * Check address validity for WMI buffer; remap if needed - * @ptr - internal (linker) fw/ucode address - * - * Valid buffer should be DWORD aligned - * - * return address for accessing buffer from the host; - * if buffer is not valid, return NULL. - */ -void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) -{ - u32 off; - u32 ptr = le32_to_cpu(ptr_); - - if (ptr % 4) - return NULL; - - ptr = wmi_addr_remap(ptr); - if (ptr < WIL6210_FW_HOST_OFF) - return NULL; - - off = HOSTADDR(ptr); - if (off > WIL6210_MEM_SIZE - 4) - return NULL; - - return wil->csr + off; -} - -/** - * Check address validity - */ -void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) -{ - u32 off; - - if (ptr % 4) - return NULL; - - if (ptr < WIL6210_FW_HOST_OFF) - return NULL; - - off = HOSTADDR(ptr); - if (off > WIL6210_MEM_SIZE - 4) - return NULL; - - return wil->csr + off; -} - -int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, - struct wil6210_mbox_hdr *hdr) -{ - void __iomem *src = wmi_buffer(wil, ptr); - if (!src) - return -EINVAL; - - wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); - - return 0; -} - -static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) -{ - struct { - struct wil6210_mbox_hdr hdr; - struct wil6210_mbox_hdr_wmi wmi; - } __packed cmd = { - .hdr = { - .type = WIL_MBOX_HDR_TYPE_WMI, - .flags = 0, - .len = cpu_to_le16(sizeof(cmd.wmi) + len), - }, - .wmi = { - .id = cpu_to_le16(cmdid), - .info1 = 0, - }, - }; - struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; - struct wil6210_mbox_ring_desc d_head; - u32 next_head; - void __iomem *dst; - void __iomem *head = wmi_addr(wil, r->head); - uint retry; - - if (sizeof(cmd) + len > r->entry_size) { - wil_err(wil, "WMI size too large: %d bytes, max is %d\n", - (int)(sizeof(cmd) + len), r->entry_size); - return -ERANGE; - - } - - might_sleep(); - - if (!test_bit(wil_status_fwready, &wil->status)) { - wil_err(wil, "FW not ready\n"); - return -EAGAIN; - } - - if (!head) { - wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); - return -EINVAL; - } - /* read Tx head till it is not busy */ - for (retry = 5; retry > 0; retry--) { - wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); - if (d_head.sync == 0) - break; - msleep(20); - } - if (d_head.sync != 0) { - wil_err(wil, "WMI head busy\n"); - return -EBUSY; - } - /* next head */ - next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); - wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); - /* wait till FW finish with previous command */ - for (retry = 5; retry > 0; retry--) { - r->tail = ioread32(wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, tx.tail)); - if (next_head != r->tail) - break; - msleep(20); - } - if (next_head == r->tail) { - wil_err(wil, "WMI ring full\n"); - return -EBUSY; - } - dst = wmi_buffer(wil, d_head.addr); - if (!dst) { - wil_err(wil, "invalid WMI buffer: 0x%08x\n", - le32_to_cpu(d_head.addr)); - return -EINVAL; - } - cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); - /* set command */ - wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); - wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, - sizeof(cmd), true); - wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, - len, true); - wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); - wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); - /* mark entry as full */ - iowrite32(1, wil->csr + HOSTADDR(r->head) + - offsetof(struct wil6210_mbox_ring_desc, sync)); - /* advance next ptr */ - iowrite32(r->head = next_head, wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, tx.head)); - - /* interrupt to FW */ - iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); - - return 0; -} - -int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) -{ - int rc; - - mutex_lock(&wil->wmi_mutex); - rc = __wmi_send(wil, cmdid, buf, len); - mutex_unlock(&wil->wmi_mutex); - - return rc; -} - -/*=== Event handlers ===*/ -static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; - struct wmi_ready_event *evt = d; - u32 ver = le32_to_cpu(evt->sw_version); - - wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); - - if (!is_valid_ether_addr(ndev->dev_addr)) { - memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); - memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); - } - snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), - "%d", ver); -} - -static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, - int len) -{ - wil_dbg_WMI(wil, "WMI: FW ready\n"); - - set_bit(wil_status_fwready, &wil->status); - /* reuse wmi_ready for the firmware ready indication */ - complete(&wil->wmi_ready); -} - -static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) -{ - struct wmi_rx_mgmt_packet_event *data = d; - struct wiphy *wiphy = wil_to_wiphy(wil); - struct ieee80211_mgmt *rx_mgmt_frame = - (struct ieee80211_mgmt *)data->payload; - int ch_no = data->info.channel+1; - u32 freq = ieee80211_channel_to_frequency(ch_no, - IEEE80211_BAND_60GHZ); - struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); - /* TODO convert LE to CPU */ - s32 signal = 0; /* TODO */ - __le16 fc = rx_mgmt_frame->frame_control; - u32 d_len = le32_to_cpu(data->info.len); - u16 d_status = le16_to_cpu(data->info.status); - - wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", - data->info.channel, data->info.mcs, data->info.snr); - wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, - le16_to_cpu(data->info.stype)); - wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", - data->info.qid, data->info.mid, data->info.cid); - - if (!channel) { - wil_err(wil, "Frame on unsupported channel\n"); - return; - } - - if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { - struct cfg80211_bss *bss; - u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); - u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); - u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); - const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; - size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, - u.beacon.variable); - wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); - - bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, - tsf, cap, bi, ie_buf, ie_len, - signal, GFP_KERNEL); - if (bss) { - wil_dbg_WMI(wil, "Added BSS %pM\n", - rx_mgmt_frame->bssid); - cfg80211_put_bss(bss); - } else { - wil_err(wil, "cfg80211_inform_bss() failed\n"); - } - } -} - -static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, - void *d, int len) -{ - if (wil->scan_request) { - struct wmi_scan_complete_event *data = d; - bool aborted = (data->status != 0); - - wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); - cfg80211_scan_done(wil->scan_request, aborted); - wil->scan_request = NULL; - } else { - wil_err(wil, "SCAN_COMPLETE while not scanning\n"); - } -} - -static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct wireless_dev *wdev = wil->wdev; - struct wmi_connect_event *evt = d; - int ch; /* channel number */ - struct station_info sinfo; - u8 *assoc_req_ie, *assoc_resp_ie; - size_t assoc_req_ielen, assoc_resp_ielen; - /* capinfo(u16) + listen_interval(u16) + IEs */ - const size_t assoc_req_ie_offset = sizeof(u16) * 2; - /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ - const size_t assoc_resp_ie_offset = sizeof(u16) * 3; - - if (len < sizeof(*evt)) { - wil_err(wil, "Connect event too short : %d bytes\n", len); - return; - } - if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + - evt->assoc_resp_len) { - wil_err(wil, - "Connect event corrupted : %d != %d + %d + %d + %d\n", - len, (int)sizeof(*evt), evt->beacon_ie_len, - evt->assoc_req_len, evt->assoc_resp_len); - return; - } - ch = evt->channel + 1; - wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", - evt->bssid, ch, evt->cid); - wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, - evt->assoc_info, len - sizeof(*evt), true); - - /* figure out IE's */ - assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + - assoc_req_ie_offset]; - assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; - if (evt->assoc_req_len <= assoc_req_ie_offset) { - assoc_req_ie = NULL; - assoc_req_ielen = 0; - } - - assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + - evt->assoc_req_len + - assoc_resp_ie_offset]; - assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; - if (evt->assoc_resp_len <= assoc_resp_ie_offset) { - assoc_resp_ie = NULL; - assoc_resp_ielen = 0; - } - - if ((wdev->iftype == NL80211_IFTYPE_STATION) || - (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { - if (wdev->sme_state != CFG80211_SME_CONNECTING) { - wil_err(wil, "Not in connecting state\n"); - return; - } - del_timer_sync(&wil->connect_timer); - cfg80211_connect_result(ndev, evt->bssid, - assoc_req_ie, assoc_req_ielen, - assoc_resp_ie, assoc_resp_ielen, - WLAN_STATUS_SUCCESS, GFP_KERNEL); - - } else if ((wdev->iftype == NL80211_IFTYPE_AP) || - (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { - memset(&sinfo, 0, sizeof(sinfo)); - - sinfo.generation = wil->sinfo_gen++; - - if (assoc_req_ie) { - sinfo.assoc_req_ies = assoc_req_ie; - sinfo.assoc_req_ies_len = assoc_req_ielen; - sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; - } - - cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); - } - set_bit(wil_status_fwconnected, &wil->status); - - /* FIXME FW can transmit only ucast frames to peer */ - /* FIXME real ring_id instead of hard coded 0 */ - memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); - - wil->pending_connect_cid = evt->cid; - queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); -} - -static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, - void *d, int len) -{ - struct wmi_disconnect_event *evt = d; - - wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", - evt->bssid, - evt->protocol_reason_status, evt->disconnect_reason); - - wil->sinfo_gen++; - - wil6210_disconnect(wil, evt->bssid); - clear_bit(wil_status_dontscan, &wil->status); -} - -static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) -{ - struct wmi_notify_req_done_event *evt = d; - - if (len < sizeof(*evt)) { - wil_err(wil, "Short NOTIFY event\n"); - return; - } - - wil->stats.tsf = le64_to_cpu(evt->tsf); - wil->stats.snr = le32_to_cpu(evt->snr_val); - wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); - wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); - wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); - wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); - wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); - wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" - "BF status 0x%08x SNR 0x%08x\n" - "Tx Tpt %d goodput %d Rx goodput %d\n" - "Sectors(rx:tx) my %d:%d peer %d:%d\n", - wil->stats.bf_mcs, wil->stats.tsf, evt->status, - wil->stats.snr, le32_to_cpu(evt->tx_tpt), - le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), - wil->stats.my_rx_sector, wil->stats.my_tx_sector, - wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); -} - -/* - * Firmware reports EAPOL frame using WME event. - * Reconstruct Ethernet frame and deliver it via normal Rx - */ -static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, - void *d, int len) -{ - struct net_device *ndev = wil_to_ndev(wil); - struct wmi_eapol_rx_event *evt = d; - u16 eapol_len = le16_to_cpu(evt->eapol_len); - int sz = eapol_len + ETH_HLEN; - struct sk_buff *skb; - struct ethhdr *eth; - - wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, - evt->src_mac); - - if (eapol_len > 196) { /* TODO: revisit size limit */ - wil_err(wil, "EAPOL too large\n"); - return; - } - - skb = alloc_skb(sz, GFP_KERNEL); - if (!skb) { - wil_err(wil, "Failed to allocate skb\n"); - return; - } - eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); - memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); - memcpy(eth->h_source, evt->src_mac, ETH_ALEN); - eth->h_proto = cpu_to_be16(ETH_P_PAE); - memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); - skb->protocol = eth_type_trans(skb, ndev); - if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += skb->len; - } else { - ndev->stats.rx_dropped++; - } -} - -static const struct { - int eventid; - void (*handler)(struct wil6210_priv *wil, int eventid, - void *data, int data_len); -} wmi_evt_handlers[] = { - {WMI_READY_EVENTID, wmi_evt_ready}, - {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, - {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, - {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, - {WMI_CONNECT_EVENTID, wmi_evt_connect}, - {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, - {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, - {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, -}; - -/* - * Run in IRQ context - * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev - * that will be eventually handled by the @wmi_event_worker in the thread - * context of thread "wil6210_wmi" - */ -void wmi_recv_cmd(struct wil6210_priv *wil) -{ - struct wil6210_mbox_ring_desc d_tail; - struct wil6210_mbox_hdr hdr; - struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; - struct pending_wmi_event *evt; - u8 *cmd; - void __iomem *src; - ulong flags; - - for (;;) { - u16 len; - - r->head = ioread32(wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, rx.head)); - if (r->tail == r->head) - return; - - /* read cmd from tail */ - wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), - sizeof(struct wil6210_mbox_ring_desc)); - if (d_tail.sync == 0) { - wil_err(wil, "Mbox evt not owned by FW?\n"); - return; - } - - if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { - wil_err(wil, "Mbox evt at 0x%08x?\n", - le32_to_cpu(d_tail.addr)); - return; - } - - len = le16_to_cpu(hdr.len); - src = wmi_buffer(wil, d_tail.addr) + - sizeof(struct wil6210_mbox_hdr); - evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, - event.wmi) + len, 4), - GFP_KERNEL); - if (!evt) { - wil_err(wil, "kmalloc for WMI event (%d) failed\n", - len); - return; - } - evt->event.hdr = hdr; - cmd = (void *)&evt->event.wmi; - wil_memcpy_fromio_32(cmd, src, len); - /* mark entry as empty */ - iowrite32(0, wil->csr + HOSTADDR(r->tail) + - offsetof(struct wil6210_mbox_ring_desc, sync)); - /* indicate */ - wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", - le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), - hdr.flags); - if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && - (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { - wil_dbg_WMI(wil, "WMI event 0x%04x\n", - evt->event.wmi.id); - } - wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, - &evt->event.hdr, sizeof(hdr) + len, true); - - /* advance tail */ - r->tail = r->base + ((r->tail - r->base + - sizeof(struct wil6210_mbox_ring_desc)) % r->size); - iowrite32(r->tail, wil->csr + HOST_MBOX + - offsetof(struct wil6210_mbox_ctl, rx.tail)); - - /* add to the pending list */ - spin_lock_irqsave(&wil->wmi_ev_lock, flags); - list_add_tail(&evt->list, &wil->pending_wmi_ev); - spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); - { - int q = queue_work(wil->wmi_wq, - &wil->wmi_event_worker); - wil_dbg_WMI(wil, "queue_work -> %d\n", q); - } - } -} - -int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec) -{ - int rc; - int remain; - - mutex_lock(&wil->wmi_mutex); - - rc = __wmi_send(wil, cmdid, buf, len); - if (rc) - goto out; - - wil->reply_id = reply_id; - wil->reply_buf = reply; - wil->reply_size = reply_size; - remain = wait_for_completion_timeout(&wil->wmi_ready, - msecs_to_jiffies(to_msec)); - if (0 == remain) { - wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", - cmdid, reply_id, to_msec); - rc = -ETIME; - } else { - wil_dbg_WMI(wil, - "wmi_call(0x%04x->0x%04x) completed in %d msec\n", - cmdid, reply_id, - to_msec - jiffies_to_msecs(remain)); - } - wil->reply_id = 0; - wil->reply_buf = NULL; - wil->reply_size = 0; - out: - mutex_unlock(&wil->wmi_mutex); - - return rc; -} - -int wmi_echo(struct wil6210_priv *wil) -{ - struct wmi_echo_cmd cmd = { - .value = cpu_to_le32(0x12345678), - }; - - return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), - WMI_ECHO_RSP_EVENTID, NULL, 0, 20); -} - -int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) -{ - struct wmi_set_mac_address_cmd cmd; - - memcpy(cmd.mac, addr, ETH_ALEN); - - wil_dbg_WMI(wil, "Set MAC %pM\n", addr); - - return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) -{ - struct wmi_bcon_ctrl_cmd cmd = { - .bcon_interval = cpu_to_le16(bi), - .network_type = wmi_nettype, - .disable_sec_offload = 1, - }; - - if (!wil->secure_pcp) - cmd.disable_sec = 1; - - return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) -{ - struct wmi_set_ssid_cmd cmd = { - .ssid_len = cpu_to_le32(ssid_len), - }; - - if (ssid_len > sizeof(cmd.ssid)) - return -EINVAL; - - memcpy(cmd.ssid, ssid, ssid_len); - - return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) -{ - int rc; - struct { - struct wil6210_mbox_hdr_wmi wmi; - struct wmi_set_ssid_cmd cmd; - } __packed reply; - int len; /* reply.cmd.ssid_len in CPU order */ - - rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, - &reply, sizeof(reply), 20); - if (rc) - return rc; - - len = le32_to_cpu(reply.cmd.ssid_len); - if (len > sizeof(reply.cmd.ssid)) - return -EINVAL; - - *ssid_len = len; - memcpy(ssid, reply.cmd.ssid, len); - - return 0; -} - -int wmi_set_channel(struct wil6210_priv *wil, int channel) -{ - struct wmi_set_pcp_channel_cmd cmd = { - .channel = channel - 1, - }; - - return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_get_channel(struct wil6210_priv *wil, int *channel) -{ - int rc; - struct { - struct wil6210_mbox_hdr_wmi wmi; - struct wmi_set_pcp_channel_cmd cmd; - } __packed reply; - - rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, - WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); - if (rc) - return rc; - - if (reply.cmd.channel > 3) - return -EINVAL; - - *channel = reply.cmd.channel + 1; - - return 0; -} - -int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) -{ - struct wmi_eapol_tx_cmd *cmd; - struct ethhdr *eth; - u16 eapol_len = skb->len - ETH_HLEN; - void *eapol = skb->data + ETH_HLEN; - uint i; - int rc; - - skb_set_mac_header(skb, 0); - eth = eth_hdr(skb); - wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); - for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { - if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) - goto found_dest; - } - - return -EINVAL; - - found_dest: - /* find out eapol data & len */ - cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); - if (!cmd) - return -EINVAL; - - memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); - cmd->eapol_len = cpu_to_le16(eapol_len); - memcpy(cmd->eapol, eapol, eapol_len); - rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); - kfree(cmd); - - return rc; -} - -int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, - const void *mac_addr) -{ - struct wmi_delete_cipher_key_cmd cmd = { - .key_index = key_index, - }; - - if (mac_addr) - memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); - - return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, - const void *mac_addr, int key_len, const void *key) -{ - struct wmi_add_cipher_key_cmd cmd = { - .key_index = key_index, - .key_usage = WMI_KEY_USE_PAIRWISE, - .key_len = key_len, - }; - - if (!key || (key_len > sizeof(cmd.key))) - return -EINVAL; - - memcpy(cmd.key, key, key_len); - if (mac_addr) - memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); - - return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); -} - -int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) -{ - int rc; - u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; - struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); - if (!cmd) { - wil_err(wil, "kmalloc(%d) failed\n", len); - return -ENOMEM; - } - - cmd->mgmt_frm_type = type; - /* BUG: FW API define ieLen as u8. Will fix FW */ - cmd->ie_len = cpu_to_le16(ie_len); - memcpy(cmd->ie_info, ie, ie_len); - rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); - kfree(cmd); - - return rc; -} - -void wmi_event_flush(struct wil6210_priv *wil) -{ - struct pending_wmi_event *evt, *t; - - wil_dbg_WMI(wil, "%s()\n", __func__); - - list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { - list_del(&evt->list); - kfree(evt); - } -} - -static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, - void *d, int len) -{ - uint i; - - for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { - if (wmi_evt_handlers[i].eventid == id) { - wmi_evt_handlers[i].handler(wil, id, d, len); - return true; - } - } - - return false; -} - -static void wmi_event_handle(struct wil6210_priv *wil, - struct wil6210_mbox_hdr *hdr) -{ - u16 len = le16_to_cpu(hdr->len); - - if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && - (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { - struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); - void *evt_data = (void *)(&wmi[1]); - u16 id = le16_to_cpu(wmi->id); - /* check if someone waits for this event */ - if (wil->reply_id && wil->reply_id == id) { - if (wil->reply_buf) { - memcpy(wil->reply_buf, wmi, - min(len, wil->reply_size)); - } else { - wmi_evt_call_handler(wil, id, evt_data, - len - sizeof(*wmi)); - } - wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); - complete(&wil->wmi_ready); - return; - } - /* unsolicited event */ - /* search for handler */ - if (!wmi_evt_call_handler(wil, id, evt_data, - len - sizeof(*wmi))) { - wil_err(wil, "Unhandled event 0x%04x\n", id); - } - } else { - wil_err(wil, "Unknown event type\n"); - print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, - hdr, sizeof(*hdr) + len, true); - } -} - -/* - * Retrieve next WMI event from the pending list - */ -static struct list_head *next_wmi_ev(struct wil6210_priv *wil) -{ - ulong flags; - struct list_head *ret = NULL; - - spin_lock_irqsave(&wil->wmi_ev_lock, flags); - - if (!list_empty(&wil->pending_wmi_ev)) { - ret = wil->pending_wmi_ev.next; - list_del(ret); - } - - spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); - - return ret; -} - -/* - * Handler for the WMI events - */ -void wmi_event_worker(struct work_struct *work) -{ - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - wmi_event_worker); - struct pending_wmi_event *evt; - struct list_head *lh; - - while ((lh = next_wmi_ev(wil)) != NULL) { - evt = list_entry(lh, struct pending_wmi_event, list); - wmi_event_handle(wil, &evt->event.hdr); - kfree(evt); - } -} - -void wmi_connect_worker(struct work_struct *work) -{ - int rc; - struct wil6210_priv *wil = container_of(work, struct wil6210_priv, - wmi_connect_worker); - - if (wil->pending_connect_cid < 0) { - wil_err(wil, "No connection pending\n"); - return; - } - - wil_dbg_WMI(wil, "Configure for connection CID %d\n", - wil->pending_connect_cid); - - rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, - wil->pending_connect_cid, 0); - wil->pending_connect_cid = -1; - if (rc == 0) - wil_link_on(wil); -} diff --git a/trunk/drivers/net/wireless/ath/wil6210/wmi.h b/trunk/drivers/net/wireless/ath/wil6210/wmi.h deleted file mode 100644 index 3bbf87572b07..000000000000 --- a/trunk/drivers/net/wireless/ath/wil6210/wmi.h +++ /dev/null @@ -1,1116 +0,0 @@ -/* - * Copyright (c) 2012 Qualcomm Atheros, Inc. - * Copyright (c) 2006-2012 Wilocity . - * - * 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. - */ - -/* - * This file contains the definitions of the WMI protocol specified in the - * Wireless Module Interface (WMI) for the Wilocity - * MARLON 60 Gigabit wireless solution. - * It includes definitions of all the commands and events. - * Commands are messages from the host to the WM. - * Events are messages from the WM to the host. - */ - -#ifndef __WILOCITY_WMI_H__ -#define __WILOCITY_WMI_H__ - -/* General */ - -#define WMI_MAC_LEN (6) -#define WMI_PROX_RANGE_NUM (3) - -/* List of Commands */ -enum wmi_command_id { - WMI_CONNECT_CMDID = 0x0001, - WMI_DISCONNECT_CMDID = 0x0003, - WMI_START_SCAN_CMDID = 0x0007, - WMI_SET_BSS_FILTER_CMDID = 0x0009, - WMI_SET_PROBED_SSID_CMDID = 0x000a, - WMI_SET_LISTEN_INT_CMDID = 0x000b, - WMI_BCON_CTRL_CMDID = 0x000f, - WMI_ADD_CIPHER_KEY_CMDID = 0x0016, - WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, - WMI_SET_APPIE_CMDID = 0x003f, - WMI_GET_APPIE_CMDID = 0x0040, - WMI_SET_WSC_STATUS_CMDID = 0x0041, - WMI_PXMT_RANGE_CFG_CMDID = 0x0042, - WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, - WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, - WMI_MEM_READ_CMDID = 0x0800, - WMI_MEM_WR_CMDID = 0x0801, - WMI_ECHO_CMDID = 0x0803, - WMI_DEEP_ECHO_CMDID = 0x0804, - WMI_CONFIG_MAC_CMDID = 0x0805, - WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, - WMI_ADD_STATION_CMDID = 0x0807, - WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, - WMI_PHY_GET_STATISTICS_CMDID = 0x0809, - WMI_FS_TUNE_CMDID = 0x080a, - WMI_CORR_MEASURE_CMDID = 0x080b, - WMI_TEMP_SENSE_CMDID = 0x080e, - WMI_DC_CALIB_CMDID = 0x080f, - WMI_SEND_TONE_CMDID = 0x0810, - WMI_IQ_TX_CALIB_CMDID = 0x0811, - WMI_IQ_RX_CALIB_CMDID = 0x0812, - WMI_SET_UCODE_IDLE_CMDID = 0x0813, - WMI_SET_WORK_MODE_CMDID = 0x0815, - WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, - WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, - WMI_MARLON_R_READ_CMDID = 0x0818, - WMI_MARLON_R_WRITE_CMDID = 0x0819, - WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, - MAC_IO_STATIC_PARAMS_CMDID = 0x081b, - MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, - WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, - WMI_CFG_RX_CHAIN_CMDID = 0x0820, - WMI_VRING_CFG_CMDID = 0x0821, - WMI_RX_ON_CMDID = 0x0822, - WMI_VRING_BA_EN_CMDID = 0x0823, - WMI_VRING_BA_DIS_CMDID = 0x0824, - WMI_RCP_ADDBA_RESP_CMDID = 0x0825, - WMI_RCP_DELBA_CMDID = 0x0826, - WMI_SET_SSID_CMDID = 0x0827, - WMI_GET_SSID_CMDID = 0x0828, - WMI_SET_PCP_CHANNEL_CMDID = 0x0829, - WMI_GET_PCP_CHANNEL_CMDID = 0x082a, - WMI_SW_TX_REQ_CMDID = 0x082b, - WMI_RX_OFF_CMDID = 0x082c, - WMI_READ_MAC_RXQ_CMDID = 0x0830, - WMI_READ_MAC_TXQ_CMDID = 0x0831, - WMI_WRITE_MAC_RXQ_CMDID = 0x0832, - WMI_WRITE_MAC_TXQ_CMDID = 0x0833, - WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, - WMI_MLME_PUSH_CMDID = 0x0835, - WMI_BEAMFORMING_MGMT_CMDID = 0x0836, - WMI_BF_TXSS_MGMT_CMDID = 0x0837, - WMI_BF_SM_MGMT_CMDID = 0x0838, - WMI_BF_RXSS_MGMT_CMDID = 0x0839, - WMI_SET_SECTORS_CMDID = 0x0849, - WMI_MAINTAIN_PAUSE_CMDID = 0x0850, - WMI_MAINTAIN_RESUME_CMDID = 0x0851, - WMI_RS_MGMT_CMDID = 0x0852, - WMI_RF_MGMT_CMDID = 0x0853, - /* Performance monitoring commands */ - WMI_BF_CTRL_CMDID = 0x0862, - WMI_NOTIFY_REQ_CMDID = 0x0863, - WMI_GET_STATUS_CMDID = 0x0864, - WMI_UNIT_TEST_CMDID = 0x0900, - WMI_HICCUP_CMDID = 0x0901, - WMI_FLASH_READ_CMDID = 0x0902, - WMI_FLASH_WRITE_CMDID = 0x0903, - WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, - - WMI_SET_MAC_ADDRESS_CMDID = 0xf003, - WMI_ABORT_SCAN_CMDID = 0xf007, - WMI_SET_PMK_CMDID = 0xf028, - - WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, - WMI_GET_PMK_CMDID = 0xf048, - WMI_SET_PASSPHRASE_CMDID = 0xf049, - WMI_SEND_ASSOC_RES_CMDID = 0xf04a, - WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, - WMI_EAPOL_TX_CMDID = 0xf04c, - WMI_MAC_ADDR_REQ_CMDID = 0xf04d, - WMI_FW_VER_CMDID = 0xf04e, -}; - -/* - * Commands data structures - */ - -/* - * Frame Types - */ -enum wmi_mgmt_frame_type { - WMI_FRAME_BEACON = 0, - WMI_FRAME_PROBE_REQ = 1, - WMI_FRAME_PROBE_RESP = 2, - WMI_FRAME_ASSOC_REQ = 3, - WMI_FRAME_ASSOC_RESP = 4, - WMI_NUM_MGMT_FRAME, -}; - -/* - * WMI_CONNECT_CMDID - */ -enum wmi_network_type { - WMI_NETTYPE_INFRA = 0x01, - WMI_NETTYPE_ADHOC = 0x02, - WMI_NETTYPE_ADHOC_CREATOR = 0x04, - WMI_NETTYPE_AP = 0x10, - WMI_NETTYPE_P2P = 0x20, - WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ -}; - -enum wmi_dot11_auth_mode { - WMI_AUTH11_OPEN = 0x01, - WMI_AUTH11_SHARED = 0x02, - WMI_AUTH11_LEAP = 0x04, - WMI_AUTH11_WSC = 0x08, -}; - -enum wmi_auth_mode { - WMI_AUTH_NONE = 0x01, - WMI_AUTH_WPA = 0x02, - WMI_AUTH_WPA2 = 0x04, - WMI_AUTH_WPA_PSK = 0x08, - WMI_AUTH_WPA2_PSK = 0x10, - WMI_AUTH_WPA_CCKM = 0x20, - WMI_AUTH_WPA2_CCKM = 0x40, -}; - -enum wmi_crypto_type { - WMI_CRYPT_NONE = 0x01, - WMI_CRYPT_WEP = 0x02, - WMI_CRYPT_TKIP = 0x04, - WMI_CRYPT_AES = 0x08, - WMI_CRYPT_AES_GCMP = 0x20, -}; - - -enum wmi_connect_ctrl_flag_bits { - WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, - WMI_CONNECT_SEND_REASSOC = 0x0002, - WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, - WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, - WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, - WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, - WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, - WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, -}; - -#define WMI_MAX_SSID_LEN (32) - -struct wmi_connect_cmd { - u8 network_type; - u8 dot11_auth_mode; - u8 auth_mode; - u8 pairwise_crypto_type; - u8 pairwise_crypto_len; - u8 group_crypto_type; - u8 group_crypto_len; - u8 ssid_len; - u8 ssid[WMI_MAX_SSID_LEN]; - u8 channel; - u8 reserved0; - u8 bssid[WMI_MAC_LEN]; - __le32 ctrl_flags; - u8 dst_mac[WMI_MAC_LEN]; - u8 reserved1[2]; -} __packed; - - -/* - * WMI_RECONNECT_CMDID - */ -struct wmi_reconnect_cmd { - u8 channel; /* hint */ - u8 reserved; - u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ -} __packed; - - -/* - * WMI_SET_PMK_CMDID - */ - -#define WMI_MIN_KEY_INDEX (0) -#define WMI_MAX_KEY_INDEX (3) -#define WMI_MAX_KEY_LEN (32) -#define WMI_PASSPHRASE_LEN (64) -#define WMI_PMK_LEN (32) - -struct wmi_set_pmk_cmd { - u8 pmk[WMI_PMK_LEN]; -} __packed; - - -/* - * WMI_SET_PASSPHRASE_CMDID - */ -struct wmi_set_passphrase_cmd { - u8 ssid[WMI_MAX_SSID_LEN]; - u8 passphrase[WMI_PASSPHRASE_LEN]; - u8 ssid_len; - u8 passphrase_len; -} __packed; - -/* - * WMI_ADD_CIPHER_KEY_CMDID - */ -enum wmi_key_usage { - WMI_KEY_USE_PAIRWISE = 0, - WMI_KEY_USE_GROUP = 1, - WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ -}; - -struct wmi_add_cipher_key_cmd { - u8 key_index; - u8 key_type; - u8 key_usage; /* enum wmi_key_usage */ - u8 key_len; - u8 key_rsc[8]; /* key replay sequence counter */ - u8 key[WMI_MAX_KEY_LEN]; - u8 key_op_ctrl; /* Additional Key Control information */ - u8 mac[WMI_MAC_LEN]; -} __packed; - -/* - * WMI_DELETE_CIPHER_KEY_CMDID - */ -struct wmi_delete_cipher_key_cmd { - u8 key_index; - u8 mac[WMI_MAC_LEN]; -} __packed; - - -/* - * WMI_START_SCAN_CMDID - * - * Start L1 scan operation - * - * Returned events: - * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. - * - WMI_SCAN_COMPLETE_EVENTID - */ -enum wmi_scan_type { - WMI_LONG_SCAN = 0, - WMI_SHORT_SCAN = 1, -}; - -struct wmi_start_scan_cmd { - u8 reserved[8]; - __le32 home_dwell_time; /* Max duration in the home channel(ms) */ - __le32 force_scan_interval; /* Time interval between scans (ms)*/ - u8 scan_type; /* wmi_scan_type */ - u8 num_channels; /* how many channels follow */ - struct { - u8 channel; - u8 reserved; - } channel_list[0]; /* channels ID's */ - /* 0 - 58320 MHz */ - /* 1 - 60480 MHz */ - /* 2 - 62640 MHz */ -} __packed; - -/* - * WMI_SET_PROBED_SSID_CMDID - */ -#define MAX_PROBED_SSID_INDEX (15) - -enum wmi_ssid_flag { - WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ - WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ - WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ -}; - -struct wmi_probed_ssid_cmd { - u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ - u8 flag; /* enum wmi_ssid_flag */ - u8 ssid_len; - u8 ssid[WMI_MAX_SSID_LEN]; -} __packed; - -/* - * WMI_SET_APPIE_CMDID - * Add Application specified IE to a management frame - */ -struct wmi_set_appie_cmd { - u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ - u8 reserved; - __le16 ie_len; /* Length of the IE to be added to MGMT frame */ - u8 ie_info[0]; -} __packed; - -#define WMI_MAX_IE_LEN (1024) - -struct wmi_pxmt_range_cfg_cmd { - u8 dst_mac[WMI_MAC_LEN]; - __le16 range; -} __packed; - -struct wmi_pxmt_snr2_range_cfg_cmd { - s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; -} __packed; - -/* - * WMI_RF_MGMT_CMDID - */ -enum wmi_rf_mgmt_type { - WMI_RF_MGMT_W_DISABLE = 0, - WMI_RF_MGMT_W_ENABLE = 1, - WMI_RF_MGMT_GET_STATUS = 2, -}; - -struct wmi_rf_mgmt_cmd { - __le32 rf_mgmt_type; -} __packed; - -/* - * WMI_SET_SSID_CMDID - */ -struct wmi_set_ssid_cmd { - __le32 ssid_len; - u8 ssid[WMI_MAX_SSID_LEN]; -} __packed; - -/* - * WMI_SET_PCP_CHANNEL_CMDID - */ -struct wmi_set_pcp_channel_cmd { - u8 channel; - u8 reserved[3]; -} __packed; - -/* - * WMI_BCON_CTRL_CMDID - */ -struct wmi_bcon_ctrl_cmd { - __le16 bcon_interval; - __le16 frag_num; - __le64 ss_mask; - u8 network_type; - u8 reserved; - u8 disable_sec_offload; - u8 disable_sec; -} __packed; - -/* - * WMI_SW_TX_REQ_CMDID - */ -struct wmi_sw_tx_req_cmd { - u8 dst_mac[WMI_MAC_LEN]; - __le16 len; - u8 payload[0]; -} __packed; - -/* - * WMI_VRING_CFG_CMDID - */ - -struct wmi_sw_ring_cfg { - __le64 ring_mem_base; - __le16 ring_size; - __le16 max_mpdu_size; -} __packed; - -struct wmi_vring_cfg_schd { - __le16 priority; - __le16 timeslot_us; -} __packed; - -enum wmi_vring_cfg_encap_trans_type { - WMI_VRING_ENC_TYPE_802_3 = 0, - WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, -}; - -enum wmi_vring_cfg_ds_cfg { - WMI_VRING_DS_PBSS = 0, - WMI_VRING_DS_STATION = 1, - WMI_VRING_DS_AP = 2, - WMI_VRING_DS_ADDR4 = 3, -}; - -enum wmi_vring_cfg_nwifi_ds_trans_type { - WMI_NWIFI_TX_TRANS_MODE_NO = 0, - WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, - WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, -}; - -enum wmi_vring_cfg_schd_params_priority { - WMI_SCH_PRIO_REGULAR = 0, - WMI_SCH_PRIO_HIGH = 1, -}; - -struct wmi_vring_cfg { - struct wmi_sw_ring_cfg tx_sw_ring; - u8 ringid; /* 0-23 vrings */ - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 encap_trans_type; - u8 ds_cfg; /* 802.3 DS cfg */ - u8 nwifi_ds_trans_type; - - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) - #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) - #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) - u8 mac_ctrl; - - #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) - #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) - #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) - u8 to_resolution; - u8 agg_max_wsize; - struct wmi_vring_cfg_schd schd_params; -} __packed; - -enum wmi_vring_cfg_cmd_action { - WMI_VRING_CMD_ADD = 0, - WMI_VRING_CMD_MODIFY = 1, - WMI_VRING_CMD_DELETE = 2, -}; - -struct wmi_vring_cfg_cmd { - __le32 action; - struct wmi_vring_cfg vring_cfg; -} __packed; - -/* - * WMI_VRING_BA_EN_CMDID - */ -struct wmi_vring_ba_en_cmd { - u8 ringid; - u8 agg_max_wsize; - __le16 ba_timeout; -} __packed; - -/* - * WMI_VRING_BA_DIS_CMDID - */ -struct wmi_vring_ba_dis_cmd { - u8 ringid; - u8 reserved; - __le16 reason; -} __packed; - -/* - * WMI_NOTIFY_REQ_CMDID - */ -struct wmi_notify_req_cmd { - u8 cid; - u8 reserved[3]; - __le32 interval_usec; -} __packed; - -/* - * WMI_CFG_RX_CHAIN_CMDID - */ -enum wmi_sniffer_cfg_mode { - WMI_SNIFFER_OFF = 0, - WMI_SNIFFER_ON = 1, -}; - -enum wmi_sniffer_cfg_phy_info_mode { - WMI_SNIFFER_PHY_INFO_DISABLED = 0, - WMI_SNIFFER_PHY_INFO_ENABLED = 1, -}; - -enum wmi_sniffer_cfg_phy_support { - WMI_SNIFFER_CP = 0, - WMI_SNIFFER_DP = 1, - WMI_SNIFFER_BOTH_PHYS = 2, -}; - -struct wmi_sniffer_cfg { - __le32 mode; /* enum wmi_sniffer_cfg_mode */ - __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ - __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ - u8 channel; - u8 reserved[3]; -} __packed; - -enum wmi_cfg_rx_chain_cmd_action { - WMI_RX_CHAIN_ADD = 0, - WMI_RX_CHAIN_DEL = 1, -}; - -enum wmi_cfg_rx_chain_cmd_decap_trans_type { - WMI_DECAP_TYPE_802_3 = 0, - WMI_DECAP_TYPE_NATIVE_WIFI = 1, -}; - -enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { - WMI_NWIFI_RX_TRANS_MODE_NO = 0, - WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, - WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, -}; - -struct wmi_cfg_rx_chain_cmd { - __le32 action; - struct wmi_sw_ring_cfg rx_sw_ring; - u8 mid; - u8 decap_trans_type; - - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) - #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) - u8 l2_802_3_offload_ctrl; - - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) - #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) - u8 l2_nwifi_offload_ctrl; - - u8 vlan_id; - u8 nwifi_ds_trans_type; - - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) - #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) - #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) - u8 l3_l4_ctrl; - - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) - #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) - #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) - #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) - #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) - #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) - #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) - #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) - u8 ring_ctrl; - - __le16 prefetch_thrsh; - __le16 wb_thrsh; - __le32 itr_value; - __le16 host_thrsh; - u8 reserved[2]; - struct wmi_sniffer_cfg sniffer_cfg; -} __packed; - -/* - * WMI_RCP_ADDBA_RESP_CMDID - */ -struct wmi_rcp_addba_resp_cmd { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 dialog_token; - __le16 status_code; - __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ - __le16 ba_timeout; -} __packed; - -/* - * WMI_RCP_DELBA_CMDID - */ -struct wmi_rcp_delba_cmd { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 reserved; - __le16 reason; -} __packed; - -/* - * WMI_RCP_ADDBA_REQ_CMDID - */ -struct wmi_rcp_addba_req_cmd { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 dialog_token; - /* ieee80211_ba_parameterset field as it received */ - __le16 ba_param_set; - __le16 ba_timeout; - /* ieee80211_ba_seqstrl field as it received */ - __le16 ba_seq_ctrl; -} __packed; - -/* - * WMI_SET_MAC_ADDRESS_CMDID - */ -struct wmi_set_mac_address_cmd { - u8 mac[WMI_MAC_LEN]; - u8 reserved[2]; -} __packed; - - -/* -* WMI_EAPOL_TX_CMDID -*/ -struct wmi_eapol_tx_cmd { - u8 dst_mac[WMI_MAC_LEN]; - __le16 eapol_len; - u8 eapol[0]; -} __packed; - -/* - * WMI_ECHO_CMDID - * - * Check FW is alive - * - * WMI_DEEP_ECHO_CMDID - * - * Check FW and ucode are alive - * - * Returned event: WMI_ECHO_RSP_EVENTID - * same event for both commands - */ -struct wmi_echo_cmd { - __le32 value; -} __packed; - -/* - * WMI Events - */ - -/* - * List of Events (target to host) - */ -enum wmi_event_id { - WMI_IMM_RSP_EVENTID = 0x0000, - WMI_READY_EVENTID = 0x1001, - WMI_CONNECT_EVENTID = 0x1002, - WMI_DISCONNECT_EVENTID = 0x1003, - WMI_SCAN_COMPLETE_EVENTID = 0x100a, - WMI_REPORT_STATISTICS_EVENTID = 0x100b, - WMI_RD_MEM_RSP_EVENTID = 0x1800, - WMI_FW_READY_EVENTID = 0x1801, - WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, - WMI_ECHO_RSP_EVENTID = 0x1803, - WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, - WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, - WMI_ADD_STATION_DONE_EVENTID = 0x1807, - WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, - WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, - WMI_FS_TUNE_DONE_EVENTID = 0x180a, - WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, - WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, - WMI_DC_CALIB_DONE_EVENTID = 0x180f, - WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, - WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, - WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, - WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, - WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, - WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, - WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, - WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, - WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, - - WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, - WMI_VRING_CFG_DONE_EVENTID = 0x1821, - WMI_RX_ON_DONE_EVENTID = 0x1822, - WMI_BA_STATUS_EVENTID = 0x1823, - WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, - WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, - WMI_DELBA_EVENTID = 0x1826, - WMI_GET_SSID_EVENTID = 0x1828, - WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, - WMI_SW_TX_COMPLETE_EVENTID = 0x182b, - WMI_RX_OFF_DONE_EVENTID = 0x182c, - - WMI_READ_MAC_RXQ_EVENTID = 0x1830, - WMI_READ_MAC_TXQ_EVENTID = 0x1831, - WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, - WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, - WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, - - WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, - WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, - WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, - WMI_RS_MGMT_DONE_EVENTID = 0x1852, - WMI_RF_MGMT_STATUS_EVENTID = 0x1853, - WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, - WMI_RX_MGMT_PACKET_EVENTID = 0x1840, - - /* Performance monitoring events */ - WMI_DATA_PORT_OPEN_EVENTID = 0x1860, - WMI_WBE_LINKDOWN_EVENTID = 0x1861, - - WMI_BF_CTRL_DONE_EVENTID = 0x1862, - WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, - WMI_GET_STATUS_DONE_EVENTID = 0x1864, - - WMI_UNIT_TEST_EVENTID = 0x1900, - WMI_FLASH_READ_DONE_EVENTID = 0x1902, - WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, - - WMI_SET_CHANNEL_EVENTID = 0x9000, - WMI_ASSOC_REQ_EVENTID = 0x9001, - WMI_EAPOL_RX_EVENTID = 0x9002, - WMI_MAC_ADDR_RESP_EVENTID = 0x9003, - WMI_FW_VER_EVENTID = 0x9004, -}; - -/* - * Events data structures - */ - -/* - * WMI_RF_MGMT_STATUS_EVENTID - */ -enum wmi_rf_status { - WMI_RF_ENABLED = 0, - WMI_RF_DISABLED_HW = 1, - WMI_RF_DISABLED_SW = 2, - WMI_RF_DISABLED_HW_SW = 3, -}; - -struct wmi_rf_mgmt_status_event { - __le32 rf_status; -} __packed; - -/* - * WMI_GET_STATUS_DONE_EVENTID - */ -struct wmi_get_status_done_event { - __le32 is_associated; - u8 cid; - u8 reserved0[3]; - u8 bssid[WMI_MAC_LEN]; - u8 channel; - u8 reserved1; - u8 network_type; - u8 reserved2[3]; - __le32 ssid_len; - u8 ssid[WMI_MAX_SSID_LEN]; - __le32 rf_status; - __le32 is_secured; -} __packed; - -/* - * WMI_FW_VER_EVENTID - */ -struct wmi_fw_ver_event { - u8 major; - u8 minor; - __le16 subminor; - __le16 build; -} __packed; - -/* -* WMI_MAC_ADDR_RESP_EVENTID -*/ -struct wmi_mac_addr_resp_event { - u8 mac[WMI_MAC_LEN]; - u8 auth_mode; - u8 crypt_mode; - __le32 offload_mode; -} __packed; - -/* -* WMI_EAPOL_RX_EVENTID -*/ -struct wmi_eapol_rx_event { - u8 src_mac[WMI_MAC_LEN]; - __le16 eapol_len; - u8 eapol[0]; -} __packed; - -/* -* WMI_READY_EVENTID -*/ -enum wmi_phy_capability { - WMI_11A_CAPABILITY = 1, - WMI_11G_CAPABILITY = 2, - WMI_11AG_CAPABILITY = 3, - WMI_11NA_CAPABILITY = 4, - WMI_11NG_CAPABILITY = 5, - WMI_11NAG_CAPABILITY = 6, - WMI_11AD_CAPABILITY = 7, - WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, -}; - -struct wmi_ready_event { - __le32 sw_version; - __le32 abi_version; - u8 mac[WMI_MAC_LEN]; - u8 phy_capability; /* enum wmi_phy_capability */ - u8 reserved; -} __packed; - -/* - * WMI_NOTIFY_REQ_DONE_EVENTID - */ -struct wmi_notify_req_done_event { - __le32 status; - __le64 tsf; - __le32 snr_val; - __le32 tx_tpt; - __le32 tx_goodput; - __le32 rx_goodput; - __le16 bf_mcs; - __le16 my_rx_sector; - __le16 my_tx_sector; - __le16 other_rx_sector; - __le16 other_tx_sector; - __le16 range; -} __packed; - -/* - * WMI_CONNECT_EVENTID - */ -struct wmi_connect_event { - u8 channel; - u8 reserved0; - u8 bssid[WMI_MAC_LEN]; - __le16 listen_interval; - __le16 beacon_interval; - u8 network_type; - u8 reserved1[3]; - u8 beacon_ie_len; - u8 assoc_req_len; - u8 assoc_resp_len; - u8 cid; - u8 reserved2[3]; - u8 assoc_info[0]; -} __packed; - -/* - * WMI_DISCONNECT_EVENTID - */ -enum wmi_disconnect_reason { - WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, - WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ - WMI_DIS_REASON_DISCONNECT_CMD = 3, - WMI_DIS_REASON_BSS_DISCONNECTED = 4, - WMI_DIS_REASON_AUTH_FAILED = 5, - WMI_DIS_REASON_ASSOC_FAILED = 6, - WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, - WMI_DIS_REASON_CSERV_DISCONNECT = 8, - WMI_DIS_REASON_INVALID_PROFILE = 10, - WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, - WMI_DIS_REASON_PROFILE_MISMATCH = 12, - WMI_DIS_REASON_CONNECTION_EVICTED = 13, - WMI_DIS_REASON_IBSS_MERGE = 14, -}; - -struct wmi_disconnect_event { - __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ - u8 bssid[WMI_MAC_LEN]; /* set if known */ - u8 disconnect_reason; /* see wmi_disconnect_reason_e */ - u8 assoc_resp_len; - u8 assoc_info[0]; -} __packed; - -/* - * WMI_SCAN_COMPLETE_EVENTID - */ -struct wmi_scan_complete_event { - __le32 status; -} __packed; - -/* - * WMI_BA_STATUS_EVENTID - */ -enum wmi_vring_ba_status { - WMI_BA_AGREED = 0, - WMI_BA_NON_AGREED = 1, -}; - -struct wmi_vring_ba_status_event { - __le16 status; - u8 reserved[2]; - u8 ringid; - u8 agg_wsize; - __le16 ba_timeout; -} __packed; - -/* - * WMI_DELBA_EVENTID - */ -struct wmi_delba_event { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 from_initiator; - __le16 reason; -} __packed; - -/* - * WMI_VRING_CFG_DONE_EVENTID - */ -enum wmi_vring_cfg_done_event_status { - WMI_VRING_CFG_SUCCESS = 0, - WMI_VRING_CFG_FAILURE = 1, -}; - -struct wmi_vring_cfg_done_event { - u8 ringid; - u8 status; - u8 reserved[2]; - __le32 tx_vring_tail_ptr; -} __packed; - -/* - * WMI_ADDBA_RESP_SENT_EVENTID - */ -enum wmi_rcp_addba_resp_sent_event_status { - WMI_ADDBA_SUCCESS = 0, - WMI_ADDBA_FAIL = 1, -}; - -struct wmi_rcp_addba_resp_sent_event { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 reserved; - __le16 status; -} __packed; - -/* - * WMI_RCP_ADDBA_REQ_EVENTID - */ -struct wmi_rcp_addba_req_event { - - #define CIDXTID_CID_POS (0) - #define CIDXTID_CID_LEN (4) - #define CIDXTID_CID_MSK (0xF) - #define CIDXTID_TID_POS (4) - #define CIDXTID_TID_LEN (4) - #define CIDXTID_TID_MSK (0xF0) - u8 cidxtid; - - u8 dialog_token; - __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ - __le16 ba_timeout; - __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ -} __packed; - -/* - * WMI_CFG_RX_CHAIN_DONE_EVENTID - */ -enum wmi_cfg_rx_chain_done_event_status { - WMI_CFG_RX_CHAIN_SUCCESS = 1, -}; - -struct wmi_cfg_rx_chain_done_event { - __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ - __le32 status; -} __packed; - -/* - * WMI_WBE_LINKDOWN_EVENTID - */ -enum wmi_wbe_link_down_event_reason { - WMI_WBE_REASON_USER_REQUEST = 0, - WMI_WBE_REASON_RX_DISASSOC = 1, - WMI_WBE_REASON_BAD_PHY_LINK = 2, -}; - -struct wmi_wbe_link_down_event { - u8 cid; - u8 reserved[3]; - __le32 reason; -} __packed; - -/* - * WMI_DATA_PORT_OPEN_EVENTID - */ -struct wmi_data_port_open_event { - u8 cid; - u8 reserved[3]; -} __packed; - -/* - * WMI_GET_PCP_CHANNEL_EVENTID - */ -struct wmi_get_pcp_channel_event { - u8 channel; - u8 reserved[3]; -} __packed; - -/* - * WMI_SW_TX_COMPLETE_EVENTID - */ -enum wmi_sw_tx_status { - WMI_TX_SW_STATUS_SUCCESS = 0, - WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, - WMI_TX_SW_STATUS_FAILED_TX = 2, -}; - -struct wmi_sw_tx_complete_event { - u8 status; /* enum wmi_sw_tx_status */ - u8 reserved[3]; -} __packed; - -/* - * WMI_GET_SSID_EVENTID - */ -struct wmi_get_ssid_event { - __le32 ssid_len; - u8 ssid[WMI_MAX_SSID_LEN]; -} __packed; - -/* - * WMI_RX_MGMT_PACKET_EVENTID - */ -struct wmi_rx_mgmt_info { - u8 mcs; - s8 snr; - __le16 range; - __le16 stype; - __le16 status; - __le32 len; - u8 qid; - u8 mid; - u8 cid; - u8 channel; /* From Radio MNGR */ -} __packed; - -struct wmi_rx_mgmt_packet_event { - struct wmi_rx_mgmt_info info; - u8 payload[0]; -} __packed; - -/* - * WMI_ECHO_RSP_EVENTID - */ -struct wmi_echo_event { - __le32 echoed_value; -} __packed; - -#endif /* __WILOCITY_WMI_H__ */ diff --git a/trunk/drivers/net/wireless/b43/b43.h b/trunk/drivers/net/wireless/b43/b43.h index 10e288d470e7..b298e5d68be2 100644 --- a/trunk/drivers/net/wireless/b43/b43.h +++ b/trunk/drivers/net/wireless/b43/b43.h @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "debugfs.h" @@ -723,10 +722,6 @@ enum b43_firmware_file_type { struct b43_request_fw_context { /* The device we are requesting the fw for. */ struct b43_wldev *dev; - /* a completion event structure needed if this call is asynchronous */ - struct completion fw_load_complete; - /* a pointer to the firmware object */ - const struct firmware *blob; /* The type of firmware to request. */ enum b43_firmware_file_type req_type; /* Error messages for each firmware type. */ diff --git a/trunk/drivers/net/wireless/b43/main.c b/trunk/drivers/net/wireless/b43/main.c index 806e34c19281..16ab280359bd 100644 --- a/trunk/drivers/net/wireless/b43/main.c +++ b/trunk/drivers/net/wireless/b43/main.c @@ -2088,18 +2088,11 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) b43warn(wl, text); } -static void b43_fw_cb(const struct firmware *firmware, void *context) -{ - struct b43_request_fw_context *ctx = context; - - ctx->blob = firmware; - complete(&ctx->fw_load_complete); -} - int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw, bool async) + struct b43_firmware_file *fw) { + const struct firmware *blob; struct b43_fw_header *hdr; u32 size; int err; @@ -2138,31 +2131,11 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - if (async) { - /* do this part asynchronously */ - init_completion(&ctx->fw_load_complete); - err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, - ctx->dev->dev->dev, GFP_KERNEL, - ctx, b43_fw_cb); - if (err < 0) { - pr_err("Unable to load firmware\n"); - return err; - } - /* stall here until fw ready */ - wait_for_completion(&ctx->fw_load_complete); - if (ctx->blob) - goto fw_ready; - /* On some ARM systems, the async request will fail, but the next sync - * request works. For this reason, we dall through here - */ - } - err = request_firmware(&ctx->blob, ctx->fwname, - ctx->dev->dev->dev); + err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", - ctx->fwname); + "Firmware file \"%s\" not found\n", ctx->fwname); return err; } else if (err) { snprintf(ctx->errors[ctx->req_type], @@ -2171,15 +2144,14 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, ctx->fwname, err); return err; } -fw_ready: - if (ctx->blob->size < sizeof(struct b43_fw_header)) + if (blob->size < sizeof(struct b43_fw_header)) goto err_format; - hdr = (struct b43_fw_header *)(ctx->blob->data); + hdr = (struct b43_fw_header *)(blob->data); switch (hdr->type) { case B43_FW_TYPE_UCODE: case B43_FW_TYPE_PCM: size = be32_to_cpu(hdr->size); - if (size != ctx->blob->size - sizeof(struct b43_fw_header)) + if (size != blob->size - sizeof(struct b43_fw_header)) goto err_format; /* fallthrough */ case B43_FW_TYPE_IV: @@ -2190,7 +2162,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, goto err_format; } - fw->data = ctx->blob; + fw->data = blob; fw->filename = name; fw->type = ctx->req_type; @@ -2200,7 +2172,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(ctx->blob); + release_firmware(blob); return -EPROTO; } @@ -2251,7 +2223,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_ucode; } } - err = b43_do_request_fw(ctx, filename, &fw->ucode, true); + err = b43_do_request_fw(ctx, filename, &fw->ucode); if (err) goto err_load; @@ -2263,7 +2235,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_pcm; fw->pcm_request_failed = false; - err = b43_do_request_fw(ctx, filename, &fw->pcm, false); + err = b43_do_request_fw(ctx, filename, &fw->pcm); if (err == -ENOENT) { /* We did not find a PCM file? Not fatal, but * core rev <= 10 must do without hwcrypto then. */ @@ -2324,7 +2296,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals, false); + err = b43_do_request_fw(ctx, filename, &fw->initvals); if (err) goto err_load; @@ -2383,7 +2355,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band); if (err) goto err_load; diff --git a/trunk/drivers/net/wireless/b43/main.h b/trunk/drivers/net/wireless/b43/main.h index abac25ee958d..8c684cd33529 100644 --- a/trunk/drivers/net/wireless/b43/main.h +++ b/trunk/drivers/net/wireless/b43/main.h @@ -137,8 +137,9 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); struct b43_request_fw_context; -int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw, bool async); +int b43_do_request_fw(struct b43_request_fw_context *ctx, + const char *name, + struct b43_firmware_file *fw); void b43_do_release_fw(struct b43_firmware_file *fw); #endif /* B43_MAIN_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 75464ad4fbd1..1261a9b84e04 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3091,11 +3091,10 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, len = wpa_ie->len + TLV_HDR_LEN; data = (u8 *)wpa_ie; - offset = TLV_HDR_LEN; + offset = 0; if (!is_rsn_ie) offset += VS_IE_FIXED_HDR_LEN; - else - offset += WPA_IE_VERSION_LEN; + offset += WPA_IE_VERSION_LEN; /* check for multicast cipher suite */ if (offset + WPA_IE_MIN_OUI_LEN > len) { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h b/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h index 822781cf15d4..796836b0f469 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/debug.h @@ -1,6 +1,5 @@ /* * Copyright (c) 2012 Broadcom Corporation - * Copyright (c) 2012 Canonical Ltd. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 0f71d1d4339d..1fbd8ecbe2ea 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1407,10 +1407,9 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) #endif t->ms = ms; t->periodic = (bool) periodic; - if (!t->set) { - t->set = true; - atomic_inc(&t->wl->callbacks); - } + t->set = true; + + atomic_inc(&t->wl->callbacks); ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 21a824232478..606b534347bc 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c @@ -1343,13 +1343,13 @@ static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain, wlc_lcnphy_rx_gain_override_enable(pi, true); wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0); - udelay(500); + usleep_range(500, 500); write_radio_reg(pi, RADIO_2064_REG112, 0); if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l)) return false; wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0); - udelay(500); + usleep_range(500, 500); write_radio_reg(pi, RADIO_2064_REG112, 0); if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h)) return false; diff --git a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c index 3726cd6fcd75..d604b4036a76 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c @@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, if (count) { char *p = buffer; - strlcpy(buffer, buf, sizeof(buffer)); + strncpy(buffer, buf, min(sizeof(buffer), count)); channel = simple_strtoul(p, NULL, 0); if (channel) params.channel = channel; diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index 90b8970eadf0..7e16d10a7f14 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -3958,21 +3958,17 @@ il_connection_init_rx_config(struct il_priv *il) memset(&il->staging, 0, sizeof(il->staging)); - switch (il->iw_mode) { - case NL80211_IFTYPE_UNSPECIFIED: + if (!il->vif) { il->staging.dev_type = RXON_DEV_TYPE_ESS; - break; - case NL80211_IFTYPE_STATION: + } else if (il->vif->type == NL80211_IFTYPE_STATION) { il->staging.dev_type = RXON_DEV_TYPE_ESS; il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - break; - case NL80211_IFTYPE_ADHOC: + } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { il->staging.dev_type = RXON_DEV_TYPE_IBSS; il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - break; - default: + } else { IL_ERR("Unsupported interface type %d\n", il->vif->type); return; } @@ -4554,7 +4550,8 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL(il_mac_add_interface); static void -il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) +il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, + bool mode_change) { lockdep_assert_held(&il->mutex); @@ -4563,7 +4560,9 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) il_force_scan_end(il); } - il_set_mode(il); + if (!mode_change) + il_set_mode(il); + } void @@ -4576,8 +4575,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) WARN_ON(il->vif != vif); il->vif = NULL; - il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; - il_teardown_interface(il, vif); + + il_teardown_interface(il, vif, false); memset(il->bssid, 0, ETH_ALEN); D_MAC80211("leave\n"); @@ -4686,10 +4685,18 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } /* success */ + il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - il->iw_mode = newtype; - il_teardown_interface(il, vif); + err = il_set_mode(il); + WARN_ON(err); + /* + * We've switched internally, but submitting to the + * device may have failed for some reason. Mask this + * error, because otherwise mac80211 will not switch + * (and set the interface type back) and we'll be + * out of sync with it. + */ err = 0; out: diff --git a/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c b/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c index 31534f7c0548..279796419ea0 100644 --- a/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/trunk/drivers/net/wireless/iwlwifi/dvm/tx.c @@ -1153,6 +1153,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, next_reclaimed = ssn; } + if (tid != IWL_TID_NON_QOS) { + priv->tid_data[sta_id][tid].next_reclaimed = + next_reclaimed; + IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", + next_reclaimed); + } + iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs); iwlagn_check_ratid_empty(priv, sta_id, tid); @@ -1203,28 +1210,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb, if (!is_agg) iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); - /* - * W/A for FW bug - the seq_ctl isn't updated when the - * queues are flushed. Fetch it from the packet itself - */ - if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) { - next_reclaimed = le16_to_cpu(hdr->seq_ctrl); - next_reclaimed = - SEQ_TO_SN(next_reclaimed + 0x10); - } - is_offchannel_skb = (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN); freed++; } - if (tid != IWL_TID_NON_QOS) { - priv->tid_data[sta_id][tid].next_reclaimed = - next_reclaimed; - IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n", - next_reclaimed); - } - WARN_ON(!is_agg && freed != 1); /* diff --git a/trunk/drivers/net/wireless/mwifiex/cfg80211.c b/trunk/drivers/net/wireless/mwifiex/cfg80211.c index cdb11b3964e2..a875499f8945 100644 --- a/trunk/drivers/net/wireless/mwifiex/cfg80211.c +++ b/trunk/drivers/net/wireless/mwifiex/cfg80211.c @@ -1459,7 +1459,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, struct cfg80211_ssid req_ssid; int ret, auth_type = 0; struct cfg80211_bss *bss = NULL; - u8 is_scanning_required = 0; + u8 is_scanning_required = 0, config_bands = 0; memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); @@ -1478,6 +1478,19 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, /* disconnect before try to associate */ mwifiex_deauthenticate(priv, NULL); + if (channel) { + if (mode == NL80211_IFTYPE_STATION) { + if (channel->band == IEEE80211_BAND_2GHZ) + config_bands = BAND_B | BAND_G | BAND_GN; + else + config_bands = BAND_A | BAND_AN; + + if (!((config_bands | priv->adapter->fw_bands) & + ~priv->adapter->fw_bands)) + priv->adapter->config_bands = config_bands; + } + } + /* As this is new association, clear locally stored * keys and security related flags */ priv->sec_info.wpa_enabled = false; @@ -1694,9 +1707,9 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, if (cfg80211_get_chandef_type(¶ms->chandef) != NL80211_CHAN_NO_HT) - config_bands |= BAND_G | BAND_GN; + config_bands |= BAND_GN; } else { - if (cfg80211_get_chandef_type(¶ms->chandef) == + if (cfg80211_get_chandef_type(¶ms->chandef) != NL80211_CHAN_NO_HT) config_bands = BAND_A; else diff --git a/trunk/drivers/net/wireless/mwifiex/pcie.c b/trunk/drivers/net/wireless/mwifiex/pcie.c index b879e1338a54..13fbc4eb1595 100644 --- a/trunk/drivers/net/wireless/mwifiex/pcie.c +++ b/trunk/drivers/net/wireless/mwifiex/pcie.c @@ -161,7 +161,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) if (pdev) { card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || !card->adapter) { + if (!card || card->adapter) { pr_err("Card or adapter structure is not valid\n"); return 0; } diff --git a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c index f542bb8ccbc8..cb682561c438 100644 --- a/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/trunk/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -56,6 +56,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, */ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) { + bool cancel_flag = false; int status; struct cmd_ctrl_node *cmd_queued; @@ -69,11 +70,14 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) atomic_inc(&adapter->cmd_pending); /* Wait for completion */ - status = wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (status) { - dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); - return status; + wait_event_interruptible(adapter->cmd_wait_q.wait, + *(cmd_queued->condition)); + if (!*(cmd_queued->condition)) + cancel_flag = true; + + if (cancel_flag) { + mwifiex_cancel_pending_ioctl(adapter); + dev_dbg(adapter->dev, "cmd cancel\n"); } status = adapter->cmd_wait_q.status; @@ -283,20 +287,6 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, if (ret) goto done; - if (bss_desc) { - u8 config_bands = 0; - - if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) - == HostCmd_SCAN_RADIO_TYPE_BG) - config_bands = BAND_B | BAND_G | BAND_GN; - else - config_bands = BAND_A | BAND_AN; - - if (!((config_bands | adapter->fw_bands) & - ~adapter->fw_bands)) - adapter->config_bands = config_bands; - } - ret = mwifiex_check_network_compatibility(priv, bss_desc); if (ret) goto done; @@ -506,11 +496,8 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return false; } - if (wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken)) { - dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); - return false; - } + wait_event_interruptible(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken); return true; } diff --git a/trunk/drivers/net/wireless/mwl8k.c b/trunk/drivers/net/wireless/mwl8k.c index 83564d36e801..f221b95b90b3 100644 --- a/trunk/drivers/net/wireless/mwl8k.c +++ b/trunk/drivers/net/wireless/mwl8k.c @@ -4250,11 +4250,9 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, p->amsdu_enabled = 0; rc = mwl8k_post_cmd(hw, &cmd->header); - if (!rc) - rc = p->station_id; kfree(cmd); - return rc; + return rc ? rc : p->station_id; } static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/p54/p54usb.c b/trunk/drivers/net/wireless/p54/p54usb.c index 800a16526c8e..e71c702e2eb1 100644 --- a/trunk/drivers/net/wireless/p54/p54usb.c +++ b/trunk/drivers/net/wireless/p54/p54usb.c @@ -47,7 +47,6 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ - {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ @@ -83,8 +82,6 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ {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, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ @@ -104,7 +101,6 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ - /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ diff --git a/trunk/drivers/net/wireless/rtlwifi/Kconfig b/trunk/drivers/net/wireless/rtlwifi/Kconfig index b80bc4612581..21b1bbb93a7e 100644 --- a/trunk/drivers/net/wireless/rtlwifi/Kconfig +++ b/trunk/drivers/net/wireless/rtlwifi/Kconfig @@ -57,12 +57,12 @@ config RTL8192CU config RTLWIFI tristate - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE default m config RTLWIFI_DEBUG bool "Additional debugging output" - depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE + depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE default y config RTL8192C_COMMON diff --git a/trunk/drivers/net/wireless/rtlwifi/pci.c b/trunk/drivers/net/wireless/rtlwifi/pci.c index 4261e8ecc4c3..3deacafdcd5e 100644 --- a/trunk/drivers/net/wireless/rtlwifi/pci.c +++ b/trunk/drivers/net/wireless/rtlwifi/pci.c @@ -743,8 +743,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) done: bufferaddress = (*((dma_addr_t *)skb->cb)); - if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) - return; tmp_one = 1; rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false, HW_DESC_RXBUFF_ADDR, @@ -1117,10 +1115,6 @@ static int _rtl_pci_init_rx_ring(struct ieee80211_hw *hw) PCI_DMA_FROMDEVICE); bufferaddress = (*((dma_addr_t *)skb->cb)); - if (pci_dma_mapping_error(rtlpci->pdev, bufferaddress)) { - dev_kfree_skb_any(skb); - return 1; - } rtlpriv->cfg->ops->set_desc((u8 *)entry, false, HW_DESC_RXBUFF_ADDR, (u8 *)&bufferaddress); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 246e5352f2e1..1d5d3604e3e0 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { rtl92c_phy_sw_chnl_callback(hw); RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schedule workitem\n"); + "sw_chnl_inprogress false schdule workitem\n"); rtlphy->sw_chnl_inprogress = false; } else { RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index c31795e379f7..173424756149 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c @@ -611,14 +611,8 @@ void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw, dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - u8 bw_40 = 0; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } rcu_read_lock(); sta = get_sta(hw, mac->vif, mac->bssid); if (mac->opmode == NL80211_IFTYPE_STATION) { @@ -780,11 +774,6 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); if (firstseg) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index a0fbf284420e..f9f3861046c1 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -587,11 +587,6 @@ void rtl92de_tx_fill_desc(struct ieee80211_hw *hw, buf_len = skb->len; mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d)); if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) { firstseg = true; @@ -745,11 +740,6 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); __le16 fc = hdr->frame_control; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); if (firstseg) SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 206561d7282f..0e9f6ebf078a 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -611,11 +611,6 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, PCI_DMA_TODEVICE); u8 bw_40 = 0; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } if (mac->opmode == NL80211_IFTYPE_STATION) { bw_40 = mac->bw_40; } else if (mac->opmode == NL80211_IFTYPE_AP || @@ -768,7 +763,6 @@ void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, bool lastseg, struct sk_buff *skb) { - struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); @@ -776,12 +770,7 @@ void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } - /* Clear all status */ + /* Clear all status */ CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); /* This bit indicate this packet is used for FW download. */ diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index 3d8536bb0d2b..39cc7938eedf 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c @@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw) if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { rtl8723ae_phy_sw_chnl_callback(hw); RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, - "sw_chnl_inprogress false schedule workitem\n"); + "sw_chnl_inprogress false schdule workitem\n"); rtlphy->sw_chnl_inprogress = false; } else { RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c index a313be8c21d2..87331d826d73 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8723ae/trx.c @@ -387,11 +387,6 @@ void rtl8723ae_tx_fill_desc(struct ieee80211_hw *hw, PCI_DMA_TODEVICE); u8 bw_40 = 0; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } if (mac->opmode == NL80211_IFTYPE_STATION) { bw_40 = mac->bw_40; } else if (mac->opmode == NL80211_IFTYPE_AP || @@ -547,11 +542,6 @@ void rtl8723ae_tx_fill_cmddesc(struct ieee80211_hw *hw, PCI_DMA_TODEVICE); __le16 fc = hdr->frame_control; - if (pci_dma_mapping_error(rtlpci->pdev, mapping)) { - RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, - "DMA mapping error"); - return; - } CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE); if (firstseg) diff --git a/trunk/drivers/net/wireless/rtlwifi/usb.c b/trunk/drivers/net/wireless/rtlwifi/usb.c index f2ecdeb3a90d..29f0969e4ba0 100644 --- a/trunk/drivers/net/wireless/rtlwifi/usb.c +++ b/trunk/drivers/net/wireless/rtlwifi/usb.c @@ -210,16 +210,17 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 index = REALTEK_USB_VENQT_CMD_IDX; int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ u8 *buffer; + dma_addr_t dma_addr; - wvalue = (u16)(addr & 0x0000ffff); - buffer = kmalloc(len, GFP_ATOMIC); + wvalue = (u16)(addr&0x0000ffff); + buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); if (!buffer) return; memcpy(buffer, data, len); usb_control_msg(udev, pipe, request, reqtype, wvalue, index, buffer, len, 50); - kfree(buffer); + usb_free_coherent(udev, (size_t)len, buffer, dma_addr); } static void _rtl_usb_io_handler_init(struct device *dev, @@ -639,7 +640,6 @@ static int _rtl_usb_receive(struct ieee80211_hw *hw) RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG, "Failed to prep_rx_urb!!\n"); err = PTR_ERR(skb); - usb_free_urb(urb); goto err_out; } diff --git a/trunk/drivers/ssb/Kconfig b/trunk/drivers/ssb/Kconfig index 5d6f2ec1c705..ff3c8a21f10d 100644 --- a/trunk/drivers/ssb/Kconfig +++ b/trunk/drivers/ssb/Kconfig @@ -162,7 +162,8 @@ config SSB_DRIVER_GIGE config SSB_DRIVER_GPIO bool "SSB GPIO driver" - depends on SSB && GPIOLIB + depends on SSB + select GPIOLIB help Driver to provide access to the GPIO pins on the bus. diff --git a/trunk/net/bluetooth/hci_core.c b/trunk/net/bluetooth/hci_core.c index 0f78e34220c9..596660d37c5e 100644 --- a/trunk/net/bluetooth/hci_core.c +++ b/trunk/net/bluetooth/hci_core.c @@ -2810,6 +2810,14 @@ static void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) if (conn) { hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF); + hci_dev_lock(hdev); + if (test_bit(HCI_MGMT, &hdev->dev_flags) && + !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) + mgmt_device_connected(hdev, &conn->dst, conn->type, + conn->dst_type, 0, NULL, 0, + conn->dev_class); + hci_dev_unlock(hdev); + /* Send to upper protocol */ l2cap_recv_acldata(conn, skb, flags); return; diff --git a/trunk/net/bluetooth/hci_event.c b/trunk/net/bluetooth/hci_event.c index 81b44481d0d9..705078a0cc39 100644 --- a/trunk/net/bluetooth/hci_event.c +++ b/trunk/net/bluetooth/hci_event.c @@ -2688,7 +2688,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { + if (ev->ncmd) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) queue_work(hdev->workqueue, &hdev->cmd_work); diff --git a/trunk/net/bluetooth/hidp/core.c b/trunk/net/bluetooth/hidp/core.c index a7352ff3fd1e..b2bcbe2dc328 100644 --- a/trunk/net/bluetooth/hidp/core.c +++ b/trunk/net/bluetooth/hidp/core.c @@ -931,7 +931,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid->version = req->version; hid->country = req->country; - strncpy(hid->name, req->name, sizeof(req->name) - 1); + strncpy(hid->name, req->name, 128); snprintf(hid->phys, sizeof(hid->phys), "%pMR", &bt_sk(session->ctrl_sock->sk)->src); diff --git a/trunk/net/bluetooth/l2cap_core.c b/trunk/net/bluetooth/l2cap_core.c index 22e658322845..2c78208d793e 100644 --- a/trunk/net/bluetooth/l2cap_core.c +++ b/trunk/net/bluetooth/l2cap_core.c @@ -3727,17 +3727,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, static int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) { - struct hci_dev *hdev = conn->hcon->hdev; - struct hci_conn *hcon = conn->hcon; - - hci_dev_lock(hdev); - if (test_bit(HCI_MGMT, &hdev->dev_flags) && - !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) - mgmt_device_connected(hdev, &hcon->dst, hcon->type, - hcon->dst_type, 0, NULL, 0, - hcon->dev_class); - hci_dev_unlock(hdev); - l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); return 0; } diff --git a/trunk/net/bluetooth/sco.c b/trunk/net/bluetooth/sco.c index 57f250c20e39..531a93d613d4 100644 --- a/trunk/net/bluetooth/sco.c +++ b/trunk/net/bluetooth/sco.c @@ -352,7 +352,7 @@ static void __sco_sock_close(struct sock *sk) case BT_CONNECTED: case BT_CONFIG: - if (sco_pi(sk)->conn->hcon) { + if (sco_pi(sk)->conn) { sk->sk_state = BT_DISCONN; sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT); hci_conn_put(sco_pi(sk)->conn->hcon); diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index 516fbc96feff..5c61677487cf 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -164,17 +164,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sta = sta_info_get(sdata, mac_addr); else sta = sta_info_get_bss(sdata, mac_addr); - /* - * The ASSOC test makes sure the driver is ready to - * receive the key. When wpa_supplicant has roamed - * using FT, it attempts to set the key before - * association has completed, this rejects that attempt - * so it will set the key again after assocation. - * - * TODO: accept the key if we have a station entry and - * add it to the device after the station. - */ - if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { + if (!sta) { ieee80211_key_free(sdata->local, key); err = -ENOENT; goto out_unlock; @@ -1019,8 +1009,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) if (old_probe_resp) kfree_rcu(old_probe_resp, rcu_head); - list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) - sta_info_flush(local, vlan); sta_info_flush(local, sdata); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); diff --git a/trunk/net/mac80211/chan.c b/trunk/net/mac80211/chan.c index 80e55527504b..53f03120db55 100644 --- a/trunk/net/mac80211/chan.c +++ b/trunk/net/mac80211/chan.c @@ -4,7 +4,6 @@ #include #include -#include #include #include "ieee80211_i.h" #include "driver-ops.h" @@ -198,15 +197,6 @@ 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); @@ -326,15 +316,6 @@ 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); @@ -350,25 +331,6 @@ void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) mutex_unlock(&sdata->local->chanctx_mtx); } -void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata) -{ - struct ieee80211_local *local = sdata->local; - struct ieee80211_sub_if_data *ap; - struct ieee80211_chanctx_conf *conf; - - if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss)) - return; - - ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap); - - mutex_lock(&local->chanctx_mtx); - - conf = rcu_dereference_protected(ap->vif.chanctx_conf, - lockdep_is_held(&local->chanctx_mtx)); - rcu_assign_pointer(sdata->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/ibss.c b/trunk/net/mac80211/ibss.c index 6b7644e818d8..8881fc77fb13 100644 --- a/trunk/net/mac80211/ibss.c +++ b/trunk/net/mac80211/ibss.c @@ -703,8 +703,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) sdata_info(sdata, "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n"); - ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, - NULL); + ieee80211_request_internal_scan(sdata, + ifibss->ssid, ifibss->ssid_len, NULL); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -802,8 +802,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) IEEE80211_SCAN_INTERVAL)) { sdata_info(sdata, "Trigger new scan to find an IBSS to join\n"); - ieee80211_request_ibss_scan(sdata, ifibss->ssid, - ifibss->ssid_len, chan); + ieee80211_request_internal_scan(sdata, + ifibss->ssid, ifibss->ssid_len, + ifibss->fixed_channel ? ifibss->channel : NULL); } else { int interval = IEEE80211_SCAN_INTERVAL; diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 2ed065c09562..42d0d0267730 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -92,6 +92,8 @@ struct ieee80211_bss { u32 device_ts; + u8 dtim_period; + bool wmm_used; bool uapsd_supported; @@ -138,6 +140,7 @@ enum ieee80211_bss_corrupt_data_flags { /** * enum ieee80211_valid_data_flags - BSS valid data flags + * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE @@ -148,6 +151,7 @@ enum ieee80211_bss_corrupt_data_flags { * beacon/probe response. */ enum ieee80211_bss_valid_data_flags { + IEEE80211_BSS_VALID_DTIM = BIT(0), IEEE80211_BSS_VALID_WMM = BIT(1), IEEE80211_BSS_VALID_RATES = BIT(2), IEEE80211_BSS_VALID_ERP = BIT(3) @@ -436,7 +440,6 @@ struct ieee80211_if_managed { unsigned long timers_running; /* used for quiesce/restart */ bool powersave; /* powersave requested for this iface */ bool broken_ap; /* AP is broken -- turn off powersave */ - u8 dtim_period; enum ieee80211_smps_mode req_smps, /* requested smps mode */ driver_smps_mode; /* smps mode request */ @@ -770,10 +773,6 @@ struct ieee80211_sub_if_data { u32 mntr_flags; } u; - spinlock_t cleanup_stations_lock; - struct list_head cleanup_stations; - struct work_struct cleanup_stations_wk; - #ifdef CONFIG_MAC80211_DEBUGFS struct { struct dentry *dir; @@ -1330,9 +1329,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); -int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan); +int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); @@ -1358,8 +1357,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); -void ieee80211_offchannel_return(struct ieee80211_local *local); +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, + bool offchannel_ps_enable); +void ieee80211_offchannel_return(struct ieee80211_local *local, + bool offchannel_ps_disable); void ieee80211_roc_setup(struct ieee80211_local *local); void ieee80211_start_next_roc(struct ieee80211_local *local); void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); @@ -1627,7 +1628,6 @@ ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, const struct cfg80211_chan_def *chandef, 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_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 8be854e86cd9..09a80b55cf5a 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -207,8 +207,17 @@ void ieee80211_recalc_idle(struct ieee80211_local *local) static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) { - if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN) + int meshhdrlen; + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + + meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; + + /* FIX: what would be proper limits for MTU? + * This interface uses 802.3 frames. */ + if (new_mtu < 256 || + new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { return -EINVAL; + } dev->mtu = new_mtu; return 0; @@ -577,13 +586,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: - /* no need to tell driver, but set carrier and chanctx */ - if (rtnl_dereference(sdata->bss->beacon)) { - ieee80211_vif_vlan_copy_chanctx(sdata); + /* no need to tell driver, but set carrier */ + if (rtnl_dereference(sdata->bss->beacon)) netif_carrier_on(dev); - } else { + else netif_carrier_off(dev); - } break; case NL80211_IFTYPE_MONITOR: if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { @@ -832,7 +839,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, switch (sdata->vif.type) { case NL80211_IFTYPE_AP_VLAN: list_del(&sdata->u.vlan.list); - rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); /* no need to tell driver */ break; case NL80211_IFTYPE_MONITOR: @@ -859,11 +865,20 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, cancel_work_sync(&sdata->work); /* * When we get here, the interface is marked down. - * Call synchronize_rcu() to wait for the RX path + * Call rcu_barrier() to wait both for the RX path * should it be using the interface and enqueuing - * frames at this very time on another CPU. + * frames at this very time on another CPU, and + * for the sta free call_rcu callbacks. + */ + rcu_barrier(); + + /* + * free_sta_rcu() enqueues a work for the actual + * sta cleanup, so we need to flush it while + * sdata is still valid. */ - synchronize_rcu(); + flush_workqueue(local->workqueue); + skb_queue_purge(&sdata->skb_queue); /* @@ -1483,15 +1498,6 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } -static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk); - - ieee80211_cleanup_sdata_stas(sdata); -} - int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct wireless_dev **new_wdev, enum nl80211_iftype type, struct vif_params *params) @@ -1567,10 +1573,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, INIT_LIST_HEAD(&sdata->key_list); - spin_lock_init(&sdata->cleanup_stations_lock); - INIT_LIST_HEAD(&sdata->cleanup_stations); - INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk); - for (i = 0; i < IEEE80211_NUM_BANDS; i++) { struct ieee80211_supported_band *sband; sband = local->hw.wiphy->bands[i]; diff --git a/trunk/net/mac80211/mesh.c b/trunk/net/mac80211/mesh.c index 649ad513547f..1bf03f9ff3ba 100644 --- a/trunk/net/mac80211/mesh.c +++ b/trunk/net/mac80211/mesh.c @@ -163,7 +163,7 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) return -ENOMEM; sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; for (i = 0; i < RMC_BUCKETS; i++) - INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]); + INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); return 0; } @@ -177,7 +177,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) return; for (i = 0; i < RMC_BUCKETS; i++) - list_for_each_entry_safe(p, n, &rmc->bucket[i], list) { + list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) { list_del(&p->list); kmem_cache_free(rm_cache, p); } @@ -210,7 +210,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, /* Don't care about endianness since only match matters */ memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum)); idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask; - list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) { + list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) { ++entries; if (time_after(jiffies, p->exp_time) || (entries == RMC_QUEUE_MAX_LEN)) { @@ -229,7 +229,7 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, p->seqnum = seqnum; p->exp_time = jiffies + RMC_TIMEOUT; memcpy(p->sa, sa, ETH_ALEN); - list_add(&p->list, &rmc->bucket[idx]); + list_add(&p->list, &rmc->bucket[idx].list); return 0; } diff --git a/trunk/net/mac80211/mesh.h b/trunk/net/mac80211/mesh.h index 84c28c6101cd..7c9215fb2ac8 100644 --- a/trunk/net/mac80211/mesh.h +++ b/trunk/net/mac80211/mesh.h @@ -184,7 +184,7 @@ struct rmc_entry { }; struct mesh_rmc { - struct list_head bucket[RMC_BUCKETS]; + struct rmc_entry bucket[RMC_BUCKETS]; u32 idx_mask; }; diff --git a/trunk/net/mac80211/mesh_hwmp.c b/trunk/net/mac80211/mesh_hwmp.c index 2659e428b80c..47aeee2d8db1 100644 --- a/trunk/net/mac80211/mesh_hwmp.c +++ b/trunk/net/mac80211/mesh_hwmp.c @@ -215,7 +215,6 @@ static void prepare_frame_for_deferred_tx(struct ieee80211_sub_if_data *sdata, skb->priority = 7; info->control.vif = &sdata->vif; - info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; ieee80211_set_qos_hdr(sdata, skb); } @@ -247,13 +246,11 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, return -EAGAIN; skb = dev_alloc_skb(local->tx_headroom + - IEEE80211_ENCRYPT_HEADROOM + - IEEE80211_ENCRYPT_TAILROOM + hdr_len + 2 + 15 /* PERR IE */); if (!skb) return -1; - skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM); + skb_reserve(skb, local->tx_headroom); mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); memset(mgmt, 0, hdr_len); mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | diff --git a/trunk/net/mac80211/mlme.c b/trunk/net/mac80211/mlme.c index a3552929a21d..7753a9ca98a6 100644 --- a/trunk/net/mac80211/mlme.c +++ b/trunk/net/mac80211/mlme.c @@ -1074,8 +1074,12 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) if (beaconint_us > latency) { local->ps_sdata = NULL; } else { + struct ieee80211_bss *bss; int maxslp = 1; - u8 dtimper = found->u.mgd.dtim_period; + u8 dtimper; + + bss = (void *)found->u.mgd.associated->priv; + dtimper = bss->dtim_period; /* If the TIM IE is invalid, pretend the value is 1 */ if (!dtimper) @@ -1406,17 +1410,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, ieee80211_led_assoc(local, 1); - 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 - * in that case, although if the TIM IE is broken powersave - * probably just won't work at all. - */ - bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1; - } else { + if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) + bss_conf->dtim_period = bss->dtim_period; + else bss_conf->dtim_period = 0; - } bss_conf->assoc = 1; @@ -1565,8 +1562,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, sdata->u.mgd.timers_running = 0; - sdata->vif.bss_conf.dtim_period = 0; - ifmgd->flags = 0; ieee80211_vif_release_channel(sdata); } @@ -2378,18 +2373,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, struct ieee80211_channel *channel; bool need_ps = false; - if ((sdata->u.mgd.associated && - ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) || - (sdata->u.mgd.assoc_data && - ether_addr_equal(mgmt->bssid, - sdata->u.mgd.assoc_data->bss->bssid))) { + if (sdata->u.mgd.associated && + ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) { + bss = (void *)sdata->u.mgd.associated->priv; /* not previously set so we may need to recalc */ - need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period; - - if (elems->tim && !elems->parse_error) { - struct ieee80211_tim_ie *tim_ie = elems->tim; - sdata->u.mgd.dtim_period = tim_ie->dtim_period; - } + need_ps = !bss->dtim_period; } if (elems->ds_params && elems->ds_params_len == 1) @@ -3908,41 +3896,20 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, /* kick off associate process */ ifmgd->assoc_data = assoc_data; - ifmgd->dtim_period = 0; err = ieee80211_prep_connection(sdata, req->bss, true); if (err) goto err_clear; - if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { - const struct cfg80211_bss_ies *beacon_ies; - - 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(); + if (!bss->dtim_period && + sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) { + /* + * 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 { assoc_data->have_beacon = true; assoc_data->sent_assoc = false; diff --git a/trunk/net/mac80211/offchannel.c b/trunk/net/mac80211/offchannel.c index a3ad4c3c80a3..a5379aea7d09 100644 --- a/trunk/net/mac80211/offchannel.c +++ b/trunk/net/mac80211/offchannel.c @@ -102,7 +102,8 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) ieee80211_sta_reset_conn_monitor(sdata); } -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, + bool offchannel_ps_enable) { struct ieee80211_sub_if_data *sdata; @@ -133,7 +134,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { netif_tx_stop_all_queues(sdata->dev); - if (sdata->vif.type == NL80211_IFTYPE_STATION && + if (offchannel_ps_enable && + (sdata->vif.type == NL80211_IFTYPE_STATION) && sdata->u.mgd.associated) ieee80211_offchannel_ps_enable(sdata); } @@ -141,7 +143,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) mutex_unlock(&local->iflist_mtx); } -void ieee80211_offchannel_return(struct ieee80211_local *local) +void ieee80211_offchannel_return(struct ieee80211_local *local, + bool offchannel_ps_disable) { struct ieee80211_sub_if_data *sdata; @@ -160,9 +163,11 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) continue; /* Tell AP we're back */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); + if (offchannel_ps_disable && + sdata->vif.type == NL80211_IFTYPE_STATION) { + if (sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); + } if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { /* @@ -380,7 +385,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) local->tmp_channel = NULL; ieee80211_hw_config(local, 0); - ieee80211_offchannel_return(local); + ieee80211_offchannel_return(local, true); } ieee80211_recalc_idle(local); diff --git a/trunk/net/mac80211/scan.c b/trunk/net/mac80211/scan.c index bf82e69d0601..8ed83dcc149f 100644 --- a/trunk/net/mac80211/scan.c +++ b/trunk/net/mac80211/scan.c @@ -113,6 +113,18 @@ ieee80211_bss_info_update(struct ieee80211_local *local, bss->valid_data |= IEEE80211_BSS_VALID_ERP; } + if (elems->tim && (!elems->parse_error || + !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) { + struct ieee80211_tim_ie *tim_ie = elems->tim; + bss->dtim_period = tim_ie->dtim_period; + if (!elems->parse_error) + bss->valid_data |= IEEE80211_BSS_VALID_DTIM; + } + + /* If the beacon had no TIM IE, or it was invalid, use 1 */ + if (beacon && !bss->dtim_period) + bss->dtim_period = 1; + /* replace old supported rates if we get new values */ if (!elems->parse_error || !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) { @@ -292,7 +304,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (!was_hw_scan) { ieee80211_configure_filter(local); drv_sw_scan_complete(local); - ieee80211_offchannel_return(local); + ieee80211_offchannel_return(local, true); } ieee80211_recalc_idle(local); @@ -341,7 +353,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; - ieee80211_offchannel_stop_vifs(local); + ieee80211_offchannel_stop_vifs(local, true); ieee80211_configure_filter(local); @@ -678,8 +690,12 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - /* disable PS */ - ieee80211_offchannel_return(local); + /* + * Re-enable vifs and beaconing. Leave PS + * in off-channel state..will put that back + * on-channel at the end of scanning. + */ + ieee80211_offchannel_return(local, false); *next_delay = HZ / 5; /* afterwards, resume scan & go to next channel */ @@ -689,7 +705,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, static void ieee80211_scan_state_resume(struct ieee80211_local *local, unsigned long *next_delay) { - ieee80211_offchannel_stop_vifs(local); + /* PS already is in off-channel mode */ + ieee80211_offchannel_stop_vifs(local, false); if (local->ops->flush) { drv_flush(local, false); @@ -815,9 +832,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, return res; } -int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan) +int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan) { struct ieee80211_local *local = sdata->local; int ret = -EBUSY; @@ -831,36 +848,22 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, /* fill internal scan request */ if (!chan) { - int i, max_n; - int n_ch = 0; + int i, nchan = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; - - max_n = local->hw.wiphy->bands[band]->n_channels; - for (i = 0; i < max_n; i++) { - struct ieee80211_channel *tmp_ch = + for (i = 0; + i < local->hw.wiphy->bands[band]->n_channels; + i++) { + local->int_scan_req->channels[nchan] = &local->hw.wiphy->bands[band]->channels[i]; - - if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_DISABLED)) - continue; - - local->int_scan_req->channels[n_ch] = tmp_ch; - n_ch++; + nchan++; } } - if (WARN_ON_ONCE(n_ch == 0)) - goto unlock; - - local->int_scan_req->n_channels = n_ch; + local->int_scan_req->n_channels = nchan; } else { - if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_DISABLED))) - goto unlock; - local->int_scan_req->channels[0] = chan; local->int_scan_req->n_channels = 1; } diff --git a/trunk/net/mac80211/sta_info.c b/trunk/net/mac80211/sta_info.c index ca9fde198188..f3e502502fee 100644 --- a/trunk/net/mac80211/sta_info.c +++ b/trunk/net/mac80211/sta_info.c @@ -91,8 +91,9 @@ static int sta_info_hash_del(struct ieee80211_local *local, return -ENOENT; } -static void cleanup_single_sta(struct sta_info *sta) +static void free_sta_work(struct work_struct *wk) { + struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk); int ac, i; struct tid_ampdu_tx *tid_tx; struct ieee80211_sub_if_data *sdata = sta->sdata; @@ -152,35 +153,11 @@ static void cleanup_single_sta(struct sta_info *sta) sta_info_free(local, sta); } -void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata) -{ - struct sta_info *sta; - - spin_lock_bh(&sdata->cleanup_stations_lock); - while (!list_empty(&sdata->cleanup_stations)) { - sta = list_first_entry(&sdata->cleanup_stations, - struct sta_info, list); - list_del(&sta->list); - spin_unlock_bh(&sdata->cleanup_stations_lock); - - cleanup_single_sta(sta); - - spin_lock_bh(&sdata->cleanup_stations_lock); - } - - spin_unlock_bh(&sdata->cleanup_stations_lock); -} - static void free_sta_rcu(struct rcu_head *h) { struct sta_info *sta = container_of(h, struct sta_info, rcu_head); - struct ieee80211_sub_if_data *sdata = sta->sdata; - spin_lock(&sdata->cleanup_stations_lock); - list_add_tail(&sta->list, &sdata->cleanup_stations); - spin_unlock(&sdata->cleanup_stations_lock); - - ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk); + ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk); } /* protected by RCU */ @@ -333,6 +310,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, spin_lock_init(&sta->lock); INIT_WORK(&sta->drv_unblock_wk, sta_unblock); + INIT_WORK(&sta->free_sta_wk, free_sta_work); INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); mutex_init(&sta->ampdu_mlme.mtx); @@ -884,7 +862,7 @@ void sta_info_init(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { - del_timer_sync(&local->sta_cleanup); + del_timer(&local->sta_cleanup); sta_info_flush(local, NULL); } @@ -913,20 +891,6 @@ int sta_info_flush(struct ieee80211_local *local, } mutex_unlock(&local->sta_mtx); - rcu_barrier(); - - if (sdata) { - ieee80211_cleanup_sdata_stas(sdata); - cancel_work_sync(&sdata->cleanup_stations_wk); - } else { - mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - ieee80211_cleanup_sdata_stas(sdata); - cancel_work_sync(&sdata->cleanup_stations_wk); - } - mutex_unlock(&local->iflist_mtx); - } - return ret; } diff --git a/trunk/net/mac80211/sta_info.h b/trunk/net/mac80211/sta_info.h index 37c1889afd3a..1489bca9ea97 100644 --- a/trunk/net/mac80211/sta_info.h +++ b/trunk/net/mac80211/sta_info.h @@ -299,6 +299,7 @@ struct sta_info { spinlock_t lock; struct work_struct drv_unblock_wk; + struct work_struct free_sta_wk; u16 listen_interval; @@ -562,6 +563,4 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); -void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata); - #endif /* STA_INFO_H */ diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index 467c1d1b66f2..e9eadc40c09c 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -1673,14 +1673,11 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, chanctx_conf = rcu_dereference(tmp_sdata->vif.chanctx_conf); } - - if (chanctx_conf) - chan = chanctx_conf->def.chan; - else if (!local->use_chanctx) - chan = local->_oper_channel; - else + if (!chanctx_conf) goto fail_rcu; + chan = chanctx_conf->def.chan; + /* * Frame injection is not allowed if beaconing is not allowed * or if we need radar detection. Beaconing is usually not allowed when diff --git a/trunk/net/wireless/scan.c b/trunk/net/wireless/scan.c index 45f1618c8e23..01592d7d4789 100644 --- a/trunk/net/wireless/scan.c +++ b/trunk/net/wireless/scan.c @@ -1358,7 +1358,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, &iwe, IW_EV_UINT_LEN); } - buf = kmalloc(31, GFP_ATOMIC); + buf = kmalloc(30, GFP_ATOMIC); if (buf) { memset(&iwe, 0, sizeof(iwe)); iwe.cmd = IWEVCUSTOM;