mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-18 08:56:23 +07:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
commit
74dd1521d0
@ -3,5 +3,5 @@
|
||||
# under Linux.
|
||||
#
|
||||
|
||||
obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
|
||||
obj-y += gpio.o irq.o nvram.o prom.o serial.o setup.o time.o sprom.o
|
||||
obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o
|
||||
|
@ -107,8 +107,7 @@ int nvram_getenv(char *name, char *val, size_t val_len)
|
||||
value = eq + 1;
|
||||
if ((eq - var) == strlen(name) &&
|
||||
strncmp(var, name, (eq - var)) == 0) {
|
||||
snprintf(val, val_len, "%s", value);
|
||||
return 0;
|
||||
return snprintf(val, val_len, "%s", value);
|
||||
}
|
||||
}
|
||||
return NVRAM_ERR_ENVNOTFOUND;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2006 Michael Buesch <m@bues.ch>
|
||||
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
|
||||
* Copyright (C) 2010-2011 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
* Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
@ -85,156 +85,7 @@ static void bcm47xx_machine_halt(void)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCM47XX_SSB
|
||||
#define READ_FROM_NVRAM(_outvar, name, buf) \
|
||||
if (nvram_getprefix(prefix, name, buf, sizeof(buf)) >= 0)\
|
||||
sprom->_outvar = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
#define READ_FROM_NVRAM2(_outvar, name1, name2, buf) \
|
||||
if (nvram_getprefix(prefix, name1, buf, sizeof(buf)) >= 0 || \
|
||||
nvram_getprefix(prefix, name2, buf, sizeof(buf)) >= 0)\
|
||||
sprom->_outvar = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
static inline int nvram_getprefix(const char *prefix, char *name,
|
||||
char *buf, int len)
|
||||
{
|
||||
if (prefix) {
|
||||
char key[100];
|
||||
|
||||
snprintf(key, sizeof(key), "%s%s", prefix, name);
|
||||
return nvram_getenv(key, buf, len);
|
||||
}
|
||||
|
||||
return nvram_getenv(name, buf, len);
|
||||
}
|
||||
|
||||
static u32 nvram_getu32(const char *name, char *buf, int len)
|
||||
{
|
||||
int rv;
|
||||
char key[100];
|
||||
u16 var0, var1;
|
||||
|
||||
snprintf(key, sizeof(key), "%s0", name);
|
||||
rv = nvram_getenv(key, buf, len);
|
||||
/* return 0 here so this looks like unset */
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
var0 = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
snprintf(key, sizeof(key), "%s1", name);
|
||||
rv = nvram_getenv(key, buf, len);
|
||||
if (rv < 0)
|
||||
return 0;
|
||||
var1 = simple_strtoul(buf, NULL, 0);
|
||||
return var1 << 16 | var0;
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
char buf[100];
|
||||
u32 boardflags;
|
||||
|
||||
memset(sprom, 0, sizeof(struct ssb_sprom));
|
||||
|
||||
sprom->revision = 1; /* Fallback: Old hardware does not define this. */
|
||||
READ_FROM_NVRAM(revision, "sromrev", buf);
|
||||
if (nvram_getprefix(prefix, "il0macaddr", buf, sizeof(buf)) >= 0 ||
|
||||
nvram_getprefix(prefix, "macaddr", buf, sizeof(buf)) >= 0)
|
||||
nvram_parse_macaddr(buf, sprom->il0mac);
|
||||
if (nvram_getprefix(prefix, "et0macaddr", buf, sizeof(buf)) >= 0)
|
||||
nvram_parse_macaddr(buf, sprom->et0mac);
|
||||
if (nvram_getprefix(prefix, "et1macaddr", buf, sizeof(buf)) >= 0)
|
||||
nvram_parse_macaddr(buf, sprom->et1mac);
|
||||
READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
|
||||
READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
|
||||
READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
|
||||
READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
|
||||
READ_FROM_NVRAM(board_rev, "boardrev", buf);
|
||||
READ_FROM_NVRAM(country_code, "ccode", buf);
|
||||
READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
|
||||
READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
|
||||
READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
|
||||
READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
|
||||
READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
|
||||
READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
|
||||
READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
|
||||
READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
|
||||
READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
|
||||
READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
|
||||
READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
|
||||
READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
|
||||
READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
|
||||
READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
|
||||
READ_FROM_NVRAM2(gpio0, "ledbh0", "wl0gpio0", buf);
|
||||
READ_FROM_NVRAM2(gpio1, "ledbh1", "wl0gpio1", buf);
|
||||
READ_FROM_NVRAM2(gpio2, "ledbh2", "wl0gpio2", buf);
|
||||
READ_FROM_NVRAM2(gpio3, "ledbh3", "wl0gpio3", buf);
|
||||
READ_FROM_NVRAM2(maxpwr_bg, "maxp2ga0", "pa0maxpwr", buf);
|
||||
READ_FROM_NVRAM2(maxpwr_al, "maxp5gla0", "pa1lomaxpwr", buf);
|
||||
READ_FROM_NVRAM2(maxpwr_a, "maxp5ga0", "pa1maxpwr", buf);
|
||||
READ_FROM_NVRAM2(maxpwr_ah, "maxp5gha0", "pa1himaxpwr", buf);
|
||||
READ_FROM_NVRAM2(itssi_bg, "itt5ga0", "pa0itssit", buf);
|
||||
READ_FROM_NVRAM2(itssi_a, "itt2ga0", "pa1itssit", buf);
|
||||
READ_FROM_NVRAM(tri2g, "tri2g", buf);
|
||||
READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
|
||||
READ_FROM_NVRAM(tri5g, "tri5g", buf);
|
||||
READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
|
||||
READ_FROM_NVRAM(txpid2g[0], "txpid2ga0", buf);
|
||||
READ_FROM_NVRAM(txpid2g[1], "txpid2ga1", buf);
|
||||
READ_FROM_NVRAM(txpid2g[2], "txpid2ga2", buf);
|
||||
READ_FROM_NVRAM(txpid2g[3], "txpid2ga3", buf);
|
||||
READ_FROM_NVRAM(txpid5g[0], "txpid5ga0", buf);
|
||||
READ_FROM_NVRAM(txpid5g[1], "txpid5ga1", buf);
|
||||
READ_FROM_NVRAM(txpid5g[2], "txpid5ga2", buf);
|
||||
READ_FROM_NVRAM(txpid5g[3], "txpid5ga3", buf);
|
||||
READ_FROM_NVRAM(txpid5gl[0], "txpid5gla0", buf);
|
||||
READ_FROM_NVRAM(txpid5gl[1], "txpid5gla1", buf);
|
||||
READ_FROM_NVRAM(txpid5gl[2], "txpid5gla2", buf);
|
||||
READ_FROM_NVRAM(txpid5gl[3], "txpid5gla3", buf);
|
||||
READ_FROM_NVRAM(txpid5gh[0], "txpid5gha0", buf);
|
||||
READ_FROM_NVRAM(txpid5gh[1], "txpid5gha1", buf);
|
||||
READ_FROM_NVRAM(txpid5gh[2], "txpid5gha2", buf);
|
||||
READ_FROM_NVRAM(txpid5gh[3], "txpid5gha3", buf);
|
||||
READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
|
||||
READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
|
||||
READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
|
||||
READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
|
||||
READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
|
||||
READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
|
||||
READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
|
||||
READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
|
||||
READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
|
||||
READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
|
||||
READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
|
||||
|
||||
sprom->ofdm2gpo = nvram_getu32("ofdm2gpo", buf, sizeof(buf));
|
||||
sprom->ofdm5glpo = nvram_getu32("ofdm5glpo", buf, sizeof(buf));
|
||||
sprom->ofdm5gpo = nvram_getu32("ofdm5gpo", buf, sizeof(buf));
|
||||
sprom->ofdm5ghpo = nvram_getu32("ofdm5ghpo", buf, sizeof(buf));
|
||||
|
||||
READ_FROM_NVRAM(antenna_gain.ghz24.a0, "ag0", buf);
|
||||
READ_FROM_NVRAM(antenna_gain.ghz24.a1, "ag1", buf);
|
||||
READ_FROM_NVRAM(antenna_gain.ghz24.a2, "ag2", buf);
|
||||
READ_FROM_NVRAM(antenna_gain.ghz24.a3, "ag3", buf);
|
||||
memcpy(&sprom->antenna_gain.ghz5, &sprom->antenna_gain.ghz24,
|
||||
sizeof(sprom->antenna_gain.ghz5));
|
||||
|
||||
if (nvram_getprefix(prefix, "boardflags", buf, sizeof(buf)) >= 0) {
|
||||
boardflags = simple_strtoul(buf, NULL, 0);
|
||||
if (boardflags) {
|
||||
sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
|
||||
sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
|
||||
}
|
||||
}
|
||||
if (nvram_getprefix(prefix, "boardflags2", buf, sizeof(buf)) >= 0) {
|
||||
boardflags = simple_strtoul(buf, NULL, 0);
|
||||
if (boardflags) {
|
||||
sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
|
||||
sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
{
|
||||
char prefix[10];
|
||||
|
||||
@ -251,7 +102,7 @@ int bcm47xx_get_sprom(struct ssb_bus *bus, struct ssb_sprom *out)
|
||||
}
|
||||
|
||||
static int bcm47xx_get_invariants(struct ssb_bus *bus,
|
||||
struct ssb_init_invariants *iv)
|
||||
struct ssb_init_invariants *iv)
|
||||
{
|
||||
char buf[20];
|
||||
|
||||
@ -281,7 +132,7 @@ static void __init bcm47xx_register_ssb(void)
|
||||
char buf[100];
|
||||
struct ssb_mipscore *mcore;
|
||||
|
||||
err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom);
|
||||
err = ssb_arch_register_fallback_sprom(&bcm47xx_get_sprom_ssb);
|
||||
if (err)
|
||||
printk(KERN_WARNING "bcm47xx: someone else already registered"
|
||||
" a ssb SPROM callback handler (err %d)\n", err);
|
||||
@ -308,10 +159,41 @@ static void __init bcm47xx_register_ssb(void)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BCM47XX_BCMA
|
||||
static int bcm47xx_get_sprom_bcma(struct bcma_bus *bus, struct ssb_sprom *out)
|
||||
{
|
||||
char prefix[10];
|
||||
struct bcma_device *core;
|
||||
|
||||
switch (bus->hosttype) {
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
snprintf(prefix, sizeof(prefix), "pci/%u/%u/",
|
||||
bus->host_pci->bus->number + 1,
|
||||
PCI_SLOT(bus->host_pci->devfn));
|
||||
bcm47xx_fill_sprom(out, prefix);
|
||||
return 0;
|
||||
case BCMA_HOSTTYPE_SOC:
|
||||
bcm47xx_fill_sprom_ethernet(out, NULL);
|
||||
core = bcma_find_core(bus, BCMA_CORE_80211);
|
||||
if (core) {
|
||||
snprintf(prefix, sizeof(prefix), "sb/%u/",
|
||||
core->core_index);
|
||||
bcm47xx_fill_sprom(out, prefix);
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
pr_warn("bcm47xx: unable to fill SPROM for given bustype.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init bcm47xx_register_bcma(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = bcma_arch_register_fallback_sprom(&bcm47xx_get_sprom_bcma);
|
||||
if (err)
|
||||
pr_warn("bcm47xx: someone else already registered a bcma SPROM callback handler (err %d)\n", err);
|
||||
|
||||
err = bcma_host_soc_register(&bcm47xx_bus.bcma);
|
||||
if (err)
|
||||
panic("Failed to initialize BCMA bus (err %d)", err);
|
||||
|
620
arch/mips/bcm47xx/sprom.c
Normal file
620
arch/mips/bcm47xx/sprom.c
Normal file
@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
|
||||
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
||||
* Copyright (C) 2006 Michael Buesch <m@bues.ch>
|
||||
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org>
|
||||
* Copyright (C) 2010-2012 Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <bcm47xx.h>
|
||||
#include <nvram.h>
|
||||
|
||||
static void create_key(const char *prefix, const char *postfix,
|
||||
const char *name, char *buf, int len)
|
||||
{
|
||||
if (prefix && postfix)
|
||||
snprintf(buf, len, "%s%s%s", prefix, name, postfix);
|
||||
else if (prefix)
|
||||
snprintf(buf, len, "%s%s", prefix, name);
|
||||
else if (postfix)
|
||||
snprintf(buf, len, "%s%s", name, postfix);
|
||||
else
|
||||
snprintf(buf, len, "%s", name);
|
||||
}
|
||||
|
||||
#define NVRAM_READ_VAL(type) \
|
||||
static void nvram_read_ ## type (const char *prefix, \
|
||||
const char *postfix, const char *name, \
|
||||
type *val, type allset) \
|
||||
{ \
|
||||
char buf[100]; \
|
||||
char key[40]; \
|
||||
int err; \
|
||||
type var; \
|
||||
\
|
||||
create_key(prefix, postfix, name, key, sizeof(key)); \
|
||||
\
|
||||
err = nvram_getenv(key, buf, sizeof(buf)); \
|
||||
if (err < 0) \
|
||||
return; \
|
||||
err = kstrto ## type (buf, 0, &var); \
|
||||
if (err) { \
|
||||
pr_warn("can not parse nvram name %s with value %s" \
|
||||
" got %i", key, buf, err); \
|
||||
return; \
|
||||
} \
|
||||
if (allset && var == allset) \
|
||||
return; \
|
||||
*val = var; \
|
||||
}
|
||||
|
||||
NVRAM_READ_VAL(u8)
|
||||
NVRAM_READ_VAL(s8)
|
||||
NVRAM_READ_VAL(u16)
|
||||
NVRAM_READ_VAL(u32)
|
||||
|
||||
#undef NVRAM_READ_VAL
|
||||
|
||||
static void nvram_read_u32_2(const char *prefix, const char *name,
|
||||
u16 *val_lo, u16 *val_hi)
|
||||
{
|
||||
char buf[100];
|
||||
char key[40];
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
create_key(prefix, NULL, name, key, sizeof(key));
|
||||
|
||||
err = nvram_getenv(key, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return;
|
||||
err = kstrtou32(buf, 0, &val);
|
||||
if (err) {
|
||||
pr_warn("can not parse nvram name %s with value %s got %i",
|
||||
key, buf, err);
|
||||
return;
|
||||
}
|
||||
*val_lo = (val & 0x0000FFFFU);
|
||||
*val_hi = (val & 0xFFFF0000U) >> 16;
|
||||
}
|
||||
|
||||
static void nvram_read_leddc(const char *prefix, const char *name,
|
||||
u8 *leddc_on_time, u8 *leddc_off_time)
|
||||
{
|
||||
char buf[100];
|
||||
char key[40];
|
||||
int err;
|
||||
u32 val;
|
||||
|
||||
create_key(prefix, NULL, name, key, sizeof(key));
|
||||
|
||||
err = nvram_getenv(key, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return;
|
||||
err = kstrtou32(buf, 0, &val);
|
||||
if (err) {
|
||||
pr_warn("can not parse nvram name %s with value %s got %i",
|
||||
key, buf, err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (val == 0xffff || val == 0xffffffff)
|
||||
return;
|
||||
|
||||
*leddc_on_time = val & 0xff;
|
||||
*leddc_off_time = (val >> 16) & 0xff;
|
||||
}
|
||||
|
||||
static void nvram_read_macaddr(const char *prefix, const char *name,
|
||||
u8 (*val)[6])
|
||||
{
|
||||
char buf[100];
|
||||
char key[40];
|
||||
int err;
|
||||
|
||||
create_key(prefix, NULL, name, key, sizeof(key));
|
||||
|
||||
err = nvram_getenv(key, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return;
|
||||
nvram_parse_macaddr(buf, *val);
|
||||
}
|
||||
|
||||
static void nvram_read_alpha2(const char *prefix, const char *name,
|
||||
char (*val)[2])
|
||||
{
|
||||
char buf[10];
|
||||
char key[40];
|
||||
int err;
|
||||
|
||||
create_key(prefix, NULL, name, key, sizeof(key));
|
||||
|
||||
err = nvram_getenv(key, buf, sizeof(buf));
|
||||
if (err < 0)
|
||||
return;
|
||||
if (buf[0] == '0')
|
||||
return;
|
||||
if (strlen(buf) > 2) {
|
||||
pr_warn("alpha2 is too long %s", buf);
|
||||
return;
|
||||
}
|
||||
memcpy(val, buf, sizeof(val));
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r1234589(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "boardrev", &sprom->board_rev, 0);
|
||||
nvram_read_u16(prefix, NULL, "boardnum", &sprom->board_num, 0);
|
||||
nvram_read_u8(prefix, NULL, "ledbh0", &sprom->gpio0, 0xff);
|
||||
nvram_read_u8(prefix, NULL, "ledbh1", &sprom->gpio1, 0xff);
|
||||
nvram_read_u8(prefix, NULL, "ledbh2", &sprom->gpio2, 0xff);
|
||||
nvram_read_u8(prefix, NULL, "ledbh3", &sprom->gpio3, 0xff);
|
||||
nvram_read_u8(prefix, NULL, "aa2g", &sprom->ant_available_bg, 0);
|
||||
nvram_read_u8(prefix, NULL, "aa5g", &sprom->ant_available_a, 0);
|
||||
nvram_read_s8(prefix, NULL, "ag0", &sprom->antenna_gain.a0, 0);
|
||||
nvram_read_s8(prefix, NULL, "ag1", &sprom->antenna_gain.a1, 0);
|
||||
nvram_read_alpha2(prefix, "ccode", &sprom->alpha2);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r12389(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "pa0b0", &sprom->pa0b0, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa0b1", &sprom->pa0b1, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa0b2", &sprom->pa0b2, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa0itssit", &sprom->itssi_bg, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa0maxpwr", &sprom->maxpwr_bg, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1b0", &sprom->pa1b0, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1b1", &sprom->pa1b1, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1b2", &sprom->pa1b2, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa1itssit", &sprom->itssi_a, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa1maxpwr", &sprom->maxpwr_a, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r1(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "boardflags", &sprom->boardflags_lo, 0);
|
||||
nvram_read_u8(prefix, NULL, "cc", &sprom->country_code, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r2389(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u8(prefix, NULL, "opo", &sprom->opo, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1lob0", &sprom->pa1lob0, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1lob1", &sprom->pa1lob1, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1lob2", &sprom->pa1lob2, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1hib0", &sprom->pa1hib0, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1hib1", &sprom->pa1hib1, 0);
|
||||
nvram_read_u16(prefix, NULL, "pa1hib2", &sprom->pa1hib2, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa1lomaxpwr", &sprom->maxpwr_al, 0);
|
||||
nvram_read_u8(prefix, NULL, "pa1himaxpwr", &sprom->maxpwr_ah, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r2(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
|
||||
&sprom->boardflags_hi);
|
||||
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r389(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u8(prefix, NULL, "bxa2g", &sprom->bxa2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssisav2g", &sprom->rssisav2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssismc2g", &sprom->rssismc2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssismf2g", &sprom->rssismf2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "bxa5g", &sprom->bxa5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssisav5g", &sprom->rssisav5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssismc5g", &sprom->rssismc5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "rssismf5g", &sprom->rssismf5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "tri2g", &sprom->tri2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "tri5g", &sprom->tri5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "tri5gl", &sprom->tri5gl, 0);
|
||||
nvram_read_u8(prefix, NULL, "tri5gh", &sprom->tri5gh, 0);
|
||||
nvram_read_s8(prefix, NULL, "rxpo2g", &sprom->rxpo2g, 0);
|
||||
nvram_read_s8(prefix, NULL, "rxpo5g", &sprom->rxpo5g, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r3(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
|
||||
&sprom->boardflags_hi);
|
||||
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
|
||||
nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
|
||||
nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
|
||||
&sprom->leddc_off_time);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r4589(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
nvram_read_u32_2(prefix, "boardflags", &sprom->boardflags_lo,
|
||||
&sprom->boardflags_hi);
|
||||
nvram_read_u32_2(prefix, "boardflags2", &sprom->boardflags2_lo,
|
||||
&sprom->boardflags2_hi);
|
||||
nvram_read_u16(prefix, NULL, "boardtype", &sprom->board_type, 0);
|
||||
nvram_read_u8(prefix, NULL, "regrev", &sprom->regrev, 0);
|
||||
nvram_read_s8(prefix, NULL, "ag2", &sprom->antenna_gain.a2, 0);
|
||||
nvram_read_s8(prefix, NULL, "ag3", &sprom->antenna_gain.a3, 0);
|
||||
nvram_read_u8(prefix, NULL, "txchain", &sprom->txchain, 0xf);
|
||||
nvram_read_u8(prefix, NULL, "rxchain", &sprom->rxchain, 0xf);
|
||||
nvram_read_u8(prefix, NULL, "antswitch", &sprom->antswitch, 0xff);
|
||||
nvram_read_leddc(prefix, "leddc", &sprom->leddc_on_time,
|
||||
&sprom->leddc_off_time);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r458(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "cck2gpo", &sprom->cck2gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "ofdm2gpo", &sprom->ofdm2gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "ofdm5gpo", &sprom->ofdm5gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "ofdm5glpo", &sprom->ofdm5glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "ofdm5ghpo", &sprom->ofdm5ghpo, 0);
|
||||
nvram_read_u16(prefix, NULL, "cddpo", &sprom->cddpo, 0);
|
||||
nvram_read_u16(prefix, NULL, "stbcpo", &sprom->stbcpo, 0);
|
||||
nvram_read_u16(prefix, NULL, "bw40po", &sprom->bw40po, 0);
|
||||
nvram_read_u16(prefix, NULL, "bwduppo", &sprom->bwduppo, 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo0", &sprom->mcs2gpo[0], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo1", &sprom->mcs2gpo[1], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo2", &sprom->mcs2gpo[2], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo3", &sprom->mcs2gpo[3], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo4", &sprom->mcs2gpo[4], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo5", &sprom->mcs2gpo[5], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo6", &sprom->mcs2gpo[6], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs2gpo7", &sprom->mcs2gpo[7], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo0", &sprom->mcs5gpo[0], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo1", &sprom->mcs5gpo[1], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo2", &sprom->mcs5gpo[2], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo3", &sprom->mcs5gpo[3], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo4", &sprom->mcs5gpo[4], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo5", &sprom->mcs5gpo[5], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo6", &sprom->mcs5gpo[6], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5gpo7", &sprom->mcs5gpo[7], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo0", &sprom->mcs5glpo[0], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo1", &sprom->mcs5glpo[1], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo2", &sprom->mcs5glpo[2], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo3", &sprom->mcs5glpo[3], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo4", &sprom->mcs5glpo[4], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo5", &sprom->mcs5glpo[5], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo6", &sprom->mcs5glpo[6], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5glpo7", &sprom->mcs5glpo[7], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo0", &sprom->mcs5ghpo[0], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo1", &sprom->mcs5ghpo[1], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo2", &sprom->mcs5ghpo[2], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo3", &sprom->mcs5ghpo[3], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo4", &sprom->mcs5ghpo[4], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo5", &sprom->mcs5ghpo[5], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo6", &sprom->mcs5ghpo[6], 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs5ghpo7", &sprom->mcs5ghpo[7], 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r45(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u8(prefix, NULL, "txpid2ga0", &sprom->txpid2g[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid2ga1", &sprom->txpid2g[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid2ga2", &sprom->txpid2g[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid2ga3", &sprom->txpid2g[3], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5ga0", &sprom->txpid5g[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5ga1", &sprom->txpid5g[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5ga2", &sprom->txpid5g[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5ga3", &sprom->txpid5g[3], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gla0", &sprom->txpid5gl[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gla1", &sprom->txpid5gl[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gla2", &sprom->txpid5gl[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gla3", &sprom->txpid5gl[3], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gha0", &sprom->txpid5gh[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gha1", &sprom->txpid5gh[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gha2", &sprom->txpid5gh[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "txpid5gha3", &sprom->txpid5gh[3], 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r89(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u8(prefix, NULL, "tssipos2g", &sprom->fem.ghz2.tssipos, 0);
|
||||
nvram_read_u8(prefix, NULL, "extpagain2g",
|
||||
&sprom->fem.ghz2.extpa_gain, 0);
|
||||
nvram_read_u8(prefix, NULL, "pdetrange2g",
|
||||
&sprom->fem.ghz2.pdet_range, 0);
|
||||
nvram_read_u8(prefix, NULL, "triso2g", &sprom->fem.ghz2.tr_iso, 0);
|
||||
nvram_read_u8(prefix, NULL, "antswctl2g", &sprom->fem.ghz2.antswlut, 0);
|
||||
nvram_read_u8(prefix, NULL, "tssipos5g", &sprom->fem.ghz5.tssipos, 0);
|
||||
nvram_read_u8(prefix, NULL, "extpagain5g",
|
||||
&sprom->fem.ghz5.extpa_gain, 0);
|
||||
nvram_read_u8(prefix, NULL, "pdetrange5g",
|
||||
&sprom->fem.ghz5.pdet_range, 0);
|
||||
nvram_read_u8(prefix, NULL, "triso5g", &sprom->fem.ghz5.tr_iso, 0);
|
||||
nvram_read_u8(prefix, NULL, "antswctl5g", &sprom->fem.ghz5.antswlut, 0);
|
||||
nvram_read_u8(prefix, NULL, "tempthresh", &sprom->tempthresh, 0);
|
||||
nvram_read_u8(prefix, NULL, "tempoffset", &sprom->tempoffset, 0);
|
||||
nvram_read_u16(prefix, NULL, "rawtempsense", &sprom->rawtempsense, 0);
|
||||
nvram_read_u8(prefix, NULL, "measpower", &sprom->measpower, 0);
|
||||
nvram_read_u8(prefix, NULL, "tempsense_slope",
|
||||
&sprom->tempsense_slope, 0);
|
||||
nvram_read_u8(prefix, NULL, "tempcorrx", &sprom->tempcorrx, 0);
|
||||
nvram_read_u8(prefix, NULL, "tempsense_option",
|
||||
&sprom->tempsense_option, 0);
|
||||
nvram_read_u8(prefix, NULL, "freqoffset_corr",
|
||||
&sprom->freqoffset_corr, 0);
|
||||
nvram_read_u8(prefix, NULL, "iqcal_swp_dis", &sprom->iqcal_swp_dis, 0);
|
||||
nvram_read_u8(prefix, NULL, "hw_iqcal_en", &sprom->hw_iqcal_en, 0);
|
||||
nvram_read_u8(prefix, NULL, "elna2g", &sprom->elna2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "elna5g", &sprom->elna5g, 0);
|
||||
nvram_read_u8(prefix, NULL, "phycal_tempdelta",
|
||||
&sprom->phycal_tempdelta, 0);
|
||||
nvram_read_u8(prefix, NULL, "temps_period", &sprom->temps_period, 0);
|
||||
nvram_read_u8(prefix, NULL, "temps_hysteresis",
|
||||
&sprom->temps_hysteresis, 0);
|
||||
nvram_read_u8(prefix, NULL, "measpower1", &sprom->measpower1, 0);
|
||||
nvram_read_u8(prefix, NULL, "measpower2", &sprom->measpower2, 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr2ga0",
|
||||
&sprom->rxgainerr2ga[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr2ga1",
|
||||
&sprom->rxgainerr2ga[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr2ga2",
|
||||
&sprom->rxgainerr2ga[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gla0",
|
||||
&sprom->rxgainerr5gla[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gla1",
|
||||
&sprom->rxgainerr5gla[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gla2",
|
||||
&sprom->rxgainerr5gla[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gma0",
|
||||
&sprom->rxgainerr5gma[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gma1",
|
||||
&sprom->rxgainerr5gma[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gma2",
|
||||
&sprom->rxgainerr5gma[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gha0",
|
||||
&sprom->rxgainerr5gha[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gha1",
|
||||
&sprom->rxgainerr5gha[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gha2",
|
||||
&sprom->rxgainerr5gha[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gua0",
|
||||
&sprom->rxgainerr5gua[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gua1",
|
||||
&sprom->rxgainerr5gua[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "rxgainerr5gua2",
|
||||
&sprom->rxgainerr5gua[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl2ga0", &sprom->noiselvl2ga[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl2ga1", &sprom->noiselvl2ga[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl2ga2", &sprom->noiselvl2ga[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gla0",
|
||||
&sprom->noiselvl5gla[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gla1",
|
||||
&sprom->noiselvl5gla[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gla2",
|
||||
&sprom->noiselvl5gla[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gma0",
|
||||
&sprom->noiselvl5gma[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gma1",
|
||||
&sprom->noiselvl5gma[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gma2",
|
||||
&sprom->noiselvl5gma[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gha0",
|
||||
&sprom->noiselvl5gha[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gha1",
|
||||
&sprom->noiselvl5gha[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gha2",
|
||||
&sprom->noiselvl5gha[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gua0",
|
||||
&sprom->noiselvl5gua[0], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gua1",
|
||||
&sprom->noiselvl5gua[1], 0);
|
||||
nvram_read_u8(prefix, NULL, "noiselvl5gua2",
|
||||
&sprom->noiselvl5gua[2], 0);
|
||||
nvram_read_u8(prefix, NULL, "pcieingress_war",
|
||||
&sprom->pcieingress_war, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_r9(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_u16(prefix, NULL, "cckbw202gpo", &sprom->cckbw202gpo, 0);
|
||||
nvram_read_u16(prefix, NULL, "cckbw20ul2gpo", &sprom->cckbw20ul2gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw202gpo",
|
||||
&sprom->legofdmbw202gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw20ul2gpo",
|
||||
&sprom->legofdmbw20ul2gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw205glpo",
|
||||
&sprom->legofdmbw205glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw20ul5glpo",
|
||||
&sprom->legofdmbw20ul5glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw205gmpo",
|
||||
&sprom->legofdmbw205gmpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw20ul5gmpo",
|
||||
&sprom->legofdmbw20ul5gmpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw205ghpo",
|
||||
&sprom->legofdmbw205ghpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "legofdmbw20ul5ghpo",
|
||||
&sprom->legofdmbw20ul5ghpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw202gpo", &sprom->mcsbw202gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw20ul2gpo", &sprom->mcsbw20ul2gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw402gpo", &sprom->mcsbw402gpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw205glpo", &sprom->mcsbw205glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw20ul5glpo",
|
||||
&sprom->mcsbw20ul5glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw405glpo", &sprom->mcsbw405glpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw205gmpo", &sprom->mcsbw205gmpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw20ul5gmpo",
|
||||
&sprom->mcsbw20ul5gmpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw405gmpo", &sprom->mcsbw405gmpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw205ghpo", &sprom->mcsbw205ghpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw20ul5ghpo",
|
||||
&sprom->mcsbw20ul5ghpo, 0);
|
||||
nvram_read_u32(prefix, NULL, "mcsbw405ghpo", &sprom->mcsbw405ghpo, 0);
|
||||
nvram_read_u16(prefix, NULL, "mcs32po", &sprom->mcs32po, 0);
|
||||
nvram_read_u16(prefix, NULL, "legofdm40duppo",
|
||||
&sprom->legofdm40duppo, 0);
|
||||
nvram_read_u8(prefix, NULL, "sar2g", &sprom->sar2g, 0);
|
||||
nvram_read_u8(prefix, NULL, "sar5g", &sprom->sar5g, 0);
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_path_r4589(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
char postfix[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
|
||||
struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
|
||||
snprintf(postfix, sizeof(postfix), "%i", i);
|
||||
nvram_read_u8(prefix, postfix, "maxp2ga",
|
||||
&pwr_info->maxpwr_2g, 0);
|
||||
nvram_read_u8(prefix, postfix, "itt2ga",
|
||||
&pwr_info->itssi_2g, 0);
|
||||
nvram_read_u8(prefix, postfix, "itt5ga",
|
||||
&pwr_info->itssi_5g, 0);
|
||||
nvram_read_u16(prefix, postfix, "pa2gw0a",
|
||||
&pwr_info->pa_2g[0], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa2gw1a",
|
||||
&pwr_info->pa_2g[1], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa2gw2a",
|
||||
&pwr_info->pa_2g[2], 0);
|
||||
nvram_read_u8(prefix, postfix, "maxp5ga",
|
||||
&pwr_info->maxpwr_5g, 0);
|
||||
nvram_read_u8(prefix, postfix, "maxp5gha",
|
||||
&pwr_info->maxpwr_5gh, 0);
|
||||
nvram_read_u8(prefix, postfix, "maxp5gla",
|
||||
&pwr_info->maxpwr_5gl, 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5gw0a",
|
||||
&pwr_info->pa_5g[0], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5gw1a",
|
||||
&pwr_info->pa_5g[1], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5gw2a",
|
||||
&pwr_info->pa_5g[2], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5glw0a",
|
||||
&pwr_info->pa_5gl[0], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5glw1a",
|
||||
&pwr_info->pa_5gl[1], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5glw2a",
|
||||
&pwr_info->pa_5gl[2], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5ghw0a",
|
||||
&pwr_info->pa_5gh[0], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5ghw1a",
|
||||
&pwr_info->pa_5gh[1], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5ghw2a",
|
||||
&pwr_info->pa_5gh[2], 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void bcm47xx_fill_sprom_path_r45(struct ssb_sprom *sprom,
|
||||
const char *prefix)
|
||||
{
|
||||
char postfix[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sprom->core_pwr_info); i++) {
|
||||
struct ssb_sprom_core_pwr_info *pwr_info = &sprom->core_pwr_info[i];
|
||||
snprintf(postfix, sizeof(postfix), "%i", i);
|
||||
nvram_read_u16(prefix, postfix, "pa2gw3a",
|
||||
&pwr_info->pa_2g[3], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5gw3a",
|
||||
&pwr_info->pa_5g[3], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5glw3a",
|
||||
&pwr_info->pa_5gl[3], 0);
|
||||
nvram_read_u16(prefix, postfix, "pa5ghw3a",
|
||||
&pwr_info->pa_5gh[3], 0);
|
||||
}
|
||||
}
|
||||
|
||||
void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
nvram_read_macaddr(prefix, "et0macaddr", &sprom->et0mac);
|
||||
nvram_read_u8(prefix, NULL, "et0mdcport", &sprom->et0mdcport, 0);
|
||||
nvram_read_u8(prefix, NULL, "et0phyaddr", &sprom->et0phyaddr, 0);
|
||||
|
||||
nvram_read_macaddr(prefix, "et1macaddr", &sprom->et1mac);
|
||||
nvram_read_u8(prefix, NULL, "et1mdcport", &sprom->et1mdcport, 0);
|
||||
nvram_read_u8(prefix, NULL, "et1phyaddr", &sprom->et1phyaddr, 0);
|
||||
|
||||
nvram_read_macaddr(prefix, "macaddr", &sprom->il0mac);
|
||||
nvram_read_macaddr(prefix, "il0macaddr", &sprom->il0mac);
|
||||
}
|
||||
|
||||
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix)
|
||||
{
|
||||
memset(sprom, 0, sizeof(struct ssb_sprom));
|
||||
|
||||
bcm47xx_fill_sprom_ethernet(sprom, prefix);
|
||||
|
||||
nvram_read_u8(prefix, NULL, "sromrev", &sprom->revision, 0);
|
||||
|
||||
switch (sprom->revision) {
|
||||
case 1:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r1(sprom, prefix);
|
||||
break;
|
||||
case 2:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r2389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r2(sprom, prefix);
|
||||
break;
|
||||
case 3:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r2389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r3(sprom, prefix);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r4589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r458(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r45(sprom, prefix);
|
||||
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_path_r45(sprom, prefix);
|
||||
break;
|
||||
case 8:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r2389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r4589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r458(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r89(sprom, prefix);
|
||||
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
|
||||
break;
|
||||
case 9:
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r2389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r4589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r89(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r9(sprom, prefix);
|
||||
bcm47xx_fill_sprom_path_r4589(sprom, prefix);
|
||||
break;
|
||||
default:
|
||||
pr_warn("Unsupported SPROM revision %d detected. Will extract"
|
||||
" v1\n", sprom->revision);
|
||||
sprom->revision = 1;
|
||||
bcm47xx_fill_sprom_r1234589(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r12389(sprom, prefix);
|
||||
bcm47xx_fill_sprom_r1(sprom, prefix);
|
||||
}
|
||||
}
|
@ -44,4 +44,7 @@ union bcm47xx_bus {
|
||||
extern union bcm47xx_bus bcm47xx_bus;
|
||||
extern enum bcm47xx_bus_type bcm47xx_bus_type;
|
||||
|
||||
void bcm47xx_fill_sprom(struct ssb_sprom *sprom, const char *prefix);
|
||||
void bcm47xx_fill_sprom_ethernet(struct ssb_sprom *sprom, const char *prefix);
|
||||
|
||||
#endif /* __ASM_BCM47XX_H */
|
||||
|
@ -37,7 +37,7 @@ struct nvram_header {
|
||||
|
||||
extern int nvram_getenv(char *name, char *val, size_t val_len);
|
||||
|
||||
static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
|
||||
static inline void nvram_parse_macaddr(char *buf, u8 macaddr[6])
|
||||
{
|
||||
if (strchr(buf, ':'))
|
||||
sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],
|
||||
|
@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
|
||||
min_msk = 0x200D;
|
||||
max_msk = 0xFFFF;
|
||||
break;
|
||||
case 0x4331:
|
||||
case 43224:
|
||||
case 43225:
|
||||
break;
|
||||
|
@ -61,7 +61,7 @@ static struct bus_type bcma_bus_type = {
|
||||
.dev_attrs = bcma_device_attrs,
|
||||
};
|
||||
|
||||
static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||
struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
@ -71,6 +71,7 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_find_core);
|
||||
|
||||
static void bcma_release_core_dev(struct device *dev)
|
||||
{
|
||||
|
@ -2,6 +2,8 @@
|
||||
* Broadcom specific AMBA
|
||||
* SPROM reading
|
||||
*
|
||||
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
@ -14,6 +16,58 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static int(*get_fallback_sprom)(struct bcma_bus *dev, struct ssb_sprom *out);
|
||||
|
||||
/**
|
||||
* bcma_arch_register_fallback_sprom - Registers a method providing a
|
||||
* fallback SPROM if no SPROM is found.
|
||||
*
|
||||
* @sprom_callback: The callback function.
|
||||
*
|
||||
* With this function the architecture implementation may register a
|
||||
* callback handler which fills the SPROM data structure. The fallback is
|
||||
* used for PCI based BCMA devices, where no valid SPROM can be found
|
||||
* in the shadow registers and to provide the SPROM for SoCs where BCMA is
|
||||
* to controll the system bus.
|
||||
*
|
||||
* This function is useful for weird architectures that have a half-assed
|
||||
* BCMA device hardwired to their PCI bus.
|
||||
*
|
||||
* This function is available for architecture code, only. So it is not
|
||||
* exported.
|
||||
*/
|
||||
int bcma_arch_register_fallback_sprom(int (*sprom_callback)(struct bcma_bus *bus,
|
||||
struct ssb_sprom *out))
|
||||
{
|
||||
if (get_fallback_sprom)
|
||||
return -EEXIST;
|
||||
get_fallback_sprom = sprom_callback;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcma_fill_sprom_with_fallback(struct bcma_bus *bus,
|
||||
struct ssb_sprom *out)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!get_fallback_sprom) {
|
||||
err = -ENOENT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = get_fallback_sprom(bus, out);
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
pr_debug("Using SPROM revision %d provided by"
|
||||
" platform.\n", bus->sprom.revision);
|
||||
return 0;
|
||||
fail:
|
||||
pr_warn("Using fallback SPROM failed (err %d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* R/W ops.
|
||||
**************************************************/
|
||||
@ -246,23 +300,128 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
|
||||
SSB_SROM8_FEM_ANTSWLUT_SHIFT);
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicates the presence of external SPROM.
|
||||
*/
|
||||
static bool bcma_sprom_ext_available(struct bcma_bus *bus)
|
||||
{
|
||||
u32 chip_status;
|
||||
u32 srom_control;
|
||||
u32 present_mask;
|
||||
|
||||
if (bus->drv_cc.core->id.rev >= 31) {
|
||||
if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
return false;
|
||||
|
||||
srom_control = bcma_read32(bus->drv_cc.core,
|
||||
BCMA_CC_SROM_CONTROL);
|
||||
return srom_control & BCMA_CC_SROM_CONTROL_PRESENT;
|
||||
}
|
||||
|
||||
/* older chipcommon revisions use chip status register */
|
||||
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
present_mask = BCMA_CC_CHIPST_4313_SPROM_PRESENT;
|
||||
break;
|
||||
|
||||
case 0x4331:
|
||||
present_mask = BCMA_CC_CHIPST_4331_SPROM_PRESENT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return chip_status & present_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicates that on-chip OTP memory is present and enabled.
|
||||
*/
|
||||
static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
|
||||
{
|
||||
u32 chip_status;
|
||||
u32 otpsize = 0;
|
||||
bool present;
|
||||
|
||||
chip_status = bcma_read32(bus->drv_cc.core, BCMA_CC_CHIPSTAT);
|
||||
switch (bus->chipinfo.id) {
|
||||
case 0x4313:
|
||||
present = chip_status & BCMA_CC_CHIPST_4313_OTP_PRESENT;
|
||||
break;
|
||||
|
||||
case 0x4331:
|
||||
present = chip_status & BCMA_CC_CHIPST_4331_OTP_PRESENT;
|
||||
break;
|
||||
|
||||
case 43224:
|
||||
case 43225:
|
||||
/* for these chips OTP is always available */
|
||||
present = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
present = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (present) {
|
||||
otpsize = bus->drv_cc.capabilities & BCMA_CC_CAP_OTPS;
|
||||
otpsize >>= BCMA_CC_CAP_OTPS_SHIFT;
|
||||
}
|
||||
|
||||
return otpsize != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify OTP is filled and determine the byte
|
||||
* offset where SPROM data is located.
|
||||
*
|
||||
* On error, returns 0; byte offset otherwise.
|
||||
*/
|
||||
static int bcma_sprom_onchip_offset(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *cc = bus->drv_cc.core;
|
||||
u32 offset;
|
||||
|
||||
/* verify OTP status */
|
||||
if ((bcma_read32(cc, BCMA_CC_OTPS) & BCMA_CC_OTPS_GU_PROG_HW) == 0)
|
||||
return 0;
|
||||
|
||||
/* obtain bit offset from otplayout register */
|
||||
offset = (bcma_read32(cc, BCMA_CC_OTPL) & BCMA_CC_OTPL_GURGN_OFFSET);
|
||||
return BCMA_CC_SPROM + (offset >> 3);
|
||||
}
|
||||
|
||||
int bcma_sprom_get(struct bcma_bus *bus)
|
||||
{
|
||||
u16 offset;
|
||||
u16 offset = BCMA_CC_SPROM;
|
||||
u16 *sprom;
|
||||
u32 sromctrl;
|
||||
int err = 0;
|
||||
|
||||
if (!bus->drv_cc.core)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM))
|
||||
return -ENOENT;
|
||||
|
||||
if (bus->drv_cc.core->id.rev >= 32) {
|
||||
sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL);
|
||||
if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT))
|
||||
return -ENOENT;
|
||||
if (!bcma_sprom_ext_available(bus)) {
|
||||
/*
|
||||
* External SPROM takes precedence so check
|
||||
* on-chip OTP only when no external SPROM
|
||||
* is present.
|
||||
*/
|
||||
if (bcma_sprom_onchip_available(bus)) {
|
||||
/* determine offset */
|
||||
offset = bcma_sprom_onchip_offset(bus);
|
||||
}
|
||||
if (!offset) {
|
||||
/*
|
||||
* Maybe there is no SPROM on the device?
|
||||
* Now we ask the arch code if there is some sprom
|
||||
* available for this device in some other storage.
|
||||
*/
|
||||
err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
sprom = kcalloc(SSB_SPROMSIZE_WORDS_R4, sizeof(u16),
|
||||
@ -273,11 +432,6 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||
if (bus->chipinfo.id == 0x4331)
|
||||
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
|
||||
|
||||
/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
|
||||
* According to brcm80211 this applies to cards with PCIe rev >= 6
|
||||
* TODO: understand this condition and use it */
|
||||
offset = (bus->chipinfo.id == 0x4331) ? BCMA_CC_SPROM :
|
||||
BCMA_CC_SPROM_PCIE6;
|
||||
pr_debug("SPROM offset 0x%x\n", offset);
|
||||
bcma_sprom_read(bus, offset, sprom);
|
||||
|
||||
|
@ -1869,7 +1869,7 @@ static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
|
||||
|
||||
static void try_auto_wep(struct airo_info *ai)
|
||||
{
|
||||
if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) {
|
||||
if (auto_wep && !test_bit(FLAG_RADIO_DOWN, &ai->flags)) {
|
||||
ai->expires = RUN_AT(3*HZ);
|
||||
wake_up_interruptible(&ai->thr_wait);
|
||||
}
|
||||
|
@ -1320,6 +1320,7 @@ struct ath5k_hw {
|
||||
struct ieee80211_vif *bslot[ATH_BCBUF];
|
||||
u16 num_ap_vifs;
|
||||
u16 num_adhoc_vifs;
|
||||
u16 num_mesh_vifs;
|
||||
unsigned int bhalq, /* SW q for outgoing beacons */
|
||||
bmisscount, /* missed beacon transmits */
|
||||
bintval, /* beacon interval in TU */
|
||||
|
@ -1867,7 +1867,8 @@ ath5k_beacon_send(struct ath5k_hw *ah)
|
||||
ah->bmisscount = 0;
|
||||
}
|
||||
|
||||
if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) ||
|
||||
if ((ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs +
|
||||
ah->num_mesh_vifs > 1) ||
|
||||
ah->opmode == NL80211_IFTYPE_MESH_POINT) {
|
||||
u64 tsf = ath5k_hw_get_tsf64(ah);
|
||||
u32 tsftu = TSF_TO_TU(tsf);
|
||||
@ -1952,7 +1953,8 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
|
||||
u64 hw_tsf;
|
||||
|
||||
intval = ah->bintval & AR5K_BEACON_PERIOD;
|
||||
if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs > 1) {
|
||||
if (ah->opmode == NL80211_IFTYPE_AP && ah->num_ap_vifs
|
||||
+ ah->num_mesh_vifs > 1) {
|
||||
intval /= ATH_BCBUF; /* staggered multi-bss beacons */
|
||||
if (intval < 15)
|
||||
ATH5K_WARN(ah, "intval %u is too low, min 15\n",
|
||||
@ -2330,15 +2332,6 @@ ath5k_calibrate_work(struct work_struct *work)
|
||||
"got new rfgain, resetting\n");
|
||||
ieee80211_queue_work(ah->hw, &ah->reset_work);
|
||||
}
|
||||
|
||||
/* TODO: On full calibration we should stop TX here,
|
||||
* so that it doesn't interfere (mostly due to gain_f
|
||||
* calibration that messes with tx packets -see phy.c).
|
||||
*
|
||||
* NOTE: Stopping the queues from above is not enough
|
||||
* to stop TX but saves us from disconecting (at least
|
||||
* we don't lose packets). */
|
||||
ieee80211_stop_queues(ah->hw);
|
||||
} else
|
||||
ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT;
|
||||
|
||||
@ -2353,10 +2346,9 @@ ath5k_calibrate_work(struct work_struct *work)
|
||||
ah->curchan->center_freq));
|
||||
|
||||
/* Clear calibration flags */
|
||||
if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
|
||||
ieee80211_wake_queues(ah->hw);
|
||||
if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL)
|
||||
ah->ah_cal_mask &= ~AR5K_CALIBRATION_FULL;
|
||||
} else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
|
||||
else if (ah->ah_cal_mask & AR5K_CALIBRATION_SHORT)
|
||||
ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT;
|
||||
}
|
||||
|
||||
|
@ -134,6 +134,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
ah->num_ap_vifs++;
|
||||
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
|
||||
ah->num_adhoc_vifs++;
|
||||
else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
|
||||
ah->num_mesh_vifs++;
|
||||
}
|
||||
|
||||
/* Any MAC address is fine, all others are included through the
|
||||
@ -175,6 +177,8 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
|
||||
ah->num_ap_vifs--;
|
||||
else if (avf->opmode == NL80211_IFTYPE_ADHOC)
|
||||
ah->num_adhoc_vifs--;
|
||||
else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
|
||||
ah->num_mesh_vifs--;
|
||||
|
||||
ath5k_update_bssid_mask_and_opmode(ah, NULL);
|
||||
mutex_unlock(&ah->lock);
|
||||
|
@ -1871,31 +1871,15 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* On full calibration do an AGC calibration and
|
||||
* request a PAPD probe for gainf calibration if
|
||||
* needed */
|
||||
if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) {
|
||||
/* On full calibration request a PAPD probe for
|
||||
* gainf calibration if needed */
|
||||
if ((ah->ah_cal_mask & AR5K_CALIBRATION_FULL) &&
|
||||
(ah->ah_radio == AR5K_RF5111 ||
|
||||
ah->ah_radio == AR5K_RF5112) &&
|
||||
channel->hw_value != AR5K_MODE_11B)
|
||||
ath5k_hw_request_rfgain_probe(ah);
|
||||
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL);
|
||||
|
||||
ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF,
|
||||
0, false);
|
||||
if (ret) {
|
||||
ATH5K_ERR(ah,
|
||||
"gain calibration timeout (%uMHz)\n",
|
||||
channel->center_freq);
|
||||
}
|
||||
|
||||
if ((ah->ah_radio == AR5K_RF5111 ||
|
||||
ah->ah_radio == AR5K_RF5112)
|
||||
&& (channel->hw_value != AR5K_MODE_11B))
|
||||
ath5k_hw_request_rfgain_probe(ah);
|
||||
}
|
||||
|
||||
/* Update noise floor
|
||||
* XXX: Only do this after AGC calibration */
|
||||
/* Update noise floor */
|
||||
if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF))
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
|
||||
|
@ -556,7 +556,8 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
|
||||
dlen, freq, vif->probe_req_report);
|
||||
|
||||
if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
|
||||
cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
|
||||
cfg80211_rx_mgmt(vif->ndev, freq, 0,
|
||||
ev->data, dlen, GFP_ATOMIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -595,7 +596,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
|
||||
return -EINVAL;
|
||||
}
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
|
||||
cfg80211_rx_mgmt(vif->ndev, freq, ev->data, dlen, GFP_ATOMIC);
|
||||
cfg80211_rx_mgmt(vif->ndev, freq, 0,
|
||||
ev->data, dlen, GFP_ATOMIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -81,6 +81,14 @@ config ATH9K_DFS_CERTIFIED
|
||||
developed. At this point enabling this option won't do anything
|
||||
except increase code size.
|
||||
|
||||
config ATH9K_MAC_DEBUG
|
||||
bool "Atheros MAC statistics"
|
||||
depends on ATH9K_DEBUGFS
|
||||
default y
|
||||
---help---
|
||||
This option enables collection of statistics for Rx/Tx status
|
||||
data and some other MAC related statistics
|
||||
|
||||
config ATH9K_RATE_CONTROL
|
||||
bool "Atheros ath9k rate control"
|
||||
depends on ATH9K
|
||||
|
@ -326,7 +326,6 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
struct ar9003_txc *txc = (struct ar9003_txc *) ds;
|
||||
struct ar9003_txs *ads;
|
||||
u32 status;
|
||||
|
||||
@ -336,11 +335,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
if ((status & AR_TxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
|
||||
if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
|
||||
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
|
||||
else
|
||||
return -ENOENT;
|
||||
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
|
||||
|
||||
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
|
||||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
|
||||
@ -354,6 +349,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
ts->ts_seqnum = MS(status, AR_SeqNum);
|
||||
ts->tid = MS(status, AR_TxTid);
|
||||
|
||||
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
|
||||
ts->desc_id = MS(ads->status1, AR_TxDescId);
|
||||
ts->ts_tstamp = ads->status4;
|
||||
ts->ts_status = 0;
|
||||
@ -440,20 +436,14 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
|
||||
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
|
||||
unsigned int phyerr;
|
||||
|
||||
/* TODO: byte swap on big endian for ar9300_10 */
|
||||
if ((rxsp->status11 & AR_RxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
if (!rxs) {
|
||||
if ((rxsp->status11 & AR_RxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
|
||||
return -EINVAL;
|
||||
|
||||
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
|
||||
return -EINVAL;
|
||||
|
||||
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
rxs->rs_status = 0;
|
||||
rxs->rs_flags = 0;
|
||||
|
@ -299,7 +299,6 @@ struct ath_tx {
|
||||
|
||||
struct ath_rx_edma {
|
||||
struct sk_buff_head rx_fifo;
|
||||
struct sk_buff_head rx_buffers;
|
||||
u32 rx_fifo_hwsize;
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
|
||||
info.txpower = MAX_RATE_POWER;
|
||||
info.keyix = ATH9K_TXKEYIX_INVALID;
|
||||
info.keytype = ATH9K_KEY_TYPE_CLEAR;
|
||||
info.flags = ATH9K_TXDESC_NOACK;
|
||||
info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_INTREQ;
|
||||
|
||||
info.buf_addr[0] = bf->bf_buf_addr;
|
||||
info.buf_len[0] = roundup(skb->len, 4);
|
||||
@ -355,7 +355,6 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf = NULL;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ath_tx_status ts;
|
||||
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
|
||||
int slot;
|
||||
u32 bfaddr, bc = 0;
|
||||
@ -462,11 +461,6 @@ void ath_beacon_tasklet(unsigned long data)
|
||||
ath9k_hw_txstart(ah, sc->beacon.beaconq);
|
||||
|
||||
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
|
||||
if (edma) {
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
ath9k_hw_txprocdesc(ah, bf->bf_desc, (void *)&ts);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -818,6 +818,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
|
||||
TX_STAT_INC(qnum, delim_underrun);
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spin_lock(&sc->debug.samp_lock);
|
||||
TX_SAMP_DBG(jiffies) = jiffies;
|
||||
TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0;
|
||||
@ -844,6 +845,7 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
|
||||
sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
|
||||
spin_unlock(&sc->debug.samp_lock);
|
||||
#endif
|
||||
|
||||
#undef TX_SAMP_DBG
|
||||
}
|
||||
@ -941,27 +943,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||
PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
|
||||
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
|
||||
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-CTL0",
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl0);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-CTL1",
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl1);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-CTL2",
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl2);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-EXT0",
|
||||
sc->debug.stats.rxstats.rs_rssi_ext0);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-EXT1",
|
||||
sc->debug.stats.rxstats.rs_rssi_ext1);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "RSSI-EXT2",
|
||||
sc->debug.stats.rxstats.rs_rssi_ext2);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10d\n", "Rx Antenna",
|
||||
sc->debug.stats.rxstats.rs_antenna);
|
||||
len += snprintf(buf + len, size - len,
|
||||
"%22s : %10u\n", "RX-Pkts-All",
|
||||
sc->debug.stats.rxstats.rx_pkts_all);
|
||||
@ -1009,16 +990,7 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
|
||||
RX_PHY_ERR_INC(rs->rs_phyerr);
|
||||
}
|
||||
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0;
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl1 = rs->rs_rssi_ctl1;
|
||||
sc->debug.stats.rxstats.rs_rssi_ctl2 = rs->rs_rssi_ctl2;
|
||||
|
||||
sc->debug.stats.rxstats.rs_rssi_ext0 = rs->rs_rssi_ext0;
|
||||
sc->debug.stats.rxstats.rs_rssi_ext1 = rs->rs_rssi_ext1;
|
||||
sc->debug.stats.rxstats.rs_rssi_ext2 = rs->rs_rssi_ext2;
|
||||
|
||||
sc->debug.stats.rxstats.rs_antenna = rs->rs_antenna;
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spin_lock(&sc->debug.samp_lock);
|
||||
RX_SAMP_DBG(jiffies) = jiffies;
|
||||
RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0;
|
||||
@ -1035,6 +1007,8 @@ void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
|
||||
sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
|
||||
spin_unlock(&sc->debug.samp_lock);
|
||||
|
||||
#endif
|
||||
|
||||
#undef RX_STAT_INC
|
||||
#undef RX_PHY_ERR_INC
|
||||
#undef RX_SAMP_DBG
|
||||
@ -1278,6 +1252,8 @@ static const struct file_operations fops_modal_eeprom = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
|
||||
void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
|
||||
{
|
||||
#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c)
|
||||
@ -1551,6 +1527,7 @@ static const struct file_operations fops_samps = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
@ -1604,8 +1581,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
&fops_base_eeprom);
|
||||
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_modal_eeprom);
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_samps);
|
||||
#endif
|
||||
|
||||
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
|
||||
|
@ -165,13 +165,6 @@ struct ath_rx_stats {
|
||||
u32 post_delim_crc_err;
|
||||
u32 decrypt_busy_err;
|
||||
u32 phy_err_stats[ATH9K_PHYERR_MAX];
|
||||
int8_t rs_rssi_ctl0;
|
||||
int8_t rs_rssi_ctl1;
|
||||
int8_t rs_rssi_ctl2;
|
||||
int8_t rs_rssi_ext0;
|
||||
int8_t rs_rssi_ext1;
|
||||
int8_t rs_rssi_ext2;
|
||||
u8 rs_antenna;
|
||||
};
|
||||
|
||||
enum ath_reset_type {
|
||||
@ -235,16 +228,17 @@ struct ath9k_debug {
|
||||
struct dentry *debugfs_phy;
|
||||
u32 regidx;
|
||||
struct ath_stats stats;
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spinlock_t samp_lock;
|
||||
struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
|
||||
u8 sampidx;
|
||||
u8 tsidx;
|
||||
u8 rsidx;
|
||||
#endif
|
||||
};
|
||||
|
||||
int ath9k_init_debug(struct ath_hw *ah);
|
||||
|
||||
void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
|
||||
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_tx_status *ts, struct ath_txq *txq,
|
||||
@ -258,10 +252,6 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
|
||||
enum ath9k_int status)
|
||||
{
|
||||
@ -282,4 +272,17 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc,
|
||||
|
||||
#endif /* CONFIG_ATH9K_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
|
||||
void ath9k_debug_samp_bb_mac(struct ath_softc *sc);
|
||||
|
||||
#else
|
||||
|
||||
static inline void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* DEBUG_H */
|
||||
|
@ -1386,10 +1386,16 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
|
||||
static bool ath9k_hw_chip_reset(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) {
|
||||
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
|
||||
return false;
|
||||
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
|
||||
int reset_type = ATH9K_RESET_WARM;
|
||||
|
||||
if (AR_SREV_9280(ah)) {
|
||||
if (ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
|
||||
reset_type = ATH9K_RESET_POWER_ON;
|
||||
else
|
||||
reset_type = ATH9K_RESET_COLD;
|
||||
}
|
||||
|
||||
if (!ath9k_hw_set_reset_reg(ah, reset_type))
|
||||
return false;
|
||||
|
||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
|
||||
|
@ -555,8 +555,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
mutex_init(&sc->mutex);
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
spin_lock_init(&sc->nodes_lock);
|
||||
spin_lock_init(&sc->debug.samp_lock);
|
||||
INIT_LIST_HEAD(&sc->nodes);
|
||||
#endif
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
spin_lock_init(&sc->debug.samp_lock);
|
||||
#endif
|
||||
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
|
||||
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
|
||||
|
@ -745,7 +745,11 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
|
||||
qi.tqi_aifs = 1;
|
||||
qi.tqi_cwmin = 0;
|
||||
qi.tqi_cwmax = 0;
|
||||
/* NB: don't enable any interrupts */
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
|
||||
TXQ_FLAG_TXERRINT_ENABLE;
|
||||
|
||||
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
|
||||
|
@ -2300,6 +2300,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
|
||||
struct ath_vif *avp;
|
||||
struct ath_buf *bf;
|
||||
struct ath_tx_status ts;
|
||||
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
|
||||
int status;
|
||||
|
||||
vif = sc->beacon.bslot[0];
|
||||
@ -2310,7 +2311,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
|
||||
if (!avp->is_bslot_active)
|
||||
return 0;
|
||||
|
||||
if (!sc->beacon.tx_processed) {
|
||||
if (!sc->beacon.tx_processed && !edma) {
|
||||
tasklet_disable(&sc->bcon_tasklet);
|
||||
|
||||
bf = avp->av_bcbuf;
|
||||
|
@ -1226,7 +1226,7 @@ static void ath_rc_init(struct ath_softc *sc,
|
||||
ath_rc_init_valid_rate_idx(ath_rc_priv);
|
||||
|
||||
for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
|
||||
for (j = 0; j < MAX_TX_RATE_PHY; j++)
|
||||
for (j = 0; j < RATE_TABLE_SIZE; j++)
|
||||
ath_rc_priv->valid_phy_rateidx[i][j] = 0;
|
||||
ath_rc_priv->valid_phy_ratecnt[i] = 0;
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ struct ath_softc;
|
||||
|
||||
#define ATH_RATE_MAX 30
|
||||
#define RATE_TABLE_SIZE 72
|
||||
#define MAX_TX_RATE_PHY 48
|
||||
|
||||
|
||||
#define RC_INVALID 0x0000
|
||||
#define RC_LEGACY 0x0001
|
||||
|
@ -169,22 +169,17 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
|
||||
enum ath9k_rx_qtype qtype, int size)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u32 nbuf = 0;
|
||||
struct ath_buf *bf, *tbf;
|
||||
|
||||
if (list_empty(&sc->rx.rxbuf)) {
|
||||
ath_dbg(common, QUEUE, "No free rx buf available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (!list_empty(&sc->rx.rxbuf)) {
|
||||
nbuf++;
|
||||
|
||||
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
|
||||
if (!ath_rx_edma_buf_link(sc, qtype))
|
||||
break;
|
||||
|
||||
if (nbuf >= size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_rx_remove_buffer(struct ath_softc *sc,
|
||||
@ -232,7 +227,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)
|
||||
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
|
||||
{
|
||||
skb_queue_head_init(&rx_edma->rx_fifo);
|
||||
skb_queue_head_init(&rx_edma->rx_buffers);
|
||||
rx_edma->rx_fifo_hwsize = size;
|
||||
}
|
||||
|
||||
@ -658,7 +652,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon)
|
||||
}
|
||||
|
||||
static bool ath_edma_get_buffers(struct ath_softc *sc,
|
||||
enum ath9k_rx_qtype qtype)
|
||||
enum ath9k_rx_qtype qtype,
|
||||
struct ath_rx_status *rs,
|
||||
struct ath_buf **dest)
|
||||
{
|
||||
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@ -677,7 +673,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
||||
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize, DMA_FROM_DEVICE);
|
||||
|
||||
ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
|
||||
ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
|
||||
if (ret == -EINPROGRESS) {
|
||||
/*let device gain the buffer again*/
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
@ -690,20 +686,21 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
||||
/* corrupt descriptor, skip this one and the following one */
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_edma_buf_link(sc, qtype);
|
||||
|
||||
skb = skb_peek(&rx_edma->rx_fifo);
|
||||
if (!skb)
|
||||
return true;
|
||||
if (skb) {
|
||||
bf = SKB_CB_ATHBUF(skb);
|
||||
BUG_ON(!bf);
|
||||
|
||||
bf = SKB_CB_ATHBUF(skb);
|
||||
BUG_ON(!bf);
|
||||
|
||||
__skb_unlink(skb, &rx_edma->rx_fifo);
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_edma_buf_link(sc, qtype);
|
||||
return true;
|
||||
__skb_unlink(skb, &rx_edma->rx_fifo);
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_edma_buf_link(sc, qtype);
|
||||
} else {
|
||||
bf = NULL;
|
||||
}
|
||||
}
|
||||
skb_queue_tail(&rx_edma->rx_buffers, skb);
|
||||
|
||||
*dest = bf;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -711,18 +708,15 @@ static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
|
||||
struct ath_rx_status *rs,
|
||||
enum ath9k_rx_qtype qtype)
|
||||
{
|
||||
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
|
||||
struct sk_buff *skb;
|
||||
struct ath_buf *bf;
|
||||
struct ath_buf *bf = NULL;
|
||||
|
||||
while (ath_edma_get_buffers(sc, qtype));
|
||||
skb = __skb_dequeue(&rx_edma->rx_buffers);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
|
||||
if (!bf)
|
||||
continue;
|
||||
|
||||
bf = SKB_CB_ATHBUF(skb);
|
||||
ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data);
|
||||
return bf;
|
||||
return bf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||
@ -954,6 +948,7 @@ static void ath9k_process_rssi(struct ath_common *common,
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = common->ah;
|
||||
int last_rssi;
|
||||
int rssi = rx_stats->rs_rssi;
|
||||
|
||||
if (!rx_stats->is_mybeacon ||
|
||||
((ah->opmode != NL80211_IFTYPE_STATION) &&
|
||||
@ -965,13 +960,12 @@ static void ath9k_process_rssi(struct ath_common *common,
|
||||
|
||||
last_rssi = sc->last_rssi;
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rx_stats->rs_rssi < 0)
|
||||
rx_stats->rs_rssi = 0;
|
||||
rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
|
||||
if (rssi < 0)
|
||||
rssi = 0;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
ah->stats.avgbrssi = rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1011,6 +1005,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
|
||||
rx_status->signal = ah->noise + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_MACTIME_MPDU;
|
||||
if (rx_stats->rs_moreaggr)
|
||||
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2296,9 +2296,12 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip beacon completions */
|
||||
if (ts.qid == sc->beacon.beaconq)
|
||||
/* Process beacon completions separately */
|
||||
if (ts.qid == sc->beacon.beaconq) {
|
||||
sc->beacon.tx_processed = true;
|
||||
sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
|
||||
continue;
|
||||
}
|
||||
|
||||
txq = &sc->tx.txq[ts.qid];
|
||||
|
||||
|
@ -2706,6 +2706,8 @@ static int b43_gpio_init(struct b43_wldev *dev)
|
||||
mask |= 0x0060;
|
||||
set |= 0x0060;
|
||||
}
|
||||
if (dev->dev->chip_id == 0x5354)
|
||||
set &= 0xff02;
|
||||
if (0 /* FIXME: conditional unknown */ ) {
|
||||
b43_write16(dev, B43_MMIO_GPIO_MASK,
|
||||
b43_read16(dev, B43_MMIO_GPIO_MASK)
|
||||
|
@ -1860,7 +1860,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
|
||||
* which accounts for the factor of 4 */
|
||||
#define REG_MAX_PWR 20
|
||||
max_pwr = min(REG_MAX_PWR * 4
|
||||
- dev->dev->bus->sprom.antenna_gain.ghz24.a0
|
||||
- dev->dev->bus->sprom.antenna_gain.a0
|
||||
- 0x6, max_pwr);
|
||||
|
||||
/* find the desired power in Q5.2 - power_level is in dBm
|
||||
|
@ -604,7 +604,7 @@ void brcmf_sdio_exit(void)
|
||||
sdio_unregister_driver(&brcmf_sdmmc_driver);
|
||||
}
|
||||
|
||||
int brcmf_sdio_init(void)
|
||||
void brcmf_sdio_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -614,6 +614,4 @@ int brcmf_sdio_init(void)
|
||||
|
||||
if (ret)
|
||||
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -108,11 +108,11 @@ extern int brcmf_add_if(struct device *dev, int ifidx,
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
extern void brcmf_sdio_exit(void);
|
||||
extern int brcmf_sdio_init(void);
|
||||
extern void brcmf_sdio_init(void);
|
||||
#endif
|
||||
#ifdef CONFIG_BRCMFMAC_USB
|
||||
extern void brcmf_usb_exit(void);
|
||||
extern int brcmf_usb_init(void);
|
||||
extern void brcmf_usb_init(void);
|
||||
#endif
|
||||
|
||||
#endif /* _BRCMF_BUS_H_ */
|
||||
|
@ -1181,27 +1181,29 @@ int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
static int __init brcmfmac_init(void)
|
||||
static void brcmf_driver_init(struct work_struct *work)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
ret = brcmf_sdio_init();
|
||||
if (ret)
|
||||
goto fail;
|
||||
brcmf_sdio_init();
|
||||
#endif
|
||||
#ifdef CONFIG_BRCMFMAC_USB
|
||||
ret = brcmf_usb_init();
|
||||
if (ret)
|
||||
goto fail;
|
||||
brcmf_usb_init();
|
||||
#endif
|
||||
}
|
||||
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
|
||||
|
||||
fail:
|
||||
return ret;
|
||||
static int __init brcmfmac_module_init(void)
|
||||
{
|
||||
if (!schedule_work(&brcmf_driver_work))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit brcmfmac_exit(void)
|
||||
static void __exit brcmfmac_module_exit(void)
|
||||
{
|
||||
cancel_work_sync(&brcmf_driver_work);
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
brcmf_sdio_exit();
|
||||
#endif
|
||||
@ -1210,5 +1212,5 @@ static void __exit brcmfmac_exit(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
module_init(brcmfmac_init);
|
||||
module_exit(brcmfmac_exit);
|
||||
module_init(brcmfmac_module_init);
|
||||
module_exit(brcmfmac_module_exit);
|
||||
|
@ -514,9 +514,9 @@ static void brcmf_usb_tx_complete(struct urb *urb)
|
||||
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
if (urb->status == 0)
|
||||
devinfo->bus_pub.stats.tx_packets++;
|
||||
devinfo->bus_pub.bus->dstats.tx_packets++;
|
||||
else
|
||||
devinfo->bus_pub.stats.tx_errors++;
|
||||
devinfo->bus_pub.bus->dstats.tx_errors++;
|
||||
|
||||
dev_kfree_skb(req->skb);
|
||||
req->skb = NULL;
|
||||
@ -536,9 +536,9 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
||||
req->skb = NULL;
|
||||
|
||||
if (urb->status == 0) {
|
||||
devinfo->bus_pub.stats.rx_packets++;
|
||||
devinfo->bus_pub.bus->dstats.rx_packets++;
|
||||
} else {
|
||||
devinfo->bus_pub.stats.rx_errors++;
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
dev_kfree_skb(skb);
|
||||
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
|
||||
return;
|
||||
@ -712,9 +712,6 @@ static int brcmf_usb_up(struct device *dev)
|
||||
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
|
||||
u16 ifnum;
|
||||
|
||||
if (devinfo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
|
||||
return 0;
|
||||
|
||||
@ -900,8 +897,8 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
|
||||
sizeof(struct bootrom_id_le));
|
||||
return false;
|
||||
} else {
|
||||
devinfo->bus_pub.attrib.devid = chipid;
|
||||
devinfo->bus_pub.attrib.chiprev = chiprev;
|
||||
devinfo->bus_pub.devid = chipid;
|
||||
devinfo->bus_pub.chiprev = chiprev;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1067,7 +1064,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
|
||||
if (devinfo == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (devinfo->bus_pub.attrib.devid == 0xDEAD)
|
||||
if (devinfo->bus_pub.devid == 0xDEAD)
|
||||
return -EINVAL;
|
||||
|
||||
err = brcmf_usb_dl_writeimage(devinfo, fw, len);
|
||||
@ -1088,7 +1085,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
|
||||
if (!devinfo)
|
||||
return -EINVAL;
|
||||
|
||||
if (devinfo->bus_pub.attrib.devid == 0xDEAD)
|
||||
if (devinfo->bus_pub.devid == 0xDEAD)
|
||||
return -EINVAL;
|
||||
|
||||
/* Check we are runnable */
|
||||
@ -1127,18 +1124,19 @@ static bool brcmf_usb_chip_support(int chipid, int chiprev)
|
||||
static int
|
||||
brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
|
||||
{
|
||||
struct brcmf_usb_attrib *attr;
|
||||
int devid, chiprev;
|
||||
int err;
|
||||
|
||||
brcmf_dbg(TRACE, "enter\n");
|
||||
if (devinfo == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
attr = &devinfo->bus_pub.attrib;
|
||||
devid = devinfo->bus_pub.devid;
|
||||
chiprev = devinfo->bus_pub.chiprev;
|
||||
|
||||
if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) {
|
||||
if (!brcmf_usb_chip_support(devid, chiprev)) {
|
||||
brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
|
||||
attr->devid, attr->chiprev);
|
||||
devid, chiprev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1617,7 +1615,7 @@ void brcmf_usb_exit(void)
|
||||
g_image.len = 0;
|
||||
}
|
||||
|
||||
int brcmf_usb_init(void)
|
||||
void brcmf_usb_init(void)
|
||||
{
|
||||
return usb_register(&brcmf_usbdrvr);
|
||||
usb_register(&brcmf_usbdrvr);
|
||||
}
|
||||
|
@ -33,36 +33,12 @@ enum brcmf_usb_pnp_state {
|
||||
};
|
||||
|
||||
struct brcmf_stats {
|
||||
u32 tx_errors;
|
||||
u32 tx_packets;
|
||||
u32 tx_multicast;
|
||||
u32 tx_ctlpkts;
|
||||
u32 tx_ctlerrs;
|
||||
u32 tx_dropped;
|
||||
u32 tx_flushed;
|
||||
u32 rx_errors;
|
||||
u32 rx_packets;
|
||||
u32 rx_multicast;
|
||||
u32 rx_ctlpkts;
|
||||
u32 rx_ctlerrs;
|
||||
u32 rx_dropped;
|
||||
u32 rx_flushed;
|
||||
|
||||
};
|
||||
|
||||
struct brcmf_usb_attrib {
|
||||
int bustype;
|
||||
int vid;
|
||||
int pid;
|
||||
int devid;
|
||||
int chiprev; /* chip revsion number */
|
||||
int mtu;
|
||||
int nchan; /* Data Channels */
|
||||
int has_2nd_bulk_in_ep;
|
||||
};
|
||||
|
||||
struct brcmf_usbdev_info;
|
||||
|
||||
struct brcmf_usbdev {
|
||||
struct brcmf_bus *bus;
|
||||
struct brcmf_usbdev_info *devinfo;
|
||||
@ -70,7 +46,8 @@ struct brcmf_usbdev {
|
||||
struct brcmf_stats stats;
|
||||
int ntxq, nrxq, rxsize;
|
||||
u32 bus_mtu;
|
||||
struct brcmf_usb_attrib attrib;
|
||||
int devid;
|
||||
int chiprev; /* chip revsion number */
|
||||
};
|
||||
|
||||
/* IO Request Block (IRB) */
|
||||
|
@ -959,14 +959,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
if (supr_status) {
|
||||
update_rate = false;
|
||||
if (supr_status == TX_STATUS_SUPR_BADCH) {
|
||||
wiphy_err(wiphy, "%s: Pkt tx suppressed, "
|
||||
"illegal channel possibly %d\n",
|
||||
wiphy_err(wiphy,
|
||||
"%s: Pkt tx suppressed, illegal channel possibly %d\n",
|
||||
__func__, CHSPEC_CHANNEL(
|
||||
wlc->default_bss->chanspec));
|
||||
} else {
|
||||
if (supr_status != TX_STATUS_SUPR_FRAG)
|
||||
wiphy_err(wiphy, "%s:"
|
||||
"supr_status 0x%x\n",
|
||||
wiphy_err(wiphy, "%s: supr_status 0x%x\n",
|
||||
__func__, supr_status);
|
||||
}
|
||||
/* no need to retry for badch; will fail again */
|
||||
@ -988,9 +987,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
}
|
||||
} else if (txs->phyerr) {
|
||||
update_rate = false;
|
||||
wiphy_err(wiphy, "wl%d: ampdu tx phy "
|
||||
"error (0x%x)\n", wlc->pub->unit,
|
||||
txs->phyerr);
|
||||
wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
|
||||
__func__, txs->phyerr);
|
||||
|
||||
if (brcm_msg_level & LOG_ERROR_VAL) {
|
||||
brcmu_prpkt("txpkt (AMPDU)", p);
|
||||
@ -1018,10 +1016,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
ack_recd = false;
|
||||
if (ba_recd) {
|
||||
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
|
||||
BCMMSG(wlc->wiphy, "tid %d seq %d,"
|
||||
" start_seq %d, bindex %d set %d, index %d\n",
|
||||
tid, seq, start_seq, bindex,
|
||||
isset(bitmap, bindex), index);
|
||||
BCMMSG(wiphy,
|
||||
"tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
|
||||
tid, seq, start_seq, bindex,
|
||||
isset(bitmap, bindex), index);
|
||||
/* if acked then clear bit and free packet */
|
||||
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
|
||||
&& isset(bitmap, bindex)) {
|
||||
|
@ -1169,25 +1169,31 @@ static struct bcma_driver brcms_bcma_driver = {
|
||||
/**
|
||||
* This is the main entry point for the brcmsmac driver.
|
||||
*
|
||||
* This function determines if a device pointed to by pdev is a WL device,
|
||||
* and if so, performs a brcms_attach() on it.
|
||||
*
|
||||
* This function is scheduled upon module initialization and
|
||||
* does the driver registration, which result in brcms_bcma_probe()
|
||||
* call resulting in the driver bringup.
|
||||
*/
|
||||
static void brcms_driver_init(struct work_struct *work)
|
||||
{
|
||||
int error;
|
||||
|
||||
error = bcma_driver_register(&brcms_bcma_driver);
|
||||
if (error)
|
||||
pr_err("%s: register returned %d\n", __func__, error);
|
||||
}
|
||||
|
||||
static DECLARE_WORK(brcms_driver_work, brcms_driver_init);
|
||||
|
||||
static int __init brcms_module_init(void)
|
||||
{
|
||||
int error = -ENODEV;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (msglevel != 0xdeadbeef)
|
||||
brcm_msg_level = msglevel;
|
||||
#endif /* DEBUG */
|
||||
#endif
|
||||
if (!schedule_work(&brcms_driver_work))
|
||||
return -EBUSY;
|
||||
|
||||
error = bcma_driver_register(&brcms_bcma_driver);
|
||||
pr_err("%s: register returned %d\n", __func__, error);
|
||||
if (!error)
|
||||
return 0;
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1199,6 +1205,7 @@ static int __init brcms_module_init(void)
|
||||
*/
|
||||
static void __exit brcms_module_exit(void)
|
||||
{
|
||||
cancel_work_sync(&brcms_driver_work);
|
||||
bcma_driver_unregister(&brcms_bcma_driver);
|
||||
}
|
||||
|
||||
|
@ -298,8 +298,6 @@ static const char *command_types[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
#define WEXT_USECHANNELS 1
|
||||
|
||||
static const long ipw2100_frequencies[] = {
|
||||
2412, 2417, 2422, 2427,
|
||||
2432, 2437, 2442, 2447,
|
||||
|
@ -27,8 +27,6 @@
|
||||
#ifndef __ipw2200_h__
|
||||
#define __ipw2200_h__
|
||||
|
||||
#define WEXT_USECHANNELS 1
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -1,6 +1,6 @@
|
||||
config IWLWIFI
|
||||
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
|
||||
depends on PCI && MAC80211
|
||||
depends on PCI && MAC80211 && HAS_IOMEM
|
||||
select FW_LOADER
|
||||
select NEW_LEDS
|
||||
select LEDS_CLASS
|
||||
@ -127,3 +127,12 @@ config IWLWIFI_P2P
|
||||
support when it is loaded.
|
||||
|
||||
Say Y only if you want to experiment with P2P.
|
||||
|
||||
config IWLWIFI_EXPERIMENTAL_MFP
|
||||
bool "support MFP (802.11w) even if uCode doesn't advertise"
|
||||
depends on IWLWIFI
|
||||
help
|
||||
This option enables experimental MFP (802.11W) support
|
||||
even if the microcode doesn't advertise it.
|
||||
|
||||
Say Y only if you want to experiment with MFP.
|
||||
|
@ -14,7 +14,7 @@ iwlwifi-objs += iwl-1000.o
|
||||
iwlwifi-objs += iwl-2000.o
|
||||
iwlwifi-objs += iwl-pci.o
|
||||
iwlwifi-objs += iwl-drv.o
|
||||
iwlwifi-objs += iwl-trans.o
|
||||
iwlwifi-objs += iwl-notif-wait.o
|
||||
iwlwifi-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
|
||||
|
||||
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-cfg.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL1000_UCODE_API_MAX 6
|
||||
@ -95,9 +96,8 @@ static void iwl1000_nic_config(struct iwl_priv *priv)
|
||||
~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK);
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
|
||||
static const struct iwl_sensitivity_ranges iwl1000_sensitivity = {
|
||||
.min_nrg_cck = 95,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 90,
|
||||
.auto_corr_min_ofdm_mrc = 170,
|
||||
.auto_corr_min_ofdm_x1 = 120,
|
||||
@ -122,23 +122,15 @@ static struct iwl_sensitivity_ranges iwl1000_sensitivity = {
|
||||
|
||||
static void iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
cfg(priv)->base_params->num_of_queues =
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||
|
||||
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||
hw_params(priv).tx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_tx_ant);
|
||||
if (cfg(priv)->rx_with_siso_diversity)
|
||||
hw_params(priv).rx_chains_num = 1;
|
||||
else
|
||||
hw_params(priv).rx_chains_num =
|
||||
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
num_of_ant(hw_params(priv).valid_rx_ant);
|
||||
|
||||
iwl1000_set_ct_threshold(priv);
|
||||
|
||||
@ -163,7 +155,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl1000_base_params = {
|
||||
static const struct iwl_base_params iwl1000_base_params = {
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
@ -178,7 +170,8 @@ static struct iwl_base_params iwl1000_base_params = {
|
||||
.max_event_log_size = 128,
|
||||
.wd_disable = true,
|
||||
};
|
||||
static struct iwl_ht_params iwl1000_ht_params = {
|
||||
|
||||
static const struct iwl_ht_params iwl1000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
.use_rts_for_aggregation = true, /* use rts/cts protection */
|
||||
.smps_mode = IEEE80211_SMPS_DYNAMIC,
|
||||
@ -197,13 +190,13 @@ static struct iwl_ht_params iwl1000_ht_params = {
|
||||
.base_params = &iwl1000_base_params, \
|
||||
.led_mode = IWL_LED_BLINK
|
||||
|
||||
struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
const struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
|
||||
IWL_DEVICE_1000,
|
||||
.ht_params = &iwl1000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1000_bg_cfg = {
|
||||
const struct iwl_cfg iwl1000_bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
|
||||
IWL_DEVICE_1000,
|
||||
};
|
||||
@ -222,13 +215,13 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.rx_with_siso_diversity = true
|
||||
|
||||
struct iwl_cfg iwl100_bgn_cfg = {
|
||||
const struct iwl_cfg iwl100_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
|
||||
IWL_DEVICE_100,
|
||||
.ht_params = &iwl1000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl100_bg_cfg = {
|
||||
const struct iwl_cfg iwl100_bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
|
||||
IWL_DEVICE_100,
|
||||
};
|
||||
|
@ -91,9 +91,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
||||
static const struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
||||
.min_nrg_cck = 97,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 80,
|
||||
.auto_corr_min_ofdm_mrc = 128,
|
||||
.auto_corr_min_ofdm_x1 = 105,
|
||||
@ -118,23 +117,15 @@ static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
|
||||
|
||||
static void iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
cfg(priv)->base_params->num_of_queues =
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ);
|
||||
|
||||
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||
hw_params(priv).tx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_tx_ant);
|
||||
if (cfg(priv)->rx_with_siso_diversity)
|
||||
hw_params(priv).rx_chains_num = 1;
|
||||
else
|
||||
hw_params(priv).rx_chains_num =
|
||||
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
num_of_ant(hw_params(priv).valid_rx_ant);
|
||||
|
||||
iwl2000_set_ct_threshold(priv);
|
||||
|
||||
@ -155,16 +146,13 @@ static struct iwl_lib_ops iwl2000_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl2030_lib = {
|
||||
.set_hw_params = iwl2000_hw_set_hw_params,
|
||||
.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
|
||||
.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
||||
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
||||
.nic_config = iwl2000_nic_config,
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
@ -176,12 +164,12 @@ static struct iwl_lib_ops iwl2030_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REGULATORY_BAND_NO_HT40,
|
||||
},
|
||||
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl2000_base_params = {
|
||||
static const struct iwl_base_params iwl2000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -200,7 +188,7 @@ static struct iwl_base_params iwl2000_base_params = {
|
||||
};
|
||||
|
||||
|
||||
static struct iwl_base_params iwl2030_base_params = {
|
||||
static const struct iwl_base_params iwl2030_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -218,12 +206,12 @@ static struct iwl_base_params iwl2030_base_params = {
|
||||
.hd_v2 = true,
|
||||
};
|
||||
|
||||
static struct iwl_ht_params iwl2000_ht_params = {
|
||||
static const struct iwl_ht_params iwl2000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
.use_rts_for_aggregation = true, /* use rts/cts protection */
|
||||
};
|
||||
|
||||
static struct iwl_bt_params iwl2030_bt_params = {
|
||||
static const struct iwl_bt_params iwl2030_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
@ -249,13 +237,13 @@ static struct iwl_bt_params iwl2030_bt_params = {
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.iq_invert = true \
|
||||
|
||||
struct iwl_cfg iwl2000_2bgn_cfg = {
|
||||
const struct iwl_cfg iwl2000_2bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
|
||||
IWL_DEVICE_2000,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||
const struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
|
||||
IWL_DEVICE_2000,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
@ -279,7 +267,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||
.adv_pm = true, \
|
||||
.iq_invert = true \
|
||||
|
||||
struct iwl_cfg iwl2030_2bgn_cfg = {
|
||||
const struct iwl_cfg iwl2030_2bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
|
||||
IWL_DEVICE_2030,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
@ -303,13 +291,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
|
||||
.rx_with_siso_diversity = true, \
|
||||
.iq_invert = true \
|
||||
|
||||
struct iwl_cfg iwl105_bgn_cfg = {
|
||||
const struct iwl_cfg iwl105_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
|
||||
IWL_DEVICE_105,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl105_bgn_d_cfg = {
|
||||
const struct iwl_cfg iwl105_bgn_d_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
|
||||
IWL_DEVICE_105,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
@ -334,7 +322,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
|
||||
.rx_with_siso_diversity = true, \
|
||||
.iq_invert = true \
|
||||
|
||||
struct iwl_cfg iwl135_bgn_cfg = {
|
||||
const struct iwl_cfg iwl135_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
|
||||
IWL_DEVICE_135,
|
||||
.ht_params = &iwl2000_ht_params,
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-cfg.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL5000_UCODE_API_MAX 5
|
||||
@ -63,12 +64,8 @@
|
||||
/* NIC configuration for 5000 series */
|
||||
static void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
iwl_rf_config(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
|
||||
/* W/A : NIC is stuck in a reset state after Early PCIe power off
|
||||
* (PCIe power is lost before PERST# is asserted),
|
||||
* causing ME FW to lose ownership and not being able to obtain it back.
|
||||
@ -76,14 +73,10 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
|
||||
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
|
||||
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
|
||||
static const struct iwl_sensitivity_ranges iwl5000_sensitivity = {
|
||||
.min_nrg_cck = 100,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 90,
|
||||
.auto_corr_min_ofdm_mrc = 170,
|
||||
.auto_corr_min_ofdm_x1 = 105,
|
||||
@ -108,7 +101,6 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
|
||||
.min_nrg_cck = 95,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 90,
|
||||
.auto_corr_min_ofdm_mrc = 170,
|
||||
.auto_corr_min_ofdm_x1 = 105,
|
||||
@ -164,20 +156,13 @@ static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
|
||||
|
||||
static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
cfg(priv)->base_params->num_of_queues =
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
hw_params(priv).tx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_tx_ant);
|
||||
hw_params(priv).rx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_rx_ant);
|
||||
|
||||
iwl5000_set_ct_threshold(priv);
|
||||
|
||||
@ -187,20 +172,13 @@ static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
|
||||
static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
cfg(priv)->base_params->num_of_queues =
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant);
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
hw_params(priv).tx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_tx_ant);
|
||||
hw_params(priv).rx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_rx_ant);
|
||||
|
||||
iwl5150_set_ct_threshold(priv);
|
||||
|
||||
@ -288,7 +266,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &hcmd);
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl5000_lib = {
|
||||
@ -327,7 +305,7 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
.temperature = iwl5150_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl5000_base_params = {
|
||||
static const struct iwl_base_params iwl5000_base_params = {
|
||||
.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -340,7 +318,8 @@ static struct iwl_base_params iwl5000_base_params = {
|
||||
.no_idle_support = true,
|
||||
.wd_disable = true,
|
||||
};
|
||||
static struct iwl_ht_params iwl5000_ht_params = {
|
||||
|
||||
static const struct iwl_ht_params iwl5000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
};
|
||||
|
||||
@ -356,7 +335,7 @@ static struct iwl_ht_params iwl5000_ht_params = {
|
||||
.base_params = &iwl5000_base_params, \
|
||||
.led_mode = IWL_LED_BLINK
|
||||
|
||||
struct iwl_cfg iwl5300_agn_cfg = {
|
||||
const struct iwl_cfg iwl5300_agn_cfg = {
|
||||
.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
|
||||
IWL_DEVICE_5000,
|
||||
/* at least EEPROM 0x11A has wrong info */
|
||||
@ -365,7 +344,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
||||
.ht_params = &iwl5000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_bgn_cfg = {
|
||||
const struct iwl_cfg iwl5100_bgn_cfg = {
|
||||
.name = "Intel(R) WiFi Link 5100 BGN",
|
||||
IWL_DEVICE_5000,
|
||||
.valid_tx_ant = ANT_B, /* .cfg overwrite */
|
||||
@ -373,14 +352,14 @@ struct iwl_cfg iwl5100_bgn_cfg = {
|
||||
.ht_params = &iwl5000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_abg_cfg = {
|
||||
const struct iwl_cfg iwl5100_abg_cfg = {
|
||||
.name = "Intel(R) WiFi Link 5100 ABG",
|
||||
IWL_DEVICE_5000,
|
||||
.valid_tx_ant = ANT_B, /* .cfg overwrite */
|
||||
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_agn_cfg = {
|
||||
const struct iwl_cfg iwl5100_agn_cfg = {
|
||||
.name = "Intel(R) WiFi Link 5100 AGN",
|
||||
IWL_DEVICE_5000,
|
||||
.valid_tx_ant = ANT_B, /* .cfg overwrite */
|
||||
@ -388,7 +367,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
||||
.ht_params = &iwl5000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5350_agn_cfg = {
|
||||
const struct iwl_cfg iwl5350_agn_cfg = {
|
||||
.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
|
||||
.fw_name_pre = IWL5000_FW_PRE,
|
||||
.ucode_api_max = IWL5000_UCODE_API_MAX,
|
||||
@ -418,14 +397,14 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
||||
.led_mode = IWL_LED_BLINK, \
|
||||
.internal_wimax_coex = true
|
||||
|
||||
struct iwl_cfg iwl5150_agn_cfg = {
|
||||
const struct iwl_cfg iwl5150_agn_cfg = {
|
||||
.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
|
||||
IWL_DEVICE_5150,
|
||||
.ht_params = &iwl5000_ht_params,
|
||||
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5150_abg_cfg = {
|
||||
const struct iwl_cfg iwl5150_abg_cfg = {
|
||||
.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
|
||||
IWL_DEVICE_5150,
|
||||
};
|
||||
|
@ -96,25 +96,25 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
|
||||
CSR_GP_DRIVER_REG_BIT_6050_1x2);
|
||||
}
|
||||
|
||||
static void iwl6000i_additional_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
/* 2x2 IPA phy type */
|
||||
iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
}
|
||||
|
||||
/* NIC configuration for 6000 series */
|
||||
static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_rf_config(priv);
|
||||
|
||||
/* no locking required for register write */
|
||||
if (cfg(priv)->pa_type == IWL_PA_INTERNAL) {
|
||||
/* 2x2 IPA phy type */
|
||||
iwl_write32(trans(priv), CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
}
|
||||
/* do additional nic configuration if needed */
|
||||
if (cfg(priv)->additional_nic_config)
|
||||
cfg(priv)->additional_nic_config(priv);
|
||||
cfg(priv)->additional_nic_config(priv);
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
static const struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
.min_nrg_cck = 110,
|
||||
.max_nrg_cck = 0, /* not used, set to 0 */
|
||||
.auto_corr_min_ofdm = 80,
|
||||
.auto_corr_min_ofdm_mrc = 128,
|
||||
.auto_corr_min_ofdm_x1 = 105,
|
||||
@ -139,24 +139,16 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
|
||||
static void iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
cfg(priv)->base_params->num_of_queues =
|
||||
iwlagn_mod_params.num_of_queues;
|
||||
|
||||
hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
|
||||
|
||||
hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
|
||||
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant);
|
||||
hw_params(priv).tx_chains_num =
|
||||
num_of_ant(hw_params(priv).valid_tx_ant);
|
||||
if (cfg(priv)->rx_with_siso_diversity)
|
||||
hw_params(priv).rx_chains_num = 1;
|
||||
else
|
||||
hw_params(priv).rx_chains_num =
|
||||
num_of_ant(cfg(priv)->valid_rx_ant);
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
num_of_ant(hw_params(priv).valid_rx_ant);
|
||||
|
||||
iwl6000_set_ct_threshold(priv);
|
||||
|
||||
@ -233,7 +225,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &hcmd);
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl6000_lib = {
|
||||
@ -250,16 +242,13 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl6030_lib = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
|
||||
.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
|
||||
.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.nic_config = iwl6000_nic_config,
|
||||
.eeprom_ops = {
|
||||
@ -272,12 +261,12 @@ static struct iwl_lib_ops iwl6030_lib = {
|
||||
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower,
|
||||
.enhanced_txpower = true,
|
||||
},
|
||||
.temperature = iwlagn_temperature,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl6000_base_params = {
|
||||
static const struct iwl_base_params iwl6000_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -294,7 +283,7 @@ static struct iwl_base_params iwl6000_base_params = {
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl6050_base_params = {
|
||||
static const struct iwl_base_params iwl6050_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -310,7 +299,8 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||
.max_event_log_size = 1024,
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
static struct iwl_base_params iwl6000_g2_base_params = {
|
||||
|
||||
static const struct iwl_base_params iwl6000_g2_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.num_of_queues = IWLAGN_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
@ -327,12 +317,12 @@ static struct iwl_base_params iwl6000_g2_base_params = {
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
|
||||
static struct iwl_ht_params iwl6000_ht_params = {
|
||||
static const struct iwl_ht_params iwl6000_ht_params = {
|
||||
.ht_greenfield_support = true,
|
||||
.use_rts_for_aggregation = true, /* use rts/cts protection */
|
||||
};
|
||||
|
||||
static struct iwl_bt_params iwl6000_bt_params = {
|
||||
static const struct iwl_bt_params iwl6000_bt_params = {
|
||||
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
|
||||
.advanced_bt_coexist = true,
|
||||
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
|
||||
@ -355,40 +345,41 @@ static struct iwl_bt_params iwl6000_bt_params = {
|
||||
.need_temp_offset_calib = true, \
|
||||
.led_mode = IWL_LED_RF_STATE
|
||||
|
||||
struct iwl_cfg iwl6005_2agn_cfg = {
|
||||
const struct iwl_cfg iwl6005_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
|
||||
IWL_DEVICE_6005,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6005_2abg_cfg = {
|
||||
const struct iwl_cfg iwl6005_2abg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
|
||||
IWL_DEVICE_6005,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6005_2bg_cfg = {
|
||||
const struct iwl_cfg iwl6005_2bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
|
||||
IWL_DEVICE_6005,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6005_2agn_sff_cfg = {
|
||||
const struct iwl_cfg iwl6005_2agn_sff_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
|
||||
IWL_DEVICE_6005,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6005_2agn_d_cfg = {
|
||||
const struct iwl_cfg iwl6005_2agn_d_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
|
||||
IWL_DEVICE_6005,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6005_2agn_mow1_cfg = {
|
||||
const struct iwl_cfg iwl6005_2agn_mow1_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
|
||||
IWL_DEVICE_6005,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
struct iwl_cfg iwl6005_2agn_mow2_cfg = {
|
||||
|
||||
const struct iwl_cfg iwl6005_2agn_mow2_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
|
||||
IWL_DEVICE_6005,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
@ -410,53 +401,53 @@ struct iwl_cfg iwl6005_2agn_mow2_cfg = {
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true \
|
||||
|
||||
struct iwl_cfg iwl6030_2agn_cfg = {
|
||||
const struct iwl_cfg iwl6030_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
|
||||
IWL_DEVICE_6030,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6030_2abg_cfg = {
|
||||
const struct iwl_cfg iwl6030_2abg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
|
||||
IWL_DEVICE_6030,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6030_2bgn_cfg = {
|
||||
const struct iwl_cfg iwl6030_2bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
|
||||
IWL_DEVICE_6030,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6030_2bg_cfg = {
|
||||
const struct iwl_cfg iwl6030_2bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
|
||||
IWL_DEVICE_6030,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6035_2agn_cfg = {
|
||||
const struct iwl_cfg iwl6035_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
|
||||
IWL_DEVICE_6030,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1030_bgn_cfg = {
|
||||
const struct iwl_cfg iwl1030_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
|
||||
IWL_DEVICE_6030,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1030_bg_cfg = {
|
||||
const struct iwl_cfg iwl1030_bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
|
||||
IWL_DEVICE_6030,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl130_bgn_cfg = {
|
||||
const struct iwl_cfg iwl130_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
|
||||
IWL_DEVICE_6030,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
.rx_with_siso_diversity = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl130_bg_cfg = {
|
||||
const struct iwl_cfg iwl130_bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
|
||||
IWL_DEVICE_6030,
|
||||
.rx_with_siso_diversity = true,
|
||||
@ -477,22 +468,22 @@ struct iwl_cfg iwl130_bg_cfg = {
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
|
||||
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
|
||||
.lib = &iwl6000_lib, \
|
||||
.additional_nic_config = iwl6000i_additional_nic_config,\
|
||||
.base_params = &iwl6000_base_params, \
|
||||
.pa_type = IWL_PA_INTERNAL, \
|
||||
.led_mode = IWL_LED_BLINK
|
||||
|
||||
struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
const struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
|
||||
IWL_DEVICE_6000i,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
const struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
|
||||
IWL_DEVICE_6000i,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
const struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
|
||||
IWL_DEVICE_6000i,
|
||||
};
|
||||
@ -513,13 +504,13 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
.led_mode = IWL_LED_BLINK, \
|
||||
.internal_wimax_coex = true
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
const struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
|
||||
IWL_DEVICE_6050,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
const struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
|
||||
IWL_DEVICE_6050,
|
||||
};
|
||||
@ -538,18 +529,18 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.led_mode = IWL_LED_BLINK, \
|
||||
.internal_wimax_coex = true
|
||||
|
||||
struct iwl_cfg iwl6150_bgn_cfg = {
|
||||
const struct iwl_cfg iwl6150_bgn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
|
||||
IWL_DEVICE_6150,
|
||||
.ht_params = &iwl6000_ht_params,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6150_bg_cfg = {
|
||||
const struct iwl_cfg iwl6150_bg_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
|
||||
IWL_DEVICE_6150,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
const struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
.ucode_api_max = IWL6000_UCODE_API_MAX,
|
||||
|
@ -68,13 +68,19 @@
|
||||
#include "iwl-agn-calib.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-ucode.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* INIT calibrations framework
|
||||
*****************************************************************************/
|
||||
|
||||
/* Opaque calibration results */
|
||||
struct iwl_calib_result {
|
||||
struct list_head list;
|
||||
size_t cmd_len;
|
||||
struct iwl_calib_hdr hdr;
|
||||
/* data follows */
|
||||
};
|
||||
|
||||
struct statistics_general_data {
|
||||
u32 beacon_silence_rssi_a;
|
||||
u32 beacon_silence_rssi_b;
|
||||
@ -84,7 +90,7 @@ struct statistics_general_data {
|
||||
u32 beacon_energy_c;
|
||||
};
|
||||
|
||||
int iwl_send_calib_results(struct iwl_trans *trans)
|
||||
int iwl_send_calib_results(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_PHY_CALIBRATION_CMD,
|
||||
@ -92,15 +98,15 @@ int iwl_send_calib_results(struct iwl_trans *trans)
|
||||
};
|
||||
struct iwl_calib_result *res;
|
||||
|
||||
list_for_each_entry(res, &trans->calib_results, list) {
|
||||
list_for_each_entry(res, &priv->calib_results, list) {
|
||||
int ret;
|
||||
|
||||
hcmd.len[0] = res->cmd_len;
|
||||
hcmd.data[0] = &res->hdr;
|
||||
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
|
||||
ret = iwl_trans_send_cmd(trans, &hcmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &hcmd);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Error %d on calib cmd %d\n",
|
||||
IWL_ERR(priv, "Error %d on calib cmd %d\n",
|
||||
ret, res->hdr.op_code);
|
||||
return ret;
|
||||
}
|
||||
@ -109,7 +115,7 @@ int iwl_send_calib_results(struct iwl_trans *trans)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_calib_set(struct iwl_trans *trans,
|
||||
int iwl_calib_set(struct iwl_priv *priv,
|
||||
const struct iwl_calib_hdr *cmd, int len)
|
||||
{
|
||||
struct iwl_calib_result *res, *tmp;
|
||||
@ -121,7 +127,7 @@ int iwl_calib_set(struct iwl_trans *trans,
|
||||
memcpy(&res->hdr, cmd, len);
|
||||
res->cmd_len = len;
|
||||
|
||||
list_for_each_entry(tmp, &trans->calib_results, list) {
|
||||
list_for_each_entry(tmp, &priv->calib_results, list) {
|
||||
if (tmp->hdr.op_code == res->hdr.op_code) {
|
||||
list_replace(&tmp->list, &res->list);
|
||||
kfree(tmp);
|
||||
@ -130,16 +136,16 @@ int iwl_calib_set(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
/* wasn't in list already */
|
||||
list_add_tail(&res->list, &trans->calib_results);
|
||||
list_add_tail(&res->list, &priv->calib_results);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_calib_free_results(struct iwl_trans *trans)
|
||||
void iwl_calib_free_results(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_result *res, *tmp;
|
||||
|
||||
list_for_each_entry_safe(res, tmp, &trans->calib_results, list) {
|
||||
list_for_each_entry_safe(res, tmp, &priv->calib_results, list) {
|
||||
list_del(&res->list);
|
||||
kfree(res);
|
||||
}
|
||||
@ -494,7 +500,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
|
||||
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
|
||||
sizeof(u16)*HD_TABLE_SIZE);
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd_out);
|
||||
return iwl_dvm_send_cmd(priv, &cmd_out);
|
||||
}
|
||||
|
||||
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
|
||||
@ -583,7 +589,7 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
|
||||
&(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
|
||||
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES);
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd_out);
|
||||
return iwl_dvm_send_cmd(priv, &cmd_out);
|
||||
}
|
||||
|
||||
void iwl_init_sensitivity(struct iwl_priv *priv)
|
||||
@ -636,7 +642,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
|
||||
data->last_bad_plcp_cnt_cck = 0;
|
||||
data->last_fa_cnt_cck = 0;
|
||||
|
||||
if (nic(priv)->fw.enhance_sensitivity_table)
|
||||
if (priv->fw->enhance_sensitivity_table)
|
||||
ret |= iwl_enhance_sensitivity_write(priv);
|
||||
else
|
||||
ret |= iwl_sensitivity_write(priv);
|
||||
@ -655,7 +661,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
|
||||
struct iwl_sensitivity_data *data = NULL;
|
||||
struct statistics_rx_non_phy *rx_info;
|
||||
struct statistics_rx_phy *ofdm, *cck;
|
||||
unsigned long flags;
|
||||
struct statistics_general_data statis;
|
||||
|
||||
if (priv->disable_sens_cal)
|
||||
@ -668,13 +673,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
rx_info = &priv->statistics.rx_non_phy;
|
||||
ofdm = &priv->statistics.rx_ofdm;
|
||||
cck = &priv->statistics.rx_cck;
|
||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||
IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -698,7 +703,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
|
||||
statis.beacon_energy_c =
|
||||
le32_to_cpu(rx_info->beacon_energy_c);
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
|
||||
|
||||
@ -747,7 +752,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
|
||||
|
||||
iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
|
||||
iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
|
||||
if (nic(priv)->fw.enhance_sensitivity_table)
|
||||
if (priv->fw->enhance_sensitivity_table)
|
||||
iwl_enhance_sensitivity_write(priv);
|
||||
else
|
||||
iwl_sensitivity_write(priv);
|
||||
@ -849,7 +854,7 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
||||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
find_first_chain(cfg(priv)->valid_tx_ant);
|
||||
find_first_chain(hw_params(priv).valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
@ -874,10 +879,8 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
||||
}
|
||||
|
||||
static void iwlagn_gain_computation(struct iwl_priv *priv,
|
||||
u32 average_noise[NUM_RX_CHAINS],
|
||||
u16 min_average_noise_antenna_i,
|
||||
u32 min_average_noise,
|
||||
u8 default_chain)
|
||||
u32 average_noise[NUM_RX_CHAINS],
|
||||
u8 default_chain)
|
||||
{
|
||||
int i;
|
||||
s32 delta_g;
|
||||
@ -925,7 +928,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
|
||||
priv->phy_calib_chain_noise_gain_cmd);
|
||||
cmd.delta_gain_1 = data->delta_gain_code[1];
|
||||
cmd.delta_gain_2 = data->delta_gain_code[2];
|
||||
iwl_trans_send_cmd_pdu(trans(priv), REPLY_PHY_CALIBRATION_CMD,
|
||||
iwl_dvm_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
|
||||
CMD_ASYNC, sizeof(cmd), &cmd);
|
||||
|
||||
data->radio_write = 1;
|
||||
@ -958,7 +961,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
u16 stat_chnum = INITIALIZATION_VALUE;
|
||||
u8 rxon_band24;
|
||||
u8 stat_band24;
|
||||
unsigned long flags;
|
||||
struct statistics_rx_non_phy *rx_info;
|
||||
|
||||
/*
|
||||
@ -983,13 +985,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
|
||||
rx_info = &priv->statistics.rx_non_phy;
|
||||
|
||||
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
|
||||
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1004,7 +1006,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
|
||||
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
|
||||
rxon_chnum, rxon_band24);
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1023,7 +1025,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
|
||||
chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
data->beacon_count++;
|
||||
|
||||
@ -1083,8 +1085,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
min_average_noise, min_average_noise_antenna_i);
|
||||
|
||||
iwlagn_gain_computation(priv, average_noise,
|
||||
min_average_noise_antenna_i, min_average_noise,
|
||||
find_first_chain(cfg(priv)->valid_rx_ant));
|
||||
find_first_chain(hw_params(priv).valid_rx_ant));
|
||||
|
||||
/* Some power changes may have been made during the calibration.
|
||||
* Update and commit the RXON
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
@ -52,7 +51,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
||||
struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
|
||||
u8 tx_ant_cfg_cmd;
|
||||
|
||||
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
|
||||
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
|
||||
"TX Power requested while scanning!\n"))
|
||||
return -EAGAIN;
|
||||
|
||||
@ -77,17 +76,19 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
||||
tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
|
||||
tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
|
||||
|
||||
if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) == 1)
|
||||
if (IWL_UCODE_API(priv->fw->ucode_ver) == 1)
|
||||
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
|
||||
else
|
||||
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
|
||||
|
||||
return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
|
||||
return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC,
|
||||
sizeof(tx_power_cmd), &tx_power_cmd);
|
||||
}
|
||||
|
||||
void iwlagn_temperature(struct iwl_priv *priv)
|
||||
{
|
||||
lockdep_assert_held(&priv->statistics.lock);
|
||||
|
||||
/* store temperature from correct statistics (in Celsius) */
|
||||
priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
|
||||
iwl_tt_handler(priv);
|
||||
@ -233,19 +234,19 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
|
||||
IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
|
||||
IWL_PAN_SCD_MULTICAST_MSK;
|
||||
|
||||
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
|
||||
flush_cmd.fifo_control);
|
||||
flush_cmd.flush_control = cpu_to_le16(flush_control);
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
|
||||
{
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
|
||||
IWL_ERR(priv, "flush request fail\n");
|
||||
@ -255,7 +256,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
|
||||
iwl_trans_wait_tx_queue_empty(trans(priv));
|
||||
done:
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -434,12 +435,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
|
||||
if (cfg(priv)->bt_params->bt_session_2) {
|
||||
memcpy(&bt_cmd_2000.basic, &basic,
|
||||
sizeof(basic));
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
|
||||
CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
|
||||
} else {
|
||||
memcpy(&bt_cmd_6000.basic, &basic,
|
||||
sizeof(basic));
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
|
||||
CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
|
||||
}
|
||||
if (ret)
|
||||
@ -452,7 +453,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
|
||||
struct iwl_rxon_context *ctx, *found_ctx = NULL;
|
||||
bool found_ap = false;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Check whether AP or GO mode is active. */
|
||||
if (rssi_ena) {
|
||||
@ -565,7 +566,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/*
|
||||
* We can not send command to firmware while scanning. When the scan
|
||||
@ -574,7 +575,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
* STATUS_SCANNING to avoid race when queue_work two times from
|
||||
* different notifications, but quit and not perform any work at all.
|
||||
*/
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status))
|
||||
goto out;
|
||||
|
||||
iwl_update_chain_flags(priv);
|
||||
@ -593,7 +594,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
*/
|
||||
iwlagn_bt_coex_rssi_monitor(priv);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -705,12 +706,11 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
|
||||
struct iwl_bt_coex_profile_notif *coex = (void *)pkt->data;
|
||||
struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
|
||||
|
||||
if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
|
||||
@ -754,9 +754,7 @@ int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
|
||||
/* FIXME: based on notification, adjust the prio_boost */
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
priv->bt_ci_compliance = coex->bt_ci_compliance;
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -971,7 +969,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||
u16 p1k[IWLAGN_P1K_SIZE];
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
|
||||
key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
|
||||
@ -1077,7 +1075,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
int iwlagn_send_patterns(struct iwl_priv *priv,
|
||||
@ -1117,13 +1115,12 @@ int iwlagn_send_patterns(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
cmd.data[0] = pattern_cmd;
|
||||
err = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
err = iwl_dvm_send_cmd(priv, &cmd);
|
||||
kfree(pattern_cmd);
|
||||
return err;
|
||||
}
|
||||
|
||||
int iwlagn_suspend(struct iwl_priv *priv,
|
||||
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
|
||||
int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
|
||||
struct iwl_rxon_cmd rxon;
|
||||
@ -1194,9 +1191,9 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
priv->shrd->wowlan = true;
|
||||
priv->wowlan = true;
|
||||
|
||||
ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_WOWLAN);
|
||||
ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -1224,11 +1221,11 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
* constraints. Since we're in the suspend path
|
||||
* that isn't really a problem though.
|
||||
*/
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
ieee80211_iter_keys(priv->hw, ctx->vif,
|
||||
iwlagn_wowlan_program_keys,
|
||||
&key_data);
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
if (key_data.error) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
@ -1243,13 +1240,13 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
.len[0] = sizeof(key_data.rsc_tsc),
|
||||
};
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &rsc_tsc_cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &rsc_tsc_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (key_data.use_tkip) {
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv),
|
||||
ret = iwl_dvm_send_cmd_pdu(priv,
|
||||
REPLY_WOWLAN_TKIP_PARAMS,
|
||||
CMD_SYNC, sizeof(tkip_cmd),
|
||||
&tkip_cmd);
|
||||
@ -1265,7 +1262,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
|
||||
kek_kck_cmd.replay_ctr = priv->replay_ctr;
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv),
|
||||
ret = iwl_dvm_send_cmd_pdu(priv,
|
||||
REPLY_WOWLAN_KEK_KCK_MATERIAL,
|
||||
CMD_SYNC, sizeof(kek_kck_cmd),
|
||||
&kek_kck_cmd);
|
||||
@ -1274,12 +1271,12 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_D3_CONFIG, CMD_SYNC,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC,
|
||||
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WOWLAN_WAKEUP_FILTER,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER,
|
||||
CMD_SYNC, sizeof(wakeup_filter_cmd),
|
||||
&wakeup_filter_cmd);
|
||||
if (ret)
|
||||
@ -1291,3 +1288,41 @@ int iwlagn_suspend(struct iwl_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
|
||||
IWL_WARN(priv, "Not sending command - %s KILL\n",
|
||||
iwl_is_rfkill(priv) ? "RF" : "CT");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronous commands from this op-mode must hold
|
||||
* the mutex, this ensures we don't try to send two
|
||||
* (or more) synchronous commands at a time.
|
||||
*/
|
||||
if (cmd->flags & CMD_SYNC)
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (priv->ucode_owner == IWL_OWNERSHIP_TM &&
|
||||
!(cmd->flags & CMD_ON_DEMAND)) {
|
||||
IWL_DEBUG_HC(priv, "tm own the uCode, no regular hcmd send\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), cmd);
|
||||
}
|
||||
|
||||
int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
|
||||
u32 flags, u16 len, const void *data)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = id,
|
||||
.len = { len, },
|
||||
.data = { data, },
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
@ -870,19 +870,16 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
{
|
||||
struct iwl_scale_tbl_info *tbl;
|
||||
bool full_concurrent = priv->bt_full_concurrent;
|
||||
unsigned long flags;
|
||||
|
||||
if (priv->bt_ant_couple_ok) {
|
||||
/*
|
||||
* Is there a need to switch between
|
||||
* full concurrency and 3-wire?
|
||||
*/
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
|
||||
full_concurrent = true;
|
||||
else
|
||||
full_concurrent = false;
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
}
|
||||
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
|
||||
(priv->bt_full_concurrent != full_concurrent)) {
|
||||
@ -2680,7 +2677,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
* which requires station table entry to exist).
|
||||
*/
|
||||
static void rs_initialize_lq(struct iwl_priv *priv,
|
||||
struct ieee80211_conf *conf,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_lq_sta *lq_sta)
|
||||
{
|
||||
@ -2915,7 +2911,7 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
|
||||
lq_sta->dbg_fixed_rate = 0;
|
||||
#endif
|
||||
|
||||
rs_initialize_lq(priv, conf, sta, lq_sta);
|
||||
rs_initialize_lq(priv, sta, lq_sta);
|
||||
}
|
||||
|
||||
static void rs_fill_link_cmd(struct iwl_priv *priv,
|
||||
|
@ -131,26 +131,27 @@ const char *get_cmd_string(u8 cmd)
|
||||
******************************************************************************/
|
||||
|
||||
static int iwlagn_rx_reply_error(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_error_resp *err_resp = (void *)pkt->data;
|
||||
|
||||
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
|
||||
"seq 0x%04X ser 0x%08X\n",
|
||||
le32_to_cpu(pkt->u.err_resp.error_type),
|
||||
get_cmd_string(pkt->u.err_resp.cmd_id),
|
||||
pkt->u.err_resp.cmd_id,
|
||||
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
|
||||
le32_to_cpu(pkt->u.err_resp.error_info));
|
||||
le32_to_cpu(err_resp->error_type),
|
||||
get_cmd_string(err_resp->cmd_id),
|
||||
err_resp->cmd_id,
|
||||
le16_to_cpu(err_resp->bad_cmd_seq_num),
|
||||
le32_to_cpu(err_resp->error_info));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
|
||||
struct iwl_csa_notification *csa = (void *)pkt->data;
|
||||
/*
|
||||
* MULTI-FIXME
|
||||
* See iwlagn_mac_channel_switch.
|
||||
@ -158,7 +159,7 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
|
||||
|
||||
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
|
||||
return 0;
|
||||
|
||||
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
|
||||
@ -177,11 +178,11 @@ static int iwlagn_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
|
||||
|
||||
static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
|
||||
struct iwl_spectrum_notification *report = (void *)pkt->data;
|
||||
|
||||
if (!report->state) {
|
||||
IWL_DEBUG_11H(priv,
|
||||
@ -195,12 +196,12 @@ static int iwlagn_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
|
||||
struct iwl_sleep_notification *sleep = (void *)pkt->data;
|
||||
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
|
||||
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
|
||||
#endif
|
||||
@ -208,7 +209,7 @@ static int iwlagn_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -217,16 +218,16 @@ static int iwlagn_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
|
||||
"notification for %s:\n", len,
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
|
||||
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_rx_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
|
||||
struct iwlagn_beacon_notif *beacon = (void *)pkt->data;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
|
||||
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
|
||||
@ -266,6 +267,8 @@ static bool iwlagn_good_ack_health(struct iwl_priv *priv,
|
||||
if (priv->agg_tids_count)
|
||||
return true;
|
||||
|
||||
lockdep_assert_held(&priv->statistics.lock);
|
||||
|
||||
old = &priv->statistics.tx;
|
||||
|
||||
actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
|
||||
@ -318,7 +321,7 @@ static bool iwlagn_good_plcp_health(struct iwl_priv *priv,
|
||||
unsigned int msecs)
|
||||
{
|
||||
int delta;
|
||||
int threshold = cfg(priv)->base_params->plcp_delta_threshold;
|
||||
int threshold = priv->plcp_delta_threshold;
|
||||
|
||||
if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
|
||||
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
|
||||
@ -352,7 +355,7 @@ static void iwlagn_recover_from_statistics(struct iwl_priv *priv,
|
||||
{
|
||||
unsigned int msecs;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
|
||||
@ -487,7 +490,7 @@ iwlagn_accumulative_statistics(struct iwl_priv *priv,
|
||||
#endif
|
||||
|
||||
static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
unsigned long stamp = jiffies;
|
||||
@ -509,9 +512,11 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
|
||||
len);
|
||||
|
||||
spin_lock(&priv->statistics.lock);
|
||||
|
||||
if (len == sizeof(struct iwl_bt_notif_statistics)) {
|
||||
struct iwl_bt_notif_statistics *stats;
|
||||
stats = &pkt->u.stats_bt;
|
||||
stats = (void *)&pkt->data;
|
||||
flag = &stats->flag;
|
||||
common = &stats->general.common;
|
||||
rx_non_phy = &stats->rx.general.common;
|
||||
@ -529,7 +534,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
#endif
|
||||
} else if (len == sizeof(struct iwl_notif_statistics)) {
|
||||
struct iwl_notif_statistics *stats;
|
||||
stats = &pkt->u.stats;
|
||||
stats = (void *)&pkt->data;
|
||||
flag = &stats->flag;
|
||||
common = &stats->general.common;
|
||||
rx_non_phy = &stats->rx.general;
|
||||
@ -542,6 +547,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
|
||||
len, sizeof(struct iwl_bt_notif_statistics),
|
||||
sizeof(struct iwl_notif_statistics));
|
||||
spin_unlock(&priv->statistics.lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -569,7 +575,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
|
||||
priv->rx_statistics_jiffies = stamp;
|
||||
|
||||
set_bit(STATUS_STATISTICS, &priv->shrd->status);
|
||||
set_bit(STATUS_STATISTICS, &priv->status);
|
||||
|
||||
/* Reschedule the statistics timer to occur in
|
||||
* reg_recalib_period seconds to ensure we get a
|
||||
@ -578,23 +584,27 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
|
||||
mod_timer(&priv->statistics_periodic, jiffies +
|
||||
msecs_to_jiffies(reg_recalib_period * 1000));
|
||||
|
||||
if (unlikely(!test_bit(STATUS_SCANNING, &priv->shrd->status)) &&
|
||||
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
|
||||
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
|
||||
iwlagn_rx_calc_noise(priv);
|
||||
queue_work(priv->workqueue, &priv->run_time_calib_work);
|
||||
}
|
||||
if (cfg(priv)->lib->temperature && change)
|
||||
cfg(priv)->lib->temperature(priv);
|
||||
|
||||
spin_unlock(&priv->statistics.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_notif_statistics *stats = (void *)pkt->data;
|
||||
|
||||
if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||
if (le32_to_cpu(stats->flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
memset(&priv->accum_stats, 0,
|
||||
sizeof(priv->accum_stats));
|
||||
@ -612,12 +622,13 @@ static int iwlagn_rx_reply_statistics(struct iwl_priv *priv,
|
||||
/* Handle notification from uCode that card's power state is changing
|
||||
* due to software, hardware, or critical temperature RFKILL */
|
||||
static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
|
||||
unsigned long status = priv->shrd->status;
|
||||
struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
|
||||
u32 flags = le32_to_cpu(card_state_notif->flags);
|
||||
unsigned long status = priv->status;
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
|
||||
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
|
||||
@ -647,32 +658,31 @@ static int iwlagn_rx_card_state_notif(struct iwl_priv *priv,
|
||||
iwl_tt_exit_ct_kill(priv);
|
||||
|
||||
if (flags & HW_CARD_DISABLED)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status);
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
|
||||
if (!(flags & RXON_CARD_DISABLED))
|
||||
iwl_scan_cancel(priv);
|
||||
|
||||
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status)))
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status)))
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
else
|
||||
wake_up(&priv->shrd->wait_command_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_beacon_notif *missed_beacon;
|
||||
struct iwl_missed_beacon_notif *missed_beacon = (void *)pkt->data;
|
||||
|
||||
missed_beacon = &pkt->u.missed_beacon;
|
||||
if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
|
||||
priv->missed_beacon_threshold) {
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
@ -681,7 +691,7 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
le32_to_cpu(missed_beacon->total_missed_becons),
|
||||
le32_to_cpu(missed_beacon->num_recvd_beacons),
|
||||
le32_to_cpu(missed_beacon->num_expected_beacons));
|
||||
if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_SCANNING, &priv->status))
|
||||
iwl_init_sensitivity(priv);
|
||||
}
|
||||
return 0;
|
||||
@ -690,13 +700,13 @@ static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
|
||||
* This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
|
||||
static int iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
priv->last_phy_res_valid = true;
|
||||
memcpy(&priv->last_phy_res, pkt->u.raw,
|
||||
memcpy(&priv->last_phy_res, pkt->data,
|
||||
sizeof(struct iwl_rx_phy_res));
|
||||
return 0;
|
||||
}
|
||||
@ -757,12 +767,14 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *hdr,
|
||||
u16 len,
|
||||
u32 ampdu_status,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct ieee80211_rx_status *stats)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
__le16 fc = hdr->frame_control;
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct page *p;
|
||||
int offset;
|
||||
|
||||
/* We only process data packets if the interface is open */
|
||||
if (unlikely(!priv->is_open)) {
|
||||
@ -782,7 +794,9 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
|
||||
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
|
||||
offset = (void *)hdr - rxb_addr(rxb);
|
||||
p = rxb_steal_page(rxb);
|
||||
skb_add_rx_frag(skb, 0, p, offset, len);
|
||||
|
||||
iwl_update_stats(priv, false, fc, len);
|
||||
|
||||
@ -793,23 +807,18 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
|
||||
* sometimes even after already having transmitted frames for the
|
||||
* association because the new RXON may reset the information.
|
||||
*/
|
||||
if (unlikely(ieee80211_is_beacon(fc))) {
|
||||
if (unlikely(ieee80211_is_beacon(fc) && priv->passive_no_rx)) {
|
||||
for_each_context(priv, ctx) {
|
||||
if (!ctx->last_tx_rejected)
|
||||
continue;
|
||||
if (compare_ether_addr(hdr->addr3,
|
||||
ctx->active.bssid_addr))
|
||||
continue;
|
||||
ctx->last_tx_rejected = false;
|
||||
iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
|
||||
"channel got active");
|
||||
iwlagn_lift_passive_no_rx(priv);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||
|
||||
ieee80211_rx(priv->hw, skb);
|
||||
rxb->page = NULL;
|
||||
}
|
||||
|
||||
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
|
||||
@ -915,7 +924,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
|
||||
/* Called for REPLY_RX (legacy ABG frames), or
|
||||
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
|
||||
static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_hdr *header;
|
||||
@ -938,12 +947,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
||||
* received.
|
||||
*/
|
||||
if (pkt->hdr.cmd == REPLY_RX) {
|
||||
phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
|
||||
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
|
||||
phy_res = (struct iwl_rx_phy_res *)pkt->data;
|
||||
header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res)
|
||||
+ phy_res->cfg_phy_cnt);
|
||||
|
||||
len = le16_to_cpu(phy_res->byte_count);
|
||||
rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
|
||||
rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*phy_res) +
|
||||
phy_res->cfg_phy_cnt + len);
|
||||
ampdu_status = le32_to_cpu(rx_pkt_status);
|
||||
} else {
|
||||
@ -952,10 +961,10 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
||||
return 0;
|
||||
}
|
||||
phy_res = &priv->last_phy_res;
|
||||
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
|
||||
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
|
||||
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
|
||||
header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
|
||||
len = le16_to_cpu(amsdu->byte_count);
|
||||
rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
|
||||
rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len);
|
||||
ampdu_status = iwlagn_translate_rx_status(priv,
|
||||
le32_to_cpu(rx_pkt_status));
|
||||
}
|
||||
@ -1035,12 +1044,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_wipan_noa_data *new_data, *old_data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->u.raw;
|
||||
struct iwl_wipan_noa_notification *noa_notif = (void *)pkt->data;
|
||||
|
||||
/* no condition -- we're in softirq */
|
||||
old_data = rcu_dereference_protected(priv->noa_data, true);
|
||||
@ -1086,7 +1095,7 @@ static int iwlagn_rx_noa_notification(struct iwl_priv *priv,
|
||||
*/
|
||||
void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
||||
{
|
||||
int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int (**handlers)(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
handlers = priv->rx_handlers;
|
||||
@ -1131,21 +1140,20 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
||||
priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
|
||||
|
||||
/* set up notification wait support */
|
||||
spin_lock_init(&priv->shrd->notif_wait_lock);
|
||||
INIT_LIST_HEAD(&priv->shrd->notif_waits);
|
||||
init_waitqueue_head(&priv->shrd->notif_waitq);
|
||||
iwl_notification_wait_init(&priv->notif_wait);
|
||||
|
||||
/* Set up BT Rx handlers */
|
||||
if (cfg(priv)->lib->bt_rx_handler_setup)
|
||||
cfg(priv)->lib->bt_rx_handler_setup(priv);
|
||||
|
||||
if (cfg(priv)->bt_params)
|
||||
iwlagn_bt_rx_handler_setup(priv);
|
||||
}
|
||||
|
||||
int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
void (*pre_rx_handler)(struct iwl_priv *,
|
||||
struct iwl_rx_cmd_buffer *);
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
@ -1153,30 +1161,22 @@ int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
|
||||
* even if the RX handler consumes the RXB we have
|
||||
* access to it in the notification wait entry.
|
||||
*/
|
||||
if (!list_empty(&priv->shrd->notif_waits)) {
|
||||
struct iwl_notification_wait *w;
|
||||
iwl_notification_wait_notify(&priv->notif_wait, pkt);
|
||||
|
||||
spin_lock(&priv->shrd->notif_wait_lock);
|
||||
list_for_each_entry(w, &priv->shrd->notif_waits, list) {
|
||||
if (w->cmd != pkt->hdr.cmd)
|
||||
continue;
|
||||
IWL_DEBUG_RX(priv,
|
||||
"Notif: %s, 0x%02x - wake the callers up\n",
|
||||
get_cmd_string(pkt->hdr.cmd),
|
||||
pkt->hdr.cmd);
|
||||
w->triggered = true;
|
||||
if (w->fn)
|
||||
w->fn(trans(priv), pkt, w->fn_data);
|
||||
}
|
||||
spin_unlock(&priv->shrd->notif_wait_lock);
|
||||
|
||||
wake_up_all(&priv->shrd->notif_waitq);
|
||||
}
|
||||
|
||||
if (priv->pre_rx_handler &&
|
||||
priv->shrd->ucode_owner == IWL_OWNERSHIP_TM)
|
||||
priv->pre_rx_handler(priv, rxb);
|
||||
else {
|
||||
/* RX data may be forwarded to userspace (using pre_rx_handler) in one
|
||||
* of two cases: the first, that the user owns the uCode through
|
||||
* testmode - in such case the pre_rx_handler is set and no further
|
||||
* processing takes place. The other case is when the user want to
|
||||
* monitor the rx w/o affecting the regular flow - the pre_rx_handler
|
||||
* will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow
|
||||
* continues.
|
||||
* We need to use ACCESS_ONCE to prevent a case where the handler
|
||||
* changes between the check and the call.
|
||||
*/
|
||||
pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler);
|
||||
if (pre_rx_handler)
|
||||
pre_rx_handler(priv, rxb);
|
||||
if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
|
||||
/* Based on type of command response or notification,
|
||||
* handle those that need handling via function in
|
||||
* rx_handlers table. See iwl_setup_rx_handlers() */
|
||||
|
@ -39,7 +39,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
|
||||
int ret;
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
CMD_SYNC, sizeof(*send), send);
|
||||
|
||||
send->filter_flags = old_filter;
|
||||
@ -60,13 +60,13 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
|
||||
u8 old_dev_type = send->dev_type;
|
||||
int ret;
|
||||
|
||||
iwl_init_notification_wait(priv->shrd, &disable_wait,
|
||||
REPLY_WIPAN_DEACTIVATION_COMPLETE,
|
||||
NULL, NULL);
|
||||
iwl_init_notification_wait(&priv->notif_wait, &disable_wait,
|
||||
REPLY_WIPAN_DEACTIVATION_COMPLETE,
|
||||
NULL, NULL);
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
send->dev_type = RXON_DEV_TYPE_P2P;
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
CMD_SYNC, sizeof(*send), send);
|
||||
|
||||
send->filter_flags = old_filter;
|
||||
@ -74,9 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
|
||||
iwl_remove_notification(priv->shrd, &disable_wait);
|
||||
iwl_remove_notification(&priv->notif_wait, &disable_wait);
|
||||
} else {
|
||||
ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ);
|
||||
ret = iwl_wait_notification(&priv->notif_wait,
|
||||
&disable_wait, HZ);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Timed out waiting for PAN disable\n");
|
||||
}
|
||||
@ -92,7 +93,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
|
||||
int ret;
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
|
||||
sizeof(*send), send);
|
||||
|
||||
send->filter_flags = old_filter;
|
||||
@ -121,7 +122,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
|
||||
ctx->qos_data.qos_active,
|
||||
ctx->qos_data.def_qos_parm.qos_flags);
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->qos_cmd, CMD_SYNC,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,
|
||||
sizeof(struct iwl_qosparam_cmd),
|
||||
&ctx->qos_data.def_qos_parm);
|
||||
if (ret)
|
||||
@ -131,7 +132,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
|
||||
static int iwlagn_update_beacon(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
|
||||
@ -180,7 +181,7 @@ static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
|
||||
ctx->staging.ofdm_ht_triple_stream_basic_rates;
|
||||
rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_assoc_cmd,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_assoc_cmd,
|
||||
CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
|
||||
return ret;
|
||||
}
|
||||
@ -266,7 +267,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
|
||||
* Associated RXON doesn't clear the station table in uCode,
|
||||
* so we don't need to restore stations etc. after this.
|
||||
*/
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_cmd, CMD_SYNC,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
@ -274,8 +275,6 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
|
||||
}
|
||||
memcpy(active, &ctx->staging, sizeof(*active));
|
||||
|
||||
iwl_reprogram_ap_sta(priv, ctx);
|
||||
|
||||
/* IBSS beacon needs to be sent after setting assoc */
|
||||
if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
|
||||
if (iwlagn_update_beacon(priv, ctx->vif))
|
||||
@ -315,7 +314,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
|
||||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx_bss = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
|
||||
@ -362,7 +361,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
slot0 = bcnint / 2;
|
||||
slot1 = bcnint - slot0;
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status) ||
|
||||
(!ctx_bss->vif->bss_conf.idle &&
|
||||
!ctx_bss->vif->bss_conf.assoc)) {
|
||||
slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
|
||||
@ -378,7 +377,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
ctx_pan->beacon_int;
|
||||
slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
|
||||
slot1 = IWL_MIN_SLOT_TIME;
|
||||
}
|
||||
@ -387,7 +386,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
cmd.slots[0].width = cpu_to_le16(slot0);
|
||||
cmd.slots[1].width = cpu_to_le16(slot1);
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_WIPAN_PARAMS, CMD_SYNC,
|
||||
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC,
|
||||
sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
|
||||
@ -420,12 +419,9 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
return -EINVAL;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EBUSY;
|
||||
|
||||
/* This function hardcodes a bunch of dual-mode assumptions */
|
||||
@ -434,10 +430,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
if (!ctx->is_active)
|
||||
return 0;
|
||||
|
||||
/* override BSSID if necessary due to preauth */
|
||||
if (ctx->preauth_bssid)
|
||||
memcpy(ctx->staging.bssid_addr, ctx->bssid, ETH_ALEN);
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
@ -445,8 +437,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
* force CTS-to-self frames protection if RTS-CTS is not preferred
|
||||
* one aggregation protection method
|
||||
*/
|
||||
if (!(cfg(priv)->ht_params &&
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation))
|
||||
if (!hw_params(priv).use_rts_for_aggregation)
|
||||
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
||||
|
||||
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
|
||||
@ -466,7 +457,7 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
* receive commit_rxon request
|
||||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status) &&
|
||||
if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
|
||||
(priv->switch_channel != ctx->staging.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_channel));
|
||||
@ -558,17 +549,14 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: changed %#x", changed);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
goto out;
|
||||
|
||||
if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
|
||||
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!iwl_is_ready(priv->shrd)) {
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
}
|
||||
@ -590,8 +578,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
unsigned long flags;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, channel->band,
|
||||
channel->hw_value);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
@ -600,8 +586,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/* Configure HT40 channels */
|
||||
if (ctx->ht.enabled != conf_is_ht(conf))
|
||||
@ -636,8 +620,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
ctx->vif);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
|
||||
iwl_update_bcast_stations(priv);
|
||||
|
||||
/*
|
||||
@ -668,7 +650,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
@ -685,7 +667,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *ht_cap;
|
||||
bool need_multiple;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
@ -789,7 +771,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
iwl_set_calib_hdr(&cmd.hdr,
|
||||
priv->phy_calib_chain_noise_reset_cmd);
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv),
|
||||
ret = iwl_dvm_send_cmd_pdu(priv,
|
||||
REPLY_PHY_CALIBRATION_CMD,
|
||||
CMD_SYNC, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
@ -810,17 +792,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
int ret;
|
||||
bool force = false;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (unlikely(!iwl_is_ready(priv->shrd))) {
|
||||
if (unlikely(!iwl_is_ready(priv))) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely(!ctx->vif)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -851,12 +833,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
* not get stuck in this case either since it
|
||||
* can happen if userspace gets confused.
|
||||
*/
|
||||
if (ctx->last_tx_rejected) {
|
||||
ctx->last_tx_rejected = false;
|
||||
iwl_trans_wake_any_queue(trans(priv),
|
||||
ctx->ctxid,
|
||||
"Disassoc: flush queue");
|
||||
}
|
||||
iwlagn_lift_passive_no_rx(priv);
|
||||
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
if (ctx->ctxid == IWL_RXON_CTX_BSS)
|
||||
@ -932,7 +910,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (!priv->disable_chain_noise_cal)
|
||||
iwlagn_chain_noise_reset(priv);
|
||||
priv->start_calib = 1;
|
||||
WARN_ON(ctx->preauth_bssid);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_IBSS) {
|
||||
@ -950,7 +927,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
IWL_ERR(priv, "Error sending IBSS beacon\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwlagn_post_scan(struct iwl_priv *priv)
|
||||
|
@ -26,7 +26,7 @@
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
@ -34,9 +34,10 @@
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
|
||||
/* priv->shrd->sta_lock must be held */
|
||||
static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
lockdep_assert_held(&priv->sta_lock);
|
||||
|
||||
if (sta_id >= IWLAGN_STATION_COUNT) {
|
||||
IWL_ERR(priv, "invalid sta_id %u", sta_id);
|
||||
return -EINVAL;
|
||||
@ -63,8 +64,8 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *addsta,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_add_sta_resp *add_sta_resp = (void *)pkt->data;
|
||||
u8 sta_id = addsta->sta.sta_id;
|
||||
unsigned long flags;
|
||||
int ret = -EIO;
|
||||
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
@ -76,9 +77,9 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
|
||||
sta_id);
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
switch (pkt->u.add_sta.status) {
|
||||
switch (add_sta_resp->status) {
|
||||
case ADD_STA_SUCCESS_MSK:
|
||||
IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
|
||||
ret = iwl_sta_ucode_activate(priv, sta_id);
|
||||
@ -97,7 +98,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
|
||||
pkt->u.add_sta.status);
|
||||
add_sta_resp->status);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -118,12 +119,12 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
priv->stations[sta_id].sta.mode ==
|
||||
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
|
||||
addsta->sta.addr);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -153,14 +154,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
might_sleep();
|
||||
}
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
|
||||
if (ret || (flags & CMD_ASYNC))
|
||||
return ret;
|
||||
/*else the command was successfully sent in SYNC mode, need to free
|
||||
* the reply page */
|
||||
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
if (cmd.handler_status)
|
||||
IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
|
||||
@ -169,34 +170,38 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
return cmd.handler_status;
|
||||
}
|
||||
|
||||
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_rxon_context *ctx)
|
||||
static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_rxon_context *ctx,
|
||||
__le32 *flags, __le32 *mask)
|
||||
{
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
|
||||
__le32 sta_flags;
|
||||
u8 mimo_ps_mode;
|
||||
|
||||
*mask = STA_FLG_RTS_MIMO_PROT_MSK |
|
||||
STA_FLG_MIMO_DIS_MSK |
|
||||
STA_FLG_HT40_EN_MSK |
|
||||
STA_FLG_MAX_AGG_SIZE_MSK |
|
||||
STA_FLG_AGG_MPDU_DENSITY_MSK;
|
||||
*flags = 0;
|
||||
|
||||
if (!sta || !sta_ht_inf->ht_supported)
|
||||
goto done;
|
||||
return;
|
||||
|
||||
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
|
||||
IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
|
||||
|
||||
IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n",
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
|
||||
"static" :
|
||||
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
|
||||
"dynamic" : "disabled");
|
||||
|
||||
sta_flags = priv->stations[index].sta.station_flags;
|
||||
|
||||
sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
|
||||
|
||||
switch (mimo_ps_mode) {
|
||||
case WLAN_HT_CAP_SM_PS_STATIC:
|
||||
sta_flags |= STA_FLG_MIMO_DIS_MSK;
|
||||
*flags |= STA_FLG_MIMO_DIS_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DYNAMIC:
|
||||
sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
|
||||
*flags |= STA_FLG_RTS_MIMO_PROT_MSK;
|
||||
break;
|
||||
case WLAN_HT_CAP_SM_PS_DISABLED:
|
||||
break;
|
||||
@ -205,20 +210,53 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
break;
|
||||
}
|
||||
|
||||
sta_flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
|
||||
*flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
|
||||
|
||||
sta_flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
|
||||
*flags |= cpu_to_le32(
|
||||
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
|
||||
|
||||
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
|
||||
sta_flags |= STA_FLG_HT40_EN_MSK;
|
||||
else
|
||||
sta_flags &= ~STA_FLG_HT40_EN_MSK;
|
||||
*flags |= STA_FLG_HT40_EN_MSK;
|
||||
}
|
||||
|
||||
priv->stations[index].sta.station_flags = sta_flags;
|
||||
done:
|
||||
return;
|
||||
int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
u8 sta_id = iwl_sta_id(sta);
|
||||
__le32 flags, mask;
|
||||
struct iwl_addsta_cmd cmd;
|
||||
|
||||
if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
|
||||
return -EINVAL;
|
||||
|
||||
iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
|
||||
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].sta.station_flags &= ~mask;
|
||||
priv->stations[sta_id].sta.station_flags |= flags;
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.mode = STA_CONTROL_MODIFY_MSK;
|
||||
cmd.station_flags_msk = mask;
|
||||
cmd.station_flags = flags;
|
||||
cmd.sta.sta_id = sta_id;
|
||||
|
||||
return iwl_send_add_sta(priv, &cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
struct ieee80211_sta *sta,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
__le32 flags, mask;
|
||||
|
||||
iwl_sta_calc_ht_flags(priv, sta, ctx, &flags, &mask);
|
||||
|
||||
lockdep_assert_held(&priv->sta_lock);
|
||||
priv->stations[index].sta.station_flags &= ~mask;
|
||||
priv->stations[index].sta.station_flags |= flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -317,18 +355,17 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap,
|
||||
struct ieee80211_sta *sta, u8 *sta_id_r)
|
||||
{
|
||||
unsigned long flags_spin;
|
||||
int ret = 0;
|
||||
u8 sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
*sta_id_r = 0;
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
|
||||
addr);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -340,7 +377,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
|
||||
IWL_DEBUG_INFO(priv, "STA %d already in process of being "
|
||||
"added.\n", sta_id);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
@ -348,24 +385,24 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
|
||||
IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
|
||||
"adding again.\n", sta_id, addr);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta,
|
||||
sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
/* Add station to device's station table */
|
||||
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
if (ret) {
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n",
|
||||
priv->stations[sta_id].sta.sta.addr);
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
*sta_id_r = sta_id;
|
||||
return ret;
|
||||
@ -373,11 +410,11 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
|
||||
/**
|
||||
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
|
||||
*
|
||||
* priv->shrd->sta_lock must be held
|
||||
*/
|
||||
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
lockdep_assert_held(&priv->sta_lock);
|
||||
|
||||
/* Ucode must be active and driver must be non active */
|
||||
if ((priv->stations[sta_id].used &
|
||||
(IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
|
||||
@ -396,8 +433,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
{
|
||||
struct iwl_rx_packet *pkt;
|
||||
int ret;
|
||||
|
||||
unsigned long flags_spin;
|
||||
struct iwl_rem_sta_cmd rm_sta_cmd;
|
||||
|
||||
struct iwl_host_cmd cmd = {
|
||||
@ -413,12 +448,12 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
pkt = cmd.resp_pkt;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
|
||||
pkt->hdr.flags);
|
||||
@ -426,14 +461,13 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
switch (pkt->u.rem_sta.status) {
|
||||
struct iwl_rem_sta_resp *rem_sta_resp = (void *)pkt->data;
|
||||
switch (rem_sta_resp->status) {
|
||||
case REM_STA_SUCCESS_MSK:
|
||||
if (!temporary) {
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock,
|
||||
flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
iwl_sta_ucode_deactivate(priv, sta_id);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock,
|
||||
flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
|
||||
break;
|
||||
@ -443,7 +477,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
break;
|
||||
}
|
||||
}
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -454,10 +488,9 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr)
|
||||
{
|
||||
unsigned long flags;
|
||||
u8 tid;
|
||||
|
||||
if (!iwl_is_ready(priv->shrd)) {
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Unable to remove station %pM, device not ready.\n",
|
||||
addr);
|
||||
@ -475,7 +508,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
if (WARN_ON(sta_id == IWL_INVALID_STATION))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
|
||||
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
|
||||
@ -505,14 +538,49 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
if (WARN_ON(priv->num_stations < 0))
|
||||
priv->num_stations = 0;
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return iwl_send_remove_station(priv, addr, sta_id, false);
|
||||
out_err:
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr)
|
||||
{
|
||||
u8 tid;
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Unable to remove station %pM, device not ready.\n",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Deactivating STA: %pM (%d)\n", addr, sta_id);
|
||||
|
||||
if (WARN_ON_ONCE(sta_id == IWL_INVALID_STATION))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
WARN_ON_ONCE(!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE));
|
||||
|
||||
for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
|
||||
memset(&priv->tid_data[sta_id][tid], 0,
|
||||
sizeof(priv->tid_data[sta_id][tid]));
|
||||
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
|
||||
priv->num_stations--;
|
||||
|
||||
if (WARN_ON_ONCE(priv->num_stations < 0))
|
||||
priv->num_stations = 0;
|
||||
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_clear_ucode_stations - clear ucode station table bits
|
||||
*
|
||||
@ -525,12 +593,11 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags_spin;
|
||||
bool cleared = false;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
|
||||
if (ctx && ctx->ctxid != priv->stations[i].ctxid)
|
||||
continue;
|
||||
@ -542,7 +609,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
|
||||
cleared = true;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
if (!cleared)
|
||||
IWL_DEBUG_INFO(priv,
|
||||
@ -561,20 +628,19 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
struct iwl_link_quality_cmd lq;
|
||||
unsigned long flags_spin;
|
||||
int i;
|
||||
bool found = false;
|
||||
int ret;
|
||||
bool send_lq;
|
||||
|
||||
if (!iwl_is_ready(priv->shrd)) {
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Not ready yet, not restoring any stations.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
|
||||
if (ctx->ctxid != priv->stations[i].ctxid)
|
||||
continue;
|
||||
@ -594,27 +660,24 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
sizeof(struct iwl_addsta_cmd));
|
||||
send_lq = false;
|
||||
if (priv->stations[i].lq) {
|
||||
if (priv->shrd->wowlan)
|
||||
if (priv->wowlan)
|
||||
iwl_sta_fill_lq(priv, ctx, i, &lq);
|
||||
else
|
||||
memcpy(&lq, priv->stations[i].lq,
|
||||
sizeof(struct iwl_link_quality_cmd));
|
||||
send_lq = true;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock,
|
||||
flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
if (ret) {
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock,
|
||||
flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
IWL_ERR(priv, "Adding station %pM failed.\n",
|
||||
priv->stations[i].sta.sta.addr);
|
||||
priv->stations[i].used &=
|
||||
~IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[i].used &=
|
||||
~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock,
|
||||
flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
/*
|
||||
* Rate scaling has already been initialized, send
|
||||
@ -623,12 +686,12 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
if (send_lq)
|
||||
iwl_send_lq_cmd(priv, ctx, &lq,
|
||||
CMD_SYNC, true);
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
if (!found)
|
||||
IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
|
||||
"no stations to be restored.\n");
|
||||
@ -637,52 +700,6 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
"complete.\n");
|
||||
}
|
||||
|
||||
void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id = ctx->ap_sta_id;
|
||||
int ret;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
struct iwl_link_quality_cmd lq;
|
||||
bool active, have_lq = false;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
|
||||
sta_cmd.mode = 0;
|
||||
if (priv->stations[sta_id].lq) {
|
||||
memcpy(&lq, priv->stations[sta_id].lq, sizeof(lq));
|
||||
have_lq = true;
|
||||
}
|
||||
|
||||
active = priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE;
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
|
||||
if (active) {
|
||||
ret = iwl_send_remove_station(
|
||||
priv, priv->stations[sta_id].sta.sta.addr,
|
||||
sta_id, true);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed to remove STA %pM (%d)\n",
|
||||
priv->stations[sta_id].sta.sta.addr, ret);
|
||||
}
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
|
||||
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed to re-add STA %pM (%d)\n",
|
||||
priv->stations[sta_id].sta.sta.addr, ret);
|
||||
if (have_lq)
|
||||
iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
|
||||
}
|
||||
|
||||
int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
@ -696,10 +713,9 @@ int iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
|
||||
|
||||
void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
|
||||
if (!(priv->stations[i].used & IWL_STA_BCAST))
|
||||
continue;
|
||||
@ -711,7 +727,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
|
||||
kfree(priv->stations[i].lq);
|
||||
priv->stations[i].lq = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
@ -783,8 +799,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long flags_spin;
|
||||
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_TX_LINK_QUALITY_CMD,
|
||||
.len = { sizeof(struct iwl_link_quality_cmd), },
|
||||
@ -796,19 +810,19 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
iwl_dump_lq_cmd(priv, lq);
|
||||
if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_lq_table_valid(priv, ctx, lq))
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
@ -819,9 +833,9 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
IWL_DEBUG_INFO(priv, "init LQ command complete, "
|
||||
"clearing sta addition status for sta %d\n",
|
||||
lq->sta_id);
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -834,7 +848,7 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
u32 rate_flags = 0;
|
||||
__le32 rate_n_flags;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
memset(link_cmd, 0, sizeof(*link_cmd));
|
||||
|
||||
@ -906,7 +920,6 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
|
||||
if (sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
@ -920,9 +933,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
|
||||
if (sta_id_r)
|
||||
*sta_id_r = sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
/* Set up default rate scaling table in device's station table */
|
||||
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
|
||||
@ -937,9 +950,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -994,7 +1007,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
||||
cmd.len[0] = cmd_size;
|
||||
|
||||
if (not_empty || send_if_empty)
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@ -1002,7 +1015,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
|
||||
int iwl_restore_default_wep_keys(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
return iwl_send_static_wepkey_cmd(priv, ctx, false);
|
||||
}
|
||||
@ -1013,13 +1026,13 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
|
||||
keyconf->keyidx);
|
||||
|
||||
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
|
||||
if (iwl_is_rfkill(priv->shrd)) {
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_WEP(priv,
|
||||
"Not sending REPLY_WEPKEY command due to RFKILL.\n");
|
||||
/* but keys in device are clear anyway so return success */
|
||||
@ -1038,7 +1051,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (keyconf->keylen != WEP_KEY_LEN_128 &&
|
||||
keyconf->keylen != WEP_KEY_LEN_64) {
|
||||
@ -1080,32 +1093,19 @@ static u8 iwlagn_key_sta_id(struct iwl_priv *priv,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
u8 sta_id = IWL_INVALID_STATION;
|
||||
|
||||
if (sta)
|
||||
sta_id = iwl_sta_id(sta);
|
||||
return iwl_sta_id(sta);
|
||||
|
||||
/*
|
||||
* The device expects GTKs for station interfaces to be
|
||||
* installed as GTKs for the AP station. If we have no
|
||||
* station ID, then use the ap_sta_id in that case.
|
||||
*/
|
||||
if (!sta && vif && vif_priv->ctx) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
sta_id = vif_priv->ctx->ap_sta_id;
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* In all other cases, the key will be
|
||||
* used either for TX only or is bound
|
||||
* to a station already.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (vif->type == NL80211_IFTYPE_STATION && vif_priv->ctx)
|
||||
return vif_priv->ctx->ap_sta_id;
|
||||
|
||||
return sta_id;
|
||||
return IWL_INVALID_STATION;
|
||||
}
|
||||
|
||||
static int iwlagn_send_sta_key(struct iwl_priv *priv,
|
||||
@ -1113,14 +1113,13 @@ static int iwlagn_send_sta_key(struct iwl_priv *priv,
|
||||
u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
|
||||
u32 cmd_flags)
|
||||
{
|
||||
unsigned long flags;
|
||||
__le16 key_flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
key_flags = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
|
||||
key_flags |= STA_KEY_FLG_MAP_KEY_MSK;
|
||||
@ -1187,7 +1186,6 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
|
||||
__le16 key_flags;
|
||||
@ -1196,16 +1194,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENOENT;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
|
||||
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
|
||||
sta_id = IWL_INVALID_STATION;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return 0;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
ctx->key_mapping_keys--;
|
||||
|
||||
@ -1245,7 +1243,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -EINVAL;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
|
||||
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET)
|
||||
@ -1300,21 +1298,20 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
|
||||
if (!link_cmd) {
|
||||
@ -1323,9 +1320,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1339,7 +1336,6 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
int iwl_update_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u8 sta_id = ctx->bcast_sta_id;
|
||||
|
||||
@ -1349,13 +1345,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
if (priv->stations[sta_id].lq)
|
||||
kfree(priv->stations[sta_id].lq);
|
||||
else
|
||||
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1379,18 +1375,17 @@ int iwl_update_bcast_stations(struct iwl_priv *priv)
|
||||
*/
|
||||
int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Remove "disable" flag, to enable Tx for this TID */
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
|
||||
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
@ -1398,24 +1393,23 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
@ -1423,11 +1417,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
struct iwl_addsta_cmd sta_cmd;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
@ -1435,13 +1428,13 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
priv->stations[sta_id].sta.station_flags_msk = 0;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
|
||||
priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
@ -1450,16 +1443,14 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask =
|
||||
STA_MODIFY_SLEEP_TX_COUNT_MSK;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
struct iwl_addsta_cmd cmd = {
|
||||
.mode = STA_CONTROL_MODIFY_MSK,
|
||||
.station_flags = STA_FLG_PWR_SAVE_MSK,
|
||||
.station_flags_msk = STA_FLG_PWR_SAVE_MSK,
|
||||
.sta.sta_id = sta_id,
|
||||
.sta.modify_mask = STA_MODIFY_SLEEP_TX_COUNT_MSK,
|
||||
.sleep_tx_count = cpu_to_le16(cnt),
|
||||
};
|
||||
|
||||
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
@ -173,7 +174,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
unsigned long flags;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (tt->state == IWL_TI_CT_KILL) {
|
||||
@ -188,7 +189,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
||||
}
|
||||
iwl_read32(trans(priv), CSR_UCODE_DRV_GP1);
|
||||
spin_lock_irqsave(&trans(priv)->reg_lock, flags);
|
||||
if (!iwl_grab_nic_access(trans(priv)))
|
||||
if (likely(iwl_grab_nic_access(trans(priv))))
|
||||
iwl_release_nic_access(trans(priv));
|
||||
spin_unlock_irqrestore(&trans(priv)->reg_lock, flags);
|
||||
|
||||
@ -224,7 +225,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
|
||||
struct iwl_priv *priv = (struct iwl_priv *)data;
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* temperature timer expired, ready to go into CT_KILL state */
|
||||
@ -232,7 +233,7 @@ static void iwl_tt_ready_for_ct_kill(unsigned long data)
|
||||
IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
|
||||
"temperature timer expired\n");
|
||||
tt->state = IWL_TI_CT_KILL;
|
||||
set_bit(STATUS_CT_KILL, &priv->shrd->status);
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
}
|
||||
}
|
||||
@ -310,24 +311,23 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
tt->tt_power_mode = IWL_POWER_INDEX_5;
|
||||
break;
|
||||
}
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
clear_bit(STATUS_CT_KILL, &priv->shrd->status);
|
||||
clear_bit(STATUS_CT_KILL, &priv->status);
|
||||
if (tt->state != IWL_TI_CT_KILL &&
|
||||
iwl_power_update_mode(priv, true)) {
|
||||
/* TT state not updated
|
||||
* try again during next temperature read
|
||||
*/
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
set_bit(STATUS_CT_KILL, &priv->shrd->status);
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
tt->state = old_state;
|
||||
IWL_ERR(priv, "Cannot update power mode, "
|
||||
"TT state not updated\n");
|
||||
} else {
|
||||
if (tt->state == IWL_TI_CT_KILL) {
|
||||
if (force) {
|
||||
set_bit(STATUS_CT_KILL,
|
||||
&priv->shrd->status);
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
} else {
|
||||
iwl_prepare_ct_kill_task(priv);
|
||||
@ -341,7 +341,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
|
||||
tt->tt_power_mode);
|
||||
}
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,9 +451,9 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
* in case get disabled before */
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
}
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
clear_bit(STATUS_CT_KILL, &priv->shrd->status);
|
||||
clear_bit(STATUS_CT_KILL, &priv->status);
|
||||
if (tt->state != IWL_TI_CT_KILL &&
|
||||
iwl_power_update_mode(priv, true)) {
|
||||
/* TT state not updated
|
||||
@ -462,7 +462,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
IWL_ERR(priv, "Cannot update power mode, "
|
||||
"TT state not updated\n");
|
||||
if (old_state == IWL_TI_CT_KILL)
|
||||
set_bit(STATUS_CT_KILL, &priv->shrd->status);
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
tt->state = old_state;
|
||||
} else {
|
||||
IWL_DEBUG_TEMP(priv,
|
||||
@ -473,8 +473,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
if (force) {
|
||||
IWL_DEBUG_TEMP(priv,
|
||||
"Enter IWL_TI_CT_KILL\n");
|
||||
set_bit(STATUS_CT_KILL,
|
||||
&priv->shrd->status);
|
||||
set_bit(STATUS_CT_KILL, &priv->status);
|
||||
iwl_perform_ct_kill_task(priv, true);
|
||||
} else {
|
||||
iwl_prepare_ct_kill_task(priv);
|
||||
@ -486,7 +485,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
|
||||
iwl_perform_ct_kill_task(priv, false);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,10 +504,10 @@ static void iwl_bg_ct_enter(struct work_struct *work)
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!iwl_is_ready(priv->shrd))
|
||||
if (!iwl_is_ready(priv))
|
||||
return;
|
||||
|
||||
if (tt->state != IWL_TI_CT_KILL) {
|
||||
@ -534,10 +533,10 @@ static void iwl_bg_ct_exit(struct work_struct *work)
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
|
||||
struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!iwl_is_ready(priv->shrd))
|
||||
if (!iwl_is_ready(priv))
|
||||
return;
|
||||
|
||||
/* stop ct_kill_exit_tm timer */
|
||||
@ -564,7 +563,7 @@ static void iwl_bg_ct_exit(struct work_struct *work)
|
||||
|
||||
void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n");
|
||||
@ -573,7 +572,7 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
|
||||
|
||||
void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n");
|
||||
@ -585,7 +584,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
|
||||
s32 temp = priv->temperature; /* degrees CELSIUS except specified */
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
@ -596,7 +595,7 @@ static void iwl_bg_tt_work(struct work_struct *work)
|
||||
|
||||
void iwl_tt_handler(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");
|
||||
|
@ -126,7 +126,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
u8 data_retry_limit;
|
||||
u8 rate_plcp;
|
||||
|
||||
if (priv->shrd->wowlan) {
|
||||
if (priv->wowlan) {
|
||||
rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
|
||||
data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
|
||||
} else {
|
||||
@ -208,10 +208,9 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
|
||||
struct ieee80211_tx_info *info,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct sk_buff *skb_frag,
|
||||
int sta_id)
|
||||
struct ieee80211_tx_info *info,
|
||||
struct iwl_tx_cmd *tx_cmd,
|
||||
struct sk_buff *skb_frag)
|
||||
{
|
||||
struct ieee80211_key_conf *keyconf = info->control.hw_key;
|
||||
|
||||
@ -249,6 +248,35 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_sta_id_or_broadcast - return sta_id or broadcast sta
|
||||
* @context: the current context
|
||||
* @sta: mac80211 station
|
||||
*
|
||||
* In certain circumstances mac80211 passes a station pointer
|
||||
* that may be %NULL, for example during TX or key setup. In
|
||||
* that case, we need to use the broadcast station, so this
|
||||
* inline wraps that pattern.
|
||||
*/
|
||||
static int iwl_sta_id_or_broadcast(struct iwl_rxon_context *context,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int sta_id;
|
||||
|
||||
if (!sta)
|
||||
return context->bcast_sta_id;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
/*
|
||||
* mac80211 should not be passing a partially
|
||||
* initialised station!
|
||||
*/
|
||||
WARN_ON(sta_id == IWL_INVALID_STATION);
|
||||
|
||||
return sta_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* start REPLY_TX command process
|
||||
*/
|
||||
@ -260,19 +288,16 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl_device_cmd *dev_cmd = NULL;
|
||||
struct iwl_tx_cmd *tx_cmd;
|
||||
|
||||
__le16 fc;
|
||||
u8 hdr_len;
|
||||
u16 len, seq_number = 0;
|
||||
u8 sta_id, tid = IWL_MAX_TID_COUNT;
|
||||
unsigned long flags;
|
||||
bool is_agg = false;
|
||||
|
||||
if (info->control.vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(info->control.vif);
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
if (iwl_is_rfkill(priv->shrd)) {
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
|
||||
goto drop_unlock_priv;
|
||||
}
|
||||
@ -308,7 +333,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
sta_id = ctx->bcast_sta_id;
|
||||
else {
|
||||
/* Find index into station table for destination station */
|
||||
sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
|
||||
sta_id = iwl_sta_id_or_broadcast(ctx, info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
@ -342,13 +367,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
is_agg = true;
|
||||
|
||||
/* irqs already disabled/saved above when locking priv->shrd->lock */
|
||||
spin_lock(&priv->shrd->sta_lock);
|
||||
|
||||
dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
|
||||
dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC);
|
||||
|
||||
if (unlikely(!dev_cmd))
|
||||
goto drop_unlock_sta;
|
||||
goto drop_unlock_priv;
|
||||
|
||||
memset(dev_cmd, 0, sizeof(*dev_cmd));
|
||||
tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
|
||||
@ -358,7 +380,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
tx_cmd->len = cpu_to_le16(len);
|
||||
|
||||
if (info->control.hw_key)
|
||||
iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
|
||||
iwlagn_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb);
|
||||
|
||||
/* TODO need this for burst mode later on */
|
||||
iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
|
||||
@ -373,6 +395,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
info->driver_data[0] = ctx;
|
||||
info->driver_data[1] = dev_cmd;
|
||||
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
|
||||
u8 *qc = NULL;
|
||||
struct iwl_tid_data *tid_data;
|
||||
@ -418,8 +442,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
!ieee80211_has_morefrags(fc))
|
||||
priv->tid_data[sta_id][tid].seq_number = seq_number;
|
||||
|
||||
spin_unlock(&priv->shrd->sta_lock);
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
/*
|
||||
* Avoid atomic ops if it isn't an associated client.
|
||||
@ -435,10 +458,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
|
||||
drop_unlock_sta:
|
||||
if (dev_cmd)
|
||||
kmem_cache_free(priv->tx_cmd_pool, dev_cmd);
|
||||
spin_unlock(&priv->shrd->sta_lock);
|
||||
kmem_cache_free(iwl_tx_cmd_pool, dev_cmd);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
drop_unlock_priv:
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -446,7 +468,6 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct iwl_tid_data *tid_data;
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
@ -456,7 +477,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
tid_data = &priv->tid_data[sta_id][tid];
|
||||
|
||||
@ -476,7 +497,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
IWL_WARN(priv, "Stopping AGG while state not ON "
|
||||
"or starting for %d on %d (%d)\n", sta_id, tid,
|
||||
priv->tid_data[sta_id][tid].agg.state);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -490,7 +511,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
tid_data->next_reclaimed);
|
||||
priv->tid_data[sta_id][tid].agg.state =
|
||||
IWL_EMPTYING_HW_QUEUE_DELBA;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -499,14 +520,10 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
turn_off:
|
||||
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
|
||||
|
||||
/* do not restore/save irqs */
|
||||
spin_unlock(&priv->shrd->sta_lock);
|
||||
spin_lock(&priv->shrd->lock);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
iwl_trans_tx_agg_disable(trans(priv), sta_id, tid);
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
|
||||
return 0;
|
||||
@ -516,7 +533,6 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
{
|
||||
struct iwl_tid_data *tid_data;
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
int ret;
|
||||
|
||||
@ -540,7 +556,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
tid_data = &priv->tid_data[sta_id][tid];
|
||||
tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||
@ -549,7 +565,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
|
||||
ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
|
||||
if (ret) {
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -566,7 +582,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -576,14 +592,13 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
{
|
||||
struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
unsigned long flags;
|
||||
u16 ssn;
|
||||
|
||||
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF);
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
|
||||
buf_size, ssn);
|
||||
@ -608,8 +623,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
sta_priv->max_agg_bufsize =
|
||||
min(sta_priv->max_agg_bufsize, buf_size);
|
||||
|
||||
if (cfg(priv)->ht_params &&
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation) {
|
||||
if (hw_params(priv).use_rts_for_aggregation) {
|
||||
/*
|
||||
* switch to RTS/CTS if it is the prefer protection
|
||||
* method for HT traffic
|
||||
@ -639,7 +653,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
|
||||
struct ieee80211_vif *vif;
|
||||
u8 *addr;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->sta_lock);
|
||||
lockdep_assert_held(&priv->sta_lock);
|
||||
|
||||
addr = priv->stations[sta_id].sta.sta.addr;
|
||||
ctx = priv->stations[sta_id].ctxid;
|
||||
@ -986,19 +1000,19 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
|
||||
{
|
||||
if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
|
||||
IWL_ERR(priv, "Tx flush command to flush out all frames\n");
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
queue_work(priv->workqueue, &priv->tx_flush);
|
||||
}
|
||||
}
|
||||
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int cmd_index __maybe_unused = SEQ_TO_INDEX(sequence);
|
||||
struct iwlagn_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
|
||||
struct iwlagn_tx_resp *tx_resp = (void *)pkt->data;
|
||||
struct ieee80211_hdr *hdr;
|
||||
u32 status = le16_to_cpu(tx_resp->status.status);
|
||||
u16 ssn = iwlagn_get_scd_ssn(tx_resp);
|
||||
@ -1006,7 +1020,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int sta_id;
|
||||
int freed;
|
||||
struct ieee80211_tx_info *info;
|
||||
unsigned long flags;
|
||||
struct sk_buff_head skbs;
|
||||
struct sk_buff *skb;
|
||||
struct iwl_rxon_context *ctx;
|
||||
@ -1017,11 +1030,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
|
||||
IWLAGN_TX_RES_RA_POS;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
if (is_agg)
|
||||
iwl_rx_reply_tx_agg(priv, tx_resp);
|
||||
|
||||
__skb_queue_head_init(&skbs);
|
||||
|
||||
if (tx_resp->frame_count == 1) {
|
||||
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
|
||||
next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10);
|
||||
@ -1041,8 +1056,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
next_reclaimed = ssn;
|
||||
}
|
||||
|
||||
__skb_queue_head_init(&skbs);
|
||||
|
||||
if (tid != IWL_TID_NON_QOS) {
|
||||
priv->tid_data[sta_id][tid].next_reclaimed =
|
||||
next_reclaimed;
|
||||
@ -1051,12 +1064,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
}
|
||||
|
||||
/*we can free until ssn % q.n_bd not inclusive */
|
||||
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id,
|
||||
ssn, status, &skbs));
|
||||
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid,
|
||||
txq_id, ssn, &skbs));
|
||||
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||
freed = 0;
|
||||
while (!skb_queue_empty(&skbs)) {
|
||||
skb = __skb_dequeue(&skbs);
|
||||
|
||||
/* process frames */
|
||||
skb_queue_walk(&skbs, skb) {
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control))
|
||||
@ -1064,7 +1078,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
ctx = info->driver_data[0];
|
||||
kmem_cache_free(priv->tx_cmd_pool,
|
||||
kmem_cache_free(iwl_tx_cmd_pool,
|
||||
(info->driver_data[1]));
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
@ -1072,9 +1086,11 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
|
||||
iwl_is_associated_ctx(ctx) && ctx->vif &&
|
||||
ctx->vif->type == NL80211_IFTYPE_STATION) {
|
||||
ctx->last_tx_rejected = true;
|
||||
iwl_trans_stop_queue(trans(priv), txq_id,
|
||||
"Tx on passive channel");
|
||||
/* block and stop all queues */
|
||||
priv->passive_no_rx = true;
|
||||
IWL_DEBUG_TX_QUEUES(priv, "stop all queues: "
|
||||
"passive channel");
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv,
|
||||
"TXQ %d status %s (0x%08x) "
|
||||
@ -1098,8 +1114,6 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
if (!is_agg)
|
||||
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
||||
|
||||
freed++;
|
||||
}
|
||||
|
||||
@ -1107,7 +1121,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
}
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
while (!skb_queue_empty(&skbs)) {
|
||||
skb = __skb_dequeue(&skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1118,17 +1138,16 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
* of frames sent via aggregation.
|
||||
*/
|
||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
|
||||
struct iwl_compressed_ba_resp *ba_resp = (void *)pkt->data;
|
||||
struct iwl_ht_agg *agg;
|
||||
struct sk_buff_head reclaimed_skbs;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
int tid;
|
||||
int freed;
|
||||
@ -1140,7 +1159,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
* (in Tx queue's circular buffer) of first TFD/frame in window */
|
||||
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
|
||||
|
||||
if (scd_flow >= hw_params(priv).max_txq_num) {
|
||||
if (scd_flow >= cfg(priv)->base_params->num_of_queues) {
|
||||
IWL_ERR(priv,
|
||||
"BUG_ON scd_flow is bigger than number of queues\n");
|
||||
return 0;
|
||||
@ -1150,12 +1169,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
tid = ba_resp->tid;
|
||||
agg = &priv->tid_data[sta_id][tid].agg;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
spin_lock(&priv->sta_lock);
|
||||
|
||||
if (unlikely(!agg->wait_for_ba)) {
|
||||
if (unlikely(ba_resp->bitmap))
|
||||
IWL_ERR(priv, "Received BA when not expected\n");
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1165,8 +1184,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
* block-ack window (we assume that they've been successfully
|
||||
* transmitted ... if not, it's too late anyway). */
|
||||
if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
|
||||
ba_resp_scd_ssn, 0, &reclaimed_skbs)) {
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
ba_resp_scd_ssn, &reclaimed_skbs)) {
|
||||
spin_unlock(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1202,9 +1221,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
|
||||
iwlagn_check_ratid_empty(priv, sta_id, tid);
|
||||
freed = 0;
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
|
||||
skb = __skb_dequeue(&reclaimed_skbs);
|
||||
skb_queue_walk(&reclaimed_skbs, skb) {
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||
@ -1213,7 +1231,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
|
||||
kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
|
||||
|
||||
if (freed == 1) {
|
||||
/* this is the first skb we deliver in this batch */
|
||||
@ -1227,10 +1245,14 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags,
|
||||
info);
|
||||
}
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
while (!skb_queue_empty(&reclaimed_skbs)) {
|
||||
skb = __skb_dequeue(&reclaimed_skbs);
|
||||
ieee80211_tx_status(priv->hw, skb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,9 +41,7 @@
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-ucode.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
@ -134,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
||||
* beacon contents.
|
||||
*/
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
|
||||
@ -199,7 +197,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
||||
cmd.data[1] = priv->beacon_skb->data;
|
||||
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY;
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
static void iwl_bg_beacon_update(struct work_struct *work)
|
||||
@ -208,7 +206,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
|
||||
container_of(work, struct iwl_priv, beacon_update);
|
||||
struct sk_buff *beacon;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "updating beacon w/o beacon context!\n");
|
||||
goto out;
|
||||
@ -238,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
|
||||
|
||||
iwlagn_send_beacon_cmd(priv);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_bt_runtime_config(struct work_struct *work)
|
||||
@ -246,11 +244,11 @@ static void iwl_bg_bt_runtime_config(struct work_struct *work)
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, bt_runtime_config);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* dont send host command if rf-kill is on */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return;
|
||||
iwlagn_send_advance_bt_config(priv);
|
||||
}
|
||||
@ -261,13 +259,13 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
|
||||
container_of(work, struct iwl_priv, bt_full_concurrency);
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
goto out;
|
||||
|
||||
/* dont send host command if rf-kill is on */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
goto out;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "BT coex in %s mode\n",
|
||||
@ -285,7 +283,7 @@ static void iwl_bg_bt_full_concurrency(struct work_struct *work)
|
||||
|
||||
iwlagn_send_advance_bt_config(priv);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -302,11 +300,11 @@ static void iwl_bg_statistics_periodic(unsigned long data)
|
||||
{
|
||||
struct iwl_priv *priv = (struct iwl_priv *)data;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* dont send host command if rf-kill is on */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return;
|
||||
|
||||
iwl_send_statistics_request(priv, CMD_ASYNC, false);
|
||||
@ -329,14 +327,13 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags);
|
||||
if (iwl_grab_nic_access(trans(priv))) {
|
||||
if (unlikely(!iwl_grab_nic_access(trans(priv)))) {
|
||||
spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
|
||||
rmb();
|
||||
|
||||
/*
|
||||
* Refuse to read more than would have fit into the log from
|
||||
@ -355,11 +352,12 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
|
||||
time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
|
||||
if (mode == 0) {
|
||||
trace_iwlwifi_dev_ucode_cont_event(priv, 0, time, ev);
|
||||
trace_iwlwifi_dev_ucode_cont_event(
|
||||
trans(priv)->dev, 0, time, ev);
|
||||
} else {
|
||||
data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
|
||||
trace_iwlwifi_dev_ucode_cont_event(priv, time,
|
||||
data, ev);
|
||||
trace_iwlwifi_dev_ucode_cont_event(
|
||||
trans(priv)->dev, time, data, ev);
|
||||
}
|
||||
}
|
||||
/* Allow device to power down */
|
||||
@ -424,7 +422,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
||||
else
|
||||
priv->event_log.wraps_once_count++;
|
||||
|
||||
trace_iwlwifi_dev_ucode_wrap_event(priv,
|
||||
trace_iwlwifi_dev_ucode_wrap_event(trans(priv)->dev,
|
||||
num_wraps - priv->event_log.num_wraps,
|
||||
next_entry, priv->event_log.next_entry);
|
||||
|
||||
@ -463,7 +461,7 @@ static void iwl_bg_ucode_trace(unsigned long data)
|
||||
{
|
||||
struct iwl_priv *priv = (struct iwl_priv *)data;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (priv->event_log.ucode_trace) {
|
||||
@ -479,18 +477,18 @@ static void iwl_bg_tx_flush(struct work_struct *work)
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, tx_flush);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* do nothing if rf-kill is on */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
|
||||
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
|
||||
}
|
||||
|
||||
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
||||
static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -552,13 +550,11 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_ct_kill_config cmd;
|
||||
struct iwl_ct_kill_throttling_config adv_cmd;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
|
||||
priv->thermal_throttle.ct_kill_toggle = false;
|
||||
|
||||
if (cfg(priv)->base_params->support_ct_kill_exit) {
|
||||
@ -567,7 +563,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
adv_cmd.critical_temperature_exit =
|
||||
cpu_to_le32(hw_params(priv).ct_kill_exit_threshold);
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv),
|
||||
ret = iwl_dvm_send_cmd_pdu(priv,
|
||||
REPLY_CT_KILL_CONFIG_CMD,
|
||||
CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
|
||||
if (ret)
|
||||
@ -582,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
||||
cmd.critical_temperature_R =
|
||||
cpu_to_le32(hw_params(priv).ct_kill_threshold);
|
||||
|
||||
ret = iwl_trans_send_cmd_pdu(trans(priv),
|
||||
ret = iwl_dvm_send_cmd_pdu(priv,
|
||||
REPLY_CT_KILL_CONFIG_CMD,
|
||||
CMD_SYNC, sizeof(cmd), &cmd);
|
||||
if (ret)
|
||||
@ -608,7 +604,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg)
|
||||
calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_RT_CFG_ALL;
|
||||
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg);
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
|
||||
@ -618,9 +614,9 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
|
||||
.valid = cpu_to_le32(valid_tx_ant),
|
||||
};
|
||||
|
||||
if (IWL_UCODE_API(nic(priv)->fw.ucode_ver) > 1) {
|
||||
if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
|
||||
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
|
||||
return iwl_trans_send_cmd_pdu(trans(priv),
|
||||
return iwl_dvm_send_cmd_pdu(priv,
|
||||
TX_ANT_CONFIGURATION_CMD,
|
||||
CMD_SYNC,
|
||||
sizeof(struct iwl_tx_ant_config_cmd),
|
||||
@ -644,12 +640,12 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
|
||||
|
||||
/* After the ALIVE response, we can send host commands to the uCode */
|
||||
set_bit(STATUS_ALIVE, &priv->shrd->status);
|
||||
set_bit(STATUS_ALIVE, &priv->status);
|
||||
|
||||
/* Enable watchdog to monitor the driver tx queues */
|
||||
iwl_setup_watchdog(priv);
|
||||
|
||||
if (iwl_is_rfkill(priv->shrd))
|
||||
if (iwl_is_rfkill(priv))
|
||||
return -ERFKILL;
|
||||
|
||||
if (priv->event_log.ucode_trace) {
|
||||
@ -673,14 +669,14 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
|
||||
priv->cur_rssi_ctx = NULL;
|
||||
|
||||
iwl_send_prio_tbl(trans(priv));
|
||||
iwl_send_prio_tbl(priv);
|
||||
|
||||
/* FIXME: w/a to force change uCode BT state machine */
|
||||
ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_OPEN,
|
||||
ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = iwl_send_bt_env(trans(priv), IWL_BT_COEX_ENV_CLOSE,
|
||||
ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE,
|
||||
BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -701,9 +697,9 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
priv->active_rate = IWL_RATES_MASK;
|
||||
|
||||
/* Configure Tx antenna selection based on H/W config */
|
||||
iwlagn_send_tx_ant_config(priv, cfg(priv)->valid_tx_ant);
|
||||
iwlagn_send_tx_ant_config(priv, hw_params(priv).valid_tx_ant);
|
||||
|
||||
if (iwl_is_associated_ctx(ctx) && !priv->shrd->wowlan) {
|
||||
if (iwl_is_associated_ctx(ctx) && !priv->wowlan) {
|
||||
struct iwl_rxon_cmd *active_rxon =
|
||||
(struct iwl_rxon_cmd *)&ctx->active;
|
||||
/* apply any changes in staging */
|
||||
@ -718,12 +714,12 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
iwlagn_set_rxon_chain(priv, ctx);
|
||||
}
|
||||
|
||||
if (!priv->shrd->wowlan) {
|
||||
if (!priv->wowlan) {
|
||||
/* WoWLAN ucode will not reply in the same way, skip it */
|
||||
iwl_reset_run_time_calib(priv);
|
||||
}
|
||||
|
||||
set_bit(STATUS_READY, &priv->shrd->status);
|
||||
set_bit(STATUS_READY, &priv->status);
|
||||
|
||||
/* Configure the adapter for unassociated operation */
|
||||
ret = iwlagn_commit_rxon(priv, ctx);
|
||||
@ -738,13 +734,47 @@ int iwl_alive_start(struct iwl_priv *priv)
|
||||
return iwl_power_update_mode(priv, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_clear_driver_stations - clear knowledge of all stations from driver
|
||||
* @priv: iwl priv struct
|
||||
*
|
||||
* This is called during iwl_down() to make sure that in the case
|
||||
* we're coming there from a hardware restart mac80211 will be
|
||||
* able to reconfigure stations -- if we're getting there in the
|
||||
* normal down flow then the stations will already be cleared.
|
||||
*/
|
||||
static void iwl_clear_driver_stations(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
priv->num_stations = 0;
|
||||
|
||||
priv->ucode_key_table = 0;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/*
|
||||
* Remove all key information that is not stored as part
|
||||
* of station information since mac80211 may not have had
|
||||
* a chance to remove all the keys. When device is
|
||||
* reconfigured by mac80211 after an error all keys will
|
||||
* be reconfigured.
|
||||
*/
|
||||
memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
|
||||
ctx->key_mapping_keys = 0;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
}
|
||||
|
||||
void iwl_down(struct iwl_priv *priv)
|
||||
{
|
||||
int exit_pending;
|
||||
|
||||
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
@ -756,7 +786,7 @@ void iwl_down(struct iwl_priv *priv)
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
|
||||
exit_pending =
|
||||
test_and_set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
|
||||
* to prevent rearm timer */
|
||||
@ -781,7 +811,7 @@ void iwl_down(struct iwl_priv *priv)
|
||||
/* Wipe out the EXIT_PENDING status bit if we are not actually
|
||||
* exiting the module */
|
||||
if (!exit_pending)
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
@ -789,15 +819,15 @@ void iwl_down(struct iwl_priv *priv)
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
/* Clear out all status bits but a few that are stable across reset */
|
||||
priv->shrd->status &=
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
|
||||
priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
|
||||
STATUS_RF_KILL_HW |
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) <<
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
|
||||
STATUS_GEO_CONFIGURED |
|
||||
test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
|
||||
STATUS_FW_ERROR |
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
STATUS_EXIT_PENDING;
|
||||
priv->shrd->status &=
|
||||
test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
|
||||
STATUS_FW_ERROR;
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = NULL;
|
||||
@ -814,11 +844,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
run_time_calib_work);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
|
||||
test_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||
test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -827,7 +857,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
|
||||
iwl_sensitivity_calibration(priv);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwlagn_prepare_restart(struct iwl_priv *priv)
|
||||
@ -839,7 +869,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
|
||||
u8 bt_status;
|
||||
bool bt_is_sco;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
for_each_context(priv, ctx)
|
||||
ctx->vif = NULL;
|
||||
@ -873,13 +903,13 @@ static void iwl_bg_restart(struct work_struct *data)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwlagn_prepare_restart(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
iwl_cancel_deferred_work(priv);
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
} else {
|
||||
@ -894,7 +924,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->hw_roc_setup)
|
||||
return;
|
||||
@ -917,9 +947,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
hw_roc_disable_work.work);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwlagn_disable_roc(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -945,8 +975,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
|
||||
iwl_setup_scan_deferred_work(priv);
|
||||
|
||||
if (cfg(priv)->lib->bt_setup_deferred_work)
|
||||
cfg(priv)->lib->bt_setup_deferred_work(priv);
|
||||
if (cfg(priv)->bt_params)
|
||||
iwlagn_bt_setup_deferred_work(priv);
|
||||
|
||||
init_timer(&priv->statistics_periodic);
|
||||
priv->statistics_periodic.data = (unsigned long)priv;
|
||||
@ -963,8 +993,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
|
||||
|
||||
void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
{
|
||||
if (cfg(priv)->lib->cancel_deferred_work)
|
||||
cfg(priv)->lib->cancel_deferred_work(priv);
|
||||
if (cfg(priv)->bt_params)
|
||||
iwlagn_bt_cancel_deferred_work(priv);
|
||||
|
||||
cancel_work_sync(&priv->run_time_calib_work);
|
||||
cancel_work_sync(&priv->beacon_update);
|
||||
@ -979,8 +1009,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
|
||||
del_timer_sync(&priv->ucode_trace);
|
||||
}
|
||||
|
||||
static void iwl_init_hw_rates(struct iwl_priv *priv,
|
||||
struct ieee80211_rate *rates)
|
||||
static void iwl_init_hw_rates(struct ieee80211_rate *rates)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1004,21 +1033,26 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spin_lock_init(&priv->shrd->sta_lock);
|
||||
spin_lock_init(&priv->sta_lock);
|
||||
|
||||
mutex_init(&priv->shrd->mutex);
|
||||
mutex_init(&priv->mutex);
|
||||
|
||||
INIT_LIST_HEAD(&trans(priv)->calib_results);
|
||||
INIT_LIST_HEAD(&priv->calib_results);
|
||||
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
||||
priv->plcp_delta_threshold =
|
||||
cfg(priv)->base_params->plcp_delta_threshold;
|
||||
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
|
||||
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
|
||||
priv->agg_tids_count = 0;
|
||||
|
||||
priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
|
||||
|
||||
/* initialize force reset */
|
||||
priv->force_reset[IWL_RF_RESET].reset_duration =
|
||||
IWL_DELAY_NEXT_FORCE_RF_RESET;
|
||||
@ -1054,7 +1088,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
|
||||
goto err_free_channel_map;
|
||||
}
|
||||
iwl_init_hw_rates(priv, priv->ieee_rates);
|
||||
iwl_init_hw_rates(priv->ieee_rates);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -1068,11 +1102,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_free_geos(priv);
|
||||
iwl_free_channel_map(priv);
|
||||
if (priv->tx_cmd_pool)
|
||||
kmem_cache_destroy(priv->tx_cmd_pool);
|
||||
kfree(priv->scan_cmd);
|
||||
kfree(priv->beacon_cmd);
|
||||
kfree(rcu_dereference_raw(priv->noa_data));
|
||||
iwl_calib_free_results(priv);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
kfree(priv->wowlan_sram);
|
||||
#endif
|
||||
@ -1084,6 +1117,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
|
||||
static void iwl_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (cfg(priv)->ht_params)
|
||||
hw_params(priv).use_rts_for_aggregation =
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation;
|
||||
|
||||
if (iwlagn_mod_params.amsdu_size_8K)
|
||||
hw_params(priv).rx_page_order =
|
||||
get_order(IWL_RX_BUF_SIZE_8K);
|
||||
@ -1092,13 +1129,10 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
|
||||
get_order(IWL_RX_BUF_SIZE_4K);
|
||||
|
||||
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL)
|
||||
cfg(priv)->sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
||||
hw_params(priv).sku &= ~EEPROM_SKU_CAP_11N_ENABLE;
|
||||
|
||||
hw_params(priv).num_ampdu_queues =
|
||||
cfg(priv)->base_params->num_of_ampdu_queues;
|
||||
hw_params(priv).shadow_reg_enable =
|
||||
cfg(priv)->base_params->shadow_reg_enable;
|
||||
hw_params(priv).sku = cfg(priv)->sku;
|
||||
hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
|
||||
|
||||
/* Device-specific setup */
|
||||
@ -1142,15 +1176,16 @@ static void iwl_debug_config(struct iwl_priv *priv)
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw)
|
||||
{
|
||||
struct iwl_fw *fw = &nic(trans)->fw;
|
||||
int err = 0;
|
||||
struct iwl_priv *priv;
|
||||
struct ieee80211_hw *hw;
|
||||
struct iwl_op_mode *op_mode;
|
||||
u16 num_mac;
|
||||
u32 ucode_flags;
|
||||
struct iwl_trans_config trans_cfg;
|
||||
|
||||
/************************
|
||||
* 1. Allocating HW data
|
||||
@ -1167,9 +1202,32 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
op_mode->ops = &iwl_dvm_ops;
|
||||
priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
priv->shrd = trans->shrd;
|
||||
priv->shrd->priv = priv;
|
||||
priv->fw = fw;
|
||||
/* TODO: remove fw from shared data later */
|
||||
priv->shrd->fw = fw;
|
||||
|
||||
iwl_trans_configure(trans(priv), op_mode);
|
||||
/*
|
||||
* Populate the state variables that the transport layer needs
|
||||
* to know about.
|
||||
*/
|
||||
trans_cfg.op_mode = op_mode;
|
||||
|
||||
ucode_flags = fw->ucode_capa.flags;
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_P2P
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
#endif
|
||||
|
||||
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
|
||||
trans_cfg.cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
} else {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
}
|
||||
|
||||
/* Configure transport layer */
|
||||
iwl_trans_configure(trans(priv), &trans_cfg);
|
||||
|
||||
/* At this point both hw and priv are allocated. */
|
||||
|
||||
@ -1198,10 +1256,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
* we should init now
|
||||
*/
|
||||
spin_lock_init(&trans(priv)->reg_lock);
|
||||
spin_lock_init(&priv->shrd->lock);
|
||||
spin_lock_init(&priv->statistics.lock);
|
||||
|
||||
/***********************
|
||||
* 3. Read REV register
|
||||
* 2. Read REV register
|
||||
***********************/
|
||||
IWL_INFO(priv, "Detected %s, REV=0x%X\n",
|
||||
cfg(priv)->name, trans(priv)->hw_rev);
|
||||
@ -1211,9 +1269,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
goto out_free_traffic_mem;
|
||||
|
||||
/*****************
|
||||
* 4. Read EEPROM
|
||||
* 3. Read EEPROM
|
||||
*****************/
|
||||
/* Read the EEPROM */
|
||||
err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
|
||||
/* Reset chip to save power until we load uCode during "up". */
|
||||
iwl_trans_stop_hw(trans(priv));
|
||||
@ -1225,7 +1282,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
err = iwl_eeprom_check_sku(priv);
|
||||
err = iwl_eeprom_init_hw_params(priv);
|
||||
if (err)
|
||||
goto out_free_eeprom;
|
||||
|
||||
@ -1243,28 +1300,27 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
/************************
|
||||
* 5. Setup HW constants
|
||||
* 4. Setup HW constants
|
||||
************************/
|
||||
iwl_set_hw_params(priv);
|
||||
|
||||
ucode_flags = fw->ucode_capa.flags;
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_P2P
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
#endif
|
||||
if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
|
||||
if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
|
||||
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
|
||||
|
||||
/*
|
||||
* if not PAN, then don't support P2P -- might be a uCode
|
||||
* packaging bug or due to the eeprom check above
|
||||
*/
|
||||
if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
|
||||
/*
|
||||
* if not PAN, then don't support P2P -- might be a uCode
|
||||
* packaging bug or due to the eeprom check above
|
||||
*/
|
||||
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
trans_cfg.cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
|
||||
/* Configure transport layer again*/
|
||||
iwl_trans_configure(trans(priv), &trans_cfg);
|
||||
}
|
||||
|
||||
/*******************
|
||||
* 6. Setup priv
|
||||
* 5. Setup priv
|
||||
*******************/
|
||||
|
||||
err = iwl_init_drv(priv);
|
||||
@ -1273,7 +1329,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
/* At this point both hw and priv are initialized. */
|
||||
|
||||
/********************
|
||||
* 7. Setup services
|
||||
* 6. Setup services
|
||||
********************/
|
||||
iwl_setup_deferred_work(priv);
|
||||
iwl_setup_rx_handlers(priv);
|
||||
@ -1289,14 +1345,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
priv->new_scan_threshold_behaviour =
|
||||
!!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
|
||||
|
||||
if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN) {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
|
||||
priv->shrd->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
|
||||
} else {
|
||||
priv->sta_key_max_num = STA_KEY_MAX_NUM;
|
||||
priv->shrd->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
|
||||
}
|
||||
|
||||
priv->phy_calib_chain_noise_reset_cmd =
|
||||
fw->ucode_capa.standard_phy_calibration_size;
|
||||
priv->phy_calib_chain_noise_gain_cmd =
|
||||
@ -1308,7 +1356,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
|
||||
/**************************************************
|
||||
* This is still part of probe() in a sense...
|
||||
*
|
||||
* 9. Setup and register with mac80211 and debugfs
|
||||
* 7. Setup and register with mac80211 and debugfs
|
||||
**************************************************/
|
||||
err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
|
||||
if (err)
|
||||
@ -1340,18 +1388,10 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
wait_for_completion(&nic(priv)->request_firmware_complete);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
|
||||
/* ieee80211_unregister_hw call wil cause iwlagn_mac_stop to
|
||||
* to be called and iwl_down since we are removing the device
|
||||
* we need to set STATUS_EXIT_PENDING bit.
|
||||
*/
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
|
||||
iwl_testmode_cleanup(priv);
|
||||
iwlagn_mac_unregister(priv);
|
||||
|
||||
@ -1360,8 +1400,6 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
/*This will stop the queues, move the device to low power state */
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
iwl_dealloc_ucode(nic(priv));
|
||||
|
||||
iwl_eeprom_free(priv->shrd);
|
||||
|
||||
/*netif_stop_queue(dev); */
|
||||
@ -1381,6 +1419,60 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
|
||||
ieee80211_free_hw(priv->hw);
|
||||
}
|
||||
|
||||
static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
if (!iwl_check_for_ct_kill(priv)) {
|
||||
IWL_ERR(priv, "Restarting adapter queue is full\n");
|
||||
iwl_nic_error(op_mode);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_nic_config(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
cfg(priv)->lib->nic_config(priv);
|
||||
}
|
||||
|
||||
static void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
set_bit(ac, &priv->transport_queue_stop);
|
||||
ieee80211_stop_queue(priv->hw, ac);
|
||||
}
|
||||
|
||||
static void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
clear_bit(ac, &priv->transport_queue_stop);
|
||||
|
||||
if (!priv->passive_no_rx)
|
||||
ieee80211_wake_queue(priv->hw, ac);
|
||||
}
|
||||
|
||||
void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
|
||||
{
|
||||
int ac;
|
||||
|
||||
if (!priv->passive_no_rx)
|
||||
return;
|
||||
|
||||
for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++) {
|
||||
if (!test_bit(ac, &priv->transport_queue_stop)) {
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d");
|
||||
ieee80211_wake_queue(priv->hw, ac);
|
||||
} else {
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d");
|
||||
}
|
||||
}
|
||||
|
||||
priv->passive_no_rx = false;
|
||||
}
|
||||
|
||||
const struct iwl_op_mode_ops iwl_dvm_ops = {
|
||||
.start = iwl_op_mode_dvm_start,
|
||||
.stop = iwl_op_mode_dvm_stop,
|
||||
@ -1390,6 +1482,8 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
|
||||
.hw_rf_kill = iwl_set_hw_rfkill_state,
|
||||
.free_skb = iwl_free_skb,
|
||||
.nic_error = iwl_nic_error,
|
||||
.cmd_queue_full = iwl_cmd_queue_full,
|
||||
.nic_config = iwl_nic_config,
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
@ -1397,6 +1491,9 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
|
||||
* driver and module entry point
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
struct kmem_cache *iwl_tx_cmd_pool;
|
||||
|
||||
static int __init iwl_init(void)
|
||||
{
|
||||
|
||||
@ -1404,20 +1501,27 @@ static int __init iwl_init(void)
|
||||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
pr_info(DRV_COPYRIGHT "\n");
|
||||
|
||||
iwl_tx_cmd_pool = kmem_cache_create("iwl_dev_cmd",
|
||||
sizeof(struct iwl_device_cmd),
|
||||
sizeof(void *), 0, NULL);
|
||||
if (!iwl_tx_cmd_pool)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = iwlagn_rate_control_register();
|
||||
if (ret) {
|
||||
pr_err("Unable to register rate control algorithm: %d\n", ret);
|
||||
return ret;
|
||||
goto error_rc_register;
|
||||
}
|
||||
|
||||
ret = iwl_pci_register_driver();
|
||||
|
||||
if (ret)
|
||||
goto error_register;
|
||||
goto error_pci_register;
|
||||
return ret;
|
||||
|
||||
error_register:
|
||||
error_pci_register:
|
||||
iwlagn_rate_control_unregister();
|
||||
error_rc_register:
|
||||
kmem_cache_destroy(iwl_tx_cmd_pool);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1425,6 +1529,7 @@ static void __exit iwl_exit(void)
|
||||
{
|
||||
iwl_pci_unregister_driver();
|
||||
iwlagn_rate_control_unregister();
|
||||
kmem_cache_destroy(iwl_tx_cmd_pool);
|
||||
}
|
||||
|
||||
module_exit(iwl_exit);
|
||||
@ -1438,8 +1543,6 @@ MODULE_PARM_DESC(debug, "debug output mask");
|
||||
|
||||
module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
|
||||
module_param_named(queues_num, iwlagn_mod_params.num_of_queues, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(queues_num, "number of hw queues.");
|
||||
module_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
|
||||
MODULE_PARM_DESC(11n_disable,
|
||||
"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
|
||||
|
@ -82,20 +82,26 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv);
|
||||
void iwlagn_prepare_restart(struct iwl_priv *priv);
|
||||
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb);
|
||||
int __must_check iwl_rx_dispatch(struct iwl_op_mode *op_mode,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
|
||||
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
|
||||
void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
|
||||
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
|
||||
void iwl_nic_error(struct iwl_op_mode *op_mode);
|
||||
|
||||
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
|
||||
|
||||
void iwlagn_lift_passive_no_rx(struct iwl_priv *priv);
|
||||
|
||||
/* MAC80211 */
|
||||
struct ieee80211_hw *iwl_alloc_all(void);
|
||||
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwl_ucode_capabilities *capa);
|
||||
const struct iwl_ucode_capabilities *capa);
|
||||
void iwlagn_mac_unregister(struct iwl_priv *priv);
|
||||
|
||||
/* commands */
|
||||
int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
|
||||
int iwl_dvm_send_cmd_pdu(struct iwl_priv *priv, u8 id,
|
||||
u32 flags, u16 len, const void *data);
|
||||
|
||||
/* RXON */
|
||||
int iwlagn_set_pan_params(struct iwl_priv *priv);
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
@ -110,9 +116,18 @@ void iwlagn_config_ht40(struct ieee80211_conf *conf,
|
||||
|
||||
/* uCode */
|
||||
int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags);
|
||||
int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
|
||||
void iwl_send_prio_tbl(struct iwl_priv *priv);
|
||||
int iwl_init_alive_start(struct iwl_priv *priv);
|
||||
int iwl_run_init_ucode(struct iwl_priv *priv);
|
||||
int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
|
||||
enum iwl_ucode_type ucode_type);
|
||||
int iwl_send_calib_results(struct iwl_priv *priv);
|
||||
int iwl_calib_set(struct iwl_priv *priv,
|
||||
const struct iwl_calib_hdr *cmd, int len);
|
||||
void iwl_calib_free_results(struct iwl_priv *priv);
|
||||
|
||||
/* lib */
|
||||
int iwlagn_send_tx_power(struct iwl_priv *priv);
|
||||
@ -124,8 +139,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int iwlagn_send_patterns(struct iwl_priv *priv,
|
||||
struct cfg80211_wowlan *wowlan);
|
||||
int iwlagn_suspend(struct iwl_priv *priv,
|
||||
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
|
||||
int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
|
||||
#endif
|
||||
|
||||
/* rx */
|
||||
@ -142,9 +156,9 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
static inline u32 iwl_tx_status_to_mac80211(u32 status)
|
||||
@ -179,7 +193,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv);
|
||||
/* bt coex */
|
||||
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
|
||||
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
|
||||
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
|
||||
@ -220,6 +234,8 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta *sta, u8 *sta_id_r);
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr);
|
||||
void iwl_deactivate_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr);
|
||||
u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
const u8 *addr, bool is_ap, struct ieee80211_sta *sta);
|
||||
|
||||
@ -227,46 +243,12 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
|
||||
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
|
||||
/**
|
||||
* iwl_clear_driver_stations - clear knowledge of all stations from driver
|
||||
* @priv: iwl priv struct
|
||||
*
|
||||
* This is called during iwl_down() to make sure that in the case
|
||||
* we're coming there from a hardware restart mac80211 will be
|
||||
* able to reconfigure stations -- if we're getting there in the
|
||||
* normal down flow then the stations will already be cleared.
|
||||
*/
|
||||
static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
priv->num_stations = 0;
|
||||
|
||||
priv->ucode_key_table = 0;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/*
|
||||
* Remove all key information that is not stored as part
|
||||
* of station information since mac80211 may not have had
|
||||
* a chance to remove all the keys. When device is
|
||||
* reconfigured by mac80211 after an error all keys will
|
||||
* be reconfigured.
|
||||
*/
|
||||
memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
|
||||
ctx->key_mapping_keys = 0;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
}
|
||||
|
||||
static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
||||
{
|
||||
if (WARN_ON(!sta))
|
||||
@ -275,37 +257,6 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
||||
return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_sta_id_or_broadcast - return sta_id or broadcast sta
|
||||
* @priv: iwl priv
|
||||
* @context: the current context
|
||||
* @sta: mac80211 station
|
||||
*
|
||||
* In certain circumstances mac80211 passes a station pointer
|
||||
* that may be %NULL, for example during TX or key setup. In
|
||||
* that case, we need to use the broadcast station, so this
|
||||
* inline wraps that pattern.
|
||||
*/
|
||||
static inline int iwl_sta_id_or_broadcast(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *context,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int sta_id;
|
||||
|
||||
if (!sta)
|
||||
return context->bcast_sta_id;
|
||||
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
/*
|
||||
* mac80211 should not be passing a partially
|
||||
* initialised station!
|
||||
*/
|
||||
WARN_ON(sta_id == IWL_INVALID_STATION);
|
||||
|
||||
return sta_id;
|
||||
}
|
||||
|
||||
int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
@ -355,7 +306,6 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
||||
}
|
||||
|
||||
/* eeprom */
|
||||
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
|
||||
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
|
||||
|
||||
extern int iwl_alive_start(struct iwl_priv *priv);
|
||||
@ -402,4 +352,58 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
}
|
||||
#endif
|
||||
|
||||
/* status checks */
|
||||
|
||||
static inline int iwl_is_ready(struct iwl_priv *priv)
|
||||
{
|
||||
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
|
||||
* set but EXIT_PENDING is not */
|
||||
return test_bit(STATUS_READY, &priv->status) &&
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
|
||||
!test_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_alive(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_ALIVE, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_rfkill(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ctkill(struct iwl_priv *priv)
|
||||
{
|
||||
return test_bit(STATUS_CT_KILL, &priv->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ready_rf(struct iwl_priv *priv)
|
||||
{
|
||||
if (iwl_is_rfkill(priv))
|
||||
return 0;
|
||||
|
||||
return iwl_is_ready(priv);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
|
||||
do { \
|
||||
if (!iwl_is_rfkill((m))) \
|
||||
IWL_ERR(m, fmt, ##args); \
|
||||
else \
|
||||
__iwl_err(trans(m)->dev, true, \
|
||||
!iwl_have_debug_level(IWL_DL_RADIO), \
|
||||
fmt, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
|
||||
do { \
|
||||
if (!iwl_is_rfkill((m))) \
|
||||
IWL_ERR(m, fmt, ##args); \
|
||||
else \
|
||||
__iwl_err(trans(m)->dev, true, true, fmt, ##args); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
||||
|
@ -68,46 +68,46 @@
|
||||
* This file declares the config structures for all devices.
|
||||
*/
|
||||
|
||||
extern struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern struct iwl_cfg iwl6005_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6005_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6005_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6005_2agn_sff_cfg;
|
||||
extern struct iwl_cfg iwl6005_2agn_d_cfg;
|
||||
extern struct iwl_cfg iwl6005_2agn_mow1_cfg;
|
||||
extern struct iwl_cfg iwl6005_2agn_mow2_cfg;
|
||||
extern struct iwl_cfg iwl1030_bgn_cfg;
|
||||
extern struct iwl_cfg iwl1030_bg_cfg;
|
||||
extern struct iwl_cfg iwl6030_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6030_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6030_2bgn_cfg;
|
||||
extern struct iwl_cfg iwl6030_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6150_bgn_cfg;
|
||||
extern struct iwl_cfg iwl6150_bg_cfg;
|
||||
extern struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern struct iwl_cfg iwl1000_bg_cfg;
|
||||
extern struct iwl_cfg iwl100_bgn_cfg;
|
||||
extern struct iwl_cfg iwl100_bg_cfg;
|
||||
extern struct iwl_cfg iwl130_bgn_cfg;
|
||||
extern struct iwl_cfg iwl130_bg_cfg;
|
||||
extern struct iwl_cfg iwl2000_2bgn_cfg;
|
||||
extern struct iwl_cfg iwl2000_2bgn_d_cfg;
|
||||
extern struct iwl_cfg iwl2030_2bgn_cfg;
|
||||
extern struct iwl_cfg iwl6035_2agn_cfg;
|
||||
extern struct iwl_cfg iwl105_bgn_cfg;
|
||||
extern struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern struct iwl_cfg iwl135_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5350_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern const struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern const struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_d_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
|
||||
extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1030_bg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6030_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern const struct iwl_cfg iwl6000_3agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl6050_2abg_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6150_bg_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl1000_bg_cfg;
|
||||
extern const struct iwl_cfg iwl100_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl100_bg_cfg;
|
||||
extern const struct iwl_cfg iwl130_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl130_bg_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl2030_2bgn_cfg;
|
||||
extern const struct iwl_cfg iwl6035_2agn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_cfg;
|
||||
extern const struct iwl_cfg iwl105_bgn_d_cfg;
|
||||
extern const struct iwl_cfg iwl135_bgn_cfg;
|
||||
|
||||
#endif /* __iwl_pci_h__ */
|
||||
|
@ -69,22 +69,9 @@
|
||||
#ifndef __iwl_commands_h__
|
||||
#define __iwl_commands_h__
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct iwl_priv;
|
||||
|
||||
/* uCode version contains 4 values: Major/Minor/API/Serial */
|
||||
#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
|
||||
#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
|
||||
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
|
||||
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
|
||||
|
||||
|
||||
/* Tx rates */
|
||||
#define IWL_CCK_RATES 4
|
||||
#define IWL_OFDM_RATES 8
|
||||
#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES)
|
||||
|
||||
enum {
|
||||
REPLY_ALIVE = 0x1,
|
||||
@ -213,48 +200,6 @@ enum {
|
||||
/* iwl_cmd_header flags value */
|
||||
#define IWL_CMD_FAILED_MSK 0x40
|
||||
|
||||
#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
|
||||
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
|
||||
#define SEQ_TO_INDEX(s) ((s) & 0xff)
|
||||
#define INDEX_TO_SEQ(i) ((i) & 0xff)
|
||||
#define SEQ_RX_FRAME cpu_to_le16(0x8000)
|
||||
|
||||
/**
|
||||
* struct iwl_cmd_header
|
||||
*
|
||||
* This header format appears in the beginning of each command sent from the
|
||||
* driver, and each response/notification received from uCode.
|
||||
*/
|
||||
struct iwl_cmd_header {
|
||||
u8 cmd; /* Command ID: REPLY_RXON, etc. */
|
||||
u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
|
||||
/*
|
||||
* The driver sets up the sequence number to values of its choosing.
|
||||
* uCode does not use this value, but passes it back to the driver
|
||||
* when sending the response to each driver-originated command, so
|
||||
* the driver can match the response to the command. Since the values
|
||||
* don't get used by uCode, the driver may set up an arbitrary format.
|
||||
*
|
||||
* There is one exception: uCode sets bit 15 when it originates
|
||||
* the response/notification, i.e. when the response/notification
|
||||
* is not a direct response to a command sent by the driver. For
|
||||
* example, uCode issues REPLY_RX when it sends a received frame
|
||||
* to the driver; it is not a direct response to any driver command.
|
||||
*
|
||||
* The Linux driver uses the following format:
|
||||
*
|
||||
* 0:7 tfd index - position within TX queue
|
||||
* 8:12 TX queue id
|
||||
* 13:14 reserved
|
||||
* 15 unsolicited RX or uCode-originated notification
|
||||
*/
|
||||
__le16 sequence;
|
||||
|
||||
/* command or response/notification data follows immediately */
|
||||
u8 data[0];
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* iwlagn rate_n_flags bit fields
|
||||
*
|
||||
@ -3151,8 +3096,6 @@ struct iwl_enhance_sensitivity_cmd {
|
||||
*/
|
||||
|
||||
/* Phy calibration command for series */
|
||||
/* The default calibrate table size if not specified by firmware */
|
||||
#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
|
||||
enum {
|
||||
IWL_PHY_CALIBRATE_DC_CMD = 8,
|
||||
IWL_PHY_CALIBRATE_LO_CMD = 9,
|
||||
@ -3161,11 +3104,8 @@ enum {
|
||||
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
|
||||
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
|
||||
IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18,
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19,
|
||||
};
|
||||
|
||||
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253)
|
||||
|
||||
/* This enum defines the bitmap of various calibrations to enable in both
|
||||
* init ucode and runtime ucode through CALIBRATION_CFG_CMD.
|
||||
*/
|
||||
@ -3905,50 +3845,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
|
||||
__le64 replay_ctr;
|
||||
} __packed;
|
||||
|
||||
/******************************************************************************
|
||||
* (13)
|
||||
* Union of all expected notifications/responses:
|
||||
*
|
||||
*****************************************************************************/
|
||||
#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
|
||||
|
||||
struct iwl_rx_packet {
|
||||
/*
|
||||
* The first 4 bytes of the RX frame header contain both the RX frame
|
||||
* size and some flags.
|
||||
* Bit fields:
|
||||
* 31: flag flush RB request
|
||||
* 30: flag ignore TC (terminal counter) request
|
||||
* 29: flag fast IRQ request
|
||||
* 28-14: Reserved
|
||||
* 13-00: RX frame size
|
||||
*/
|
||||
__le32 len_n_flags;
|
||||
struct iwl_cmd_header hdr;
|
||||
union {
|
||||
struct iwl_alive_resp alive_frame;
|
||||
struct iwl_spectrum_notification spectrum_notif;
|
||||
struct iwl_csa_notification csa_notif;
|
||||
struct iwl_error_resp err_resp;
|
||||
struct iwl_card_state_notif card_state_notif;
|
||||
struct iwl_add_sta_resp add_sta;
|
||||
struct iwl_rem_sta_resp rem_sta;
|
||||
struct iwl_sleep_notification sleep_notif;
|
||||
struct iwl_spectrum_resp spectrum;
|
||||
struct iwl_notif_statistics stats;
|
||||
struct iwl_bt_notif_statistics stats_bt;
|
||||
struct iwl_compressed_ba_resp compressed_ba;
|
||||
struct iwl_missed_beacon_notif missed_beacon;
|
||||
struct iwl_coex_medium_notification coex_medium_notif;
|
||||
struct iwl_coex_event_resp coex_event;
|
||||
struct iwl_bt_coex_profile_notif bt_coex_profile_notif;
|
||||
__le32 status;
|
||||
u8 raw[0];
|
||||
} u;
|
||||
} __packed;
|
||||
|
||||
int iwl_agn_check_rxon_cmd(struct iwl_priv *priv);
|
||||
|
||||
/*
|
||||
* REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
|
||||
*/
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-wifi.h"
|
||||
|
||||
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
@ -114,7 +113,7 @@ int iwl_init_geos(struct iwl_priv *priv)
|
||||
if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
|
||||
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -137,7 +136,7 @@ int iwl_init_geos(struct iwl_priv *priv)
|
||||
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
|
||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
|
||||
|
||||
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||
IEEE80211_BAND_5GHZ);
|
||||
|
||||
@ -147,7 +146,7 @@ int iwl_init_geos(struct iwl_priv *priv)
|
||||
sband->bitrates = rates;
|
||||
sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
|
||||
|
||||
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
iwl_init_ht_hw_capab(priv, &sband->ht_cap,
|
||||
IEEE80211_BAND_2GHZ);
|
||||
|
||||
@ -202,18 +201,18 @@ int iwl_init_geos(struct iwl_priv *priv)
|
||||
priv->tx_power_next = max_tx_power;
|
||||
|
||||
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
|
||||
cfg(priv)->sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
||||
hw_params(priv).sku & EEPROM_SKU_CAP_BAND_52GHZ) {
|
||||
IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
|
||||
"Please send your %s to maintainer.\n",
|
||||
trans(priv)->hw_id_str);
|
||||
cfg(priv)->sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
||||
hw_params(priv).sku &= ~EEPROM_SKU_CAP_BAND_52GHZ;
|
||||
}
|
||||
|
||||
IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
|
||||
priv->bands[IEEE80211_BAND_2GHZ].n_channels,
|
||||
priv->bands[IEEE80211_BAND_5GHZ].n_channels);
|
||||
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
|
||||
set_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -225,7 +224,7 @@ void iwl_free_geos(struct iwl_priv *priv)
|
||||
{
|
||||
kfree(priv->ieee_channels);
|
||||
kfree(priv->ieee_rates);
|
||||
clear_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status);
|
||||
clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
|
||||
}
|
||||
|
||||
static bool iwl_is_channel_extension(struct iwl_priv *priv,
|
||||
@ -317,7 +316,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
|
||||
conf = &priv->hw->conf;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
|
||||
|
||||
@ -370,7 +369,7 @@ int iwl_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
le32_to_cpu(ctx->timing.beacon_init_val),
|
||||
le16_to_cpu(ctx->timing.atim_window));
|
||||
|
||||
return iwl_trans_send_cmd_pdu(trans(priv), ctx->rxon_timing_cmd,
|
||||
return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
|
||||
CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
|
||||
}
|
||||
|
||||
@ -799,11 +798,10 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
|
||||
&priv->shrd->status))
|
||||
if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
|
||||
ieee80211_chswitch_done(ctx->vif, is_success);
|
||||
}
|
||||
|
||||
@ -836,7 +834,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||
unsigned long reload_jiffies;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(priv->shrd) & IWL_DL_FW_ERRORS)
|
||||
if (iwl_have_debug_level(IWL_DL_FW_ERRORS))
|
||||
iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
|
||||
#endif
|
||||
|
||||
@ -846,11 +844,11 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||
/* Cancel currently queued command. */
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status);
|
||||
|
||||
iwl_abort_notification_waits(priv->shrd);
|
||||
iwl_abort_notification_waits(&priv->notif_wait);
|
||||
|
||||
/* Keep the restart process from trying to send host
|
||||
* commands by clearing the ready bit */
|
||||
clear_bit(STATUS_READY, &priv->shrd->status);
|
||||
clear_bit(STATUS_READY, &priv->status);
|
||||
|
||||
wake_up(&priv->shrd->wait_command_queue);
|
||||
|
||||
@ -875,7 +873,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||
priv->reload_count = 0;
|
||||
}
|
||||
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
if (iwlagn_mod_params.restart_fw) {
|
||||
IWL_DEBUG_FW_ERRORS(priv,
|
||||
"Restarting adapter due to uCode error.\n");
|
||||
@ -893,7 +891,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
||||
bool defer;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (priv->tx_power_user_lmt == tx_power && !force)
|
||||
return 0;
|
||||
@ -913,7 +911,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EIO;
|
||||
|
||||
/* scan complete and commit_rxon use tx_power_next value,
|
||||
@ -921,7 +919,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
|
||||
priv->tx_power_next = tx_power;
|
||||
|
||||
/* do not set tx power when scanning or channel changing */
|
||||
defer = test_bit(STATUS_SCANNING, &priv->shrd->status) ||
|
||||
defer = test_bit(STATUS_SCANNING, &priv->status) ||
|
||||
memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
|
||||
if (defer && !force) {
|
||||
IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
|
||||
@ -959,7 +957,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
|
||||
IWL_DEBUG_INFO(priv, "BT coex %s\n",
|
||||
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
|
||||
|
||||
if (iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
|
||||
if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
|
||||
CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
|
||||
IWL_ERR(priv, "failed to send BT Coex Config\n");
|
||||
}
|
||||
@ -972,12 +970,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
|
||||
};
|
||||
|
||||
if (flags & CMD_ASYNC)
|
||||
return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
|
||||
return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
|
||||
CMD_ASYNC,
|
||||
sizeof(struct iwl_statistics_cmd),
|
||||
&statistics_cmd);
|
||||
else
|
||||
return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD,
|
||||
return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
|
||||
CMD_SYNC,
|
||||
sizeof(struct iwl_statistics_cmd),
|
||||
&statistics_cmd);
|
||||
@ -1004,7 +1002,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
|
||||
{
|
||||
u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
|
||||
|
||||
if (iwl_get_debug_level(priv->shrd) & IWL_DL_TX) {
|
||||
if (iwl_have_debug_level(IWL_DL_TX)) {
|
||||
if (!priv->tx_traffic) {
|
||||
priv->tx_traffic =
|
||||
kzalloc(traffic_size, GFP_KERNEL);
|
||||
@ -1012,7 +1010,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) {
|
||||
if (iwl_have_debug_level(IWL_DL_RX)) {
|
||||
if (!priv->rx_traffic) {
|
||||
priv->rx_traffic =
|
||||
kzalloc(traffic_size, GFP_KERNEL);
|
||||
@ -1039,7 +1037,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
|
||||
__le16 fc;
|
||||
u16 len;
|
||||
|
||||
if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)))
|
||||
if (likely(!iwl_have_debug_level(IWL_DL_TX)))
|
||||
return;
|
||||
|
||||
if (!priv->tx_traffic)
|
||||
@ -1063,7 +1061,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
|
||||
__le16 fc;
|
||||
u16 len;
|
||||
|
||||
if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)))
|
||||
if (likely(!iwl_have_debug_level(IWL_DL_RX)))
|
||||
return;
|
||||
|
||||
if (!priv->rx_traffic)
|
||||
@ -1220,7 +1218,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
|
||||
|
||||
static void iwl_force_rf_reset(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!iwl_is_any_associated(priv)) {
|
||||
@ -1245,7 +1243,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
|
||||
{
|
||||
struct iwl_force_reset *force_reset;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return -EINVAL;
|
||||
|
||||
if (mode >= IWL_MAX_FORCE_RESET) {
|
||||
@ -1301,7 +1299,7 @@ int iwl_cmd_echo_test(struct iwl_priv *priv)
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
|
||||
else
|
||||
@ -1335,30 +1333,20 @@ void iwl_bg_watchdog(unsigned long data)
|
||||
int cnt;
|
||||
unsigned long timeout;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (iwl_is_rfkill(priv->shrd))
|
||||
if (iwl_is_rfkill(priv))
|
||||
return;
|
||||
|
||||
timeout = cfg(priv)->base_params->wd_timeout;
|
||||
timeout = hw_params(priv).wd_timeout;
|
||||
if (timeout == 0)
|
||||
return;
|
||||
|
||||
/* monitor and check for stuck cmd queue */
|
||||
if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue))
|
||||
return;
|
||||
|
||||
/* monitor and check for other stuck queues */
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
for (cnt = 0; cnt < hw_params(priv).max_txq_num; cnt++) {
|
||||
/* skip as we already checked the command queue */
|
||||
if (cnt == priv->shrd->cmd_queue)
|
||||
continue;
|
||||
if (iwl_check_stuck_queue(priv, cnt))
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* monitor and check for stuck queues */
|
||||
for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++)
|
||||
if (iwl_check_stuck_queue(priv, cnt))
|
||||
return;
|
||||
|
||||
mod_timer(&priv->watchdog, jiffies +
|
||||
msecs_to_jiffies(IWL_WD_TICK(timeout)));
|
||||
@ -1366,7 +1354,7 @@ void iwl_bg_watchdog(unsigned long data)
|
||||
|
||||
void iwl_setup_watchdog(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned int timeout = cfg(priv)->base_params->wd_timeout;
|
||||
unsigned int timeout = hw_params(priv).wd_timeout;
|
||||
|
||||
if (!iwlagn_mod_params.wd_disable) {
|
||||
/* use system default */
|
||||
@ -1471,34 +1459,19 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
||||
}
|
||||
if (state)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
void iwl_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
cfg(priv)->lib->nic_config(priv);
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
|
||||
}
|
||||
|
||||
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
|
||||
kmem_cache_free(iwl_tx_cmd_pool, (info->driver_data[1]));
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
ieee80211_stop_queue(priv->hw, ac);
|
||||
}
|
||||
|
||||
void iwl_wake_sw_queue(struct iwl_op_mode *op_mode, u8 ac)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
|
||||
|
||||
ieee80211_wake_queue(priv->hw, ac);
|
||||
}
|
||||
|
@ -77,12 +77,6 @@ struct iwl_cmd;
|
||||
struct iwl_lib_ops {
|
||||
/* set hw dependent parameters */
|
||||
void (*set_hw_params)(struct iwl_priv *priv);
|
||||
/* setup BT Rx handler */
|
||||
void (*bt_rx_handler_setup)(struct iwl_priv *priv);
|
||||
/* setup BT related deferred work */
|
||||
void (*bt_setup_deferred_work)(struct iwl_priv *priv);
|
||||
/* cancel deferred work */
|
||||
void (*cancel_deferred_work)(struct iwl_priv *priv);
|
||||
int (*set_channel_switch)(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
/* device specific configuration */
|
||||
@ -95,72 +89,6 @@ struct iwl_lib_ops {
|
||||
void (*temperature)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
/*
|
||||
* @max_ll_items: max number of OTP blocks
|
||||
* @shadow_ram_support: shadow support for OTP memory
|
||||
* @led_compensation: compensate on the led on/off time per HW according
|
||||
* to the deviation to achieve the desired led frequency.
|
||||
* The detail algorithm is described in iwl-led.c
|
||||
* @chain_noise_num_beacons: number of beacons used to compute chain noise
|
||||
* @adv_thermal_throttle: support advance thermal throttle
|
||||
* @support_ct_kill_exit: support ct kill exit condition
|
||||
* @support_wimax_coexist: support wimax/wifi co-exist
|
||||
* @plcp_delta_threshold: plcp error rate threshold used to trigger
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @shadow_reg_enable: HW shadhow register bit
|
||||
* @no_idle_support: do not support idle mode
|
||||
* @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
|
||||
* wd_disable: disable watchdog timer
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
int eeprom_size;
|
||||
int num_of_queues; /* def: HW dependent */
|
||||
int num_of_ampdu_queues;/* def: HW dependent */
|
||||
/* for iwl_apm_init() */
|
||||
u32 pll_cfg_val;
|
||||
|
||||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
u16 led_compensation;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
const bool support_wimax_coexist;
|
||||
u8 plcp_delta_threshold;
|
||||
s32 chain_noise_scale;
|
||||
unsigned int wd_timeout;
|
||||
u32 max_event_log_size;
|
||||
const bool shadow_reg_enable;
|
||||
const bool no_idle_support;
|
||||
const bool hd_v2;
|
||||
const bool wd_disable;
|
||||
};
|
||||
/*
|
||||
* @advanced_bt_coexist: support advanced bt coexist
|
||||
* @bt_init_traffic_load: specify initial bt traffic load
|
||||
* @bt_prio_boost: default bt priority boost value
|
||||
* @agg_time_limit: maximum number of uSec in aggregation
|
||||
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
||||
*/
|
||||
struct iwl_bt_params {
|
||||
bool advanced_bt_coexist;
|
||||
u8 bt_init_traffic_load;
|
||||
u8 bt_prio_boost;
|
||||
u16 agg_time_limit;
|
||||
bool bt_sco_disable;
|
||||
bool bt_session_2;
|
||||
};
|
||||
/*
|
||||
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
|
||||
*/
|
||||
struct iwl_ht_params {
|
||||
const bool ht_greenfield_support; /* if used set to true */
|
||||
bool use_rts_for_aggregation;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
};
|
||||
|
||||
/***************************
|
||||
* L i b *
|
||||
***************************/
|
||||
@ -244,8 +172,6 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
void iwl_force_scan_end(struct iwl_priv *priv);
|
||||
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ta, const u8 *ie, int ie_len, int left);
|
||||
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
|
||||
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
|
||||
void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
|
||||
@ -265,6 +191,10 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
|
||||
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
|
||||
|
||||
/* traffic log definitions */
|
||||
#define IWL_TRAFFIC_ENTRIES (256)
|
||||
#define IWL_TRAFFIC_ENTRY_SIZE (64)
|
||||
|
||||
/*****************************************************
|
||||
* S e n d i n g H o s t C o m m a n d s *
|
||||
*****************************************************/
|
||||
|
@ -104,7 +104,7 @@ void __iwl_err(struct device *dev, bool rfkill_prefix, bool trace_only,
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
|
||||
void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
void __iwl_dbg(struct device *dev,
|
||||
u32 level, bool limit, const char *function,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
@ -116,7 +116,7 @@ void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(shared) & level &&
|
||||
if (iwl_have_debug_level(level) &&
|
||||
(!limit || net_ratelimit()))
|
||||
dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
|
||||
function, &vaf);
|
||||
|
@ -47,12 +47,12 @@ void __iwl_crit(struct device *dev, const char *fmt, ...);
|
||||
#define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
|
||||
|
||||
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
|
||||
void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
void __iwl_dbg(struct device *dev,
|
||||
u32 level, bool limit, const char *function,
|
||||
const char *fmt, ...);
|
||||
#else
|
||||
static inline void
|
||||
__iwl_dbg(struct iwl_shared *shared, struct device *dev,
|
||||
__iwl_dbg(struct device *dev,
|
||||
u32 level, bool limit, const char *function,
|
||||
const char *fmt, ...)
|
||||
{}
|
||||
@ -65,35 +65,19 @@ do { \
|
||||
} while (0)
|
||||
|
||||
#define IWL_DEBUG(m, level, fmt, args...) \
|
||||
__iwl_dbg((m)->shrd, trans(m)->dev, level, false, __func__, fmt, ##args)
|
||||
__iwl_dbg(trans(m)->dev, level, false, __func__, fmt, ##args)
|
||||
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
|
||||
__iwl_dbg((m)->shrd, trans(m)->dev, level, true, __func__, fmt, ##args)
|
||||
__iwl_dbg(trans(m)->dev, level, true, __func__, fmt, ##args)
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
#define iwl_print_hex_dump(m, level, p, len) \
|
||||
do { \
|
||||
if (iwl_get_debug_level((m)->shrd) & level) \
|
||||
if (iwl_have_debug_level(level)) \
|
||||
print_hex_dump(KERN_DEBUG, "iwl data: ", \
|
||||
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
|
||||
} while (0)
|
||||
#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
|
||||
do { \
|
||||
if (!iwl_is_rfkill((m)->shrd)) \
|
||||
IWL_ERR(m, fmt, ##args); \
|
||||
else \
|
||||
__iwl_err(trans(m)->dev, true, \
|
||||
!(iwl_get_debug_level((m)->shrd) & IWL_DL_RADIO),\
|
||||
fmt, ##args); \
|
||||
} while (0)
|
||||
#else
|
||||
#define iwl_print_hex_dump(m, level, p, len)
|
||||
#define IWL_DEBUG_QUIET_RFKILL(m, fmt, args...) \
|
||||
do { \
|
||||
if (!iwl_is_rfkill((m)->shrd)) \
|
||||
IWL_ERR(m, fmt, ##args); \
|
||||
else \
|
||||
__iwl_err(trans(m)->dev, true, true, fmt, ##args); \
|
||||
} while (0)
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-wifi.h"
|
||||
|
||||
/* create and remove of files */
|
||||
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \
|
||||
@ -235,12 +234,11 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
|
||||
|
||||
/* default is to dump the entire data segment */
|
||||
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
|
||||
struct iwl_nic *nic = nic(priv);
|
||||
priv->dbgfs_sram_offset = 0x800000;
|
||||
if (nic->shrd->ucode_type == IWL_UCODE_INIT)
|
||||
priv->dbgfs_sram_len = nic->fw.ucode_init.data.len;
|
||||
if (priv->shrd->ucode_type == IWL_UCODE_INIT)
|
||||
priv->dbgfs_sram_len = priv->fw->ucode_init.data.len;
|
||||
else
|
||||
priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len;
|
||||
priv->dbgfs_sram_len = priv->fw->ucode_rt.data.len;
|
||||
}
|
||||
len = priv->dbgfs_sram_len;
|
||||
|
||||
@ -343,7 +341,7 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos,
|
||||
priv->wowlan_sram,
|
||||
nic(priv)->fw.ucode_wowlan.data.len);
|
||||
priv->fw->ucode_wowlan.data.len);
|
||||
}
|
||||
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -456,7 +454,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
|
||||
char *buf;
|
||||
ssize_t ret;
|
||||
|
||||
if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
@ -527,32 +525,26 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
|
||||
test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
|
||||
test_bit(STATUS_INT_ENABLED, &priv->shrd->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
|
||||
test_bit(STATUS_CT_KILL, &priv->shrd->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
|
||||
test_bit(STATUS_INIT, &priv->shrd->status));
|
||||
test_bit(STATUS_CT_KILL, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n",
|
||||
test_bit(STATUS_ALIVE, &priv->shrd->status));
|
||||
test_bit(STATUS_ALIVE, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
|
||||
test_bit(STATUS_READY, &priv->shrd->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
|
||||
test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
|
||||
test_bit(STATUS_READY, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status));
|
||||
test_bit(STATUS_GEO_CONFIGURED, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n",
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->shrd->status));
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n",
|
||||
test_bit(STATUS_STATISTICS, &priv->shrd->status));
|
||||
test_bit(STATUS_STATISTICS, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
|
||||
test_bit(STATUS_SCANNING, &priv->shrd->status));
|
||||
test_bit(STATUS_SCANNING, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
|
||||
test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status));
|
||||
test_bit(STATUS_SCAN_ABORTING, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
|
||||
test_bit(STATUS_SCAN_HW, &priv->shrd->status));
|
||||
test_bit(STATUS_SCAN_HW, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
|
||||
test_bit(STATUS_POWER_PMI, &priv->shrd->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
|
||||
@ -758,14 +750,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
|
||||
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
priv->power_data.debug_sleep_level_override = value;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_power_update_mode(priv, true);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -836,7 +828,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
|
||||
|
||||
char *buf;
|
||||
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
|
||||
(hw_params(priv).max_txq_num * 32 * 8) + 400;
|
||||
(cfg(priv)->base_params->num_of_queues * 32 * 8) + 400;
|
||||
const u8 *ptr;
|
||||
ssize_t ret;
|
||||
|
||||
@ -845,8 +837,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
|
||||
IWL_ERR(priv, "Can not allocate buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (priv->tx_traffic &&
|
||||
(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
|
||||
if (priv->tx_traffic && iwl_have_debug_level(IWL_DL_TX)) {
|
||||
ptr = priv->tx_traffic;
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"Tx Traffic idx: %u\n", priv->tx_traffic_idx);
|
||||
@ -864,8 +855,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->rx_traffic &&
|
||||
(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
|
||||
if (priv->rx_traffic && iwl_have_debug_level(IWL_DL_RX)) {
|
||||
ptr = priv->rx_traffic;
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"Rx Traffic idx: %u\n", priv->rx_traffic_idx);
|
||||
@ -920,6 +910,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
|
||||
int p = 0;
|
||||
u32 flag;
|
||||
|
||||
lockdep_assert_held(&priv->statistics.lock);
|
||||
|
||||
flag = le32_to_cpu(priv->statistics.flag);
|
||||
|
||||
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
|
||||
@ -953,7 +945,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
||||
struct statistics_rx_non_phy *delta_general, *max_general;
|
||||
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
@ -967,6 +959,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
ofdm = &priv->statistics.rx_ofdm;
|
||||
cck = &priv->statistics.rx_cck;
|
||||
general = &priv->statistics.rx_non_phy;
|
||||
@ -1363,6 +1356,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
||||
accum_ht->unsupport_mcs,
|
||||
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
|
||||
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
@ -1379,7 +1374,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
||||
ssize_t ret;
|
||||
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
@ -1392,6 +1387,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
|
||||
tx = &priv->statistics.tx;
|
||||
accum_tx = &priv->accum_stats.tx;
|
||||
delta_tx = &priv->delta_stats.tx;
|
||||
@ -1541,19 +1538,25 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
||||
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"tx power: (1/2 dB step)\n");
|
||||
if ((cfg(priv)->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
|
||||
if ((hw_params(priv).valid_tx_ant & ANT_A) &&
|
||||
tx->tx_power.ant_a)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna A:",
|
||||
tx->tx_power.ant_a);
|
||||
if ((cfg(priv)->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
|
||||
if ((hw_params(priv).valid_tx_ant & ANT_B) &&
|
||||
tx->tx_power.ant_b)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna B:",
|
||||
tx->tx_power.ant_b);
|
||||
if ((cfg(priv)->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
|
||||
if ((hw_params(priv).valid_tx_ant & ANT_C) &&
|
||||
tx->tx_power.ant_c)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
fmt_hex, "antenna C:",
|
||||
tx->tx_power.ant_c);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
@ -1573,7 +1576,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
||||
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
|
||||
struct statistics_div *div, *accum_div, *delta_div, *max_div;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
@ -1586,6 +1589,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
|
||||
general = &priv->statistics.common;
|
||||
dbg = &priv->statistics.common.dbg;
|
||||
div = &priv->statistics.common.div;
|
||||
@ -1670,6 +1676,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
||||
accum_general->num_of_sos_states,
|
||||
delta_general->num_of_sos_states,
|
||||
max_general->num_of_sos_states);
|
||||
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
@ -1686,16 +1695,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
|
||||
ssize_t ret;
|
||||
struct statistics_bt_activity *bt, *accum_bt;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
if (!priv->bt_enable_flag)
|
||||
return -EINVAL;
|
||||
|
||||
/* make request to uCode to retrieve statistics information */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
if (ret) {
|
||||
IWL_ERR(priv,
|
||||
@ -1713,6 +1722,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
|
||||
spin_lock_bh(&priv->statistics.lock);
|
||||
|
||||
bt = &priv->statistics.bt_activity;
|
||||
accum_bt = &priv->accum_stats.bt_activity;
|
||||
|
||||
@ -1758,6 +1770,8 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
|
||||
le32_to_cpu(priv->statistics.num_bt_kills),
|
||||
priv->statistics.accum_num_bt_kills);
|
||||
|
||||
spin_unlock_bh(&priv->statistics.lock);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
@ -1774,7 +1788,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
|
||||
(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
|
||||
ssize_t ret;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
@ -2086,9 +2100,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
|
||||
return -EFAULT;
|
||||
|
||||
/* make request to uCode to retrieve statistics information */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_send_statistics_request(priv, CMD_SYNC, true);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
@ -2132,7 +2146,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
|
||||
|
||||
if (trace) {
|
||||
priv->event_log.ucode_trace = true;
|
||||
if (iwl_is_alive(priv->shrd)) {
|
||||
if (iwl_is_alive(priv)) {
|
||||
/* start collecting data now */
|
||||
mod_timer(&priv->ucode_trace, jiffies);
|
||||
}
|
||||
@ -2221,7 +2235,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
|
||||
const size_t bufsz = sizeof(buf);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
|
||||
cfg(priv)->base_params->plcp_delta_threshold);
|
||||
priv->plcp_delta_threshold);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
@ -2243,10 +2257,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
|
||||
return -EINVAL;
|
||||
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
|
||||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
|
||||
cfg(priv)->base_params->plcp_delta_threshold =
|
||||
priv->plcp_delta_threshold =
|
||||
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
|
||||
else
|
||||
cfg(priv)->base_params->plcp_delta_threshold = plcp;
|
||||
priv->plcp_delta_threshold = plcp;
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -2322,7 +2336,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
|
||||
if (sscanf(buf, "%d", &flush) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
if (iwl_is_rfkill(priv->shrd))
|
||||
if (iwl_is_rfkill(priv))
|
||||
return -EFAULT;
|
||||
|
||||
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
|
||||
@ -2348,7 +2362,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
|
||||
if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
|
||||
timeout = IWL_DEF_WD_TIMEOUT;
|
||||
|
||||
cfg(priv)->base_params->wd_timeout = timeout;
|
||||
hw_params(priv).wd_timeout = timeout;
|
||||
iwl_setup_watchdog(priv);
|
||||
return count;
|
||||
}
|
||||
@ -2411,7 +2425,7 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
|
||||
if (cfg(priv)->ht_params)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"use %s for aggregation\n",
|
||||
(cfg(priv)->ht_params->use_rts_for_aggregation) ?
|
||||
(hw_params(priv).use_rts_for_aggregation) ?
|
||||
"rts/cts" : "cts-to-self");
|
||||
else
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A");
|
||||
@ -2438,9 +2452,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
|
||||
if (sscanf(buf, "%d", &rts) != 1)
|
||||
return -EINVAL;
|
||||
if (rts)
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation = true;
|
||||
hw_params(priv).use_rts_for_aggregation = true;
|
||||
else
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation = false;
|
||||
hw_params(priv).use_rts_for_aggregation = false;
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -2486,52 +2500,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
|
||||
DEBUGFS_READ_FILE_OPS(reply_tx_error);
|
||||
DEBUGFS_WRITE_FILE_OPS(echo_test);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
char buf[11];
|
||||
int len;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "0x%.8x",
|
||||
iwl_get_debug_level(shrd));
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
char buf[11];
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
if (count > sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (copy_from_user(buf, user_buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
shrd->dbg_level_dev = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
*
|
||||
@ -2596,9 +2564,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
|
||||
if (iwl_advanced_bt_coexist(priv))
|
||||
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
|
||||
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
|
||||
&priv->disable_sens_cal);
|
||||
|
@ -36,11 +36,10 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/leds.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/ieee80211_radiotap.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-led.h"
|
||||
@ -50,6 +49,7 @@
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-op-mode.h"
|
||||
#include "iwl-notif-wait.h"
|
||||
|
||||
struct iwl_tx_queue;
|
||||
|
||||
@ -294,7 +294,6 @@ struct iwl_vif_priv {
|
||||
|
||||
struct iwl_sensitivity_ranges {
|
||||
u16 min_nrg_cck;
|
||||
u16 max_nrg_cck;
|
||||
|
||||
u16 nrg_th_cck;
|
||||
u16 nrg_th_ofdm;
|
||||
@ -670,11 +669,6 @@ struct iwl_rxon_context {
|
||||
bool enabled, is_40mhz;
|
||||
u8 extension_chan_offset;
|
||||
} ht;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
bool preauth_bssid;
|
||||
|
||||
bool last_tx_rejected;
|
||||
};
|
||||
|
||||
enum iwl_scan_type {
|
||||
@ -718,29 +712,44 @@ struct iwl_priv {
|
||||
|
||||
/*data shared among all the driver's layers */
|
||||
struct iwl_shared *shrd;
|
||||
const struct iwl_fw *fw;
|
||||
unsigned long status;
|
||||
|
||||
spinlock_t sta_lock;
|
||||
struct mutex mutex;
|
||||
|
||||
unsigned long transport_queue_stop;
|
||||
bool passive_no_rx;
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
struct ieee80211_hw *hw;
|
||||
struct ieee80211_channel *ieee_channels;
|
||||
struct ieee80211_rate *ieee_rates;
|
||||
struct kmem_cache *tx_cmd_pool;
|
||||
|
||||
struct list_head calib_results;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
|
||||
enum ieee80211_band band;
|
||||
|
||||
void (*pre_rx_handler)(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
struct iwl_rx_cmd_buffer *rxb);
|
||||
int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
struct iwl_notif_wait_data notif_wait;
|
||||
|
||||
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
|
||||
|
||||
/* spectrum measurement report caching */
|
||||
struct iwl_spectrum_notification measure_report;
|
||||
u8 measurement_status;
|
||||
|
||||
#define IWL_OWNERSHIP_DRIVER 0
|
||||
#define IWL_OWNERSHIP_TM 1
|
||||
u8 ucode_owner;
|
||||
|
||||
/* ucode beacon time */
|
||||
u32 ucode_beacon_time;
|
||||
int missed_beacon_threshold;
|
||||
@ -766,6 +775,8 @@ struct iwl_priv {
|
||||
struct iwl_channel_info *channel_info; /* channel info array */
|
||||
u8 channel_count; /* # of channels */
|
||||
|
||||
u8 plcp_delta_threshold;
|
||||
|
||||
/* thermal calibration */
|
||||
s32 temperature; /* Celsius */
|
||||
s32 last_temperature;
|
||||
@ -788,6 +799,8 @@ struct iwl_priv {
|
||||
|
||||
bool new_scan_threshold_behaviour;
|
||||
|
||||
bool wowlan;
|
||||
|
||||
/* EEPROM MAC addresses */
|
||||
struct mac_address addresses[2];
|
||||
|
||||
@ -845,6 +858,7 @@ struct iwl_priv {
|
||||
struct statistics_bt_activity bt_activity;
|
||||
__le32 num_bt_kills, accum_num_bt_kills;
|
||||
#endif
|
||||
spinlock_t lock;
|
||||
} statistics;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
struct {
|
||||
@ -968,6 +982,7 @@ struct iwl_priv {
|
||||
bool have_rekey_data;
|
||||
}; /*iwl_priv */
|
||||
|
||||
extern struct kmem_cache *iwl_tx_cmd_pool;
|
||||
extern struct iwl_mod_params iwlagn_mod_params;
|
||||
|
||||
static inline struct iwl_rxon_context *
|
||||
|
@ -41,130 +41,134 @@ static inline void trace_ ## name(proto) {}
|
||||
static inline void trace_ ## name(proto) {}
|
||||
#endif
|
||||
|
||||
#define PRIV_ENTRY __field(void *, priv)
|
||||
#define PRIV_ASSIGN __entry->priv = priv
|
||||
#define DEV_ENTRY __string(dev, dev_name(dev))
|
||||
#define DEV_ASSIGN __assign_str(dev, dev_name(dev))
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwlwifi_io
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ioread32,
|
||||
TP_PROTO(void *priv, u32 offs, u32 val),
|
||||
TP_ARGS(priv, offs, val),
|
||||
TP_PROTO(const struct device *dev, u32 offs, u32 val),
|
||||
TP_ARGS(dev, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__field(u32, offs)
|
||||
__field(u32, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val)
|
||||
TP_printk("[%s] read io[%#x] = %#x",
|
||||
__get_str(dev), __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_iowrite8,
|
||||
TP_PROTO(void *priv, u32 offs, u8 val),
|
||||
TP_ARGS(priv, offs, val),
|
||||
TP_PROTO(const struct device *dev, u32 offs, u8 val),
|
||||
TP_ARGS(dev, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__field(u32, offs)
|
||||
__field(u8, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
|
||||
TP_printk("[%s] write io[%#x] = %#x)",
|
||||
__get_str(dev), __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_iowrite32,
|
||||
TP_PROTO(void *priv, u32 offs, u32 val),
|
||||
TP_ARGS(priv, offs, val),
|
||||
TP_PROTO(const struct device *dev, u32 offs, u32 val),
|
||||
TP_ARGS(dev, offs, val),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__field(u32, offs)
|
||||
__field(u32, val)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->offs = offs;
|
||||
__entry->val = val;
|
||||
),
|
||||
TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val)
|
||||
TP_printk("[%s] write io[%#x] = %#x)",
|
||||
__get_str(dev), __entry->offs, __entry->val)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_irq,
|
||||
TP_PROTO(void *priv),
|
||||
TP_ARGS(priv),
|
||||
TP_PROTO(const struct device *dev),
|
||||
TP_ARGS(dev),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
),
|
||||
/* TP_printk("") doesn't compile */
|
||||
TP_printk("%d", 0)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ict_read,
|
||||
TP_PROTO(void *priv, u32 index, u32 value),
|
||||
TP_ARGS(priv, index, value),
|
||||
TP_PROTO(const struct device *dev, u32 index, u32 value),
|
||||
TP_ARGS(dev, index, value),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__field(u32, index)
|
||||
__field(u32, value)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->index = index;
|
||||
__entry->value = value;
|
||||
),
|
||||
TP_printk("read ict[%d] = %#.8x", __entry->index, __entry->value)
|
||||
TP_printk("[%s] read ict[%d] = %#.8x",
|
||||
__get_str(dev), __entry->index, __entry->value)
|
||||
);
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM iwlwifi_ucode
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
|
||||
TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
|
||||
TP_ARGS(priv, time, data, ev),
|
||||
TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
|
||||
TP_ARGS(dev, time, data, ev),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
|
||||
__field(u32, time)
|
||||
__field(u32, data)
|
||||
__field(u32, ev)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->time = time;
|
||||
__entry->data = data;
|
||||
__entry->ev = ev;
|
||||
),
|
||||
TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
|
||||
__entry->priv, __entry->time, __entry->data, __entry->ev)
|
||||
TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
|
||||
__get_str(dev), __entry->time, __entry->data, __entry->ev)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
|
||||
TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry),
|
||||
TP_ARGS(priv, wraps, n_entry, p_entry),
|
||||
TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
|
||||
TP_ARGS(dev, wraps, n_entry, p_entry),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
|
||||
__field(u32, wraps)
|
||||
__field(u32, n_entry)
|
||||
__field(u32, p_entry)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->wraps = wraps;
|
||||
__entry->n_entry = n_entry;
|
||||
__entry->p_entry = p_entry;
|
||||
),
|
||||
TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
|
||||
__entry->priv, __entry->wraps, __entry->n_entry,
|
||||
TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
|
||||
__get_str(dev), __entry->wraps, __entry->n_entry,
|
||||
__entry->p_entry)
|
||||
);
|
||||
|
||||
@ -232,52 +236,52 @@ TRACE_EVENT(iwlwifi_dbg,
|
||||
#define TRACE_SYSTEM iwlwifi
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_hcmd,
|
||||
TP_PROTO(void *priv, u32 flags,
|
||||
TP_PROTO(const struct device *dev, u32 flags,
|
||||
const void *hcmd0, size_t len0,
|
||||
const void *hcmd1, size_t len1,
|
||||
const void *hcmd2, size_t len2),
|
||||
TP_ARGS(priv, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
|
||||
TP_ARGS(dev, flags, hcmd0, len0, hcmd1, len1, hcmd2, len2),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__dynamic_array(u8, hcmd0, len0)
|
||||
__dynamic_array(u8, hcmd1, len1)
|
||||
__dynamic_array(u8, hcmd2, len2)
|
||||
__field(u32, flags)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
|
||||
memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
|
||||
memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
|
||||
__entry->flags = flags;
|
||||
),
|
||||
TP_printk("[%p] hcmd %#.2x (%ssync)",
|
||||
__entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0],
|
||||
TP_printk("[%s] hcmd %#.2x (%ssync)",
|
||||
__get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0],
|
||||
__entry->flags & CMD_ASYNC ? "a" : "")
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_rx,
|
||||
TP_PROTO(void *priv, void *rxbuf, size_t len),
|
||||
TP_ARGS(priv, rxbuf, len),
|
||||
TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
|
||||
TP_ARGS(dev, rxbuf, len),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__dynamic_array(u8, rxbuf, len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
|
||||
),
|
||||
TP_printk("[%p] RX cmd %#.2x",
|
||||
__entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
|
||||
TP_printk("[%s] RX cmd %#.2x",
|
||||
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_tx,
|
||||
TP_PROTO(void *priv, void *tfd, size_t tfdlen,
|
||||
TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
|
||||
void *buf0, size_t buf0_len,
|
||||
void *buf1, size_t buf1_len),
|
||||
TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
|
||||
TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
|
||||
__field(size_t, framelen)
|
||||
__dynamic_array(u8, tfd, tfdlen)
|
||||
@ -291,29 +295,28 @@ TRACE_EVENT(iwlwifi_dev_tx,
|
||||
__dynamic_array(u8, buf1, buf1_len)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->framelen = buf0_len + buf1_len;
|
||||
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
|
||||
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
|
||||
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
|
||||
),
|
||||
TP_printk("[%p] TX %.2x (%zu bytes)",
|
||||
__entry->priv,
|
||||
((u8 *)__get_dynamic_array(buf0))[0],
|
||||
TP_printk("[%s] TX %.2x (%zu bytes)",
|
||||
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
|
||||
__entry->framelen)
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_error,
|
||||
TP_PROTO(void *priv, u32 desc, u32 tsf_low,
|
||||
TP_PROTO(const struct device *dev, u32 desc, u32 tsf_low,
|
||||
u32 data1, u32 data2, u32 line, u32 blink1,
|
||||
u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
|
||||
u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
|
||||
u32 brd_ver),
|
||||
TP_ARGS(priv, desc, tsf_low, data1, data2, line,
|
||||
TP_ARGS(dev, desc, tsf_low, data1, data2, line,
|
||||
blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
|
||||
gp3, ucode_ver, hw_ver, brd_ver),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
__field(u32, desc)
|
||||
__field(u32, tsf_low)
|
||||
__field(u32, data1)
|
||||
@ -332,7 +335,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
|
||||
__field(u32, brd_ver)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->desc = desc;
|
||||
__entry->tsf_low = tsf_low;
|
||||
__entry->data1 = data1;
|
||||
@ -350,11 +353,11 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
|
||||
__entry->hw_ver = hw_ver;
|
||||
__entry->brd_ver = brd_ver;
|
||||
),
|
||||
TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
|
||||
TP_printk("[%s] #%02d %010u data 0x%08X 0x%08X line %u, "
|
||||
"blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
|
||||
"bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
|
||||
"hw 0x%08X brd 0x%08X",
|
||||
__entry->priv, __entry->desc, __entry->tsf_low,
|
||||
__get_str(dev), __entry->desc, __entry->tsf_low,
|
||||
__entry->data1,
|
||||
__entry->data2, __entry->line, __entry->blink1,
|
||||
__entry->blink2, __entry->ilink1, __entry->ilink2,
|
||||
@ -364,23 +367,23 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
|
||||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_ucode_event,
|
||||
TP_PROTO(void *priv, u32 time, u32 data, u32 ev),
|
||||
TP_ARGS(priv, time, data, ev),
|
||||
TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
|
||||
TP_ARGS(dev, time, data, ev),
|
||||
TP_STRUCT__entry(
|
||||
PRIV_ENTRY
|
||||
DEV_ENTRY
|
||||
|
||||
__field(u32, time)
|
||||
__field(u32, data)
|
||||
__field(u32, ev)
|
||||
),
|
||||
TP_fast_assign(
|
||||
PRIV_ASSIGN;
|
||||
DEV_ASSIGN;
|
||||
__entry->time = time;
|
||||
__entry->data = data;
|
||||
__entry->ev = ev;
|
||||
),
|
||||
TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
|
||||
__entry->priv, __entry->time, __entry->data, __entry->ev)
|
||||
TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
|
||||
__get_str(dev), __entry->time, __entry->data, __entry->ev)
|
||||
);
|
||||
#endif /* __IWLWIFI_DEVICE_TRACE */
|
||||
|
||||
|
@ -61,33 +61,686 @@
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <linux/completion.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "iwl-drv.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-op-mode.h"
|
||||
|
||||
int iwl_drv_start(struct iwl_shared *shrd,
|
||||
struct iwl_trans *trans, struct iwl_cfg *cfg)
|
||||
/* private includes */
|
||||
#include "iwl-fw-file.h"
|
||||
|
||||
/**
|
||||
* struct iwl_drv - drv common data
|
||||
* @fw: the iwl_fw structure
|
||||
* @shrd: pointer to common shared structure
|
||||
* @op_mode: the running op_mode
|
||||
* @fw_index: firmware revision to try loading
|
||||
* @firmware_name: composite filename of ucode file to load
|
||||
* @request_firmware_complete: the firmware has been obtained from user space
|
||||
*/
|
||||
struct iwl_drv {
|
||||
struct iwl_fw fw;
|
||||
|
||||
struct iwl_shared *shrd;
|
||||
struct iwl_op_mode *op_mode;
|
||||
|
||||
int fw_index; /* firmware we're trying to load */
|
||||
char firmware_name[25]; /* name of firmware file to load */
|
||||
|
||||
struct completion request_firmware_complete;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
|
||||
{
|
||||
if (desc->v_addr)
|
||||
dma_free_coherent(trans(drv)->dev, desc->len,
|
||||
desc->v_addr, desc->p_addr);
|
||||
desc->v_addr = NULL;
|
||||
desc->len = 0;
|
||||
}
|
||||
|
||||
static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
|
||||
{
|
||||
iwl_free_fw_desc(drv, &img->code);
|
||||
iwl_free_fw_desc(drv, &img->data);
|
||||
}
|
||||
|
||||
static void iwl_dealloc_ucode(struct iwl_drv *drv)
|
||||
{
|
||||
iwl_free_fw_img(drv, &drv->fw.ucode_rt);
|
||||
iwl_free_fw_img(drv, &drv->fw.ucode_init);
|
||||
iwl_free_fw_img(drv, &drv->fw.ucode_wowlan);
|
||||
}
|
||||
|
||||
static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
|
||||
const void *data, size_t len)
|
||||
{
|
||||
if (!len) {
|
||||
desc->v_addr = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
desc->v_addr = dma_alloc_coherent(trans(drv)->dev, len,
|
||||
&desc->p_addr, GFP_KERNEL);
|
||||
if (!desc->v_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
desc->len = len;
|
||||
memcpy(desc->v_addr, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
|
||||
#define UCODE_EXPERIMENTAL_INDEX 100
|
||||
#define UCODE_EXPERIMENTAL_TAG "exp"
|
||||
|
||||
static int iwl_request_firmware(struct iwl_drv *drv, bool first)
|
||||
{
|
||||
const struct iwl_cfg *cfg = cfg(drv);
|
||||
const char *name_pre = cfg->fw_name_pre;
|
||||
char tag[8];
|
||||
|
||||
if (first) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
|
||||
drv->fw_index = UCODE_EXPERIMENTAL_INDEX;
|
||||
strcpy(tag, UCODE_EXPERIMENTAL_TAG);
|
||||
} else if (drv->fw_index == UCODE_EXPERIMENTAL_INDEX) {
|
||||
#endif
|
||||
drv->fw_index = cfg->ucode_api_max;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
} else {
|
||||
drv->fw_index--;
|
||||
sprintf(tag, "%d", drv->fw_index);
|
||||
}
|
||||
|
||||
if (drv->fw_index < cfg->ucode_api_min) {
|
||||
IWL_ERR(drv, "no suitable firmware found!\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
sprintf(drv->firmware_name, "%s%s%s", name_pre, tag, ".ucode");
|
||||
|
||||
IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n",
|
||||
(drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? "EXPERIMENTAL " : "",
|
||||
drv->firmware_name);
|
||||
|
||||
return request_firmware_nowait(THIS_MODULE, 1, drv->firmware_name,
|
||||
trans(drv)->dev,
|
||||
GFP_KERNEL, drv, iwl_ucode_callback);
|
||||
}
|
||||
|
||||
struct iwlagn_firmware_pieces {
|
||||
const void *inst, *data, *init, *init_data, *wowlan_inst, *wowlan_data;
|
||||
size_t inst_size, data_size, init_size, init_data_size,
|
||||
wowlan_inst_size, wowlan_data_size;
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
};
|
||||
|
||||
static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces)
|
||||
{
|
||||
struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
|
||||
u32 api_ver, hdr_size, build;
|
||||
char buildstr[25];
|
||||
const u8 *src;
|
||||
|
||||
drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
|
||||
api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
|
||||
|
||||
switch (api_ver) {
|
||||
default:
|
||||
hdr_size = 28;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(drv, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
build = le32_to_cpu(ucode->u.v2.build);
|
||||
pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
|
||||
pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
|
||||
pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
|
||||
pieces->init_data_size =
|
||||
le32_to_cpu(ucode->u.v2.init_data_size);
|
||||
src = ucode->u.v2.data;
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
hdr_size = 24;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(drv, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
build = 0;
|
||||
pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
|
||||
pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
|
||||
pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
|
||||
pieces->init_data_size =
|
||||
le32_to_cpu(ucode->u.v1.init_data_size);
|
||||
src = ucode->u.v1.data;
|
||||
break;
|
||||
}
|
||||
|
||||
if (build)
|
||||
sprintf(buildstr, " build %u%s", build,
|
||||
(drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? " (EXP)" : "");
|
||||
else
|
||||
buildstr[0] = '\0';
|
||||
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%u.%u.%u%s",
|
||||
IWL_UCODE_MAJOR(drv->fw.ucode_ver),
|
||||
IWL_UCODE_MINOR(drv->fw.ucode_ver),
|
||||
IWL_UCODE_API(drv->fw.ucode_ver),
|
||||
IWL_UCODE_SERIAL(drv->fw.ucode_ver),
|
||||
buildstr);
|
||||
|
||||
/* Verify size of file vs. image size info in file's header */
|
||||
if (ucode_raw->size != hdr_size + pieces->inst_size +
|
||||
pieces->data_size + pieces->init_size +
|
||||
pieces->init_data_size) {
|
||||
|
||||
IWL_ERR(drv,
|
||||
"uCode file size %d does not match expected size\n",
|
||||
(int)ucode_raw->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pieces->inst = src;
|
||||
src += pieces->inst_size;
|
||||
pieces->data = src;
|
||||
src += pieces->data_size;
|
||||
pieces->init = src;
|
||||
src += pieces->init_size;
|
||||
pieces->init_data = src;
|
||||
src += pieces->init_data_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces,
|
||||
struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
|
||||
struct iwl_ucode_tlv *tlv;
|
||||
size_t len = ucode_raw->size;
|
||||
const u8 *data;
|
||||
int wanted_alternative = iwlagn_mod_params.wanted_ucode_alternative;
|
||||
int tmp;
|
||||
u64 alternatives;
|
||||
u32 tlv_len;
|
||||
enum iwl_ucode_tlv_type tlv_type;
|
||||
const u8 *tlv_data;
|
||||
char buildstr[25];
|
||||
u32 build;
|
||||
|
||||
if (len < sizeof(*ucode)) {
|
||||
IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC)) {
|
||||
IWL_ERR(drv, "invalid uCode magic: 0X%x\n",
|
||||
le32_to_cpu(ucode->magic));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check which alternatives are present, and "downgrade"
|
||||
* when the chosen alternative is not present, warning
|
||||
* the user when that happens. Some files may not have
|
||||
* any alternatives, so don't warn in that case.
|
||||
*/
|
||||
alternatives = le64_to_cpu(ucode->alternatives);
|
||||
tmp = wanted_alternative;
|
||||
if (wanted_alternative > 63)
|
||||
wanted_alternative = 63;
|
||||
while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
|
||||
wanted_alternative--;
|
||||
if (wanted_alternative && wanted_alternative != tmp)
|
||||
IWL_WARN(drv,
|
||||
"uCode alternative %d not available, choosing %d\n",
|
||||
tmp, wanted_alternative);
|
||||
|
||||
drv->fw.ucode_ver = le32_to_cpu(ucode->ver);
|
||||
build = le32_to_cpu(ucode->build);
|
||||
|
||||
if (build)
|
||||
sprintf(buildstr, " build %u%s", build,
|
||||
(drv->fw_index == UCODE_EXPERIMENTAL_INDEX)
|
||||
? " (EXP)" : "");
|
||||
else
|
||||
buildstr[0] = '\0';
|
||||
|
||||
snprintf(drv->fw.fw_version,
|
||||
sizeof(drv->fw.fw_version),
|
||||
"%u.%u.%u.%u%s",
|
||||
IWL_UCODE_MAJOR(drv->fw.ucode_ver),
|
||||
IWL_UCODE_MINOR(drv->fw.ucode_ver),
|
||||
IWL_UCODE_API(drv->fw.ucode_ver),
|
||||
IWL_UCODE_SERIAL(drv->fw.ucode_ver),
|
||||
buildstr);
|
||||
|
||||
data = ucode->data;
|
||||
|
||||
len -= sizeof(*ucode);
|
||||
|
||||
while (len >= sizeof(*tlv)) {
|
||||
u16 tlv_alt;
|
||||
|
||||
len -= sizeof(*tlv);
|
||||
tlv = (void *)data;
|
||||
|
||||
tlv_len = le32_to_cpu(tlv->length);
|
||||
tlv_type = le16_to_cpu(tlv->type);
|
||||
tlv_alt = le16_to_cpu(tlv->alternative);
|
||||
tlv_data = tlv->data;
|
||||
|
||||
if (len < tlv_len) {
|
||||
IWL_ERR(drv, "invalid TLV len: %zd/%u\n",
|
||||
len, tlv_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
|
||||
/*
|
||||
* Alternative 0 is always valid.
|
||||
*
|
||||
* Skip alternative TLVs that are not selected.
|
||||
*/
|
||||
if (tlv_alt != 0 && tlv_alt != wanted_alternative)
|
||||
continue;
|
||||
|
||||
switch (tlv_type) {
|
||||
case IWL_UCODE_TLV_INST:
|
||||
pieces->inst = tlv_data;
|
||||
pieces->inst_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_DATA:
|
||||
pieces->data = tlv_data;
|
||||
pieces->data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT:
|
||||
pieces->init = tlv_data;
|
||||
pieces->init_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_DATA:
|
||||
pieces->init_data = tlv_data;
|
||||
pieces->init_data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_BOOT:
|
||||
IWL_ERR(drv, "Found unexpected BOOT ucode\n");
|
||||
break;
|
||||
case IWL_UCODE_TLV_PROBE_MAX_LEN:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
capa->max_probe_length =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_PAN:
|
||||
if (tlv_len)
|
||||
goto invalid_tlv_len;
|
||||
capa->flags |= IWL_UCODE_TLV_FLAGS_PAN;
|
||||
break;
|
||||
case IWL_UCODE_TLV_FLAGS:
|
||||
/* must be at least one u32 */
|
||||
if (tlv_len < sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
/* and a proper number of u32s */
|
||||
if (tlv_len % sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
/*
|
||||
* This driver only reads the first u32 as
|
||||
* right now no more features are defined,
|
||||
* if that changes then either the driver
|
||||
* will not work with the new firmware, or
|
||||
* it'll not take advantage of new features.
|
||||
*/
|
||||
capa->flags = le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_EVTLOG_PTR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->init_evtlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_EVTLOG_SIZE:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->init_evtlog_size =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_ERRLOG_PTR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->init_errlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_EVTLOG_PTR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->inst_evtlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->inst_evtlog_size =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_RUNT_ERRLOG_PTR:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
pieces->inst_errlog_ptr =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
case IWL_UCODE_TLV_ENHANCE_SENS_TBL:
|
||||
if (tlv_len)
|
||||
goto invalid_tlv_len;
|
||||
drv->fw.enhance_sensitivity_table = true;
|
||||
break;
|
||||
case IWL_UCODE_TLV_WOWLAN_INST:
|
||||
pieces->wowlan_inst = tlv_data;
|
||||
pieces->wowlan_inst_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_WOWLAN_DATA:
|
||||
pieces->wowlan_data = tlv_data;
|
||||
pieces->wowlan_data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE:
|
||||
if (tlv_len != sizeof(u32))
|
||||
goto invalid_tlv_len;
|
||||
capa->standard_phy_calibration_size =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len) {
|
||||
IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
|
||||
iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_tlv_len:
|
||||
IWL_ERR(drv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len);
|
||||
iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_ucode_callback - callback when firmware was loaded
|
||||
*
|
||||
* If loaded successfully, copies the firmware into buffers
|
||||
* for the card to fetch (via DMA).
|
||||
*/
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
{
|
||||
struct iwl_drv *drv = context;
|
||||
const struct iwl_cfg *cfg = cfg(drv);
|
||||
struct iwl_fw *fw = &drv->fw;
|
||||
struct iwl_ucode_header *ucode;
|
||||
int err;
|
||||
struct iwlagn_firmware_pieces pieces;
|
||||
const unsigned int api_max = cfg->ucode_api_max;
|
||||
unsigned int api_ok = cfg->ucode_api_ok;
|
||||
const unsigned int api_min = cfg->ucode_api_min;
|
||||
u32 api_ver;
|
||||
|
||||
fw->ucode_capa.max_probe_length = 200;
|
||||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
|
||||
if (!api_ok)
|
||||
api_ok = api_max;
|
||||
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
|
||||
if (!ucode_raw) {
|
||||
if (drv->fw_index <= api_ok)
|
||||
IWL_ERR(drv,
|
||||
"request for firmware file '%s' failed.\n",
|
||||
drv->firmware_name);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(drv, "Loaded firmware file '%s' (%zd bytes).\n",
|
||||
drv->firmware_name, ucode_raw->size);
|
||||
|
||||
/* Make sure that we got at least the API version number */
|
||||
if (ucode_raw->size < 4) {
|
||||
IWL_ERR(drv, "File size way too small!\n");
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* Data from ucode file: header followed by uCode images */
|
||||
ucode = (struct iwl_ucode_header *)ucode_raw->data;
|
||||
|
||||
if (ucode->ver)
|
||||
err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces);
|
||||
else
|
||||
err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces,
|
||||
&fw->ucode_capa);
|
||||
|
||||
if (err)
|
||||
goto try_again;
|
||||
|
||||
api_ver = IWL_UCODE_API(drv->fw.ucode_ver);
|
||||
|
||||
/*
|
||||
* api_ver should match the api version forming part of the
|
||||
* firmware filename ... but we don't check for that and only rely
|
||||
* on the API version read from firmware header from here on forward
|
||||
*/
|
||||
/* no api version check required for experimental uCode */
|
||||
if (drv->fw_index != UCODE_EXPERIMENTAL_INDEX) {
|
||||
if (api_ver < api_min || api_ver > api_max) {
|
||||
IWL_ERR(drv,
|
||||
"Driver unable to support your firmware API. "
|
||||
"Driver supports v%u, firmware is v%u.\n",
|
||||
api_max, api_ver);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (api_ver < api_ok) {
|
||||
if (api_ok != api_max)
|
||||
IWL_ERR(drv, "Firmware has old API version, "
|
||||
"expected v%u through v%u, got v%u.\n",
|
||||
api_ok, api_max, api_ver);
|
||||
else
|
||||
IWL_ERR(drv, "Firmware has old API version, "
|
||||
"expected v%u, got v%u.\n",
|
||||
api_max, api_ver);
|
||||
IWL_ERR(drv, "New firmware can be obtained from "
|
||||
"http://www.intellinuxwireless.org/.\n");
|
||||
}
|
||||
}
|
||||
|
||||
IWL_INFO(drv, "loaded firmware version %s", drv->fw.fw_version);
|
||||
|
||||
/*
|
||||
* For any of the failures below (before allocating pci memory)
|
||||
* we will try to load a version with a smaller API -- maybe the
|
||||
* user just got a corrupted version of the latest API.
|
||||
*/
|
||||
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
drv->fw.ucode_ver);
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
|
||||
pieces.inst_size);
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
|
||||
pieces.data_size);
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
|
||||
pieces.init_size);
|
||||
IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
|
||||
pieces.init_data_size);
|
||||
|
||||
/* Verify that uCode images will fit in card's SRAM */
|
||||
if (pieces.inst_size > cfg->max_inst_size) {
|
||||
IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
|
||||
pieces.inst_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.data_size > cfg->max_data_size) {
|
||||
IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
|
||||
pieces.data_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.init_size > cfg->max_inst_size) {
|
||||
IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
|
||||
pieces.init_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (pieces.init_data_size > cfg->max_data_size) {
|
||||
IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
|
||||
pieces.init_data_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
/* Allocate ucode buffers for card's bus-master loading ... */
|
||||
|
||||
/* Runtime instructions and 2 copies of data:
|
||||
* 1) unmodified from disk
|
||||
* 2) backup cache for save/restore during power-downs */
|
||||
if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.code,
|
||||
pieces.inst, pieces.inst_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(drv, &drv->fw.ucode_rt.data,
|
||||
pieces.data, pieces.data_size))
|
||||
goto err_pci_alloc;
|
||||
|
||||
/* Initialization instructions and data */
|
||||
if (pieces.init_size && pieces.init_data_size) {
|
||||
if (iwl_alloc_fw_desc(drv,
|
||||
&drv->fw.ucode_init.code,
|
||||
pieces.init, pieces.init_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(drv,
|
||||
&drv->fw.ucode_init.data,
|
||||
pieces.init_data, pieces.init_data_size))
|
||||
goto err_pci_alloc;
|
||||
}
|
||||
|
||||
/* WoWLAN instructions and data */
|
||||
if (pieces.wowlan_inst_size && pieces.wowlan_data_size) {
|
||||
if (iwl_alloc_fw_desc(drv,
|
||||
&drv->fw.ucode_wowlan.code,
|
||||
pieces.wowlan_inst,
|
||||
pieces.wowlan_inst_size))
|
||||
goto err_pci_alloc;
|
||||
if (iwl_alloc_fw_desc(drv,
|
||||
&drv->fw.ucode_wowlan.data,
|
||||
pieces.wowlan_data,
|
||||
pieces.wowlan_data_size))
|
||||
goto err_pci_alloc;
|
||||
}
|
||||
|
||||
/* Now that we can no longer fail, copy information */
|
||||
|
||||
/*
|
||||
* The (size - 16) / 12 formula is based on the information recorded
|
||||
* for each event, which is of mode 1 (including timestamp) for all
|
||||
* new microcodes that include this information.
|
||||
*/
|
||||
fw->init_evtlog_ptr = pieces.init_evtlog_ptr;
|
||||
if (pieces.init_evtlog_size)
|
||||
fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->init_evtlog_size =
|
||||
cfg->base_params->max_event_log_size;
|
||||
fw->init_errlog_ptr = pieces.init_errlog_ptr;
|
||||
fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
|
||||
if (pieces.inst_evtlog_size)
|
||||
fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
|
||||
else
|
||||
fw->inst_evtlog_size =
|
||||
cfg->base_params->max_event_log_size;
|
||||
fw->inst_errlog_ptr = pieces.inst_errlog_ptr;
|
||||
|
||||
/*
|
||||
* figure out the offset of chain noise reset and gain commands
|
||||
* base on the size of standard phy calibration commands table size
|
||||
*/
|
||||
if (fw->ucode_capa.standard_phy_calibration_size >
|
||||
IWL_MAX_PHY_CALIBRATE_TBL_SIZE)
|
||||
fw->ucode_capa.standard_phy_calibration_size =
|
||||
IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE;
|
||||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&drv->request_firmware_complete);
|
||||
|
||||
drv->op_mode = iwl_dvm_ops.start(drv->shrd->trans, &drv->fw);
|
||||
|
||||
if (!drv->op_mode)
|
||||
goto out_unbind;
|
||||
|
||||
return;
|
||||
|
||||
try_again:
|
||||
/* try next, if any */
|
||||
release_firmware(ucode_raw);
|
||||
if (iwl_request_firmware(drv, false))
|
||||
goto out_unbind;
|
||||
return;
|
||||
|
||||
err_pci_alloc:
|
||||
IWL_ERR(drv, "failed to allocate pci memory\n");
|
||||
iwl_dealloc_ucode(drv);
|
||||
release_firmware(ucode_raw);
|
||||
out_unbind:
|
||||
complete(&drv->request_firmware_complete);
|
||||
device_release_driver(trans(drv)->dev);
|
||||
}
|
||||
|
||||
int iwl_drv_start(struct iwl_shared *shrd,
|
||||
struct iwl_trans *trans, const struct iwl_cfg *cfg)
|
||||
{
|
||||
struct iwl_drv *drv;
|
||||
int ret;
|
||||
|
||||
shrd->cfg = cfg;
|
||||
|
||||
shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL);
|
||||
if (!shrd->nic) {
|
||||
dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic");
|
||||
drv = kzalloc(sizeof(*drv), GFP_KERNEL);
|
||||
if (!drv) {
|
||||
dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
|
||||
return -ENOMEM;
|
||||
}
|
||||
shrd->nic->shrd = shrd;
|
||||
drv->shrd = shrd;
|
||||
shrd->drv = drv;
|
||||
|
||||
init_completion(&shrd->nic->request_firmware_complete);
|
||||
init_completion(&drv->request_firmware_complete);
|
||||
|
||||
ret = iwl_request_firmware(shrd->nic, true);
|
||||
ret = iwl_request_firmware(drv, true);
|
||||
|
||||
if (ret) {
|
||||
dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
|
||||
kfree(shrd->nic);
|
||||
kfree(drv);
|
||||
shrd->drv = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -95,9 +748,16 @@ int iwl_drv_start(struct iwl_shared *shrd,
|
||||
|
||||
void iwl_drv_stop(struct iwl_shared *shrd)
|
||||
{
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (shrd->nic->op_mode)
|
||||
iwl_op_mode_stop(shrd->nic->op_mode);
|
||||
struct iwl_drv *drv = shrd->drv;
|
||||
|
||||
kfree(shrd->nic);
|
||||
wait_for_completion(&drv->request_firmware_complete);
|
||||
|
||||
/* op_mode can be NULL if its start failed */
|
||||
if (drv->op_mode)
|
||||
iwl_op_mode_stop(drv->op_mode);
|
||||
|
||||
iwl_dealloc_ucode(drv);
|
||||
|
||||
kfree(drv);
|
||||
shrd->drv = NULL;
|
||||
}
|
||||
|
@ -105,7 +105,7 @@
|
||||
* function.
|
||||
*/
|
||||
int iwl_drv_start(struct iwl_shared *shrd,
|
||||
struct iwl_trans *trans, struct iwl_cfg *cfg);
|
||||
struct iwl_trans *trans, const struct iwl_cfg *cfg);
|
||||
|
||||
/**
|
||||
* iwl_drv_stop - stop the drv
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
/************************** EEPROM BANDS ****************************
|
||||
*
|
||||
@ -252,46 +253,46 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
|
||||
|
||||
}
|
||||
|
||||
int iwl_eeprom_check_sku(struct iwl_priv *priv)
|
||||
int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
u16 radio_cfg;
|
||||
|
||||
if (!cfg(priv)->sku) {
|
||||
/* not using sku overwrite */
|
||||
cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
|
||||
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||
!cfg(priv)->ht_params) {
|
||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
|
||||
if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||
!cfg(priv)->ht_params) {
|
||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!cfg(priv)->sku) {
|
||||
|
||||
if (!hw_params(priv).sku) {
|
||||
IWL_ERR(priv, "Invalid device sku\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_INFO(priv, "Device SKU: 0x%X\n", cfg(priv)->sku);
|
||||
IWL_INFO(priv, "Device SKU: 0x%X\n", hw_params(priv).sku);
|
||||
|
||||
if (!cfg(priv)->valid_tx_ant && !cfg(priv)->valid_rx_ant) {
|
||||
/* not using .cfg overwrite */
|
||||
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
|
||||
cfg(priv)->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) {
|
||||
IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
|
||||
cfg(priv)->valid_tx_ant,
|
||||
cfg(priv)->valid_rx_ant);
|
||||
return -EINVAL;
|
||||
}
|
||||
IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
|
||||
cfg(priv)->valid_tx_ant, cfg(priv)->valid_rx_ant);
|
||||
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
|
||||
|
||||
hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
hw_params(priv).valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
|
||||
/* check overrides (some devices have wrong EEPROM) */
|
||||
if (cfg(priv)->valid_tx_ant)
|
||||
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
|
||||
if (cfg(priv)->valid_rx_ant)
|
||||
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
|
||||
|
||||
if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) {
|
||||
IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n",
|
||||
hw_params(priv).valid_tx_ant,
|
||||
hw_params(priv).valid_rx_ant);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
* for some special cases,
|
||||
* EEPROM did not reflect the correct antenna setting
|
||||
* so overwrite the valid tx/rx antenna from .cfg
|
||||
*/
|
||||
|
||||
IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
|
||||
hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -512,7 +513,7 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_cfg *cfg,
|
||||
static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
@ -588,7 +589,7 @@ iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
|
||||
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
|
||||
@ -1024,8 +1025,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
||||
* driver need to process addition information
|
||||
* to determine the max channel tx power limits
|
||||
*/
|
||||
if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower)
|
||||
cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv);
|
||||
if (cfg(priv)->lib->eeprom_ops.enhanced_txpower)
|
||||
iwl_eeprom_enhanced_txpower(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -302,14 +302,14 @@ extern const u8 iwl_eeprom_band_1[14];
|
||||
|
||||
struct iwl_eeprom_ops {
|
||||
const u32 regulatory_bands[7];
|
||||
void (*update_enhanced_txpower) (struct iwl_priv *priv);
|
||||
bool enhanced_txpower;
|
||||
};
|
||||
|
||||
|
||||
int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev);
|
||||
void iwl_eeprom_free(struct iwl_shared *shrd);
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv);
|
||||
int iwl_eeprom_check_sku(struct iwl_priv *priv);
|
||||
int iwl_eeprom_init_hw_params(struct iwl_priv *priv);
|
||||
const u8 *iwl_eeprom_query_addr(const struct iwl_shared *shrd, size_t offset);
|
||||
u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
|
||||
int iwl_init_channel_map(struct iwl_priv *priv);
|
||||
|
@ -60,8 +60,8 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_ucode_h__
|
||||
#define __iwl_ucode_h__
|
||||
#ifndef __iwl_fw_file_h__
|
||||
#define __iwl_fw_file_h__
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
@ -126,22 +126,6 @@ enum iwl_ucode_tlv_type {
|
||||
IWL_UCODE_TLV_FLAGS = 18,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_ucode_tlv_flag - ucode API flags
|
||||
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
|
||||
* was a separate TLV but moved here to save space.
|
||||
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
|
||||
* treats good CRC threshold as a boolean
|
||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
|
||||
*/
|
||||
enum iwl_ucode_tlv_flag {
|
||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
|
||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
|
||||
};
|
||||
|
||||
struct iwl_ucode_tlv {
|
||||
__le16 type; /* see above */
|
||||
__le16 alternative; /* see comment */
|
||||
@ -173,48 +157,4 @@ struct iwl_tlv_ucode_header {
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
struct iwl_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
u32 standard_phy_calibration_size;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/* one for each uCode image (inst/data, boot/init/runtime) */
|
||||
struct fw_desc {
|
||||
dma_addr_t p_addr; /* hardware address */
|
||||
void *v_addr; /* software address */
|
||||
u32 len; /* size in bytes */
|
||||
};
|
||||
|
||||
struct fw_img {
|
||||
struct fw_desc code; /* firmware code image */
|
||||
struct fw_desc data; /* firmware data image */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
* @ucode_ver: ucode version from the ucode file
|
||||
* @fw_version: firmware version string
|
||||
* @ucode_rt: run time ucode image
|
||||
* @ucode_init: init ucode image
|
||||
* @ucode_wowlan: wake on wireless ucode image (optional)
|
||||
* @ucode_capa: capabilities parsed from the ucode file.
|
||||
* @enhance_sensitivity_table: device can do enhanced sensitivity.
|
||||
*/
|
||||
struct iwl_fw {
|
||||
|
||||
u32 ucode_ver;
|
||||
|
||||
char fw_version[ETHTOOL_BUSINFO_LEN];
|
||||
|
||||
/* ucode images */
|
||||
struct fw_img ucode_rt;
|
||||
struct fw_img ucode_init;
|
||||
struct fw_img ucode_wowlan;
|
||||
|
||||
struct iwl_ucode_capabilities ucode_capa;
|
||||
bool enhance_sensitivity_table;
|
||||
};
|
||||
|
||||
#endif /* __iwl_ucode_h__ */
|
||||
#endif /* __iwl_fw_file_h__ */
|
@ -60,52 +60,87 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_wifi_h__
|
||||
#define __iwl_wifi_h__
|
||||
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-ucode.h"
|
||||
|
||||
#define UCODE_EXPERIMENTAL_INDEX 100
|
||||
#ifndef __iwl_fw_h__
|
||||
#define __iwl_fw_h__
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* struct iwl_nic - nic common data
|
||||
* @fw: the iwl_fw structure
|
||||
* @shrd: pointer to common shared structure
|
||||
* @op_mode: the running op_mode
|
||||
* @fw_index: firmware revision to try loading
|
||||
* @firmware_name: composite filename of ucode file to load
|
||||
* enum iwl_ucode_tlv_flag - ucode API flags
|
||||
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
|
||||
* was a separate TLV but moved here to save space.
|
||||
* @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
|
||||
* treats good CRC threshold as a boolean
|
||||
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
|
||||
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
|
||||
*/
|
||||
enum iwl_ucode_tlv_flag {
|
||||
IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
|
||||
IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
|
||||
IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
|
||||
IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
|
||||
};
|
||||
|
||||
/* The default calibrate table size if not specified by firmware file */
|
||||
#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
|
||||
#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
|
||||
#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
|
||||
|
||||
struct iwl_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
u32 standard_phy_calibration_size;
|
||||
u32 flags;
|
||||
};
|
||||
|
||||
/* one for each uCode image (inst/data, boot/init/runtime) */
|
||||
struct fw_desc {
|
||||
dma_addr_t p_addr; /* hardware address */
|
||||
void *v_addr; /* software address */
|
||||
u32 len; /* size in bytes */
|
||||
};
|
||||
|
||||
struct fw_img {
|
||||
struct fw_desc code; /* firmware code image */
|
||||
struct fw_desc data; /* firmware data image */
|
||||
};
|
||||
|
||||
/* uCode version contains 4 values: Major/Minor/API/Serial */
|
||||
#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
|
||||
#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
|
||||
#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
|
||||
#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
|
||||
|
||||
/**
|
||||
* struct iwl_fw - variables associated with the firmware
|
||||
*
|
||||
* @ucode_ver: ucode version from the ucode file
|
||||
* @fw_version: firmware version string
|
||||
* @ucode_rt: run time ucode image
|
||||
* @ucode_init: init ucode image
|
||||
* @ucode_wowlan: wake on wireless ucode image (optional)
|
||||
* @ucode_capa: capabilities parsed from the ucode file.
|
||||
* @enhance_sensitivity_table: device can do enhanced sensitivity.
|
||||
* @init_evtlog_ptr: event log offset for init ucode.
|
||||
* @init_evtlog_size: event log size for init ucode.
|
||||
* @init_errlog_ptr: error log offfset for init ucode.
|
||||
* @inst_evtlog_ptr: event log offset for runtime ucode.
|
||||
* @inst_evtlog_size: event log size for runtime ucode.
|
||||
* @inst_errlog_ptr: error log offfset for runtime ucode.
|
||||
* @request_firmware_complete: the firmware has been obtained from user space
|
||||
*/
|
||||
struct iwl_nic {
|
||||
struct iwl_fw fw;
|
||||
struct iwl_fw {
|
||||
u32 ucode_ver;
|
||||
|
||||
struct iwl_shared *shrd;
|
||||
struct iwl_op_mode *op_mode;
|
||||
char fw_version[ETHTOOL_BUSINFO_LEN];
|
||||
|
||||
int fw_index; /* firmware we're trying to load */
|
||||
char firmware_name[25]; /* name of firmware file to load */
|
||||
/* ucode images */
|
||||
struct fw_img ucode_rt;
|
||||
struct fw_img ucode_init;
|
||||
struct fw_img ucode_wowlan;
|
||||
|
||||
struct iwl_ucode_capabilities ucode_capa;
|
||||
bool enhance_sensitivity_table;
|
||||
|
||||
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
|
||||
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
|
||||
|
||||
struct completion request_firmware_complete;
|
||||
};
|
||||
|
||||
|
||||
int __must_check iwl_request_firmware(struct iwl_nic *nic, bool first);
|
||||
void iwl_dealloc_ucode(struct iwl_nic *nic);
|
||||
|
||||
int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type);
|
||||
void iwl_send_prio_tbl(struct iwl_trans *trans);
|
||||
int iwl_init_alive_start(struct iwl_trans *trans);
|
||||
int iwl_run_init_ucode(struct iwl_trans *trans);
|
||||
int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
|
||||
enum iwl_ucode_type ucode_type);
|
||||
#endif /* __iwl_wifi_h__ */
|
||||
#endif /* __iwl_fw_h__ */
|
@ -118,16 +118,17 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwl_grab_nic_access(struct iwl_trans *trans)
|
||||
bool iwl_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
int ret = iwl_grab_nic_access_silent(trans);
|
||||
if (ret) {
|
||||
if (unlikely(ret)) {
|
||||
u32 val = iwl_read32(trans, CSR_GP_CNTRL);
|
||||
IWL_ERR(trans,
|
||||
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
|
||||
WARN_ONCE(1, "Timeout waiting for hardware access "
|
||||
"(CSR_GP_CNTRL 0x%08x)\n", val);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
void iwl_release_nic_access(struct iwl_trans *trans)
|
||||
@ -135,6 +136,13 @@ void iwl_release_nic_access(struct iwl_trans *trans)
|
||||
lockdep_assert_held(&trans->reg_lock);
|
||||
__iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
/*
|
||||
* Above we read the CSR_GP_CNTRL register, which will flush
|
||||
* any previous writes, but we need the write that clears the
|
||||
* MAC_ACCESS_REQ bit to be performed before any other writes
|
||||
* scheduled on different CPUs (after we drop reg_lock).
|
||||
*/
|
||||
mmiowb();
|
||||
}
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
@ -156,7 +164,7 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_grab_nic_access(trans)) {
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
iwl_write32(trans, reg, value);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
@ -181,7 +189,6 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
|
||||
rmb();
|
||||
return iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
|
||||
}
|
||||
|
||||
@ -189,7 +196,6 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
|
||||
{
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
((addr & 0x0000FFFF) | (3 << 24)));
|
||||
wmb();
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
}
|
||||
|
||||
@ -211,7 +217,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 addr, u32 val)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_grab_nic_access(trans)) {
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
__iwl_write_prph(trans, addr, val);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
@ -223,9 +229,11 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
__iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask);
|
||||
iwl_release_nic_access(trans);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
__iwl_write_prph(trans, reg,
|
||||
__iwl_read_prph(trans, reg) | mask);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
|
||||
@ -235,10 +243,11 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 reg,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
__iwl_write_prph(trans, reg,
|
||||
(__iwl_read_prph(trans, reg) & mask) | bits);
|
||||
iwl_release_nic_access(trans);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
__iwl_write_prph(trans, reg,
|
||||
(__iwl_read_prph(trans, reg) & mask) | bits);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
|
||||
@ -248,10 +257,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
val = __iwl_read_prph(trans, reg);
|
||||
__iwl_write_prph(trans, reg, (val & ~mask));
|
||||
iwl_release_nic_access(trans);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
val = __iwl_read_prph(trans, reg);
|
||||
__iwl_write_prph(trans, reg, (val & ~mask));
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
|
||||
@ -263,15 +273,12 @@ void _iwl_read_targ_mem_words(struct iwl_trans *trans, u32 addr,
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
|
||||
rmb();
|
||||
|
||||
for (offs = 0; offs < words; offs++)
|
||||
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
|
||||
iwl_release_nic_access(trans);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
|
||||
for (offs = 0; offs < words; offs++)
|
||||
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
|
||||
@ -292,10 +299,8 @@ int _iwl_write_targ_mem_words(struct iwl_trans *trans, u32 addr,
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_grab_nic_access(trans)) {
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
wmb();
|
||||
|
||||
for (offs = 0; offs < words; offs++)
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
|
||||
iwl_release_nic_access(trans);
|
||||
|
@ -35,20 +35,20 @@
|
||||
|
||||
static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite8(priv(trans), ofs, val);
|
||||
trace_iwlwifi_dev_iowrite8(trans->dev, ofs, val);
|
||||
iwl_trans_write8(trans, ofs, val);
|
||||
}
|
||||
|
||||
static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
trace_iwlwifi_dev_iowrite32(priv(trans), ofs, val);
|
||||
trace_iwlwifi_dev_iowrite32(trans->dev, ofs, val);
|
||||
iwl_trans_write32(trans, ofs, val);
|
||||
}
|
||||
|
||||
static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
u32 val = iwl_trans_read32(trans, ofs);
|
||||
trace_iwlwifi_dev_ioread32(priv(trans), ofs, val);
|
||||
trace_iwlwifi_dev_ioread32(trans->dev, ofs, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout);
|
||||
|
||||
int iwl_grab_nic_access_silent(struct iwl_trans *trans);
|
||||
int iwl_grab_nic_access(struct iwl_trans *trans);
|
||||
bool iwl_grab_nic_access(struct iwl_trans *trans);
|
||||
void iwl_release_nic_access(struct iwl_trans *trans);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
|
||||
|
@ -112,7 +112,7 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
||||
iwl_write32(trans(priv), CSR_LED_REG,
|
||||
reg & CSR_LED_BSM_CTRL_MSK);
|
||||
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
return iwl_dvm_send_cmd(priv, &cmd);
|
||||
}
|
||||
|
||||
/* Set led pattern command */
|
||||
@ -126,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
|
||||
};
|
||||
int ret;
|
||||
|
||||
if (!test_bit(STATUS_READY, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_READY, &priv->status))
|
||||
return -EBUSY;
|
||||
|
||||
if (priv->blink_on == on && priv->blink_off == off)
|
||||
|
@ -42,9 +42,7 @@
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include "iwl-ucode.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
@ -136,7 +134,7 @@ iwlagn_iface_combinations_p2p[] = {
|
||||
* other mac80211 functions grouped here.
|
||||
*/
|
||||
int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwl_ucode_capabilities *capa)
|
||||
const struct iwl_ucode_capabilities *capa)
|
||||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
@ -161,11 +159,14 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
|
||||
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_EXPERIMENTAL_MFP
|
||||
/* enable 11w if the uCode advertise */
|
||||
if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
|
||||
#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
|
||||
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
|
||||
|
||||
hw->sta_data_size = sizeof(struct iwl_station_priv);
|
||||
@ -195,7 +196,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
if (nic(priv)->fw.ucode_wowlan.code.len &&
|
||||
if (priv->fw->ucode_wowlan.code.len &&
|
||||
trans(priv)->ops->wowlan_suspend &&
|
||||
device_can_wakeup(trans(priv)->dev)) {
|
||||
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
|
||||
WIPHY_WOWLAN_DISCONNECT |
|
||||
@ -262,9 +264,9 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
struct iwl_rxon_context *ctx;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
|
||||
return -EIO;
|
||||
}
|
||||
@ -277,13 +279,13 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
}
|
||||
}
|
||||
|
||||
ret = iwl_run_init_ucode(trans(priv));
|
||||
ret = iwl_run_init_ucode(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = iwl_load_ucode_wait_alive(trans(priv), IWL_UCODE_REGULAR);
|
||||
ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
|
||||
goto error;
|
||||
@ -295,9 +297,9 @@ static int __iwl_up(struct iwl_priv *priv)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
iwl_down(priv);
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
IWL_ERR(priv, "Unable to initialize device.\n");
|
||||
return ret;
|
||||
@ -311,16 +313,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
/* we should be verifying the device is ready to be opened */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = __iwl_up(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Start UP work done.\n");
|
||||
|
||||
/* Now we should be done, and the READY bit should be set. */
|
||||
if (WARN_ON(!test_bit(STATUS_READY, &priv->shrd->status)))
|
||||
if (WARN_ON(!test_bit(STATUS_READY, &priv->status)))
|
||||
ret = -EIO;
|
||||
|
||||
iwlagn_led_enable(priv);
|
||||
@ -341,9 +343,9 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
|
||||
priv->is_open = 0;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_down(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
iwl_cancel_deferred_work(priv);
|
||||
|
||||
@ -368,7 +370,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
||||
return;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
|
||||
goto out;
|
||||
@ -380,7 +382,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
|
||||
priv->have_rekey_data = true;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
@ -397,7 +399,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/* Don't attempt WoWLAN when not associated, tear down instead. */
|
||||
if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
|
||||
@ -406,24 +408,22 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = iwlagn_suspend(priv, hw, wowlan);
|
||||
ret = iwlagn_suspend(priv, wowlan);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
device_set_wakeup_enable(trans(priv)->dev, true);
|
||||
|
||||
/* Now let the ucode operate on its own */
|
||||
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
iwl_trans_wowlan_suspend(trans(priv));
|
||||
|
||||
goto out;
|
||||
|
||||
error:
|
||||
priv->shrd->wowlan = false;
|
||||
priv->wowlan = false;
|
||||
iwlagn_prepare_restart(priv);
|
||||
ieee80211_restart_hw(priv->hw);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
@ -439,7 +439,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
int ret = -EIO;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
@ -448,7 +448,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
spin_lock_irqsave(&trans(priv)->reg_lock, flags);
|
||||
ret = iwl_grab_nic_access_silent(trans(priv));
|
||||
if (ret == 0) {
|
||||
if (likely(ret == 0)) {
|
||||
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base);
|
||||
status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
|
||||
iwl_release_nic_access(trans(priv));
|
||||
@ -457,17 +457,16 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
if (ret == 0) {
|
||||
struct iwl_nic *nic = nic(priv);
|
||||
if (!priv->wowlan_sram)
|
||||
priv->wowlan_sram =
|
||||
kzalloc(nic->fw.ucode_wowlan.data.len,
|
||||
kzalloc(priv->fw->ucode_wowlan.data.len,
|
||||
GFP_KERNEL);
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
_iwl_read_targ_mem_words(
|
||||
trans(priv), 0x800000,
|
||||
priv->wowlan_sram,
|
||||
nic->fw.ucode_wowlan.data.len / 4);
|
||||
priv->fw->ucode_wowlan.data.len / 4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -475,7 +474,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
/* we'll clear ctx->vif during iwlagn_prepare_restart() */
|
||||
vif = ctx->vif;
|
||||
|
||||
priv->shrd->wowlan = false;
|
||||
priv->wowlan = false;
|
||||
|
||||
device_set_wakeup_enable(trans(priv)->dev, false);
|
||||
|
||||
@ -485,7 +484,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
iwl_connection_init_rx_config(priv, ctx);
|
||||
iwlagn_set_rxon_chain(priv, ctx);
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
ieee80211_resume_disconnect(vif);
|
||||
@ -563,7 +562,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
|
||||
BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
|
||||
@ -614,7 +613,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
@ -633,11 +632,11 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
|
||||
sta->addr, tid);
|
||||
|
||||
if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE))
|
||||
if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE))
|
||||
return -EACCES;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
@ -649,8 +648,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
IWL_DEBUG_HT(priv, "stop Rx\n");
|
||||
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
ret = 0;
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
|
||||
@ -666,10 +663,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
|
||||
priv->agg_tids_count);
|
||||
}
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
ret = 0;
|
||||
if (!priv->agg_tids_count && cfg(priv)->ht_params &&
|
||||
cfg(priv)->ht_params->use_rts_for_aggregation) {
|
||||
if (!priv->agg_tids_count &&
|
||||
hw_params(priv).use_rts_for_aggregation) {
|
||||
/*
|
||||
* switch off RTS/CTS if it was previously enabled
|
||||
*/
|
||||
@ -683,7 +678,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
return ret;
|
||||
}
|
||||
@ -696,12 +691,9 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "received request to add station %pM\n",
|
||||
sta->addr);
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
|
||||
sta->addr);
|
||||
sta_priv->sta_id = IWL_INVALID_STATION;
|
||||
@ -716,17 +708,119 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
IWL_ERR(priv, "Unable to add station %pM (%d)\n",
|
||||
sta->addr, ret);
|
||||
/* Should we return success if return code is EEXIST ? */
|
||||
goto out;
|
||||
return ret;
|
||||
}
|
||||
|
||||
sta_priv->sta_id = sta_id;
|
||||
|
||||
/* Initialize rate scaling */
|
||||
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
|
||||
sta->addr);
|
||||
iwl_rs_rate_init(priv, sta, sta_id);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n", sta->addr);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
/*
|
||||
* Station will be removed from device when the RXON
|
||||
* is set to unassociated -- just deactivate it here
|
||||
* to avoid re-programming it.
|
||||
*/
|
||||
ret = 0;
|
||||
iwl_deactivate_station(priv, sta_priv->sta_id, sta->addr);
|
||||
} else {
|
||||
ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
|
||||
if (ret)
|
||||
IWL_DEBUG_QUIET_RFKILL(priv,
|
||||
"Error removing station %pM\n", sta->addr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_sta_state(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
enum ieee80211_sta_state old_state,
|
||||
enum ieee80211_sta_state new_state)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
enum {
|
||||
NONE, ADD, REMOVE, HT_RATE_INIT, ADD_RATE_INIT,
|
||||
} op = NONE;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "station %pM state change %d->%d\n",
|
||||
sta->addr, old_state, new_state);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||
new_state == IEEE80211_STA_NONE)
|
||||
op = ADD;
|
||||
else if (old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST)
|
||||
op = REMOVE;
|
||||
else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC)
|
||||
op = HT_RATE_INIT;
|
||||
} else {
|
||||
if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC)
|
||||
op = ADD_RATE_INIT;
|
||||
else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH)
|
||||
op = REMOVE;
|
||||
}
|
||||
|
||||
switch (op) {
|
||||
case ADD:
|
||||
ret = iwlagn_mac_sta_add(hw, vif, sta);
|
||||
break;
|
||||
case REMOVE:
|
||||
ret = iwlagn_mac_sta_remove(hw, vif, sta);
|
||||
break;
|
||||
case ADD_RATE_INIT:
|
||||
ret = iwlagn_mac_sta_add(hw, vif, sta);
|
||||
if (ret)
|
||||
break;
|
||||
/* Initialize rate scaling */
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Initializing rate scaling for station %pM\n",
|
||||
sta->addr);
|
||||
iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
|
||||
ret = 0;
|
||||
break;
|
||||
case HT_RATE_INIT:
|
||||
/* Initialize rate scaling */
|
||||
ret = iwl_sta_update_ht(priv, vif_priv->ctx, sta);
|
||||
if (ret)
|
||||
break;
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Initializing rate scaling for station %pM\n",
|
||||
sta->addr);
|
||||
iwl_rs_rate_init(priv, sta, iwl_sta_id(sta));
|
||||
ret = 0;
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* mac80211 might WARN if we fail, but due the way we
|
||||
* (badly) handle hard rfkill, we might fail here
|
||||
*/
|
||||
if (iwl_is_rfkill(priv))
|
||||
ret = 0;
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
@ -753,14 +847,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (iwl_is_rfkill(priv->shrd))
|
||||
if (iwl_is_rfkill(priv))
|
||||
goto out;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) ||
|
||||
test_bit(STATUS_SCANNING, &priv->shrd->status) ||
|
||||
test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
|
||||
test_bit(STATUS_SCANNING, &priv->status) ||
|
||||
test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
|
||||
goto out;
|
||||
|
||||
if (!iwl_is_associated_ctx(ctx))
|
||||
@ -779,8 +873,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irq(&priv->shrd->lock);
|
||||
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/* Configure HT40 channels */
|
||||
@ -797,23 +889,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
iwl_set_rxon_ht(priv, ht_conf);
|
||||
iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
|
||||
|
||||
spin_unlock_irq(&priv->shrd->lock);
|
||||
|
||||
iwl_set_rate(priv);
|
||||
/*
|
||||
* at this point, staging_rxon has the
|
||||
* configuration for channel switch
|
||||
*/
|
||||
set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
||||
set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
|
||||
priv->switch_channel = cpu_to_le16(ch);
|
||||
if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) {
|
||||
clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status);
|
||||
clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
|
||||
priv->switch_channel = 0;
|
||||
ieee80211_chswitch_done(ctx->vif, false);
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
@ -843,7 +933,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
#undef CHK
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
ctx->staging.filter_flags &= ~filter_nand;
|
||||
@ -855,7 +945,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
*/
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
/*
|
||||
* Receiving all multicast frames is always enabled by the
|
||||
@ -871,14 +961,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
|
||||
goto done;
|
||||
}
|
||||
if (iwl_is_rfkill(priv->shrd)) {
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
|
||||
goto done;
|
||||
}
|
||||
@ -897,7 +987,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
|
||||
iwl_trans_wait_tx_queue_empty(trans(priv));
|
||||
done:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
@ -917,9 +1007,9 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@ -988,7 +1078,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
|
||||
iwlagn_disable_roc(priv);
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return err;
|
||||
@ -1002,102 +1092,22 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
|
||||
iwlagn_disable_roc(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_tx_sync(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const u8 *bssid,
|
||||
enum ieee80211_tx_sync_type type)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
struct iwl_rxon_context *ctx = vif_priv->ctx;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
|
||||
if (ctx->ctxid != IWL_RXON_CTX_PAN)
|
||||
return 0;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
if (iwl_is_associated_ctx(ctx)) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ctx->preauth_bssid || test_bit(STATUS_SCAN_HW,
|
||||
&priv->shrd->status)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = iwl_add_station_common(priv, ctx, bssid, true, NULL, &sta_id);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (WARN_ON(sta_id != ctx->ap_sta_id)) {
|
||||
ret = -EIO;
|
||||
goto out_remove_sta;
|
||||
}
|
||||
|
||||
memcpy(ctx->bssid, bssid, ETH_ALEN);
|
||||
ctx->preauth_bssid = true;
|
||||
|
||||
ret = iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
out_remove_sta:
|
||||
iwl_remove_station(priv, sta_id, bssid);
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwlagn_mac_finish_tx_sync(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
const u8 *bssid,
|
||||
enum ieee80211_tx_sync_type type)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
struct iwl_rxon_context *ctx = vif_priv->ctx;
|
||||
|
||||
if (ctx->ctxid != IWL_RXON_CTX_PAN)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
if (iwl_is_associated_ctx(ctx))
|
||||
goto out;
|
||||
|
||||
iwl_remove_station(priv, ctx->ap_sta_id, bssid);
|
||||
ctx->preauth_bssid = false;
|
||||
/* no need to commit */
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
enum ieee80211_rssi_event rssi_event)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (cfg(priv)->bt_params &&
|
||||
cfg(priv)->bt_params->advanced_bt_coexist) {
|
||||
@ -1112,7 +1122,7 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
|
||||
"ignoring RSSI callback\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
@ -1133,7 +1143,6 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
struct iwl_rxon_context *ctx = vif_priv->ctx;
|
||||
unsigned long flags;
|
||||
int q;
|
||||
|
||||
if (WARN_ON(!ctx))
|
||||
@ -1141,7 +1150,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd)) {
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
|
||||
return -EIO;
|
||||
}
|
||||
@ -1153,7 +1162,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
|
||||
q = AC_NUM - 1 - queue;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
ctx->qos_data.def_qos_parm.ac[q].cw_min =
|
||||
cpu_to_le16(params->cw_min);
|
||||
@ -1165,7 +1174,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
|
||||
|
||||
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
return 0;
|
||||
@ -1193,7 +1202,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
int err;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/*
|
||||
* This variable will be correct only when there's just
|
||||
@ -1238,11 +1247,11 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
cancel_delayed_work_sync(&priv->hw_roc_disable_work);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
iwlagn_disable_roc(priv);
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd)) {
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_WARN(priv, "Try to add interface when device not ready\n");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@ -1285,7 +1294,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
|
||||
ctx->vif = NULL;
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
return err;
|
||||
@ -1297,7 +1306,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
|
||||
{
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (priv->scan_vif == vif) {
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
@ -1329,7 +1338,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (WARN_ON(ctx->vif != vif)) {
|
||||
struct iwl_rxon_context *tmp;
|
||||
@ -1342,7 +1351,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
iwl_teardown_interface(priv, vif, false);
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
@ -1364,9 +1373,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
||||
|
||||
newtype = ieee80211_iftype_p2p(newtype, newp2p);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (!ctx->vif || !iwl_is_ready_rf(priv->shrd)) {
|
||||
if (!ctx->vif || !iwl_is_ready_rf(priv)) {
|
||||
/*
|
||||
* Huh? But wait ... this can maybe happen when
|
||||
* we're in the middle of a firmware restart!
|
||||
@ -1428,7 +1437,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return err;
|
||||
@ -1446,7 +1455,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
if (req->n_channels == 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/*
|
||||
* If an internal scan is in progress, just set
|
||||
@ -1475,47 +1484,20 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter: received request to remove "
|
||||
"station %pM\n", sta->addr);
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
|
||||
sta->addr);
|
||||
ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
|
||||
if (ret)
|
||||
IWL_DEBUG_QUIET_RFKILL(priv, "Error removing station %pM\n",
|
||||
sta->addr);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->shrd->sta_lock, flags);
|
||||
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
|
||||
priv->stations[sta_id].sta.sta.modify_mask = 0;
|
||||
priv->stations[sta_id].sta.sleep_tx_count = 0;
|
||||
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
|
||||
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
struct iwl_addsta_cmd cmd = {
|
||||
.mode = STA_CONTROL_MODIFY_MSK,
|
||||
.station_flags_msk = STA_FLG_PWR_SAVE_MSK,
|
||||
.sta.sta_id = sta_id,
|
||||
};
|
||||
|
||||
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
|
||||
}
|
||||
|
||||
static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
@ -1572,8 +1554,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.ampdu_action = iwlagn_mac_ampdu_action,
|
||||
.hw_scan = iwlagn_mac_hw_scan,
|
||||
.sta_notify = iwlagn_mac_sta_notify,
|
||||
.sta_add = iwlagn_mac_sta_add,
|
||||
.sta_remove = iwlagn_mac_sta_remove,
|
||||
.sta_state = iwlagn_mac_sta_state,
|
||||
.channel_switch = iwlagn_mac_channel_switch,
|
||||
.flush = iwlagn_mac_flush,
|
||||
.tx_last_beacon = iwlagn_mac_tx_last_beacon,
|
||||
@ -1582,8 +1563,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.rssi_callback = iwlagn_mac_rssi_callback,
|
||||
CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
|
||||
CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump)
|
||||
.tx_sync = iwlagn_mac_tx_sync,
|
||||
.finish_tx_sync = iwlagn_mac_finish_tx_sync,
|
||||
.set_tim = iwlagn_mac_set_tim,
|
||||
};
|
||||
|
||||
|
157
drivers/net/wireless/iwlwifi/iwl-notif-wait.c
Normal file
157
drivers/net/wireless/iwlwifi/iwl-notif-wait.c
Normal file
@ -0,0 +1,157 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* 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
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "iwl-notif-wait.h"
|
||||
|
||||
|
||||
void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_wait)
|
||||
{
|
||||
spin_lock_init(¬if_wait->notif_wait_lock);
|
||||
INIT_LIST_HEAD(¬if_wait->notif_waits);
|
||||
init_waitqueue_head(¬if_wait->notif_waitq);
|
||||
}
|
||||
|
||||
void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
if (!list_empty(¬if_wait->notif_waits)) {
|
||||
struct iwl_notification_wait *w;
|
||||
|
||||
spin_lock(¬if_wait->notif_wait_lock);
|
||||
list_for_each_entry(w, ¬if_wait->notif_waits, list) {
|
||||
if (w->cmd != pkt->hdr.cmd)
|
||||
continue;
|
||||
w->triggered = true;
|
||||
if (w->fn)
|
||||
w->fn(notif_wait, pkt, w->fn_data);
|
||||
}
|
||||
spin_unlock(¬if_wait->notif_wait_lock);
|
||||
|
||||
wake_up_all(¬if_wait->notif_waitq);
|
||||
}
|
||||
}
|
||||
|
||||
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_notification_wait *wait_entry;
|
||||
|
||||
spin_lock_irqsave(¬if_wait->notif_wait_lock, flags);
|
||||
list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list)
|
||||
wait_entry->aborted = true;
|
||||
spin_unlock_irqrestore(¬if_wait->notif_wait_lock, flags);
|
||||
|
||||
wake_up_all(¬if_wait->notif_waitq);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
iwl_init_notification_wait(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
u8 cmd,
|
||||
void (*fn)(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_rx_packet *pkt, void *data),
|
||||
void *fn_data)
|
||||
{
|
||||
wait_entry->fn = fn;
|
||||
wait_entry->fn_data = fn_data;
|
||||
wait_entry->cmd = cmd;
|
||||
wait_entry->triggered = false;
|
||||
wait_entry->aborted = false;
|
||||
|
||||
spin_lock_bh(¬if_wait->notif_wait_lock);
|
||||
list_add(&wait_entry->list, ¬if_wait->notif_waits);
|
||||
spin_unlock_bh(¬if_wait->notif_wait_lock);
|
||||
}
|
||||
|
||||
int iwl_wait_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wait_event_timeout(notif_wait->notif_waitq,
|
||||
wait_entry->triggered || wait_entry->aborted,
|
||||
timeout);
|
||||
|
||||
spin_lock_bh(¬if_wait->notif_wait_lock);
|
||||
list_del(&wait_entry->list);
|
||||
spin_unlock_bh(¬if_wait->notif_wait_lock);
|
||||
|
||||
if (wait_entry->aborted)
|
||||
return -EIO;
|
||||
|
||||
/* return value is always >= 0 */
|
||||
if (ret <= 0)
|
||||
return -ETIMEDOUT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_remove_notification(struct iwl_notif_wait_data *notif_wait,
|
||||
struct iwl_notification_wait *wait_entry)
|
||||
{
|
||||
spin_lock_bh(¬if_wait->notif_wait_lock);
|
||||
list_del(&wait_entry->list);
|
||||
spin_unlock_bh(¬if_wait->notif_wait_lock);
|
||||
}
|
@ -41,7 +41,6 @@
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
@ -60,18 +59,71 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef __iwl_notif_wait_h__
|
||||
#define __iwl_notif_wait_h__
|
||||
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include "iwl-trans.h"
|
||||
|
||||
int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
||||
u32 flags, u16 len, const void *data)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = id,
|
||||
.len = { len, },
|
||||
.data = { data, },
|
||||
.flags = flags,
|
||||
};
|
||||
struct iwl_notif_wait_data {
|
||||
struct list_head notif_waits;
|
||||
spinlock_t notif_wait_lock;
|
||||
wait_queue_head_t notif_waitq;
|
||||
};
|
||||
|
||||
return iwl_trans_send_cmd(trans, &cmd);
|
||||
}
|
||||
/**
|
||||
* struct iwl_notification_wait - notification wait entry
|
||||
* @list: list head for global list
|
||||
* @fn: function called with the notification
|
||||
* @cmd: command ID
|
||||
*
|
||||
* This structure is not used directly, to wait for a
|
||||
* notification declare it on the stack, and call
|
||||
* iwlagn_init_notification_wait() with appropriate
|
||||
* parameters. Then do whatever will cause the ucode
|
||||
* to notify the driver, and to wait for that then
|
||||
* call iwlagn_wait_notification().
|
||||
*
|
||||
* Each notification is one-shot. If at some point we
|
||||
* need to support multi-shot notifications (which
|
||||
* can't be allocated on the stack) we need to modify
|
||||
* the code for them.
|
||||
*/
|
||||
struct iwl_notification_wait {
|
||||
struct list_head list;
|
||||
|
||||
void (*fn)(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_rx_packet *pkt, void *data);
|
||||
void *fn_data;
|
||||
|
||||
u8 cmd;
|
||||
bool triggered, aborted;
|
||||
};
|
||||
|
||||
|
||||
/* caller functions */
|
||||
void iwl_notification_wait_init(struct iwl_notif_wait_data *notif_data);
|
||||
void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_rx_packet *pkt);
|
||||
void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_data);
|
||||
|
||||
/* user functions */
|
||||
void __acquires(wait_entry)
|
||||
iwl_init_notification_wait(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
u8 cmd,
|
||||
void (*fn)(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_rx_packet *pkt, void *data),
|
||||
void *fn_data);
|
||||
|
||||
int __must_check __releases(wait_entry)
|
||||
iwl_wait_notification(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout);
|
||||
|
||||
void __releases(wait_entry)
|
||||
iwl_remove_notification(struct iwl_notif_wait_data *notif_data,
|
||||
struct iwl_notification_wait *wait_entry);
|
||||
|
||||
#endif /* __iwl_notif_wait_h__ */
|
@ -67,7 +67,8 @@ struct iwl_op_mode;
|
||||
struct iwl_trans;
|
||||
struct sk_buff;
|
||||
struct iwl_device_cmd;
|
||||
struct iwl_rx_mem_buffer;
|
||||
struct iwl_rx_cmd_buffer;
|
||||
struct iwl_fw;
|
||||
|
||||
/**
|
||||
* DOC: Operational mode - what is it ?
|
||||
@ -121,17 +122,23 @@ struct iwl_rx_mem_buffer;
|
||||
* there are Tx packets pending in the transport layer.
|
||||
* Must be atomic
|
||||
* @nic_error: error notification. Must be atomic
|
||||
* @cmd_queue_full: Called when the command queue gets full. Must be atomic.
|
||||
* @nic_config: configure NIC, called before firmware is started.
|
||||
* May sleep
|
||||
*/
|
||||
struct iwl_op_mode_ops {
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans);
|
||||
struct iwl_op_mode *(*start)(struct iwl_trans *trans,
|
||||
const struct iwl_fw *fw);
|
||||
void (*stop)(struct iwl_op_mode *op_mode);
|
||||
int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb,
|
||||
int (*rx)(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac);
|
||||
void (*queue_not_full)(struct iwl_op_mode *op_mode, u8 ac);
|
||||
void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
|
||||
void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
|
||||
void (*nic_error)(struct iwl_op_mode *op_mode);
|
||||
void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
|
||||
void (*nic_config)(struct iwl_op_mode *op_mode);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -156,7 +163,7 @@ static inline void iwl_op_mode_stop(struct iwl_op_mode *op_mode)
|
||||
}
|
||||
|
||||
static inline int iwl_op_mode_rx(struct iwl_op_mode *op_mode,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
return op_mode->ops->rx(op_mode, rxb, cmd);
|
||||
@ -190,6 +197,17 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
|
||||
op_mode->ops->nic_error(op_mode);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
op_mode->ops->cmd_queue_full(op_mode);
|
||||
}
|
||||
|
||||
static inline void iwl_op_mode_nic_config(struct iwl_op_mode *op_mode)
|
||||
{
|
||||
might_sleep();
|
||||
op_mode->ops->nic_config(op_mode);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Op mode layers implementations
|
||||
******************************************************/
|
||||
|
@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
|
||||
|
||||
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
||||
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
|
||||
struct iwl_shared *shrd;
|
||||
struct iwl_trans *iwl_trans;
|
||||
int err;
|
||||
@ -278,17 +278,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_IDI
|
||||
iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent);
|
||||
if (iwl_trans == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_bus;
|
||||
}
|
||||
|
||||
shrd->trans = iwl_trans;
|
||||
pci_set_drvdata(pdev, iwl_trans);
|
||||
|
||||
err = iwl_drv_start(shrd, iwl_trans, cfg);
|
||||
#else
|
||||
iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent);
|
||||
#endif
|
||||
if (iwl_trans == NULL) {
|
||||
err = -ENOMEM;
|
||||
goto out_free_bus;
|
||||
@ -298,7 +290,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
pci_set_drvdata(pdev, iwl_trans);
|
||||
|
||||
err = iwl_drv_start(shrd, iwl_trans, cfg);
|
||||
#endif
|
||||
if (err)
|
||||
goto out_free_trans;
|
||||
|
||||
|
@ -215,7 +215,7 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
|
||||
|
||||
if (hw_params(priv).shadow_reg_enable)
|
||||
if (cfg(priv)->base_params->shadow_reg_enable)
|
||||
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
||||
@ -301,7 +301,7 @@ static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
|
||||
if (priv->power_data.bus_pm)
|
||||
cmd->flags |= IWL_POWER_PCI_PM_MSK;
|
||||
|
||||
if (hw_params(priv).shadow_reg_enable)
|
||||
if (cfg(priv)->base_params->shadow_reg_enable)
|
||||
cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
|
||||
@ -336,7 +336,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
|
||||
le32_to_cpu(cmd->sleep_interval[3]),
|
||||
le32_to_cpu(cmd->sleep_interval[4]));
|
||||
|
||||
return iwl_trans_send_cmd_pdu(trans(priv), POWER_TABLE_CMD, CMD_SYNC,
|
||||
return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
|
||||
sizeof(struct iwl_powertable_cmd), cmd);
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ static void iwl_power_build_cmd(struct iwl_priv *priv,
|
||||
|
||||
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
if (priv->shrd->wowlan)
|
||||
if (priv->wowlan)
|
||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
|
||||
else if (!cfg(priv)->base_params->no_idle_support &&
|
||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
@ -383,7 +383,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
|
||||
int ret;
|
||||
bool update_chains;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Don't update the RX chain when chain noise calibration is running */
|
||||
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
|
||||
@ -392,12 +392,12 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
|
||||
if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
|
||||
return 0;
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EIO;
|
||||
|
||||
/* scan complete use sleep_power_next, need to be updated */
|
||||
memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
|
||||
if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
|
||||
if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
|
||||
IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -216,10 +216,6 @@
|
||||
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
|
||||
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
|
||||
|
||||
#define SCD_QUEUECHAIN_SEL_ALL(priv) \
|
||||
(((1<<hw_params(priv).max_txq_num) - 1) &\
|
||||
(~(1<<(priv)->shrd->cmd_queue)))
|
||||
|
||||
#define SCD_BASE (PRPH_BASE + 0xa02c00)
|
||||
|
||||
#define SCD_SRAM_BASE_ADDR (SCD_BASE + 0x0)
|
||||
|
@ -57,39 +57,39 @@
|
||||
static int iwl_send_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_ABORT_CMD,
|
||||
.flags = CMD_SYNC | CMD_WANT_SKB,
|
||||
};
|
||||
__le32 *status;
|
||||
|
||||
/* Exit instantly with error when device is not ready
|
||||
* to receive scan abort command or it does not perform
|
||||
* hardware scan currently */
|
||||
if (!test_bit(STATUS_READY, &priv->shrd->status) ||
|
||||
!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) ||
|
||||
!test_bit(STATUS_SCAN_HW, &priv->shrd->status) ||
|
||||
test_bit(STATUS_FW_ERROR, &priv->shrd->status) ||
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_READY, &priv->status) ||
|
||||
!test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
|
||||
!test_bit(STATUS_SCAN_HW, &priv->status) ||
|
||||
test_bit(STATUS_FW_ERROR, &priv->shrd->status))
|
||||
return -EIO;
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->u.status != CAN_ABORT_STATUS) {
|
||||
status = (void *)cmd.resp_pkt->data;
|
||||
if (*status != CAN_ABORT_STATUS) {
|
||||
/* The scan abort will return 1 for success or
|
||||
* 2 for "failure". A failure condition can be
|
||||
* due to simply not being in an active scan which
|
||||
* can occur if we send the scan abort before we
|
||||
* the microcode has notified us that a scan is
|
||||
* completed. */
|
||||
IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
|
||||
IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n",
|
||||
le32_to_cpu(*status));
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
iwl_free_resp(&cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -116,20 +116,20 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
||||
{
|
||||
bool aborted;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
|
||||
if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Completed scan.\n");
|
||||
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
|
||||
aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
||||
aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
|
||||
if (aborted)
|
||||
IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
|
||||
|
||||
if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
|
||||
goto out_settings;
|
||||
}
|
||||
@ -165,7 +165,7 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
||||
|
||||
out_settings:
|
||||
/* Can we still talk to firmware ? */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return;
|
||||
|
||||
iwlagn_post_scan(priv);
|
||||
@ -173,18 +173,18 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
||||
|
||||
void iwl_force_scan_end(struct iwl_priv *priv)
|
||||
{
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
if (!test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
|
||||
clear_bit(STATUS_SCANNING, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCANNING, &priv->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
|
||||
clear_bit(STATUS_SCAN_COMPLETE, &priv->status);
|
||||
iwl_complete_scan(priv, true);
|
||||
}
|
||||
|
||||
@ -192,14 +192,14 @@ static void iwl_do_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!test_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
if (!test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
|
||||
if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
|
||||
return;
|
||||
}
|
||||
@ -231,14 +231,14 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(ms);
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
|
||||
|
||||
iwl_do_scan_abort(priv);
|
||||
|
||||
while (time_before_eq(jiffies, timeout)) {
|
||||
if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
|
||||
if (!test_bit(STATUS_SCAN_HW, &priv->status))
|
||||
goto finished;
|
||||
msleep(20);
|
||||
}
|
||||
@ -261,13 +261,12 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
||||
|
||||
/* Service response to REPLY_SCAN_CMD (0x80) */
|
||||
static int iwl_rx_reply_scan(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanreq_notification *notif =
|
||||
(struct iwl_scanreq_notification *)pkt->u.raw;
|
||||
struct iwl_scanreq_notification *notif = (void *)pkt->data;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
|
||||
#endif
|
||||
@ -276,12 +275,12 @@ static int iwl_rx_reply_scan(struct iwl_priv *priv,
|
||||
|
||||
/* Service SCAN_START_NOTIFICATION (0x82) */
|
||||
static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanstart_notification *notif =
|
||||
(struct iwl_scanstart_notification *)pkt->u.raw;
|
||||
struct iwl_scanstart_notification *notif = (void *)pkt->data;
|
||||
|
||||
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
|
||||
IWL_DEBUG_SCAN(priv, "Scan start: "
|
||||
"%d [802.11%s] "
|
||||
@ -303,13 +302,12 @@ static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
|
||||
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
|
||||
static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanresults_notification *notif =
|
||||
(struct iwl_scanresults_notification *)pkt->u.raw;
|
||||
struct iwl_scanresults_notification *notif = (void *)pkt->data;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
|
||||
"%d [802.11%s] "
|
||||
@ -329,11 +327,11 @@ static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
||||
|
||||
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
|
||||
static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_rx_cmd_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
|
||||
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->data;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
|
||||
scan_notif->scanned_channels,
|
||||
@ -352,8 +350,8 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
* to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
|
||||
* to avoid a race there.
|
||||
*/
|
||||
set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
set_bit(STATUS_SCAN_COMPLETE, &priv->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
queue_work(priv->workqueue, &priv->scan_completed);
|
||||
|
||||
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
|
||||
@ -574,6 +572,53 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
||||
return added;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_fill_probe_req - fill in all required fields and IE for probe request
|
||||
*/
|
||||
|
||||
static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta,
|
||||
const u8 *ies, int ie_len, int left)
|
||||
{
|
||||
int len = 0;
|
||||
u8 *pos = NULL;
|
||||
|
||||
/* Make sure there is enough space for the probe request,
|
||||
* two mandatory IEs and the data */
|
||||
left -= 24;
|
||||
if (left < 0)
|
||||
return 0;
|
||||
|
||||
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
|
||||
memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
|
||||
memcpy(frame->sa, ta, ETH_ALEN);
|
||||
memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
|
||||
frame->seq_ctrl = 0;
|
||||
|
||||
len += 24;
|
||||
|
||||
/* ...next IE... */
|
||||
pos = &frame->u.probe_req.variable[0];
|
||||
|
||||
/* fill in our indirect SSID IE */
|
||||
left -= 2;
|
||||
if (left < 0)
|
||||
return 0;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = 0;
|
||||
|
||||
len += 2;
|
||||
|
||||
if (WARN_ON(left < ie_len))
|
||||
return len;
|
||||
|
||||
if (ies && ie_len) {
|
||||
memcpy(pos, ies, ie_len);
|
||||
len += ie_len;
|
||||
}
|
||||
|
||||
return (u16)len;
|
||||
}
|
||||
|
||||
static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
@ -596,7 +641,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
@ -793,7 +838,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
scan->rx_chain = cpu_to_le16(rx_chain);
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_NORMAL:
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
cmd_len = iwl_fill_probe_req(
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
@ -803,7 +848,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
case IWL_SCAN_ROC:
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
cmd_len = iwl_fill_probe_req(
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
@ -882,15 +927,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
scan->len = cpu_to_le16(cmd.len[0]);
|
||||
|
||||
/* set scan bit here for PAN params */
|
||||
set_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
set_bit(STATUS_SCAN_HW, &priv->status);
|
||||
|
||||
ret = iwlagn_set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
iwlagn_set_pan_params(priv);
|
||||
}
|
||||
|
||||
@ -913,22 +958,22 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd)) {
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_WARN(priv, "Request scan called when driver not ready.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"Multiple concurrent scan requests in parallel.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCAN_ABORTING, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
@ -938,14 +983,14 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
|
||||
"internal short ");
|
||||
|
||||
set_bit(STATUS_SCANNING, &priv->shrd->status);
|
||||
set_bit(STATUS_SCANNING, &priv->status);
|
||||
priv->scan_type = scan_type;
|
||||
priv->scan_start = jiffies;
|
||||
priv->scan_band = band;
|
||||
|
||||
ret = iwlagn_request_scan(priv, vif);
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCANNING, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCANNING, &priv->status);
|
||||
priv->scan_type = IWL_SCAN_NORMAL;
|
||||
return ret;
|
||||
}
|
||||
@ -973,14 +1018,14 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Start internal scan\n");
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
|
||||
IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
|
||||
goto unlock;
|
||||
}
|
||||
@ -988,7 +1033,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
|
||||
if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
|
||||
IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
|
||||
unlock:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_scan_check(struct work_struct *data)
|
||||
@ -1001,56 +1046,9 @@ static void iwl_bg_scan_check(struct work_struct *data)
|
||||
/* Since we are here firmware does not finish scan and
|
||||
* most likely is in bad shape, so we don't bother to
|
||||
* send abort command, just force scan complete to mac80211 */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_force_scan_end(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_fill_probe_req - fill in all required fields and IE for probe request
|
||||
*/
|
||||
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ta, const u8 *ies, int ie_len, int left)
|
||||
{
|
||||
int len = 0;
|
||||
u8 *pos = NULL;
|
||||
|
||||
/* Make sure there is enough space for the probe request,
|
||||
* two mandatory IEs and the data */
|
||||
left -= 24;
|
||||
if (left < 0)
|
||||
return 0;
|
||||
|
||||
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
|
||||
memcpy(frame->da, iwl_bcast_addr, ETH_ALEN);
|
||||
memcpy(frame->sa, ta, ETH_ALEN);
|
||||
memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN);
|
||||
frame->seq_ctrl = 0;
|
||||
|
||||
len += 24;
|
||||
|
||||
/* ...next IE... */
|
||||
pos = &frame->u.probe_req.variable[0];
|
||||
|
||||
/* fill in our indirect SSID IE */
|
||||
left -= 2;
|
||||
if (left < 0)
|
||||
return 0;
|
||||
*pos++ = WLAN_EID_SSID;
|
||||
*pos++ = 0;
|
||||
|
||||
len += 2;
|
||||
|
||||
if (WARN_ON(left < ie_len))
|
||||
return len;
|
||||
|
||||
if (ies && ie_len) {
|
||||
memcpy(pos, ies, ie_len);
|
||||
len += ie_len;
|
||||
}
|
||||
|
||||
return (u16)len;
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_abort_scan(struct work_struct *work)
|
||||
@ -1061,9 +1059,9 @@ static void iwl_bg_abort_scan(struct work_struct *work)
|
||||
|
||||
/* We keep scan_check work queued in case when firmware will not
|
||||
* report back scan completed notification */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void iwl_bg_scan_completed(struct work_struct *work)
|
||||
@ -1071,9 +1069,9 @@ static void iwl_bg_scan_completed(struct work_struct *work)
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, scan_completed);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_process_scan_complete(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
|
||||
@ -1091,8 +1089,8 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
|
||||
cancel_work_sync(&priv->scan_completed);
|
||||
|
||||
if (cancel_delayed_work_sync(&priv->scan_check)) {
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_force_scan_end(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
}
|
||||
|
@ -65,12 +65,11 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mm.h> /* for page_address */
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-fw.h"
|
||||
|
||||
/**
|
||||
* DOC: shared area - role and goal
|
||||
@ -116,7 +115,6 @@ extern struct iwl_mod_params iwlagn_mod_params;
|
||||
* Holds the module parameters
|
||||
*
|
||||
* @sw_crypto: using hardware encryption, default = 0
|
||||
* @num_of_queues: number of tx queue, HW dependent
|
||||
* @disable_11n: disable 11n capabilities, default = 0,
|
||||
* use IWL_DISABLE_HT_* constants
|
||||
* @amsdu_size_8K: enable 8K amsdu size, default = 1
|
||||
@ -138,7 +136,6 @@ extern struct iwl_mod_params iwlagn_mod_params;
|
||||
*/
|
||||
struct iwl_mod_params {
|
||||
int sw_crypto;
|
||||
int num_of_queues;
|
||||
unsigned int disable_11n;
|
||||
int amsdu_size_8K;
|
||||
int antenna;
|
||||
@ -163,7 +160,6 @@ struct iwl_mod_params {
|
||||
*
|
||||
* Holds the module parameters
|
||||
*
|
||||
* @max_txq_num: Max # Tx queues supported
|
||||
* @num_ampdu_queues: num of ampdu queues
|
||||
* @tx_chains_num: Number of TX chains
|
||||
* @rx_chains_num: Number of RX chains
|
||||
@ -177,16 +173,16 @@ struct iwl_mod_params {
|
||||
* relevant for 1000, 6000 and up
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @struct iwl_sensitivity_ranges: range of sensitivity values
|
||||
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
|
||||
*/
|
||||
struct iwl_hw_params {
|
||||
u8 max_txq_num;
|
||||
u8 num_ampdu_queues;
|
||||
u8 tx_chains_num;
|
||||
u8 rx_chains_num;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u8 ht40_channel;
|
||||
bool shadow_reg_enable;
|
||||
bool use_rts_for_aggregation;
|
||||
u16 sku;
|
||||
u32 rx_page_order;
|
||||
u32 ct_kill_threshold;
|
||||
@ -213,45 +209,6 @@ enum iwl_ucode_type {
|
||||
IWL_UCODE_WOWLAN,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_notification_wait - notification wait entry
|
||||
* @list: list head for global list
|
||||
* @fn: function called with the notification
|
||||
* @cmd: command ID
|
||||
*
|
||||
* This structure is not used directly, to wait for a
|
||||
* notification declare it on the stack, and call
|
||||
* iwlagn_init_notification_wait() with appropriate
|
||||
* parameters. Then do whatever will cause the ucode
|
||||
* to notify the driver, and to wait for that then
|
||||
* call iwlagn_wait_notification().
|
||||
*
|
||||
* Each notification is one-shot. If at some point we
|
||||
* need to support multi-shot notifications (which
|
||||
* can't be allocated on the stack) we need to modify
|
||||
* the code for them.
|
||||
*/
|
||||
struct iwl_notification_wait {
|
||||
struct list_head list;
|
||||
|
||||
void (*fn)(struct iwl_trans *trans, struct iwl_rx_packet *pkt,
|
||||
void *data);
|
||||
void *fn_data;
|
||||
|
||||
u8 cmd;
|
||||
bool triggered, aborted;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum iwl_pa_type - Power Amplifier type
|
||||
* @IWL_PA_SYSTEM: based on uCode configuration
|
||||
* @IWL_PA_INTERNAL: use Internal only
|
||||
*/
|
||||
enum iwl_pa_type {
|
||||
IWL_PA_SYSTEM = 0,
|
||||
IWL_PA_INTERNAL = 1,
|
||||
};
|
||||
|
||||
/*
|
||||
* LED mode
|
||||
* IWL_LED_DEFAULT: use device default
|
||||
@ -268,6 +225,73 @@ enum iwl_led_mode {
|
||||
IWL_LED_DISABLE,
|
||||
};
|
||||
|
||||
/*
|
||||
* @max_ll_items: max number of OTP blocks
|
||||
* @shadow_ram_support: shadow support for OTP memory
|
||||
* @led_compensation: compensate on the led on/off time per HW according
|
||||
* to the deviation to achieve the desired led frequency.
|
||||
* The detail algorithm is described in iwl-led.c
|
||||
* @chain_noise_num_beacons: number of beacons used to compute chain noise
|
||||
* @adv_thermal_throttle: support advance thermal throttle
|
||||
* @support_ct_kill_exit: support ct kill exit condition
|
||||
* @support_wimax_coexist: support wimax/wifi co-exist
|
||||
* @plcp_delta_threshold: plcp error rate threshold used to trigger
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @shadow_reg_enable: HW shadhow register bit
|
||||
* @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
|
||||
* @no_idle_support: do not support idle mode
|
||||
* wd_disable: disable watchdog timer
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
int eeprom_size;
|
||||
int num_of_queues; /* def: HW dependent */
|
||||
int num_of_ampdu_queues;/* def: HW dependent */
|
||||
/* for iwl_apm_init() */
|
||||
u32 pll_cfg_val;
|
||||
|
||||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
u16 led_compensation;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
const bool support_wimax_coexist;
|
||||
u8 plcp_delta_threshold;
|
||||
s32 chain_noise_scale;
|
||||
unsigned int wd_timeout;
|
||||
u32 max_event_log_size;
|
||||
const bool shadow_reg_enable;
|
||||
const bool hd_v2;
|
||||
const bool no_idle_support;
|
||||
const bool wd_disable;
|
||||
};
|
||||
|
||||
/*
|
||||
* @advanced_bt_coexist: support advanced bt coexist
|
||||
* @bt_init_traffic_load: specify initial bt traffic load
|
||||
* @bt_prio_boost: default bt priority boost value
|
||||
* @agg_time_limit: maximum number of uSec in aggregation
|
||||
* @bt_sco_disable: uCode should not response to BT in SCO/ESCO mode
|
||||
*/
|
||||
struct iwl_bt_params {
|
||||
bool advanced_bt_coexist;
|
||||
u8 bt_init_traffic_load;
|
||||
u8 bt_prio_boost;
|
||||
u16 agg_time_limit;
|
||||
bool bt_sco_disable;
|
||||
bool bt_session_2;
|
||||
};
|
||||
/*
|
||||
* @use_rts_for_aggregation: use rts/cts protection for HT traffic
|
||||
*/
|
||||
struct iwl_ht_params {
|
||||
const bool ht_greenfield_support; /* if used set to true */
|
||||
bool use_rts_for_aggregation;
|
||||
enum ieee80211_smps_mode smps_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_cfg
|
||||
* @name: Offical name of the device
|
||||
@ -282,7 +306,6 @@ enum iwl_led_mode {
|
||||
* @max_data_size: The maximal length of the fw data section
|
||||
* @valid_tx_ant: valid transmit antenna
|
||||
* @valid_rx_ant: valid receive antenna
|
||||
* @sku: sku information from EEPROM
|
||||
* @eeprom_ver: EEPROM version
|
||||
* @eeprom_calib_ver: EEPROM calibration version
|
||||
* @lib: pointer to the lib ops
|
||||
@ -290,7 +313,6 @@ enum iwl_led_mode {
|
||||
* @base_params: pointer to basic parameters
|
||||
* @ht_params: point to ht patameters
|
||||
* @bt_params: pointer to bt parameters
|
||||
* @pa_type: used by 6000 series only to identify the type of Power Amplifier
|
||||
* @need_temp_offset_calib: need to perform temperature offset calibration
|
||||
* @no_xtal_calib: some devices do not need crystal calibration data,
|
||||
* don't send it to those
|
||||
@ -321,17 +343,15 @@ struct iwl_cfg {
|
||||
const u32 max_inst_size;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
u16 sku;
|
||||
u16 eeprom_ver;
|
||||
u16 eeprom_calib_ver;
|
||||
const struct iwl_lib_ops *lib;
|
||||
void (*additional_nic_config)(struct iwl_priv *priv);
|
||||
/* params not likely to change within a device family */
|
||||
struct iwl_base_params *base_params;
|
||||
const struct iwl_base_params *base_params;
|
||||
/* params likely to change within a device family */
|
||||
struct iwl_ht_params *ht_params;
|
||||
struct iwl_bt_params *bt_params;
|
||||
enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */
|
||||
const struct iwl_ht_params *ht_params;
|
||||
const struct iwl_bt_params *bt_params;
|
||||
const bool need_temp_offset_calib; /* if used set to true */
|
||||
const bool no_xtal_calib;
|
||||
u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
|
||||
@ -346,10 +366,6 @@ struct iwl_cfg {
|
||||
/**
|
||||
* struct iwl_shared - shared fields for all the layers of the driver
|
||||
*
|
||||
* @dbg_level_dev: dbg level set per device. Prevails on
|
||||
* iwlagn_mod_params.debug_level if set (!= 0)
|
||||
* @ucode_owner: IWL_OWNERSHIP_*
|
||||
* @cmd_queue: command queue number
|
||||
* @status: STATUS_*
|
||||
* @wowlan: are we running wowlan uCode
|
||||
* @valid_contexts: microcode/device supports multiple contexts
|
||||
@ -360,39 +376,20 @@ struct iwl_cfg {
|
||||
* @nic: pointer to the nic data
|
||||
* @hw_params: see struct iwl_hw_params
|
||||
* @lock: protect general shared data
|
||||
* @sta_lock: protects the station table.
|
||||
* If lock and sta_lock are needed, lock must be acquired first.
|
||||
* @mutex:
|
||||
* @wait_command_queue: the wait_queue for SYNC host command nad uCode load
|
||||
* @wait_command_queue: the wait_queue for SYNC host commands
|
||||
* @eeprom: pointer to the eeprom/OTP image
|
||||
* @ucode_type: indicator of loaded ucode image
|
||||
* @notif_waits: things waiting for notification
|
||||
* @notif_wait_lock: lock protecting notification
|
||||
* @notif_waitq: head of notification wait queue
|
||||
* @device_pointers: pointers to ucode event tables
|
||||
*/
|
||||
struct iwl_shared {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
u32 dbg_level_dev;
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
#define IWL_OWNERSHIP_DRIVER 0
|
||||
#define IWL_OWNERSHIP_TM 1
|
||||
u8 ucode_owner;
|
||||
u8 cmd_queue;
|
||||
unsigned long status;
|
||||
bool wowlan;
|
||||
u8 valid_contexts;
|
||||
|
||||
struct iwl_cfg *cfg;
|
||||
struct iwl_priv *priv;
|
||||
const struct iwl_cfg *cfg;
|
||||
struct iwl_trans *trans;
|
||||
struct iwl_nic *nic;
|
||||
void *drv;
|
||||
struct iwl_hw_params hw_params;
|
||||
|
||||
spinlock_t lock;
|
||||
spinlock_t sta_lock;
|
||||
struct mutex mutex;
|
||||
const struct iwl_fw *fw;
|
||||
|
||||
wait_queue_head_t wait_command_queue;
|
||||
|
||||
@ -402,11 +399,6 @@ struct iwl_shared {
|
||||
/* ucode related variables */
|
||||
enum iwl_ucode_type ucode_type;
|
||||
|
||||
/* notification wait support */
|
||||
struct list_head notif_waits;
|
||||
spinlock_t notif_wait_lock;
|
||||
wait_queue_head_t notif_waitq;
|
||||
|
||||
struct {
|
||||
u32 error_event_table;
|
||||
u32 log_event_table;
|
||||
@ -415,111 +407,13 @@ struct iwl_shared {
|
||||
};
|
||||
|
||||
/*Whatever _m is (iwl_trans, iwl_priv, these macros will work */
|
||||
#define priv(_m) ((_m)->shrd->priv)
|
||||
#define cfg(_m) ((_m)->shrd->cfg)
|
||||
#define nic(_m) ((_m)->shrd->nic)
|
||||
#define trans(_m) ((_m)->shrd->trans)
|
||||
#define hw_params(_m) ((_m)->shrd->hw_params)
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/*
|
||||
* iwl_get_debug_level: Return active debug level for device
|
||||
*
|
||||
* Using sysfs it is possible to set per device debug level. This debug
|
||||
* level will be used if set, otherwise the global debug level which can be
|
||||
* set via module parameter is used.
|
||||
*/
|
||||
static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
|
||||
static inline bool iwl_have_debug_level(u32 level)
|
||||
{
|
||||
if (shrd->dbg_level_dev)
|
||||
return shrd->dbg_level_dev;
|
||||
else
|
||||
return iwlagn_mod_params.debug_level;
|
||||
}
|
||||
#else
|
||||
static inline u32 iwl_get_debug_level(struct iwl_shared *shrd)
|
||||
{
|
||||
return iwlagn_mod_params.debug_level;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void iwl_free_pages(struct iwl_shared *shrd, unsigned long page)
|
||||
{
|
||||
free_pages(page, shrd->hw_params.rx_page_order);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
|
||||
* @index -- current index
|
||||
* @n_bd -- total number of entries in queue (must be power of 2)
|
||||
*/
|
||||
static inline int iwl_queue_inc_wrap(int index, int n_bd)
|
||||
{
|
||||
return ++index & (n_bd - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
|
||||
* @index -- current index
|
||||
* @n_bd -- total number of entries in queue (must be power of 2)
|
||||
*/
|
||||
static inline int iwl_queue_dec_wrap(int index, int n_bd)
|
||||
{
|
||||
return --index & (n_bd - 1);
|
||||
}
|
||||
|
||||
struct iwl_rx_mem_buffer {
|
||||
dma_addr_t page_dma;
|
||||
struct page *page;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define rxb_addr(r) page_address(r->page)
|
||||
|
||||
/*
|
||||
* mac80211 queues, ACs, hardware queues, FIFOs.
|
||||
*
|
||||
* Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
|
||||
*
|
||||
* Mac80211 uses the following numbers, which we get as from it
|
||||
* by way of skb_get_queue_mapping(skb):
|
||||
*
|
||||
* VO 0
|
||||
* VI 1
|
||||
* BE 2
|
||||
* BK 3
|
||||
*
|
||||
*
|
||||
* Regular (not A-MPDU) frames are put into hardware queues corresponding
|
||||
* to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
|
||||
* own queue per aggregation session (RA/TID combination), such queues are
|
||||
* set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
|
||||
* order to map frames to the right queue, we also need an AC->hw queue
|
||||
* mapping. This is implemented here.
|
||||
*
|
||||
* Due to the way hw queues are set up (by the hw specific modules like
|
||||
* iwl-4965.c, iwl-5000.c etc.), the AC->hw queue mapping is the identity
|
||||
* mapping.
|
||||
*/
|
||||
|
||||
static const u8 tid_to_ac[] = {
|
||||
IEEE80211_AC_BE,
|
||||
IEEE80211_AC_BK,
|
||||
IEEE80211_AC_BK,
|
||||
IEEE80211_AC_BE,
|
||||
IEEE80211_AC_VI,
|
||||
IEEE80211_AC_VI,
|
||||
IEEE80211_AC_VO,
|
||||
IEEE80211_AC_VO
|
||||
};
|
||||
|
||||
static inline int get_ac_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
return tid_to_ac[tid];
|
||||
|
||||
/* no support for TIDs 8-15 yet */
|
||||
return -EINVAL;
|
||||
return iwlagn_mod_params.debug_level & level;
|
||||
}
|
||||
|
||||
enum iwl_rxon_context_id {
|
||||
@ -530,34 +424,9 @@ enum iwl_rxon_context_id {
|
||||
};
|
||||
|
||||
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
|
||||
void iwl_nic_config(struct iwl_priv *priv);
|
||||
const char *get_cmd_string(u8 cmd);
|
||||
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
|
||||
|
||||
|
||||
/* notification wait support */
|
||||
void iwl_abort_notification_waits(struct iwl_shared *shrd);
|
||||
void __acquires(wait_entry)
|
||||
iwl_init_notification_wait(struct iwl_shared *shrd,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
u8 cmd,
|
||||
void (*fn)(struct iwl_trans *trans,
|
||||
struct iwl_rx_packet *pkt,
|
||||
void *data),
|
||||
void *fn_data);
|
||||
int __must_check __releases(wait_entry)
|
||||
iwl_wait_notification(struct iwl_shared *shrd,
|
||||
struct iwl_notification_wait *wait_entry,
|
||||
unsigned long timeout);
|
||||
void __releases(wait_entry)
|
||||
iwl_remove_notification(struct iwl_shared *shrd,
|
||||
struct iwl_notification_wait *wait_entry);
|
||||
|
||||
#define IWL_CMD(x) case x: return #x
|
||||
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
|
||||
|
||||
#define IWL_TRAFFIC_ENTRIES (256)
|
||||
#define IWL_TRAFFIC_ENTRY_SIZE (64)
|
||||
|
||||
/*****************************************************
|
||||
* DRIVER STATUS FUNCTIONS
|
||||
@ -583,46 +452,4 @@ iwl_remove_notification(struct iwl_shared *shrd,
|
||||
#define STATUS_CHANNEL_SWITCH_PENDING 19
|
||||
#define STATUS_SCAN_COMPLETE 20
|
||||
|
||||
static inline int iwl_is_ready(struct iwl_shared *shrd)
|
||||
{
|
||||
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
|
||||
* set but EXIT_PENDING is not */
|
||||
return test_bit(STATUS_READY, &shrd->status) &&
|
||||
test_bit(STATUS_GEO_CONFIGURED, &shrd->status) &&
|
||||
!test_bit(STATUS_EXIT_PENDING, &shrd->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_alive(struct iwl_shared *shrd)
|
||||
{
|
||||
return test_bit(STATUS_ALIVE, &shrd->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_init(struct iwl_shared *shrd)
|
||||
{
|
||||
return test_bit(STATUS_INIT, &shrd->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_rfkill_hw(struct iwl_shared *shrd)
|
||||
{
|
||||
return test_bit(STATUS_RF_KILL_HW, &shrd->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_rfkill(struct iwl_shared *shrd)
|
||||
{
|
||||
return iwl_is_rfkill_hw(shrd);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ctkill(struct iwl_shared *shrd)
|
||||
{
|
||||
return test_bit(STATUS_CT_KILL, &shrd->status);
|
||||
}
|
||||
|
||||
static inline int iwl_is_ready_rf(struct iwl_shared *shrd)
|
||||
{
|
||||
if (iwl_is_rfkill(shrd))
|
||||
return 0;
|
||||
|
||||
return iwl_is_ready(shrd);
|
||||
}
|
||||
|
||||
#endif /* #__iwl_shared_h__ */
|
||||
|
@ -70,7 +70,6 @@
|
||||
#include <net/mac80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-debug.h"
|
||||
@ -79,6 +78,7 @@
|
||||
#include "iwl-testmode.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-fh.h"
|
||||
#include "iwl-prph.h"
|
||||
|
||||
|
||||
/* Periphery registers absolute lower bound. This is used in order to
|
||||
@ -125,13 +125,15 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = {
|
||||
[IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, },
|
||||
[IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, },
|
||||
|
||||
[IWL_TM_ATTR_ENABLE_NOTIFICATION] = {.type = NLA_FLAG, },
|
||||
};
|
||||
|
||||
/*
|
||||
* See the struct iwl_rx_packet in iwl-commands.h for the format of the
|
||||
* received events from the device
|
||||
*/
|
||||
static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
|
||||
static inline int get_event_length(struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
if (pkt)
|
||||
@ -162,7 +164,7 @@ static inline int get_event_length(struct iwl_rx_mem_buffer *rxb)
|
||||
*/
|
||||
|
||||
static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
struct iwl_rx_cmd_buffer *rxb)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
struct sk_buff *skb;
|
||||
@ -183,7 +185,8 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
|
||||
return;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
|
||||
NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data);
|
||||
/* the length doesn't include len_n_flags field, so add it manually */
|
||||
NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length + sizeof(__le32), data);
|
||||
cfg80211_testmode_event(skb, GFP_ATOMIC);
|
||||
return;
|
||||
|
||||
@ -194,7 +197,7 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv,
|
||||
|
||||
void iwl_testmode_init(struct iwl_priv *priv)
|
||||
{
|
||||
priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
|
||||
priv->pre_rx_handler = NULL;
|
||||
priv->testmode_trace.trace_enabled = false;
|
||||
priv->testmode_mem.read_in_progress = false;
|
||||
}
|
||||
@ -283,7 +286,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
IWL_DEBUG_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x,"
|
||||
" len %d\n", cmd.id, cmd.flags, cmd.len[0]);
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
ret = iwl_dvm_send_cmd(priv, &cmd);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to send hcmd\n");
|
||||
return ret;
|
||||
@ -292,7 +295,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
return ret;
|
||||
|
||||
/* Handling return of SKB to the user */
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
pkt = cmd.resp_pkt;
|
||||
if (!pkt) {
|
||||
IWL_ERR(priv, "HCMD received a null response packet\n");
|
||||
return ret;
|
||||
@ -309,7 +312,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
|
||||
/* The reply is in a page, that we cannot send to user space. */
|
||||
memcpy(reply_buf, &(pkt->hdr), reply_len);
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
iwl_free_resp(&cmd);
|
||||
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT);
|
||||
NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, reply_len, reply_buf);
|
||||
@ -419,23 +422,23 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv)
|
||||
struct iwl_notification_wait calib_wait;
|
||||
int ret;
|
||||
|
||||
iwl_init_notification_wait(priv->shrd, &calib_wait,
|
||||
CALIBRATION_COMPLETE_NOTIFICATION,
|
||||
NULL, NULL);
|
||||
ret = iwl_init_alive_start(trans(priv));
|
||||
iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
|
||||
CALIBRATION_COMPLETE_NOTIFICATION,
|
||||
NULL, NULL);
|
||||
ret = iwl_init_alive_start(priv);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Fail init calibration: %d\n", ret);
|
||||
goto cfg_init_calib_error;
|
||||
}
|
||||
|
||||
ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ);
|
||||
ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 2 * HZ);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error detecting"
|
||||
" CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret);
|
||||
return ret;
|
||||
|
||||
cfg_init_calib_error:
|
||||
iwl_remove_notification(priv->shrd, &calib_wait);
|
||||
iwl_remove_notification(&priv->notif_wait, &calib_wait);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -484,7 +487,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW:
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
|
||||
if (status)
|
||||
IWL_ERR(priv, "Error loading init ucode: %d\n", status);
|
||||
break;
|
||||
@ -495,7 +498,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW:
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR);
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_REGULAR);
|
||||
if (status) {
|
||||
IWL_ERR(priv,
|
||||
"Error loading runtime ucode: %d\n", status);
|
||||
@ -510,7 +513,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW:
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
iwl_trans_stop_device(trans);
|
||||
status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN);
|
||||
status = iwl_load_ucode_wait_alive(priv, IWL_UCODE_WOWLAN);
|
||||
if (status) {
|
||||
IWL_ERR(priv,
|
||||
"Error loading WOWLAN ucode: %d\n", status);
|
||||
@ -553,7 +556,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_GET_FW_VERSION:
|
||||
IWL_INFO(priv, "uCode version raw: 0x%x\n",
|
||||
nic(priv)->fw.ucode_ver);
|
||||
priv->fw->ucode_ver);
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20);
|
||||
if (!skb) {
|
||||
@ -561,7 +564,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
return -ENOMEM;
|
||||
}
|
||||
NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION,
|
||||
nic(priv)->fw.ucode_ver);
|
||||
priv->fw->ucode_ver);
|
||||
status = cfg80211_testmode_reply(skb);
|
||||
if (status < 0)
|
||||
IWL_ERR(priv, "Error sending msg : %d\n", status);
|
||||
@ -590,16 +593,16 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
}
|
||||
switch (priv->shrd->ucode_type) {
|
||||
case IWL_UCODE_REGULAR:
|
||||
inst_size = nic(priv)->fw.ucode_rt.code.len;
|
||||
data_size = nic(priv)->fw.ucode_rt.data.len;
|
||||
inst_size = priv->fw->ucode_rt.code.len;
|
||||
data_size = priv->fw->ucode_rt.data.len;
|
||||
break;
|
||||
case IWL_UCODE_INIT:
|
||||
inst_size = nic(priv)->fw.ucode_init.code.len;
|
||||
data_size = nic(priv)->fw.ucode_init.data.len;
|
||||
inst_size = priv->fw->ucode_init.code.len;
|
||||
data_size = priv->fw->ucode_init.data.len;
|
||||
break;
|
||||
case IWL_UCODE_WOWLAN:
|
||||
inst_size = nic(priv)->fw.ucode_wowlan.code.len;
|
||||
data_size = nic(priv)->fw.ucode_wowlan.data.len;
|
||||
inst_size = priv->fw->ucode_wowlan.code.len;
|
||||
data_size = priv->fw->ucode_wowlan.data.len;
|
||||
break;
|
||||
case IWL_UCODE_NONE:
|
||||
IWL_ERR(priv, "No uCode has not been loaded\n");
|
||||
@ -713,7 +716,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int iwl_testmode_trace_dump(struct ieee80211_hw *hw, struct nlattr **tb,
|
||||
static int iwl_testmode_trace_dump(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
@ -770,9 +773,13 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb)
|
||||
}
|
||||
|
||||
owner = nla_get_u8(tb[IWL_TM_ATTR_UCODE_OWNER]);
|
||||
if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM))
|
||||
priv->shrd->ucode_owner = owner;
|
||||
else {
|
||||
if (owner == IWL_OWNERSHIP_DRIVER) {
|
||||
priv->ucode_owner = owner;
|
||||
priv->pre_rx_handler = NULL;
|
||||
} else if (owner == IWL_OWNERSHIP_TM) {
|
||||
priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
|
||||
priv->ucode_owner = owner;
|
||||
} else {
|
||||
IWL_ERR(priv, "Invalid owner\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -905,9 +912,9 @@ static int iwl_testmode_indirect_mem(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
|
||||
struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw,
|
||||
struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
int idx, length;
|
||||
@ -937,6 +944,20 @@ static int iwl_testmode_buffer_dump(struct ieee80211_hw *hw, struct nlattr **tb,
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
static int iwl_testmode_notifications(struct ieee80211_hw *hw,
|
||||
struct nlattr **tb)
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
bool enable;
|
||||
|
||||
enable = nla_get_flag(tb[IWL_TM_ATTR_ENABLE_NOTIFICATION]);
|
||||
if (enable)
|
||||
priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt;
|
||||
else
|
||||
priv->pre_rx_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* The testmode gnl message handler that takes the gnl message from the
|
||||
* user space and parses it per the policy iwl_testmode_gnl_msg_policy, then
|
||||
@ -976,7 +997,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
return -ENOMSG;
|
||||
}
|
||||
/* in case multiple accesses to the device happens */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) {
|
||||
case IWL_TM_CMD_APP2DEV_UCODE:
|
||||
@ -1022,13 +1043,19 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
result = iwl_testmode_indirect_mem(hw, tb);
|
||||
break;
|
||||
|
||||
case IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
|
||||
IWL_DEBUG_INFO(priv, "testmode notifications cmd "
|
||||
"to driver\n");
|
||||
result = iwl_testmode_notifications(hw, tb);
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "Unknown testmode command\n");
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1063,21 +1090,21 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/* in case multiple accesses to the device happens */
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
mutex_lock(&priv->mutex);
|
||||
switch (cmd) {
|
||||
case IWL_TM_CMD_APP2DEV_READ_TRACE:
|
||||
IWL_DEBUG_INFO(priv, "uCode trace cmd to driver\n");
|
||||
result = iwl_testmode_trace_dump(hw, tb, skb, cb);
|
||||
result = iwl_testmode_trace_dump(hw, skb, cb);
|
||||
break;
|
||||
case IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP:
|
||||
IWL_DEBUG_INFO(priv, "testmode sram dump cmd to driver\n");
|
||||
result = iwl_testmode_buffer_dump(hw, tb, skb, cb);
|
||||
result = iwl_testmode_buffer_dump(hw, skb, cb);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
mutex_unlock(&priv->mutex);
|
||||
return result;
|
||||
}
|
||||
|
@ -122,6 +122,9 @@
|
||||
* Fore reading, a READ command is sent from the userspace and the data
|
||||
* is returned when the user calls a DUMP command.
|
||||
* For writing, only a WRITE command is used.
|
||||
* @IWL_TM_CMD_APP2DEV_NOTIFICATIONS:
|
||||
* Command to enable/disable notifications (currently RX packets) from the
|
||||
* driver to userspace.
|
||||
*/
|
||||
enum iwl_tm_cmd_t {
|
||||
IWL_TM_CMD_APP2DEV_UCODE = 1,
|
||||
@ -152,7 +155,8 @@ enum iwl_tm_cmd_t {
|
||||
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_READ = 26,
|
||||
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_DUMP = 27,
|
||||
IWL_TM_CMD_APP2DEV_INDIRECT_BUFFER_WRITE = 28,
|
||||
IWL_TM_CMD_MAX = 29,
|
||||
IWL_TM_CMD_APP2DEV_NOTIFICATIONS = 29,
|
||||
IWL_TM_CMD_MAX = 30,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -256,6 +260,10 @@ enum iwl_tm_cmd_t {
|
||||
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE this flag
|
||||
* indicates that the user wants to receive the response of the command
|
||||
* in a reply SKB. If it's not present, the response is not returned.
|
||||
* @IWL_TM_ATTR_ENABLE_NOTIFICATIONS:
|
||||
* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_NOTIFICATIONS, this
|
||||
* flag enables (if present) or disables (if not) the forwarding
|
||||
* to userspace.
|
||||
*/
|
||||
enum iwl_tm_attr_t {
|
||||
IWL_TM_ATTR_NOT_APPLICABLE = 0,
|
||||
@ -282,7 +290,8 @@ enum iwl_tm_attr_t {
|
||||
IWL_TM_ATTR_FW_INST_SIZE = 21,
|
||||
IWL_TM_ATTR_FW_DATA_SIZE = 22,
|
||||
IWL_TM_ATTR_UCODE_CMD_SKB = 23,
|
||||
IWL_TM_ATTR_MAX = 24,
|
||||
IWL_TM_ATTR_ENABLE_NOTIFICATION = 24,
|
||||
IWL_TM_ATTR_MAX = 25,
|
||||
};
|
||||
|
||||
/* uCode trace buffer */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "iwl-fh.h"
|
||||
@ -49,6 +50,12 @@ struct iwl_host_cmd;
|
||||
/*This file includes the declaration that are internal to the
|
||||
* trans_pcie layer */
|
||||
|
||||
struct iwl_rx_mem_buffer {
|
||||
dma_addr_t page_dma;
|
||||
struct page *page;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct isr_statistics - interrupt statistics
|
||||
*
|
||||
@ -109,6 +116,26 @@ struct iwl_dma_ptr {
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
|
||||
* @index -- current index
|
||||
* @n_bd -- total number of entries in queue (must be power of 2)
|
||||
*/
|
||||
static inline int iwl_queue_inc_wrap(int index, int n_bd)
|
||||
{
|
||||
return ++index & (n_bd - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
|
||||
* @index -- current index
|
||||
* @n_bd -- total number of entries in queue (must be power of 2)
|
||||
*/
|
||||
static inline int iwl_queue_dec_wrap(int index, int n_bd)
|
||||
{
|
||||
return --index & (n_bd - 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* This queue number is required for proper operation
|
||||
* because the ucode will stop/start the scheduler as
|
||||
@ -169,6 +196,7 @@ struct iwl_queue {
|
||||
* @meta: array of meta data for each command/tx buffer
|
||||
* @dma_addr_cmd: physical address of cmd/tx buffer array
|
||||
* @txb: array of per-TFD driver data
|
||||
* lock: queue lock
|
||||
* @time_stamp: time (in jiffies) of last read_ptr change
|
||||
* @need_update: indicates need to update read/write index
|
||||
* @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
|
||||
@ -187,6 +215,7 @@ struct iwl_tx_queue {
|
||||
struct iwl_device_cmd **cmd;
|
||||
struct iwl_cmd_meta *meta;
|
||||
struct sk_buff **skbs;
|
||||
spinlock_t lock;
|
||||
unsigned long time_stamp;
|
||||
u8 need_update;
|
||||
u8 sched_retry;
|
||||
@ -202,6 +231,7 @@ struct iwl_tx_queue {
|
||||
* @rxq: all the RX queue data
|
||||
* @rx_replenish: work that will be called when buffers need to be allocated
|
||||
* @trans: pointer to the generic transport area
|
||||
* @irq - the irq number for the device
|
||||
* @irq_requested: true when the irq has been requested
|
||||
* @scd_base_addr: scheduler sram base address in SRAM
|
||||
* @scd_bc_tbls: pointer to the byte count table of the scheduler
|
||||
@ -215,6 +245,10 @@ struct iwl_tx_queue {
|
||||
* queue_stop_count: tracks what SW queue is stopped
|
||||
* @pci_dev: basic pci-network driver stuff
|
||||
* @hw_base: pci hardware address support
|
||||
* @ucode_write_complete: indicates that the ucode has been copied.
|
||||
* @ucode_write_waitq: wait queue for uCode load
|
||||
* @status - transport specific status flags
|
||||
* @cmd_queue - command queue number
|
||||
*/
|
||||
struct iwl_trans_pcie {
|
||||
struct iwl_rx_queue rxq;
|
||||
@ -231,6 +265,7 @@ struct iwl_trans_pcie {
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct isr_statistics isr_stats;
|
||||
|
||||
unsigned int irq;
|
||||
spinlock_t irq_lock;
|
||||
u32 inta_mask;
|
||||
u32 scd_base_addr;
|
||||
@ -251,6 +286,11 @@ struct iwl_trans_pcie {
|
||||
/* PCI bus related data */
|
||||
struct pci_dev *pci_dev;
|
||||
void __iomem *hw_base;
|
||||
|
||||
bool ucode_write_complete;
|
||||
wait_queue_head_t ucode_write_waitq;
|
||||
unsigned long status;
|
||||
u8 cmd_queue;
|
||||
};
|
||||
|
||||
#define IWL_TRANS_GET_PCIE_TRANS(_iwl_trans) \
|
||||
@ -285,7 +325,7 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
|
||||
int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
|
||||
int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans,
|
||||
struct iwl_rx_mem_buffer *rxb, int handler_status);
|
||||
struct iwl_rx_cmd_buffer *rxb, int handler_status);
|
||||
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
struct iwl_tx_queue *txq,
|
||||
u16 byte_cnt);
|
||||
@ -318,7 +358,8 @@ void iwl_dump_csr(struct iwl_trans *trans);
|
||||
******************************************************/
|
||||
static inline void iwl_disable_interrupts(struct iwl_trans *trans)
|
||||
{
|
||||
clear_bit(STATUS_INT_ENABLED, &trans->shrd->status);
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
clear_bit(STATUS_INT_ENABLED, &trans_pcie->status);
|
||||
|
||||
/* disable interrupts from uCode/NIC to host */
|
||||
iwl_write32(trans, CSR_INT_MASK, 0x00000000);
|
||||
@ -332,14 +373,19 @@ static inline void iwl_disable_interrupts(struct iwl_trans *trans)
|
||||
|
||||
static inline void iwl_enable_interrupts(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
IWL_DEBUG_ISR(trans, "Enabling interrupts\n");
|
||||
set_bit(STATUS_INT_ENABLED, &trans->shrd->status);
|
||||
set_bit(STATUS_INT_ENABLED, &trans_pcie->status);
|
||||
iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask);
|
||||
}
|
||||
|
||||
static inline void iwl_enable_rfkill_int(struct iwl_trans *trans)
|
||||
{
|
||||
IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
|
||||
iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
|
||||
}
|
||||
|
||||
/*
|
||||
* we have 8 bits used like this:
|
||||
*
|
||||
@ -365,7 +411,7 @@ static inline u8 iwl_get_queue_ac(struct iwl_tx_queue *txq)
|
||||
}
|
||||
|
||||
static inline void iwl_wake_queue(struct iwl_trans *trans,
|
||||
struct iwl_tx_queue *txq, const char *msg)
|
||||
struct iwl_tx_queue *txq)
|
||||
{
|
||||
u8 queue = txq->swq_id;
|
||||
u8 ac = queue & 3;
|
||||
@ -376,19 +422,19 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
|
||||
if (test_and_clear_bit(hwq, trans_pcie->queue_stopped)) {
|
||||
if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0) {
|
||||
iwl_op_mode_queue_not_full(trans->op_mode, ac);
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d. %s",
|
||||
hwq, ac, msg);
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Wake hwq %d ac %d",
|
||||
hwq, ac);
|
||||
} else {
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Don't wake hwq %d ac %d"
|
||||
" stop count %d. %s",
|
||||
hwq, ac, atomic_read(&trans_pcie->
|
||||
queue_stop_count[ac]), msg);
|
||||
IWL_DEBUG_TX_QUEUES(trans,
|
||||
"Don't wake hwq %d ac %d stop count %d",
|
||||
hwq, ac,
|
||||
atomic_read(&trans_pcie->queue_stop_count[ac]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void iwl_stop_queue(struct iwl_trans *trans,
|
||||
struct iwl_tx_queue *txq, const char *msg)
|
||||
struct iwl_tx_queue *txq)
|
||||
{
|
||||
u8 queue = txq->swq_id;
|
||||
u8 ac = queue & 3;
|
||||
@ -399,34 +445,22 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
|
||||
if (!test_and_set_bit(hwq, trans_pcie->queue_stopped)) {
|
||||
if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0) {
|
||||
iwl_op_mode_queue_full(trans->op_mode, ac);
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Stop hwq %d ac %d"
|
||||
" stop count %d. %s",
|
||||
hwq, ac, atomic_read(&trans_pcie->
|
||||
queue_stop_count[ac]), msg);
|
||||
IWL_DEBUG_TX_QUEUES(trans,
|
||||
"Stop hwq %d ac %d stop count %d",
|
||||
hwq, ac,
|
||||
atomic_read(&trans_pcie->queue_stop_count[ac]));
|
||||
} else {
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Don't stop hwq %d ac %d"
|
||||
" stop count %d. %s",
|
||||
hwq, ac, atomic_read(&trans_pcie->
|
||||
queue_stop_count[ac]), msg);
|
||||
IWL_DEBUG_TX_QUEUES(trans,
|
||||
"Don't stop hwq %d ac %d stop count %d",
|
||||
hwq, ac,
|
||||
atomic_read(&trans_pcie->queue_stop_count[ac]));
|
||||
}
|
||||
} else {
|
||||
IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped/ %s",
|
||||
hwq, msg);
|
||||
IWL_DEBUG_TX_QUEUES(trans, "stop hwq %d, but it is stopped",
|
||||
hwq);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ieee80211_stop_queue
|
||||
#undef ieee80211_stop_queue
|
||||
#endif
|
||||
|
||||
#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
|
||||
|
||||
#ifdef ieee80211_wake_queue
|
||||
#undef ieee80211_wake_queue
|
||||
#endif
|
||||
|
||||
#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
|
||||
|
||||
static inline void iwl_txq_ctx_activate(struct iwl_trans_pcie *trans_pcie,
|
||||
int txq_id)
|
||||
{
|
||||
|
@ -30,11 +30,9 @@
|
||||
#include <linux/wait.h>
|
||||
#include <linux/gfp.h>
|
||||
|
||||
/*TODO: Remove include to iwl-core.h*/
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-prph.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-trans-pcie-int.h"
|
||||
#include "iwl-wifi.h"
|
||||
#include "iwl-op-mode.h"
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_IDI
|
||||
@ -142,7 +140,7 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans,
|
||||
if (q->need_update == 0)
|
||||
goto exit_unlock;
|
||||
|
||||
if (hw_params(trans).shadow_reg_enable) {
|
||||
if (cfg(trans)->base_params->shadow_reg_enable) {
|
||||
/* shadow register enabled */
|
||||
/* Device expects a multiple of 8 */
|
||||
q->write_actual = (q->write & ~0x7);
|
||||
@ -358,6 +356,113 @@ void iwl_bg_rx_replenish(struct work_struct *data)
|
||||
iwlagn_rx_replenish(trans_pcie->trans);
|
||||
}
|
||||
|
||||
static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
|
||||
struct iwl_device_cmd *cmd;
|
||||
unsigned long flags;
|
||||
int len, err;
|
||||
u16 sequence;
|
||||
struct iwl_rx_cmd_buffer rxcb;
|
||||
struct iwl_rx_packet *pkt;
|
||||
bool reclaim;
|
||||
int index, cmd_index;
|
||||
|
||||
if (WARN_ON(!rxb))
|
||||
return;
|
||||
|
||||
dma_unmap_page(trans->dev, rxb->page_dma,
|
||||
PAGE_SIZE << hw_params(trans).rx_page_order,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
rxcb._page = rxb->page;
|
||||
pkt = rxb_addr(&rxcb);
|
||||
|
||||
IWL_DEBUG_RX(trans, "%s, 0x%02x\n",
|
||||
get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
||||
|
||||
|
||||
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
len += sizeof(u32); /* account for status word */
|
||||
trace_iwlwifi_dev_rx(trans->dev, pkt, len);
|
||||
|
||||
/* Reclaim a command buffer only if this packet is a response
|
||||
* to a (driver-originated) command.
|
||||
* If the packet (e.g. Rx frame) originated from uCode,
|
||||
* there is no command buffer to reclaim.
|
||||
* Ucode should set SEQ_RX_FRAME bit if ucode-originated,
|
||||
* but apparently a few don't get set; catch them here. */
|
||||
reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
|
||||
(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
|
||||
(pkt->hdr.cmd != REPLY_RX) &&
|
||||
(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
|
||||
(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
|
||||
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
|
||||
(pkt->hdr.cmd != REPLY_TX);
|
||||
|
||||
sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim)
|
||||
cmd = txq->cmd[cmd_index];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
/* warn if this is cmd response / notification and the uCode
|
||||
* didn't set the SEQ_RX_FRAME for a frame that is
|
||||
* uCode-originated
|
||||
* If you saw this code after the second half of 2012, then
|
||||
* please remove it
|
||||
*/
|
||||
WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
|
||||
(!(pkt->hdr.sequence & SEQ_RX_FRAME)),
|
||||
"reclaim is false, SEQ_RX_FRAME unset: %s\n",
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
|
||||
err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
|
||||
|
||||
/*
|
||||
* XXX: After here, we should always check rxcb._page
|
||||
* against NULL before touching it or its virtual
|
||||
* memory (pkt). Because some rx_handler might have
|
||||
* already taken or freed the pages.
|
||||
*/
|
||||
|
||||
if (reclaim) {
|
||||
/* Invoke any callbacks, transfer the buffer to caller,
|
||||
* and fire off the (possibly) blocking
|
||||
* iwl_trans_send_cmd()
|
||||
* as we reclaim the driver command queue */
|
||||
if (rxcb._page)
|
||||
iwl_tx_cmd_complete(trans, &rxcb, err);
|
||||
else
|
||||
IWL_WARN(trans, "Claim null rxb?\n");
|
||||
}
|
||||
|
||||
/* page was stolen from us */
|
||||
if (rxcb._page == NULL)
|
||||
rxb->page = NULL;
|
||||
|
||||
/* Reuse the page if possible. For notification packets and
|
||||
* SKBs that fail to Rx correctly, add them back into the
|
||||
* rx_free list for reuse later. */
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (rxb->page != NULL) {
|
||||
rxb->page_dma =
|
||||
dma_map_page(trans->dev, rxb->page, 0,
|
||||
PAGE_SIZE << hw_params(trans).rx_page_order,
|
||||
DMA_FROM_DEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_rx_handle - Main entry function for receiving responses from uCode
|
||||
*
|
||||
@ -367,20 +472,12 @@ void iwl_bg_rx_replenish(struct work_struct *data)
|
||||
*/
|
||||
static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
|
||||
struct iwl_device_cmd *cmd;
|
||||
u32 r, i;
|
||||
int reclaim;
|
||||
unsigned long flags;
|
||||
u8 fill_rx = 0;
|
||||
u32 count = 8;
|
||||
int total_empty;
|
||||
int index, cmd_index;
|
||||
|
||||
/* uCode's read index (stored in shared DRAM) indicates the last Rx
|
||||
* buffer that the driver may process (last buffer filled by ucode). */
|
||||
@ -400,102 +497,14 @@ static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
fill_rx = 1;
|
||||
|
||||
while (i != r) {
|
||||
int len, err;
|
||||
u16 sequence;
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
|
||||
rxb = rxq->queue[i];
|
||||
|
||||
/* If an RXB doesn't have a Rx queue slot associated with it,
|
||||
* then a bug has been introduced in the queue refilling
|
||||
* routines -- catch it here */
|
||||
if (WARN_ON(rxb == NULL)) {
|
||||
i = (i + 1) & RX_QUEUE_MASK;
|
||||
continue;
|
||||
}
|
||||
|
||||
rxq->queue[i] = NULL;
|
||||
|
||||
dma_unmap_page(trans->dev, rxb->page_dma,
|
||||
PAGE_SIZE << hw_params(trans).rx_page_order,
|
||||
DMA_FROM_DEVICE);
|
||||
pkt = rxb_addr(rxb);
|
||||
IWL_DEBUG_RX(trans, "rxbuf: r = %d, i = %d (%p)\n", rxb);
|
||||
|
||||
IWL_DEBUG_RX(trans, "r = %d, i = %d, %s, 0x%02x\n", r,
|
||||
i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
||||
|
||||
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
len += sizeof(u32); /* account for status word */
|
||||
trace_iwlwifi_dev_rx(priv(trans), pkt, len);
|
||||
|
||||
/* Reclaim a command buffer only if this packet is a response
|
||||
* to a (driver-originated) command.
|
||||
* If the packet (e.g. Rx frame) originated from uCode,
|
||||
* there is no command buffer to reclaim.
|
||||
* Ucode should set SEQ_RX_FRAME bit if ucode-originated,
|
||||
* but apparently a few don't get set; catch them here. */
|
||||
reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
|
||||
(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
|
||||
(pkt->hdr.cmd != REPLY_RX) &&
|
||||
(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
|
||||
(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
|
||||
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
|
||||
(pkt->hdr.cmd != REPLY_TX);
|
||||
|
||||
sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim)
|
||||
cmd = txq->cmd[cmd_index];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
/* warn if this is cmd response / notification and the uCode
|
||||
* didn't set the SEQ_RX_FRAME for a frame that is
|
||||
* uCode-originated
|
||||
* If you saw this code after the second half of 2012, then
|
||||
* please remove it
|
||||
*/
|
||||
WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
|
||||
(!(pkt->hdr.sequence & SEQ_RX_FRAME)),
|
||||
"reclaim is false, SEQ_RX_FRAME unset: %s\n",
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
|
||||
err = iwl_op_mode_rx(trans->op_mode, rxb, cmd);
|
||||
|
||||
/*
|
||||
* XXX: After here, we should always check rxb->page
|
||||
* against NULL before touching it or its virtual
|
||||
* memory (pkt). Because some rx_handler might have
|
||||
* already taken or freed the pages.
|
||||
*/
|
||||
|
||||
if (reclaim) {
|
||||
/* Invoke any callbacks, transfer the buffer to caller,
|
||||
* and fire off the (possibly) blocking
|
||||
* iwl_trans_send_cmd()
|
||||
* as we reclaim the driver command queue */
|
||||
if (rxb->page)
|
||||
iwl_tx_cmd_complete(trans, rxb, err);
|
||||
else
|
||||
IWL_WARN(trans, "Claim null rxb?\n");
|
||||
}
|
||||
|
||||
/* Reuse the page if possible. For notification packets and
|
||||
* SKBs that fail to Rx correctly, add them back into the
|
||||
* rx_free list for reuse later. */
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (rxb->page != NULL) {
|
||||
rxb->page_dma = dma_map_page(trans->dev, rxb->page,
|
||||
0, PAGE_SIZE <<
|
||||
hw_params(trans).rx_page_order,
|
||||
DMA_FROM_DEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
iwl_rx_handle_rxbuf(trans, rxb);
|
||||
|
||||
i = (i + 1) & RX_QUEUE_MASK;
|
||||
/* If there are a lot of unused frames,
|
||||
@ -591,17 +600,16 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
|
||||
{
|
||||
u32 base;
|
||||
struct iwl_error_event_table table;
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
base = trans->shrd->device_pointers.error_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
base = nic->init_errlog_ptr;
|
||||
base = trans->shrd->fw->init_errlog_ptr;
|
||||
} else {
|
||||
if (!base)
|
||||
base = nic->inst_errlog_ptr;
|
||||
base = trans->shrd->fw->inst_errlog_ptr;
|
||||
}
|
||||
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
@ -623,7 +631,7 @@ static void iwl_dump_nic_error_log(struct iwl_trans *trans)
|
||||
|
||||
trans_pcie->isr_stats.err_code = table.error_id;
|
||||
|
||||
trace_iwlwifi_dev_ucode_error(priv(nic), table.error_id, table.tsf_low,
|
||||
trace_iwlwifi_dev_ucode_error(trans->dev, table.error_id, table.tsf_low,
|
||||
table.data1, table.data2, table.line,
|
||||
table.blink1, table.blink2, table.ilink1,
|
||||
table.ilink2, table.bcon_time, table.gp1,
|
||||
@ -689,7 +697,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
IWL_ERR(trans, "Loaded firmware version: %s\n",
|
||||
nic(trans)->fw.fw_version);
|
||||
trans->shrd->fw->fw_version);
|
||||
|
||||
iwl_dump_nic_error_log(trans);
|
||||
iwl_dump_csr(trans);
|
||||
@ -715,7 +723,6 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
u32 ptr; /* SRAM byte address of log data */
|
||||
u32 ev, time, data; /* event log data */
|
||||
unsigned long reg_flags;
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
|
||||
if (num_events == 0)
|
||||
return pos;
|
||||
@ -723,10 +730,10 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
base = trans->shrd->device_pointers.log_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
if (!base)
|
||||
base = nic->init_evtlog_ptr;
|
||||
base = trans->shrd->fw->init_evtlog_ptr;
|
||||
} else {
|
||||
if (!base)
|
||||
base = nic->inst_evtlog_ptr;
|
||||
base = trans->shrd->fw->inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (mode == 0)
|
||||
@ -738,11 +745,11 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&trans->reg_lock, reg_flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
if (unlikely(!iwl_grab_nic_access(trans)))
|
||||
goto out_unlock;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, ptr);
|
||||
rmb();
|
||||
|
||||
/* "time" is actually "data" for mode 0 (no timestamp).
|
||||
* place event id # at far right for easier visual parsing. */
|
||||
@ -756,7 +763,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
"EVT_LOG:0x%08x:%04u\n",
|
||||
time, ev);
|
||||
} else {
|
||||
trace_iwlwifi_dev_ucode_event(priv(trans), 0,
|
||||
trace_iwlwifi_dev_ucode_event(trans->dev, 0,
|
||||
time, ev);
|
||||
IWL_ERR(trans, "EVT_LOG:0x%08x:%04u\n",
|
||||
time, ev);
|
||||
@ -770,7 +777,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
} else {
|
||||
IWL_ERR(trans, "EVT_LOGT:%010u:0x%08x:%04u\n",
|
||||
time, data, ev);
|
||||
trace_iwlwifi_dev_ucode_event(priv(trans), time,
|
||||
trace_iwlwifi_dev_ucode_event(trans->dev, time,
|
||||
data, ev);
|
||||
}
|
||||
}
|
||||
@ -778,6 +785,7 @@ static int iwl_print_event_log(struct iwl_trans *trans, u32 start_idx,
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_release_nic_access(trans);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
|
||||
return pos;
|
||||
}
|
||||
@ -832,17 +840,16 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
|
||||
u32 logsize;
|
||||
int pos = 0;
|
||||
size_t bufsz = 0;
|
||||
struct iwl_nic *nic = nic(trans);
|
||||
|
||||
base = trans->shrd->device_pointers.log_event_table;
|
||||
if (trans->shrd->ucode_type == IWL_UCODE_INIT) {
|
||||
logsize = nic->init_evtlog_size;
|
||||
logsize = trans->shrd->fw->init_evtlog_size;
|
||||
if (!base)
|
||||
base = nic->init_evtlog_ptr;
|
||||
base = trans->shrd->fw->init_evtlog_ptr;
|
||||
} else {
|
||||
logsize = nic->inst_evtlog_size;
|
||||
logsize = trans->shrd->fw->inst_evtlog_size;
|
||||
if (!base)
|
||||
base = nic->inst_evtlog_ptr;
|
||||
base = trans->shrd->fw->inst_evtlog_ptr;
|
||||
}
|
||||
|
||||
if (!iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
@ -881,7 +888,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (!(iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) && !full_log)
|
||||
if (!(iwl_have_debug_level(IWL_DL_FW_ERRORS)) && !full_log)
|
||||
size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
|
||||
? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
|
||||
#else
|
||||
@ -901,7 +908,7 @@ int iwl_dump_nic_event_log(struct iwl_trans *trans, bool full_log,
|
||||
if (!*buf)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if ((iwl_get_debug_level(trans->shrd) & IWL_DL_FW_ERRORS) || full_log) {
|
||||
if (iwl_have_debug_level(IWL_DL_FW_ERRORS) || full_log) {
|
||||
/*
|
||||
* if uCode has wrapped back to top of log,
|
||||
* start at the oldest entry,
|
||||
@ -960,7 +967,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
inta = trans_pcie->inta;
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(trans->shrd) & IWL_DL_ISR) {
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
/* just for debug */
|
||||
inta_mask = iwl_read32(trans, CSR_INT_MASK);
|
||||
IWL_DEBUG_ISR(trans, "inta 0x%08x, enabled 0x%08x\n ",
|
||||
@ -989,7 +996,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
/* NIC fires this, but we don't use it, redundant with WAKEUP */
|
||||
if (inta & CSR_INT_BIT_SCD) {
|
||||
IWL_DEBUG_ISR(trans, "Scheduler finished to transmit "
|
||||
@ -1009,30 +1016,16 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
|
||||
/* HW RF KILL switch toggled */
|
||||
if (inta & CSR_INT_BIT_RF_KILL) {
|
||||
int hw_rf_kill = 0;
|
||||
if (!(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
|
||||
hw_rf_kill = 1;
|
||||
bool hw_rfkill;
|
||||
|
||||
hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
IWL_WARN(trans, "RF_KILL bit toggled to %s.\n",
|
||||
hw_rf_kill ? "disable radio" : "enable radio");
|
||||
hw_rfkill ? "disable radio" : "enable radio");
|
||||
|
||||
isr_stats->rfkill++;
|
||||
|
||||
/* driver only loads ucode once setting the interface up.
|
||||
* the driver allows loading the ucode even if the radio
|
||||
* is killed. Hence update the killswitch state here. The
|
||||
* rfkill handler will care about restarting if needed.
|
||||
*/
|
||||
if (!test_bit(STATUS_ALIVE, &trans->shrd->status)) {
|
||||
if (hw_rf_kill)
|
||||
set_bit(STATUS_RF_KILL_HW,
|
||||
&trans->shrd->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW,
|
||||
&trans->shrd->status);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rf_kill);
|
||||
}
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
handled |= CSR_INT_BIT_RF_KILL;
|
||||
}
|
||||
@ -1057,7 +1050,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
if (inta & CSR_INT_BIT_WAKEUP) {
|
||||
IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
|
||||
iwl_rx_queue_update_write_ptr(trans, &trans_pcie->rxq);
|
||||
for (i = 0; i < hw_params(trans).max_txq_num; i++)
|
||||
for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++)
|
||||
iwl_txq_update_write_ptr(trans,
|
||||
&trans_pcie->txq[i]);
|
||||
|
||||
@ -1122,8 +1115,8 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
isr_stats->tx++;
|
||||
handled |= CSR_INT_BIT_FH_TX;
|
||||
/* Wake up uCode load routine, now that load is complete */
|
||||
trans->ucode_write_complete = 1;
|
||||
wake_up(&trans->shrd->wait_command_queue);
|
||||
trans_pcie->ucode_write_complete = true;
|
||||
wake_up(&trans_pcie->ucode_write_waitq);
|
||||
}
|
||||
|
||||
if (inta & ~handled) {
|
||||
@ -1138,13 +1131,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
|
||||
/* Re-enable all interrupts */
|
||||
/* only Re-enable if disabled by irq */
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status))
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status))
|
||||
iwl_enable_interrupts(trans);
|
||||
/* Re-enable RF_KILL if it occurred */
|
||||
else if (handled & CSR_INT_BIT_RF_KILL) {
|
||||
IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
|
||||
iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
|
||||
}
|
||||
else if (handled & CSR_INT_BIT_RF_KILL)
|
||||
iwl_enable_rfkill_int(trans);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@ -1269,7 +1260,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
if (!trans)
|
||||
return IRQ_NONE;
|
||||
|
||||
trace_iwlwifi_dev_irq(priv(trans));
|
||||
trace_iwlwifi_dev_irq(trans->dev);
|
||||
|
||||
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
@ -1301,7 +1292,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
if (iwl_get_debug_level(trans->shrd) & (IWL_DL_ISR)) {
|
||||
if (iwl_have_debug_level(IWL_DL_ISR)) {
|
||||
inta_fh = iwl_read32(trans, CSR_FH_INT_STATUS);
|
||||
IWL_DEBUG_ISR(trans, "ISR inta 0x%08x, enabled 0x%08x, "
|
||||
"fh 0x%08x\n", inta, inta_mask, inta_fh);
|
||||
@ -1312,7 +1303,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&trans_pcie->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
@ -1323,7 +1314,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service. */
|
||||
/* only Re-enable if disabled by irq and no schedules tasklet. */
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
@ -1359,7 +1350,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
if (!trans_pcie->use_ict)
|
||||
return iwl_isr(irq, data);
|
||||
|
||||
trace_iwlwifi_dev_irq(priv(trans));
|
||||
trace_iwlwifi_dev_irq(trans->dev);
|
||||
|
||||
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
|
||||
|
||||
@ -1376,7 +1367,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
|
||||
trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index, read);
|
||||
trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index, read);
|
||||
if (!read) {
|
||||
IWL_DEBUG_ISR(trans, "Ignore interrupt, inta == 0\n");
|
||||
goto none;
|
||||
@ -1395,7 +1386,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
|
||||
|
||||
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
|
||||
trace_iwlwifi_dev_ict_read(priv(trans), trans_pcie->ict_index,
|
||||
trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
|
||||
read);
|
||||
} while (read);
|
||||
|
||||
@ -1423,7 +1414,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta))
|
||||
tasklet_schedule(&trans_pcie->irq_tasklet);
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
|
||||
else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta) {
|
||||
/* Allow interrupt if was disabled by this handler and
|
||||
* no tasklet was schedules, We should not enable interrupt,
|
||||
@ -1439,7 +1430,7 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
|
||||
/* re-enable interrupts here since we don't have anything to service.
|
||||
* only Re-enable if disabled by irq.
|
||||
*/
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans->shrd->status) &&
|
||||
if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
|
||||
!trans_pcie->inta)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
|
@ -41,6 +41,43 @@
|
||||
#define IWL_TX_CRC_SIZE 4
|
||||
#define IWL_TX_DELIMITER_SIZE 4
|
||||
|
||||
/*
|
||||
* mac80211 queues, ACs, hardware queues, FIFOs.
|
||||
*
|
||||
* Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
|
||||
*
|
||||
* Mac80211 uses the following numbers, which we get as from it
|
||||
* by way of skb_get_queue_mapping(skb):
|
||||
*
|
||||
* VO 0
|
||||
* VI 1
|
||||
* BE 2
|
||||
* BK 3
|
||||
*
|
||||
*
|
||||
* Regular (not A-MPDU) frames are put into hardware queues corresponding
|
||||
* to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
|
||||
* own queue per aggregation session (RA/TID combination), such queues are
|
||||
* set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
|
||||
* order to map frames to the right queue, we also need an AC->hw queue
|
||||
* mapping. This is implemented here.
|
||||
*
|
||||
* Due to the way hw queues are set up (by the hw specific code), the AC->hw
|
||||
* queue mapping is the identity mapping.
|
||||
*/
|
||||
|
||||
static const u8 tid_to_ac[] = {
|
||||
IEEE80211_AC_BE,
|
||||
IEEE80211_AC_BK,
|
||||
IEEE80211_AC_BK,
|
||||
IEEE80211_AC_BE,
|
||||
IEEE80211_AC_VI,
|
||||
IEEE80211_AC_VI,
|
||||
IEEE80211_AC_VO,
|
||||
IEEE80211_AC_VO
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* iwl_trans_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
|
||||
*/
|
||||
@ -99,7 +136,7 @@ void iwl_txq_update_write_ptr(struct iwl_trans *trans, struct iwl_tx_queue *txq)
|
||||
if (txq->need_update == 0)
|
||||
return;
|
||||
|
||||
if (hw_params(trans).shadow_reg_enable) {
|
||||
if (cfg(trans)->base_params->shadow_reg_enable) {
|
||||
/* shadow register enabled */
|
||||
iwl_write32(trans, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
@ -217,6 +254,8 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||
{
|
||||
struct iwl_tfd *tfd_tmp = txq->tfds;
|
||||
|
||||
lockdep_assert_held(&txq->lock);
|
||||
|
||||
iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
|
||||
|
||||
/* free SKB */
|
||||
@ -358,7 +397,7 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
|
||||
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
if (txq_id != trans->shrd->cmd_queue)
|
||||
if (txq_id != trans_pcie->cmd_queue)
|
||||
sta_id = tx_cmd->sta_id;
|
||||
|
||||
bc_ent = cpu_to_le16(1 | (sta_id << 12));
|
||||
@ -440,6 +479,15 @@ void iwl_trans_tx_queue_set_status(struct iwl_trans *trans,
|
||||
scd_retry ? "BA" : "AC/CMD", txq_id);
|
||||
}
|
||||
|
||||
static inline int get_ac_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
return tid_to_ac[tid];
|
||||
|
||||
/* no support for TIDs 8-15 yet */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int get_fifo_from_tid(struct iwl_trans_pcie *trans_pcie,
|
||||
u8 ctx, u16 tid)
|
||||
{
|
||||
@ -547,7 +595,8 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int txq_id;
|
||||
|
||||
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
|
||||
for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
|
||||
txq_id++)
|
||||
if (!test_and_set_bit(txq_id,
|
||||
&trans_pcie->txq_ctx_active_msk))
|
||||
return txq_id;
|
||||
@ -616,15 +665,13 @@ int iwl_trans_pcie_tx_agg_disable(struct iwl_trans *trans, int sta_id, int tid)
|
||||
static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
struct iwl_device_cmd *out_cmd;
|
||||
struct iwl_cmd_meta *out_meta;
|
||||
dma_addr_t phys_addr;
|
||||
unsigned long flags;
|
||||
u32 idx;
|
||||
u16 copy_size, cmd_size;
|
||||
bool is_ct_kill = false;
|
||||
bool had_nocopy = false;
|
||||
int i;
|
||||
u8 *cmd_dest;
|
||||
@ -639,12 +686,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((trans->shrd->ucode_owner == IWL_OWNERSHIP_TM) &&
|
||||
!(cmd->flags & CMD_ON_DEMAND)) {
|
||||
IWL_DEBUG_HC(trans, "tm own the uCode, no regular hcmd send\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
copy_size = sizeof(out_cmd->hdr);
|
||||
cmd_size = sizeof(out_cmd->hdr);
|
||||
|
||||
@ -674,23 +715,13 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
|
||||
return -EINVAL;
|
||||
|
||||
if (iwl_is_rfkill(trans->shrd) || iwl_is_ctkill(trans->shrd)) {
|
||||
IWL_WARN(trans, "Not sending command - %s KILL\n",
|
||||
iwl_is_rfkill(trans->shrd) ? "RF" : "CT");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&trans->hcmd_lock, flags);
|
||||
spin_lock_bh(&txq->lock);
|
||||
|
||||
if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
|
||||
spin_unlock_irqrestore(&trans->hcmd_lock, flags);
|
||||
spin_unlock_bh(&txq->lock);
|
||||
|
||||
IWL_ERR(trans, "No space in command queue\n");
|
||||
is_ct_kill = iwl_check_for_ct_kill(priv(trans));
|
||||
if (!is_ct_kill) {
|
||||
IWL_ERR(trans, "Restarting adapter queue is full\n");
|
||||
iwl_op_mode_nic_error(trans->op_mode);
|
||||
}
|
||||
iwl_op_mode_cmd_queue_full(trans->op_mode);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
@ -707,7 +738,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
out_cmd->hdr.cmd = cmd->id;
|
||||
out_cmd->hdr.flags = 0;
|
||||
out_cmd->hdr.sequence =
|
||||
cpu_to_le16(QUEUE_TO_SEQ(trans->shrd->cmd_queue) |
|
||||
cpu_to_le16(QUEUE_TO_SEQ(trans_pcie->cmd_queue) |
|
||||
INDEX_TO_SEQ(q->write_ptr));
|
||||
|
||||
/* and copy the data that needs to be copied */
|
||||
@ -727,7 +758,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
get_cmd_string(out_cmd->hdr.cmd),
|
||||
out_cmd->hdr.cmd,
|
||||
le16_to_cpu(out_cmd->hdr.sequence), cmd_size,
|
||||
q->write_ptr, idx, trans->shrd->cmd_queue);
|
||||
q->write_ptr, idx, trans_pcie->cmd_queue);
|
||||
|
||||
phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
|
||||
DMA_BIDIRECTIONAL);
|
||||
@ -779,7 +810,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
/* check that tracing gets all possible blocks */
|
||||
BUILD_BUG_ON(IWL_MAX_CMD_TFDS + 1 != 3);
|
||||
#ifdef CONFIG_IWLWIFI_DEVICE_TRACING
|
||||
trace_iwlwifi_dev_hcmd(priv(trans), cmd->flags,
|
||||
trace_iwlwifi_dev_hcmd(trans->dev, cmd->flags,
|
||||
trace_bufs[0], trace_lens[0],
|
||||
trace_bufs[1], trace_lens[1],
|
||||
trace_bufs[2], trace_lens[2]);
|
||||
@ -790,7 +821,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
iwl_txq_update_write_ptr(trans, txq);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&trans->hcmd_lock, flags);
|
||||
spin_unlock_bh(&txq->lock);
|
||||
return idx;
|
||||
}
|
||||
|
||||
@ -809,6 +840,8 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
|
||||
struct iwl_queue *q = &txq->q;
|
||||
int nfreed = 0;
|
||||
|
||||
lockdep_assert_held(&txq->lock);
|
||||
|
||||
if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
|
||||
IWL_ERR(trans, "%s: Read index for DMA queue txq id (%d), "
|
||||
"index %d is out of range [0-%d] %d %d.\n", __func__,
|
||||
@ -838,7 +871,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
|
||||
* will be executed. The attached skb (if present) will only be freed
|
||||
* if the callback returns 1
|
||||
*/
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_cmd_buffer *rxb,
|
||||
int handler_status)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -849,21 +882,22 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd;
|
||||
struct iwl_cmd_meta *meta;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
|
||||
unsigned long flags;
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans_pcie->cmd_queue];
|
||||
|
||||
/* If a Tx command is being handled and it isn't in the actual
|
||||
* command queue then there a command routing bug has been introduced
|
||||
* in the queue management code. */
|
||||
if (WARN(txq_id != trans->shrd->cmd_queue,
|
||||
if (WARN(txq_id != trans_pcie->cmd_queue,
|
||||
"wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
|
||||
txq_id, trans->shrd->cmd_queue, sequence,
|
||||
trans_pcie->txq[trans->shrd->cmd_queue].q.read_ptr,
|
||||
trans_pcie->txq[trans->shrd->cmd_queue].q.write_ptr)) {
|
||||
txq_id, trans_pcie->cmd_queue, sequence,
|
||||
trans_pcie->txq[trans_pcie->cmd_queue].q.read_ptr,
|
||||
trans_pcie->txq[trans_pcie->cmd_queue].q.write_ptr)) {
|
||||
iwl_print_hex_error(trans, pkt, 32);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
cmd = txq->cmd[cmd_index];
|
||||
meta = &txq->meta[cmd_index];
|
||||
@ -875,12 +909,13 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
|
||||
|
||||
/* Input error checking is done when commands are added to queue. */
|
||||
if (meta->flags & CMD_WANT_SKB) {
|
||||
meta->source->reply_page = (unsigned long)rxb_addr(rxb);
|
||||
meta->source->handler_status = handler_status;
|
||||
rxb->page = NULL;
|
||||
}
|
||||
struct page *p = rxb_steal_page(rxb);
|
||||
|
||||
spin_lock_irqsave(&trans->hcmd_lock, flags);
|
||||
meta->source->resp_pkt = pkt;
|
||||
meta->source->_rx_page_addr = (unsigned long)page_address(p);
|
||||
meta->source->_rx_page_order = hw_params(trans).rx_page_order;
|
||||
meta->source->handler_status = handler_status;
|
||||
}
|
||||
|
||||
iwl_hcmd_queue_reclaim(trans, txq_id, index);
|
||||
|
||||
@ -898,7 +933,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
|
||||
|
||||
meta->flags = 0;
|
||||
|
||||
spin_unlock_irqrestore(&trans->hcmd_lock, flags);
|
||||
spin_unlock(&txq->lock);
|
||||
}
|
||||
|
||||
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
|
||||
@ -912,12 +947,9 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
|
||||
return -EBUSY;
|
||||
|
||||
ret = iwl_enqueue_hcmd(trans, cmd);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_QUIET_RFKILL(trans,
|
||||
IWL_ERR(trans,
|
||||
"Error sending %s: enqueue_hcmd failed: %d\n",
|
||||
get_cmd_string(cmd->id), ret);
|
||||
return ret;
|
||||
@ -931,26 +963,22 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
int cmd_idx;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&trans->shrd->mutex);
|
||||
|
||||
IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
|
||||
get_cmd_string(cmd->id));
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
|
||||
return -EBUSY;
|
||||
|
||||
|
||||
if (test_bit(STATUS_RF_KILL_HW, &trans->shrd->status)) {
|
||||
IWL_ERR(trans, "Command %s aborted: RF KILL Switch\n",
|
||||
get_cmd_string(cmd->id));
|
||||
return -ECANCELED;
|
||||
}
|
||||
if (test_bit(STATUS_FW_ERROR, &trans->shrd->status)) {
|
||||
IWL_ERR(trans, "Command %s failed: FW Error\n",
|
||||
get_cmd_string(cmd->id));
|
||||
return -EIO;
|
||||
}
|
||||
set_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
|
||||
|
||||
if (WARN_ON(test_and_set_bit(STATUS_HCMD_ACTIVE,
|
||||
&trans->shrd->status))) {
|
||||
IWL_ERR(trans, "Command %s: a command is already active!\n",
|
||||
get_cmd_string(cmd->id));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(trans, "Setting HCMD_ACTIVE for command %s\n",
|
||||
get_cmd_string(cmd->id));
|
||||
|
||||
@ -958,7 +986,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (cmd_idx < 0) {
|
||||
ret = cmd_idx;
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
|
||||
IWL_DEBUG_QUIET_RFKILL(trans,
|
||||
IWL_ERR(trans,
|
||||
"Error sending %s: enqueue_hcmd failed: %d\n",
|
||||
get_cmd_string(cmd->id), ret);
|
||||
return ret;
|
||||
@ -970,15 +998,15 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (!ret) {
|
||||
if (test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status)) {
|
||||
struct iwl_tx_queue *txq =
|
||||
&trans_pcie->txq[trans->shrd->cmd_queue];
|
||||
&trans_pcie->txq[trans_pcie->cmd_queue];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
|
||||
IWL_DEBUG_QUIET_RFKILL(trans,
|
||||
IWL_ERR(trans,
|
||||
"Error sending %s: time out after %dms.\n",
|
||||
get_cmd_string(cmd->id),
|
||||
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
|
||||
|
||||
IWL_DEBUG_QUIET_RFKILL(trans,
|
||||
IWL_ERR(trans,
|
||||
"Current CMD queue read_ptr %d write_ptr %d\n",
|
||||
q->read_ptr, q->write_ptr);
|
||||
|
||||
@ -990,7 +1018,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
|
||||
if ((cmd->flags & CMD_WANT_SKB) && !cmd->resp_pkt) {
|
||||
IWL_ERR(trans, "Error: Response NULL in '%s'\n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -EIO;
|
||||
@ -1007,13 +1035,13 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
* in later, it will possibly set an invalid
|
||||
* address (cmd->meta.source).
|
||||
*/
|
||||
trans_pcie->txq[trans->shrd->cmd_queue].meta[cmd_idx].flags &=
|
||||
trans_pcie->txq[trans_pcie->cmd_queue].meta[cmd_idx].flags &=
|
||||
~CMD_WANT_SKB;
|
||||
}
|
||||
|
||||
if (cmd->reply_page) {
|
||||
iwl_free_pages(trans->shrd, cmd->reply_page);
|
||||
cmd->reply_page = 0;
|
||||
if (cmd->resp_pkt) {
|
||||
iwl_free_resp(cmd);
|
||||
cmd->resp_pkt = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -1038,9 +1066,11 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||
int freed = 0;
|
||||
|
||||
/* This function is not meant to release cmd queue*/
|
||||
if (WARN_ON(txq_id == trans->shrd->cmd_queue))
|
||||
if (WARN_ON(txq_id == trans_pcie->cmd_queue))
|
||||
return 0;
|
||||
|
||||
lockdep_assert_held(&txq->lock);
|
||||
|
||||
/*Since we free until index _not_ inclusive, the one before index is
|
||||
* the last we will free. This one must be used */
|
||||
last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
|
||||
|
@ -75,8 +75,12 @@
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-ucode.h"
|
||||
|
||||
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
|
||||
|
||||
#define SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie) \
|
||||
(((1<<cfg(trans)->base_params->num_of_queues) - 1) &\
|
||||
(~(1<<(trans_pcie)->cmd_queue)))
|
||||
|
||||
static int iwl_trans_rx_alloc(struct iwl_trans *trans)
|
||||
{
|
||||
@ -301,6 +305,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
|
||||
{
|
||||
size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
|
||||
int i;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (WARN_ON(txq->meta || txq->cmd || txq->skbs || txq->tfds))
|
||||
return -EINVAL;
|
||||
@ -313,7 +318,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
|
||||
if (!txq->meta || !txq->cmd)
|
||||
goto error;
|
||||
|
||||
if (txq_id == trans->shrd->cmd_queue)
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < slots_num; i++) {
|
||||
txq->cmd[i] = kmalloc(sizeof(struct iwl_device_cmd),
|
||||
GFP_KERNEL);
|
||||
@ -324,7 +329,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
|
||||
/* Alloc driver data array and TFD circular buffer */
|
||||
/* Driver private data, only for Tx (not command) queues,
|
||||
* not shared with device. */
|
||||
if (txq_id != trans->shrd->cmd_queue) {
|
||||
if (txq_id != trans_pcie->cmd_queue) {
|
||||
txq->skbs = kcalloc(TFD_QUEUE_SIZE_MAX, sizeof(txq->skbs[0]),
|
||||
GFP_KERNEL);
|
||||
if (!txq->skbs) {
|
||||
@ -352,7 +357,7 @@ static int iwl_trans_txq_alloc(struct iwl_trans *trans,
|
||||
txq->skbs = NULL;
|
||||
/* since txq->cmd has been zeroed,
|
||||
* all non allocated cmd[i] will be NULL */
|
||||
if (txq->cmd && txq_id == trans->shrd->cmd_queue)
|
||||
if (txq->cmd && txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < slots_num; i++)
|
||||
kfree(txq->cmd[i]);
|
||||
kfree(txq->meta);
|
||||
@ -390,6 +395,8 @@ static int iwl_trans_txq_init(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_init(&txq->lock);
|
||||
|
||||
/*
|
||||
* Tell nic where to find circular buffer of Tx Frame Descriptors for
|
||||
* given Tx queue, and enable the DMA channel used for that queue.
|
||||
@ -409,8 +416,6 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
enum dma_data_direction dma_dir;
|
||||
unsigned long flags;
|
||||
spinlock_t *lock;
|
||||
|
||||
if (!q->n_bd)
|
||||
return;
|
||||
@ -418,22 +423,19 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
|
||||
/* In the command queue, all the TBs are mapped as BIDI
|
||||
* so unmap them as such.
|
||||
*/
|
||||
if (txq_id == trans->shrd->cmd_queue) {
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
dma_dir = DMA_BIDIRECTIONAL;
|
||||
lock = &trans->hcmd_lock;
|
||||
} else {
|
||||
else
|
||||
dma_dir = DMA_TO_DEVICE;
|
||||
lock = &trans->shrd->sta_lock;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(lock, flags);
|
||||
spin_lock_bh(&txq->lock);
|
||||
while (q->write_ptr != q->read_ptr) {
|
||||
/* The read_ptr needs to bound by q->n_window */
|
||||
iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
|
||||
dma_dir);
|
||||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
|
||||
}
|
||||
spin_unlock_irqrestore(lock, flags);
|
||||
spin_unlock_bh(&txq->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -457,7 +459,7 @@ static void iwl_tx_queue_free(struct iwl_trans *trans, int txq_id)
|
||||
|
||||
/* De-alloc array of command/tx buffers */
|
||||
|
||||
if (txq_id == trans->shrd->cmd_queue)
|
||||
if (txq_id == trans_pcie->cmd_queue)
|
||||
for (i = 0; i < txq->q.n_window; i++)
|
||||
kfree(txq->cmd[i]);
|
||||
|
||||
@ -495,7 +497,7 @@ static void iwl_trans_pcie_tx_free(struct iwl_trans *trans)
|
||||
/* Tx queues */
|
||||
if (trans_pcie->txq) {
|
||||
for (txq_id = 0;
|
||||
txq_id < hw_params(trans).max_txq_num; txq_id++)
|
||||
txq_id < cfg(trans)->base_params->num_of_queues; txq_id++)
|
||||
iwl_tx_queue_free(trans, txq_id);
|
||||
}
|
||||
|
||||
@ -520,7 +522,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
|
||||
int txq_id, slots_num;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
u16 scd_bc_tbls_size = hw_params(trans).max_txq_num *
|
||||
u16 scd_bc_tbls_size = cfg(trans)->base_params->num_of_queues *
|
||||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
|
||||
/*It is not allowed to alloc twice, so warn when this happens.
|
||||
@ -544,7 +546,7 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
|
||||
goto error;
|
||||
}
|
||||
|
||||
trans_pcie->txq = kcalloc(hw_params(trans).max_txq_num,
|
||||
trans_pcie->txq = kcalloc(cfg(trans)->base_params->num_of_queues,
|
||||
sizeof(struct iwl_tx_queue), GFP_KERNEL);
|
||||
if (!trans_pcie->txq) {
|
||||
IWL_ERR(trans, "Not enough memory for txq\n");
|
||||
@ -553,8 +555,9 @@ static int iwl_trans_tx_alloc(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
|
||||
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
|
||||
slots_num = (txq_id == trans->shrd->cmd_queue) ?
|
||||
for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
|
||||
txq_id++) {
|
||||
slots_num = (txq_id == trans_pcie->cmd_queue) ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
ret = iwl_trans_txq_alloc(trans, &trans_pcie->txq[txq_id],
|
||||
slots_num, txq_id);
|
||||
@ -598,8 +601,9 @@ static int iwl_tx_init(struct iwl_trans *trans)
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* Alloc and init all Tx queues, including the command queue (#4/#9) */
|
||||
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++) {
|
||||
slots_num = (txq_id == trans->shrd->cmd_queue) ?
|
||||
for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
|
||||
txq_id++) {
|
||||
slots_num = (txq_id == trans_pcie->cmd_queue) ?
|
||||
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
|
||||
ret = iwl_trans_txq_init(trans, &trans_pcie->txq[txq_id],
|
||||
slots_num, txq_id);
|
||||
@ -687,6 +691,7 @@ static void iwl_apm_config(struct iwl_trans *trans)
|
||||
*/
|
||||
static int iwl_apm_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret = 0;
|
||||
IWL_DEBUG_INFO(trans, "Init card's basic functions\n");
|
||||
|
||||
@ -756,7 +761,7 @@ static int iwl_apm_init(struct iwl_trans *trans)
|
||||
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
set_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
|
||||
set_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@ -782,9 +787,10 @@ static int iwl_apm_stop_master(struct iwl_trans *trans)
|
||||
|
||||
static void iwl_apm_stop(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
IWL_DEBUG_INFO(trans, "Stop card, put in low power state\n");
|
||||
|
||||
clear_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status);
|
||||
clear_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status);
|
||||
|
||||
/* Stop device's DMA activity */
|
||||
iwl_apm_stop_master(trans);
|
||||
@ -819,7 +825,7 @@ static int iwl_nic_init(struct iwl_trans *trans)
|
||||
|
||||
iwl_set_pwr_vmain(trans);
|
||||
|
||||
iwl_nic_config(priv(trans));
|
||||
iwl_op_mode_nic_config(trans->op_mode);
|
||||
|
||||
#ifndef CONFIG_IWLWIFI_IDI
|
||||
/* Allocate the RX queue, or reset if it is already allocated */
|
||||
@ -830,14 +836,12 @@ static int iwl_nic_init(struct iwl_trans *trans)
|
||||
if (iwl_tx_init(trans))
|
||||
return -ENOMEM;
|
||||
|
||||
if (hw_params(trans).shadow_reg_enable) {
|
||||
if (cfg(trans)->base_params->shadow_reg_enable) {
|
||||
/* enable shadow regs in HW */
|
||||
iwl_set_bit(trans, CSR_MAC_SHADOW_REG_CTRL,
|
||||
0x800FFFFF);
|
||||
}
|
||||
|
||||
set_bit(STATUS_INIT, &trans->shrd->status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -948,13 +952,14 @@ static const u8 iwlagn_pan_ac_to_queue[] = {
|
||||
* ucode
|
||||
*/
|
||||
static int iwl_load_section(struct iwl_trans *trans, const char *name,
|
||||
struct fw_desc *image, u32 dst_addr)
|
||||
const struct fw_desc *image, u32 dst_addr)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
dma_addr_t phy_addr = image->p_addr;
|
||||
u32 byte_cnt = image->len;
|
||||
int ret;
|
||||
|
||||
trans->ucode_write_complete = 0;
|
||||
trans_pcie->ucode_write_complete = false;
|
||||
|
||||
iwl_write_direct32(trans,
|
||||
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
|
||||
@ -985,8 +990,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name,
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
|
||||
|
||||
IWL_DEBUG_FW(trans, "%s uCode section being loaded...\n", name);
|
||||
ret = wait_event_timeout(trans->shrd->wait_command_queue,
|
||||
trans->ucode_write_complete, 5 * HZ);
|
||||
ret = wait_event_timeout(trans_pcie->ucode_write_waitq,
|
||||
trans_pcie->ucode_write_complete, 5 * HZ);
|
||||
if (!ret) {
|
||||
IWL_ERR(trans, "Could not load the %s uCode section\n",
|
||||
name);
|
||||
@ -996,7 +1001,8 @@ static int iwl_load_section(struct iwl_trans *trans, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
|
||||
static int iwl_load_given_ucode(struct iwl_trans *trans,
|
||||
const struct fw_img *image)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@ -1016,13 +1022,14 @@ static int iwl_load_given_ucode(struct iwl_trans *trans, struct fw_img *image)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
bool hw_rfkill;
|
||||
|
||||
trans->shrd->ucode_owner = IWL_OWNERSHIP_DRIVER;
|
||||
trans_pcie->ac_to_queue[IWL_RXON_CTX_BSS] = iwlagn_bss_ac_to_queue;
|
||||
trans_pcie->ac_to_queue[IWL_RXON_CTX_PAN] = iwlagn_pan_ac_to_queue;
|
||||
|
||||
@ -1032,22 +1039,19 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
trans_pcie->mcast_queue[IWL_RXON_CTX_BSS] = 0;
|
||||
trans_pcie->mcast_queue[IWL_RXON_CTX_PAN] = IWL_IPAN_MCAST_QUEUE;
|
||||
|
||||
if ((hw_params(trans).sku & EEPROM_SKU_CAP_AMT_ENABLE) &&
|
||||
iwl_prepare_card_hw(trans)) {
|
||||
/* This may fail if AMT took ownership of the device */
|
||||
if (iwl_prepare_card_hw(trans)) {
|
||||
IWL_WARN(trans, "Exit HW not ready\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* If platform's RF_KILL switch is NOT set to KILL */
|
||||
if (iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
|
||||
clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
else
|
||||
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
if (iwl_is_rfkill(trans->shrd)) {
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, true);
|
||||
iwl_enable_interrupts(trans);
|
||||
if (hw_rfkill) {
|
||||
iwl_enable_rfkill_int(trans);
|
||||
return -ERFKILL;
|
||||
}
|
||||
|
||||
@ -1073,9 +1077,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
||||
|
||||
/* Load the given image to the HW */
|
||||
iwl_load_given_ucode(trans, fw);
|
||||
|
||||
return 0;
|
||||
return iwl_load_given_ucode(trans, fw);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1116,7 +1118,8 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
a += 4)
|
||||
iwl_write_targ_mem(trans, a, 0);
|
||||
for (; a < trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(hw_params(trans).max_txq_num);
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(
|
||||
cfg(trans)->base_params->num_of_queues);
|
||||
a += 4)
|
||||
iwl_write_targ_mem(trans, a, 0);
|
||||
|
||||
@ -1135,11 +1138,11 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
|
||||
|
||||
iwl_write_prph(trans, SCD_QUEUECHAIN_SEL,
|
||||
SCD_QUEUECHAIN_SEL_ALL(trans));
|
||||
SCD_QUEUECHAIN_SEL_ALL(trans, trans_pcie));
|
||||
iwl_write_prph(trans, SCD_AGGR_SEL, 0);
|
||||
|
||||
/* initiate the queues */
|
||||
for (i = 0; i < hw_params(trans).max_txq_num; i++) {
|
||||
for (i = 0; i < cfg(trans)->base_params->num_of_queues; i++) {
|
||||
iwl_write_prph(trans, SCD_QUEUE_RDPTR(i), 0);
|
||||
iwl_write_direct32(trans, HBUS_TARG_WRPTR, 0 | (i << 8));
|
||||
iwl_write_targ_mem(trans, trans_pcie->scd_base_addr +
|
||||
@ -1156,7 +1159,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
iwl_write_prph(trans, SCD_INTERRUPT_MASK,
|
||||
IWL_MASK(0, hw_params(trans).max_txq_num));
|
||||
IWL_MASK(0, cfg(trans)->base_params->num_of_queues));
|
||||
|
||||
/* Activate all Tx DMA/FIFO channels */
|
||||
iwl_trans_txq_set_sched(trans, IWL_MASK(0, 7));
|
||||
@ -1167,7 +1170,7 @@ static void iwl_tx_start(struct iwl_trans *trans)
|
||||
else
|
||||
queue_to_fifo = iwlagn_default_queue_to_tx_fifo;
|
||||
|
||||
iwl_trans_set_wr_ptrs(trans, trans->shrd->cmd_queue, 0);
|
||||
iwl_trans_set_wr_ptrs(trans, trans_pcie->cmd_queue, 0);
|
||||
|
||||
/* make sure all queue are not stopped */
|
||||
memset(&trans_pcie->queue_stopped[0], 0,
|
||||
@ -1216,7 +1219,7 @@ static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans)
|
||||
*/
|
||||
static int iwl_trans_tx_stop(struct iwl_trans *trans)
|
||||
{
|
||||
int ch, txq_id;
|
||||
int ch, txq_id, ret;
|
||||
unsigned long flags;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
@ -1229,9 +1232,10 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
|
||||
for (ch = 0; ch < FH_TCSR_CHNL_NUM; ch++) {
|
||||
iwl_write_direct32(trans,
|
||||
FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
|
||||
if (iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
|
||||
ret = iwl_poll_direct_bit(trans, FH_TSSR_TX_STATUS_REG,
|
||||
FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
|
||||
1000))
|
||||
1000);
|
||||
if (ret < 0)
|
||||
IWL_ERR(trans, "Failing on timeout while stopping"
|
||||
" DMA channel %d [0x%08x]", ch,
|
||||
iwl_read_direct32(trans,
|
||||
@ -1245,7 +1249,8 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
/* Unmap DMA from host system and free skb's */
|
||||
for (txq_id = 0; txq_id < hw_params(trans).max_txq_num; txq_id++)
|
||||
for (txq_id = 0; txq_id < cfg(trans)->base_params->num_of_queues;
|
||||
txq_id++)
|
||||
iwl_tx_queue_unmap(trans, txq_id);
|
||||
|
||||
return 0;
|
||||
@ -1271,7 +1276,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
* restart. So don't process again if the device is
|
||||
* already dead.
|
||||
*/
|
||||
if (test_bit(STATUS_DEVICE_ENABLED, &trans->shrd->status)) {
|
||||
if (test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) {
|
||||
iwl_trans_tx_stop(trans);
|
||||
#ifndef CONFIG_IWLWIFI_IDI
|
||||
iwl_trans_rx_stop(trans);
|
||||
@ -1297,7 +1302,7 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
/* wait to make sure we flush pending tasklet*/
|
||||
synchronize_irq(trans->irq);
|
||||
synchronize_irq(trans_pcie->irq);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
|
||||
cancel_work_sync(&trans_pcie->rx_replenish);
|
||||
@ -1306,6 +1311,17 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
/* let the ucode operate on its own */
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
iwl_disable_interrupts(trans);
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id, u8 tid)
|
||||
@ -1358,6 +1374,8 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
txq = &trans_pcie->txq[txq_id];
|
||||
q = &txq->q;
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
|
||||
/* In AGG mode, the index in the ring must correspond to the WiFi
|
||||
* sequence number. This is a HW requirements to help the SCD to parse
|
||||
* the BA.
|
||||
@ -1404,7 +1422,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
&dev_cmd->hdr, firstlen,
|
||||
DMA_BIDIRECTIONAL);
|
||||
if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
|
||||
return -1;
|
||||
goto out_err;
|
||||
dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
|
||||
dma_unmap_len_set(out_meta, len, firstlen);
|
||||
|
||||
@ -1426,7 +1444,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
dma_unmap_addr(out_meta, mapping),
|
||||
dma_unmap_len(out_meta, len),
|
||||
DMA_BIDIRECTIONAL);
|
||||
return -1;
|
||||
goto out_err;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1457,7 +1475,7 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
trace_iwlwifi_dev_tx(priv(trans),
|
||||
trace_iwlwifi_dev_tx(trans->dev,
|
||||
&((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
|
||||
sizeof(struct iwl_tfd),
|
||||
&dev_cmd->hdr, firstlen,
|
||||
@ -1478,10 +1496,14 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
txq->need_update = 1;
|
||||
iwl_txq_update_write_ptr(trans, txq);
|
||||
} else {
|
||||
iwl_stop_queue(trans, txq, "Queue is full");
|
||||
iwl_stop_queue(trans, txq);
|
||||
}
|
||||
}
|
||||
spin_unlock(&txq->lock);
|
||||
return 0;
|
||||
out_err:
|
||||
spin_unlock(&txq->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
@ -1489,6 +1511,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int err;
|
||||
bool hw_rfkill;
|
||||
|
||||
trans_pcie->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
@ -1498,11 +1521,11 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
|
||||
iwl_alloc_isr_ict(trans);
|
||||
|
||||
err = request_irq(trans->irq, iwl_isr_ict, IRQF_SHARED,
|
||||
err = request_irq(trans_pcie->irq, iwl_isr_ict, IRQF_SHARED,
|
||||
DRV_NAME, trans);
|
||||
if (err) {
|
||||
IWL_ERR(trans, "Error allocating IRQ %d\n",
|
||||
trans->irq);
|
||||
trans_pcie->irq);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -1518,21 +1541,14 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
|
||||
iwl_apm_init(trans);
|
||||
|
||||
/* If platform's RF_KILL switch is NOT set to KILL */
|
||||
if (iwl_read32(trans,
|
||||
CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
|
||||
clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
else
|
||||
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode,
|
||||
test_bit(STATUS_RF_KILL_HW,
|
||||
&trans->shrd->status));
|
||||
hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
return err;
|
||||
|
||||
err_free_irq:
|
||||
free_irq(trans->irq, trans);
|
||||
free_irq(trans_pcie->irq, trans);
|
||||
error:
|
||||
iwl_free_isr_ict(trans);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
@ -1546,13 +1562,11 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans)
|
||||
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
||||
|
||||
/* Even if we stop the HW, we still want the RF kill interrupt */
|
||||
IWL_DEBUG_ISR(trans, "Enabling rfkill interrupt\n");
|
||||
iwl_write32(trans, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
|
||||
iwl_enable_rfkill_int(trans);
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
||||
int txq_id, int ssn, u32 status,
|
||||
struct sk_buff_head *skbs)
|
||||
int txq_id, int ssn, struct sk_buff_head *skbs)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
||||
@ -1560,6 +1574,8 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
||||
int tfd_num = ssn & (txq->q.n_bd - 1);
|
||||
int freed = 0;
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
|
||||
txq->time_stamp = jiffies;
|
||||
|
||||
if (unlikely(txq_id >= IWLAGN_FIRST_AMPDU_QUEUE &&
|
||||
@ -1574,6 +1590,7 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Bad queue mapping txq_id %d, "
|
||||
"agg_txq[sta_id[tid] %d", txq_id,
|
||||
trans_pcie->agg_txq[sta_id][tid]);
|
||||
spin_unlock(&txq->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1582,28 +1599,35 @@ static int iwl_trans_pcie_reclaim(struct iwl_trans *trans, int sta_id, int tid,
|
||||
txq_id, iwl_get_queue_ac(txq), txq->q.read_ptr,
|
||||
tfd_num, ssn);
|
||||
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
|
||||
if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
|
||||
(!txq->sched_retry ||
|
||||
status != TX_STATUS_FAIL_PASSIVE_NO_RX))
|
||||
iwl_wake_queue(trans, txq, "Packets reclaimed");
|
||||
if (iwl_queue_space(&txq->q) > txq->q.low_mark)
|
||||
iwl_wake_queue(trans, txq);
|
||||
}
|
||||
|
||||
spin_unlock(&txq->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_write8(struct iwl_trans *trans, u32 ofs, u8 val)
|
||||
{
|
||||
iowrite8(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
writeb(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_write32(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
{
|
||||
iowrite32(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
writel(val, IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
}
|
||||
|
||||
static u32 iwl_trans_pcie_read32(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
u32 val = ioread32(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
return val;
|
||||
return readl(IWL_TRANS_GET_PCIE_TRANS(trans)->hw_base + ofs);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
trans_pcie->cmd_queue = trans_cfg->cmd_queue;
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
@ -1611,18 +1635,17 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
iwl_calib_free_results(trans);
|
||||
iwl_trans_pcie_tx_free(trans);
|
||||
#ifndef CONFIG_IWLWIFI_IDI
|
||||
iwl_trans_pcie_rx_free(trans);
|
||||
#endif
|
||||
if (trans_pcie->irq_requested == true) {
|
||||
free_irq(trans->irq, trans);
|
||||
free_irq(trans_pcie->irq, trans);
|
||||
iwl_free_isr_ict(trans);
|
||||
}
|
||||
|
||||
pci_disable_msi(trans_pcie->pci_dev);
|
||||
pci_iounmap(trans_pcie->pci_dev, trans_pcie->hw_base);
|
||||
iounmap(trans_pcie->hw_base);
|
||||
pci_release_regions(trans_pcie->pci_dev);
|
||||
pci_disable_device(trans_pcie->pci_dev);
|
||||
|
||||
@ -1633,42 +1656,20 @@ static void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int iwl_trans_pcie_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
/*
|
||||
* This function is called when system goes into suspend state
|
||||
* mac80211 will call iwlagn_mac_stop() from the mac80211 suspend
|
||||
* function first but since iwlagn_mac_stop() has no knowledge of
|
||||
* who the caller is,
|
||||
* it will not call apm_ops.stop() to stop the DMA operation.
|
||||
* Calling apm_ops.stop here to make sure we stop the DMA.
|
||||
*
|
||||
* But of course ... if we have configured WoWLAN then we did other
|
||||
* things already :-)
|
||||
*/
|
||||
if (!trans->shrd->wowlan) {
|
||||
iwl_apm_stop(trans);
|
||||
} else {
|
||||
iwl_disable_interrupts(trans);
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_resume(struct iwl_trans *trans)
|
||||
{
|
||||
bool hw_rfkill = false;
|
||||
bool hw_rfkill;
|
||||
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
if (!(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
|
||||
hw_rfkill = true;
|
||||
hw_rfkill = !(iwl_read32(trans, CSR_GP_CNTRL) &
|
||||
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
|
||||
if (hw_rfkill)
|
||||
set_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
iwl_enable_rfkill_int(trans);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &trans->shrd->status);
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
@ -1676,32 +1677,6 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static void iwl_trans_pcie_wake_any_queue(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
const char *msg)
|
||||
{
|
||||
u8 ac, txq_id;
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
for (ac = 0; ac < AC_NUM; ac++) {
|
||||
txq_id = trans_pcie->ac_to_queue[ctx][ac];
|
||||
IWL_DEBUG_TX_QUEUES(trans, "Queue Status: Q[%d] %s\n",
|
||||
ac,
|
||||
(atomic_read(&trans_pcie->queue_stop_count[ac]) > 0)
|
||||
? "stopped" : "awake");
|
||||
iwl_wake_queue(trans, &trans_pcie->txq[txq_id], msg);
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_stop_queue(struct iwl_trans *trans, int txq_id,
|
||||
const char *msg)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
iwl_stop_queue(trans, &trans_pcie->txq[txq_id], msg);
|
||||
}
|
||||
|
||||
#define IWL_FLUSH_WAIT_MS 2000
|
||||
|
||||
static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
|
||||
@ -1714,8 +1689,8 @@ static int iwl_trans_pcie_wait_tx_queue_empty(struct iwl_trans *trans)
|
||||
int ret = 0;
|
||||
|
||||
/* waiting for all the tx frames complete might take a while */
|
||||
for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
|
||||
if (cnt == trans->shrd->cmd_queue)
|
||||
for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
|
||||
if (cnt == trans_pcie->cmd_queue)
|
||||
continue;
|
||||
txq = &trans_pcie->txq[cnt];
|
||||
q = &txq->q;
|
||||
@ -1960,7 +1935,9 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
|
||||
int pos = 0;
|
||||
int cnt;
|
||||
int ret;
|
||||
const size_t bufsz = sizeof(char) * 64 * hw_params(trans).max_txq_num;
|
||||
size_t bufsz;
|
||||
|
||||
bufsz = sizeof(char) * 64 * cfg(trans)->base_params->num_of_queues;
|
||||
|
||||
if (!trans_pcie->txq) {
|
||||
IWL_ERR(trans, "txq not ready\n");
|
||||
@ -1970,7 +1947,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (cnt = 0; cnt < hw_params(trans).max_txq_num; cnt++) {
|
||||
for (cnt = 0; cnt < cfg(trans)->base_params->num_of_queues; cnt++) {
|
||||
txq = &trans_pcie->txq[cnt];
|
||||
q = &txq->q;
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
@ -2219,7 +2196,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
|
||||
.start_fw = iwl_trans_pcie_start_fw,
|
||||
.stop_device = iwl_trans_pcie_stop_device,
|
||||
|
||||
.wake_any_queue = iwl_trans_pcie_wake_any_queue,
|
||||
.wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
|
||||
|
||||
.send_cmd = iwl_trans_pcie_send_cmd,
|
||||
|
||||
@ -2231,7 +2208,6 @@ const struct iwl_trans_ops trans_ops_pcie = {
|
||||
.tx_agg_setup = iwl_trans_pcie_tx_agg_setup,
|
||||
|
||||
.free = iwl_trans_pcie_free,
|
||||
.stop_queue = iwl_trans_pcie_stop_queue,
|
||||
|
||||
.dbgfs_register = iwl_trans_pcie_dbgfs_register,
|
||||
|
||||
@ -2245,6 +2221,7 @@ const struct iwl_trans_ops trans_ops_pcie = {
|
||||
.write8 = iwl_trans_pcie_write8,
|
||||
.write32 = iwl_trans_pcie_write32,
|
||||
.read32 = iwl_trans_pcie_read32,
|
||||
.configure = iwl_trans_pcie_configure,
|
||||
};
|
||||
|
||||
struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
|
||||
@ -2267,8 +2244,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
|
||||
trans->ops = &trans_ops_pcie;
|
||||
trans->shrd = shrd;
|
||||
trans_pcie->trans = trans;
|
||||
spin_lock_init(&trans->hcmd_lock);
|
||||
spin_lock_init(&trans_pcie->irq_lock);
|
||||
init_waitqueue_head(&trans_pcie->ucode_write_waitq);
|
||||
|
||||
/* W/A - seems to solve weird behavior. We need to remove this if we
|
||||
* don't want to stay in L1 all the time. This wastes a lot of power */
|
||||
@ -2304,9 +2281,9 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
|
||||
goto out_pci_disable_device;
|
||||
}
|
||||
|
||||
trans_pcie->hw_base = pci_iomap(pdev, 0, 0);
|
||||
trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
|
||||
if (!trans_pcie->hw_base) {
|
||||
dev_printk(KERN_ERR, &pdev->dev, "pci_iomap failed");
|
||||
dev_printk(KERN_ERR, &pdev->dev, "pci_ioremap_bar failed");
|
||||
err = -ENODEV;
|
||||
goto out_pci_release_regions;
|
||||
}
|
||||
@ -2330,7 +2307,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct iwl_shared *shrd,
|
||||
"pci_enable_msi failed(0X%x)", err);
|
||||
|
||||
trans->dev = &pdev->dev;
|
||||
trans->irq = pdev->irq;
|
||||
trans_pcie->irq = pdev->irq;
|
||||
trans_pcie->pci_dev = pdev;
|
||||
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
|
||||
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
|
||||
|
@ -64,6 +64,7 @@
|
||||
#define __iwl_trans_h__
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/mm.h> /* for page_address */
|
||||
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-debug.h"
|
||||
@ -121,6 +122,62 @@ struct dentry;
|
||||
#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
|
||||
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
|
||||
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
|
||||
#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f)
|
||||
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
|
||||
#define SEQ_TO_INDEX(s) ((s) & 0xff)
|
||||
#define INDEX_TO_SEQ(i) ((i) & 0xff)
|
||||
#define SEQ_RX_FRAME cpu_to_le16(0x8000)
|
||||
|
||||
/**
|
||||
* struct iwl_cmd_header
|
||||
*
|
||||
* This header format appears in the beginning of each command sent from the
|
||||
* driver, and each response/notification received from uCode.
|
||||
*/
|
||||
struct iwl_cmd_header {
|
||||
u8 cmd; /* Command ID: REPLY_RXON, etc. */
|
||||
u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
|
||||
/*
|
||||
* The driver sets up the sequence number to values of its choosing.
|
||||
* uCode does not use this value, but passes it back to the driver
|
||||
* when sending the response to each driver-originated command, so
|
||||
* the driver can match the response to the command. Since the values
|
||||
* don't get used by uCode, the driver may set up an arbitrary format.
|
||||
*
|
||||
* There is one exception: uCode sets bit 15 when it originates
|
||||
* the response/notification, i.e. when the response/notification
|
||||
* is not a direct response to a command sent by the driver. For
|
||||
* example, uCode issues REPLY_RX when it sends a received frame
|
||||
* to the driver; it is not a direct response to any driver command.
|
||||
*
|
||||
* The Linux driver uses the following format:
|
||||
*
|
||||
* 0:7 tfd index - position within TX queue
|
||||
* 8:12 TX queue id
|
||||
* 13:14 reserved
|
||||
* 15 unsolicited RX or uCode-originated notification
|
||||
*/
|
||||
__le16 sequence;
|
||||
} __packed;
|
||||
|
||||
|
||||
#define FH_RSCSR_FRAME_SIZE_MSK 0x00003FFF /* bits 0-13 */
|
||||
|
||||
struct iwl_rx_packet {
|
||||
/*
|
||||
* The first 4 bytes of the RX frame header contain both the RX frame
|
||||
* size and some flags.
|
||||
* Bit fields:
|
||||
* 31: flag flush RB request
|
||||
* 30: flag ignore TC (terminal counter) request
|
||||
* 29: flag fast IRQ request
|
||||
* 28-14: Reserved
|
||||
* 13-00: RX frame size
|
||||
*/
|
||||
__le32 len_n_flags;
|
||||
struct iwl_cmd_header hdr;
|
||||
u8 data[];
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* enum CMD_MODE - how to send the host commands ?
|
||||
@ -173,7 +230,9 @@ enum iwl_hcmd_dataflag {
|
||||
* struct iwl_host_cmd - Host command to the uCode
|
||||
*
|
||||
* @data: array of chunks that composes the data of the host command
|
||||
* @reply_page: pointer to the page that holds the response to the host command
|
||||
* @resp_pkt: response packet, if %CMD_WANT_SKB was set
|
||||
* @_rx_page_order: (internally used to free response packet)
|
||||
* @_rx_page_addr: (internally used to free response packet)
|
||||
* @handler_status: return value of the handler of the command
|
||||
* (put in setup_rx_handlers) - valid for SYNC mode only
|
||||
* @flags: can be CMD_*
|
||||
@ -183,7 +242,9 @@ enum iwl_hcmd_dataflag {
|
||||
*/
|
||||
struct iwl_host_cmd {
|
||||
const void *data[IWL_MAX_CMD_TFDS];
|
||||
unsigned long reply_page;
|
||||
struct iwl_rx_packet *resp_pkt;
|
||||
unsigned long _rx_page_addr;
|
||||
u32 _rx_page_order;
|
||||
int handler_status;
|
||||
|
||||
u32 flags;
|
||||
@ -192,6 +253,40 @@ struct iwl_host_cmd {
|
||||
u8 id;
|
||||
};
|
||||
|
||||
static inline void iwl_free_resp(struct iwl_host_cmd *cmd)
|
||||
{
|
||||
free_pages(cmd->_rx_page_addr, cmd->_rx_page_order);
|
||||
}
|
||||
|
||||
struct iwl_rx_cmd_buffer {
|
||||
struct page *_page;
|
||||
};
|
||||
|
||||
static inline void *rxb_addr(struct iwl_rx_cmd_buffer *r)
|
||||
{
|
||||
return page_address(r->_page);
|
||||
}
|
||||
|
||||
static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
|
||||
{
|
||||
struct page *p = r->_page;
|
||||
r->_page = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
/**
|
||||
* struct iwl_trans_config - transport configuration
|
||||
*
|
||||
* @op_mode: pointer to the upper layer.
|
||||
* Must be set before any other call.
|
||||
* @cmd_queue: the index of the command queue.
|
||||
* Must be set before start_fw.
|
||||
*/
|
||||
struct iwl_trans_config {
|
||||
struct iwl_op_mode *op_mode;
|
||||
u8 cmd_queue;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_ops - transport specific operations
|
||||
*
|
||||
@ -207,9 +302,11 @@ struct iwl_host_cmd {
|
||||
* May sleep
|
||||
* @fw_alive: called when the fw sends alive notification
|
||||
* May sleep
|
||||
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
|
||||
* @stop_device:stops the whole device (embedded CPU put to reset)
|
||||
* May sleep
|
||||
* @wowlan_suspend: put the device into the correct mode for WoWLAN during
|
||||
* suspend. This is optional, if not implemented WoWLAN will not be
|
||||
* supported. This callback may sleep.
|
||||
* @send_cmd:send a host command
|
||||
* May sleep only if CMD_SYNC is set
|
||||
* @tx: send an skb
|
||||
@ -217,17 +314,16 @@ struct iwl_host_cmd {
|
||||
* @reclaim: free packet until ssn. Returns a list of freed packets.
|
||||
* Must be atomic
|
||||
* @tx_agg_alloc: allocate resources for a TX BA session
|
||||
* May sleep
|
||||
* Must be atomic
|
||||
* @tx_agg_setup: setup a tx queue for AMPDU - will be called once the HW is
|
||||
* ready and a successful ADDBA response has been received.
|
||||
* May sleep
|
||||
* @tx_agg_disable: de-configure a Tx queue to send AMPDUs
|
||||
* May sleep
|
||||
* Must be atomic
|
||||
* @free: release all the ressource for the transport layer itself such as
|
||||
* irq, tasklet etc... From this point on, the device may not issue
|
||||
* any interrupt (incl. RFKILL).
|
||||
* May sleep
|
||||
* @stop_queue: stop a specific queue
|
||||
* @check_stuck_queue: check if a specific queue is stuck
|
||||
* @wait_tx_queue_empty: wait until all tx queues are empty
|
||||
* May sleep
|
||||
@ -238,18 +334,19 @@ struct iwl_host_cmd {
|
||||
* @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
|
||||
* @configure: configure parameters required by the transport layer from
|
||||
* the op_mode. May be called several times before start_fw, can't be
|
||||
* called after that.
|
||||
*/
|
||||
struct iwl_trans_ops {
|
||||
|
||||
int (*start_hw)(struct iwl_trans *iwl_trans);
|
||||
void (*stop_hw)(struct iwl_trans *iwl_trans);
|
||||
int (*start_fw)(struct iwl_trans *trans, struct fw_img *fw);
|
||||
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
|
||||
void (*fw_alive)(struct iwl_trans *trans);
|
||||
void (*stop_device)(struct iwl_trans *trans);
|
||||
|
||||
void (*wake_any_queue)(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
const char *msg);
|
||||
void (*wowlan_suspend)(struct iwl_trans *trans);
|
||||
|
||||
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
||||
@ -257,8 +354,7 @@ struct iwl_trans_ops {
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id, u8 tid);
|
||||
int (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
|
||||
int txq_id, int ssn, u32 status,
|
||||
struct sk_buff_head *skbs);
|
||||
int txq_id, int ssn, struct sk_buff_head *skbs);
|
||||
|
||||
int (*tx_agg_disable)(struct iwl_trans *trans,
|
||||
int sta_id, int tid);
|
||||
@ -270,8 +366,6 @@ struct iwl_trans_ops {
|
||||
|
||||
void (*free)(struct iwl_trans *trans);
|
||||
|
||||
void (*stop_queue)(struct iwl_trans *trans, int q, const char *msg);
|
||||
|
||||
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
|
||||
int (*check_stuck_queue)(struct iwl_trans *trans, int q);
|
||||
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
|
||||
@ -282,14 +376,8 @@ struct iwl_trans_ops {
|
||||
void (*write8)(struct iwl_trans *trans, u32 ofs, u8 val);
|
||||
void (*write32)(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
|
||||
};
|
||||
|
||||
/* Opaque calibration results */
|
||||
struct iwl_calib_result {
|
||||
struct list_head list;
|
||||
size_t cmd_len;
|
||||
struct iwl_calib_hdr hdr;
|
||||
/* data follows */
|
||||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -309,52 +397,44 @@ enum iwl_trans_state {
|
||||
* @ops - pointer to iwl_trans_ops
|
||||
* @op_mode - pointer to the op_mode
|
||||
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
|
||||
* @hcmd_lock: protects HCMD
|
||||
* @reg_lock - protect hw register access
|
||||
* @dev - pointer to struct device * that represents the device
|
||||
* @irq - the irq number for the device
|
||||
* @hw_id: a u32 with the ID of the device / subdevice.
|
||||
* Set during transport allocation.
|
||||
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
|
||||
* @ucode_write_complete: indicates that the ucode has been copied.
|
||||
* @nvm_device_type: indicates OTP or eeprom
|
||||
* @pm_support: set to true in start_hw if link pm is supported
|
||||
* @calib_results: list head for init calibration results
|
||||
*/
|
||||
struct iwl_trans {
|
||||
const struct iwl_trans_ops *ops;
|
||||
struct iwl_op_mode *op_mode;
|
||||
struct iwl_shared *shrd;
|
||||
enum iwl_trans_state state;
|
||||
spinlock_t hcmd_lock;
|
||||
spinlock_t reg_lock;
|
||||
|
||||
struct device *dev;
|
||||
unsigned int irq;
|
||||
u32 hw_rev;
|
||||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
|
||||
u8 ucode_write_complete;
|
||||
|
||||
int nvm_device_type;
|
||||
bool pm_support;
|
||||
|
||||
struct list_head calib_results;
|
||||
|
||||
/* pointer to trans specific struct */
|
||||
/*Ensure that this pointer will always be aligned to sizeof pointer */
|
||||
char trans_specific[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
static inline void iwl_trans_configure(struct iwl_trans *trans,
|
||||
struct iwl_op_mode *op_mode)
|
||||
const struct iwl_trans_config *trans_cfg)
|
||||
{
|
||||
/*
|
||||
* only set the op_mode for the moment. Later on, this function will do
|
||||
* more
|
||||
*/
|
||||
trans->op_mode = op_mode;
|
||||
trans->op_mode = trans_cfg->op_mode;
|
||||
|
||||
trans->ops->configure(trans, trans_cfg);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_start_hw(struct iwl_trans *trans)
|
||||
@ -382,7 +462,8 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans)
|
||||
trans->state = IWL_TRANS_FW_ALIVE;
|
||||
}
|
||||
|
||||
static inline int iwl_trans_start_fw(struct iwl_trans *trans, struct fw_img *fw)
|
||||
static inline int iwl_trans_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
@ -398,17 +479,12 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
const char *msg)
|
||||
static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
trans->ops->wake_any_queue(trans, ctx, msg);
|
||||
might_sleep();
|
||||
trans->ops->wowlan_suspend(trans);
|
||||
}
|
||||
|
||||
|
||||
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
struct iwl_host_cmd *cmd)
|
||||
{
|
||||
@ -418,9 +494,6 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
return trans->ops->send_cmd(trans, cmd);
|
||||
}
|
||||
|
||||
int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
||||
u32 flags, u16 len, const void *data);
|
||||
|
||||
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id, u8 tid)
|
||||
@ -432,21 +505,18 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
}
|
||||
|
||||
static inline int iwl_trans_reclaim(struct iwl_trans *trans, int sta_id,
|
||||
int tid, int txq_id, int ssn, u32 status,
|
||||
int tid, int txq_id, int ssn,
|
||||
struct sk_buff_head *skbs)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn,
|
||||
status, skbs);
|
||||
return trans->ops->reclaim(trans, sta_id, tid, txq_id, ssn, skbs);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
|
||||
int sta_id, int tid)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
@ -456,8 +526,6 @@ static inline int iwl_trans_tx_agg_disable(struct iwl_trans *trans,
|
||||
static inline int iwl_trans_tx_agg_alloc(struct iwl_trans *trans,
|
||||
int sta_id, int tid)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
@ -483,15 +551,6 @@ static inline void iwl_trans_free(struct iwl_trans *trans)
|
||||
trans->ops->free(trans);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_stop_queue(struct iwl_trans *trans, int q,
|
||||
const char *msg)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
|
||||
|
||||
trans->ops->stop_queue(trans, q, msg);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
|
||||
{
|
||||
if (trans->state != IWL_TRANS_FW_ALIVE)
|
||||
@ -540,14 +599,6 @@ static inline u32 iwl_trans_read32(struct iwl_trans *trans, u32 ofs)
|
||||
return trans->ops->read32(trans, ofs);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Utils functions
|
||||
******************************************************/
|
||||
int iwl_send_calib_results(struct iwl_trans *trans);
|
||||
int iwl_calib_set(struct iwl_trans *trans,
|
||||
const struct iwl_calib_hdr *cmd, int len);
|
||||
void iwl_calib_free_results(struct iwl_trans *trans);
|
||||
|
||||
/*****************************************************
|
||||
* Transport layers implementations + their allocation function
|
||||
******************************************************/
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <net/genetlink.h>
|
||||
#include "mac80211_hwsim.h"
|
||||
|
||||
@ -321,11 +322,15 @@ struct mac80211_hwsim_data {
|
||||
struct dentry *debugfs_group;
|
||||
|
||||
int power_level;
|
||||
|
||||
/* difference between this hw's clock and the real clock, in usecs */
|
||||
u64 tsf_offset;
|
||||
};
|
||||
|
||||
|
||||
struct hwsim_radiotap_hdr {
|
||||
struct ieee80211_radiotap_header hdr;
|
||||
__le64 rt_tsft;
|
||||
u8 rt_flags;
|
||||
u8 rt_rate;
|
||||
__le16 rt_channel;
|
||||
@ -367,6 +372,28 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
|
||||
{
|
||||
struct timeval tv = ktime_to_timeval(ktime_get_real());
|
||||
u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
|
||||
return cpu_to_le64(now + data->tsf_offset);
|
||||
}
|
||||
|
||||
static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
return le64_to_cpu(__mac80211_hwsim_get_tsf(data));
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u64 tsf)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
struct timeval tv = ktime_to_timeval(ktime_get_real());
|
||||
u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
|
||||
data->tsf_offset = tsf - now;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
|
||||
struct sk_buff *tx_skb)
|
||||
@ -391,7 +418,9 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
|
||||
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
|
||||
hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
|
||||
(1 << IEEE80211_RADIOTAP_RATE) |
|
||||
(1 << IEEE80211_RADIOTAP_TSFT) |
|
||||
(1 << IEEE80211_RADIOTAP_CHANNEL));
|
||||
hdr->rt_tsft = __mac80211_hwsim_get_tsf(data);
|
||||
hdr->rt_flags = 0;
|
||||
hdr->rt_rate = txrate->bitrate / 5;
|
||||
hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
|
||||
@ -610,7 +639,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
memset(&rx_status, 0, sizeof(rx_status));
|
||||
/* TODO: set mactime */
|
||||
rx_status.mactime = le64_to_cpu(__mac80211_hwsim_get_tsf(data));
|
||||
rx_status.flag |= RX_FLAG_MACTIME_MPDU;
|
||||
rx_status.freq = data->channel->center_freq;
|
||||
rx_status.band = data->channel->band;
|
||||
rx_status.rate_idx = info->control.rates[0].idx;
|
||||
@ -667,6 +697,12 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
bool ack;
|
||||
struct ieee80211_tx_info *txi;
|
||||
u32 _pid;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
|
||||
if (ieee80211_is_beacon(mgmt->frame_control) ||
|
||||
ieee80211_is_probe_resp(mgmt->frame_control))
|
||||
mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
|
||||
|
||||
mac80211_hwsim_monitor_rx(hw, skb);
|
||||
|
||||
@ -763,9 +799,11 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = arg;
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *info;
|
||||
u32 _pid;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
|
||||
hwsim_check_magic(vif);
|
||||
|
||||
@ -779,6 +817,9 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
||||
return;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
mgmt->u.beacon.timestamp = __mac80211_hwsim_get_tsf(data);
|
||||
|
||||
mac80211_hwsim_monitor_rx(hw, skb);
|
||||
|
||||
/* wmediumd mode check */
|
||||
@ -1199,6 +1240,8 @@ static struct ieee80211_ops mac80211_hwsim_ops =
|
||||
.sw_scan_start = mac80211_hwsim_sw_scan,
|
||||
.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
|
||||
.flush = mac80211_hwsim_flush,
|
||||
.get_tsf = mac80211_hwsim_get_tsf,
|
||||
.set_tsf = mac80211_hwsim_set_tsf,
|
||||
};
|
||||
|
||||
|
||||
|
@ -613,7 +613,6 @@ static struct ieee80211_rate mwifiex_rates[] = {
|
||||
{.bitrate = 20, .hw_value = 4, },
|
||||
{.bitrate = 55, .hw_value = 11, },
|
||||
{.bitrate = 110, .hw_value = 22, },
|
||||
{.bitrate = 220, .hw_value = 44, },
|
||||
{.bitrate = 60, .hw_value = 12, },
|
||||
{.bitrate = 90, .hw_value = 18, },
|
||||
{.bitrate = 120, .hw_value = 24, },
|
||||
@ -622,7 +621,6 @@ static struct ieee80211_rate mwifiex_rates[] = {
|
||||
{.bitrate = 360, .hw_value = 72, },
|
||||
{.bitrate = 480, .hw_value = 96, },
|
||||
{.bitrate = 540, .hw_value = 108, },
|
||||
{.bitrate = 720, .hw_value = 144, },
|
||||
};
|
||||
|
||||
/* Channel definitions to be advertised to cfg80211 */
|
||||
@ -648,7 +646,7 @@ static struct ieee80211_supported_band mwifiex_band_2ghz = {
|
||||
.channels = mwifiex_channels_2ghz,
|
||||
.n_channels = ARRAY_SIZE(mwifiex_channels_2ghz),
|
||||
.bitrates = mwifiex_rates,
|
||||
.n_bitrates = 14,
|
||||
.n_bitrates = ARRAY_SIZE(mwifiex_rates),
|
||||
};
|
||||
|
||||
static struct ieee80211_channel mwifiex_channels_5ghz[] = {
|
||||
@ -688,8 +686,8 @@ static struct ieee80211_channel mwifiex_channels_5ghz[] = {
|
||||
static struct ieee80211_supported_band mwifiex_band_5ghz = {
|
||||
.channels = mwifiex_channels_5ghz,
|
||||
.n_channels = ARRAY_SIZE(mwifiex_channels_5ghz),
|
||||
.bitrates = mwifiex_rates - 4,
|
||||
.n_bitrates = ARRAY_SIZE(mwifiex_rates) + 4,
|
||||
.bitrates = mwifiex_rates + 4,
|
||||
.n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4,
|
||||
};
|
||||
|
||||
|
||||
@ -841,12 +839,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
u8 *bssid, int mode, struct ieee80211_channel *channel,
|
||||
struct cfg80211_connect_params *sme, bool privacy)
|
||||
{
|
||||
struct mwifiex_802_11_ssid req_ssid;
|
||||
struct cfg80211_ssid req_ssid;
|
||||
int ret, auth_type = 0;
|
||||
struct cfg80211_bss *bss = NULL;
|
||||
u8 is_scanning_required = 0;
|
||||
|
||||
memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
|
||||
memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
|
||||
|
||||
req_ssid.ssid_len = ssid_len;
|
||||
if (ssid_len > IEEE80211_MAX_SSID_LEN) {
|
||||
@ -873,6 +871,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
priv->sec_info.wpa2_enabled = false;
|
||||
priv->wep_key_curr_index = 0;
|
||||
priv->sec_info.encryption_mode = 0;
|
||||
priv->sec_info.is_authtype_auto = 0;
|
||||
ret = mwifiex_set_encode(priv, NULL, 0, 0, 1);
|
||||
|
||||
if (mode == NL80211_IFTYPE_ADHOC) {
|
||||
@ -894,11 +893,12 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
|
||||
}
|
||||
|
||||
/* Now handle infra mode. "sme" is valid for infra mode only */
|
||||
if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC
|
||||
|| sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
|
||||
if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) {
|
||||
auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
|
||||
else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY)
|
||||
auth_type = NL80211_AUTHTYPE_SHARED_KEY;
|
||||
priv->sec_info.is_authtype_auto = 1;
|
||||
} else {
|
||||
auth_type = sme->auth_type;
|
||||
}
|
||||
|
||||
if (sme->crypto.n_ciphers_pairwise) {
|
||||
priv->sec_info.encryption_mode =
|
||||
@ -1106,12 +1106,10 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
|
||||
dev_err(priv->adapter->dev, "failed to alloc scan_req\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < request->n_ssids; i++) {
|
||||
memcpy(priv->user_scan_cfg->ssid_list[i].ssid,
|
||||
request->ssids[i].ssid, request->ssids[i].ssid_len);
|
||||
priv->user_scan_cfg->ssid_list[i].max_len =
|
||||
request->ssids[i].ssid_len;
|
||||
}
|
||||
|
||||
priv->user_scan_cfg->num_ssids = request->n_ssids;
|
||||
priv->user_scan_cfg->ssid_list = request->ssids;
|
||||
|
||||
for (i = 0; i < request->n_channels; i++) {
|
||||
chan = request->channels[i];
|
||||
priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
|
||||
|
@ -771,7 +771,7 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
|
||||
|
||||
/* Check init command response */
|
||||
if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) {
|
||||
if (ret == -1) {
|
||||
if (ret) {
|
||||
dev_err(adapter->dev, "%s: cmd %#x failed during "
|
||||
"initialization\n", __func__, cmdresp_no);
|
||||
mwifiex_init_fw_complete(adapter);
|
||||
@ -781,10 +781,8 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
|
||||
}
|
||||
|
||||
if (adapter->curr_cmd) {
|
||||
if (adapter->curr_cmd->wait_q_enabled && (!ret))
|
||||
adapter->cmd_wait_q.status = 0;
|
||||
else if (adapter->curr_cmd->wait_q_enabled && (ret == -1))
|
||||
adapter->cmd_wait_q.status = -1;
|
||||
if (adapter->curr_cmd->wait_q_enabled)
|
||||
adapter->cmd_wait_q.status = ret;
|
||||
|
||||
/* Clean up and put current command back to cmd_free_q */
|
||||
mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
|
||||
|
@ -91,11 +91,6 @@ struct mwifiex_fw_image {
|
||||
u32 fw_len;
|
||||
};
|
||||
|
||||
struct mwifiex_802_11_ssid {
|
||||
u32 ssid_len;
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
};
|
||||
|
||||
struct mwifiex_wait_queue {
|
||||
wait_queue_head_t wait;
|
||||
int status;
|
||||
|
@ -852,11 +852,6 @@ struct mwifiex_user_scan_chan {
|
||||
u32 scan_time;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_user_scan_ssid {
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 max_len;
|
||||
} __packed;
|
||||
|
||||
struct mwifiex_user_scan_cfg {
|
||||
/*
|
||||
* BSS mode to be sent in the firmware command
|
||||
@ -867,8 +862,9 @@ struct mwifiex_user_scan_cfg {
|
||||
u8 reserved;
|
||||
/* BSSID filter sent in the firmware command to limit the results */
|
||||
u8 specific_bssid[ETH_ALEN];
|
||||
/* SSID filter list used in the to limit the scan results */
|
||||
struct mwifiex_user_scan_ssid ssid_list[MWIFIEX_MAX_SSID_LIST_LENGTH];
|
||||
/* SSID filter list used in the firmware to limit the scan results */
|
||||
struct cfg80211_ssid *ssid_list;
|
||||
u8 num_ssids;
|
||||
/* Variable number (fixed maximum) of channels to scan up */
|
||||
struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX];
|
||||
} __packed;
|
||||
|
@ -50,7 +50,7 @@ struct mwifiex_chan_freq {
|
||||
};
|
||||
|
||||
struct mwifiex_ssid_bssid {
|
||||
struct mwifiex_802_11_ssid ssid;
|
||||
struct cfg80211_ssid ssid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
};
|
||||
|
||||
@ -122,7 +122,7 @@ struct mwifiex_ver_ext {
|
||||
|
||||
struct mwifiex_bss_info {
|
||||
u32 bss_mode;
|
||||
struct mwifiex_802_11_ssid ssid;
|
||||
struct cfg80211_ssid ssid;
|
||||
u32 bss_chan;
|
||||
u32 region_code;
|
||||
u32 media_connected;
|
||||
|
@ -585,7 +585,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
|
||||
le16_to_cpu(assoc_rsp->cap_info_bitmap),
|
||||
le16_to_cpu(assoc_rsp->a_id));
|
||||
|
||||
ret = -1;
|
||||
ret = le16_to_cpu(assoc_rsp->status_code);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -714,7 +714,7 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
|
||||
int
|
||||
mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd,
|
||||
struct mwifiex_802_11_ssid *req_ssid)
|
||||
struct cfg80211_ssid *req_ssid)
|
||||
{
|
||||
int rsn_ie_len = 0;
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
@ -1245,7 +1245,7 @@ int mwifiex_associate(struct mwifiex_private *priv,
|
||||
*/
|
||||
int
|
||||
mwifiex_adhoc_start(struct mwifiex_private *priv,
|
||||
struct mwifiex_802_11_ssid *adhoc_ssid)
|
||||
struct cfg80211_ssid *adhoc_ssid)
|
||||
{
|
||||
dev_dbg(priv->adapter->dev, "info: Adhoc Channel = %d\n",
|
||||
priv->adhoc_channel);
|
||||
|
@ -219,6 +219,7 @@ struct mwifiex_802_11_security {
|
||||
u8 wapi_key_on;
|
||||
u8 wep_enabled;
|
||||
u32 authentication_mode;
|
||||
u8 is_authtype_auto;
|
||||
u32 encryption_mode;
|
||||
};
|
||||
|
||||
@ -243,7 +244,7 @@ struct ieee_types_generic {
|
||||
|
||||
struct mwifiex_bssdescriptor {
|
||||
u8 mac_address[ETH_ALEN];
|
||||
struct mwifiex_802_11_ssid ssid;
|
||||
struct cfg80211_ssid ssid;
|
||||
u32 privacy;
|
||||
s32 rssi;
|
||||
u32 channel;
|
||||
@ -387,7 +388,7 @@ struct mwifiex_private {
|
||||
s16 bcn_rssi_avg;
|
||||
s16 bcn_nf_avg;
|
||||
struct mwifiex_bssdescriptor *attempted_bss_desc;
|
||||
struct mwifiex_802_11_ssid prev_ssid;
|
||||
struct cfg80211_ssid prev_ssid;
|
||||
u8 prev_bssid[ETH_ALEN];
|
||||
struct mwifiex_current_bss_params curr_bss_params;
|
||||
u16 beacon_period;
|
||||
@ -746,8 +747,7 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
|
||||
struct cmd_ctrl_node *cmd_node);
|
||||
int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *resp);
|
||||
s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
|
||||
struct mwifiex_802_11_ssid *ssid2);
|
||||
s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2);
|
||||
int mwifiex_associate(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
|
||||
@ -759,12 +759,12 @@ void mwifiex_reset_connect_state(struct mwifiex_private *priv);
|
||||
u8 mwifiex_band_to_radio_type(u8 band);
|
||||
int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
|
||||
int mwifiex_adhoc_start(struct mwifiex_private *priv,
|
||||
struct mwifiex_802_11_ssid *adhoc_ssid);
|
||||
struct cfg80211_ssid *adhoc_ssid);
|
||||
int mwifiex_adhoc_join(struct mwifiex_private *priv,
|
||||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd,
|
||||
struct mwifiex_802_11_ssid *req_ssid);
|
||||
struct cfg80211_ssid *req_ssid);
|
||||
int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
|
||||
struct host_cmd_ds_command *cmd,
|
||||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
@ -897,7 +897,7 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
|
||||
struct net_device *dev);
|
||||
int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
|
||||
int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||
struct mwifiex_802_11_ssid *req_ssid);
|
||||
struct cfg80211_ssid *req_ssid);
|
||||
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
|
||||
int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
|
||||
int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
|
||||
@ -906,13 +906,12 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
|
||||
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
|
||||
struct mwifiex_rate_cfg *rate);
|
||||
int mwifiex_request_scan(struct mwifiex_private *priv,
|
||||
struct mwifiex_802_11_ssid *req_ssid);
|
||||
struct cfg80211_ssid *req_ssid);
|
||||
int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
|
||||
struct mwifiex_user_scan_cfg *scan_req);
|
||||
int mwifiex_change_adhoc_chan(struct mwifiex_private *priv, int channel);
|
||||
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
|
||||
|
||||
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel);
|
||||
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
|
||||
|
||||
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
|
||||
int key_len, u8 key_index, int disable);
|
||||
|
@ -163,8 +163,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
|
||||
* This function compares two SSIDs and checks if they match.
|
||||
*/
|
||||
s32
|
||||
mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
|
||||
struct mwifiex_802_11_ssid *ssid2)
|
||||
mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
|
||||
{
|
||||
if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
|
||||
return -1;
|
||||
@ -738,7 +737,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
|
||||
u16 scan_dur;
|
||||
u8 channel;
|
||||
u8 radio_type;
|
||||
u32 ssid_idx;
|
||||
int i;
|
||||
u8 ssid_filter;
|
||||
u8 rates[MWIFIEX_SUPPORTED_RATES];
|
||||
u32 rates_size;
|
||||
@ -793,14 +792,8 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
|
||||
user_scan_in->specific_bssid,
|
||||
sizeof(scan_cfg_out->specific_bssid));
|
||||
|
||||
for (ssid_idx = 0;
|
||||
((ssid_idx < ARRAY_SIZE(user_scan_in->ssid_list))
|
||||
&& (*user_scan_in->ssid_list[ssid_idx].ssid
|
||||
|| user_scan_in->ssid_list[ssid_idx].max_len));
|
||||
ssid_idx++) {
|
||||
|
||||
ssid_len = strlen(user_scan_in->ssid_list[ssid_idx].
|
||||
ssid) + 1;
|
||||
for (i = 0; i < user_scan_in->num_ssids; i++) {
|
||||
ssid_len = user_scan_in->ssid_list[i].ssid_len;
|
||||
|
||||
wildcard_ssid_tlv =
|
||||
(struct mwifiex_ie_types_wildcard_ssid_params *)
|
||||
@ -811,19 +804,26 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
|
||||
(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
|
||||
max_ssid_length)));
|
||||
|
||||
/* max_ssid_length = 0 tells firmware to perform
|
||||
specific scan for the SSID filled */
|
||||
wildcard_ssid_tlv->max_ssid_length = 0;
|
||||
/*
|
||||
* max_ssid_length = 0 tells firmware to perform
|
||||
* specific scan for the SSID filled, whereas
|
||||
* max_ssid_length = IEEE80211_MAX_SSID_LEN is for
|
||||
* wildcard scan.
|
||||
*/
|
||||
if (ssid_len)
|
||||
wildcard_ssid_tlv->max_ssid_length = 0;
|
||||
else
|
||||
wildcard_ssid_tlv->max_ssid_length =
|
||||
IEEE80211_MAX_SSID_LEN;
|
||||
|
||||
memcpy(wildcard_ssid_tlv->ssid,
|
||||
user_scan_in->ssid_list[ssid_idx].ssid,
|
||||
ssid_len);
|
||||
user_scan_in->ssid_list[i].ssid, ssid_len);
|
||||
|
||||
tlv_pos += (sizeof(wildcard_ssid_tlv->header)
|
||||
+ le16_to_cpu(wildcard_ssid_tlv->header.len));
|
||||
|
||||
dev_dbg(adapter->dev, "info: scan: ssid_list[%d]: %s, %d\n",
|
||||
ssid_idx, wildcard_ssid_tlv->ssid,
|
||||
dev_dbg(adapter->dev, "info: scan: ssid[%d]: %s, %d\n",
|
||||
i, wildcard_ssid_tlv->ssid,
|
||||
wildcard_ssid_tlv->max_ssid_length);
|
||||
|
||||
/* Empty wildcard ssid with a maxlen will match many or
|
||||
@ -832,7 +832,6 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
|
||||
filtered. */
|
||||
if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
|
||||
ssid_filter = false;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -841,7 +840,7 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
|
||||
* truncate scan results. That is not an issue with an SSID
|
||||
* or BSSID filter applied to the scan results in the firmware.
|
||||
*/
|
||||
if ((ssid_idx && ssid_filter)
|
||||
if ((i && ssid_filter)
|
||||
|| memcmp(scan_cfg_out->specific_bssid, &zero_mac,
|
||||
sizeof(zero_mac)))
|
||||
*filtered_scan = true;
|
||||
@ -1851,7 +1850,7 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
|
||||
* firmware, filtered on a specific SSID.
|
||||
*/
|
||||
static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
|
||||
struct mwifiex_802_11_ssid *req_ssid)
|
||||
struct cfg80211_ssid *req_ssid)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
@ -1877,8 +1876,8 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
|
||||
req_ssid->ssid_len);
|
||||
scan_cfg->ssid_list = req_ssid;
|
||||
scan_cfg->num_ssids = 1;
|
||||
|
||||
ret = mwifiex_scan_networks(priv, scan_cfg);
|
||||
|
||||
@ -1896,7 +1895,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
|
||||
* scan, depending upon whether an SSID is provided or not.
|
||||
*/
|
||||
int mwifiex_request_scan(struct mwifiex_private *priv,
|
||||
struct mwifiex_802_11_ssid *req_ssid)
|
||||
struct cfg80211_ssid *req_ssid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user