* fix IBSS which got broken over time
 * new USB id for bcm43242 dongle
 * arp offload configuration through inet notifier
 
 ath9k
 
 * add random number generator support (CONFIG_ATH9K_HWRNG)
 
 iwlwifi
 
 * Make scan parameters low latency aware
 * Fix in the NL80211_FEATURE_FULL_AP_CLIENT_STATE state case
 * Fix enable injection mode (Chaya Rachel)
 * Various cleanups (Dan / Julia / myself)
 * Allow to stay more time on popular channels (David Spinadel)
 * Bug fixes for D0i3 (Eliad / Luca)
 * Fixes for GO uAPSD (myself)
 * Start of TSO support (myself)
 * Rate control bug fixes (Eyal / Gregory)
 * Start the work on 9000 devices (Johannes / Sara / Oren)
 * Start the work on a new Tx queue allocation model (Liad)
 * Debug infrastructure enhancements (Golan)
 
 mwifiex
 
 * add a debugfs file for chip reset
 * advertise SMS4 cipher suite
 * increase ap and station interface limit to 3
 * enable MSI support on newer pcie devices (8897 onwards)
 
 rtlwifi
 
 * fix lots of module parameter usage
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQEcBAABAgAGBQJWi5RxAAoJEG4XJFUm622bujQH/Rti4fRBnJcRt5EZAv/pvdIx
 AGPcYQQfFbFRjzxjrcY30AYCC6OoID9n7BNtELIWabA6dQHWGJd2aebZGH85O4Eh
 xgAty5CRf9E4+9MNiv+OqkL64/E6/YmSeOYiNSWl6SgRE4VYmexLXttpppImmoER
 zowmtqzLSN/4l4yX5p2BVy3NAXN0R1WjYKNUXAJvJj59814upXf+XrOKCghzHIs4
 2NE/aFoscscKWCSS3+MIIW4q9QWw7f8YvAdrO6k47LLkjm4+C/I5BeAlHUOEQUS7
 xyoB/7KoHXlzRen8LmoL9SsqopTL2tKEjE/1f0QgLKOHXqpPRb4iKBFjsR94HJg=
 =aeCM
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-for-davem-2016-01-05' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
brcfmac

* fix IBSS which got broken over time
* new USB id for bcm43242 dongle
* arp offload configuration through inet notifier

ath9k

* add random number generator support (CONFIG_ATH9K_HWRNG)

iwlwifi

* Make scan parameters low latency aware
* Fix in the NL80211_FEATURE_FULL_AP_CLIENT_STATE state case
* Fix enable injection mode (Chaya Rachel)
* Various cleanups (Dan / Julia / myself)
* Allow to stay more time on popular channels (David Spinadel)
* Bug fixes for D0i3 (Eliad / Luca)
* Fixes for GO uAPSD (myself)
* Start of TSO support (myself)
* Rate control bug fixes (Eyal / Gregory)
* Start the work on 9000 devices (Johannes / Sara / Oren)
* Start the work on a new Tx queue allocation model (Liad)
* Debug infrastructure enhancements (Golan)

mwifiex

* add a debugfs file for chip reset
* advertise SMS4 cipher suite
* increase ap and station interface limit to 3
* enable MSI support on newer pcie devices (8897 onwards)

rtlwifi

* fix lots of module parameter usage
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-01-06 00:05:04 -05:00
commit 56b87180cc
184 changed files with 3890 additions and 1885 deletions

View File

@ -101,50 +101,13 @@ static void bcm47xx_machine_halt(void)
}
#ifdef CONFIG_BCM47XX_SSB
static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv)
{
char buf[20];
int len, err;
/* Fill boardinfo structure */
memset(&iv->boardinfo, 0 , sizeof(struct ssb_boardinfo));
len = bcm47xx_nvram_getenv("boardvendor", buf, sizeof(buf));
if (len > 0) {
err = kstrtou16(strim(buf), 0, &iv->boardinfo.vendor);
if (err)
pr_warn("Couldn't parse nvram board vendor entry with value \"%s\"\n",
buf);
}
if (!iv->boardinfo.vendor)
iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
len = bcm47xx_nvram_getenv("boardtype", buf, sizeof(buf));
if (len > 0) {
err = kstrtou16(strim(buf), 0, &iv->boardinfo.type);
if (err)
pr_warn("Couldn't parse nvram board type entry with value \"%s\"\n",
buf);
}
memset(&iv->sprom, 0, sizeof(struct ssb_sprom));
bcm47xx_fill_sprom(&iv->sprom, NULL, false);
if (bcm47xx_nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
return 0;
}
static void __init bcm47xx_register_ssb(void)
{
int err;
char buf[100];
struct ssb_mipscore *mcore;
err = ssb_bus_ssbbus_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE,
bcm47xx_get_invariants);
err = ssb_bus_host_soc_register(&bcm47xx_bus.ssb, SSB_ENUM_BASE);
if (err)
panic("Failed to initialize SSB bus (err %d)", err);

View File

@ -668,11 +668,36 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
core->id.rev, core->id.class);
}
static unsigned int bcma_bus_registered;
/*
* If built-in, bus has to be registered early, before any driver calls
* bcma_driver_register.
* Otherwise registering driver would trigger BUG in driver_register.
*/
static int __init bcma_init_bus_register(void)
{
int err;
if (bcma_bus_registered)
return 0;
err = bus_register(&bcma_bus_type);
if (!err)
bcma_bus_registered = 1;
return err;
}
#ifndef MODULE
fs_initcall(bcma_init_bus_register);
#endif
/* Main initialization has to be done with SPI/mtd/NAND/SPROM available */
static int __init bcma_modinit(void)
{
int err;
err = bus_register(&bcma_bus_type);
err = bcma_init_bus_register();
if (err)
return err;
@ -691,7 +716,7 @@ static int __init bcma_modinit(void)
return err;
}
fs_initcall(bcma_modinit);
module_init(bcma_modinit);
static void __exit bcma_modexit(void)
{

View File

@ -1139,7 +1139,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
{
struct ath10k *ar = file->private_data;
char buf[64];
u8 amsdu = 3, ampdu = 64;
u8 amsdu, ampdu;
unsigned int len;
mutex_lock(&ar->conf_mutex);

View File

@ -250,7 +250,8 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
if (WARN_ON(arvif->vif->type != NL80211_IFTYPE_AP &&
arvif->vif->type != NL80211_IFTYPE_ADHOC))
arvif->vif->type != NL80211_IFTYPE_ADHOC &&
arvif->vif->type != NL80211_IFTYPE_MESH_POINT))
return -EINVAL;
spin_lock_bh(&ar->data_lock);

View File

@ -4312,34 +4312,58 @@ void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
}
static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len)
static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len)
{
dma_addr_t paddr;
u32 pool_size;
u32 pool_size = 0;
int idx = ar->wmi.num_mem_chunks;
void *vaddr = NULL;
pool_size = num_units * round_up(unit_len, 4);
if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
return -ENOMEM;
if (!pool_size)
return -EINVAL;
while (!vaddr && num_units) {
pool_size = num_units * round_up(unit_len, 4);
if (!pool_size)
return -EINVAL;
ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
pool_size,
&paddr,
GFP_KERNEL);
if (!ar->wmi.mem_chunks[idx].vaddr) {
ath10k_warn(ar, "failed to allocate memory chunk\n");
vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
if (!vaddr)
num_units /= 2;
}
if (!num_units)
return -ENOMEM;
paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
if (dma_mapping_error(ar->dev, paddr)) {
kfree(vaddr);
return -ENOMEM;
}
memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size);
ar->wmi.mem_chunks[idx].vaddr = vaddr;
ar->wmi.mem_chunks[idx].paddr = paddr;
ar->wmi.mem_chunks[idx].len = pool_size;
ar->wmi.mem_chunks[idx].req_id = req_id;
ar->wmi.num_mem_chunks++;
return num_units;
}
static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len)
{
int ret;
while (num_units) {
ret = ath10k_wmi_alloc_chunk(ar, req_id, num_units, unit_len);
if (ret < 0)
return ret;
num_units -= ret;
}
return 0;
}
@ -7717,10 +7741,11 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
/* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
dma_free_coherent(ar->dev,
ar->wmi.mem_chunks[i].len,
ar->wmi.mem_chunks[i].vaddr,
ar->wmi.mem_chunks[i].paddr);
dma_unmap_single(ar->dev,
ar->wmi.mem_chunks[i].paddr,
ar->wmi.mem_chunks[i].len,
DMA_TO_DEVICE);
kfree(ar->wmi.mem_chunks[i].vaddr);
}
ar->wmi.num_mem_chunks = 0;

View File

@ -767,7 +767,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
flags |= AR5K_TXDESC_NOACK;
rc_flags = info->control.rates[0].flags;
rc_flags = bf->rates[0].flags;
hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0);

View File

@ -3930,8 +3930,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ar->hw.tx_ant = 2;
ar->hw.rx_ant = 2;
ar->hw.tx_ant = 0x3; /* mask, 2 antenna */
ar->hw.rx_ant = 0x3;
} else {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;

View File

@ -2222,8 +2222,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
}
if (status) {
ath6kl_err("failed to get pending recv messages: %d\n",
status);
if (status != -ECANCELED)
ath6kl_err("failed to get pending recv messages: %d\n",
status);
/* cleanup any packets in sync completion queue */
list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) {

View File

@ -954,8 +954,10 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name);
ret = request_firmware(&fw, filename, ar->dev);
if (ret)
if (ret) {
ath6kl_err("Failed request firmware, rv: %d\n", ret);
return ret;
}
data = fw->data;
len = fw->size;
@ -964,11 +966,15 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
if (len < magic_len) {
ath6kl_err("Magic length is invalid, len: %zd magic_len: %zd\n",
len, magic_len);
ret = -EINVAL;
goto out;
}
if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
ath6kl_err("Magic is invalid, magic_len: %zd\n",
magic_len);
ret = -EINVAL;
goto out;
}
@ -987,7 +993,12 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
len -= sizeof(*hdr);
data += sizeof(*hdr);
ath6kl_dbg(ATH6KL_DBG_BOOT, "ie-id: %d len: %zd (0x%zx)\n",
ie_id, ie_len, ie_len);
if (len < ie_len) {
ath6kl_err("IE len is invalid, len: %zd ie_len: %zd ie-id: %d\n",
len, ie_len, ie_id);
ret = -EINVAL;
goto out;
}
@ -1008,6 +1019,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
if (ar->fw_otp == NULL) {
ath6kl_err("fw_otp cannot be allocated\n");
ret = -ENOMEM;
goto out;
}
@ -1025,6 +1037,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw = vmalloc(ie_len);
if (ar->fw == NULL) {
ath6kl_err("fw storage cannot be allocated, len: %zd\n", ie_len);
ret = -ENOMEM;
goto out;
}
@ -1039,6 +1052,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
if (ar->fw_patch == NULL) {
ath6kl_err("fw_patch storage cannot be allocated, len: %zd\n", ie_len);
ret = -ENOMEM;
goto out;
}

View File

@ -176,3 +176,14 @@ config ATH9K_HTC_DEBUGFS
depends on ATH9K_HTC && DEBUG_FS
---help---
Say Y, if you need access to ath9k_htc's statistics.
config ATH9K_HWRNG
bool "Random number generator support"
depends on ATH9K && (HW_RANDOM = y || HW_RANDOM = ATH9K)
default y
---help---
This option incorporates the ADC register output as a source of
randomness into Linux entropy pool (/dev/urandom and /dev/random)
Say Y, feeds the entropy directly from the WiFi driver to the input
pool.

View File

@ -15,6 +15,7 @@ ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
ath9k-$(CONFIG_ATH9K_TX99) += tx99.o
ath9k-$(CONFIG_ATH9K_WOW) += wow.o
ath9k-$(CONFIG_ATH9K_HWRNG) += rng.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o

View File

@ -23,6 +23,7 @@
#include <linux/leds.h>
#include <linux/completion.h>
#include <linux/time.h>
#include <linux/hw_random.h>
#include "common.h"
#include "debug.h"
@ -981,6 +982,7 @@ struct ath_softc {
struct ath_offchannel offchannel;
struct ath_chanctx *next_chan;
struct completion go_beacon;
struct timespec last_event_time;
#endif
unsigned long driver_data;
@ -1040,6 +1042,11 @@ struct ath_softc {
u32 wow_intr_before_sleep;
bool force_wow;
#endif
#ifdef CONFIG_ATH9K_HWRNG
u32 rng_last;
struct task_struct *rng_task;
#endif
};
/********/
@ -1062,6 +1069,22 @@ static inline int ath9k_tx99_send(struct ath_softc *sc,
}
#endif /* CONFIG_ATH9K_TX99 */
/***************************/
/* Random Number Generator */
/***************************/
#ifdef CONFIG_ATH9K_HWRNG
void ath9k_rng_start(struct ath_softc *sc);
void ath9k_rng_stop(struct ath_softc *sc);
#else
static inline void ath9k_rng_start(struct ath_softc *sc)
{
}
static inline void ath9k_rng_stop(struct ath_softc *sc)
{
}
#endif
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
{
common->bus_ops->read_cachesize(common, csz);

View File

@ -148,7 +148,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
ath_assign_seq(common, skb);
if (vif->p2p)
/* Always assign NOA attr when MCC enabled */
if (ath9k_is_chanctx_enabled())
ath9k_beacon_add_noa(sc, avp, skb);
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,

View File

@ -226,6 +226,20 @@ static const char *chanctx_state_string(enum ath_chanctx_state state)
}
}
static const u32 chanctx_event_delta(struct ath_softc *sc)
{
u64 ms;
struct timespec ts, *old;
getrawmonotonic(&ts);
old = &sc->last_event_time;
ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
ms -= old->tv_sec * 1000 + old->tv_nsec / 1000000;
sc->last_event_time = ts;
return (u32)ms;
}
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@ -356,14 +370,16 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
unsigned long timeout;
ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
tsf_time -= ath9k_hw_gettsf32(ah);
tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
mod_timer(&sc->sched.timer, jiffies + tsf_time);
timeout = msecs_to_jiffies(tsf_time / 1000) + 1;
mod_timer(&sc->sched.timer, jiffies + timeout);
ath_dbg(common, CHAN_CTX,
"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
"Setup chanctx timer with timeout: %d (%d) ms\n",
tsf_time / 1000, jiffies_to_msecs(timeout));
}
static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
@ -403,7 +419,7 @@ static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
avp->offchannel_duration = sc->sched.offchannel_duration;
ath_dbg(common, CHAN_CTX,
"offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
"offchannel noa_duration: %d, noa_start: %u, noa_index: %d\n",
avp->offchannel_duration,
avp->offchannel_start,
avp->noa_index);
@ -443,7 +459,7 @@ static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
avp->periodic_noa = true;
ath_dbg(common, CHAN_CTX,
"noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
"noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
avp->noa_duration,
avp->noa_start,
avp->noa_index,
@ -464,7 +480,7 @@ static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
avp->noa_duration = duration + sc->sched.channel_switch_time;
ath_dbg(common, CHAN_CTX,
"oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
"oneshot noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
avp->noa_duration,
avp->noa_start,
avp->noa_index,
@ -487,10 +503,11 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
spin_lock_bh(&sc->chan_lock);
ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s\n",
ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s, delta: %u ms\n",
sc->cur_chan->chandef.center_freq1,
chanctx_event_string(ev),
chanctx_state_string(sc->sched.state));
chanctx_state_string(sc->sched.state),
chanctx_event_delta(sc));
switch (ev) {
case ATH_CHANCTX_EVENT_BEACON_PREPARE:
@ -1099,6 +1116,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
nullfunc->frame_control |=
cpu_to_le16(IEEE80211_FCTL_PM);
skb->priority = 7;
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
dev_kfree_skb_any(skb);
@ -1401,8 +1419,9 @@ void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
s32 tsf, target_tsf;
u32 tsf, target_tsf;
if (!avp || !avp->noa.has_next_tsf)
return;
@ -1414,11 +1433,17 @@ static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
target_tsf = avp->noa.next_tsf;
if (!avp->noa.absent)
target_tsf -= ATH_P2P_PS_STOP_TIME;
else
target_tsf += ATH_P2P_PS_STOP_TIME;
if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000);
ath_dbg(common, CHAN_CTX, "%s absent %d tsf 0x%08X next_tsf 0x%08X (%dms)\n",
__func__, avp->noa.absent, tsf, target_tsf,
(target_tsf - tsf) / 1000);
ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, target_tsf, 1000000);
}
static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
@ -1433,6 +1458,10 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
return;
sc->p2p_ps_vif = avp;
if (sc->ps_flags & PS_BEACON_SYNC)
return;
tsf = ath9k_hw_gettsf32(sc->sc_ah);
ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
ath9k_update_p2p_ps_timer(sc, avp);
@ -1495,6 +1524,8 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
noa->index = avp->noa_index;
noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp);
if (noa->oppps_ctwindow)
noa->oppps_ctwindow |= BIT(7);
if (avp->noa_duration) {
if (avp->periodic_noa) {
@ -1536,6 +1567,8 @@ void ath9k_p2p_ps_timer(void *priv)
tsf = ath9k_hw_gettsf32(sc->sc_ah);
if (!avp->noa.absent)
tsf += ATH_P2P_PS_STOP_TIME;
else
tsf -= ATH_P2P_PS_STOP_TIME;
if (!avp->noa.has_next_tsf ||
avp->noa.next_tsf - tsf > BIT(31))
@ -1571,8 +1604,7 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc,
spin_lock_bh(&sc->sc_pcu_lock);
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (!(sc->ps_flags & PS_BEACON_SYNC))
ath9k_update_p2p_ps(sc, vif);
ath9k_update_p2p_ps(sc, vif);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
spin_unlock_bh(&sc->sc_pcu_lock);
}

View File

@ -18,30 +18,16 @@
#define FUDGE 2
/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
{
u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
tsf_mod = tsf & (BIT(10) - 1);
tsf_hi = tsf >> 32;
tsf_lo = ((u32) tsf) >> 10;
mod_hi = tsf_hi % div_tu;
mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
return (mod_lo << 10) | tsf_mod;
}
static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf,
unsigned int interval)
{
unsigned int offset;
unsigned int offset, divisor;
tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
offset = ath9k_mod_tsf64_tu(tsf, interval);
divisor = TU_TO_USEC(interval);
div_u64_rem(tsf, divisor, &offset);
return (u32) tsf + TU_TO_USEC(interval) - offset;
return (u32) tsf + divisor - offset;
}
/*

View File

@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
return ret;
}
int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
{
u16 magic;
u16 *eepdata;
int i;
struct ath_common *common = ath9k_hw_common(ah);
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
ath_err(common, "Reading Magic # failed\n");
return -EIO;
}
if (magic == AR5416_EEPROM_MAGIC) {
*swap_needed = false;
} else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
if (ah->ah_flags & AH_NO_EEP_SWAP) {
ath_info(common,
"Ignoring endianness difference in EEPROM magic bytes.\n");
*swap_needed = false;
} else {
*swap_needed = true;
}
} else {
ath_err(common,
"Invalid EEPROM Magic (0x%04x).\n", magic);
return -EINVAL;
}
eepdata = (u16 *)(&ah->eeprom);
if (*swap_needed) {
ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing.\n");
for (i = 0; i < size; i++)
eepdata[i] = swab16(eepdata[i]);
}
return 0;
}
bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
{
u32 i, sum = 0;
u16 *eepdata = (u16 *)(&ah->eeprom);
struct ath_common *common = ath9k_hw_common(ah);
for (i = 0; i < size; i++)
sum ^= eepdata[i];
if (sum != 0xffff) {
ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
return false;
}
return true;
}
bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
{
struct ath_common *common = ath9k_hw_common(ah);
if (ah->eep_ops->get_eeprom_ver(ah) != version ||
ah->eep_ops->get_eeprom_rev(ah) < minrev) {
ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
ah->eep_ops->get_eeprom_ver(ah),
ah->eep_ops->get_eeprom_rev(ah));
return -EINVAL;
}
return true;
}
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
u8 *pVpdList, u16 numIntercepts,
u8 *pRetVpdList)

View File

@ -664,6 +664,9 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
u16 *indexL, u16 *indexR);
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size);
bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size);
bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev);
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
int eep_start_loc, int size);
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,

View File

@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif
#undef SIZE_EEPROM_4K
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
{
#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
struct ath_common *common = ath9k_hw_common(ah);
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
u16 *eepdata, temp, magic, magic2;
u32 sum = 0, el;
bool need_swap = false;
int i, addr;
u32 el;
bool need_swap;
int i, err;
if (!ath9k_hw_use_flash(ah)) {
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
}
ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
if (magic != AR5416_EEPROM_MAGIC) {
magic2 = swab16(magic);
if (magic2 == AR5416_EEPROM_MAGIC) {
need_swap = true;
eepdata = (u16 *) (&ah->eeprom);
for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
temp = swab16(*eepdata);
*eepdata = temp;
eepdata++;
}
} else {
ath_err(common,
"Invalid EEPROM Magic. Endianness mismatch.\n");
return -EINVAL;
}
}
}
ath_dbg(common, EEPROM, "need_swap = %s\n",
need_swap ? "True" : "False");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
if (err)
return err;
if (need_swap)
el = swab16(ah->eeprom.map4k.baseEepHeader.length);
el = swab16(eep->baseEepHeader.length);
else
el = ah->eeprom.map4k.baseEepHeader.length;
el = eep->baseEepHeader.length;
if (el > sizeof(struct ar5416_eeprom_4k))
el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
else
el = el / sizeof(u16);
eepdata = (u16 *)(&ah->eeprom);
for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_4K);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;
if (need_swap) {
u32 integer;
u16 word;
ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing\n");
word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;
@ -283,17 +239,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
}
}
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
sum, ah->eep_ops->get_eeprom_ver(ah));
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}
return 0;
#undef EEPROM_4K_SIZE
}
#undef SIZE_EEPROM_4K
static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{

View File

@ -177,59 +177,24 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
{
u32 sum = 0, el, integer;
u16 temp, word, magic, magic2, *eepdata;
int i, addr;
bool need_swap = false;
u32 el, integer;
u16 word;
int i, err;
bool need_swap;
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
struct ath_common *common = ath9k_hw_common(ah);
if (!ath9k_hw_use_flash(ah)) {
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
&magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
}
ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
if (magic != AR5416_EEPROM_MAGIC) {
magic2 = swab16(magic);
if (magic2 == AR5416_EEPROM_MAGIC) {
need_swap = true;
eepdata = (u16 *)(&ah->eeprom);
for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
temp = swab16(*eepdata);
*eepdata = temp;
eepdata++;
}
} else {
ath_err(common,
"Invalid EEPROM Magic. Endianness mismatch.\n");
return -EINVAL;
}
}
}
ath_dbg(common, EEPROM, "need_swap = %s\n",
need_swap ? "True" : "False");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
if (err)
return err;
if (need_swap)
el = swab16(ah->eeprom.map9287.baseEepHeader.length);
el = swab16(eep->baseEepHeader.length);
else
el = ah->eeprom.map9287.baseEepHeader.length;
el = eep->baseEepHeader.length;
if (el > sizeof(struct ar9287_eeprom))
el = sizeof(struct ar9287_eeprom) / sizeof(u16);
else
el = el / sizeof(u16);
eepdata = (u16 *)(&ah->eeprom);
for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;
if (need_swap) {
word = swab16(eep->baseEepHeader.length);
@ -270,16 +235,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
}
}
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
|| ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
sum, ah->eep_ops->get_eeprom_ver(ah));
if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}
return 0;
}
#undef SIZE_EEPROM_AR9287
static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{

View File

@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_def_fill_eeprom(ah);
}
#undef SIZE_EEPROM_DEF
#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr)
@ -257,59 +255,31 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
u16 *eepdata, temp, magic;
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;
u32 el;
bool need_swap;
int i, err;
if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
ath_err(common, "Reading Magic # failed\n");
return false;
}
if (swab16(magic) == AR5416_EEPROM_MAGIC &&
!(ah->ah_flags & AH_NO_EEP_SWAP)) {
size = sizeof(struct ar5416_eeprom_def);
need_swap = true;
eepdata = (u16 *) (&ah->eeprom);
for (addr = 0; addr < size / sizeof(u16); addr++) {
temp = swab16(*eepdata);
*eepdata = temp;
eepdata++;
}
}
ath_dbg(common, EEPROM, "need_swap = %s\n",
need_swap ? "True" : "False");
err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
if (err)
return err;
if (need_swap)
el = swab16(ah->eeprom.def.baseEepHeader.length);
el = swab16(eep->baseEepHeader.length);
else
el = ah->eeprom.def.baseEepHeader.length;
el = eep->baseEepHeader.length;
if (el > sizeof(struct ar5416_eeprom_def))
el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
else
el = el / sizeof(u16);
eepdata = (u16 *)(&ah->eeprom);
for (i = 0; i < el; i++)
sum ^= *eepdata++;
el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
if (!ath9k_hw_nvram_validate_checksum(ah, el))
return -EINVAL;
if (need_swap) {
u32 integer, j;
u16 word;
ath_dbg(common, EEPROM,
"EEPROM Endianness is not native.. Changing.\n");
word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;
@ -356,12 +326,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
}
}
if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
sum, ah->eep_ops->get_eeprom_ver(ah));
if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
AR5416_EEP_NO_BACK_VER))
return -EINVAL;
}
/* Enable fixup for AR_AN_TOP2 if necessary */
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return 0;
}
#undef SIZE_EEPROM_DEF
static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{

View File

@ -2299,10 +2299,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
else
nextTbtt = bs->bs_nexttbtt;
ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim);
ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt);
ath_dbg(common, BEACON, "beacon period %d\n", beaconintval);
ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod);
ath_dbg(common, BEACON, "next DTIM %u\n", bs->bs_nextdtim);
ath_dbg(common, BEACON, "next beacon %u\n", nextTbtt);
ath_dbg(common, BEACON, "beacon period %u\n", beaconintval);
ath_dbg(common, BEACON, "DTIM period %u\n", dtimperiod);
ENABLE_REGWRITE_BUFFER(ah);
@ -2761,9 +2761,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah);
if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
REG_WRITE(ah, AR_RX_FILTER, bits);
phybits = 0;

View File

@ -739,6 +739,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath9k_ps_restore(sc);
ath9k_rng_start(sc);
return 0;
}
@ -828,6 +830,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_deinit_channel_context(sc);
ath9k_rng_stop(sc);
mutex_lock(&sc->mutex);
ath_cancel_work(sc);

View File

@ -424,6 +424,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
AR_SREV_9561(sc->sc_ah))
rfilt |= ATH9K_RX_FILTER_4ADDRESS;
if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
rfilt |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
if (ath9k_is_chanctx_enabled() &&
test_bit(ATH_OP_SCANNING, &common->op_flags))
rfilt |= ATH9K_RX_FILTER_BEACON;

View File

@ -0,0 +1,107 @@
/*
* Copyright (c) 2015 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 <linux/hw_random.h>
#include <linux/kthread.h>
#include "ath9k.h"
#include "hw.h"
#include "ar9003_phy.h"
#define ATH9K_RNG_BUF_SIZE 320
#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 320) >> 10) /* quality: 320/1024 */
static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
{
int i, j;
u32 v1, v2, rng_last = sc->rng_last;
struct ath_hw *ah = sc->sc_ah;
ath9k_ps_wakeup(sc);
REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
for (i = 0, j = 0; i < buf_size; i++) {
v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;
v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;
/* wait for data ready */
if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff &&
v2 != 0xffff)
buf[j++] = (v1 << 16) | v2;
rng_last = v2;
}
ath9k_ps_restore(sc);
sc->rng_last = rng_last;
return j << 2;
}
static int ath9k_rng_kthread(void *data)
{
int bytes_read;
struct ath_softc *sc = data;
u32 *rng_buf;
rng_buf = kmalloc_array(ATH9K_RNG_BUF_SIZE, sizeof(u32), GFP_KERNEL);
if (!rng_buf)
goto out;
while (!kthread_should_stop()) {
bytes_read = ath9k_rng_data_read(sc, rng_buf,
ATH9K_RNG_BUF_SIZE);
if (unlikely(!bytes_read)) {
msleep_interruptible(10);
continue;
}
/* sleep until entropy bits under write_wakeup_threshold */
add_hwgenerator_randomness((void *)rng_buf, bytes_read,
ATH9K_RNG_ENTROPY(bytes_read));
}
kfree(rng_buf);
out:
sc->rng_task = NULL;
return 0;
}
void ath9k_rng_start(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
if (sc->rng_task)
return;
if (!AR_SREV_9300_20_OR_LATER(ah))
return;
sc->rng_task = kthread_run(ath9k_rng_kthread, sc, "ath9k-hwrng");
if (IS_ERR(sc->rng_task))
sc->rng_task = NULL;
}
void ath9k_rng_stop(struct ath_softc *sc)
{
if (sc->rng_task)
kthread_stop(sc->rng_task);
}

View File

@ -1473,11 +1473,14 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *txtid;
struct ath_txq *txq;
struct ath_node *an;
u8 density;
ath_dbg(common, XMIT, "%s called\n", __func__);
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
txq = txtid->txq;
@ -1512,10 +1515,13 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
struct ath_txq *txq = txtid->txq;
ath_dbg(common, XMIT, "%s called\n", __func__);
ath_txq_lock(sc, txq);
txtid->active = false;
ath_tx_flush_tid(sc, txtid);
@ -1526,11 +1532,14 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
struct ath_node *an)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_txq *txq;
bool buffered;
int tidno;
ath_dbg(common, XMIT, "%s called\n", __func__);
for (tidno = 0, tid = &an->tid[tidno];
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
@ -1555,10 +1564,13 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_txq *txq;
int tidno;
ath_dbg(common, XMIT, "%s called\n", __func__);
for (tidno = 0, tid = &an->tid[tidno];
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
@ -1579,10 +1591,13 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tidno)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_node *an;
struct ath_txq *txq;
ath_dbg(common, XMIT, "%s called\n", __func__);
an = (struct ath_node *)sta->drv_priv;
tid = ATH_AN_2_TID(an, tidno);
txq = tid->txq;
@ -2316,6 +2331,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
queue = ieee80211_is_data_present(hdr->frame_control);
/* If chanctx, queue all null frames while NOA could be there */
if (ath9k_is_chanctx_enabled() &&
ieee80211_is_nullfunc(hdr->frame_control) &&
!txctl->force_channel)
queue = true;
/* Force queueing of all frames that belong to a virtual interface on
* a different channel context, to ensure that they are sent on the
* correct channel.
@ -2894,7 +2915,7 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
if (skb_headroom(skb) < padsize) {
ath_dbg(common, XMIT,
"tx99 padding failed\n");
return -EINVAL;
return -EINVAL;
}
skb_push(skb, padsize);

View File

@ -781,8 +781,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil_bcast_fini(wil);
/* prevent NAPI from being scheduled */
/* prevent NAPI from being scheduled and prevent wmi commands */
mutex_lock(&wil->wmi_mutex);
bitmap_zero(wil->status, wil_status_last);
mutex_unlock(&wil->wmi_mutex);
if (wil->scan_request) {
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",

View File

@ -228,6 +228,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
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--) {
if (!test_bit(wil_status_fwready, wil->status)) {
wil_err(wil, "WMI: cannot send command while FW not ready\n");
return -EAGAIN;
}
r->tail = wil_r(wil, RGF_MBOX +
offsetof(struct wil6210_mbox_ctl, tx.tail));
if (next_head != r->tail)

View File

@ -91,6 +91,10 @@
#define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400
#define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS 20
#define BRCMF_SCAN_CHANNEL_TIME 40
#define BRCMF_SCAN_UNASSOC_TIME 40
#define BRCMF_SCAN_PASSIVE_TIME 120
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
@ -392,15 +396,23 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
{
int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
bool check_combos = false;
int ret = 0;
memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
if (pos == vif)
if (pos == vif) {
iftype_num[new_type]++;
else
} else {
/* concurrent interfaces so need check combinations */
check_combos = true;
iftype_num[pos->wdev.iftype]++;
}
return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
if (check_combos)
ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
return ret;
}
static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
@ -1027,11 +1039,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
struct brcmf_if *ifp = vif->ifp;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct cfg80211_ssid *ssids;
struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
u32 passive_scan;
bool escan_req;
bool spec_scan;
s32 err;
struct brcmf_ssid_le ssid_le;
u32 SSID_len;
brcmf_dbg(SCAN, "START ESCAN\n");
@ -1084,13 +1096,13 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
} else {
brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
ssids->ssid, ssids->ssid_len);
memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
sr->ssid_le.SSID_len = cpu_to_le32(0);
memset(&ssid_le, 0, sizeof(ssid_le));
SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len);
ssid_le.SSID_len = cpu_to_le32(0);
spec_scan = false;
if (SSID_len) {
memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
memcpy(ssid_le.SSID, ssids->ssid, SSID_len);
ssid_le.SSID_len = cpu_to_le32(SSID_len);
spec_scan = true;
} else
brcmf_dbg(SCAN, "Broadcast scan\n");
@ -1103,12 +1115,12 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
goto scan_out;
}
brcmf_scan_config_mpc(ifp, 0);
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
&sr->ssid_le, sizeof(sr->ssid_le));
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le,
sizeof(ssid_le));
if (err) {
if (err == -EBUSY)
brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
sr->ssid_le.SSID);
ssid_le.SSID);
else
brcmf_err("WLC_SCAN error (%d)\n", err);
@ -1261,17 +1273,17 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
brcmf_dbg(TRACE, "Enter\n");
if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
err = brcmf_fil_cmd_data_set(vif->ifp,
BRCMF_C_DISASSOC, NULL, 0);
if (err) {
brcmf_err("WLC_DISASSOC failed (%d)\n", err);
}
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
true, GFP_KERNEL);
if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) ||
(vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT))
cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
true, GFP_KERNEL);
}
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
@ -2685,8 +2697,8 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
return err;
}
static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev, const u8 *bssid)
static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
struct net_device *ndev, const u8 *bssid)
{
struct wiphy *wiphy = cfg_to_wiphy(cfg);
struct ieee80211_channel *notify_channel;
@ -2731,6 +2743,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
band = wiphy->bands[IEEE80211_BAND_5GHZ];
freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
cfg->channel = freq;
notify_channel = ieee80211_get_channel(wiphy, freq);
notify_capability = le16_to_cpu(bi->capability);
@ -3219,26 +3232,22 @@ exit:
}
static __used s32
brcmf_update_pmklist(struct net_device *ndev,
struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
{
int i, j;
u32 pmkid_len;
struct brcmf_pmk_list_le *pmk_list;
int i;
u32 npmk;
s32 err;
pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
pmk_list = &cfg->pmk_list;
npmk = le32_to_cpu(pmk_list->npmk);
brcmf_dbg(CONN, "No of elements %d\n", pmkid_len);
for (i = 0; i < pmkid_len; i++) {
brcmf_dbg(CONN, "PMKID[%d]: %pM =\n", i,
&pmk_list->pmkids.pmkid[i].BSSID);
for (j = 0; j < WLAN_PMKID_LEN; j++)
brcmf_dbg(CONN, "%02x\n",
pmk_list->pmkids.pmkid[i].PMKID[j]);
}
brcmf_dbg(CONN, "No of elements %d\n", npmk);
for (i = 0; i < npmk; i++)
brcmf_dbg(CONN, "PMK[%d]: %pM\n", i, &pmk_list->pmk[i].bssid);
if (!err)
brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
(char *)pmk_list, sizeof(*pmk_list));
err = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,
sizeof(*pmk_list));
return err;
}
@ -3249,34 +3258,37 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
s32 err = 0;
u32 pmkid_len, i;
struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
s32 err;
u32 npmk, i;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
pmkid_len = le32_to_cpu(pmkids->npmkid);
for (i = 0; i < pmkid_len; i++)
if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
npmk = le32_to_cpu(cfg->pmk_list.npmk);
for (i = 0; i < npmk; i++)
if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
break;
if (i < WL_NUM_PMKIDS_MAX) {
memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
if (i == pmkid_len) {
pmkid_len++;
pmkids->npmkid = cpu_to_le32(pmkid_len);
if (i < BRCMF_MAXPMKID) {
memcpy(pmk[i].bssid, pmksa->bssid, ETH_ALEN);
memcpy(pmk[i].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
if (i == npmk) {
npmk++;
cfg->pmk_list.npmk = cpu_to_le32(npmk);
}
} else
err = -EINVAL;
} else {
brcmf_err("Too many PMKSA entries cached %d\n", npmk);
return -EINVAL;
}
brcmf_dbg(CONN, "set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
pmkids->pmkid[pmkid_len].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
brcmf_dbg(CONN, "%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid);
for (i = 0; i < WLAN_PMKID_LEN; i += 4)
brcmf_dbg(CONN, "%02x %02x %02x %02x\n", pmk[npmk].pmkid[i],
pmk[npmk].pmkid[i + 1], pmk[npmk].pmkid[i + 2],
pmk[npmk].pmkid[i + 3]);
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@ -3284,50 +3296,39 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
static s32
brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_pmksa *pmksa)
struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list pmkid;
s32 err = 0;
u32 pmkid_len, i;
struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
s32 err;
u32 npmk, i;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", &pmksa->bssid);
brcmf_dbg(CONN, "del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
&pmkid.pmkid[0].BSSID);
for (i = 0; i < WLAN_PMKID_LEN; i++)
brcmf_dbg(CONN, "%02x\n", pmkid.pmkid[0].PMKID[i]);
pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
for (i = 0; i < pmkid_len; i++)
if (!memcmp
(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
ETH_ALEN))
npmk = le32_to_cpu(cfg->pmk_list.npmk);
for (i = 0; i < npmk; i++)
if (!memcmp(&pmksa->bssid, &pmk[i].bssid, ETH_ALEN))
break;
if ((pmkid_len > 0)
&& (i < pmkid_len)) {
memset(&cfg->pmk_list->pmkids.pmkid[i], 0,
sizeof(struct pmkid));
for (; i < (pmkid_len - 1); i++) {
memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
&cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
ETH_ALEN);
memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
&cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
if ((npmk > 0) && (i < npmk)) {
for (; i < (npmk - 1); i++) {
memcpy(&pmk[i].bssid, &pmk[i + 1].bssid, ETH_ALEN);
memcpy(&pmk[i].pmkid, &pmk[i + 1].pmkid,
WLAN_PMKID_LEN);
}
cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
} else
err = -EINVAL;
memset(&pmk[i], 0, sizeof(*pmk));
cfg->pmk_list.npmk = cpu_to_le32(npmk - 1);
} else {
brcmf_err("Cache entry not found\n");
return -EINVAL;
}
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@ -3339,14 +3340,14 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err = 0;
s32 err;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@ -5071,9 +5072,9 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
} else if (brcmf_is_linkup(e)) {
brcmf_dbg(CONN, "Linkup\n");
if (brcmf_is_ibssmode(ifp->vif)) {
brcmf_inform_ibss(cfg, ndev, e->addr);
chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
memcpy(profile->bssid, e->addr, ETH_ALEN);
wl_inform_ibss(cfg, ndev, e->addr);
cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
&ifp->vif->sme_state);
@ -5199,7 +5200,6 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
conf->rts_threshold = (u32)-1;
conf->retry_short = (u32)-1;
conf->retry_long = (u32)-1;
conf->tx_power = -1;
}
static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
@ -5246,8 +5246,6 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
cfg->escan_ioctl_buf = NULL;
kfree(cfg->extra_buf);
cfg->extra_buf = NULL;
kfree(cfg->pmk_list);
cfg->pmk_list = NULL;
}
static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
@ -5261,9 +5259,6 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (!cfg->extra_buf)
goto init_priv_mem_out;
cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
if (!cfg->pmk_list)
goto init_priv_mem_out;
return 0;
@ -5357,37 +5352,27 @@ roam_setup_done:
}
static s32
brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
s32 scan_unassoc_time, s32 scan_passive_time)
brcmf_dongle_scantime(struct brcmf_if *ifp)
{
s32 err = 0;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
scan_assoc_time);
BRCMF_SCAN_CHANNEL_TIME);
if (err) {
if (err == -EOPNOTSUPP)
brcmf_dbg(INFO, "Scan assoc time is not supported\n");
else
brcmf_err("Scan assoc time error (%d)\n", err);
brcmf_err("Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
scan_unassoc_time);
BRCMF_SCAN_UNASSOC_TIME);
if (err) {
if (err == -EOPNOTSUPP)
brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
else
brcmf_err("Scan unassoc time error (%d)\n", err);
brcmf_err("Scan unassoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
scan_passive_time);
BRCMF_SCAN_PASSIVE_TIME);
if (err) {
if (err == -EOPNOTSUPP)
brcmf_dbg(INFO, "Scan passive time is not supported\n");
else
brcmf_err("Scan passive time error (%d)\n", err);
brcmf_err("Scan passive time error (%d)\n", err);
goto dongle_scantime_out;
}
@ -5978,7 +5963,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
wiphy->max_num_pmkids = BRCMF_MAXPMKID;
err = brcmf_setup_ifmodes(wiphy, ifp);
if (err)
@ -6007,8 +5992,9 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
WIPHY_FLAG_OFFCHAN_TX |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_SUPPORTS_TDLS;
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
if (!brcmf_roamoff)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
@ -6089,8 +6075,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
/* make sure RF is ready for work */
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME,
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
brcmf_dongle_scantime(ifp);
power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
@ -6401,13 +6386,15 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto wiphy_unreg_out;
}
err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
if (err) {
brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
} else {
brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
brcmf_notify_tdls_peer_event);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {
err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
if (err) {
brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
} else {
brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
brcmf_notify_tdls_peer_event);
}
}
/* (re-) activate FWEH event handling */

View File

@ -21,7 +21,6 @@
#include <brcmu_d11.h>
#define WL_NUM_SCAN_MAX 10
#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
#define WL_ASSOC_INFO_MAX 512 /* assoc related fil max buf */
@ -29,10 +28,6 @@
#define WL_ROAM_TRIGGER_LEVEL -75
#define WL_ROAM_DELTA 20
#define WL_SCAN_CHANNEL_TIME 40
#define WL_SCAN_UNASSOC_TIME 40
#define WL_SCAN_PASSIVE_TIME 120
#define WL_ESCAN_BUF_SIZE (1024 * 64)
#define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */
@ -99,19 +94,6 @@ struct brcmf_cfg80211_conf {
u32 rts_threshold;
u32 retry_short;
u32 retry_long;
s32 tx_power;
struct ieee80211_channel channel;
};
/* basic structure of scan request */
struct brcmf_cfg80211_scan_req {
struct brcmf_ssid_le ssid_le;
};
/* basic structure of information element */
struct brcmf_cfg80211_ie {
u16 offset;
u8 buf[WL_TLV_INFO_MAX];
};
/* security information with currently associated ap */
@ -213,12 +195,6 @@ struct brcmf_cfg80211_assoc_ielen_le {
__le32 resp_len;
};
/* wpa2 pmk list */
struct brcmf_cfg80211_pmk_list {
struct pmkid_list pmkids;
struct pmkid foo[MAXPMKID - 1];
};
/* dongle escan state */
enum wl_escan_state {
WL_ESCAN_STATE_IDLE,
@ -234,87 +210,6 @@ struct escan_info {
struct cfg80211_scan_request *request);
};
/**
* struct brcmf_pno_param_le - PNO scan configuration parameters
*
* @version: PNO parameters version.
* @scan_freq: scan frequency.
* @lost_network_timeout: #sec. to declare discovered network as lost.
* @flags: Bit field to control features of PFN such as sort criteria auto
* enable switch and background scan.
* @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
* criteria.
* @bestn: number of best networks in each scan.
* @mscan: number of scans recorded.
* @repeat: minimum number of scan intervals before scan frequency changes
* in adaptive scan.
* @exp: exponent of 2 for maximum scan interval.
* @slow_freq: slow scan period.
*/
struct brcmf_pno_param_le {
__le32 version;
__le32 scan_freq;
__le32 lost_network_timeout;
__le16 flags;
__le16 rssi_margin;
u8 bestn;
u8 mscan;
u8 repeat;
u8 exp;
__le32 slow_freq;
};
/**
* struct brcmf_pno_net_param_le - scan parameters per preferred network.
*
* @ssid: ssid name and its length.
* @flags: bit2: hidden.
* @infra: BSS vs IBSS.
* @auth: Open vs Closed.
* @wpa_auth: WPA type.
* @wsec: wsec value.
*/
struct brcmf_pno_net_param_le {
struct brcmf_ssid_le ssid;
__le32 flags;
__le32 infra;
__le32 auth;
__le32 wpa_auth;
__le32 wsec;
};
/**
* struct brcmf_pno_net_info_le - information per found network.
*
* @bssid: BSS network identifier.
* @channel: channel number only.
* @SSID_len: length of ssid.
* @SSID: ssid characters.
* @RSSI: receive signal strength (in dBm).
* @timestamp: age in seconds.
*/
struct brcmf_pno_net_info_le {
u8 bssid[ETH_ALEN];
u8 channel;
u8 SSID_len;
u8 SSID[32];
__le16 RSSI;
__le16 timestamp;
};
/**
* struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
*
* @version: PNO version identifier.
* @status: indicates completion status of PNO scan.
* @count: amount of brcmf_pno_net_info_le entries appended.
*/
struct brcmf_pno_scanresults_le {
__le32 version;
__le32 status;
__le32 count;
};
/**
* struct brcmf_cfg80211_vif_event - virtual interface event information.
*
@ -341,9 +236,7 @@ struct brcmf_cfg80211_vif_event {
* @scan_request: cfg80211 scan request object.
* @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information.
* @scan_req_int: internal scan request object.
* @bss_info: bss information for cfg80211 layer.
* @ie: information element object for internal purpose.
* @conn_info: association info.
* @pmk_list: wpa2 pmk list.
* @scan_status: scan activity on the dongle.
@ -376,11 +269,9 @@ struct brcmf_cfg80211_info {
struct brcmf_btcoex_info *btcoex;
struct cfg80211_scan_request *scan_request;
struct mutex usr_sync;
struct brcmf_cfg80211_scan_req scan_req_int;
struct wl_cfg80211_bss_info *bss_info;
struct brcmf_cfg80211_ie ie;
struct brcmf_cfg80211_connect_info conn_info;
struct brcmf_cfg80211_pmk_list *pmk_list;
struct brcmf_pmk_list_le pmk_list;
unsigned long scan_status;
struct brcmf_pub *pub;
u32 channel;

View File

@ -138,6 +138,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
if (brcmf_feature_disable) {
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",

View File

@ -25,6 +25,7 @@
* WOWL: Wake-On-WLAN.
* P2P: peer-to-peer
* RSDB: Real Simultaneous Dual Band
* TDLS: Tunneled Direct Link Setup
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
@ -32,7 +33,8 @@
BRCMF_FEAT_DEF(PNO) \
BRCMF_FEAT_DEF(WOWL) \
BRCMF_FEAT_DEF(P2P) \
BRCMF_FEAT_DEF(RSDB)
BRCMF_FEAT_DEF(RSDB) \
BRCMF_FEAT_DEF(TDLS)
/*
* Quirks:

View File

@ -126,6 +126,8 @@
#define BRCMF_TXBF_SU_BFR_CAP BIT(0)
#define BRCMF_TXBF_MU_BFR_CAP BIT(1)
#define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
@ -646,4 +648,107 @@ struct brcmf_wowl_wakeind_le {
__le32 ucode_wakeind;
};
/**
* struct brcmf_pmksa - PMK Security Association
*
* @bssid: The AP's BSSID.
* @pmkid: he PMK material itself.
*/
struct brcmf_pmksa {
u8 bssid[ETH_ALEN];
u8 pmkid[WLAN_PMKID_LEN];
};
/**
* struct brcmf_pmk_list_le - List of pmksa's.
*
* @npmk: Number of pmksa's.
* @pmk: PMK SA information.
*/
struct brcmf_pmk_list_le {
__le32 npmk;
struct brcmf_pmksa pmk[BRCMF_MAXPMKID];
};
/**
* struct brcmf_pno_param_le - PNO scan configuration parameters
*
* @version: PNO parameters version.
* @scan_freq: scan frequency.
* @lost_network_timeout: #sec. to declare discovered network as lost.
* @flags: Bit field to control features of PFN such as sort criteria auto
* enable switch and background scan.
* @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
* criteria.
* @bestn: number of best networks in each scan.
* @mscan: number of scans recorded.
* @repeat: minimum number of scan intervals before scan frequency changes
* in adaptive scan.
* @exp: exponent of 2 for maximum scan interval.
* @slow_freq: slow scan period.
*/
struct brcmf_pno_param_le {
__le32 version;
__le32 scan_freq;
__le32 lost_network_timeout;
__le16 flags;
__le16 rssi_margin;
u8 bestn;
u8 mscan;
u8 repeat;
u8 exp;
__le32 slow_freq;
};
/**
* struct brcmf_pno_net_param_le - scan parameters per preferred network.
*
* @ssid: ssid name and its length.
* @flags: bit2: hidden.
* @infra: BSS vs IBSS.
* @auth: Open vs Closed.
* @wpa_auth: WPA type.
* @wsec: wsec value.
*/
struct brcmf_pno_net_param_le {
struct brcmf_ssid_le ssid;
__le32 flags;
__le32 infra;
__le32 auth;
__le32 wpa_auth;
__le32 wsec;
};
/**
* struct brcmf_pno_net_info_le - information per found network.
*
* @bssid: BSS network identifier.
* @channel: channel number only.
* @SSID_len: length of ssid.
* @SSID: ssid characters.
* @RSSI: receive signal strength (in dBm).
* @timestamp: age in seconds.
*/
struct brcmf_pno_net_info_le {
u8 bssid[ETH_ALEN];
u8 channel;
u8 SSID_len;
u8 SSID[32];
__le16 RSSI;
__le16 timestamp;
};
/**
* struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
*
* @version: PNO version identifier.
* @status: indicates completion status of PNO scan.
* @count: amount of brcmf_pno_net_info_le entries appended.
*/
struct brcmf_pno_scanresults_le {
__le32 version;
__le32 status;
__le32 count;
};
#endif /* FWIL_TYPES_H_ */

View File

@ -1609,10 +1609,11 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
{
struct brcmf_fws_info *fws = ifp->drvr->fws;
brcmf_fws_lock(fws);
if (fws)
if (fws) {
brcmf_fws_lock(fws);
fws->bcmc_credit_check = true;
brcmf_fws_unlock(fws);
brcmf_fws_unlock(fws);
}
return 0;
}

View File

@ -473,8 +473,7 @@ static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)
static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
{
msgbuf->ctl_completed = true;
if (waitqueue_active(&msgbuf->ioctl_resp_wait))
wake_up(&msgbuf->ioctl_resp_wait);
wake_up(&msgbuf->ioctl_resp_wait);
}

View File

@ -46,6 +46,7 @@ enum brcmf_pcie_state {
BRCMF_FW_NVRAM_DEF(43602, "brcmfmac43602-pcie.bin", "brcmfmac43602-pcie.txt");
BRCMF_FW_NVRAM_DEF(4350, "brcmfmac4350-pcie.bin", "brcmfmac4350-pcie.txt");
BRCMF_FW_NVRAM_DEF(4350C, "brcmfmac4350c2-pcie.bin", "brcmfmac4350c2-pcie.txt");
BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-pcie.bin", "brcmfmac4356-pcie.txt");
BRCMF_FW_NVRAM_DEF(43570, "brcmfmac43570-pcie.bin", "brcmfmac43570-pcie.txt");
BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt");
@ -56,7 +57,8 @@ BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFFFF, 4350),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
@ -1873,7 +1875,7 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev)
struct brcmf_pciedev_info *devinfo;
struct brcmf_bus *bus;
brcmf_err("Enter\n");
brcmf_dbg(PCIE, "Enter\n");
bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo;
@ -1904,7 +1906,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev)
struct pci_dev *pdev;
int err;
brcmf_err("Enter\n");
brcmf_dbg(PCIE, "Enter\n");
bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo;

View File

@ -1678,8 +1678,7 @@ static int brcmf_sdio_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
static int brcmf_sdio_dcmd_resp_wake(struct brcmf_sdio *bus)
{
if (waitqueue_active(&bus->dcmd_resp_wait))
wake_up_interruptible(&bus->dcmd_resp_wait);
wake_up_interruptible(&bus->dcmd_resp_wait);
return 0;
}
@ -2003,8 +2002,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
static void
brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus)
{
if (waitqueue_active(&bus->ctrl_wait))
wake_up_interruptible(&bus->ctrl_wait);
wake_up_interruptible(&bus->ctrl_wait);
return;
}

View File

@ -196,8 +196,7 @@ static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
{
if (waitqueue_active(&devinfo->ioctl_resp_wait))
wake_up(&devinfo->ioctl_resp_wait);
wake_up(&devinfo->ioctl_resp_wait);
}
static void
@ -1453,6 +1452,7 @@ static struct usb_device_id brcmf_usb_devid_table[] = {
BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
{ USB_DEVICE(BRCM_USB_VENDOR_ID_LG, BRCM_USB_43242_LG_DEVICE_ID) },
/* special entry for device with firmware loaded and running */
BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
{ /* end: all zeroes */ }

View File

@ -177,8 +177,8 @@ static bool brcms_c_country_valid(const char *ccode)
* only allow ascii alpha uppercase for the first 2
* chars.
*/
if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
(0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
if (!((ccode[0] & 0x80) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
(ccode[1] & 0x80) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
return false;
/*

View File

@ -21,6 +21,7 @@
#include <linux/mmc/sdio_ids.h>
#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCM_USB_VENDOR_ID_LG 0x043e
#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
/* Chipcommon Core Chip IDs */
@ -57,6 +58,7 @@
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
#define BRCM_USB_43236_DEVICE_ID 0xbd17
#define BRCM_USB_43242_DEVICE_ID 0xbd1f
#define BRCM_USB_43242_LG_DEVICE_ID 0x3101
#define BRCM_USB_43569_DEVICE_ID 0xbd27
#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc

View File

@ -237,9 +237,6 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define WPA2_AUTH_RESERVED4 0x0400
#define WPA2_AUTH_RESERVED5 0x0800
/* pmkid */
#define MAXPMKID 16
#define DOT11_DEFAULT_RTS_LEN 2347
#define DOT11_DEFAULT_FRAG_LEN 2346
@ -251,24 +248,4 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define HT_CAP_RX_STBC_NO 0x0
#define HT_CAP_RX_STBC_ONE_STREAM 0x1
struct pmkid {
u8 BSSID[ETH_ALEN];
u8 PMKID[WLAN_PMKID_LEN];
};
struct pmkid_list {
__le32 npmkid;
struct pmkid pmkid[1];
};
struct pmkid_cand {
u8 BSSID[ETH_ALEN];
u8 preauth;
};
struct pmkid_cand_list {
u32 npmkid_cand;
struct pmkid_cand pmkid_cand[1];
};
#endif /* _BRCMU_WIFI_H_ */

View File

@ -1865,14 +1865,14 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags)
cmd.len = il->ops->build_addsta_hcmd(sta, data);
ret = il_send_cmd(il, &cmd);
if (ret || (flags & CMD_ASYNC))
if (ret)
return ret;
if (flags & CMD_ASYNC)
return 0;
pkt = (struct il_rx_pkt *)cmd.reply_page;
ret = il_process_add_sta_resp(il, sta, pkt, true);
if (ret == 0) {
pkt = (struct il_rx_pkt *)cmd.reply_page;
ret = il_process_add_sta_resp(il, sta, pkt, true);
}
il_free_pages(il, cmd.reply_page);
return ret;
@ -3602,7 +3602,7 @@ il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap)
}
EXPORT_SYMBOL(il_is_ht40_tx_allowed);
static u16
static u16 noinline
il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
u16 new_val;

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -473,13 +473,4 @@ do { \
} while (0)
#endif /* CONFIG_IWLWIFI_DEBUG */
extern const char *const iwl_dvm_cmd_strings[REPLY_MAX + 1];
static inline const char *iwl_dvm_get_cmd_string(u8 cmd)
{
const char *s = iwl_dvm_cmd_strings[cmd];
if (s)
return s;
return "UNKNOWN";
}
#endif /* __iwl_agn_h__ */

View File

@ -311,7 +311,7 @@ static int iwl_sens_energy_cck(struct iwl_priv *priv,
/* If previous beacon had too many false alarms,
* give it some extra margin by reducing sensitivity again
* (but don't go below measured energy of desired Rx) */
if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
if (data->nrg_prev_state == IWL_FA_TOO_MANY) {
IWL_DEBUG_CALIB(priv, "... increasing margin\n");
if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
data->nrg_th_cck -= NRG_MARGIN;

View File

@ -22,7 +22,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@ -32,7 +32,9 @@
#include <linux/debugfs.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
#include "iwl-debug.h"
#include "iwl-trans.h"
#include "iwl-io.h"
#include "dev.h"
#include "agn.h"
@ -438,7 +440,7 @@ static ssize_t iwl_dbgfs_rx_handlers_read(struct file *file,
if (priv->rx_handlers_stats[cnt] > 0)
pos += scnprintf(buf + pos, bufsz - pos,
"\tRx handler[%36s]:\t\t %u\n",
iwl_dvm_get_cmd_string(cnt),
iwl_get_cmd_string(priv->trans, (u32)cnt),
priv->rx_handlers_stats[cnt]);
}

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -1262,7 +1262,7 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (test_bit(STATUS_FW_ERROR, &priv->status)) {
IWL_ERR(priv, "Command %s failed: FW Error\n",
iwl_dvm_get_cmd_string(cmd->id));
iwl_get_cmd_string(priv->trans, cmd->id));
return -EIO;
}

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -115,6 +115,9 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, WANT_MONITOR_VIF);
if (priv->trans->max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FMT;

View File

@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@ -22,7 +23,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -69,6 +70,93 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search.
* A warning will be triggered on violation.
*/
static const struct iwl_hcmd_names iwl_dvm_cmd_names[] = {
HCMD_NAME(REPLY_ALIVE),
HCMD_NAME(REPLY_ERROR),
HCMD_NAME(REPLY_ECHO),
HCMD_NAME(REPLY_RXON),
HCMD_NAME(REPLY_RXON_ASSOC),
HCMD_NAME(REPLY_QOS_PARAM),
HCMD_NAME(REPLY_RXON_TIMING),
HCMD_NAME(REPLY_ADD_STA),
HCMD_NAME(REPLY_REMOVE_STA),
HCMD_NAME(REPLY_REMOVE_ALL_STA),
HCMD_NAME(REPLY_TX),
HCMD_NAME(REPLY_TXFIFO_FLUSH),
HCMD_NAME(REPLY_WEPKEY),
HCMD_NAME(REPLY_LEDS_CMD),
HCMD_NAME(REPLY_TX_LINK_QUALITY_CMD),
HCMD_NAME(COEX_PRIORITY_TABLE_CMD),
HCMD_NAME(COEX_MEDIUM_NOTIFICATION),
HCMD_NAME(COEX_EVENT_CMD),
HCMD_NAME(TEMPERATURE_NOTIFICATION),
HCMD_NAME(CALIBRATION_CFG_CMD),
HCMD_NAME(CALIBRATION_RES_NOTIFICATION),
HCMD_NAME(CALIBRATION_COMPLETE_NOTIFICATION),
HCMD_NAME(REPLY_QUIET_CMD),
HCMD_NAME(REPLY_CHANNEL_SWITCH),
HCMD_NAME(CHANNEL_SWITCH_NOTIFICATION),
HCMD_NAME(REPLY_SPECTRUM_MEASUREMENT_CMD),
HCMD_NAME(SPECTRUM_MEASURE_NOTIFICATION),
HCMD_NAME(POWER_TABLE_CMD),
HCMD_NAME(PM_SLEEP_NOTIFICATION),
HCMD_NAME(PM_DEBUG_STATISTIC_NOTIFIC),
HCMD_NAME(REPLY_SCAN_CMD),
HCMD_NAME(REPLY_SCAN_ABORT_CMD),
HCMD_NAME(SCAN_START_NOTIFICATION),
HCMD_NAME(SCAN_RESULTS_NOTIFICATION),
HCMD_NAME(SCAN_COMPLETE_NOTIFICATION),
HCMD_NAME(BEACON_NOTIFICATION),
HCMD_NAME(REPLY_TX_BEACON),
HCMD_NAME(WHO_IS_AWAKE_NOTIFICATION),
HCMD_NAME(REPLY_TX_POWER_DBM_CMD),
HCMD_NAME(QUIET_NOTIFICATION),
HCMD_NAME(REPLY_TX_PWR_TABLE_CMD),
HCMD_NAME(REPLY_TX_POWER_DBM_CMD_V1),
HCMD_NAME(TX_ANT_CONFIGURATION_CMD),
HCMD_NAME(MEASURE_ABORT_NOTIFICATION),
HCMD_NAME(REPLY_BT_CONFIG),
HCMD_NAME(REPLY_STATISTICS_CMD),
HCMD_NAME(STATISTICS_NOTIFICATION),
HCMD_NAME(REPLY_CARD_STATE_CMD),
HCMD_NAME(CARD_STATE_NOTIFICATION),
HCMD_NAME(MISSED_BEACONS_NOTIFICATION),
HCMD_NAME(REPLY_CT_KILL_CONFIG_CMD),
HCMD_NAME(SENSITIVITY_CMD),
HCMD_NAME(REPLY_PHY_CALIBRATION_CMD),
HCMD_NAME(REPLY_WIPAN_PARAMS),
HCMD_NAME(REPLY_WIPAN_RXON),
HCMD_NAME(REPLY_WIPAN_RXON_TIMING),
HCMD_NAME(REPLY_WIPAN_RXON_ASSOC),
HCMD_NAME(REPLY_WIPAN_QOS_PARAM),
HCMD_NAME(REPLY_WIPAN_WEPKEY),
HCMD_NAME(REPLY_WIPAN_P2P_CHANNEL_SWITCH),
HCMD_NAME(REPLY_WIPAN_NOA_NOTIFICATION),
HCMD_NAME(REPLY_WIPAN_DEACTIVATION_COMPLETE),
HCMD_NAME(REPLY_RX_PHY_CMD),
HCMD_NAME(REPLY_RX_MPDU_CMD),
HCMD_NAME(REPLY_RX),
HCMD_NAME(REPLY_COMPRESSED_BA),
HCMD_NAME(REPLY_BT_COEX_PRIO_TABLE),
HCMD_NAME(REPLY_BT_COEX_PROT_ENV),
HCMD_NAME(REPLY_BT_COEX_PROFILE_NOTIF),
HCMD_NAME(REPLY_D3_CONFIG),
HCMD_NAME(REPLY_WOWLAN_PATTERNS),
HCMD_NAME(REPLY_WOWLAN_WAKEUP_FILTER),
HCMD_NAME(REPLY_WOWLAN_TSC_RSC_PARAMS),
HCMD_NAME(REPLY_WOWLAN_TKIP_PARAMS),
HCMD_NAME(REPLY_WOWLAN_KEK_KCK_MATERIAL),
HCMD_NAME(REPLY_WOWLAN_GET_STATUS),
};
static const struct iwl_hcmd_arr iwl_dvm_groups[] = {
[0x0] = HCMD_ARR(iwl_dvm_cmd_names),
};
static const struct iwl_op_mode_ops iwl_dvm_ops;
void iwl_update_chain_flags(struct iwl_priv *priv)
@ -341,7 +429,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
/* Make sure device is powered up for SRAM reads */
if (!iwl_trans_grab_nic_access(priv->trans, false, &reg_flags))
if (!iwl_trans_grab_nic_access(priv->trans, &reg_flags))
return;
/* Set starting address; reads will auto-increment */
@ -1244,7 +1332,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED;
trans_cfg.command_names = iwl_dvm_cmd_strings;
trans_cfg.command_groups = iwl_dvm_groups;
trans_cfg.command_groups_size = ARRAY_SIZE(iwl_dvm_groups);
trans_cfg.cmd_fifo = IWLAGN_CMD_FIFO_NUM;
WARN_ON(sizeof(priv->transport_queue_stop) * BITS_PER_BYTE <
@ -1265,6 +1355,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
trans->command_groups = trans_cfg.command_groups;
trans->command_groups_size = trans_cfg.command_groups_size;
/* At this point both hw and priv are allocated. */
@ -1639,7 +1731,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
/* Make sure device is powered up for SRAM reads */
if (!iwl_trans_grab_nic_access(trans, false, &reg_flags))
if (!iwl_trans_grab_nic_access(trans, &reg_flags))
return pos;
/* Set starting address; reads will auto-increment */

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portionhelp of the ieee80211 subsystem header files.
@ -22,7 +23,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -32,91 +33,13 @@
#include <linux/sched.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>
#include "iwl-trans.h"
#include "iwl-io.h"
#include "dev.h"
#include "calib.h"
#include "agn.h"
#define IWL_CMD_ENTRY(x) [x] = #x
const char *const iwl_dvm_cmd_strings[REPLY_MAX + 1] = {
IWL_CMD_ENTRY(REPLY_ALIVE),
IWL_CMD_ENTRY(REPLY_ERROR),
IWL_CMD_ENTRY(REPLY_ECHO),
IWL_CMD_ENTRY(REPLY_RXON),
IWL_CMD_ENTRY(REPLY_RXON_ASSOC),
IWL_CMD_ENTRY(REPLY_QOS_PARAM),
IWL_CMD_ENTRY(REPLY_RXON_TIMING),
IWL_CMD_ENTRY(REPLY_ADD_STA),
IWL_CMD_ENTRY(REPLY_REMOVE_STA),
IWL_CMD_ENTRY(REPLY_REMOVE_ALL_STA),
IWL_CMD_ENTRY(REPLY_TXFIFO_FLUSH),
IWL_CMD_ENTRY(REPLY_WEPKEY),
IWL_CMD_ENTRY(REPLY_TX),
IWL_CMD_ENTRY(REPLY_LEDS_CMD),
IWL_CMD_ENTRY(REPLY_TX_LINK_QUALITY_CMD),
IWL_CMD_ENTRY(COEX_PRIORITY_TABLE_CMD),
IWL_CMD_ENTRY(COEX_MEDIUM_NOTIFICATION),
IWL_CMD_ENTRY(COEX_EVENT_CMD),
IWL_CMD_ENTRY(REPLY_QUIET_CMD),
IWL_CMD_ENTRY(REPLY_CHANNEL_SWITCH),
IWL_CMD_ENTRY(CHANNEL_SWITCH_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_SPECTRUM_MEASUREMENT_CMD),
IWL_CMD_ENTRY(SPECTRUM_MEASURE_NOTIFICATION),
IWL_CMD_ENTRY(POWER_TABLE_CMD),
IWL_CMD_ENTRY(PM_SLEEP_NOTIFICATION),
IWL_CMD_ENTRY(PM_DEBUG_STATISTIC_NOTIFIC),
IWL_CMD_ENTRY(REPLY_SCAN_CMD),
IWL_CMD_ENTRY(REPLY_SCAN_ABORT_CMD),
IWL_CMD_ENTRY(SCAN_START_NOTIFICATION),
IWL_CMD_ENTRY(SCAN_RESULTS_NOTIFICATION),
IWL_CMD_ENTRY(SCAN_COMPLETE_NOTIFICATION),
IWL_CMD_ENTRY(BEACON_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_TX_BEACON),
IWL_CMD_ENTRY(WHO_IS_AWAKE_NOTIFICATION),
IWL_CMD_ENTRY(QUIET_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_TX_PWR_TABLE_CMD),
IWL_CMD_ENTRY(MEASURE_ABORT_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_BT_CONFIG),
IWL_CMD_ENTRY(REPLY_STATISTICS_CMD),
IWL_CMD_ENTRY(STATISTICS_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_CARD_STATE_CMD),
IWL_CMD_ENTRY(CARD_STATE_NOTIFICATION),
IWL_CMD_ENTRY(MISSED_BEACONS_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_CT_KILL_CONFIG_CMD),
IWL_CMD_ENTRY(SENSITIVITY_CMD),
IWL_CMD_ENTRY(REPLY_PHY_CALIBRATION_CMD),
IWL_CMD_ENTRY(REPLY_RX_PHY_CMD),
IWL_CMD_ENTRY(REPLY_RX_MPDU_CMD),
IWL_CMD_ENTRY(REPLY_COMPRESSED_BA),
IWL_CMD_ENTRY(CALIBRATION_CFG_CMD),
IWL_CMD_ENTRY(CALIBRATION_RES_NOTIFICATION),
IWL_CMD_ENTRY(CALIBRATION_COMPLETE_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_TX_POWER_DBM_CMD),
IWL_CMD_ENTRY(TEMPERATURE_NOTIFICATION),
IWL_CMD_ENTRY(TX_ANT_CONFIGURATION_CMD),
IWL_CMD_ENTRY(REPLY_BT_COEX_PROFILE_NOTIF),
IWL_CMD_ENTRY(REPLY_BT_COEX_PRIO_TABLE),
IWL_CMD_ENTRY(REPLY_BT_COEX_PROT_ENV),
IWL_CMD_ENTRY(REPLY_WIPAN_PARAMS),
IWL_CMD_ENTRY(REPLY_WIPAN_RXON),
IWL_CMD_ENTRY(REPLY_WIPAN_RXON_TIMING),
IWL_CMD_ENTRY(REPLY_WIPAN_RXON_ASSOC),
IWL_CMD_ENTRY(REPLY_WIPAN_QOS_PARAM),
IWL_CMD_ENTRY(REPLY_WIPAN_WEPKEY),
IWL_CMD_ENTRY(REPLY_WIPAN_P2P_CHANNEL_SWITCH),
IWL_CMD_ENTRY(REPLY_WIPAN_NOA_NOTIFICATION),
IWL_CMD_ENTRY(REPLY_WIPAN_DEACTIVATION_COMPLETE),
IWL_CMD_ENTRY(REPLY_WOWLAN_PATTERNS),
IWL_CMD_ENTRY(REPLY_WOWLAN_WAKEUP_FILTER),
IWL_CMD_ENTRY(REPLY_WOWLAN_TSC_RSC_PARAMS),
IWL_CMD_ENTRY(REPLY_WOWLAN_TKIP_PARAMS),
IWL_CMD_ENTRY(REPLY_WOWLAN_KEK_KCK_MATERIAL),
IWL_CMD_ENTRY(REPLY_WOWLAN_GET_STATUS),
IWL_CMD_ENTRY(REPLY_D3_CONFIG),
};
#undef IWL_CMD_ENTRY
/******************************************************************************
*
* Generic RX handler implementations
@ -1095,7 +1018,9 @@ void iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct napi_struct *napi,
} else {
/* No handling needed */
IWL_DEBUG_RX(priv, "No handler needed for %s, 0x%02x\n",
iwl_dvm_get_cmd_string(pkt->hdr.cmd),
iwl_get_cmd_string(priv->trans,
iwl_cmd_id(pkt->hdr.cmd,
0, 0)),
pkt->hdr.cmd);
}
}

View File

@ -20,7 +20,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include <linux/slab.h>

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@ -184,7 +184,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
priv->thermal_throttle.ct_kill_toggle = true;
}
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
if (iwl_trans_grab_nic_access(priv->trans, false, &flags))
if (iwl_trans_grab_nic_access(priv->trans, &flags))
iwl_trans_release_nic_access(priv->trans, &flags);
/* Reschedule the ct_kill timer to occur in

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_tt_setting_h__

View File

@ -22,7 +22,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -383,6 +383,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
iwlagn_tx_cmd_build_rate(priv, tx_cmd, info, sta, fc);
memset(&info->status, 0, sizeof(info->status));
memset(info->driver_data, 0, sizeof(info->driver_data));
info->driver_data[0] = ctx;
info->driver_data[1] = dev_cmd;

View File

@ -27,7 +27,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -83,7 +83,7 @@
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_9000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_queues = 31,
.pll_cfg_val = 0,
.shadow_ram_support = true,
.led_compensation = 57,

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -1,6 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2009 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@ -51,6 +52,22 @@ TRACE_EVENT(iwlwifi_dev_tx_data,
TP_printk("[%s] TX frame data", __get_str(dev))
);
TRACE_EVENT(iwlwifi_dev_tx_tso_chunk,
TP_PROTO(const struct device *dev,
u8 *data_src, size_t data_len),
TP_ARGS(dev, data_src, data_len),
TP_STRUCT__entry(
DEV_ENTRY
__dynamic_array(u8, data, data_len)
),
TP_fast_assign(
DEV_ASSIGN;
memcpy(__get_dynamic_array(data), data_src, data_len);
),
TP_printk("[%s] TX frame data", __get_str(dev))
);
TRACE_EVENT(iwlwifi_dev_rx_data,
TP_PROTO(const struct device *dev,
const struct iwl_trans *trans,

View File

@ -20,7 +20,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -594,7 +594,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces,
struct iwl_ucode_capabilities *capa)
struct iwl_ucode_capabilities *capa,
bool *usniffer_images)
{
struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
struct iwl_ucode_tlv *tlv;
@ -607,7 +608,6 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
char buildstr[25];
u32 build, paging_mem_size;
int num_of_cpus;
bool usniffer_images = false;
bool usniffer_req = false;
bool gscan_capa = false;
@ -980,7 +980,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
break;
}
case IWL_UCODE_TLV_SEC_RT_USNIFFER:
usniffer_images = true;
*usniffer_images = true;
iwl_store_ucode_sec(pieces, tlv_data,
IWL_UCODE_REGULAR_USNIFFER,
tlv_len);
@ -1031,7 +1031,7 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
}
}
if (usniffer_req && !usniffer_images) {
if (usniffer_req && !*usniffer_images) {
IWL_ERR(drv,
"user selected to work with usniffer but usniffer image isn't available in ucode package\n");
return -EINVAL;
@ -1192,6 +1192,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
u32 api_ver;
int i;
bool load_module = false;
bool usniffer_images = false;
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size =
@ -1229,7 +1230,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
err = iwl_parse_v1_v2_firmware(drv, ucode_raw, pieces);
else
err = iwl_parse_tlv_firmware(drv, ucode_raw, pieces,
&fw->ucode_capa);
&fw->ucode_capa, &usniffer_images);
if (err)
goto try_again;

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -69,7 +69,7 @@
/* for all modules */
#define DRV_NAME "iwlwifi"
#define DRV_COPYRIGHT "Copyright(c) 2003- 2015 Intel Corporation"
#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define DRV_AUTHOR "<linuxwifi@intel.com>"
/* radio config bits (actual values from NVM definition) */
#define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */

View File

@ -454,11 +454,11 @@ static void iwl_eeprom_enhanced_txpower(struct device *dev,
TXP_CHECK_AND_PRINT(COMMON_TYPE),
txp->flags);
IWL_DEBUG_EEPROM(dev,
"\t\t chain_A: 0x%02x chain_B: 0X%02x chain_C: 0X%02x\n",
"\t\t chain_A: %d chain_B: %d chain_C: %d\n",
txp->chain_a_max, txp->chain_b_max,
txp->chain_c_max);
IWL_DEBUG_EEPROM(dev,
"\t\t MIMO2: 0x%02x MIMO3: 0x%02x High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n",
"\t\t MIMO2: %d MIMO3: %d High 20_on_40: 0x%02x Low 20_on_40: 0x%02x\n",
txp->mimo2_max, txp->mimo3_max,
((txp->delta_20_in_40 & 0xf0) >> 4),
(txp->delta_20_in_40 & 0x0f));

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@ -82,7 +82,7 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
{
u32 value = 0x5a5a5a5a;
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
value = iwl_read32(trans, reg);
iwl_trans_release_nic_access(trans, &flags);
}
@ -95,7 +95,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
{
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
iwl_write32(trans, reg, value);
iwl_trans_release_nic_access(trans, &flags);
}
@ -138,7 +138,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
unsigned long flags;
u32 val = 0x5a5a5a5a;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
val = iwl_read_prph_no_grab(trans, ofs);
iwl_trans_release_nic_access(trans, &flags);
}
@ -150,7 +150,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
{
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
iwl_write_prph_no_grab(trans, ofs, val);
iwl_trans_release_nic_access(trans, &flags);
}
@ -176,7 +176,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
{
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
iwl_write_prph_no_grab(trans, ofs,
iwl_read_prph_no_grab(trans, ofs) |
mask);
@ -190,7 +190,7 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
{
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
iwl_write_prph_no_grab(trans, ofs,
(iwl_read_prph_no_grab(trans, ofs) &
mask) | bits);
@ -204,7 +204,7 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
unsigned long flags;
u32 val;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
if (iwl_trans_grab_nic_access(trans, &flags)) {
val = iwl_read_prph_no_grab(trans, ofs);
iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
iwl_trans_release_nic_access(trans, &flags);

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -27,7 +27,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -123,6 +123,8 @@ struct iwl_cfg;
* received on the RSS queue(s). The queue parameter indicates which of the
* RSS queues received this frame; it will always be non-zero.
* This method must not sleep.
* @async_cb: called when an ASYNC command with CMD_WANT_ASYNC_CALLBACK set
* completes. Must be atomic.
* @queue_full: notifies that a HW queue is full.
* Must be atomic and called with BH disabled.
* @queue_not_full: notifies that a HW queue is not full any more.
@ -155,6 +157,8 @@ struct iwl_op_mode_ops {
struct iwl_rx_cmd_buffer *rxb);
void (*rx_rss)(struct iwl_op_mode *op_mode, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, unsigned int queue);
void (*async_cb)(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd);
void (*queue_full)(struct iwl_op_mode *op_mode, int queue);
void (*queue_not_full)(struct iwl_op_mode *op_mode, int queue);
bool (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
@ -203,6 +207,13 @@ static inline void iwl_op_mode_rx_rss(struct iwl_op_mode *op_mode,
op_mode->ops->rx_rss(op_mode, napi, rxb, queue);
}
static inline void iwl_op_mode_async_cb(struct iwl_op_mode *op_mode,
const struct iwl_device_cmd *cmd)
{
if (op_mode->ops->async_cb)
op_mode->ops->async_cb(op_mode, cmd);
}
static inline void iwl_op_mode_queue_full(struct iwl_op_mode *op_mode,
int queue)
{

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -25,7 +25,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -61,7 +61,10 @@
*
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/bsearch.h>
#include "iwl-trans.h"
#include "iwl-drv.h"
struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
struct device *dev,
@ -112,3 +115,91 @@ void iwl_trans_free(struct iwl_trans *trans)
kmem_cache_destroy(trans->dev_cmd_pool);
kfree(trans);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
{
int ret;
if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
test_bit(STATUS_RFKILL, &trans->status)))
return -ERFKILL;
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
if (WARN_ON((cmd->flags & CMD_WANT_ASYNC_CALLBACK) &&
!(cmd->flags & CMD_ASYNC)))
return -EINVAL;
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
ret = trans->ops->send_cmd(trans, cmd);
if (!(cmd->flags & CMD_ASYNC))
lock_map_release(&trans->sync_cmd_lockdep_map);
return ret;
}
IWL_EXPORT_SYMBOL(iwl_trans_send_cmd);
/* Comparator for struct iwl_hcmd_names.
* Used in the binary search over a list of host commands.
*
* @key: command_id that we're looking for.
* @elt: struct iwl_hcmd_names candidate for match.
*
* @return 0 iff equal.
*/
static int iwl_hcmd_names_cmp(const void *key, const void *elt)
{
const struct iwl_hcmd_names *name = elt;
u8 cmd1 = *(u8 *)key;
u8 cmd2 = name->cmd_id;
return (cmd1 - cmd2);
}
const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id)
{
u8 grp, cmd;
struct iwl_hcmd_names *ret;
const struct iwl_hcmd_arr *arr;
size_t size = sizeof(struct iwl_hcmd_names);
grp = iwl_cmd_groupid(id);
cmd = iwl_cmd_opcode(id);
if (!trans->command_groups || grp >= trans->command_groups_size ||
!trans->command_groups[grp].arr)
return "UNKNOWN";
arr = &trans->command_groups[grp];
ret = bsearch(&cmd, arr->arr, arr->size, size, iwl_hcmd_names_cmp);
if (!ret)
return "UNKNOWN";
return ret->cmd_name;
}
IWL_EXPORT_SYMBOL(iwl_get_cmd_string);
int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans)
{
int i, j;
const struct iwl_hcmd_arr *arr;
for (i = 0; i < trans->command_groups_size; i++) {
arr = &trans->command_groups[i];
if (!arr->arr)
continue;
for (j = 0; j < arr->size - 1; j++)
if (arr->arr[j].cmd_id > arr->arr[j + 1].cmd_id)
return -1;
}
return 0;
}
IWL_EXPORT_SYMBOL(iwl_cmd_groups_verify_sorted);

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -68,6 +68,7 @@
#include <linux/ieee80211.h>
#include <linux/mm.h> /* for page_address */
#include <linux/lockdep.h>
#include <linux/kernel.h>
#include "iwl-debug.h"
#include "iwl-config.h"
@ -248,6 +249,8 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
* @CMD_MAKE_TRANS_IDLE: The command response should mark the trans as idle.
* @CMD_WAKE_UP_TRANS: The command response should wake up the trans
* (i.e. mark it as non-idle).
* @CMD_WANT_ASYNC_CALLBACK: the op_mode's async callback function must be
* called after this command completes. Valid only with CMD_ASYNC.
* @CMD_TB_BITMAP_POS: Position of the first bit for the TB bitmap. We need to
* check that we leave enough room for the TBs bitmap which needs 20 bits.
*/
@ -259,6 +262,7 @@ enum CMD_MODE {
CMD_SEND_IN_IDLE = BIT(4),
CMD_MAKE_TRANS_IDLE = BIT(5),
CMD_WAKE_UP_TRANS = BIT(6),
CMD_WANT_ASYNC_CALLBACK = BIT(7),
CMD_TB_BITMAP_POS = 11,
};
@ -377,6 +381,11 @@ static inline void iwl_free_rxb(struct iwl_rx_cmd_buffer *r)
#define MAX_NO_RECLAIM_CMDS 6
/*
* The first entry in driver_data array in ieee80211_tx_info
* that can be used by the transport.
*/
#define IWL_TRANS_FIRST_DRIVER_DATA 2
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
/*
@ -439,6 +448,22 @@ iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
}
}
struct iwl_hcmd_names {
u8 cmd_id;
const char *const cmd_name;
};
#define HCMD_NAME(x) \
{ .cmd_id = x, .cmd_name = #x }
struct iwl_hcmd_arr {
const struct iwl_hcmd_names *arr;
int size;
};
#define HCMD_ARR(x) \
{ .arr = x, .size = ARRAY_SIZE(x) }
/**
* struct iwl_trans_config - transport configuration
*
@ -458,8 +483,10 @@ iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
* in DWORD (as opposed to bytes)
* @scd_set_active: should the transport configure the SCD for HCMD queue
* @wide_cmd_header: firmware supports wide host command header
* @command_names: array of command names, must be 256 entries
* (one for each command); for debugging only
* @sw_csum_tx: transport should compute the TCP checksum
* @command_groups: array of command groups, each member is an array of the
* commands in the group; for debugging only
* @command_groups_size: number of command groups, to avoid illegal access
* @sdio_adma_addr: the default address to set for the ADMA in SDIO mode until
* we get the ALIVE from the uCode
*/
@ -476,8 +503,10 @@ struct iwl_trans_config {
bool bc_table_dword;
bool scd_set_active;
bool wide_cmd_header;
const char *const *command_names;
bool sw_csum_tx;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
u32 sdio_adma_addr;
};
@ -528,7 +557,11 @@ struct iwl_trans_txq_scd_cfg {
* If RFkill is asserted in the middle of a SYNC host command, it must
* return -ERFKILL straight away.
* May sleep only if CMD_ASYNC is not set
* @tx: send an skb
* @tx: send an skb. The transport relies on the op_mode to zero the
* the ieee80211_tx_info->driver_data. If the MPDU is an A-MSDU, all
* the CSUM will be taken care of (TCP CSUM and IP header in case of
* IPv4). If the MPDU is a single MSDU, the op_mode must compute the IP
* header if it is IPv4.
* Must be atomic
* @reclaim: free packet until ssn. Returns a list of freed packets.
* Must be atomic
@ -542,6 +575,11 @@ struct iwl_trans_txq_scd_cfg {
* @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
* @freeze_txq_timer: prevents the timer of the queue from firing until the
* queue is set to awake. Must be atomic.
* @block_txq_ptrs: stop updating the write pointers of the Tx queues. Note
* that the transport needs to refcount the calls since this function
* will be called several times with block = true, and then the queues
* need to be unblocked only after the same number of calls with
* block = false.
* @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR
@ -600,6 +638,7 @@ struct iwl_trans_ops {
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
bool freeze);
void (*block_txq_ptrs)(struct iwl_trans *trans, bool block);
void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
@ -613,8 +652,7 @@ struct iwl_trans_ops {
void (*configure)(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg);
void (*set_pmi)(struct iwl_trans *trans, bool state);
bool (*grab_nic_access)(struct iwl_trans *trans, bool silent,
unsigned long *flags);
bool (*grab_nic_access)(struct iwl_trans *trans, unsigned long *flags);
void (*release_nic_access)(struct iwl_trans *trans,
unsigned long *flags);
void (*set_bits_mask)(struct iwl_trans *trans, u32 reg, u32 mask,
@ -641,18 +679,61 @@ enum iwl_trans_state {
};
/**
* enum iwl_d0i3_mode - d0i3 mode
* DOC: Platform power management
*
* @IWL_D0I3_MODE_OFF - d0i3 is disabled
* @IWL_D0I3_MODE_ON_IDLE - enter d0i3 when device is idle
* (e.g. no active references)
* @IWL_D0I3_MODE_ON_SUSPEND - enter d0i3 only on suspend
* (in case of 'any' trigger)
* There are two types of platform power management: system-wide
* (WoWLAN) and runtime.
*
* In system-wide power management the entire platform goes into a low
* power state (e.g. idle or suspend to RAM) at the same time and the
* device is configured as a wakeup source for the entire platform.
* This is usually triggered by userspace activity (e.g. the user
* presses the suspend button or a power management daemon decides to
* put the platform in low power mode). The device's behavior in this
* mode is dictated by the wake-on-WLAN configuration.
*
* In runtime power management, only the devices which are themselves
* idle enter a low power state. This is done at runtime, which means
* that the entire system is still running normally. This mode is
* usually triggered automatically by the device driver and requires
* the ability to enter and exit the low power modes in a very short
* time, so there is not much impact in usability.
*
* The terms used for the device's behavior are as follows:
*
* - D0: the device is fully powered and the host is awake;
* - D3: the device is in low power mode and only reacts to
* specific events (e.g. magic-packet received or scan
* results found);
* - D0I3: the device is in low power mode and reacts to any
* activity (e.g. RX);
*
* These terms reflect the power modes in the firmware and are not to
* be confused with the physical device power state. The NIC can be
* in D0I3 mode even if, for instance, the PCI device is in D3 state.
*/
enum iwl_d0i3_mode {
IWL_D0I3_MODE_OFF = 0,
IWL_D0I3_MODE_ON_IDLE,
IWL_D0I3_MODE_ON_SUSPEND,
/**
* enum iwl_plat_pm_mode - platform power management mode
*
* This enumeration describes the device's platform power management
* behavior when in idle mode (i.e. runtime power management) or when
* in system-wide suspend (i.e WoWLAN).
*
* @IWL_PLAT_PM_MODE_DISABLED: power management is disabled for this
* device. At runtime, this means that nothing happens and the
* device always remains in active. In system-wide suspend mode,
* it means that the all connections will be closed automatically
* by mac80211 before the platform is suspended.
* @IWL_PLAT_PM_MODE_D3: the device goes into D3 mode (i.e. WoWLAN).
* For runtime power management, this mode is not officially
* supported.
* @IWL_PLAT_PM_MODE_D0I3: the device goes into D0I3 mode.
*/
enum iwl_plat_pm_mode {
IWL_PLAT_PM_MODE_DISABLED,
IWL_PLAT_PM_MODE_D3,
IWL_PLAT_PM_MODE_D0I3,
};
/**
@ -692,6 +773,12 @@ enum iwl_d0i3_mode {
* the opmode.
* @paging_download_buf: Buffer used for copying all of the pages before
* downloading them to the FW. The buffer is allocated in the opmode
* @system_pm_mode: the system-wide power management mode in use.
* This mode is set dynamically, depending on the WoWLAN values
* configured from the userspace at runtime.
* @runtime_pm_mode: the runtime power management mode in use. This
* mode is set during the initialization phase and is not
* supposed to change during runtime.
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@ -711,6 +798,9 @@ struct iwl_trans {
bool pm_support;
bool ltr_enabled;
const struct iwl_hcmd_arr *command_groups;
int command_groups_size;
u8 num_rx_queues;
/* The following fields are internal only */
@ -739,21 +829,24 @@ struct iwl_trans {
struct iwl_fw_paging *paging_db;
void *paging_download_buf;
enum iwl_d0i3_mode d0i3_mode;
bool wowlan_d0i3;
enum iwl_plat_pm_mode system_pm_mode;
enum iwl_plat_pm_mode runtime_pm_mode;
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
};
const char *iwl_get_cmd_string(struct iwl_trans *trans, u32 id);
int iwl_cmd_groups_verify_sorted(const struct iwl_trans_config *trans);
static inline void iwl_trans_configure(struct iwl_trans *trans,
const struct iwl_trans_config *trans_cfg)
{
trans->op_mode = trans_cfg->op_mode;
trans->ops->configure(trans, trans_cfg);
WARN_ON(iwl_cmd_groups_verify_sorted(trans_cfg));
}
static inline int _iwl_trans_start_hw(struct iwl_trans *trans, bool low_power)
@ -880,34 +973,6 @@ iwl_trans_dump_data(struct iwl_trans *trans,
return trans->ops->dump_data(trans, trigger);
}
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
int ret;
if (unlikely(!(cmd->flags & CMD_SEND_IN_RFKILL) &&
test_bit(STATUS_RFKILL, &trans->status)))
return -ERFKILL;
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
if (!(cmd->flags & CMD_ASYNC))
lock_map_acquire_read(&trans->sync_cmd_lockdep_map);
ret = trans->ops->send_cmd(trans, cmd);
if (!(cmd->flags & CMD_ASYNC))
lock_map_release(&trans->sync_cmd_lockdep_map);
return ret;
}
static inline struct iwl_device_cmd *
iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
{
@ -920,6 +985,8 @@ iwl_trans_alloc_tx_cmd(struct iwl_trans *trans)
(dev_cmd_ptr + trans->dev_cmd_headroom);
}
int iwl_trans_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
static inline void iwl_trans_free_tx_cmd(struct iwl_trans *trans,
struct iwl_device_cmd *dev_cmd)
{
@ -934,8 +1001,10 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
if (unlikely(test_bit(STATUS_FW_ERROR, &trans->status)))
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
return trans->ops->tx(trans, skb, dev_cmd, queue);
}
@ -943,8 +1012,10 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
int ssn, struct sk_buff_head *skbs)
{
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return;
}
trans->ops->reclaim(trans, queue, ssn, skbs);
}
@ -962,8 +1033,10 @@ iwl_trans_txq_enable_cfg(struct iwl_trans *trans, int queue, u16 ssn,
{
might_sleep();
if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return;
}
trans->ops->txq_enable(trans, queue, ssn, cfg, queue_wdg_timeout);
}
@ -1003,18 +1076,34 @@ static inline void iwl_trans_freeze_txq_timer(struct iwl_trans *trans,
unsigned long txqs,
bool freeze)
{
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return;
}
if (trans->ops->freeze_txq_timer)
trans->ops->freeze_txq_timer(trans, txqs, freeze);
}
static inline void iwl_trans_block_txq_ptrs(struct iwl_trans *trans,
bool block)
{
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return;
}
if (trans->ops->block_txq_ptrs)
trans->ops->block_txq_ptrs(trans, block);
}
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
u32 txqs)
{
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
if (WARN_ON_ONCE(trans->state != IWL_TRANS_FW_ALIVE)) {
IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
return trans->ops->wait_tx_queue_empty(trans, txqs);
}
@ -1092,9 +1181,9 @@ iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value)
trans->ops->set_bits_mask(trans, reg, mask, value);
}
#define iwl_trans_grab_nic_access(trans, silent, flags) \
#define iwl_trans_grab_nic_access(trans, flags) \
__cond_lock(nic_access, \
likely((trans)->ops->grab_nic_access(trans, silent, flags)))
likely((trans)->ops->grab_nic_access(trans, flags)))
static inline void __releases(nic_access)
iwl_trans_release_nic_access(struct iwl_trans *trans, unsigned long *flags)

View File

@ -1,12 +1,12 @@
obj-$(CONFIG_IWLMVM) += iwlmvm.o
iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += utils.o rx.o rxmq.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o
iwlmvm-y += power.o coex.o coex_legacy.o
iwlmvm-y += tt.o offloading.o tdls.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmvm-y += tof.o fw-dbg.o
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
iwlmvm-$(CONFIG_PM) += d3.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -106,6 +106,7 @@
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_80_20_FAR_RANGE_TWEAK 1
#define IWL_MVM_TOF_IS_RESPONDER 0
#define IWL_MVM_SW_TX_CSUM_OFFLOAD 0
#define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2
#define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -104,9 +104,13 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
struct inet6_ifaddr *ifa;
int idx = 0;
memset(mvmvif->tentative_addrs, 0, sizeof(mvmvif->tentative_addrs));
read_lock_bh(&idev->lock);
list_for_each_entry(ifa, &idev->addr_list, if_list) {
mvmvif->target_ipv6_addrs[idx] = ifa->addr;
if (ifa->flags & IFA_F_TENTATIVE)
__set_bit(idx, mvmvif->tentative_addrs);
idx++;
if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
break;
@ -775,6 +779,9 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
*/
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
/* the fw is reset, so all the keys are cleared */
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
mvm->ptk_ivlen = 0;
mvm->ptk_icvlen = 0;
mvm->ptk_ivlen = 0;
@ -797,6 +804,8 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
wowlan_config_cmd->is_11n_connection =
ap_sta->ht_cap.ht_supported;
wowlan_config_cmd->flags = ENABLE_L3_FILTERING |
ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING;
/* Query the last used seqno and set it */
ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
@ -846,15 +855,38 @@ iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
return 0;
}
static void
iwl_mvm_iter_d0i3_ap_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
void (*iter)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *key,
void *data),
void *data)
{
struct ieee80211_sta *ap_sta;
rcu_read_lock();
ap_sta = rcu_dereference(mvm->fw_id_to_mac_id[mvm->d0i3_ap_sta_id]);
if (IS_ERR_OR_NULL(ap_sta))
goto out;
ieee80211_iter_keys_rcu(mvm->hw, vif, iter, data);
out:
rcu_read_unlock();
}
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool configure_keys,
bool d0i3,
u32 cmd_flags)
{
struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
struct wowlan_key_data key_data = {
.configure_keys = configure_keys,
.configure_keys = !d0i3,
.use_rsc_tsc = false,
.tkip = &tkip_cmd,
.use_tkip = false,
@ -867,15 +899,28 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
return -ENOMEM;
/*
* Note that currently we don't propagate cmd_flags
* to the iterator. In case of key_data.configure_keys,
* all the configured commands are SYNC, and
* iwl_mvm_wowlan_program_keys() will take care of
* locking/unlocking mvm->mutex.
* if we have to configure keys, call ieee80211_iter_keys(),
* as we need non-atomic context in order to take the
* required locks.
* for the d0i3 we can't use ieee80211_iter_keys(), as
* taking (almost) any mutex might result in deadlock.
*/
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_wowlan_program_keys,
&key_data);
if (!d0i3) {
/*
* Note that currently we don't propagate cmd_flags
* to the iterator. In case of key_data.configure_keys,
* all the configured commands are SYNC, and
* iwl_mvm_wowlan_program_keys() will take care of
* locking/unlocking mvm->mutex.
*/
ieee80211_iter_keys(mvm->hw, vif,
iwl_mvm_wowlan_program_keys,
&key_data);
} else {
iwl_mvm_iter_d0i3_ap_keys(mvm, vif,
iwl_mvm_wowlan_program_keys,
&key_data);
}
if (key_data.error) {
ret = -EIO;
@ -900,7 +945,8 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
goto out;
}
if (mvmvif->rekey_data.valid) {
/* configure rekey data only if offloaded rekey is supported (d3) */
if (mvmvif->rekey_data.valid && !d0i3) {
memset(&kek_kck_cmd, 0, sizeof(kek_kck_cmd));
memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,
NL80211_KCK_LEN);
@ -917,6 +963,7 @@ int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
if (ret)
goto out;
}
ret = 0;
out:
kfree(key_data.rsc_tsc);
return ret;
@ -946,8 +993,11 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
* that isn't really a problem though.
*/
mutex_unlock(&mvm->mutex);
iwl_mvm_wowlan_config_key_params(mvm, vif, true, CMD_ASYNC);
ret = iwl_mvm_wowlan_config_key_params(mvm, vif, false,
CMD_ASYNC);
mutex_lock(&mvm->mutex);
if (ret)
return ret;
}
ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
@ -960,7 +1010,7 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
if (ret)
return ret;
ret = iwl_mvm_send_proto_offload(mvm, vif, false, 0);
ret = iwl_mvm_send_proto_offload(mvm, vif, false, true, 0);
if (ret)
return ret;
@ -1179,19 +1229,20 @@ remove_notif:
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_trans *trans = mvm->trans;
int ret;
/* make sure the d0i3 exit work is not pending */
flush_work(&mvm->d0i3_exit_work);
ret = iwl_trans_suspend(mvm->trans);
ret = iwl_trans_suspend(trans);
if (ret)
return ret;
mvm->trans->wowlan_d0i3 = wowlan->any;
if (mvm->trans->wowlan_d0i3) {
/* 'any' trigger means d0i3 usage */
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
if (wowlan->any) {
trans->system_pm_mode = IWL_PLAT_PM_MODE_D0I3;
if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
ret = iwl_mvm_enter_d0i3_sync(mvm);
if (ret)
@ -1202,11 +1253,13 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
mutex_unlock(&mvm->d0i3_suspend_mutex);
iwl_trans_d3_suspend(mvm->trans, false);
iwl_trans_d3_suspend(trans, false);
return 0;
}
trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
return __iwl_mvm_suspend(hw, wowlan, false);
}
@ -1711,6 +1764,29 @@ out_unlock:
return false;
}
void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status)
{
struct iwl_mvm_d3_gtk_iter_data gtkdata = {
.status = status,
};
/*
* rekey handling requires taking locks that can't be taken now.
* however, d0i3 doesn't offload rekey, so we're fine.
*/
if (WARN_ON_ONCE(status->num_of_gtk_rekeys))
return;
/* find last GTK that we used initially, if any */
gtkdata.find_phase = true;
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
gtkdata.find_phase = false;
iwl_mvm_iter_d0i3_ap_keys(mvm, vif, iwl_mvm_d3_update_keys, &gtkdata);
}
struct iwl_mvm_nd_query_results {
u32 matched_profiles;
struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
@ -1969,8 +2045,9 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
{
bool exit_now;
enum iwl_d3_status d3_status;
struct iwl_trans *trans = mvm->trans;
iwl_trans_d3_resume(mvm->trans, &d3_status, false);
iwl_trans_d3_resume(trans, &d3_status, false);
/*
* make sure to clear D0I3_DEFER_WAKEUP before
@ -1987,9 +2064,9 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
_iwl_mvm_exit_d0i3(mvm);
}
iwl_trans_resume(mvm->trans);
iwl_trans_resume(trans);
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND) {
if (iwl_mvm_enter_d0i3_on_suspend(mvm)) {
int ret = iwl_mvm_exit_d0i3(mvm->hw->priv);
if (ret)
@ -2005,12 +2082,16 @@ static int iwl_mvm_resume_d0i3(struct iwl_mvm *mvm)
int iwl_mvm_resume(struct ieee80211_hw *hw)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
/* 'any' trigger means d0i3 was used */
if (hw->wiphy->wowlan_config->any)
return iwl_mvm_resume_d0i3(mvm);
if (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3)
ret = iwl_mvm_resume_d0i3(mvm);
else
return iwl_mvm_resume_d3(mvm);
ret = iwl_mvm_resume_d3(mvm);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
return ret;
}
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled)
@ -2034,6 +2115,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
ieee80211_stop_queues(mvm->hw);
synchronize_net();
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
/* start pseudo D3 */
rtnl_lock();
err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
@ -2088,9 +2171,13 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
int remaining_time = 10;
mvm->d3_test_active = false;
rtnl_lock();
__iwl_mvm_resume(mvm, true);
rtnl_unlock();
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
iwl_abort_notification_waits(&mvm->notif_wait);
ieee80211_restart_hw(mvm->hw);

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -1029,7 +1029,8 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
if (ret)
return ret;
iwl_mvm_fw_dbg_collect(mvm, FW_DBG_TRIGGER_USER, NULL, 0, NULL);
iwl_mvm_fw_dbg_collect(mvm, FW_DBG_TRIGGER_USER, buf,
(count - 1), NULL);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
@ -1316,6 +1317,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
PRINT_MVM_REF(IWL_MVM_REF_FW_DBG_COLLECT);
PRINT_MVM_REF(IWL_MVM_REF_INIT_UCODE);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@ -1450,7 +1452,7 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -94,10 +95,14 @@ struct iwl_d3_manager_config {
* enum iwl_d3_proto_offloads - enabled protocol offloads
* @IWL_D3_PROTO_OFFLOAD_ARP: ARP data is enabled
* @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled
* @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid
* @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid
*/
enum iwl_proto_offloads {
IWL_D3_PROTO_OFFLOAD_ARP = BIT(0),
IWL_D3_PROTO_OFFLOAD_NS = BIT(1),
IWL_D3_PROTO_IPV4_VALID = BIT(2),
IWL_D3_PROTO_IPV6_VALID = BIT(3),
};
#define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2
@ -241,6 +246,13 @@ enum iwl_wowlan_wakeup_filters {
IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16),
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
enum iwl_wowlan_flags {
IS_11W_ASSOC = BIT(0),
ENABLE_L3_FILTERING = BIT(1),
ENABLE_NBNS_FILTERING = BIT(2),
ENABLE_DHCP_FILTERING = BIT(3),
};
struct iwl_wowlan_config_cmd {
__le32 wakeup_filter;
__le16 non_qos_seq;
@ -248,8 +260,9 @@ struct iwl_wowlan_config_cmd {
u8 wowlan_ba_teardown_tids;
u8 is_11n_connection;
u8 offloading_tid;
u8 reserved[3];
} __packed; /* WOWLAN_CONFIG_API_S_VER_3 */
u8 flags;
u8 reserved[2];
} __packed; /* WOWLAN_CONFIG_API_S_VER_4 */
/*
* WOWLAN_TSC_RSC_PARAMS

View File

@ -27,7 +27,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -79,6 +79,11 @@
#define IWL_RX_INFO_ENERGY_ANT_B_POS 8
#define IWL_RX_INFO_ENERGY_ANT_C_POS 16
enum iwl_mac_context_info {
MAC_CONTEXT_INFO_NONE,
MAC_CONTEXT_INFO_GSCAN,
};
/**
* struct iwl_rx_phy_info - phy info
* (REPLY_RX_PHY_CMD = 0xc0)
@ -97,6 +102,8 @@
* @frame_time: frame's time on the air, based on byte count and frame rate
* calculation
* @mac_active_msk: what MACs were active when the frame was received
* @mac_context_info: additional info on the context in which the frame was
* received as defined in &enum iwl_mac_context_info
*
* Before each Rx, the device sends this data. It contains PHY information
* about the reception of the packet.
@ -114,7 +121,8 @@ struct iwl_rx_phy_info {
__le32 non_cfg_phy[IWL_RX_INFO_PHY_CNT];
__le32 rate_n_flags;
__le32 byte_count;
__le16 mac_active_msk;
u8 mac_active_msk;
u8 mac_context_info;
__le16 frame_time;
} __packed;
@ -279,11 +287,17 @@ enum iwl_rx_mpdu_status {
IWL_RX_MPDU_STATUS_KEY_ERROR = BIT(4),
IWL_RX_MPDU_STATUS_ICV_OK = BIT(5),
IWL_RX_MPDU_STATUS_MIC_OK = BIT(6),
/* TODO - verify this is the correct value */
IWL_RX_MPDU_RES_STATUS_TTAK_OK = BIT(7),
IWL_RX_MPDU_STATUS_SEC_MASK = 0x7 << 8,
IWL_RX_MPDU_STATUS_SEC_NONE = 0x0 << 8,
IWL_RX_MPDU_STATUS_SEC_WEP = 0x1 << 8,
IWL_RX_MPDU_STATUS_SEC_CCM = 0x2 << 8,
IWL_RX_MPDU_STATUS_SEC_TKIP = 0x3 << 8,
/* TODO - define IWL_RX_MPDU_STATUS_SEC_EXT_ENC - this is a stub */
IWL_RX_MPDU_STATUS_SEC_EXT_ENC = 0x4 << 8,
/* TODO - define IWL_RX_MPDU_STATUS_SEC_GCM - this is a stub */
IWL_RX_MPDU_STATUS_SEC_GCM = 0x5 << 8,
IWL_RX_MPDU_STATUS_DECRYPTED = BIT(11),
IWL_RX_MPDU_STATUS_WEP_MATCH = BIT(12),
IWL_RX_MPDU_STATUS_EXT_IV_MATCH = BIT(13),
@ -302,6 +316,8 @@ enum iwl_rx_mpdu_sta_id_flags {
IWL_RX_MPDU_SIF_FILTER_STATUS_MASK = 0xc0,
};
#define IWL_RX_REORDER_DATA_INVALID_BAID 0x7f
enum iwl_rx_mpdu_reorder_data {
IWL_RX_MPDU_REORDER_NSSN_MASK = 0x00000fff,
IWL_RX_MPDU_REORDER_SN_MASK = 0x00fff000,

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -285,6 +285,8 @@ struct iwl_scan_channel_opt {
* @IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED: all passive scans will be fragmented
* @IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED: insert WFA vendor-specific TPC report
* and DS parameter set IEs into probe requests.
* @IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL: use extended dwell time on channels
* 1, 6 and 11.
* @IWL_MVM_LMAC_SCAN_FLAG_MATCH: Send match found notification on matches
*/
enum iwl_mvm_lmac_scan_flags {
@ -295,6 +297,7 @@ enum iwl_mvm_lmac_scan_flags {
IWL_MVM_LMAC_SCAN_FLAG_MULTIPLE_SSIDS = BIT(4),
IWL_MVM_LMAC_SCAN_FLAG_FRAGMENTED = BIT(5),
IWL_MVM_LMAC_SCAN_FLAGS_RRM_ENABLED = BIT(6),
IWL_MVM_LMAC_SCAN_FLAG_EXTENDED_DWELL = BIT(7),
IWL_MVM_LMAC_SCAN_FLAG_MATCH = BIT(9),
};
@ -322,6 +325,7 @@ enum iwl_scan_priority_ext {
* @active-dwell: dwell time for active channels
* @passive-dwell: dwell time for passive channels
* @fragmented-dwell: dwell time for fragmented passive scan
* @extended_dwell: dwell time for channels 1, 6 and 11 (in certain cases)
* @reserved2: for alignment and future use
* @rx_chain_selct: PHY_RX_CHAIN_* flags
* @scan_flags: &enum iwl_mvm_lmac_scan_flags
@ -346,7 +350,8 @@ struct iwl_scan_req_lmac {
u8 active_dwell;
u8 passive_dwell;
u8 fragmented_dwell;
__le16 reserved2;
u8 extended_dwell;
u8 reserved2;
__le16 rx_chain_select;
__le32 scan_flags;
__le32 max_out_time;
@ -490,7 +495,7 @@ enum iwl_channel_flags {
* @dwell_active: default dwell time for active scan
* @dwell_passive: default dwell time for passive scan
* @dwell_fragmented: default dwell time for fragmented scan
* @reserved: for future use and alignment
* @dwell_extended: default dwell time for channels 1, 6 and 11
* @mac_addr: default mac address to be used in probes
* @bcast_sta_id: the index of the station in the fw
* @channel_flags: default channel flags - enum iwl_channel_flags
@ -507,7 +512,7 @@ struct iwl_scan_config {
u8 dwell_active;
u8 dwell_passive;
u8 dwell_fragmented;
u8 reserved;
u8 dwell_extended;
u8 mac_addr[ETH_ALEN];
u8 bcast_sta_id;
u8 channel_flags;
@ -543,7 +548,8 @@ enum iwl_umac_scan_general_flags {
IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID = BIT(6),
IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED = BIT(7),
IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8),
IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9)
IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9),
IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL = BIT(10),
};
/**
@ -597,7 +603,7 @@ struct iwl_scan_req_umac_tail {
* @uid: scan id, &enum iwl_umac_scan_uid_offsets
* @ooc_priority: out of channel priority - &enum iwl_scan_priority
* @general_flags: &enum iwl_umac_scan_general_flags
* @reserved1: for future use and alignment
* @extended_dwell: dwell time for channels 1, 6 and 11
* @active_dwell: dwell time for active scan
* @passive_dwell: dwell time for passive scan
* @fragmented_dwell: dwell time for fragmented passive scan
@ -606,7 +612,7 @@ struct iwl_scan_req_umac_tail {
* @scan_priority: scan internal prioritization &enum iwl_scan_priority
* @channel_flags: &enum iwl_scan_channel_flags
* @n_channels: num of channels in scan request
* @reserved2: for future use and alignment
* @reserved: for future use and alignment
* @data: &struct iwl_scan_channel_cfg_umac and
* &struct iwl_scan_req_umac_tail
*/
@ -616,7 +622,7 @@ struct iwl_scan_req_umac {
__le32 ooc_priority;
/* SCAN_GENERAL_PARAMS_API_S_VER_1 */
__le32 general_flags;
u8 reserved1;
u8 extended_dwell;
u8 active_dwell;
u8 passive_dwell;
u8 fragmented_dwell;
@ -626,7 +632,7 @@ struct iwl_scan_req_umac {
/* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
u8 channel_flags;
u8 n_channels;
__le16 reserved2;
__le16 reserved;
u8 data[];
} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -270,6 +270,9 @@ enum {
REPLY_MAX = 0xff,
};
/* Please keep this enum *SORTED* by hex value.
* Needed for binary search, otherwise a warning will be triggered.
*/
enum iwl_phy_ops_subcmd_ids {
CMD_DTS_MEASUREMENT_TRIGGER_WIDE = 0x0,
DTS_MEASUREMENT_NOTIF_WIDE = 0xFF,
@ -277,6 +280,8 @@ enum iwl_phy_ops_subcmd_ids {
/* command groups */
enum {
LEGACY_GROUP = 0x0,
LONG_GROUP = 0x1,
PHY_OPS_GROUP = 0x4,
};

View File

@ -122,7 +122,7 @@ static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
unsigned long flags;
int i, j;
if (!iwl_trans_grab_nic_access(mvm->trans, false, &flags))
if (!iwl_trans_grab_nic_access(mvm->trans, &flags))
return;
/* Pull RXF data from all RXFs */
@ -349,6 +349,7 @@ static const struct {
{ .start = 0x00a04560, .end = 0x00a0457c },
{ .start = 0x00a04590, .end = 0x00a04598 },
{ .start = 0x00a045c0, .end = 0x00a045f4 },
{ .start = 0x00a44000, .end = 0x00a7bf80 },
};
static u32 iwl_dump_prph(struct iwl_trans *trans,
@ -358,7 +359,7 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
unsigned long flags;
u32 prph_len = 0, i;
if (!iwl_trans_grab_nic_access(trans, false, &flags))
if (!iwl_trans_grab_nic_access(trans, &flags))
return 0;
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
@ -383,7 +384,7 @@ static u32 iwl_dump_prph(struct iwl_trans *trans,
*val++ = cpu_to_le32(iwl_read_prph_no_grab(trans,
reg));
*data = iwl_fw_error_next_data(*data);
*data = iwl_fw_error_next_data(*data);
}
iwl_trans_release_nic_access(trans, &flags);
@ -400,7 +401,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_trigger_desc *dump_trig;
struct iwl_mvm_dump_ptrs *fw_error_dump;
u32 sram_len, sram_ofs;
u32 file_len, fifo_data_len = 0;
u32 file_len, fifo_data_len = 0, prph_len = 0;
u32 smem_len = mvm->cfg->smem_len;
u32 sram2_len = mvm->cfg->dccm2_len;
bool monitor_dump_only = false;
@ -460,12 +461,24 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_data) +
sizeof(struct iwl_fw_error_dump_fifo);
}
/* Make room for PRPH registers */
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4;
prph_len += sizeof(*dump_data) +
sizeof(struct iwl_fw_error_dump_prph) +
num_bytes_in_chunk;
}
}
file_len = sizeof(*dump_file) +
sizeof(*dump_data) * 2 +
sram_len + sizeof(*dump_mem) +
fifo_data_len +
prph_len +
sizeof(*dump_info);
/* Make room for the SMEM, if it exists */
@ -489,17 +502,6 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_info);
}
/* Make room for PRPH registers */
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4;
file_len += sizeof(*dump_data) +
sizeof(struct iwl_fw_error_dump_prph) +
num_bytes_in_chunk;
}
/*
* In 8000 HW family B-step include the ICCM (which resides separately)
*/
@ -625,7 +627,8 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
}
dump_data = iwl_fw_error_next_data(dump_data);
iwl_dump_prph(mvm->trans, &dump_data);
if (prph_len)
iwl_dump_prph(mvm->trans, &dump_data);
dump_trans_data:
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans,

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -27,7 +27,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -855,11 +855,17 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
u32 action)
{
struct iwl_mac_ctx_cmd cmd = {};
u32 tfd_queue_msk = 0;
int ret, i;
WARN_ON(vif->type != NL80211_IFTYPE_MONITOR);
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, NULL, action);
for (i = 0; i < IEEE80211_NUM_ACS; i++)
if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
tfd_queue_msk |= BIT(vif->hw_queue[i]);
cmd.filter_flags = cpu_to_le32(MAC_FILTER_IN_PROMISC |
MAC_FILTER_IN_CONTROL_AND_MGMT |
MAC_FILTER_IN_BEACON |
@ -867,6 +873,12 @@ static int iwl_mvm_mac_ctxt_cmd_listener(struct iwl_mvm *mvm,
MAC_FILTER_IN_CRC32);
ieee80211_hw_set(mvm->hw, RX_INCLUDES_FCS);
/* Allocate sniffer station */
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->snif_sta, tfd_queue_msk,
vif->type);
if (ret)
return ret;
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@ -1289,8 +1301,10 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->uploaded = false;
if (vif->type == NL80211_IFTYPE_MONITOR)
if (vif->type == NL80211_IFTYPE_MONITOR) {
__clear_bit(IEEE80211_HW_RX_INCLUDES_FCS, mvm->hw->flags);
iwl_mvm_dealloc_snif_sta(mvm);
}
return 0;
}

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -439,6 +439,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
if (mvm->trans->max_skb_frags)
hw->netdev_features = NETIF_F_HIGHDMA | NETIF_F_SG;
hw->queues = mvm->first_agg_queue;
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
@ -664,6 +667,10 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (!iwl_mvm_is_csum_supported(mvm))
hw->netdev_features &= ~NETIF_F_RXCSUM;
if (IWL_MVM_SW_TX_CSUM_OFFLOAD)
hw->netdev_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
ret = ieee80211_register_hw(mvm->hw);
if (ret)
iwl_mvm_leds_exit(mvm);
@ -964,6 +971,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->calibrating = false;
/* just in case one was running */
iwl_mvm_cleanup_roc_te(mvm);
ieee80211_remain_on_channel_expired(mvm->hw);
/*
@ -976,6 +984,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->d0i3_ap_sta_id = IWL_MVM_STATION_COUNT;
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained));
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
@ -993,6 +1002,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
mvm->vif_count = 0;
mvm->rx_ba_sessions = 0;
mvm->fw_dbg_conf = FW_DBG_INVALID;
mvm->scan_type = IWL_SCAN_TYPE_NOT_SET;
/* keep statistics ticking */
iwl_mvm_accu_radio_stats(mvm);
@ -1004,10 +1014,18 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
/* Clean up some internal and mac80211 state on restart */
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
/* Clean up some internal and mac80211 state on restart */
iwl_mvm_restart_cleanup(mvm);
} else {
/* Hold the reference to prevent runtime suspend while
* the start procedure runs. It's a bit confusing
* that the UCODE_DOWN reference is taken, but it just
* means "UCODE is not UP yet". ( TODO: rename this
* reference).
*/
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
}
ret = iwl_mvm_up(mvm);
if (ret && test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
@ -1074,15 +1092,13 @@ static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
{
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
if (mvm->trans->d0i3_mode == IWL_D0I3_MODE_ON_SUSPEND)
if (!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ))
WARN_ONCE(1, "D0i3 exit on resume timed out\n");
if (iwl_mvm_is_d0i3_supported(mvm) &&
iwl_mvm_enter_d0i3_on_suspend(mvm))
WARN_ONCE(!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3,
&mvm->status),
HZ),
"D0i3 exit on resume timed out\n");
}
static void
@ -1110,14 +1126,6 @@ void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
*/
memset(&mvm->accu_radio_stats, 0, sizeof(mvm->accu_radio_stats));
/*
* Disallow low power states when the FW is down by taking
* the UCODE_DOWN ref. in case of ongoing hw restart the
* ref is already taken, so don't take it again.
*/
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
/* async_handlers_wk is now blocked */
/*
@ -1729,8 +1737,8 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
return true;
}
static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm)
{
struct iwl_bcast_filter_cmd cmd;
@ -1744,8 +1752,7 @@ static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
sizeof(cmd), &cmd);
}
#else
static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm)
{
return 0;
}
@ -1860,7 +1867,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
}
iwl_mvm_recalc_multicast(mvm);
iwl_mvm_configure_bcast_filter(mvm, vif);
iwl_mvm_configure_bcast_filter(mvm);
/* reset rssi values */
mvmvif->bf_data.ave_beacon_signal = 0;
@ -1868,6 +1875,9 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_TT,
IEEE80211_SMPS_AUTOMATIC);
if (fw_has_capa(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_CAPA_UMAC_SCAN))
iwl_mvm_config_scan(mvm);
} else if (changes & BSS_CHANGED_BEACON_INFO) {
/*
* We received a beacon _after_ association so
@ -1908,7 +1918,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_ARP_FILTER) {
IWL_DEBUG_MAC80211(mvm, "arp filter changed\n");
iwl_mvm_configure_bcast_filter(mvm, vif);
iwl_mvm_configure_bcast_filter(mvm);
}
}
@ -2238,7 +2248,6 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
/*
@ -2254,11 +2263,6 @@ static void iwl_mvm_sta_pre_rcu_remove(struct ieee80211_hw *hw,
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
ERR_PTR(-ENOENT));
if (mvm_sta->vif->type == NL80211_IFTYPE_AP) {
mvmvif->ap_assoc_sta_count--;
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
mutex_unlock(&mvm->mutex);
}
@ -2370,6 +2374,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
ret = 0;
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC) {
if (vif->type == NL80211_IFTYPE_AP) {
mvmvif->ap_assoc_sta_count++;
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
ret = iwl_mvm_update_sta(mvm, vif, sta);
if (ret == 0)
iwl_mvm_rs_rate_init(mvm, sta,
@ -2396,6 +2404,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
ret = 0;
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
if (vif->type == NL80211_IFTYPE_AP) {
mvmvif->ap_assoc_sta_count--;
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
ret = 0;
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_NONE) {
@ -3116,6 +3128,11 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
ret = iwl_mvm_update_quotas(mvm, false, NULL);
if (ret)
goto out_remove_binding;
ret = iwl_mvm_add_snif_sta(mvm, vif);
if (ret)
goto out_remove_binding;
}
/* Handle binding during CSA */
@ -3189,6 +3206,7 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
case NL80211_IFTYPE_MONITOR:
mvmvif->monitor_active = false;
mvmvif->ps_disabled = false;
iwl_mvm_rm_snif_sta(mvm, vif);
break;
case NL80211_IFTYPE_AP:
/* This part is triggered only during CSA */

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@ -294,6 +294,7 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_EXIT_WORK,
IWL_MVM_REF_PROTECT_CSA,
IWL_MVM_REF_FW_DBG_COLLECT,
IWL_MVM_REF_INIT_UCODE,
/* update debugfs.c when changing this */
@ -404,7 +405,7 @@ struct iwl_mvm_vif {
*/
struct iwl_mvm_phy_ctxt *phy_ctxt;
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM
/* WoWLAN GTK rekey data */
struct {
u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
@ -421,6 +422,7 @@ struct iwl_mvm_vif {
#if IS_ENABLED(CONFIG_IPV6)
/* IPv6 addresses for WoWLAN */
struct in6_addr target_ipv6_addrs[IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX];
unsigned long tentative_addrs[BITS_TO_LONGS(IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)];
int num_target_ipv6_addrs;
#endif
@ -475,6 +477,14 @@ enum iwl_scan_status {
IWL_MVM_SCAN_MASK = 0xff,
};
enum iwl_mvm_scan_type {
IWL_SCAN_TYPE_NOT_SET,
IWL_SCAN_TYPE_UNASSOC,
IWL_SCAN_TYPE_WILD,
IWL_SCAN_TYPE_MILD,
IWL_SCAN_TYPE_FRAGMENTED,
};
/**
* struct iwl_nvm_section - describes an NVM section in memory.
*
@ -643,7 +653,7 @@ struct iwl_mvm {
unsigned int scan_status;
void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
bool scan_fragmented;
enum iwl_mvm_scan_type scan_type;
/* max number of simultaneous scans the FW supports */
unsigned int max_scans;
@ -667,6 +677,7 @@ struct iwl_mvm {
/* Internal station */
struct iwl_mvm_int_sta aux_sta;
struct iwl_mvm_int_sta snif_sta;
bool last_ebs_successful;
@ -727,7 +738,7 @@ struct iwl_mvm {
struct ieee80211_vif *p2p_device_vif;
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM
struct wiphy_wowlan_support wowlan;
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
@ -924,6 +935,19 @@ static inline bool iwl_mvm_is_dqa_supported(struct iwl_mvm *mvm)
IWL_UCODE_TLV_CAPA_DQA_SUPPORT);
}
static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm)
{
/* For now we only use this mode to differentiate between
* slave transports, which handle D0i3 entry in suspend by
* themselves in conjunction with runtime PM D0i3. So, this
* function is used to check whether we need to do anything
* when entering suspend or if the transport layer has already
* done it.
*/
return (mvm->trans->system_pm_mode == IWL_PLAT_PM_MODE_D0I3) &&
(mvm->trans->runtime_pm_mode != IWL_PLAT_PM_MODE_D0I3);
}
static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm)
{
bool nvm_lar = mvm->nvm_data->lar_enabled;
@ -1111,6 +1135,11 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
void iwl_mvm_rx_rx_phy_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_rx_mpdu(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_phy_cmd_mq(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_frame_release(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb, int queue);
void iwl_mvm_rx_tx_cmd(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_ba_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb);
void iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
@ -1249,10 +1278,6 @@ static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
/* D3 (WoWLAN, NetDetect) */
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
int iwl_mvm_resume(struct ieee80211_hw *hw);
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool configure_keys,
u32 cmd_flags);
void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled);
void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -1263,10 +1288,31 @@ void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,
void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, int idx);
extern const struct file_operations iwl_dbgfs_d3_test_ops;
#ifdef CONFIG_PM_SLEEP
#ifdef CONFIG_PM
int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool host_awake,
u32 cmd_flags);
void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status);
void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
#else
static inline int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool host_awake,
u32 cmd_flags)
{
return 0;
}
static inline void iwl_mvm_d0i3_update_keys(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct iwl_wowlan_status *status)
{
}
static inline void
iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
@ -1277,6 +1323,7 @@ void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
bool offload_ns,
u32 cmd_flags);
/* D0i3 */

View File

@ -26,7 +26,7 @@
* in the file called COPYING.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE

View File

@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -33,6 +34,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -64,6 +66,7 @@
*****************************************************************************/
#include <net/ipv6.h>
#include <net/addrconf.h>
#include <linux/bitops.h>
#include "mvm.h"
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
@ -86,6 +89,7 @@ void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
bool offload_ns,
u32 cmd_flags)
{
union {
@ -106,6 +110,13 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
#if IS_ENABLED(CONFIG_IPV6)
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int i;
/*
* Skip tentative address when ns offload is enabled to avoid
* violating RFC4862.
* Keep tentative address when ns offload is disabled so the NS packets
* will not be filtered out and will wake up the host.
*/
bool skip_tentative = offload_ns;
if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL ||
capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE) {
@ -113,6 +124,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct iwl_targ_addr *addrs;
int n_nsc, n_addrs;
int c;
int num_skipped = 0;
if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) {
nsc = cmd.v3s.ns_config;
@ -126,9 +138,6 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L;
}
if (mvmvif->num_target_ipv6_addrs)
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
/*
* For each address we have (and that will fit) fill a target
* address struct and combine for NS offload structs with the
@ -140,6 +149,12 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct in6_addr solicited_addr;
int j;
if (skip_tentative &&
test_bit(i, mvmvif->tentative_addrs)) {
num_skipped++;
continue;
}
addrconf_addr_solict_mult(&mvmvif->target_ipv6_addrs[i],
&solicited_addr);
for (j = 0; j < c; j++)
@ -154,41 +169,64 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
memcpy(nsc[j].target_mac_addr, vif->addr, ETH_ALEN);
}
if (mvmvif->num_target_ipv6_addrs - num_skipped)
enabled |= IWL_D3_PROTO_IPV6_VALID;
if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL)
cmd.v3s.num_valid_ipv6_addrs = cpu_to_le32(i);
cmd.v3s.num_valid_ipv6_addrs =
cpu_to_le32(i - num_skipped);
else
cmd.v3l.num_valid_ipv6_addrs = cpu_to_le32(i);
cmd.v3l.num_valid_ipv6_addrs =
cpu_to_le32(i - num_skipped);
} else if (capa_flags & IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS) {
if (mvmvif->num_target_ipv6_addrs) {
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
}
bool found = false;
BUILD_BUG_ON(sizeof(cmd.v2.target_ipv6_addr[0]) !=
sizeof(mvmvif->target_ipv6_addrs[0]));
for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++)
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V2); i++) {
if (skip_tentative &&
test_bit(i, mvmvif->tentative_addrs))
continue;
memcpy(cmd.v2.target_ipv6_addr[i],
&mvmvif->target_ipv6_addrs[i],
sizeof(cmd.v2.target_ipv6_addr[i]));
} else {
if (mvmvif->num_target_ipv6_addrs) {
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
}
found = true;
}
if (found) {
enabled |= IWL_D3_PROTO_IPV6_VALID;
memcpy(cmd.v2.ndp_mac_addr, vif->addr, ETH_ALEN);
}
} else {
bool found = false;
BUILD_BUG_ON(sizeof(cmd.v1.target_ipv6_addr[0]) !=
sizeof(mvmvif->target_ipv6_addrs[0]));
for (i = 0; i < min(mvmvif->num_target_ipv6_addrs,
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++)
IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1); i++) {
if (skip_tentative &&
test_bit(i, mvmvif->tentative_addrs))
continue;
memcpy(cmd.v1.target_ipv6_addr[i],
&mvmvif->target_ipv6_addrs[i],
sizeof(cmd.v1.target_ipv6_addr[i]));
}
#endif
found = true;
}
if (found) {
enabled |= IWL_D3_PROTO_IPV6_VALID;
memcpy(cmd.v1.ndp_mac_addr, vif->addr, ETH_ALEN);
}
}
if (offload_ns && (enabled & IWL_D3_PROTO_IPV6_VALID))
enabled |= IWL_D3_PROTO_OFFLOAD_NS;
#endif
if (capa_flags & IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL) {
common = &cmd.v3s.common;
size = sizeof(cmd.v3s);
@ -204,7 +242,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
}
if (vif->bss_conf.arp_addr_cnt) {
enabled |= IWL_D3_PROTO_OFFLOAD_ARP;
enabled |= IWL_D3_PROTO_OFFLOAD_ARP | IWL_D3_PROTO_IPV4_VALID;
common->host_ipv4_addr = vif->bss_conf.arp_addr_list[0];
memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN);
}

Some files were not shown because too many files have changed in this diff Show More