Merge remote branch 'wireless-next/master' into ath6kl-next

This commit is contained in:
Kalle Valo 2012-03-26 16:26:56 +03:00
commit 0564161ea9
226 changed files with 8848 additions and 7674 deletions

View File

@ -0,0 +1,99 @@
#
# This outlines the Linux authentication/association and
# deauthentication/disassociation flows.
#
# This can be converted into a diagram using the service
# at http://www.websequencediagrams.com/
#
participant userspace
participant mac80211
participant driver
alt authentication needed (not FT)
userspace->mac80211: authenticate
alt authenticated/authenticating already
mac80211->driver: sta_state(AP, not-exists)
mac80211->driver: bss_info_changed(clear BSSID)
else associated
note over mac80211,driver
like deauth/disassoc, without sending the
BA session stop & deauth/disassoc frames
end note
end
mac80211->driver: config(channel, non-HT)
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
mac80211->driver: sta_state(AP, exists)
alt no probe request data known
mac80211->driver: TX directed probe request
driver->mac80211: RX probe response
end
mac80211->driver: TX auth frame
driver->mac80211: RX auth frame
alt WEP shared key auth
mac80211->driver: TX auth frame
driver->mac80211: RX auth frame
end
mac80211->driver: sta_state(AP, authenticated)
mac80211->userspace: RX auth frame
end
userspace->mac80211: associate
alt authenticated or associated
note over mac80211,driver: cleanup like for authenticate
end
alt not previously authenticated (FT)
mac80211->driver: config(channel, non-HT)
mac80211->driver: bss_info_changed(set BSSID, basic rate bitmap)
mac80211->driver: sta_state(AP, exists)
mac80211->driver: sta_state(AP, authenticated)
end
mac80211->driver: TX assoc
driver->mac80211: RX assoc response
note over mac80211: init rate control
mac80211->driver: sta_state(AP, associated)
alt not using WPA
mac80211->driver: sta_state(AP, authorized)
end
mac80211->driver: set up QoS parameters
alt is HT channel
mac80211->driver: config(channel, HT params)
end
mac80211->driver: bss_info_changed(QoS, HT, associated with AID)
mac80211->userspace: associated
note left of userspace: associated now
alt using WPA
note over userspace
do 4-way-handshake
(data frames)
end note
userspace->mac80211: authorized
mac80211->driver: sta_state(AP, authorized)
end
userspace->mac80211: deauthenticate/disassociate
mac80211->driver: stop BA sessions
mac80211->driver: TX deauth/disassoc
mac80211->driver: flush frames
mac80211->driver: sta_state(AP,associated)
mac80211->driver: sta_state(AP,authenticated)
mac80211->driver: sta_state(AP,exists)
mac80211->driver: sta_state(AP,not-exists)
mac80211->driver: turn off powersave
mac80211->driver: bss_info_changed(clear BSSID, not associated, no QoS, ...)
mac80211->driver: config(non-HT channel type)
mac80211->userspace: disconnected

View File

@ -3,5 +3,5 @@
# under Linux. # 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 obj-$(CONFIG_BCM47XX_SSB) += wgt634u.o

View File

@ -107,8 +107,7 @@ int nvram_getenv(char *name, char *val, size_t val_len)
value = eq + 1; value = eq + 1;
if ((eq - var) == strlen(name) && if ((eq - var) == strlen(name) &&
strncmp(var, name, (eq - var)) == 0) { strncmp(var, name, (eq - var)) == 0) {
snprintf(val, val_len, "%s", value); return snprintf(val, val_len, "%s", value);
return 0;
} }
} }
return NVRAM_ERR_ENVNOTFOUND; return NVRAM_ERR_ENVNOTFOUND;

View File

@ -3,7 +3,7 @@
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
* Copyright (C) 2006 Michael Buesch <m@bues.ch> * Copyright (C) 2006 Michael Buesch <m@bues.ch>
* Copyright (C) 2010 Waldemar Brodkorb <wbx@openadk.org> * 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 * 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 * 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 #ifdef CONFIG_BCM47XX_SSB
#define READ_FROM_NVRAM(_outvar, name, buf) \ static int bcm47xx_get_sprom_ssb(struct ssb_bus *bus, struct ssb_sprom *out)
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)
{ {
char prefix[10]; 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, static int bcm47xx_get_invariants(struct ssb_bus *bus,
struct ssb_init_invariants *iv) struct ssb_init_invariants *iv)
{ {
char buf[20]; char buf[20];
@ -281,7 +132,7 @@ static void __init bcm47xx_register_ssb(void)
char buf[100]; char buf[100];
struct ssb_mipscore *mcore; 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) if (err)
printk(KERN_WARNING "bcm47xx: someone else already registered" printk(KERN_WARNING "bcm47xx: someone else already registered"
" a ssb SPROM callback handler (err %d)\n", err); " a ssb SPROM callback handler (err %d)\n", err);
@ -308,10 +159,41 @@ static void __init bcm47xx_register_ssb(void)
#endif #endif
#ifdef CONFIG_BCM47XX_BCMA #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) static void __init bcm47xx_register_bcma(void)
{ {
int err; 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); err = bcma_host_soc_register(&bcm47xx_bus.bcma);
if (err) if (err)
panic("Failed to initialize BCMA bus (err %d)", err); panic("Failed to initialize BCMA bus (err %d)", err);

620
arch/mips/bcm47xx/sprom.c Normal file
View 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);
}
}

View File

@ -44,4 +44,7 @@ union bcm47xx_bus {
extern union bcm47xx_bus bcm47xx_bus; extern union bcm47xx_bus bcm47xx_bus;
extern enum bcm47xx_bus_type bcm47xx_bus_type; 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 */ #endif /* __ASM_BCM47XX_H */

View File

@ -37,7 +37,7 @@ struct nvram_header {
extern int nvram_getenv(char *name, char *val, size_t val_len); 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, ':')) if (strchr(buf, ':'))
sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0],

View File

@ -80,6 +80,7 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc)
min_msk = 0x200D; min_msk = 0x200D;
max_msk = 0xFFFF; max_msk = 0xFFFF;
break; break;
case 0x4331:
case 43224: case 43224:
case 43225: case 43225:
break; break;

View File

@ -61,7 +61,7 @@ static struct bus_type bcma_bus_type = {
.dev_attrs = bcma_device_attrs, .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; struct bcma_device *core;
@ -71,6 +71,7 @@ static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
} }
return NULL; return NULL;
} }
EXPORT_SYMBOL_GPL(bcma_find_core);
static void bcma_release_core_dev(struct device *dev) static void bcma_release_core_dev(struct device *dev)
{ {

View File

@ -2,6 +2,8 @@
* Broadcom specific AMBA * Broadcom specific AMBA
* SPROM reading * SPROM reading
* *
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details. * Licensed under the GNU/GPL. See COPYING for details.
*/ */
@ -14,6 +16,58 @@
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/slab.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. * 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); 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) int bcma_sprom_get(struct bcma_bus *bus)
{ {
u16 offset; u16 offset = BCMA_CC_SPROM;
u16 *sprom; u16 *sprom;
u32 sromctrl;
int err = 0; int err = 0;
if (!bus->drv_cc.core) if (!bus->drv_cc.core)
return -EOPNOTSUPP; return -EOPNOTSUPP;
if (!(bus->drv_cc.capabilities & BCMA_CC_CAP_SPROM)) if (!bcma_sprom_ext_available(bus)) {
return -ENOENT; /*
* External SPROM takes precedence so check
if (bus->drv_cc.core->id.rev >= 32) { * on-chip OTP only when no external SPROM
sromctrl = bcma_read32(bus->drv_cc.core, BCMA_CC_SROM_CONTROL); * is present.
if (!(sromctrl & BCMA_CC_SROM_CONTROL_PRESENT)) */
return -ENOENT; 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), 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) if (bus->chipinfo.id == 0x4331)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); 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); pr_debug("SPROM offset 0x%x\n", offset);
bcma_sprom_read(bus, offset, sprom); bcma_sprom_read(bus, offset, sprom);

View File

@ -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) 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); ai->expires = RUN_AT(3*HZ);
wake_up_interruptible(&ai->thr_wait); wake_up_interruptible(&ai->thr_wait);
} }

View File

@ -174,28 +174,24 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common); void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common); int32_t ath_hw_get_listen_time(struct ath_common *common);
extern __printf(2, 3) void ath_printk(const char *level, const char *fmt, ...); __printf(3, 4)
void ath_printk(const char *level, const struct ath_common *common,
#define _ath_printk(level, common, fmt, ...) \ const char *fmt, ...);
do { \
__always_unused struct ath_common *unused = common; \
ath_printk(level, fmt, ##__VA_ARGS__); \
} while (0)
#define ath_emerg(common, fmt, ...) \ #define ath_emerg(common, fmt, ...) \
_ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__) ath_printk(KERN_EMERG, common, fmt, ##__VA_ARGS__)
#define ath_alert(common, fmt, ...) \ #define ath_alert(common, fmt, ...) \
_ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__) ath_printk(KERN_ALERT, common, fmt, ##__VA_ARGS__)
#define ath_crit(common, fmt, ...) \ #define ath_crit(common, fmt, ...) \
_ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__) ath_printk(KERN_CRIT, common, fmt, ##__VA_ARGS__)
#define ath_err(common, fmt, ...) \ #define ath_err(common, fmt, ...) \
_ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__) ath_printk(KERN_ERR, common, fmt, ##__VA_ARGS__)
#define ath_warn(common, fmt, ...) \ #define ath_warn(common, fmt, ...) \
_ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__) ath_printk(KERN_WARNING, common, fmt, ##__VA_ARGS__)
#define ath_notice(common, fmt, ...) \ #define ath_notice(common, fmt, ...) \
_ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__) ath_printk(KERN_NOTICE, common, fmt, ##__VA_ARGS__)
#define ath_info(common, fmt, ...) \ #define ath_info(common, fmt, ...) \
_ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__) ath_printk(KERN_INFO, common, fmt, ##__VA_ARGS__)
/** /**
* enum ath_debug_level - atheros wireless debug level * enum ath_debug_level - atheros wireless debug level
@ -256,7 +252,7 @@ enum ATH_DEBUG {
#define ath_dbg(common, dbg_mask, fmt, ...) \ #define ath_dbg(common, dbg_mask, fmt, ...) \
do { \ do { \
if ((common)->debug_mask & ATH_DBG_##dbg_mask) \ if ((common)->debug_mask & ATH_DBG_##dbg_mask) \
_ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \ ath_printk(KERN_DEBUG, common, fmt, ##__VA_ARGS__); \
} while (0) } while (0)
#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg) #define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)

View File

@ -1320,6 +1320,7 @@ struct ath5k_hw {
struct ieee80211_vif *bslot[ATH_BCBUF]; struct ieee80211_vif *bslot[ATH_BCBUF];
u16 num_ap_vifs; u16 num_ap_vifs;
u16 num_adhoc_vifs; u16 num_adhoc_vifs;
u16 num_mesh_vifs;
unsigned int bhalq, /* SW q for outgoing beacons */ unsigned int bhalq, /* SW q for outgoing beacons */
bmisscount, /* missed beacon transmits */ bmisscount, /* missed beacon transmits */
bintval, /* beacon interval in TU */ bintval, /* beacon interval in TU */

View File

@ -1867,7 +1867,8 @@ ath5k_beacon_send(struct ath5k_hw *ah)
ah->bmisscount = 0; 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) { ah->opmode == NL80211_IFTYPE_MESH_POINT) {
u64 tsf = ath5k_hw_get_tsf64(ah); u64 tsf = ath5k_hw_get_tsf64(ah);
u32 tsftu = TSF_TO_TU(tsf); u32 tsftu = TSF_TO_TU(tsf);
@ -1952,7 +1953,8 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
u64 hw_tsf; u64 hw_tsf;
intval = ah->bintval & AR5K_BEACON_PERIOD; 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 */ intval /= ATH_BCBUF; /* staggered multi-bss beacons */
if (intval < 15) if (intval < 15)
ATH5K_WARN(ah, "intval %u is too low, min 15\n", 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"); "got new rfgain, resetting\n");
ieee80211_queue_work(ah->hw, &ah->reset_work); 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 } else
ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT; ah->ah_cal_mask |= AR5K_CALIBRATION_SHORT;
@ -2353,10 +2346,9 @@ ath5k_calibrate_work(struct work_struct *work)
ah->curchan->center_freq)); ah->curchan->center_freq));
/* Clear calibration flags */ /* Clear calibration flags */
if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL) { if (ah->ah_cal_mask & AR5K_CALIBRATION_FULL)
ieee80211_wake_queues(ah->hw);
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; ah->ah_cal_mask &= ~AR5K_CALIBRATION_SHORT;
} }

View File

@ -134,6 +134,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
ah->num_ap_vifs++; ah->num_ap_vifs++;
else if (avf->opmode == NL80211_IFTYPE_ADHOC) else if (avf->opmode == NL80211_IFTYPE_ADHOC)
ah->num_adhoc_vifs++; 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 /* 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--; ah->num_ap_vifs--;
else if (avf->opmode == NL80211_IFTYPE_ADHOC) else if (avf->opmode == NL80211_IFTYPE_ADHOC)
ah->num_adhoc_vifs--; ah->num_adhoc_vifs--;
else if (avf->opmode == NL80211_IFTYPE_MESH_POINT)
ah->num_mesh_vifs--;
ath5k_update_bssid_mask_and_opmode(ah, NULL); ath5k_update_bssid_mask_and_opmode(ah, NULL);
mutex_unlock(&ah->lock); mutex_unlock(&ah->lock);

View File

@ -1871,31 +1871,15 @@ ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
ret = 0; ret = 0;
} }
/* On full calibration do an AGC calibration and /* On full calibration request a PAPD probe for
* request a PAPD probe for gainf calibration if * gainf calibration if needed */
* needed */ if ((ah->ah_cal_mask & AR5K_CALIBRATION_FULL) &&
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, /* Update noise floor */
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 */
if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF)) if (!(ah->ah_cal_mask & AR5K_CALIBRATION_NF))
ath5k_hw_update_noise_floor(ah); ath5k_hw_update_noise_floor(ah);

View File

@ -557,7 +557,8 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
dlen, freq, vif->probe_req_report); dlen, freq, vif->probe_req_report);
if (vif->probe_req_report || vif->nw_type == AP_NETWORK) 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; return 0;
} }
@ -596,7 +597,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
return -EINVAL; return -EINVAL;
} }
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); 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; return 0;
} }

View File

@ -81,6 +81,14 @@ config ATH9K_DFS_CERTIFIED
developed. At this point enabling this option won't do anything developed. At this point enabling this option won't do anything
except increase code size. 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 config ATH9K_RATE_CONTROL
bool "Atheros ath9k rate control" bool "Atheros ath9k rate control"
depends on ATH9K depends on ATH9K

View File

@ -834,9 +834,10 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
AR_SREV_9287_11_OR_LATER(ah)) AR_SREV_9287_11_OR_LATER(ah))
REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites);
if (AR_SREV_9271_10(ah)) if (AR_SREV_9271_10(ah)) {
REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only, REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENA);
modesIndex, regWrites); REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_ADC_ON, 0xa);
}
ENABLE_REGWRITE_BUFFER(ah); ENABLE_REGWRITE_BUFFER(ah);
@ -858,21 +859,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
REGWRITE_BUFFER_FLUSH(ah); REGWRITE_BUFFER_FLUSH(ah);
if (AR_SREV_9271(ah)) {
if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == 1)
REG_WRITE_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
modesIndex, regWrites);
else
REG_WRITE_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
modesIndex, regWrites);
}
REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) { if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex,
regWrites); regWrites);
}
ar5008_hw_override_ini(ah, chan); ar5008_hw_override_ini(ah, chan);
ar5008_hw_set_channel_regs(ah, chan); ar5008_hw_set_channel_regs(ah, chan);

View File

@ -34,23 +34,8 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9271Modes_9271), 5); ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271, INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2); ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
ar9287Common_normal_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1), 2);
INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 5);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg, INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5); ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
return; return;
} }
@ -79,7 +64,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2); ARRAY_SIZE(ar9280Common_9280_2), 2);
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9280Modes_fast_clock_9280_2, ar9280Modes_fast_clock_9280_2,
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9160_10_OR_LATER(ah)) { } else if (AR_SREV_9160_10_OR_LATER(ah)) {
@ -160,11 +145,6 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
INI_RA(addac, 31,1) = 0; INI_RA(addac, 31,1) = 0;
} }
} }
}
/* Support for Japan ch.14 (2484) spread */
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
{
if (AR_SREV_9287_11_OR_LATER(ah)) { if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniCckfirNormal, INIT_INI_ARRAY(&ah->iniCckfirNormal,
ar9287Common_normal_cck_fir_coeff_9287_1_1, ar9287Common_normal_cck_fir_coeff_9287_1_1,
@ -204,14 +184,10 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
} }
} }
static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah) static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
{ {
u32 txgain_type;
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
AR5416_EEP_MINOR_VER_19) { AR5416_EEP_MINOR_VER_19) {
txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2, ar9280Modes_high_power_tx_gain_9280_2,
@ -227,8 +203,22 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
} }
} }
static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
{
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
}
static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah) static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
{ {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
if (AR_SREV_9287_11_OR_LATER(ah)) if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain, INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1, ar9287Modes_rx_gain_9287_1_1,
@ -236,15 +226,15 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
else if (AR_SREV_9280_20(ah)) else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah); ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) { if (AR_SREV_9271(ah)) {
ar9271_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain, INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1, ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5); ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
} else if (AR_SREV_9280_20(ah)) { } else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah); ar9280_20_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9285_12_OR_LATER(ah)) { } else if (AR_SREV_9285_12_OR_LATER(ah)) {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
/* txgain table */ /* txgain table */
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
if (AR_SREV_9285E_20(ah)) { if (AR_SREV_9285E_20(ah)) {

View File

@ -3092,12 +3092,6 @@ static const u32 ar9271Common_9271[][2] = {
{0x0000d384, 0xf3307ff0}, {0x0000d384, 0xf3307ff0},
}; };
static const u32 ar9271Modes_9271_1_0_only[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311},
{0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001},
};
static const u32 ar9271Modes_9271_ANI_reg[][5] = { static const u32 ar9271Modes_9271_ANI_reg[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2}, {0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2},

View File

@ -347,15 +347,12 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags) u32 size, u32 flags)
{ {
struct ar5416_desc *ads = AR5416DESC(ds); struct ar5416_desc *ads = AR5416DESC(ds);
struct ath9k_hw_capabilities *pCap = &ah->caps;
ads->ds_ctl1 = size & AR_BufLen; ads->ds_ctl1 = size & AR_BufLen;
if (flags & ATH9K_RXDESC_INTREQ) if (flags & ATH9K_RXDESC_INTREQ)
ads->ds_ctl1 |= AR_RxIntrReq; ads->ds_ctl1 |= AR_RxIntrReq;
ads->ds_rxstatus8 &= ~AR_RxDone; memset(&ads->u.rx, 0, sizeof(ads->u.rx));
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
memset(&(ads->u), 0, sizeof(ads->u));
} }
EXPORT_SYMBOL(ath9k_hw_setuprxdesc); EXPORT_SYMBOL(ath9k_hw_setuprxdesc);

View File

@ -60,6 +60,8 @@
#define AR_PHY_RF_CTL3 0x9828 #define AR_PHY_RF_CTL3 0x9828
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 #define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 #define AR_PHY_TX_END_TO_A2_RX_ON_S 16
#define AR_PHY_TX_END_TO_ADC_ON 0xFF000000
#define AR_PHY_TX_END_TO_ADC_ON_S 24
#define AR_PHY_ADC_CTL 0x982C #define AR_PHY_ADC_CTL 0x982C
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 #define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003

View File

@ -295,266 +295,6 @@ static const u32 ar9300_2p2_radio_core[][2] = {
{0x00016bd4, 0x00000000}, {0x00016bd4, 0x00000000},
}; };
static const u32 ar9300Common_rx_gain_table_merlin_2p2[][2] = {
/* Addr allmodes */
{0x0000a000, 0x02000101},
{0x0000a004, 0x02000102},
{0x0000a008, 0x02000103},
{0x0000a00c, 0x02000104},
{0x0000a010, 0x02000200},
{0x0000a014, 0x02000201},
{0x0000a018, 0x02000202},
{0x0000a01c, 0x02000203},
{0x0000a020, 0x02000204},
{0x0000a024, 0x02000205},
{0x0000a028, 0x02000208},
{0x0000a02c, 0x02000302},
{0x0000a030, 0x02000303},
{0x0000a034, 0x02000304},
{0x0000a038, 0x02000400},
{0x0000a03c, 0x02010300},
{0x0000a040, 0x02010301},
{0x0000a044, 0x02010302},
{0x0000a048, 0x02000500},
{0x0000a04c, 0x02010400},
{0x0000a050, 0x02020300},
{0x0000a054, 0x02020301},
{0x0000a058, 0x02020302},
{0x0000a05c, 0x02020303},
{0x0000a060, 0x02020400},
{0x0000a064, 0x02030300},
{0x0000a068, 0x02030301},
{0x0000a06c, 0x02030302},
{0x0000a070, 0x02030303},
{0x0000a074, 0x02030400},
{0x0000a078, 0x02040300},
{0x0000a07c, 0x02040301},
{0x0000a080, 0x02040302},
{0x0000a084, 0x02040303},
{0x0000a088, 0x02030500},
{0x0000a08c, 0x02040400},
{0x0000a090, 0x02050203},
{0x0000a094, 0x02050204},
{0x0000a098, 0x02050205},
{0x0000a09c, 0x02040500},
{0x0000a0a0, 0x02050301},
{0x0000a0a4, 0x02050302},
{0x0000a0a8, 0x02050303},
{0x0000a0ac, 0x02050400},
{0x0000a0b0, 0x02050401},
{0x0000a0b4, 0x02050402},
{0x0000a0b8, 0x02050403},
{0x0000a0bc, 0x02050500},
{0x0000a0c0, 0x02050501},
{0x0000a0c4, 0x02050502},
{0x0000a0c8, 0x02050503},
{0x0000a0cc, 0x02050504},
{0x0000a0d0, 0x02050600},
{0x0000a0d4, 0x02050601},
{0x0000a0d8, 0x02050602},
{0x0000a0dc, 0x02050603},
{0x0000a0e0, 0x02050604},
{0x0000a0e4, 0x02050700},
{0x0000a0e8, 0x02050701},
{0x0000a0ec, 0x02050702},
{0x0000a0f0, 0x02050703},
{0x0000a0f4, 0x02050704},
{0x0000a0f8, 0x02050705},
{0x0000a0fc, 0x02050708},
{0x0000a100, 0x02050709},
{0x0000a104, 0x0205070a},
{0x0000a108, 0x0205070b},
{0x0000a10c, 0x0205070c},
{0x0000a110, 0x0205070d},
{0x0000a114, 0x02050710},
{0x0000a118, 0x02050711},
{0x0000a11c, 0x02050712},
{0x0000a120, 0x02050713},
{0x0000a124, 0x02050714},
{0x0000a128, 0x02050715},
{0x0000a12c, 0x02050730},
{0x0000a130, 0x02050731},
{0x0000a134, 0x02050732},
{0x0000a138, 0x02050733},
{0x0000a13c, 0x02050734},
{0x0000a140, 0x02050735},
{0x0000a144, 0x02050750},
{0x0000a148, 0x02050751},
{0x0000a14c, 0x02050752},
{0x0000a150, 0x02050753},
{0x0000a154, 0x02050754},
{0x0000a158, 0x02050755},
{0x0000a15c, 0x02050770},
{0x0000a160, 0x02050771},
{0x0000a164, 0x02050772},
{0x0000a168, 0x02050773},
{0x0000a16c, 0x02050774},
{0x0000a170, 0x02050775},
{0x0000a174, 0x00000776},
{0x0000a178, 0x00000776},
{0x0000a17c, 0x00000776},
{0x0000a180, 0x00000776},
{0x0000a184, 0x00000776},
{0x0000a188, 0x00000776},
{0x0000a18c, 0x00000776},
{0x0000a190, 0x00000776},
{0x0000a194, 0x00000776},
{0x0000a198, 0x00000776},
{0x0000a19c, 0x00000776},
{0x0000a1a0, 0x00000776},
{0x0000a1a4, 0x00000776},
{0x0000a1a8, 0x00000776},
{0x0000a1ac, 0x00000776},
{0x0000a1b0, 0x00000776},
{0x0000a1b4, 0x00000776},
{0x0000a1b8, 0x00000776},
{0x0000a1bc, 0x00000776},
{0x0000a1c0, 0x00000776},
{0x0000a1c4, 0x00000776},
{0x0000a1c8, 0x00000776},
{0x0000a1cc, 0x00000776},
{0x0000a1d0, 0x00000776},
{0x0000a1d4, 0x00000776},
{0x0000a1d8, 0x00000776},
{0x0000a1dc, 0x00000776},
{0x0000a1e0, 0x00000776},
{0x0000a1e4, 0x00000776},
{0x0000a1e8, 0x00000776},
{0x0000a1ec, 0x00000776},
{0x0000a1f0, 0x00000776},
{0x0000a1f4, 0x00000776},
{0x0000a1f8, 0x00000776},
{0x0000a1fc, 0x00000776},
{0x0000b000, 0x02000101},
{0x0000b004, 0x02000102},
{0x0000b008, 0x02000103},
{0x0000b00c, 0x02000104},
{0x0000b010, 0x02000200},
{0x0000b014, 0x02000201},
{0x0000b018, 0x02000202},
{0x0000b01c, 0x02000203},
{0x0000b020, 0x02000204},
{0x0000b024, 0x02000205},
{0x0000b028, 0x02000208},
{0x0000b02c, 0x02000302},
{0x0000b030, 0x02000303},
{0x0000b034, 0x02000304},
{0x0000b038, 0x02000400},
{0x0000b03c, 0x02010300},
{0x0000b040, 0x02010301},
{0x0000b044, 0x02010302},
{0x0000b048, 0x02000500},
{0x0000b04c, 0x02010400},
{0x0000b050, 0x02020300},
{0x0000b054, 0x02020301},
{0x0000b058, 0x02020302},
{0x0000b05c, 0x02020303},
{0x0000b060, 0x02020400},
{0x0000b064, 0x02030300},
{0x0000b068, 0x02030301},
{0x0000b06c, 0x02030302},
{0x0000b070, 0x02030303},
{0x0000b074, 0x02030400},
{0x0000b078, 0x02040300},
{0x0000b07c, 0x02040301},
{0x0000b080, 0x02040302},
{0x0000b084, 0x02040303},
{0x0000b088, 0x02030500},
{0x0000b08c, 0x02040400},
{0x0000b090, 0x02050203},
{0x0000b094, 0x02050204},
{0x0000b098, 0x02050205},
{0x0000b09c, 0x02040500},
{0x0000b0a0, 0x02050301},
{0x0000b0a4, 0x02050302},
{0x0000b0a8, 0x02050303},
{0x0000b0ac, 0x02050400},
{0x0000b0b0, 0x02050401},
{0x0000b0b4, 0x02050402},
{0x0000b0b8, 0x02050403},
{0x0000b0bc, 0x02050500},
{0x0000b0c0, 0x02050501},
{0x0000b0c4, 0x02050502},
{0x0000b0c8, 0x02050503},
{0x0000b0cc, 0x02050504},
{0x0000b0d0, 0x02050600},
{0x0000b0d4, 0x02050601},
{0x0000b0d8, 0x02050602},
{0x0000b0dc, 0x02050603},
{0x0000b0e0, 0x02050604},
{0x0000b0e4, 0x02050700},
{0x0000b0e8, 0x02050701},
{0x0000b0ec, 0x02050702},
{0x0000b0f0, 0x02050703},
{0x0000b0f4, 0x02050704},
{0x0000b0f8, 0x02050705},
{0x0000b0fc, 0x02050708},
{0x0000b100, 0x02050709},
{0x0000b104, 0x0205070a},
{0x0000b108, 0x0205070b},
{0x0000b10c, 0x0205070c},
{0x0000b110, 0x0205070d},
{0x0000b114, 0x02050710},
{0x0000b118, 0x02050711},
{0x0000b11c, 0x02050712},
{0x0000b120, 0x02050713},
{0x0000b124, 0x02050714},
{0x0000b128, 0x02050715},
{0x0000b12c, 0x02050730},
{0x0000b130, 0x02050731},
{0x0000b134, 0x02050732},
{0x0000b138, 0x02050733},
{0x0000b13c, 0x02050734},
{0x0000b140, 0x02050735},
{0x0000b144, 0x02050750},
{0x0000b148, 0x02050751},
{0x0000b14c, 0x02050752},
{0x0000b150, 0x02050753},
{0x0000b154, 0x02050754},
{0x0000b158, 0x02050755},
{0x0000b15c, 0x02050770},
{0x0000b160, 0x02050771},
{0x0000b164, 0x02050772},
{0x0000b168, 0x02050773},
{0x0000b16c, 0x02050774},
{0x0000b170, 0x02050775},
{0x0000b174, 0x00000776},
{0x0000b178, 0x00000776},
{0x0000b17c, 0x00000776},
{0x0000b180, 0x00000776},
{0x0000b184, 0x00000776},
{0x0000b188, 0x00000776},
{0x0000b18c, 0x00000776},
{0x0000b190, 0x00000776},
{0x0000b194, 0x00000776},
{0x0000b198, 0x00000776},
{0x0000b19c, 0x00000776},
{0x0000b1a0, 0x00000776},
{0x0000b1a4, 0x00000776},
{0x0000b1a8, 0x00000776},
{0x0000b1ac, 0x00000776},
{0x0000b1b0, 0x00000776},
{0x0000b1b4, 0x00000776},
{0x0000b1b8, 0x00000776},
{0x0000b1bc, 0x00000776},
{0x0000b1c0, 0x00000776},
{0x0000b1c4, 0x00000776},
{0x0000b1c8, 0x00000776},
{0x0000b1cc, 0x00000776},
{0x0000b1d0, 0x00000776},
{0x0000b1d4, 0x00000776},
{0x0000b1d8, 0x00000776},
{0x0000b1dc, 0x00000776},
{0x0000b1e0, 0x00000776},
{0x0000b1e4, 0x00000776},
{0x0000b1e8, 0x00000776},
{0x0000b1ec, 0x00000776},
{0x0000b1f0, 0x00000776},
{0x0000b1f4, 0x00000776},
{0x0000b1f8, 0x00000776},
{0x0000b1fc, 0x00000776},
};
static const u32 ar9300_2p2_mac_postamble[][5] = { static const u32 ar9300_2p2_mac_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
@ -572,48 +312,6 @@ static const u32 ar9300_2p2_soc_postamble[][5] = {
{0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023},
}; };
static const u32 ar9200_merlin_2p2_radio_core[][2] = {
/* Addr allmodes */
{0x00007800, 0x00040000},
{0x00007804, 0xdb005012},
{0x00007808, 0x04924914},
{0x0000780c, 0x21084210},
{0x00007810, 0x6d801300},
{0x00007814, 0x0019beff},
{0x00007818, 0x07e41000},
{0x0000781c, 0x00392000},
{0x00007820, 0x92592480},
{0x00007824, 0x00040000},
{0x00007828, 0xdb005012},
{0x0000782c, 0x04924914},
{0x00007830, 0x21084210},
{0x00007834, 0x6d801300},
{0x00007838, 0x0019beff},
{0x0000783c, 0x07e40000},
{0x00007840, 0x00392000},
{0x00007844, 0x92592480},
{0x00007848, 0x00100000},
{0x0000784c, 0x773f0567},
{0x00007850, 0x54214514},
{0x00007854, 0x12035828},
{0x00007858, 0x92592692},
{0x0000785c, 0x00000000},
{0x00007860, 0x56400000},
{0x00007864, 0x0a8e370e},
{0x00007868, 0xc0102850},
{0x0000786c, 0x812d4000},
{0x00007870, 0x807ec400},
{0x00007874, 0x001b6db0},
{0x00007878, 0x00376b63},
{0x0000787c, 0x06db6db6},
{0x00007880, 0x006d8000},
{0x00007884, 0xffeffffe},
{0x00007888, 0xffeffffe},
{0x0000788c, 0x00010000},
{0x00007890, 0x02060aeb},
{0x00007894, 0x5a108000},
};
static const u32 ar9300_2p2_baseband_postamble[][5] = { static const u32 ar9300_2p2_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},

View File

@ -87,11 +87,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* additional clock settings */ /* additional clock settings */
if (ah->is_clk_25mhz) if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_25M, ar9331_1p1_xtal_25M,
ARRAY_SIZE(ar9331_1p1_xtal_25M), 2); ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
else else
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_40M, ar9331_1p1_xtal_40M,
ARRAY_SIZE(ar9331_1p1_xtal_40M), 2); ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
} else if (AR_SREV_9330_12(ah)) { } else if (AR_SREV_9330_12(ah)) {
@ -140,11 +140,11 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
/* additional clock settings */ /* additional clock settings */
if (ah->is_clk_25mhz) if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_25M, ar9331_1p2_xtal_25M,
ARRAY_SIZE(ar9331_1p2_xtal_25M), 2); ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
else else
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_40M, ar9331_1p2_xtal_40M,
ARRAY_SIZE(ar9331_1p2_xtal_40M), 2); ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
} else if (AR_SREV_9340(ah)) { } else if (AR_SREV_9340(ah)) {
@ -194,15 +194,16 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0), ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
5); 5);
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9340Modes_fast_clock_1p0, ar9340Modes_fast_clock_1p0,
ARRAY_SIZE(ar9340Modes_fast_clock_1p0), ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
3); 3);
INIT_INI_ARRAY(&ah->iniModesAdditional_40M, if (!ah->is_clk_25mhz)
ar9340_1p0_radio_core_40M, INIT_INI_ARRAY(&ah->iniAdditional,
ARRAY_SIZE(ar9340_1p0_radio_core_40M), ar9340_1p0_radio_core_40M,
2); ARRAY_SIZE(ar9340_1p0_radio_core_40M),
2);
} else if (AR_SREV_9485_11(ah)) { } else if (AR_SREV_9485_11(ah)) {
/* mac */ /* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
@ -321,7 +322,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
2); 2);
/* Fast clock modal settings */ /* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9462_modes_fast_clock_2p0, ar9462_modes_fast_clock_2p0,
ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3); ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
@ -378,7 +379,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table), ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5); 5);
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9580_1p0_modes_fast_clock, ar9580_1p0_modes_fast_clock,
ARRAY_SIZE(ar9580_1p0_modes_fast_clock), ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
3); 3);
@ -445,7 +446,7 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
2); 2);
/* Fast clock modal settings */ /* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional, INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9300Modes_fast_clock_2p2, ar9300Modes_fast_clock_2p2,
ARRAY_SIZE(ar9300Modes_fast_clock_2p2), ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
3); 3);

View File

@ -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, static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts) struct ath_tx_status *ts)
{ {
struct ar9003_txc *txc = (struct ar9003_txc *) ds;
struct ar9003_txs *ads; struct ar9003_txs *ads;
u32 status; u32 status;
@ -336,11 +335,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
if ((status & AR_TxDone) == 0) if ((status & AR_TxDone) == 0)
return -EINPROGRESS; return -EINPROGRESS;
ts->qid = MS(ads->ds_info, AR_TxQcuNum); ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
if (!txc || (MS(txc->info, AR_TxQcuNum) == ts->qid))
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
else
return -ENOENT;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) || if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) { (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->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid); ts->tid = MS(status, AR_TxTid);
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId); ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_tstamp = ads->status4; ts->ts_tstamp = ads->status4;
ts->ts_status = 0; 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; struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
unsigned int phyerr; unsigned int phyerr;
/* TODO: byte swap on big endian for ar9300_10 */ if ((rxsp->status11 & AR_RxDone) == 0)
return -EINPROGRESS;
if (!rxs) { if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
if ((rxsp->status11 & AR_RxDone) == 0) return -EINVAL;
return -EINPROGRESS;
if (MS(rxsp->ds_info, AR_DescId) != 0x168c) if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
return -EINVAL; return -EINPROGRESS;
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
return -EINPROGRESS;
return 0;
}
rxs->rs_status = 0; rxs->rs_status = 0;
rxs->rs_flags = 0; rxs->rs_flags = 0;

View File

@ -679,18 +679,17 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
* different modal values. * different modal values.
*/ */
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional, REG_WRITE_ARRAY(&ah->iniModesFastClock,
modesIndex, regWrites); modesIndex, regWrites);
if (AR_SREV_9330(ah)) REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
if (AR_SREV_9462(ah)) if (AR_SREV_9462(ah))
ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1); ar9003_hw_prog_ini(ah, &ah->ini_BTCOEX_MAX_TXPWR, 1);
if (chan->channel == 2484)
ar9003_hw_prog_ini(ah, &ah->ini_japan2484, 1);
ah->modes_index = modesIndex; ah->modes_index = modesIndex;
ar9003_hw_override_ini(ah); ar9003_hw_override_ini(ah);
ar9003_hw_set_channel_regs(ah, chan); ar9003_hw_set_channel_regs(ah, chan);
@ -1320,13 +1319,9 @@ static int ar9003_hw_fast_chan_change(struct ath_hw *ah,
* different modal values. * different modal values.
*/ */
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) if (IS_CHAN_A_FAST_CLOCK(ah, chan))
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, regWrites); REG_WRITE_ARRAY(&ah->iniModesFastClock, modesIndex, regWrites);
if (AR_SREV_9330(ah)) REG_WRITE_ARRAY(&ah->iniAdditional, 1, regWrites);
REG_WRITE_ARRAY(&ah->iniModesAdditional, 1, regWrites);
if (AR_SREV_9340(ah) && !ah->is_clk_25mhz)
REG_WRITE_ARRAY(&ah->iniModesAdditional_40M, 1, regWrites);
ah->modes_index = modesIndex; ah->modes_index = modesIndex;
*ini_reloaded = true; *ini_reloaded = true;

View File

@ -299,7 +299,6 @@ struct ath_tx {
struct ath_rx_edma { struct ath_rx_edma {
struct sk_buff_head rx_fifo; struct sk_buff_head rx_fifo;
struct sk_buff_head rx_buffers;
u32 rx_fifo_hwsize; u32 rx_fifo_hwsize;
}; };
@ -584,19 +583,13 @@ struct ath_ant_comb {
#define SC_OP_INVALID BIT(0) #define SC_OP_INVALID BIT(0)
#define SC_OP_BEACONS BIT(1) #define SC_OP_BEACONS BIT(1)
#define SC_OP_RXAGGR BIT(2) #define SC_OP_OFFCHANNEL BIT(2)
#define SC_OP_TXAGGR BIT(3) #define SC_OP_RXFLUSH BIT(3)
#define SC_OP_OFFCHANNEL BIT(4) #define SC_OP_TSF_RESET BIT(4)
#define SC_OP_PREAMBLE_SHORT BIT(5) #define SC_OP_BT_PRIORITY_DETECTED BIT(5)
#define SC_OP_PROTECT_ENABLE BIT(6) #define SC_OP_BT_SCAN BIT(6)
#define SC_OP_RXFLUSH BIT(7) #define SC_OP_ANI_RUN BIT(7)
#define SC_OP_LED_ASSOCIATED BIT(8) #define SC_OP_PRIM_STA_VIF BIT(8)
#define SC_OP_LED_ON BIT(9)
#define SC_OP_TSF_RESET BIT(11)
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
#define SC_OP_PRIM_STA_VIF BIT(15)
/* Powersave flags */ /* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0) #define PS_WAIT_FOR_BEACON BIT(0)
@ -618,15 +611,12 @@ struct ath9k_vif_iter_data {
int nstations; /* number of station vifs */ int nstations; /* number of station vifs */
int nwds; /* number of WDS vifs */ int nwds; /* number of WDS vifs */
int nadhocs; /* number of adhoc vifs */ int nadhocs; /* number of adhoc vifs */
int nothers; /* number of vifs not specified above. */
}; };
struct ath_softc { struct ath_softc {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
int chan_idx;
int chan_is_ht;
struct survey_info *cur_survey; struct survey_info *cur_survey;
struct survey_info survey[ATH9K_NUM_CHANNELS]; struct survey_info survey[ATH9K_NUM_CHANNELS];

View File

@ -67,7 +67,7 @@ int ath_beaconq_config(struct ath_softc *sc)
* up rate codes, and channel flags. Beacons are always sent out at the * up rate codes, and channel flags. Beacons are always sent out at the
* lowest rate, and are not retried. * lowest rate, and are not retried.
*/ */
static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
struct ath_buf *bf, int rateidx) struct ath_buf *bf, int rateidx)
{ {
struct sk_buff *skb = bf->bf_mpdu; struct sk_buff *skb = bf->bf_mpdu;
@ -82,7 +82,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
sband = &sc->sbands[common->hw->conf.channel->band]; sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value; rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) if (vif->bss_conf.use_short_preamble)
rate |= sband->bitrates[rateidx].hw_value_short; rate |= sband->bitrates[rateidx].hw_value_short;
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
@ -91,7 +91,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
info.txpower = MAX_RATE_POWER; info.txpower = MAX_RATE_POWER;
info.keyix = ATH9K_TXKEYIX_INVALID; info.keyix = ATH9K_TXKEYIX_INVALID;
info.keytype = ATH9K_KEY_TYPE_CLEAR; 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_addr[0] = bf->bf_buf_addr;
info.buf_len[0] = roundup(skb->len, 4); info.buf_len[0] = roundup(skb->len, 4);
@ -209,7 +209,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
} }
} }
ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx); ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
while (skb) { while (skb) {
ath_tx_cabq(hw, skb); ath_tx_cabq(hw, skb);
@ -355,7 +355,6 @@ void ath_beacon_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL; struct ath_buf *bf = NULL;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct ath_tx_status ts;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int slot; int slot;
u32 bfaddr, bc = 0; u32 bfaddr, bc = 0;
@ -462,11 +461,6 @@ void ath_beacon_tasklet(unsigned long data)
ath9k_hw_txstart(ah, sc->beacon.beaconq); ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ 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);
}
} }
} }

View File

@ -738,9 +738,9 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len, len += snprintf(buf + len, sizeof(buf) - len,
"VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i" "VIF-COUNTS: AP: %i STA: %i MESH: %i WDS: %i"
" ADHOC: %i OTHER: %i TOTAL: %hi BEACON-VIF: %hi\n", " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
iter_data.naps, iter_data.nstations, iter_data.nmeshes, iter_data.naps, iter_data.nstations, iter_data.nmeshes,
iter_data.nwds, iter_data.nadhocs, iter_data.nothers, iter_data.nwds, iter_data.nadhocs,
sc->nvifs, sc->nbcnvifs); sc->nvifs, sc->nbcnvifs);
if (len > sizeof(buf)) if (len > sizeof(buf))
@ -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) if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
TX_STAT_INC(qnum, delim_underrun); TX_STAT_INC(qnum, delim_underrun);
#ifdef CONFIG_ATH9K_MAC_DEBUG
spin_lock(&sc->debug.samp_lock); spin_lock(&sc->debug.samp_lock);
TX_SAMP_DBG(jiffies) = jiffies; TX_SAMP_DBG(jiffies) = jiffies;
TX_SAMP_DBG(rssi_ctl0) = ts->ts_rssi_ctl0; 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; sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock); spin_unlock(&sc->debug.samp_lock);
#endif
#undef TX_SAMP_DBG #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-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_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, len += snprintf(buf + len, size - len,
"%22s : %10u\n", "RX-Pkts-All", "%22s : %10u\n", "RX-Pkts-All",
sc->debug.stats.rxstats.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); RX_PHY_ERR_INC(rs->rs_phyerr);
} }
sc->debug.stats.rxstats.rs_rssi_ctl0 = rs->rs_rssi_ctl0; #ifdef CONFIG_ATH9K_MAC_DEBUG
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;
spin_lock(&sc->debug.samp_lock); spin_lock(&sc->debug.samp_lock);
RX_SAMP_DBG(jiffies) = jiffies; RX_SAMP_DBG(jiffies) = jiffies;
RX_SAMP_DBG(rssi_ctl0) = rs->rs_rssi_ctl0; 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; sc->debug.rsidx = (sc->debug.rsidx + 1) % ATH_DBG_MAX_SAMPLES;
spin_unlock(&sc->debug.samp_lock); spin_unlock(&sc->debug.samp_lock);
#endif
#undef RX_STAT_INC #undef RX_STAT_INC
#undef RX_PHY_ERR_INC #undef RX_PHY_ERR_INC
#undef RX_SAMP_DBG #undef RX_SAMP_DBG
@ -1278,6 +1252,8 @@ static const struct file_operations fops_modal_eeprom = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
#ifdef CONFIG_ATH9K_MAC_DEBUG
void ath9k_debug_samp_bb_mac(struct ath_softc *sc) void ath9k_debug_samp_bb_mac(struct ath_softc *sc)
{ {
#define ATH_SAMP_DBG(c) (sc->debug.bb_mac_samp[sc->debug.sampidx].c) #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, .llseek = default_llseek,
}; };
#endif
int ath9k_init_debug(struct ath_hw *ah) int ath9k_init_debug(struct ath_hw *ah)
{ {
@ -1604,8 +1581,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_base_eeprom); &fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc, debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_modal_eeprom); &fops_modal_eeprom);
#ifdef CONFIG_ATH9K_MAC_DEBUG
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_samps); &fops_samps);
#endif
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);

View File

@ -165,13 +165,6 @@ struct ath_rx_stats {
u32 post_delim_crc_err; u32 post_delim_crc_err;
u32 decrypt_busy_err; u32 decrypt_busy_err;
u32 phy_err_stats[ATH9K_PHYERR_MAX]; 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 { enum ath_reset_type {
@ -235,16 +228,17 @@ struct ath9k_debug {
struct dentry *debugfs_phy; struct dentry *debugfs_phy;
u32 regidx; u32 regidx;
struct ath_stats stats; struct ath_stats stats;
#ifdef CONFIG_ATH9K_MAC_DEBUG
spinlock_t samp_lock; spinlock_t samp_lock;
struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES]; struct ath_dbg_bb_mac_samp bb_mac_samp[ATH_DBG_MAX_SAMPLES];
u8 sampidx; u8 sampidx;
u8 tsidx; u8 tsidx;
u8 rsidx; u8 rsidx;
#endif
}; };
int ath9k_init_debug(struct ath_hw *ah); 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_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_status *ts, struct ath_txq *txq, 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; 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, static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status) enum ath9k_int status)
{ {
@ -282,4 +272,17 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc,
#endif /* CONFIG_ATH9K_DEBUGFS */ #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 */ #endif /* DEBUG_H */

View File

@ -362,7 +362,8 @@ void ath9k_stop_btcoex(struct ath_softc *sc)
ath9k_hw_btcoex_disable(ah); ath9k_hw_btcoex_disable(ah);
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_pause(sc); ath9k_btcoex_timer_pause(sc);
ath_mci_flush_profile(&sc->btcoex.mci); if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_MCI)
ath_mci_flush_profile(&sc->btcoex.mci);
} }
} }

View File

@ -919,7 +919,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
/* setup initial channel */ /* setup initial channel */
init_channel = ath9k_cmn_get_curchannel(hw, ah); init_channel = ath9k_cmn_get_curchannel(hw, ah);
ath9k_hw_htc_resetinit(ah);
ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (ret) { if (ret) {
ath_err(common, ath_err(common,

View File

@ -449,6 +449,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->slottime = ATH9K_SLOT_TIME_9; ah->slottime = ATH9K_SLOT_TIME_9;
ah->globaltxtimeout = (u32) -1; ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED; ah->power_mode = ATH9K_PM_UNDEFINED;
ah->htc_reset_init = true;
} }
static int ath9k_hw_init_macaddr(struct ath_hw *ah) static int ath9k_hw_init_macaddr(struct ath_hw *ah)
@ -555,7 +556,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
return -EIO; return -EIO;
} }
if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) {
if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI ||
((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) &&
!ah->is_pciexpress)) { !ah->is_pciexpress)) {
@ -619,9 +620,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (!ah->is_pciexpress) if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah); ath9k_hw_disablepcie(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
ar9002_hw_cck_chan14_spread(ah);
r = ath9k_hw_post_init(ah); r = ath9k_hw_post_init(ah);
if (r) if (r)
return r; return r;
@ -1386,10 +1384,16 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
static bool ath9k_hw_chip_reset(struct ath_hw *ah, static bool ath9k_hw_chip_reset(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { int reset_type = ATH9K_RESET_WARM;
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON))
return false; if (AR_SREV_9280(ah)) {
} else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) 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; return false;
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
@ -1515,17 +1519,81 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
} }
EXPORT_SYMBOL(ath9k_hw_check_alive); EXPORT_SYMBOL(ath9k_hw_check_alive);
/*
* Fast channel change:
* (Change synthesizer based on channel freq without resetting chip)
*
* Don't do FCC when
* - Flag is not set
* - Chip is just coming out of full sleep
* - Channel to be set is same as current channel
* - Channel flags are different, (eg.,moving from 2GHz to 5GHz channel)
*/
static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
int ret;
if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI)
goto fail;
if (ah->chip_fullsleep)
goto fail;
if (!ah->curchan)
goto fail;
if (chan->channel == ah->curchan->channel)
goto fail;
if ((chan->channelFlags & CHANNEL_ALL) !=
(ah->curchan->channelFlags & CHANNEL_ALL))
goto fail;
if (!ath9k_hw_check_alive(ah))
goto fail;
/*
* For AR9462, make sure that calibration data for
* re-using are present.
*/
if (AR_SREV_9462(ah) && (!ah->caldata ||
!ah->caldata->done_txiqcal_once ||
!ah->caldata->done_txclcal_once ||
!ah->caldata->rtt_hist.num_readings))
goto fail;
ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n",
ah->curchan->channel, chan->channel);
ret = ath9k_hw_channel_change(ah, chan);
if (!ret)
goto fail;
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
if ((ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && ar9003_mci_is_ready(ah))
ar9003_mci_2g5g_switch(ah, true);
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
return 0;
fail:
return -EINVAL;
}
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool bChannelChange) struct ath9k_hw_cal_data *caldata, bool fastcc)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
u32 saveLedState; u32 saveLedState;
struct ath9k_channel *curchan = ah->curchan;
u32 saveDefAntenna; u32 saveDefAntenna;
u32 macStaId1; u32 macStaId1;
u64 tsf = 0; u64 tsf = 0;
int i, r; int i, r;
bool allow_fbs = false, start_mci_reset = false; bool start_mci_reset = false;
bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI); bool mci = !!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI);
bool save_fullsleep = ah->chip_fullsleep; bool save_fullsleep = ah->chip_fullsleep;
@ -1538,8 +1606,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
return -EIO; return -EIO;
if (curchan && !ah->chip_fullsleep) if (ah->curchan && !ah->chip_fullsleep)
ath9k_hw_getnf(ah, curchan); ath9k_hw_getnf(ah, ah->curchan);
ah->caldata = caldata; ah->caldata = caldata;
if (caldata && if (caldata &&
@ -1552,32 +1620,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
} }
ah->noise = ath9k_hw_getchan_noise(ah, chan); ah->noise = ath9k_hw_getchan_noise(ah, chan);
if (AR_SREV_9280(ah) && common->bus_ops->ath_bus_type == ATH_PCI) if (fastcc) {
bChannelChange = false; r = ath9k_hw_do_fastcc(ah, chan);
if (!r)
if (caldata && return r;
caldata->done_txiqcal_once &&
caldata->done_txclcal_once &&
caldata->rtt_hist.num_readings)
allow_fbs = true;
if (bChannelChange &&
(ah->chip_fullsleep != true) &&
(ah->curchan != NULL) &&
(chan->channel != ah->curchan->channel) &&
(allow_fbs ||
((chan->channelFlags & CHANNEL_ALL) ==
(ah->curchan->channelFlags & CHANNEL_ALL)))) {
if (ath9k_hw_channel_change(ah, chan)) {
ath9k_hw_loadnf(ah, ah->curchan);
ath9k_hw_start_nfcal(ah, true);
if (mci && ar9003_mci_is_ready(ah))
ar9003_mci_2g5g_switch(ah, true);
if (AR_SREV_9271(ah))
ar9002_hw_load_ani_reg(ah, chan);
return 0;
}
} }
if (mci) if (mci)
@ -2384,8 +2430,17 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9485_OR_LATER(ah)) if (AR_SREV_9485_OR_LATER(ah))
ah->enabled_cals |= TX_IQ_ON_AGC_CAL; ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
} }
if (AR_SREV_9462(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT | ATH9K_HW_CAP_MCI; if (AR_SREV_9462(ah)) {
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
pCap->hw_caps |= ATH9K_HW_CAP_MCI;
if (AR_SREV_9462_20(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RTT;
}
return 0; return 0;
} }
@ -2511,12 +2566,6 @@ void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
} }
EXPORT_SYMBOL(ath9k_hw_set_gpio); EXPORT_SYMBOL(ath9k_hw_set_gpio);
u32 ath9k_hw_getdefantenna(struct ath_hw *ah)
{
return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
}
EXPORT_SYMBOL(ath9k_hw_getdefantenna);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
{ {
REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
@ -2574,6 +2623,7 @@ bool ath9k_hw_phy_disable(struct ath_hw *ah)
return false; return false;
ath9k_hw_init_pll(ah, NULL); ath9k_hw_init_pll(ah, NULL);
ah->htc_reset_init = true;
return true; return true;
} }
EXPORT_SYMBOL(ath9k_hw_phy_disable); EXPORT_SYMBOL(ath9k_hw_phy_disable);
@ -2934,12 +2984,6 @@ EXPORT_SYMBOL(ath_gen_timer_isr);
/* HTC */ /* HTC */
/********/ /********/
void ath9k_hw_htc_resetinit(struct ath_hw *ah)
{
ah->htc_reset_init = true;
}
EXPORT_SYMBOL(ath9k_hw_htc_resetinit);
static struct { static struct {
u32 version; u32 version;
const char * name; const char * name;

View File

@ -827,19 +827,14 @@ struct ath_hw {
struct ar5416IniArray iniAddac; struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes; struct ar5416IniArray iniPcieSerdes;
struct ar5416IniArray iniPcieSerdesLowPower; struct ar5416IniArray iniPcieSerdesLowPower;
struct ar5416IniArray iniModesAdditional; struct ar5416IniArray iniModesFastClock;
struct ar5416IniArray iniModesAdditional_40M; struct ar5416IniArray iniAdditional;
struct ar5416IniArray iniModesRxGain; struct ar5416IniArray iniModesRxGain;
struct ar5416IniArray iniModesTxGain; struct ar5416IniArray iniModesTxGain;
struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal; struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484; struct ar5416IniArray iniCckfirJapan2484;
struct ar5416IniArray ini_japan2484; struct ar5416IniArray ini_japan2484;
struct ar5416IniArray iniCommon_normal_cck_fir_coeff_9271;
struct ar5416IniArray iniCommon_japan_2484_cck_fir_coeff_9271;
struct ar5416IniArray iniModes_9271_ANI_reg; struct ar5416IniArray iniModes_9271_ANI_reg;
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
struct ar5416IniArray ini_radio_post_sys2ant; struct ar5416IniArray ini_radio_post_sys2ant;
struct ar5416IniArray ini_BTCOEX_MAX_TXPWR; struct ar5416IniArray ini_BTCOEX_MAX_TXPWR;
@ -924,7 +919,7 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah); void ath9k_hw_deinit(struct ath_hw *ah);
int ath9k_hw_init(struct ath_hw *ah); int ath9k_hw_init(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
struct ath9k_hw_cal_data *caldata, bool bChannelChange); struct ath9k_hw_cal_data *caldata, bool fastcc);
int ath9k_hw_fill_cap_info(struct ath_hw *ah); int ath9k_hw_fill_cap_info(struct ath_hw *ah);
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
@ -934,7 +929,6 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
u32 ah_signal_type); u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
u32 ath9k_hw_getdefantenna(struct ath_hw *ah);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
/* General Operation */ /* General Operation */
@ -988,9 +982,6 @@ void ath_gen_timer_isr(struct ath_hw *hw);
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len); void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
/* HTC */
void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */ /* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled, void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent); u32 *coef_mantissa, u32 *coef_exponent);
@ -1000,7 +991,6 @@ void ath9k_hw_apply_txpower(struct ath_hw *ah, struct ath9k_channel *chan);
* Code Specific to AR5008, AR9001 or AR9002, * Code Specific to AR5008, AR9001 or AR9002,
* we stuff these here to avoid callbacks for AR9003. * we stuff these here to avoid callbacks for AR9003.
*/ */
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
int ar9002_hw_rf_claim(struct ath_hw *ah); int ar9002_hw_rf_claim(struct ath_hw *ah);
void ar9002_hw_enable_async_fifo(struct ath_hw *ah); void ar9002_hw_enable_async_fifo(struct ath_hw *ah);

View File

@ -172,7 +172,7 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
struct ath_softc *sc = (struct ath_softc *) common->priv; struct ath_softc *sc = (struct ath_softc *) common->priv;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) { if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sc->sc_serial_rw, flags); spin_lock_irqsave(&sc->sc_serial_rw, flags);
iowrite32(val, sc->mem + reg_offset); iowrite32(val, sc->mem + reg_offset);
@ -188,7 +188,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
struct ath_softc *sc = (struct ath_softc *) common->priv; struct ath_softc *sc = (struct ath_softc *) common->priv;
u32 val; u32 val;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) { if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&sc->sc_serial_rw, flags); spin_lock_irqsave(&sc->sc_serial_rw, flags);
val = ioread32(sc->mem + reg_offset); val = ioread32(sc->mem + reg_offset);
@ -219,7 +219,7 @@ static unsigned int ath9k_reg_rmw(void *hw_priv, u32 reg_offset, u32 set, u32 cl
unsigned long uninitialized_var(flags); unsigned long uninitialized_var(flags);
u32 val; u32 val;
if (ah->config.serialize_regmode == SER_REG_MODE_ON) { if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_ON) {
spin_lock_irqsave(&sc->sc_serial_rw, flags); spin_lock_irqsave(&sc->sc_serial_rw, flags);
val = __ath9k_reg_rmw(sc, reg_offset, set, clr); val = __ath9k_reg_rmw(sc, reg_offset, set, clr);
spin_unlock_irqrestore(&sc->sc_serial_rw, flags); spin_unlock_irqrestore(&sc->sc_serial_rw, flags);
@ -484,19 +484,11 @@ static void ath9k_init_misc(struct ath_softc *sc)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0; int i = 0;
setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc); setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
sc->config.txpowlimit = ATH_TXPOWER_MAX; sc->config.txpowlimit = ATH_TXPOWER_MAX;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
sc->sc_flags |= SC_OP_TXAGGR;
sc->sc_flags |= SC_OP_RXAGGR;
}
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN); memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
sc->beacon.slottime = ATH9K_SLOT_TIME_9; sc->beacon.slottime = ATH9K_SLOT_TIME_9;
for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
@ -555,8 +547,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
mutex_init(&sc->mutex); mutex_init(&sc->mutex);
#ifdef CONFIG_ATH9K_DEBUGFS #ifdef CONFIG_ATH9K_DEBUGFS
spin_lock_init(&sc->nodes_lock); spin_lock_init(&sc->nodes_lock);
spin_lock_init(&sc->debug.samp_lock);
INIT_LIST_HEAD(&sc->nodes); INIT_LIST_HEAD(&sc->nodes);
#endif
#ifdef CONFIG_ATH9K_MAC_DEBUG
spin_lock_init(&sc->debug.samp_lock);
#endif #endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,

View File

@ -185,13 +185,6 @@ bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
} }
EXPORT_SYMBOL(ath9k_hw_stop_dma_queue); EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
{
*txqs &= ah->intr_txqs;
ah->intr_txqs &= ~(*txqs);
}
EXPORT_SYMBOL(ath9k_hw_gettxintrtxqs);
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
const struct ath9k_tx_queue_info *qinfo) const struct ath9k_tx_queue_info *qinfo)
{ {
@ -340,6 +333,15 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
} }
EXPORT_SYMBOL(ath9k_hw_setuptxqueue); EXPORT_SYMBOL(ath9k_hw_setuptxqueue);
static void ath9k_hw_clear_queue_interrupts(struct ath_hw *ah, u32 q)
{
ah->txok_interrupt_mask &= ~(1 << q);
ah->txerr_interrupt_mask &= ~(1 << q);
ah->txdesc_interrupt_mask &= ~(1 << q);
ah->txeol_interrupt_mask &= ~(1 << q);
ah->txurn_interrupt_mask &= ~(1 << q);
}
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
@ -354,11 +356,7 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
ath_dbg(common, QUEUE, "Release TX queue: %u\n", q); ath_dbg(common, QUEUE, "Release TX queue: %u\n", q);
qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
ah->txok_interrupt_mask &= ~(1 << q); ath9k_hw_clear_queue_interrupts(ah, q);
ah->txerr_interrupt_mask &= ~(1 << q);
ah->txdesc_interrupt_mask &= ~(1 << q);
ah->txeol_interrupt_mask &= ~(1 << q);
ah->txurn_interrupt_mask &= ~(1 << q);
ath9k_hw_set_txq_interrupts(ah, qi); ath9k_hw_set_txq_interrupts(ah, qi);
return true; return true;
@ -510,26 +508,17 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
if (AR_SREV_9300_20_OR_LATER(ah)) if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN); REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) ath9k_hw_clear_queue_interrupts(ah, q);
if (qi->tqi_qflags & TXQ_FLAG_TXINT_ENABLE) {
ah->txok_interrupt_mask |= 1 << q; ah->txok_interrupt_mask |= 1 << q;
else
ah->txok_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
ah->txerr_interrupt_mask |= 1 << q; ah->txerr_interrupt_mask |= 1 << q;
else }
ah->txerr_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
ah->txdesc_interrupt_mask |= 1 << q; ah->txdesc_interrupt_mask |= 1 << q;
else
ah->txdesc_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
ah->txeol_interrupt_mask |= 1 << q; ah->txeol_interrupt_mask |= 1 << q;
else
ah->txeol_interrupt_mask &= ~(1 << q);
if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
ah->txurn_interrupt_mask |= 1 << q; ah->txurn_interrupt_mask |= 1 << q;
else
ah->txurn_interrupt_mask &= ~(1 << q);
ath9k_hw_set_txq_interrupts(ah, qi); ath9k_hw_set_txq_interrupts(ah, qi);
return true; return true;
@ -745,7 +734,10 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
qi.tqi_aifs = 1; qi.tqi_aifs = 1;
qi.tqi_cwmin = 0; qi.tqi_cwmin = 0;
qi.tqi_cwmax = 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_TXINT_ENABLE;
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
} }
EXPORT_SYMBOL(ath9k_hw_beaconq_setup); EXPORT_SYMBOL(ath9k_hw_beaconq_setup);

View File

@ -583,8 +583,7 @@ enum ath9k_tx_queue {
#define ATH9K_WME_UPSD 4 #define ATH9K_WME_UPSD 4
enum ath9k_tx_queue_flags { enum ath9k_tx_queue_flags {
TXQ_FLAG_TXOKINT_ENABLE = 0x0001, TXQ_FLAG_TXINT_ENABLE = 0x0001,
TXQ_FLAG_TXERRINT_ENABLE = 0x0001,
TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, TXQ_FLAG_TXDESCINT_ENABLE = 0x0002,
TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, TXQ_FLAG_TXEOLINT_ENABLE = 0x0004,
TXQ_FLAG_TXURNINT_ENABLE = 0x0008, TXQ_FLAG_TXURNINT_ENABLE = 0x0008,
@ -714,7 +713,6 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q); bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
void ath9k_hw_abort_tx_dma(struct ath_hw *ah); void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
const struct ath9k_tx_queue_info *qinfo); const struct ath9k_tx_queue_info *qinfo);
bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,

View File

@ -118,13 +118,15 @@ void ath9k_ps_restore(struct ath_softc *sc)
if (--sc->ps_usecount != 0) if (--sc->ps_usecount != 0)
goto unlock; goto unlock;
if (sc->ps_idle && (sc->ps_flags & PS_WAIT_FOR_TX_ACK)) if (sc->ps_flags & PS_WAIT_FOR_TX_ACK)
goto unlock;
if (sc->ps_idle)
mode = ATH9K_PM_FULL_SLEEP; mode = ATH9K_PM_FULL_SLEEP;
else if (sc->ps_enabled && else if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON | !(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB | PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA | PS_WAIT_FOR_PSPOLL_DATA)))
PS_WAIT_FOR_TX_ACK)))
mode = ATH9K_PM_NETWORK_SLEEP; mode = ATH9K_PM_NETWORK_SLEEP;
else else
goto unlock; goto unlock;
@ -332,10 +334,6 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
hchan = ah->curchan; hchan = ah->curchan;
} }
if (fastcc && (ah->chip_fullsleep ||
!ath9k_hw_check_alive(ah)))
fastcc = false;
if (!ath_prepare_reset(sc, retry_tx, flush)) if (!ath_prepare_reset(sc, retry_tx, flush))
fastcc = false; fastcc = false;
@ -641,7 +639,8 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
#endif #endif
an->sta = sta; an->sta = sta;
an->vif = vif; an->vif = vif;
if (sc->sc_flags & SC_OP_TXAGGR) {
if (sta->ht_cap.ht_supported) {
ath_tx_node_init(sc, an); ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor); sta->ht_cap.ampdu_factor);
@ -660,7 +659,7 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
an->sta = NULL; an->sta = NULL;
#endif #endif
if (sc->sc_flags & SC_OP_TXAGGR) if (sta->ht_cap.ht_supported)
ath_tx_node_cleanup(sc, an); ath_tx_node_cleanup(sc, an);
} }
@ -993,12 +992,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
curchan->center_freq); curchan->center_freq);
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
/* setup initial channel */
sc->chan_idx = curchan->hw_value;
init_channel = ath9k_cmn_get_curchannel(hw, ah); init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */ /* Reset SERDES registers */
@ -1047,9 +1042,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
sc->sc_flags &= ~SC_OP_INVALID; sc->sc_flags &= ~SC_OP_INVALID;
sc->sc_ah->is_monitoring = false; sc->sc_ah->is_monitoring = false;
/* Disable BMISS interrupt when we're not associated */
ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
if (!ath_complete_reset(sc, false)) { if (!ath_complete_reset(sc, false)) {
r = -EIO; r = -EIO;
spin_unlock_bh(&sc->sc_pcu_lock); spin_unlock_bh(&sc->sc_pcu_lock);
@ -1277,7 +1269,6 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
iter_data->nwds++; iter_data->nwds++;
break; break;
default: default:
iter_data->nothers++;
break; break;
} }
} }
@ -1761,7 +1752,7 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_node *an = (struct ath_node *) sta->drv_priv; struct ath_node *an = (struct ath_node *) sta->drv_priv;
if (!(sc->sc_flags & SC_OP_TXAGGR)) if (!sta->ht_cap.ht_supported)
return; return;
switch (cmd) { switch (cmd) {
@ -1973,7 +1964,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
if (changed & BSS_CHANGED_BSSID) { if (changed & BSS_CHANGED_ASSOC) {
ath9k_config_bss(sc, vif); ath9k_config_bss(sc, vif);
ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n", ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
@ -2053,25 +2044,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
ath_beacon_config(sc, vif); ath_beacon_config(sc, vif);
} }
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
ath_dbg(common, CONFIG, "BSS Changed PREAMBLE %d\n",
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
else
sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT;
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
ath_dbg(common, CONFIG, "BSS Changed CTS PROT %d\n",
bss_conf->use_cts_prot);
if (bss_conf->use_cts_prot &&
hw->conf.channel->band != IEEE80211_BAND_5GHZ)
sc->sc_flags |= SC_OP_PROTECT_ENABLE;
else
sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
}
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
} }
@ -2129,15 +2101,10 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
switch (action) { switch (action) {
case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_START:
if (!(sc->sc_flags & SC_OP_RXAGGR))
ret = -ENOTSUPP;
break; break;
case IEEE80211_AMPDU_RX_STOP: case IEEE80211_AMPDU_RX_STOP:
break; break;
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
if (!(sc->sc_flags & SC_OP_TXAGGR))
return -EOPNOTSUPP;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
ret = ath_tx_aggr_start(sc, sta, tid, ssn); ret = ath_tx_aggr_start(sc, sta, tid, ssn);
if (!ret) if (!ret)
@ -2300,6 +2267,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
struct ath_vif *avp; struct ath_vif *avp;
struct ath_buf *bf; struct ath_buf *bf;
struct ath_tx_status ts; struct ath_tx_status ts;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int status; int status;
vif = sc->beacon.bslot[0]; vif = sc->beacon.bslot[0];
@ -2310,7 +2278,7 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
if (!avp->is_bslot_active) if (!avp->is_bslot_active)
return 0; return 0;
if (!sc->beacon.tx_processed) { if (!sc->beacon.tx_processed && !edma) {
tasklet_disable(&sc->bcon_tasklet); tasklet_disable(&sc->bcon_tasklet);
bf = avp->av_bcbuf; bf = avp->av_bcbuf;

View File

@ -748,7 +748,8 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
* If 802.11g protection is enabled, determine whether to use RTS/CTS or * If 802.11g protection is enabled, determine whether to use RTS/CTS or
* just CTS. Note that this is only done for OFDM/HT unicast frames. * just CTS. Note that this is only done for OFDM/HT unicast frames.
*/ */
if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && if ((tx_info->control.vif &&
tx_info->control.vif->bss_conf.use_cts_prot) &&
(rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM ||
WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { WLAN_RC_PHY_HT(rate_table->info[rix].phy))) {
rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT;
@ -1226,7 +1227,7 @@ static void ath_rc_init(struct ath_softc *sc,
ath_rc_init_valid_rate_idx(ath_rc_priv); ath_rc_init_valid_rate_idx(ath_rc_priv);
for (i = 0; i < WLAN_RC_PHY_MAX; i++) { 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_rateidx[i][j] = 0;
ath_rc_priv->valid_phy_ratecnt[i] = 0; ath_rc_priv->valid_phy_ratecnt[i] = 0;
} }
@ -1298,12 +1299,13 @@ static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta,
return caps; return caps;
} }
static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta,
u8 tidno) u8 tidno)
{ {
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid; struct ath_atx_tid *txtid;
if (!(sc->sc_flags & SC_OP_TXAGGR)) if (!sta->ht_cap.ht_supported)
return false; return false;
txtid = ATH_AN_2_TID(an, tidno); txtid = ATH_AN_2_TID(an, tidno);
@ -1374,13 +1376,11 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
if (ieee80211_is_data_qos(fc) && if (ieee80211_is_data_qos(fc) &&
skb_get_queue_mapping(skb) != IEEE80211_AC_VO) { skb_get_queue_mapping(skb) != IEEE80211_AC_VO) {
u8 *qc, tid; u8 *qc, tid;
struct ath_node *an;
qc = ieee80211_get_qos_ctl(hdr); qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf; tid = qc[0] & 0xf;
an = (struct ath_node *)sta->drv_priv;
if(ath_tx_aggr_check(sc, an, tid)) if(ath_tx_aggr_check(sc, sta, tid))
ieee80211_start_tx_ba_session(sta, tid, 0); ieee80211_start_tx_ba_session(sta, tid, 0);
} }
} }

View File

@ -25,8 +25,6 @@ struct ath_softc;
#define ATH_RATE_MAX 30 #define ATH_RATE_MAX 30
#define RATE_TABLE_SIZE 72 #define RATE_TABLE_SIZE 72
#define MAX_TX_RATE_PHY 48
#define RC_INVALID 0x0000 #define RC_INVALID 0x0000
#define RC_LEGACY 0x0001 #define RC_LEGACY 0x0001

View File

@ -169,22 +169,17 @@ static void ath_rx_addbuffer_edma(struct ath_softc *sc,
enum ath9k_rx_qtype qtype, int size) enum ath9k_rx_qtype qtype, int size)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u32 nbuf = 0; struct ath_buf *bf, *tbf;
if (list_empty(&sc->rx.rxbuf)) { if (list_empty(&sc->rx.rxbuf)) {
ath_dbg(common, QUEUE, "No free rx buf available\n"); ath_dbg(common, QUEUE, "No free rx buf available\n");
return; return;
} }
while (!list_empty(&sc->rx.rxbuf)) { list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list)
nbuf++;
if (!ath_rx_edma_buf_link(sc, qtype)) if (!ath_rx_edma_buf_link(sc, qtype))
break; break;
if (nbuf >= size)
break;
}
} }
static void ath_rx_remove_buffer(struct ath_softc *sc, 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) 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_fifo);
skb_queue_head_init(&rx_edma->rx_buffers);
rx_edma->rx_fifo_hwsize = size; 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, 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_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
struct ath_hw *ah = sc->sc_ah; 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, dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
common->rx_bufsize, DMA_FROM_DEVICE); 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) { if (ret == -EINPROGRESS) {
/*let device gain the buffer again*/ /*let device gain the buffer again*/
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, 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 */ /* corrupt descriptor, skip this one and the following one */
list_add_tail(&bf->list, &sc->rx.rxbuf); list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype); ath_rx_edma_buf_link(sc, qtype);
skb = skb_peek(&rx_edma->rx_fifo); skb = skb_peek(&rx_edma->rx_fifo);
if (!skb) if (skb) {
return true; bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
bf = SKB_CB_ATHBUF(skb); __skb_unlink(skb, &rx_edma->rx_fifo);
BUG_ON(!bf); list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
__skb_unlink(skb, &rx_edma->rx_fifo); } else {
list_add_tail(&bf->list, &sc->rx.rxbuf); bf = NULL;
ath_rx_edma_buf_link(sc, qtype); }
return true;
} }
skb_queue_tail(&rx_edma->rx_buffers, skb);
*dest = bf;
return true; 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, struct ath_rx_status *rs,
enum ath9k_rx_qtype qtype) enum ath9k_rx_qtype qtype)
{ {
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype]; struct ath_buf *bf = NULL;
struct sk_buff *skb;
struct ath_buf *bf;
while (ath_edma_get_buffers(sc, qtype)); while (ath_edma_get_buffers(sc, qtype, rs, &bf)) {
skb = __skb_dequeue(&rx_edma->rx_buffers); if (!bf)
if (!skb) continue;
return NULL;
bf = SKB_CB_ATHBUF(skb); return bf;
ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data); }
return bf; return NULL;
} }
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, 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_softc *sc = hw->priv;
struct ath_hw *ah = common->ah; struct ath_hw *ah = common->ah;
int last_rssi; int last_rssi;
int rssi = rx_stats->rs_rssi;
if (!rx_stats->is_mybeacon || if (!rx_stats->is_mybeacon ||
((ah->opmode != NL80211_IFTYPE_STATION) && ((ah->opmode != NL80211_IFTYPE_STATION) &&
@ -965,13 +960,12 @@ static void ath9k_process_rssi(struct ath_common *common,
last_rssi = sc->last_rssi; last_rssi = sc->last_rssi;
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
rx_stats->rs_rssi = ATH_EP_RND(last_rssi, rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
ATH_RSSI_EP_MULTIPLIER); if (rssi < 0)
if (rx_stats->rs_rssi < 0) rssi = 0;
rx_stats->rs_rssi = 0;
/* Update Beacon RSSI, this is used by ANI. */ /* Update Beacon RSSI, this is used by ANI. */
ah->stats.avgbrssi = rx_stats->rs_rssi; ah->stats.avgbrssi = rssi;
} }
/* /*
@ -988,8 +982,6 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
{ {
struct ath_hw *ah = common->ah; struct ath_hw *ah = common->ah;
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
/* /*
* everything but the rate is checked here, the rate check is done * everything but the rate is checked here, the rate check is done
* separately to avoid doing two lookups for a rate for each frame. * separately to avoid doing two lookups for a rate for each frame.
@ -1011,6 +1003,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
rx_status->signal = ah->noise + rx_stats->rs_rssi; rx_status->signal = ah->noise + rx_stats->rs_rssi;
rx_status->antenna = rx_stats->rs_antenna; rx_status->antenna = rx_stats->rs_antenna;
rx_status->flag |= RX_FLAG_MACTIME_MPDU; rx_status->flag |= RX_FLAG_MACTIME_MPDU;
if (rx_stats->rs_moreaggr)
rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
return 0; return 0;
} }
@ -1845,6 +1839,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
if (sc->sc_flags & SC_OP_RXFLUSH) if (sc->sc_flags & SC_OP_RXFLUSH)
goto requeue_drop_frag; goto requeue_drop_frag;
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
if (rs.rs_tstamp > tsf_lower && if (rs.rs_tstamp > tsf_lower &&
unlikely(rs.rs_tstamp - tsf_lower > 0x10000000)) unlikely(rs.rs_tstamp - tsf_lower > 0x10000000))

View File

@ -1151,6 +1151,7 @@ enum {
#define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4) #define AR_INTR_PRIO_ASYNC_ENABLE (AR_SREV_9340(ah) ? 0x4094 : 0x40d4)
#define AR_ENT_OTP 0x40d8 #define AR_ENT_OTP 0x40d8
#define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000 #define AR_ENT_OTP_CHAIN2_DISABLE 0x00020000
#define AR_ENT_OTP_49GHZ_DISABLE 0x00100000
#define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000 #define AR_ENT_OTP_MIN_PKT_SIZE_DISABLE 0x00800000
#define AR_CH0_BB_DPLL1 0x16180 #define AR_CH0_BB_DPLL1 0x16180

View File

@ -955,7 +955,9 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
*/ */
rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
info->rtscts_rate = rate->hw_value; info->rtscts_rate = rate->hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
if (tx_info->control.vif &&
tx_info->control.vif->bss_conf.use_short_preamble)
info->rtscts_rate |= rate->hw_value_short; info->rtscts_rate |= rate->hw_value_short;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
@ -1290,14 +1292,11 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
an = (struct ath_node *)sta->drv_priv; an = (struct ath_node *)sta->drv_priv;
if (sc->sc_flags & SC_OP_TXAGGR) { txtid = ATH_AN_2_TID(an, tid);
txtid = ATH_AN_2_TID(an, tid); txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
txtid->baw_size = txtid->state |= AGGR_ADDBA_COMPLETE;
IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; txtid->state &= ~AGGR_ADDBA_PROGRESS;
txtid->state |= AGGR_ADDBA_COMPLETE; ath_tx_resume_tid(sc, txtid);
txtid->state &= ~AGGR_ADDBA_PROGRESS;
ath_tx_resume_tid(sc, txtid);
}
} }
/********************/ /********************/
@ -1356,8 +1355,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
* based intr on the EOSP frames. * based intr on the EOSP frames.
*/ */
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE | qi.tqi_qflags = TXQ_FLAG_TXINT_ENABLE;
TXQ_FLAG_TXERRINT_ENABLE;
} else { } else {
if (qtype == ATH9K_TX_QUEUE_UAPSD) if (qtype == ATH9K_TX_QUEUE_UAPSD)
qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
@ -1523,7 +1521,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx); ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
/* flush any pending frames if aggregation is enabled */ /* flush any pending frames if aggregation is enabled */
if ((sc->sc_flags & SC_OP_TXAGGR) && !retry_tx) if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx)
ath_txq_drain_pending_buffers(sc, txq); ath_txq_drain_pending_buffers(sc, txq);
ath_txq_unlock_complete(sc, txq); ath_txq_unlock_complete(sc, txq);
@ -1871,7 +1869,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb,
struct ath_buf *bf; struct ath_buf *bf;
u8 tidno; u8 tidno;
if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an && if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && txctl->an &&
ieee80211_is_data_qos(hdr->frame_control)) { ieee80211_is_data_qos(hdr->frame_control)) {
tidno = ieee80211_get_qos_ctl(hdr)[0] & tidno = ieee80211_get_qos_ctl(hdr)[0] &
IEEE80211_QOS_CTL_TID_MASK; IEEE80211_QOS_CTL_TID_MASK;
@ -2141,7 +2139,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
} else } else
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true); ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
if (sc->sc_flags & SC_OP_TXAGGR) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ath_txq_schedule(sc, txq); ath_txq_schedule(sc, txq);
} }
@ -2166,7 +2164,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (list_empty(&txq->axq_q)) { if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL; txq->axq_link = NULL;
if (sc->sc_flags & SC_OP_TXAGGR) if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
ath_txq_schedule(sc, txq); ath_txq_schedule(sc, txq);
break; break;
} }
@ -2263,10 +2261,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
void ath_tx_tasklet(struct ath_softc *sc) void ath_tx_tasklet(struct ath_softc *sc)
{ {
struct ath_hw *ah = sc->sc_ah;
u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1) & ah->intr_txqs;
int i; int i;
u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1);
ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask);
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
@ -2296,9 +2293,12 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
break; break;
} }
/* Skip beacon completions */ /* Process beacon completions separately */
if (ts.qid == sc->beacon.beaconq) if (ts.qid == sc->beacon.beaconq) {
sc->beacon.tx_processed = true;
sc->beacon.tx_last = !(ts.ts_status & ATH9K_TXERR_MASK);
continue; continue;
}
txq = &sc->tx.txq[ts.qid]; txq = &sc->tx.txq[ts.qid];

View File

@ -57,7 +57,8 @@ struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
} }
EXPORT_SYMBOL(ath_rxbuf_alloc); EXPORT_SYMBOL(ath_rxbuf_alloc);
void ath_printk(const char *level, const char *fmt, ...) void ath_printk(const char *level, const struct ath_common* common,
const char *fmt, ...)
{ {
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
@ -67,7 +68,11 @@ void ath_printk(const char *level, const char *fmt, ...)
vaf.fmt = fmt; vaf.fmt = fmt;
vaf.va = &args; vaf.va = &args;
printk("%sath: %pV", level, &vaf); if (common && common->hw && common->hw->wiphy)
printk("%sath: %s: %pV",
level, wiphy_name(common->hw->wiphy), &vaf);
else
printk("%sath: %pV", level, &vaf);
va_end(args); va_end(args);
} }

View File

@ -932,6 +932,9 @@ struct b43_wl {
/* Flag that implement the queues stopping. */ /* Flag that implement the queues stopping. */
bool tx_queue_stopped[B43_QOS_QUEUE_NUM]; bool tx_queue_stopped[B43_QOS_QUEUE_NUM];
/* firmware loading work */
struct work_struct firmware_load;
/* The device LEDs. */ /* The device LEDs. */
struct b43_leds leds; struct b43_leds leds;

View File

@ -2390,8 +2390,14 @@ error:
return err; return err;
} }
static int b43_request_firmware(struct b43_wldev *dev) static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl);
static void b43_one_core_detach(struct b43_bus_dev *dev);
static void b43_request_firmware(struct work_struct *work)
{ {
struct b43_wl *wl = container_of(work,
struct b43_wl, firmware_load);
struct b43_wldev *dev = wl->current_dev;
struct b43_request_fw_context *ctx; struct b43_request_fw_context *ctx;
unsigned int i; unsigned int i;
int err; int err;
@ -2399,23 +2405,23 @@ static int b43_request_firmware(struct b43_wldev *dev)
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx) if (!ctx)
return -ENOMEM; return;
ctx->dev = dev; ctx->dev = dev;
ctx->req_type = B43_FWTYPE_PROPRIETARY; ctx->req_type = B43_FWTYPE_PROPRIETARY;
err = b43_try_request_fw(ctx); err = b43_try_request_fw(ctx);
if (!err) if (!err)
goto out; /* Successfully loaded it. */ goto start_ieee80211; /* Successfully loaded it. */
err = ctx->fatal_failure; /* Was fw version known? */
if (err) if (ctx->fatal_failure)
goto out; goto out;
/* proprietary fw not found, try open source */
ctx->req_type = B43_FWTYPE_OPENSOURCE; ctx->req_type = B43_FWTYPE_OPENSOURCE;
err = b43_try_request_fw(ctx); err = b43_try_request_fw(ctx);
if (!err) if (!err)
goto out; /* Successfully loaded it. */ goto start_ieee80211; /* Successfully loaded it. */
err = ctx->fatal_failure; if(ctx->fatal_failure)
if (err)
goto out; goto out;
/* Could not find a usable firmware. Print the errors. */ /* Could not find a usable firmware. Print the errors. */
@ -2425,11 +2431,20 @@ static int b43_request_firmware(struct b43_wldev *dev)
b43err(dev->wl, errmsg); b43err(dev->wl, errmsg);
} }
b43_print_fw_helptext(dev->wl, 1); b43_print_fw_helptext(dev->wl, 1);
err = -ENOENT; goto out;
start_ieee80211:
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
goto out;
err_one_core_detach:
b43_one_core_detach(dev->dev);
out: out:
kfree(ctx); kfree(ctx);
return err;
} }
static int b43_upload_microcode(struct b43_wldev *dev) static int b43_upload_microcode(struct b43_wldev *dev)
@ -2706,6 +2721,8 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask |= 0x0060; mask |= 0x0060;
set |= 0x0060; set |= 0x0060;
} }
if (dev->dev->chip_id == 0x5354)
set &= 0xff02;
if (0 /* FIXME: conditional unknown */ ) { if (0 /* FIXME: conditional unknown */ ) {
b43_write16(dev, B43_MMIO_GPIO_MASK, b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK) b43_read16(dev, B43_MMIO_GPIO_MASK)
@ -3021,9 +3038,6 @@ static int b43_chip_init(struct b43_wldev *dev)
macctl |= B43_MACCTL_INFRA; macctl |= B43_MACCTL_INFRA;
b43_write32(dev, B43_MMIO_MACCTL, macctl); b43_write32(dev, B43_MMIO_MACCTL, macctl);
err = b43_request_firmware(dev);
if (err)
goto out;
err = b43_upload_microcode(dev); err = b43_upload_microcode(dev);
if (err) if (err)
goto out; /* firmware is released later */ goto out; /* firmware is released later */
@ -4153,6 +4167,7 @@ redo:
mutex_unlock(&wl->mutex); mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work); cancel_delayed_work_sync(&dev->periodic_work);
cancel_work_sync(&wl->tx_work); cancel_work_sync(&wl->tx_work);
cancel_work_sync(&wl->firmware_load);
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
dev = wl->current_dev; dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) { if (!dev || b43_status(dev) < B43_STAT_STARTED) {
@ -5312,16 +5327,13 @@ static int b43_bcma_probe(struct bcma_device *core)
if (err) if (err)
goto bcma_err_wireless_exit; goto bcma_err_wireless_exit;
err = ieee80211_register_hw(wl->hw); /* setup and start work to load firmware */
if (err) INIT_WORK(&wl->firmware_load, b43_request_firmware);
goto bcma_err_one_core_detach; schedule_work(&wl->firmware_load);
b43_leds_register(wl->current_dev);
bcma_out: bcma_out:
return err; return err;
bcma_err_one_core_detach:
b43_one_core_detach(dev);
bcma_err_wireless_exit: bcma_err_wireless_exit:
ieee80211_free_hw(wl->hw); ieee80211_free_hw(wl->hw);
return err; return err;
@ -5388,18 +5400,13 @@ int b43_ssb_probe(struct ssb_device *sdev, const struct ssb_device_id *id)
if (err) if (err)
goto err_wireless_exit; goto err_wireless_exit;
if (first) { /* setup and start work to load firmware */
err = ieee80211_register_hw(wl->hw); INIT_WORK(&wl->firmware_load, b43_request_firmware);
if (err) schedule_work(&wl->firmware_load);
goto err_one_core_detach;
b43_leds_register(wl->current_dev);
}
out: out:
return err; return err;
err_one_core_detach:
b43_one_core_detach(dev);
err_wireless_exit: err_wireless_exit:
if (first) if (first)
b43_wireless_exit(dev, wl); b43_wireless_exit(dev, wl);

View File

@ -581,6 +581,9 @@ struct b43legacy_wl {
struct mutex mutex; /* locks wireless core state */ struct mutex mutex; /* locks wireless core state */
spinlock_t leds_lock; /* lock for leds */ spinlock_t leds_lock; /* lock for leds */
/* firmware loading work */
struct work_struct firmware_load;
/* We can only have one operating interface (802.11 core) /* We can only have one operating interface (802.11 core)
* at a time. General information about this interface follows. * at a time. General information about this interface follows.
*/ */

View File

@ -1557,8 +1557,15 @@ err_format:
return -EPROTO; return -EPROTO;
} }
static int b43legacy_request_firmware(struct b43legacy_wldev *dev) static int b43legacy_one_core_attach(struct ssb_device *dev,
struct b43legacy_wl *wl);
static void b43legacy_one_core_detach(struct ssb_device *dev);
static void b43legacy_request_firmware(struct work_struct *work)
{ {
struct b43legacy_wl *wl = container_of(work,
struct b43legacy_wl, firmware_load);
struct b43legacy_wldev *dev = wl->current_dev;
struct b43legacy_firmware *fw = &dev->fw; struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision; const u8 rev = dev->dev->id.revision;
const char *filename; const char *filename;
@ -1624,8 +1631,14 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
if (err) if (err)
goto err_load; goto err_load;
} }
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
return;
return 0; err_one_core_detach:
b43legacy_one_core_detach(dev->dev);
goto error;
err_load: err_load:
b43legacy_print_fw_helptext(dev->wl); b43legacy_print_fw_helptext(dev->wl);
@ -1639,7 +1652,7 @@ err_no_initvals:
error: error:
b43legacy_release_firmware(dev); b43legacy_release_firmware(dev);
return err; return;
} }
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
@ -2153,9 +2166,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_INFRA; macctl |= B43legacy_MACCTL_INFRA;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
err = b43legacy_request_firmware(dev);
if (err)
goto out;
err = b43legacy_upload_microcode(dev); err = b43legacy_upload_microcode(dev);
if (err) if (err)
goto out; /* firmware is released later */ goto out; /* firmware is released later */
@ -3860,17 +3870,13 @@ static int b43legacy_probe(struct ssb_device *dev,
if (err) if (err)
goto err_wireless_exit; goto err_wireless_exit;
if (first) { /* setup and start work to load firmware */
err = ieee80211_register_hw(wl->hw); INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
if (err) schedule_work(&wl->firmware_load);
goto err_one_core_detach;
}
out: out:
return err; return err;
err_one_core_detach:
b43legacy_one_core_detach(dev);
err_wireless_exit: err_wireless_exit:
if (first) if (first)
b43legacy_wireless_exit(dev, wl); b43legacy_wireless_exit(dev, wl);
@ -3885,6 +3891,7 @@ static void b43legacy_remove(struct ssb_device *dev)
/* We must cancel any work here before unregistering from ieee80211, /* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */ * as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work); cancel_work_sync(&wldev->restart_work);
cancel_work_sync(&wl->firmware_load);
B43legacy_WARN_ON(!wl); B43legacy_WARN_ON(!wl);
if (wl->current_dev == wldev) if (wl->current_dev == wldev)

View File

@ -1860,7 +1860,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
* which accounts for the factor of 4 */ * which accounts for the factor of 4 */
#define REG_MAX_PWR 20 #define REG_MAX_PWR 20
max_pwr = min(REG_MAX_PWR * 4 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); - 0x6, max_pwr);
/* find the desired power in Q5.2 - power_level is in dBm /* find the desired power in Q5.2 - power_level is in dBm

View File

@ -604,7 +604,7 @@ void brcmf_sdio_exit(void)
sdio_unregister_driver(&brcmf_sdmmc_driver); sdio_unregister_driver(&brcmf_sdmmc_driver);
} }
int brcmf_sdio_init(void) void brcmf_sdio_init(void)
{ {
int ret; int ret;
@ -614,6 +614,4 @@ int brcmf_sdio_init(void)
if (ret) if (ret)
brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret); brcmf_dbg(ERROR, "sdio_register_driver failed: %d\n", ret);
return ret;
} }

View File

@ -108,11 +108,11 @@ extern int brcmf_add_if(struct device *dev, int ifidx,
#ifdef CONFIG_BRCMFMAC_SDIO #ifdef CONFIG_BRCMFMAC_SDIO
extern void brcmf_sdio_exit(void); extern void brcmf_sdio_exit(void);
extern int brcmf_sdio_init(void); extern void brcmf_sdio_init(void);
#endif #endif
#ifdef CONFIG_BRCMFMAC_USB #ifdef CONFIG_BRCMFMAC_USB
extern void brcmf_usb_exit(void); extern void brcmf_usb_exit(void);
extern int brcmf_usb_init(void); extern void brcmf_usb_init(void);
#endif #endif
#endif /* _BRCMF_BUS_H_ */ #endif /* _BRCMF_BUS_H_ */

View File

@ -1181,27 +1181,29 @@ exit:
} }
#endif /* DEBUG */ #endif /* DEBUG */
static int __init brcmfmac_init(void) static void brcmf_driver_init(struct work_struct *work)
{ {
int ret = 0;
#ifdef CONFIG_BRCMFMAC_SDIO #ifdef CONFIG_BRCMFMAC_SDIO
ret = brcmf_sdio_init(); brcmf_sdio_init();
if (ret)
goto fail;
#endif #endif
#ifdef CONFIG_BRCMFMAC_USB #ifdef CONFIG_BRCMFMAC_USB
ret = brcmf_usb_init(); brcmf_usb_init();
if (ret)
goto fail;
#endif #endif
}
static DECLARE_WORK(brcmf_driver_work, brcmf_driver_init);
fail: static int __init brcmfmac_module_init(void)
return ret; {
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 #ifdef CONFIG_BRCMFMAC_SDIO
brcmf_sdio_exit(); brcmf_sdio_exit();
#endif #endif
@ -1210,5 +1212,5 @@ static void __exit brcmfmac_exit(void)
#endif #endif
} }
module_init(brcmfmac_init); module_init(brcmfmac_module_init);
module_exit(brcmfmac_exit); module_exit(brcmfmac_module_exit);

View File

@ -514,9 +514,9 @@ static void brcmf_usb_tx_complete(struct urb *urb)
brcmf_usb_del_fromq(devinfo, req); brcmf_usb_del_fromq(devinfo, req);
if (urb->status == 0) if (urb->status == 0)
devinfo->bus_pub.stats.tx_packets++; devinfo->bus_pub.bus->dstats.tx_packets++;
else else
devinfo->bus_pub.stats.tx_errors++; devinfo->bus_pub.bus->dstats.tx_errors++;
dev_kfree_skb(req->skb); dev_kfree_skb(req->skb);
req->skb = NULL; req->skb = NULL;
@ -536,9 +536,9 @@ static void brcmf_usb_rx_complete(struct urb *urb)
req->skb = NULL; req->skb = NULL;
if (urb->status == 0) { if (urb->status == 0) {
devinfo->bus_pub.stats.rx_packets++; devinfo->bus_pub.bus->dstats.rx_packets++;
} else { } else {
devinfo->bus_pub.stats.rx_errors++; devinfo->bus_pub.bus->dstats.rx_errors++;
dev_kfree_skb(skb); dev_kfree_skb(skb);
brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
return; return;
@ -712,9 +712,6 @@ static int brcmf_usb_up(struct device *dev)
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
u16 ifnum; u16 ifnum;
if (devinfo == NULL)
return -EINVAL;
if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
return 0; return 0;
@ -900,8 +897,8 @@ brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
sizeof(struct bootrom_id_le)); sizeof(struct bootrom_id_le));
return false; return false;
} else { } else {
devinfo->bus_pub.attrib.devid = chipid; devinfo->bus_pub.devid = chipid;
devinfo->bus_pub.attrib.chiprev = chiprev; devinfo->bus_pub.chiprev = chiprev;
} }
return true; return true;
} }
@ -1067,7 +1064,7 @@ static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
if (devinfo == NULL) if (devinfo == NULL)
return -EINVAL; return -EINVAL;
if (devinfo->bus_pub.attrib.devid == 0xDEAD) if (devinfo->bus_pub.devid == 0xDEAD)
return -EINVAL; return -EINVAL;
err = brcmf_usb_dl_writeimage(devinfo, fw, len); err = brcmf_usb_dl_writeimage(devinfo, fw, len);
@ -1088,7 +1085,7 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
if (!devinfo) if (!devinfo)
return -EINVAL; return -EINVAL;
if (devinfo->bus_pub.attrib.devid == 0xDEAD) if (devinfo->bus_pub.devid == 0xDEAD)
return -EINVAL; return -EINVAL;
/* Check we are runnable */ /* Check we are runnable */
@ -1127,18 +1124,19 @@ static bool brcmf_usb_chip_support(int chipid, int chiprev)
static int static int
brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
{ {
struct brcmf_usb_attrib *attr; int devid, chiprev;
int err; int err;
brcmf_dbg(TRACE, "enter\n"); brcmf_dbg(TRACE, "enter\n");
if (devinfo == NULL) if (devinfo == NULL)
return -ENODEV; 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", brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
attr->devid, attr->chiprev); devid, chiprev);
return -EINVAL; return -EINVAL;
} }
@ -1617,7 +1615,7 @@ void brcmf_usb_exit(void)
g_image.len = 0; g_image.len = 0;
} }
int brcmf_usb_init(void) void brcmf_usb_init(void)
{ {
return usb_register(&brcmf_usbdrvr); usb_register(&brcmf_usbdrvr);
} }

View File

@ -33,36 +33,12 @@ enum brcmf_usb_pnp_state {
}; };
struct brcmf_stats { struct brcmf_stats {
u32 tx_errors;
u32 tx_packets;
u32 tx_multicast;
u32 tx_ctlpkts; u32 tx_ctlpkts;
u32 tx_ctlerrs; u32 tx_ctlerrs;
u32 tx_dropped;
u32 tx_flushed;
u32 rx_errors;
u32 rx_packets;
u32 rx_multicast;
u32 rx_ctlpkts; u32 rx_ctlpkts;
u32 rx_ctlerrs; 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_usbdev {
struct brcmf_bus *bus; struct brcmf_bus *bus;
struct brcmf_usbdev_info *devinfo; struct brcmf_usbdev_info *devinfo;
@ -70,7 +46,8 @@ struct brcmf_usbdev {
struct brcmf_stats stats; struct brcmf_stats stats;
int ntxq, nrxq, rxsize; int ntxq, nrxq, rxsize;
u32 bus_mtu; u32 bus_mtu;
struct brcmf_usb_attrib attrib; int devid;
int chiprev; /* chip revsion number */
}; };
/* IO Request Block (IRB) */ /* IO Request Block (IRB) */

View File

@ -2003,7 +2003,6 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
s32 err = 0; s32 err = 0;
u16 channel; u16 channel;
u32 freq; u32 freq;
u64 notify_timestamp;
u16 notify_capability; u16 notify_capability;
u16 notify_interval; u16 notify_interval;
u8 *notify_ie; u8 *notify_ie;
@ -2026,7 +2025,6 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
freq = ieee80211_channel_to_frequency(channel, band->band); freq = ieee80211_channel_to_frequency(channel, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq); notify_channel = ieee80211_get_channel(wiphy, freq);
notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
notify_capability = le16_to_cpu(bi->capability); notify_capability = le16_to_cpu(bi->capability);
notify_interval = le16_to_cpu(bi->beacon_period); notify_interval = le16_to_cpu(bi->beacon_period);
notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
@ -2040,10 +2038,9 @@ static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv,
WL_CONN("Capability: %X\n", notify_capability); WL_CONN("Capability: %X\n", notify_capability);
WL_CONN("Beacon interval: %d\n", notify_interval); WL_CONN("Beacon interval: %d\n", notify_interval);
WL_CONN("Signal: %d\n", notify_signal); WL_CONN("Signal: %d\n", notify_signal);
WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID, bss = cfg80211_inform_bss(wiphy, notify_channel, (const u8 *)bi->BSSID,
notify_timestamp, notify_capability, notify_interval, notify_ie, 0, notify_capability, notify_interval, notify_ie,
notify_ielen, notify_signal, GFP_KERNEL); notify_ielen, notify_signal, GFP_KERNEL);
if (!bss) if (!bss)
@ -2098,7 +2095,6 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
s32 err = 0; s32 err = 0;
u16 channel; u16 channel;
u32 freq; u32 freq;
u64 notify_timestamp;
u16 notify_capability; u16 notify_capability;
u16 notify_interval; u16 notify_interval;
u8 *notify_ie; u8 *notify_ie;
@ -2134,7 +2130,6 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
freq = ieee80211_channel_to_frequency(channel, band->band); freq = ieee80211_channel_to_frequency(channel, band->band);
notify_channel = ieee80211_get_channel(wiphy, freq); notify_channel = ieee80211_get_channel(wiphy, freq);
notify_timestamp = jiffies_to_msecs(jiffies)*1000; /* uSec */
notify_capability = le16_to_cpu(bi->capability); notify_capability = le16_to_cpu(bi->capability);
notify_interval = le16_to_cpu(bi->beacon_period); notify_interval = le16_to_cpu(bi->beacon_period);
notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset); notify_ie = (u8 *)bi + le16_to_cpu(bi->ie_offset);
@ -2145,10 +2140,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv,
WL_CONN("capability: %X\n", notify_capability); WL_CONN("capability: %X\n", notify_capability);
WL_CONN("beacon interval: %d\n", notify_interval); WL_CONN("beacon interval: %d\n", notify_interval);
WL_CONN("signal: %d\n", notify_signal); WL_CONN("signal: %d\n", notify_signal);
WL_CONN("notify_timestamp: %#018llx\n", notify_timestamp);
bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, bss = cfg80211_inform_bss(wiphy, notify_channel, bssid,
notify_timestamp, notify_capability, notify_interval, 0, notify_capability, notify_interval,
notify_ie, notify_ielen, notify_signal, GFP_KERNEL); notify_ie, notify_ielen, notify_signal, GFP_KERNEL);
if (!bss) { if (!bss) {

View File

@ -959,14 +959,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
if (supr_status) { if (supr_status) {
update_rate = false; update_rate = false;
if (supr_status == TX_STATUS_SUPR_BADCH) { if (supr_status == TX_STATUS_SUPR_BADCH) {
wiphy_err(wiphy, "%s: Pkt tx suppressed, " wiphy_err(wiphy,
"illegal channel possibly %d\n", "%s: Pkt tx suppressed, illegal channel possibly %d\n",
__func__, CHSPEC_CHANNEL( __func__, CHSPEC_CHANNEL(
wlc->default_bss->chanspec)); wlc->default_bss->chanspec));
} else { } else {
if (supr_status != TX_STATUS_SUPR_FRAG) if (supr_status != TX_STATUS_SUPR_FRAG)
wiphy_err(wiphy, "%s:" wiphy_err(wiphy, "%s: supr_status 0x%x\n",
"supr_status 0x%x\n",
__func__, supr_status); __func__, supr_status);
} }
/* no need to retry for badch; will fail again */ /* 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) { } else if (txs->phyerr) {
update_rate = false; update_rate = false;
wiphy_err(wiphy, "wl%d: ampdu tx phy " wiphy_err(wiphy, "%s: ampdu tx phy error (0x%x)\n",
"error (0x%x)\n", wlc->pub->unit, __func__, txs->phyerr);
txs->phyerr);
if (brcm_msg_level & LOG_ERROR_VAL) { if (brcm_msg_level & LOG_ERROR_VAL) {
brcmu_prpkt("txpkt (AMPDU)", p); brcmu_prpkt("txpkt (AMPDU)", p);
@ -1018,10 +1016,10 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
ack_recd = false; ack_recd = false;
if (ba_recd) { if (ba_recd) {
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX); bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
BCMMSG(wlc->wiphy, "tid %d seq %d," BCMMSG(wiphy,
" start_seq %d, bindex %d set %d, index %d\n", "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
tid, seq, start_seq, bindex, tid, seq, start_seq, bindex,
isset(bitmap, bindex), index); isset(bitmap, bindex), index);
/* if acked then clear bit and free packet */ /* if acked then clear bit and free packet */
if ((bindex < AMPDU_TX_BA_MAX_WSIZE) if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
&& isset(bitmap, bindex)) { && isset(bitmap, bindex)) {

View File

@ -1169,25 +1169,31 @@ static struct bcma_driver brcms_bcma_driver = {
/** /**
* This is the main entry point for the brcmsmac 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, * This function is scheduled upon module initialization and
* and if so, performs a brcms_attach() on it. * 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) static int __init brcms_module_init(void)
{ {
int error = -ENODEV;
#ifdef DEBUG #ifdef DEBUG
if (msglevel != 0xdeadbeef) if (msglevel != 0xdeadbeef)
brcm_msg_level = msglevel; brcm_msg_level = msglevel;
#endif /* DEBUG */ #endif
if (!schedule_work(&brcms_driver_work))
return -EBUSY;
error = bcma_driver_register(&brcms_bcma_driver); return 0;
pr_err("%s: register returned %d\n", __func__, error);
if (!error)
return 0;
return error;
} }
/** /**
@ -1199,6 +1205,7 @@ static int __init brcms_module_init(void)
*/ */
static void __exit brcms_module_exit(void) static void __exit brcms_module_exit(void)
{ {
cancel_work_sync(&brcms_driver_work);
bcma_driver_unregister(&brcms_bcma_driver); bcma_driver_unregister(&brcms_bcma_driver);
} }

View File

@ -298,8 +298,6 @@ static const char *command_types[] = {
}; };
#endif #endif
#define WEXT_USECHANNELS 1
static const long ipw2100_frequencies[] = { static const long ipw2100_frequencies[] = {
2412, 2417, 2422, 2427, 2412, 2417, 2422, 2427,
2432, 2437, 2442, 2447, 2432, 2437, 2442, 2447,

View File

@ -27,8 +27,6 @@
#ifndef __ipw2200_h__ #ifndef __ipw2200_h__
#define __ipw2200_h__ #define __ipw2200_h__
#define WEXT_USECHANNELS 1
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/init.h> #include <linux/init.h>
@ -1999,18 +1997,6 @@ struct ipw_cmd_log {
#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ #define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */
#define CFG_SYS_ANTENNA_SLOW_DIV 0x02 /* consider background noise */ #define CFG_SYS_ANTENNA_SLOW_DIV 0x02 /* consider background noise */
/*
* The definitions below were lifted off the ipw2100 driver, which only
* supports 'b' mode, so I'm sure these are not exactly correct.
*
* Somebody fix these!!
*/
#define REG_MIN_CHANNEL 0
#define REG_MAX_CHANNEL 14
#define REG_CHANNEL_MASK 0x00003FFF
#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff
#define IPW_MAX_CONFIG_RETRIES 10 #define IPW_MAX_CONFIG_RETRIES 10
#endif /* __ipw2200_h__ */ #endif /* __ipw2200_h__ */

View File

@ -5355,7 +5355,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (changes & BSS_CHANGED_ASSOC) { if (changes & BSS_CHANGED_ASSOC) {
D_MAC80211("ASSOC %d\n", bss_conf->assoc); D_MAC80211("ASSOC %d\n", bss_conf->assoc);
if (bss_conf->assoc) { if (bss_conf->assoc) {
il->timestamp = bss_conf->timestamp; il->timestamp = bss_conf->last_tsf;
if (!il_is_rfkill(il)) if (!il_is_rfkill(il))
il->ops->post_associate(il); il->ops->post_associate(il);

View File

@ -1,6 +1,6 @@
config IWLWIFI config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (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 FW_LOADER
select NEW_LEDS select NEW_LEDS
select LEDS_CLASS select LEDS_CLASS
@ -127,3 +127,12 @@ config IWLWIFI_P2P
support when it is loaded. support when it is loaded.
Say Y only if you want to experiment with P2P. 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.

View File

@ -14,7 +14,7 @@ iwlwifi-objs += iwl-1000.o
iwlwifi-objs += iwl-2000.o iwlwifi-objs += iwl-2000.o
iwlwifi-objs += iwl-pci.o iwlwifi-objs += iwl-pci.o
iwlwifi-objs += iwl-drv.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-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlwifi-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o

View File

@ -43,6 +43,7 @@
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-shared.h" #include "iwl-shared.h"
#include "iwl-cfg.h" #include "iwl-cfg.h"
#include "iwl-prph.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL1000_UCODE_API_MAX 6 #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); ~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, .min_nrg_cck = 95,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90, .auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 120, .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) 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).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) if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
hw_params(priv).rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(cfg(priv)->valid_rx_ant); num_of_ant(hw_params(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;
iwl1000_set_ct_threshold(priv); iwl1000_set_ct_threshold(priv);
@ -163,7 +155,7 @@ static struct iwl_lib_ops iwl1000_lib = {
.temperature = iwlagn_temperature, .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_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
.eeprom_size = OTP_LOW_IMAGE_SIZE, .eeprom_size = OTP_LOW_IMAGE_SIZE,
@ -178,7 +170,8 @@ static struct iwl_base_params iwl1000_base_params = {
.max_event_log_size = 128, .max_event_log_size = 128,
.wd_disable = true, .wd_disable = true,
}; };
static struct iwl_ht_params iwl1000_ht_params = {
static const struct iwl_ht_params iwl1000_ht_params = {
.ht_greenfield_support = true, .ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */ .use_rts_for_aggregation = true, /* use rts/cts protection */
.smps_mode = IEEE80211_SMPS_DYNAMIC, .smps_mode = IEEE80211_SMPS_DYNAMIC,
@ -197,13 +190,13 @@ static struct iwl_ht_params iwl1000_ht_params = {
.base_params = &iwl1000_base_params, \ .base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_BLINK .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", .name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
IWL_DEVICE_1000, IWL_DEVICE_1000,
.ht_params = &iwl1000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
IWL_DEVICE_1000, IWL_DEVICE_1000,
}; };
@ -222,13 +215,13 @@ struct iwl_cfg iwl1000_bg_cfg = {
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true .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", .name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
IWL_DEVICE_100, IWL_DEVICE_100,
.ht_params = &iwl1000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 100 BG",
IWL_DEVICE_100, IWL_DEVICE_100,
}; };

View File

@ -91,9 +91,8 @@ static void iwl2000_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); 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, .min_nrg_cck = 97,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 80, .auto_corr_min_ofdm = 80,
.auto_corr_min_ofdm_mrc = 128, .auto_corr_min_ofdm_mrc = 128,
.auto_corr_min_ofdm_x1 = 105, .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) 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).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) if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
hw_params(priv).rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(cfg(priv)->valid_rx_ant); num_of_ant(hw_params(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;
iwl2000_set_ct_threshold(priv); iwl2000_set_ct_threshold(priv);
@ -155,16 +146,13 @@ static struct iwl_lib_ops iwl2000_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40, EEPROM_REGULATORY_BAND_NO_HT40,
}, },
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower, .enhanced_txpower = true,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
static struct iwl_lib_ops iwl2030_lib = { static struct iwl_lib_ops iwl2030_lib = {
.set_hw_params = iwl2000_hw_set_hw_params, .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, .nic_config = iwl2000_nic_config,
.eeprom_ops = { .eeprom_ops = {
.regulatory_bands = { .regulatory_bands = {
@ -176,12 +164,12 @@ static struct iwl_lib_ops iwl2030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REGULATORY_BAND_NO_HT40, EEPROM_REGULATORY_BAND_NO_HT40,
}, },
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower, .enhanced_txpower = true,
}, },
.temperature = iwlagn_temperature, .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, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_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, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@ -218,12 +206,12 @@ static struct iwl_base_params iwl2030_base_params = {
.hd_v2 = true, .hd_v2 = true,
}; };
static struct iwl_ht_params iwl2000_ht_params = { static const struct iwl_ht_params iwl2000_ht_params = {
.ht_greenfield_support = true, .ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */ .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 */ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.advanced_bt_coexist = true, .advanced_bt_coexist = true,
.agg_time_limit = BT_AGG_THRESHOLD_DEF, .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, \ .led_mode = IWL_LED_RF_STATE, \
.iq_invert = true \ .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", .name = "Intel(R) Centrino(R) Wireless-N 2200 BGN",
IWL_DEVICE_2000, IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 2200D BGN",
IWL_DEVICE_2000, IWL_DEVICE_2000,
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,
@ -279,7 +267,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
.adv_pm = true, \ .adv_pm = true, \
.iq_invert = 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", .name = "Intel(R) Centrino(R) Wireless-N 2230 BGN",
IWL_DEVICE_2030, IWL_DEVICE_2030,
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,
@ -303,13 +291,13 @@ struct iwl_cfg iwl2030_2bgn_cfg = {
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.iq_invert = 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", .name = "Intel(R) Centrino(R) Wireless-N 105 BGN",
IWL_DEVICE_105, IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 105D BGN",
IWL_DEVICE_105, IWL_DEVICE_105,
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,
@ -334,7 +322,7 @@ struct iwl_cfg iwl105_bgn_d_cfg = {
.rx_with_siso_diversity = true, \ .rx_with_siso_diversity = true, \
.iq_invert = 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", .name = "Intel(R) Centrino(R) Wireless-N 135 BGN",
IWL_DEVICE_135, IWL_DEVICE_135,
.ht_params = &iwl2000_ht_params, .ht_params = &iwl2000_ht_params,

View File

@ -45,6 +45,7 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h" #include "iwl-shared.h"
#include "iwl-cfg.h" #include "iwl-cfg.h"
#include "iwl-prph.h"
/* Highest firmware API version supported */ /* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 5 #define IWL5000_UCODE_API_MAX 5
@ -63,12 +64,8 @@
/* NIC configuration for 5000 series */ /* NIC configuration for 5000 series */
static void iwl5000_nic_config(struct iwl_priv *priv) static void iwl5000_nic_config(struct iwl_priv *priv)
{ {
unsigned long flags;
iwl_rf_config(priv); 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 /* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted), * (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back. * 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, 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,
~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, .min_nrg_cck = 100,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90, .auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 105, .auto_corr_min_ofdm_x1 = 105,
@ -108,7 +101,6 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
static struct iwl_sensitivity_ranges iwl5150_sensitivity = { static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
.min_nrg_cck = 95, .min_nrg_cck = 95,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 90, .auto_corr_min_ofdm = 90,
.auto_corr_min_ofdm_mrc = 170, .auto_corr_min_ofdm_mrc = 170,
.auto_corr_min_ofdm_x1 = 105, .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) 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) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); BIT(IEEE80211_BAND_5GHZ);
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); hw_params(priv).tx_chains_num =
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant); num_of_ant(hw_params(priv).valid_tx_ant);
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; hw_params(priv).rx_chains_num =
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; num_of_ant(hw_params(priv).valid_rx_ant);
iwl5000_set_ct_threshold(priv); 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) 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) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); BIT(IEEE80211_BAND_5GHZ);
hw_params(priv).tx_chains_num = num_of_ant(cfg(priv)->valid_tx_ant); hw_params(priv).tx_chains_num =
hw_params(priv).rx_chains_num = num_of_ant(cfg(priv)->valid_rx_ant); num_of_ant(hw_params(priv).valid_tx_ant);
hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant; hw_params(priv).rx_chains_num =
hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant; num_of_ant(hw_params(priv).valid_rx_ant);
iwl5150_set_ct_threshold(priv); iwl5150_set_ct_threshold(priv);
@ -288,7 +266,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT; return -EFAULT;
} }
return iwl_trans_send_cmd(trans(priv), &hcmd); return iwl_dvm_send_cmd(priv, &hcmd);
} }
static struct iwl_lib_ops iwl5000_lib = { static struct iwl_lib_ops iwl5000_lib = {
@ -327,7 +305,7 @@ static struct iwl_lib_ops iwl5150_lib = {
.temperature = iwl5150_temperature, .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, .eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_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, .no_idle_support = true,
.wd_disable = 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, .ht_greenfield_support = true,
}; };
@ -356,7 +335,7 @@ static struct iwl_ht_params iwl5000_ht_params = {
.base_params = &iwl5000_base_params, \ .base_params = &iwl5000_base_params, \
.led_mode = IWL_LED_BLINK .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", .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
IWL_DEVICE_5000, IWL_DEVICE_5000,
/* at least EEPROM 0x11A has wrong info */ /* at least EEPROM 0x11A has wrong info */
@ -365,7 +344,7 @@ struct iwl_cfg iwl5300_agn_cfg = {
.ht_params = &iwl5000_ht_params, .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", .name = "Intel(R) WiFi Link 5100 BGN",
IWL_DEVICE_5000, IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */ .valid_tx_ant = ANT_B, /* .cfg overwrite */
@ -373,14 +352,14 @@ struct iwl_cfg iwl5100_bgn_cfg = {
.ht_params = &iwl5000_ht_params, .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", .name = "Intel(R) WiFi Link 5100 ABG",
IWL_DEVICE_5000, IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */ .valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .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", .name = "Intel(R) WiFi Link 5100 AGN",
IWL_DEVICE_5000, IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */ .valid_tx_ant = ANT_B, /* .cfg overwrite */
@ -388,7 +367,7 @@ struct iwl_cfg iwl5100_agn_cfg = {
.ht_params = &iwl5000_ht_params, .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", .name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
.fw_name_pre = IWL5000_FW_PRE, .fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX, .ucode_api_max = IWL5000_UCODE_API_MAX,
@ -418,14 +397,14 @@ struct iwl_cfg iwl5350_agn_cfg = {
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true .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", .name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
IWL_DEVICE_5150, IWL_DEVICE_5150,
.ht_params = &iwl5000_ht_params, .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", .name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
IWL_DEVICE_5150, IWL_DEVICE_5150,
}; };

View File

@ -96,25 +96,25 @@ static void iwl6150_additional_nic_config(struct iwl_priv *priv)
CSR_GP_DRIVER_REG_BIT_6050_1x2); 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 */ /* NIC configuration for 6000 series */
static void iwl6000_nic_config(struct iwl_priv *priv) static void iwl6000_nic_config(struct iwl_priv *priv)
{ {
iwl_rf_config(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 */ /* do additional nic configuration if needed */
if (cfg(priv)->additional_nic_config) 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, .min_nrg_cck = 110,
.max_nrg_cck = 0, /* not used, set to 0 */
.auto_corr_min_ofdm = 80, .auto_corr_min_ofdm = 80,
.auto_corr_min_ofdm_mrc = 128, .auto_corr_min_ofdm_mrc = 128,
.auto_corr_min_ofdm_x1 = 105, .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) 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) | hw_params(priv).ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
BIT(IEEE80211_BAND_5GHZ); 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) if (cfg(priv)->rx_with_siso_diversity)
hw_params(priv).rx_chains_num = 1; hw_params(priv).rx_chains_num = 1;
else else
hw_params(priv).rx_chains_num = hw_params(priv).rx_chains_num =
num_of_ant(cfg(priv)->valid_rx_ant); num_of_ant(hw_params(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;
iwl6000_set_ct_threshold(priv); iwl6000_set_ct_threshold(priv);
@ -233,7 +225,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
return -EFAULT; return -EFAULT;
} }
return iwl_trans_send_cmd(trans(priv), &hcmd); return iwl_dvm_send_cmd(priv, &hcmd);
} }
static struct iwl_lib_ops iwl6000_lib = { 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_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS EEPROM_REG_BAND_52_HT40_CHANNELS
}, },
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower, .enhanced_txpower = true,
}, },
.temperature = iwlagn_temperature, .temperature = iwlagn_temperature,
}; };
static struct iwl_lib_ops iwl6030_lib = { static struct iwl_lib_ops iwl6030_lib = {
.set_hw_params = iwl6000_hw_set_hw_params, .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, .set_channel_switch = iwl6000_hw_channel_switch,
.nic_config = iwl6000_nic_config, .nic_config = iwl6000_nic_config,
.eeprom_ops = { .eeprom_ops = {
@ -272,12 +261,12 @@ static struct iwl_lib_ops iwl6030_lib = {
EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS EEPROM_REG_BAND_52_HT40_CHANNELS
}, },
.update_enhanced_txpower = iwl_eeprom_enhanced_txpower, .enhanced_txpower = true,
}, },
.temperature = iwlagn_temperature, .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, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_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, .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, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_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, .max_event_log_size = 1024,
.shadow_reg_enable = true, .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, .eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES, .num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_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, .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, .ht_greenfield_support = true,
.use_rts_for_aggregation = true, /* use rts/cts protection */ .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 */ /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.advanced_bt_coexist = true, .advanced_bt_coexist = true,
.agg_time_limit = BT_AGG_THRESHOLD_DEF, .agg_time_limit = BT_AGG_THRESHOLD_DEF,
@ -355,40 +345,41 @@ static struct iwl_bt_params iwl6000_bt_params = {
.need_temp_offset_calib = true, \ .need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE .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", .name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
IWL_DEVICE_6005, IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
IWL_DEVICE_6005, 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", .name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
IWL_DEVICE_6005, 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", .name = "Intel(R) Centrino(R) Advanced-N 6205S AGN",
IWL_DEVICE_6005, IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6205D AGN",
IWL_DEVICE_6005, IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6206 AGN",
IWL_DEVICE_6005, IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6207 AGN",
IWL_DEVICE_6005, IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params, .ht_params = &iwl6000_ht_params,
@ -410,53 +401,53 @@ struct iwl_cfg iwl6005_2agn_mow2_cfg = {
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.adv_pm = true \ .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", .name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
IWL_DEVICE_6030, 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", .name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
IWL_DEVICE_6030, 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", .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
IWL_DEVICE_6030, 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", .name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params, .ht_params = &iwl6000_ht_params,
.rx_with_siso_diversity = true, .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", .name = "Intel(R) Centrino(R) Wireless-N 130 BG",
IWL_DEVICE_6030, IWL_DEVICE_6030,
.rx_with_siso_diversity = true, .rx_with_siso_diversity = true,
@ -477,22 +468,22 @@ struct iwl_cfg iwl130_bg_cfg = {
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \ .eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \ .eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.lib = &iwl6000_lib, \ .lib = &iwl6000_lib, \
.additional_nic_config = iwl6000i_additional_nic_config,\
.base_params = &iwl6000_base_params, \ .base_params = &iwl6000_base_params, \
.pa_type = IWL_PA_INTERNAL, \
.led_mode = IWL_LED_BLINK .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", .name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
IWL_DEVICE_6000i, IWL_DEVICE_6000i,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
IWL_DEVICE_6000i, 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", .name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
IWL_DEVICE_6000i, IWL_DEVICE_6000i,
}; };
@ -513,13 +504,13 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true .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", .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
IWL_DEVICE_6050, IWL_DEVICE_6050,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
IWL_DEVICE_6050, IWL_DEVICE_6050,
}; };
@ -538,18 +529,18 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.led_mode = IWL_LED_BLINK, \ .led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true .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", .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BGN",
IWL_DEVICE_6150, IWL_DEVICE_6150,
.ht_params = &iwl6000_ht_params, .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", .name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
IWL_DEVICE_6150, 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", .name = "Intel(R) Centrino(R) Ultimate-N 6300 AGN",
.fw_name_pre = IWL6000_FW_PRE, .fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX, .ucode_api_max = IWL6000_UCODE_API_MAX,

View File

@ -68,13 +68,19 @@
#include "iwl-agn-calib.h" #include "iwl-agn-calib.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-wifi.h"
#include "iwl-ucode.h"
/***************************************************************************** /*****************************************************************************
* INIT calibrations framework * 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 { struct statistics_general_data {
u32 beacon_silence_rssi_a; u32 beacon_silence_rssi_a;
u32 beacon_silence_rssi_b; u32 beacon_silence_rssi_b;
@ -84,7 +90,7 @@ struct statistics_general_data {
u32 beacon_energy_c; 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 = { struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD, .id = REPLY_PHY_CALIBRATION_CMD,
@ -92,15 +98,15 @@ int iwl_send_calib_results(struct iwl_trans *trans)
}; };
struct iwl_calib_result *res; 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; int ret;
hcmd.len[0] = res->cmd_len; hcmd.len[0] = res->cmd_len;
hcmd.data[0] = &res->hdr; hcmd.data[0] = &res->hdr;
hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY; hcmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
ret = iwl_trans_send_cmd(trans, &hcmd); ret = iwl_dvm_send_cmd(priv, &hcmd);
if (ret) { 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); ret, res->hdr.op_code);
return ret; return ret;
} }
@ -109,7 +115,7 @@ int iwl_send_calib_results(struct iwl_trans *trans)
return 0; 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) const struct iwl_calib_hdr *cmd, int len)
{ {
struct iwl_calib_result *res, *tmp; struct iwl_calib_result *res, *tmp;
@ -121,7 +127,7 @@ int iwl_calib_set(struct iwl_trans *trans,
memcpy(&res->hdr, cmd, len); memcpy(&res->hdr, cmd, len);
res->cmd_len = 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) { if (tmp->hdr.op_code == res->hdr.op_code) {
list_replace(&tmp->list, &res->list); list_replace(&tmp->list, &res->list);
kfree(tmp); kfree(tmp);
@ -130,16 +136,16 @@ int iwl_calib_set(struct iwl_trans *trans,
} }
/* wasn't in list already */ /* wasn't in list already */
list_add_tail(&res->list, &trans->calib_results); list_add_tail(&res->list, &priv->calib_results);
return 0; 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; 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); list_del(&res->list);
kfree(res); kfree(res);
} }
@ -494,7 +500,7 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE); 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 */ /* 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]), &(cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX]),
sizeof(u16)*ENHANCE_HD_TABLE_ENTRIES); 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) 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_bad_plcp_cnt_cck = 0;
data->last_fa_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); ret |= iwl_enhance_sensitivity_write(priv);
else else
ret |= iwl_sensitivity_write(priv); ret |= iwl_sensitivity_write(priv);
@ -655,7 +661,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
struct iwl_sensitivity_data *data = NULL; struct iwl_sensitivity_data *data = NULL;
struct statistics_rx_non_phy *rx_info; struct statistics_rx_non_phy *rx_info;
struct statistics_rx_phy *ofdm, *cck; struct statistics_rx_phy *ofdm, *cck;
unsigned long flags;
struct statistics_general_data statis; struct statistics_general_data statis;
if (priv->disable_sens_cal) if (priv->disable_sens_cal)
@ -668,13 +673,13 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
return; return;
} }
spin_lock_irqsave(&priv->shrd->lock, flags); spin_lock_bh(&priv->statistics.lock);
rx_info = &priv->statistics.rx_non_phy; rx_info = &priv->statistics.rx_non_phy;
ofdm = &priv->statistics.rx_ofdm; ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck; cck = &priv->statistics.rx_cck;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
spin_unlock_irqrestore(&priv->shrd->lock, flags); spin_unlock_bh(&priv->statistics.lock);
return; return;
} }
@ -698,7 +703,7 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv)
statis.beacon_energy_c = statis.beacon_energy_c =
le32_to_cpu(rx_info->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); 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_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); 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); iwl_enhance_sensitivity_write(priv);
else else
iwl_sensitivity_write(priv); 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 * connect the first valid tx chain
*/ */
first_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; data->disconn_array[first_chain] = 0;
active_chains |= BIT(first_chain); active_chains |= BIT(first_chain);
IWL_DEBUG_CALIB(priv, 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, static void iwlagn_gain_computation(struct iwl_priv *priv,
u32 average_noise[NUM_RX_CHAINS], u32 average_noise[NUM_RX_CHAINS],
u16 min_average_noise_antenna_i, u8 default_chain)
u32 min_average_noise,
u8 default_chain)
{ {
int i; int i;
s32 delta_g; s32 delta_g;
@ -925,7 +928,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv,
priv->phy_calib_chain_noise_gain_cmd); priv->phy_calib_chain_noise_gain_cmd);
cmd.delta_gain_1 = data->delta_gain_code[1]; cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2]; 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); CMD_ASYNC, sizeof(cmd), &cmd);
data->radio_write = 1; data->radio_write = 1;
@ -958,7 +961,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
u16 stat_chnum = INITIALIZATION_VALUE; u16 stat_chnum = INITIALIZATION_VALUE;
u8 rxon_band24; u8 rxon_band24;
u8 stat_band24; u8 stat_band24;
unsigned long flags;
struct statistics_rx_non_phy *rx_info; struct statistics_rx_non_phy *rx_info;
/* /*
@ -983,13 +985,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
return; return;
} }
spin_lock_irqsave(&priv->shrd->lock, flags); spin_lock_bh(&priv->statistics.lock);
rx_info = &priv->statistics.rx_non_phy; rx_info = &priv->statistics.rx_non_phy;
if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
spin_unlock_irqrestore(&priv->shrd->lock, flags); spin_unlock_bh(&priv->statistics.lock);
return; return;
} }
@ -1004,7 +1006,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
rxon_chnum, rxon_band24); rxon_chnum, rxon_band24);
spin_unlock_irqrestore(&priv->shrd->lock, flags); spin_unlock_bh(&priv->statistics.lock);
return; 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_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; 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++; data->beacon_count++;
@ -1083,8 +1085,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
min_average_noise, min_average_noise_antenna_i); min_average_noise, min_average_noise_antenna_i);
iwlagn_gain_computation(priv, average_noise, iwlagn_gain_computation(priv, average_noise,
min_average_noise_antenna_i, min_average_noise, find_first_chain(hw_params(priv).valid_rx_ant));
find_first_chain(cfg(priv)->valid_rx_ant));
/* Some power changes may have been made during the calibration. /* Some power changes may have been made during the calibration.
* Update and commit the RXON * Update and commit the RXON

View File

@ -32,7 +32,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include "iwl-wifi.h"
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-io.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; struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
u8 tx_ant_cfg_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")) "TX Power requested while scanning!\n"))
return -EAGAIN; 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.flags = IWLAGN_TX_POWER_NO_CLOSED;
tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO; 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; tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
else else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; 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); sizeof(tx_power_cmd), &tx_power_cmd);
} }
void iwlagn_temperature(struct iwl_priv *priv) void iwlagn_temperature(struct iwl_priv *priv)
{ {
lockdep_assert_held(&priv->statistics.lock);
/* store temperature from correct statistics (in Celsius) */ /* store temperature from correct statistics (in Celsius) */
priv->temperature = le32_to_cpu(priv->statistics.common.temperature); priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
iwl_tt_handler(priv); 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_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
IWL_PAN_SCD_MULTICAST_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; flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n", IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
flush_cmd.fifo_control); flush_cmd.fifo_control);
flush_cmd.flush_control = cpu_to_le16(flush_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) 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); ieee80211_stop_queues(priv->hw);
if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) { if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
IWL_ERR(priv, "flush request fail\n"); 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)); iwl_trans_wait_tx_queue_empty(trans(priv));
done: done:
ieee80211_wake_queues(priv->hw); 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) { if (cfg(priv)->bt_params->bt_session_2) {
memcpy(&bt_cmd_2000.basic, &basic, memcpy(&bt_cmd_2000.basic, &basic,
sizeof(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); CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
} else { } else {
memcpy(&bt_cmd_6000.basic, &basic, memcpy(&bt_cmd_6000.basic, &basic,
sizeof(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); CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
} }
if (ret) 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; struct iwl_rxon_context *ctx, *found_ctx = NULL;
bool found_ap = false; bool found_ap = false;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
/* Check whether AP or GO mode is active. */ /* Check whether AP or GO mode is active. */
if (rssi_ena) { if (rssi_ena) {
@ -565,7 +566,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
break; break;
} }
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
/* /*
* We can not send command to firmware while scanning. When the scan * 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 * STATUS_SCANNING to avoid race when queue_work two times from
* different notifications, but quit and not perform any work at all. * 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; goto out;
iwl_update_chain_flags(priv); 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); iwlagn_bt_coex_rssi_monitor(priv);
out: 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, 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) struct iwl_device_cmd *cmd)
{ {
unsigned long flags;
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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; struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) { 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 */ /* FIXME: based on notification, adjust the prio_boost */
spin_lock_irqsave(&priv->shrd->lock, flags);
priv->bt_ci_compliance = coex->bt_ci_compliance; priv->bt_ci_compliance = coex->bt_ci_compliance;
spin_unlock_irqrestore(&priv->shrd->lock, flags);
return 0; return 0;
} }
@ -971,7 +969,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
u16 p1k[IWLAGN_P1K_SIZE]; u16 p1k[IWLAGN_P1K_SIZE];
int ret, i; int ret, i;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
key->cipher == WLAN_CIPHER_SUITE_WEP104) && key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
@ -1077,7 +1075,7 @@ static void iwlagn_wowlan_program_keys(struct ieee80211_hw *hw,
break; break;
} }
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
} }
int iwlagn_send_patterns(struct iwl_priv *priv, 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; cmd.data[0] = pattern_cmd;
err = iwl_trans_send_cmd(trans(priv), &cmd); err = iwl_dvm_send_cmd(priv, &cmd);
kfree(pattern_cmd); kfree(pattern_cmd);
return err; return err;
} }
int iwlagn_suspend(struct iwl_priv *priv, int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
{ {
struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd; struct iwlagn_wowlan_wakeup_filter_cmd wakeup_filter_cmd;
struct iwl_rxon_cmd rxon; struct iwl_rxon_cmd rxon;
@ -1192,11 +1189,12 @@ int iwlagn_suspend(struct iwl_priv *priv,
memcpy(&rxon, &ctx->active, sizeof(rxon)); memcpy(&rxon, &ctx->active, sizeof(rxon));
priv->ucode_loaded = false;
iwl_trans_stop_device(trans(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) if (ret)
goto out; goto out;
@ -1224,11 +1222,11 @@ int iwlagn_suspend(struct iwl_priv *priv,
* constraints. Since we're in the suspend path * constraints. Since we're in the suspend path
* that isn't really a problem though. * that isn't really a problem though.
*/ */
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
ieee80211_iter_keys(priv->hw, ctx->vif, ieee80211_iter_keys(priv->hw, ctx->vif,
iwlagn_wowlan_program_keys, iwlagn_wowlan_program_keys,
&key_data); &key_data);
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (key_data.error) { if (key_data.error) {
ret = -EIO; ret = -EIO;
goto out; goto out;
@ -1243,13 +1241,13 @@ int iwlagn_suspend(struct iwl_priv *priv,
.len[0] = sizeof(key_data.rsc_tsc), .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) if (ret)
goto out; goto out;
} }
if (key_data.use_tkip) { if (key_data.use_tkip) {
ret = iwl_trans_send_cmd_pdu(trans(priv), ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_WOWLAN_TKIP_PARAMS, REPLY_WOWLAN_TKIP_PARAMS,
CMD_SYNC, sizeof(tkip_cmd), CMD_SYNC, sizeof(tkip_cmd),
&tkip_cmd); &tkip_cmd);
@ -1265,7 +1263,7 @@ int iwlagn_suspend(struct iwl_priv *priv,
kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN); kek_kck_cmd.kek_len = cpu_to_le16(NL80211_KEK_LEN);
kek_kck_cmd.replay_ctr = priv->replay_ctr; 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, REPLY_WOWLAN_KEK_KCK_MATERIAL,
CMD_SYNC, sizeof(kek_kck_cmd), CMD_SYNC, sizeof(kek_kck_cmd),
&kek_kck_cmd); &kek_kck_cmd);
@ -1274,12 +1272,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); sizeof(d3_cfg_cmd), &d3_cfg_cmd);
if (ret) if (ret)
goto out; 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), CMD_SYNC, sizeof(wakeup_filter_cmd),
&wakeup_filter_cmd); &wakeup_filter_cmd);
if (ret) if (ret)
@ -1291,3 +1289,41 @@ int iwlagn_suspend(struct iwl_priv *priv,
return ret; return ret;
} }
#endif #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);
}

View File

@ -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; struct iwl_scale_tbl_info *tbl;
bool full_concurrent = priv->bt_full_concurrent; bool full_concurrent = priv->bt_full_concurrent;
unsigned long flags;
if (priv->bt_ant_couple_ok) { if (priv->bt_ant_couple_ok) {
/* /*
* Is there a need to switch between * Is there a need to switch between
* full concurrency and 3-wire? * full concurrency and 3-wire?
*/ */
spin_lock_irqsave(&priv->shrd->lock, flags);
if (priv->bt_ci_compliance && priv->bt_ant_couple_ok) if (priv->bt_ci_compliance && priv->bt_ant_couple_ok)
full_concurrent = true; full_concurrent = true;
else else
full_concurrent = false; full_concurrent = false;
spin_unlock_irqrestore(&priv->shrd->lock, flags);
} }
if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || if ((priv->bt_traffic_load != priv->last_bt_traffic_load) ||
(priv->bt_full_concurrent != full_concurrent)) { (priv->bt_full_concurrent != full_concurrent)) {
@ -2680,7 +2677,6 @@ out:
* which requires station table entry to exist). * which requires station table entry to exist).
*/ */
static void rs_initialize_lq(struct iwl_priv *priv, static void rs_initialize_lq(struct iwl_priv *priv,
struct ieee80211_conf *conf,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_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; lq_sta->dbg_fixed_rate = 0;
#endif #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, static void rs_fill_link_cmd(struct iwl_priv *priv,

View File

@ -131,26 +131,27 @@ const char *get_cmd_string(u8 cmd)
******************************************************************************/ ******************************************************************************/
static int iwlagn_rx_reply_error(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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) " IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n", "seq 0x%04X ser 0x%08X\n",
le32_to_cpu(pkt->u.err_resp.error_type), le32_to_cpu(err_resp->error_type),
get_cmd_string(pkt->u.err_resp.cmd_id), get_cmd_string(err_resp->cmd_id),
pkt->u.err_resp.cmd_id, err_resp->cmd_id,
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), le16_to_cpu(err_resp->bad_cmd_seq_num),
le32_to_cpu(pkt->u.err_resp.error_info)); le32_to_cpu(err_resp->error_info));
return 0; 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 * MULTI-FIXME
* See iwlagn_mac_channel_switch. * 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_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_rxon_cmd *rxon = (void *)&ctx->active; 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; return 0;
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) { 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, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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) { if (!report->state) {
IWL_DEBUG_11H(priv, 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, 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) struct iwl_device_cmd *cmd)
{ {
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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", IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src); sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif #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, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 " IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
"notification for %s:\n", len, "notification for %s:\n", len,
get_cmd_string(pkt->hdr.cmd)); 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; return 0;
} }
static int iwlagn_rx_beacon_notif(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 #ifdef CONFIG_IWLWIFI_DEBUG
u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status); u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); 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) if (priv->agg_tids_count)
return true; return true;
lockdep_assert_held(&priv->statistics.lock);
old = &priv->statistics.tx; old = &priv->statistics.tx;
actual_delta = le32_to_cpu(cur->actual_ack_cnt) - 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) unsigned int msecs)
{ {
int delta; 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) { if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n"); 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; unsigned int msecs;
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies); msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
@ -487,7 +490,7 @@ iwlagn_accumulative_statistics(struct iwl_priv *priv,
#endif #endif
static int iwlagn_rx_statistics(struct iwl_priv *priv, 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) struct iwl_device_cmd *cmd)
{ {
unsigned long stamp = jiffies; 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", IWL_DEBUG_RX(priv, "Statistics notification received (%d bytes).\n",
len); len);
spin_lock(&priv->statistics.lock);
if (len == sizeof(struct iwl_bt_notif_statistics)) { if (len == sizeof(struct iwl_bt_notif_statistics)) {
struct iwl_bt_notif_statistics *stats; struct iwl_bt_notif_statistics *stats;
stats = &pkt->u.stats_bt; stats = (void *)&pkt->data;
flag = &stats->flag; flag = &stats->flag;
common = &stats->general.common; common = &stats->general.common;
rx_non_phy = &stats->rx.general.common; rx_non_phy = &stats->rx.general.common;
@ -529,7 +534,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
#endif #endif
} else if (len == sizeof(struct iwl_notif_statistics)) { } else if (len == sizeof(struct iwl_notif_statistics)) {
struct iwl_notif_statistics *stats; struct iwl_notif_statistics *stats;
stats = &pkt->u.stats; stats = (void *)&pkt->data;
flag = &stats->flag; flag = &stats->flag;
common = &stats->general.common; common = &stats->general.common;
rx_non_phy = &stats->rx.general; 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", WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
len, sizeof(struct iwl_bt_notif_statistics), len, sizeof(struct iwl_bt_notif_statistics),
sizeof(struct iwl_notif_statistics)); sizeof(struct iwl_notif_statistics));
spin_unlock(&priv->statistics.lock);
return 0; return 0;
} }
@ -569,7 +575,7 @@ static int iwlagn_rx_statistics(struct iwl_priv *priv,
priv->rx_statistics_jiffies = stamp; 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 /* Reschedule the statistics timer to occur in
* reg_recalib_period seconds to ensure we get a * 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 + mod_timer(&priv->statistics_periodic, jiffies +
msecs_to_jiffies(reg_recalib_period * 1000)); 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)) { (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwlagn_rx_calc_noise(priv); iwlagn_rx_calc_noise(priv);
queue_work(priv->workqueue, &priv->run_time_calib_work); queue_work(priv->workqueue, &priv->run_time_calib_work);
} }
if (cfg(priv)->lib->temperature && change) if (cfg(priv)->lib->temperature && change)
cfg(priv)->lib->temperature(priv); cfg(priv)->lib->temperature(priv);
spin_unlock(&priv->statistics.lock);
return 0; return 0;
} }
static int iwlagn_rx_reply_statistics(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 #ifdef CONFIG_IWLWIFI_DEBUGFS
memset(&priv->accum_stats, 0, memset(&priv->accum_stats, 0,
sizeof(priv->accum_stats)); 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 /* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */ * due to software, hardware, or critical temperature RFKILL */
static int iwlagn_rx_card_state_notif(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); struct iwl_card_state_notif *card_state_notif = (void *)pkt->data;
unsigned long status = priv->shrd->status; 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", IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
(flags & HW_CARD_DISABLED) ? "Kill" : "On", (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); iwl_tt_exit_ct_kill(priv);
if (flags & HW_CARD_DISABLED) if (flags & HW_CARD_DISABLED)
set_bit(STATUS_RF_KILL_HW, &priv->shrd->status); set_bit(STATUS_RF_KILL_HW, &priv->status);
else else
clear_bit(STATUS_RF_KILL_HW, &priv->shrd->status); clear_bit(STATUS_RF_KILL_HW, &priv->status);
if (!(flags & RXON_CARD_DISABLED)) if (!(flags & RXON_CARD_DISABLED))
iwl_scan_cancel(priv); iwl_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) != 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, 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 else
wake_up(&priv->shrd->wait_command_queue); wake_up(&trans(priv)->wait_command_queue);
return 0; return 0;
} }
static int iwlagn_rx_missed_beacon_notif(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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) > if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
priv->missed_beacon_threshold) { priv->missed_beacon_threshold) {
IWL_DEBUG_CALIB(priv, 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->total_missed_becons),
le32_to_cpu(missed_beacon->num_recvd_beacons), le32_to_cpu(missed_beacon->num_recvd_beacons),
le32_to_cpu(missed_beacon->num_expected_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); iwl_init_sensitivity(priv);
} }
return 0; 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). /* 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. */ * 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, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
priv->last_phy_res_valid = true; 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)); sizeof(struct iwl_rx_phy_res));
return 0; return 0;
} }
@ -757,12 +767,14 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
struct ieee80211_hdr *hdr, struct ieee80211_hdr *hdr,
u16 len, u16 len,
u32 ampdu_status, u32 ampdu_status,
struct iwl_rx_mem_buffer *rxb, struct iwl_rx_cmd_buffer *rxb,
struct ieee80211_rx_status *stats) struct ieee80211_rx_status *stats)
{ {
struct sk_buff *skb; struct sk_buff *skb;
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
struct page *p;
int offset;
/* We only process data packets if the interface is open */ /* We only process data packets if the interface is open */
if (unlikely(!priv->is_open)) { if (unlikely(!priv->is_open)) {
@ -782,7 +794,9 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
return; 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); 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 * sometimes even after already having transmitted frames for the
* association because the new RXON may reset the information. * 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) { for_each_context(priv, ctx) {
if (!ctx->last_tx_rejected)
continue;
if (compare_ether_addr(hdr->addr3, if (compare_ether_addr(hdr->addr3,
ctx->active.bssid_addr)) ctx->active.bssid_addr))
continue; continue;
ctx->last_tx_rejected = false; iwlagn_lift_passive_no_rx(priv);
iwl_trans_wake_any_queue(trans(priv), ctx->ctxid,
"channel got active");
} }
} }
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
ieee80211_rx(priv->hw, skb); ieee80211_rx(priv->hw, skb);
rxb->page = NULL;
} }
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) 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 /* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
static int iwlagn_rx_reply_rx(struct iwl_priv *priv, 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 iwl_device_cmd *cmd)
{ {
struct ieee80211_hdr *header; struct ieee80211_hdr *header;
@ -938,12 +947,12 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
* received. * received.
*/ */
if (pkt->hdr.cmd == REPLY_RX) { if (pkt->hdr.cmd == REPLY_RX) {
phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; phy_res = (struct iwl_rx_phy_res *)pkt->data;
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res)
+ phy_res->cfg_phy_cnt); + phy_res->cfg_phy_cnt);
len = le16_to_cpu(phy_res->byte_count); 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); phy_res->cfg_phy_cnt + len);
ampdu_status = le32_to_cpu(rx_pkt_status); ampdu_status = le32_to_cpu(rx_pkt_status);
} else { } else {
@ -952,10 +961,10 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
return 0; return 0;
} }
phy_res = &priv->last_phy_res; phy_res = &priv->last_phy_res;
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw; amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
len = le16_to_cpu(amsdu->byte_count); 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, ampdu_status = iwlagn_translate_rx_status(priv,
le32_to_cpu(rx_pkt_status)); 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, 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_device_cmd *cmd)
{ {
struct iwl_wipan_noa_data *new_data, *old_data; struct iwl_wipan_noa_data *new_data, *old_data;
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 */ /* no condition -- we're in softirq */
old_data = rcu_dereference_protected(priv->noa_data, true); 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) 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); struct iwl_device_cmd *cmd);
handlers = priv->rx_handlers; 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; priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
/* set up notification wait support */ /* set up notification wait support */
spin_lock_init(&priv->shrd->notif_wait_lock); iwl_notification_wait_init(&priv->notif_wait);
INIT_LIST_HEAD(&priv->shrd->notif_waits);
init_waitqueue_head(&priv->shrd->notif_waitq);
/* Set up BT Rx handlers */ /* Set up BT Rx handlers */
if (cfg(priv)->lib->bt_rx_handler_setup) if (cfg(priv)->bt_params)
cfg(priv)->lib->bt_rx_handler_setup(priv); iwlagn_bt_rx_handler_setup(priv);
} }
int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_mem_buffer *rxb, int iwl_rx_dispatch(struct iwl_op_mode *op_mode, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd) struct iwl_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode); 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; 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 * even if the RX handler consumes the RXB we have
* access to it in the notification wait entry. * access to it in the notification wait entry.
*/ */
if (!list_empty(&priv->shrd->notif_waits)) { iwl_notification_wait_notify(&priv->notif_wait, pkt);
struct iwl_notification_wait *w;
spin_lock(&priv->shrd->notif_wait_lock); /* RX data may be forwarded to userspace (using pre_rx_handler) in one
list_for_each_entry(w, &priv->shrd->notif_waits, list) { * of two cases: the first, that the user owns the uCode through
if (w->cmd != pkt->hdr.cmd) * testmode - in such case the pre_rx_handler is set and no further
continue; * processing takes place. The other case is when the user want to
IWL_DEBUG_RX(priv, * monitor the rx w/o affecting the regular flow - the pre_rx_handler
"Notif: %s, 0x%02x - wake the callers up\n", * will be set but the ownership flag != IWL_OWNERSHIP_TM and the flow
get_cmd_string(pkt->hdr.cmd), * continues.
pkt->hdr.cmd); * We need to use ACCESS_ONCE to prevent a case where the handler
w->triggered = true; * changes between the check and the call.
if (w->fn) */
w->fn(trans(priv), pkt, w->fn_data); pre_rx_handler = ACCESS_ONCE(priv->pre_rx_handler);
} if (pre_rx_handler)
spin_unlock(&priv->shrd->notif_wait_lock); pre_rx_handler(priv, rxb);
if (priv->ucode_owner != IWL_OWNERSHIP_TM) {
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 {
/* Based on type of command response or notification, /* Based on type of command response or notification,
* handle those that need handling via function in * handle those that need handling via function in
* rx_handlers table. See iwl_setup_rx_handlers() */ * rx_handlers table. See iwl_setup_rx_handlers() */

View File

@ -39,7 +39,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
int ret; int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; 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); CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter; 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; u8 old_dev_type = send->dev_type;
int ret; int ret;
iwl_init_notification_wait(priv->shrd, &disable_wait, iwl_init_notification_wait(&priv->notif_wait, &disable_wait,
REPLY_WIPAN_DEACTIVATION_COMPLETE, REPLY_WIPAN_DEACTIVATION_COMPLETE,
NULL, NULL); NULL, NULL);
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P; 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); CMD_SYNC, sizeof(*send), send);
send->filter_flags = old_filter; send->filter_flags = old_filter;
@ -74,9 +74,10 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
if (ret) { if (ret) {
IWL_ERR(priv, "Error disabling PAN (%d)\n", 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 { } else {
ret = iwl_wait_notification(priv->shrd, &disable_wait, HZ); ret = iwl_wait_notification(&priv->notif_wait,
&disable_wait, HZ);
if (ret) if (ret)
IWL_ERR(priv, "Timed out waiting for PAN disable\n"); 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; int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK; 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); sizeof(*send), send);
send->filter_flags = old_filter; 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.qos_active,
ctx->qos_data.def_qos_parm.qos_flags); 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), sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm); &ctx->qos_data.def_qos_parm);
if (ret) if (ret)
@ -131,7 +132,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
static int iwlagn_update_beacon(struct iwl_priv *priv, static int iwlagn_update_beacon(struct iwl_priv *priv,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
dev_kfree_skb(priv->beacon_skb); dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif); 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; ctx->staging.ofdm_ht_triple_stream_basic_rates;
rxon_assoc.acquisition_data = ctx->staging.acquisition_data; 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); CMD_ASYNC, sizeof(rxon_assoc), &rxon_assoc);
return ret; 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, * Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this. * 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); sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) { if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", 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)); memcpy(active, &ctx->staging, sizeof(*active));
iwl_reprogram_ap_sta(priv, ctx);
/* IBSS beacon needs to be sent after setting assoc */ /* IBSS beacon needs to be sent after setting assoc */
if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC)) if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
if (iwlagn_update_beacon(priv, ctx->vif)) 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); 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_bss = &priv->contexts[IWL_RXON_CTX_BSS];
ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN]; ctx_pan = &priv->contexts[IWL_RXON_CTX_PAN];
@ -362,7 +361,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
slot0 = bcnint / 2; slot0 = bcnint / 2;
slot1 = bcnint - slot0; 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.idle &&
!ctx_bss->vif->bss_conf.assoc)) { !ctx_bss->vif->bss_conf.assoc)) {
slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME; 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; ctx_pan->beacon_int;
slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1); 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; slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
slot1 = 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[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1); 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); sizeof(cmd), &cmd);
if (ret) if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", 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); bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
int ret; int ret;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) if (!iwl_is_alive(priv))
return -EINVAL;
if (!iwl_is_alive(priv->shrd))
return -EBUSY; return -EBUSY;
/* This function hardcodes a bunch of dual-mode assumptions */ /* 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) if (!ctx->is_active)
return 0; 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 */ /* always get timestamp with Rx frame */
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; 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 * force CTS-to-self frames protection if RTS-CTS is not preferred
* one aggregation protection method * one aggregation protection method
*/ */
if (!(cfg(priv)->ht_params && if (!hw_params(priv).use_rts_for_aggregation)
cfg(priv)->ht_params->use_rts_for_aggregation))
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN; ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) || 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 * receive commit_rxon request
* abort any previous channel switch if still in process * 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)) { (priv->switch_channel != ctx->staging.channel)) {
IWL_DEBUG_11H(priv, "abort channel switch on %d\n", IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
le16_to_cpu(priv->switch_channel)); 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); 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)) if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
goto out;
if (unlikely(test_bit(STATUS_SCANNING, &priv->shrd->status))) {
IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
goto out; goto out;
} }
if (!iwl_is_ready(priv->shrd)) { if (!iwl_is_ready(priv)) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
goto out; goto out;
} }
@ -590,8 +578,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
} }
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
unsigned long flags;
ch_info = iwl_get_channel_info(priv, channel->band, ch_info = iwl_get_channel_info(priv, channel->band,
channel->hw_value); channel->hw_value);
if (!is_channel_valid(ch_info)) { if (!is_channel_valid(ch_info)) {
@ -600,8 +586,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
goto out; goto out;
} }
spin_lock_irqsave(&priv->shrd->lock, flags);
for_each_context(priv, ctx) { for_each_context(priv, ctx) {
/* Configure HT40 channels */ /* Configure HT40 channels */
if (ctx->ht.enabled != conf_is_ht(conf)) if (ctx->ht.enabled != conf_is_ht(conf))
@ -636,8 +620,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
ctx->vif); ctx->vif);
} }
spin_unlock_irqrestore(&priv->shrd->lock, flags);
iwl_update_bcast_stations(priv); iwl_update_bcast_stations(priv);
/* /*
@ -668,7 +650,7 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
iwlagn_commit_rxon(priv, ctx); iwlagn_commit_rxon(priv, ctx);
} }
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return ret; return ret;
@ -685,7 +667,7 @@ static void iwlagn_check_needed_chains(struct iwl_priv *priv,
struct ieee80211_sta_ht_cap *ht_cap; struct ieee80211_sta_ht_cap *ht_cap;
bool need_multiple; bool need_multiple;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
@ -789,7 +771,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
iwl_set_calib_hdr(&cmd.hdr, iwl_set_calib_hdr(&cmd.hdr,
priv->phy_calib_chain_noise_reset_cmd); 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, REPLY_PHY_CALIBRATION_CMD,
CMD_SYNC, sizeof(cmd), &cmd); CMD_SYNC, sizeof(cmd), &cmd);
if (ret) if (ret)
@ -810,17 +792,17 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
int ret; int ret;
bool force = false; 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"); IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
return; return;
} }
if (unlikely(!ctx->vif)) { if (unlikely(!ctx->vif)) {
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n"); IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
return; return;
} }
@ -840,7 +822,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_ASSOC) { if (changes & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) { if (bss_conf->assoc) {
priv->timestamp = bss_conf->timestamp; priv->timestamp = bss_conf->last_tsf;
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
} else { } else {
/* /*
@ -851,12 +833,8 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
* not get stuck in this case either since it * not get stuck in this case either since it
* can happen if userspace gets confused. * can happen if userspace gets confused.
*/ */
if (ctx->last_tx_rejected) { iwlagn_lift_passive_no_rx(priv);
ctx->last_tx_rejected = false;
iwl_trans_wake_any_queue(trans(priv),
ctx->ctxid,
"Disassoc: flush queue");
}
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
if (ctx->ctxid == IWL_RXON_CTX_BSS) 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) if (!priv->disable_chain_noise_cal)
iwlagn_chain_noise_reset(priv); iwlagn_chain_noise_reset(priv);
priv->start_calib = 1; priv->start_calib = 1;
WARN_ON(ctx->preauth_bssid);
} }
if (changes & BSS_CHANGED_IBSS) { 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"); 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) void iwlagn_post_scan(struct iwl_priv *priv)

View File

@ -26,7 +26,7 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/
#include <linux/etherdevice.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "iwl-dev.h" #include "iwl-dev.h"
@ -34,9 +34,10 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-trans.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) 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) { if (sta_id >= IWLAGN_STATION_COUNT) {
IWL_ERR(priv, "invalid sta_id %u", sta_id); IWL_ERR(priv, "invalid sta_id %u", sta_id);
return -EINVAL; return -EINVAL;
@ -63,8 +64,8 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
struct iwl_addsta_cmd *addsta, struct iwl_addsta_cmd *addsta,
struct iwl_rx_packet *pkt) struct iwl_rx_packet *pkt)
{ {
struct iwl_add_sta_resp *add_sta_resp = (void *)pkt->data;
u8 sta_id = addsta->sta.sta_id; u8 sta_id = addsta->sta.sta_id;
unsigned long flags;
int ret = -EIO; int ret = -EIO;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { 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", IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
sta_id); 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: case ADD_STA_SUCCESS_MSK:
IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
ret = iwl_sta_ucode_activate(priv, sta_id); ret = iwl_sta_ucode_activate(priv, sta_id);
@ -97,7 +98,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
break; break;
default: default:
IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
pkt->u.add_sta.status); add_sta_resp->status);
break; break;
} }
@ -118,12 +119,12 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode == priv->stations[sta_id].sta.mode ==
STA_CONTROL_MODIFY_MSK ? "Modified" : "Added", STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
addsta->sta.addr); addsta->sta.addr);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock(&priv->sta_lock);
return ret; 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
@ -153,14 +154,14 @@ int iwl_send_add_sta(struct iwl_priv *priv,
might_sleep(); might_sleep();
} }
ret = iwl_trans_send_cmd(trans(priv), &cmd); ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret || (flags & CMD_ASYNC)) if (ret || (flags & CMD_ASYNC))
return ret; return ret;
/*else the command was successfully sent in SYNC mode, need to free /*else the command was successfully sent in SYNC mode, need to free
* the reply page */ * the reply page */
iwl_free_pages(priv->shrd, cmd.reply_page); iwl_free_resp(&cmd);
if (cmd.handler_status) if (cmd.handler_status)
IWL_ERR(priv, "%s - error in the CMD response %d", __func__, 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; return cmd.handler_status;
} }
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, static void iwl_sta_calc_ht_flags(struct iwl_priv *priv,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct iwl_rxon_context *ctx) struct iwl_rxon_context *ctx,
__le32 *flags, __le32 *mask)
{ {
struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap; struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
__le32 sta_flags;
u8 mimo_ps_mode; 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) if (!sta || !sta_ht_inf->ht_supported)
goto done; return;
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; 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) ? (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
"static" : "static" :
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
"dynamic" : "disabled"); "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) { switch (mimo_ps_mode) {
case WLAN_HT_CAP_SM_PS_STATIC: case WLAN_HT_CAP_SM_PS_STATIC:
sta_flags |= STA_FLG_MIMO_DIS_MSK; *flags |= STA_FLG_MIMO_DIS_MSK;
break; break;
case WLAN_HT_CAP_SM_PS_DYNAMIC: case WLAN_HT_CAP_SM_PS_DYNAMIC:
sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; *flags |= STA_FLG_RTS_MIMO_PROT_MSK;
break; break;
case WLAN_HT_CAP_SM_PS_DISABLED: case WLAN_HT_CAP_SM_PS_DISABLED:
break; break;
@ -205,20 +210,53 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
break; break;
} }
sta_flags |= cpu_to_le32( *flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS); (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
sta_flags |= cpu_to_le32( *flags |= cpu_to_le32(
(u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap)) if (iwl_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
sta_flags |= STA_FLG_HT40_EN_MSK; *flags |= STA_FLG_HT40_EN_MSK;
else }
sta_flags &= ~STA_FLG_HT40_EN_MSK;
priv->stations[index].sta.station_flags = sta_flags; int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
done: struct ieee80211_sta *sta)
return; {
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, const u8 *addr, bool is_ap,
struct ieee80211_sta *sta, u8 *sta_id_r) struct ieee80211_sta *sta, u8 *sta_id_r)
{ {
unsigned long flags_spin;
int ret = 0; int ret = 0;
u8 sta_id; u8 sta_id;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
*sta_id_r = 0; *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); sta_id = iwl_prep_station(priv, ctx, addr, is_ap, sta);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare station %pM for addition\n", IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
addr); addr);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); spin_unlock_bh(&priv->sta_lock);
return -EINVAL; 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) { if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
IWL_DEBUG_INFO(priv, "STA %d already in process of being " IWL_DEBUG_INFO(priv, "STA %d already in process of being "
"added.\n", sta_id); "added.\n", sta_id);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); spin_unlock_bh(&priv->sta_lock);
return -EEXIST; 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)) { (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not " IWL_DEBUG_ASSOC(priv, "STA %d (%pM) already added, not "
"adding again.\n", sta_id, addr); "adding again.\n", sta_id, addr);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); spin_unlock_bh(&priv->sta_lock);
return -EEXIST; return -EEXIST;
} }
priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS; priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, memcpy(&sta_cmd, &priv->stations[sta_id].sta,
sizeof(struct iwl_addsta_cmd)); 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 */ /* Add station to device's station table */
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) { 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", IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[sta_id].sta.sta.addr); priv->stations[sta_id].sta.sta.addr);
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; 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; *sta_id_r = sta_id;
return ret; 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 * 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) 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 */ /* Ucode must be active and driver must be non active */
if ((priv->stations[sta_id].used & if ((priv->stations[sta_id].used &
(IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != (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; struct iwl_rx_packet *pkt;
int ret; int ret;
unsigned long flags_spin;
struct iwl_rem_sta_cmd rm_sta_cmd; struct iwl_rem_sta_cmd rm_sta_cmd;
struct iwl_host_cmd 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; cmd.flags |= CMD_WANT_SKB;
ret = iwl_trans_send_cmd(trans(priv), &cmd); ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret) if (ret)
return ret; return ret;
pkt = (struct iwl_rx_packet *)cmd.reply_page; pkt = cmd.resp_pkt;
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
pkt->hdr.flags); pkt->hdr.flags);
@ -426,14 +461,13 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
} }
if (!ret) { 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: case REM_STA_SUCCESS_MSK:
if (!temporary) { if (!temporary) {
spin_lock_irqsave(&priv->shrd->sta_lock, spin_lock_bh(&priv->sta_lock);
flags_spin);
iwl_sta_ucode_deactivate(priv, sta_id); iwl_sta_ucode_deactivate(priv, sta_id);
spin_unlock_irqrestore(&priv->shrd->sta_lock, spin_unlock_bh(&priv->sta_lock);
flags_spin);
} }
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
break; break;
@ -443,7 +477,7 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
break; break;
} }
} }
iwl_free_pages(priv->shrd, cmd.reply_page); iwl_free_resp(&cmd);
return ret; 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, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr) const u8 *addr)
{ {
unsigned long flags;
u8 tid; u8 tid;
if (!iwl_is_ready(priv->shrd)) { if (!iwl_is_ready(priv)) {
IWL_DEBUG_INFO(priv, IWL_DEBUG_INFO(priv,
"Unable to remove station %pM, device not ready.\n", "Unable to remove station %pM, device not ready.\n",
addr); 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)) if (WARN_ON(sta_id == IWL_INVALID_STATION))
return -EINVAL; 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)) { if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", 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)) if (WARN_ON(priv->num_stations < 0))
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); return iwl_send_remove_station(priv, addr, sta_id, false);
out_err: out_err:
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return -EINVAL; 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 * 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) struct iwl_rxon_context *ctx)
{ {
int i; int i;
unsigned long flags_spin;
bool cleared = false; bool cleared = false;
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); 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++) { for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (ctx && ctx->ctxid != priv->stations[i].ctxid) if (ctx && ctx->ctxid != priv->stations[i].ctxid)
continue; continue;
@ -542,7 +609,7 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv,
cleared = true; cleared = true;
} }
} }
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); spin_unlock_bh(&priv->sta_lock);
if (!cleared) if (!cleared)
IWL_DEBUG_INFO(priv, 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_addsta_cmd sta_cmd;
struct iwl_link_quality_cmd lq; struct iwl_link_quality_cmd lq;
unsigned long flags_spin;
int i; int i;
bool found = false; bool found = false;
int ret; int ret;
bool send_lq; bool send_lq;
if (!iwl_is_ready(priv->shrd)) { if (!iwl_is_ready(priv)) {
IWL_DEBUG_INFO(priv, IWL_DEBUG_INFO(priv,
"Not ready yet, not restoring any stations.\n"); "Not ready yet, not restoring any stations.\n");
return; return;
} }
IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n"); 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++) { for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (ctx->ctxid != priv->stations[i].ctxid) if (ctx->ctxid != priv->stations[i].ctxid)
continue; continue;
@ -594,27 +660,24 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
sizeof(struct iwl_addsta_cmd)); sizeof(struct iwl_addsta_cmd));
send_lq = false; send_lq = false;
if (priv->stations[i].lq) { if (priv->stations[i].lq) {
if (priv->shrd->wowlan) if (priv->wowlan)
iwl_sta_fill_lq(priv, ctx, i, &lq); iwl_sta_fill_lq(priv, ctx, i, &lq);
else else
memcpy(&lq, priv->stations[i].lq, memcpy(&lq, priv->stations[i].lq,
sizeof(struct iwl_link_quality_cmd)); sizeof(struct iwl_link_quality_cmd));
send_lq = true; send_lq = true;
} }
spin_unlock_irqrestore(&priv->shrd->sta_lock, spin_unlock_bh(&priv->sta_lock);
flags_spin);
ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
if (ret) { if (ret) {
spin_lock_irqsave(&priv->shrd->sta_lock, spin_lock_bh(&priv->sta_lock);
flags_spin);
IWL_ERR(priv, "Adding station %pM failed.\n", IWL_ERR(priv, "Adding station %pM failed.\n",
priv->stations[i].sta.sta.addr); priv->stations[i].sta.sta.addr);
priv->stations[i].used &= priv->stations[i].used &=
~IWL_STA_DRIVER_ACTIVE; ~IWL_STA_DRIVER_ACTIVE;
priv->stations[i].used &= priv->stations[i].used &=
~IWL_STA_UCODE_INPROGRESS; ~IWL_STA_UCODE_INPROGRESS;
spin_unlock_irqrestore(&priv->shrd->sta_lock, spin_unlock_bh(&priv->sta_lock);
flags_spin);
} }
/* /*
* Rate scaling has already been initialized, send * 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) if (send_lq)
iwl_send_lq_cmd(priv, ctx, &lq, iwl_send_lq_cmd(priv, ctx, &lq,
CMD_SYNC, true); 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; 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) if (!found)
IWL_DEBUG_INFO(priv, "Restoring all known stations .... " IWL_DEBUG_INFO(priv, "Restoring all known stations .... "
"no stations to be restored.\n"); "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"); "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 iwl_get_free_ucode_key_offset(struct iwl_priv *priv)
{ {
int i; 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) void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
{ {
unsigned long flags;
int i; int i;
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock_bh(&priv->sta_lock);
for (i = 0; i < IWLAGN_STATION_COUNT; i++) { for (i = 0; i < IWLAGN_STATION_COUNT; i++) {
if (!(priv->stations[i].used & IWL_STA_BCAST)) if (!(priv->stations[i].used & IWL_STA_BCAST))
continue; continue;
@ -711,7 +727,7 @@ void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
kfree(priv->stations[i].lq); kfree(priv->stations[i].lq);
priv->stations[i].lq = NULL; priv->stations[i].lq = NULL;
} }
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
} }
#ifdef CONFIG_IWLWIFI_DEBUG #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) struct iwl_link_quality_cmd *lq, u8 flags, bool init)
{ {
int ret = 0; int ret = 0;
unsigned long flags_spin;
struct iwl_host_cmd cmd = { struct iwl_host_cmd cmd = {
.id = REPLY_TX_LINK_QUALITY_CMD, .id = REPLY_TX_LINK_QUALITY_CMD,
.len = { sizeof(struct iwl_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; 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)) { 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; return -EINVAL;
} }
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags_spin); spin_unlock_bh(&priv->sta_lock);
iwl_dump_lq_cmd(priv, lq); iwl_dump_lq_cmd(priv, lq);
if (WARN_ON(init && (cmd.flags & CMD_ASYNC))) if (WARN_ON(init && (cmd.flags & CMD_ASYNC)))
return -EINVAL; return -EINVAL;
if (is_lq_table_valid(priv, ctx, lq)) if (is_lq_table_valid(priv, ctx, lq))
ret = iwl_trans_send_cmd(trans(priv), &cmd); ret = iwl_dvm_send_cmd(priv, &cmd);
else else
ret = -EINVAL; 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, " IWL_DEBUG_INFO(priv, "init LQ command complete, "
"clearing sta addition status for sta %d\n", "clearing sta addition status for sta %d\n",
lq->sta_id); 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; 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; return ret;
} }
@ -834,7 +848,7 @@ void iwl_sta_fill_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
u32 rate_flags = 0; u32 rate_flags = 0;
__le32 rate_n_flags; __le32 rate_n_flags;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
memset(link_cmd, 0, sizeof(*link_cmd)); memset(link_cmd, 0, sizeof(*link_cmd));
@ -906,7 +920,6 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
int ret; int ret;
u8 sta_id; u8 sta_id;
struct iwl_link_quality_cmd *link_cmd; struct iwl_link_quality_cmd *link_cmd;
unsigned long flags;
if (sta_id_r) if (sta_id_r)
*sta_id_r = IWL_INVALID_STATION; *sta_id_r = IWL_INVALID_STATION;
@ -920,9 +933,9 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
if (sta_id_r) if (sta_id_r)
*sta_id_r = sta_id; *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; 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 */ /* Set up default rate scaling table in device's station table */
link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id); 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) if (ret)
IWL_ERR(priv, "Link quality command failed (%d)\n", 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; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return 0; return 0;
} }
@ -994,7 +1007,7 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
cmd.len[0] = cmd_size; cmd.len[0] = cmd_size;
if (not_empty || send_if_empty) if (not_empty || send_if_empty)
return iwl_trans_send_cmd(trans(priv), &cmd); return iwl_dvm_send_cmd(priv, &cmd);
else else
return 0; 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, int iwl_restore_default_wep_keys(struct iwl_priv *priv,
struct iwl_rxon_context *ctx) 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); 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; int ret;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
keyconf->keyidx); keyconf->keyidx);
memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); 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, IWL_DEBUG_WEP(priv,
"Not sending REPLY_WEPKEY command due to RFKILL.\n"); "Not sending REPLY_WEPKEY command due to RFKILL.\n");
/* but keys in device are clear anyway so return success */ /* 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; int ret;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
if (keyconf->keylen != WEP_KEY_LEN_128 && if (keyconf->keylen != WEP_KEY_LEN_128 &&
keyconf->keylen != WEP_KEY_LEN_64) { 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 ieee80211_sta *sta)
{ {
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
u8 sta_id = IWL_INVALID_STATION;
if (sta) if (sta)
sta_id = iwl_sta_id(sta); return iwl_sta_id(sta);
/* /*
* The device expects GTKs for station interfaces to be * The device expects GTKs for station interfaces to be
* installed as GTKs for the AP station. If we have no * installed as GTKs for the AP station. If we have no
* station ID, then use the ap_sta_id in that case. * station ID, then use the ap_sta_id in that case.
*/ */
if (!sta && vif && vif_priv->ctx) { if (vif->type == NL80211_IFTYPE_STATION && vif_priv->ctx)
switch (vif->type) { return vif_priv->ctx->ap_sta_id;
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;
}
}
return sta_id; return IWL_INVALID_STATION;
} }
static int iwlagn_send_sta_key(struct iwl_priv *priv, 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, u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
u32 cmd_flags) u32 cmd_flags)
{ {
unsigned long flags;
__le16 key_flags; __le16 key_flags;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
int i; 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)); 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 = cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
key_flags |= STA_KEY_FLG_MAP_KEY_MSK; 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_key_conf *keyconf,
struct ieee80211_sta *sta) struct ieee80211_sta *sta)
{ {
unsigned long flags;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta); u8 sta_id = iwlagn_key_sta_id(priv, ctx->vif, sta);
__le16 key_flags; __le16 key_flags;
@ -1196,16 +1194,16 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -ENOENT; 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)); memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(sta_cmd));
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE))
sta_id = IWL_INVALID_STATION; 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) if (sta_id == IWL_INVALID_STATION)
return 0; return 0;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
ctx->key_mapping_keys--; ctx->key_mapping_keys--;
@ -1245,7 +1243,7 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -EINVAL; return -EINVAL;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv); keyconf->hw_key_idx = iwl_get_free_ucode_key_offset(priv);
if (keyconf->hw_key_idx == WEP_INVALID_OFFSET) 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_rxon_context *ctx)
{ {
struct iwl_link_quality_cmd *link_cmd; struct iwl_link_quality_cmd *link_cmd;
unsigned long flags;
u8 sta_id; 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); sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
if (sta_id == IWL_INVALID_STATION) { if (sta_id == IWL_INVALID_STATION) {
IWL_ERR(priv, "Unable to prepare broadcast station\n"); 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; return -EINVAL;
} }
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
priv->stations[sta_id].used |= IWL_STA_BCAST; 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); link_cmd = iwl_sta_alloc_lq(priv, ctx, sta_id);
if (!link_cmd) { if (!link_cmd) {
@ -1323,9 +1320,9 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
return -ENOMEM; return -ENOMEM;
} }
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock_bh(&priv->sta_lock);
priv->stations[sta_id].lq = link_cmd; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return 0; return 0;
} }
@ -1339,7 +1336,6 @@ int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
int iwl_update_bcast_station(struct iwl_priv *priv, int iwl_update_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx) struct iwl_rxon_context *ctx)
{ {
unsigned long flags;
struct iwl_link_quality_cmd *link_cmd; struct iwl_link_quality_cmd *link_cmd;
u8 sta_id = ctx->bcast_sta_id; u8 sta_id = ctx->bcast_sta_id;
@ -1349,13 +1345,13 @@ int iwl_update_bcast_station(struct iwl_priv *priv,
return -ENOMEM; return -ENOMEM;
} }
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock_bh(&priv->sta_lock);
if (priv->stations[sta_id].lq) if (priv->stations[sta_id].lq)
kfree(priv->stations[sta_id].lq); kfree(priv->stations[sta_id].lq);
else else
IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
priv->stations[sta_id].lq = link_cmd; priv->stations[sta_id].lq = link_cmd;
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return 0; 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) 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; 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 */ /* 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.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.tid_disable_tx &= cpu_to_le16(~(1 << tid));
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); 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); 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 iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid, u16 ssn) int tid, u16 ssn)
{ {
unsigned long flags;
int sta_id; int sta_id;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) if (sta_id == IWL_INVALID_STATION)
return -ENXIO; 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.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; 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_tid = (u8)tid;
priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); 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); 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 iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
int tid) int tid)
{ {
unsigned long flags;
int sta_id; int sta_id;
struct iwl_addsta_cmd sta_cmd; struct iwl_addsta_cmd sta_cmd;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
if (sta_id == IWL_INVALID_STATION) { 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; 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.station_flags_msk = 0;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; 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.remove_immediate_ba_tid = (u8)tid;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); 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); 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) void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
{ {
unsigned long flags; struct iwl_addsta_cmd cmd = {
.mode = STA_CONTROL_MODIFY_MSK,
spin_lock_irqsave(&priv->shrd->sta_lock, flags); .station_flags = STA_FLG_PWR_SAVE_MSK,
priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; .station_flags_msk = STA_FLG_PWR_SAVE_MSK,
priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; .sta.sta_id = sta_id,
priv->stations[sta_id].sta.sta.modify_mask = .sta.modify_mask = STA_MODIFY_SLEEP_TX_COUNT_MSK,
STA_MODIFY_SLEEP_TX_COUNT_MSK; .sleep_tx_count = cpu_to_le16(cnt),
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);
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
} }

View File

@ -34,6 +34,7 @@
#include <net/mac80211.h> #include <net/mac80211.h>
#include "iwl-agn.h"
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.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; struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
unsigned long flags; unsigned long flags;
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
if (tt->state == IWL_TI_CT_KILL) { 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); iwl_read32(trans(priv), CSR_UCODE_DRV_GP1);
spin_lock_irqsave(&trans(priv)->reg_lock, flags); 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)); iwl_release_nic_access(trans(priv));
spin_unlock_irqrestore(&trans(priv)->reg_lock, flags); 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_priv *priv = (struct iwl_priv *)data;
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 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; return;
/* temperature timer expired, ready to go into CT_KILL state */ /* 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 " IWL_DEBUG_TEMP(priv, "entering CT_KILL state when "
"temperature timer expired\n"); "temperature timer expired\n");
tt->state = IWL_TI_CT_KILL; 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); 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; tt->tt_power_mode = IWL_POWER_INDEX_5;
break; break;
} }
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (old_state == IWL_TI_CT_KILL) 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 && if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) { iwl_power_update_mode(priv, true)) {
/* TT state not updated /* TT state not updated
* try again during next temperature read * try again during next temperature read
*/ */
if (old_state == IWL_TI_CT_KILL) 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; tt->state = old_state;
IWL_ERR(priv, "Cannot update power mode, " IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n"); "TT state not updated\n");
} else { } else {
if (tt->state == IWL_TI_CT_KILL) { if (tt->state == IWL_TI_CT_KILL) {
if (force) { if (force) {
set_bit(STATUS_CT_KILL, set_bit(STATUS_CT_KILL, &priv->status);
&priv->shrd->status);
iwl_perform_ct_kill_task(priv, true); iwl_perform_ct_kill_task(priv, true);
} else { } else {
iwl_prepare_ct_kill_task(priv); 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", IWL_DEBUG_TEMP(priv, "Power Index change to %u\n",
tt->tt_power_mode); 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 */ * in case get disabled before */
iwl_set_rxon_ht(priv, &priv->current_ht_config); 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) 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 && if (tt->state != IWL_TI_CT_KILL &&
iwl_power_update_mode(priv, true)) { iwl_power_update_mode(priv, true)) {
/* TT state not updated /* 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, " IWL_ERR(priv, "Cannot update power mode, "
"TT state not updated\n"); "TT state not updated\n");
if (old_state == IWL_TI_CT_KILL) 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; tt->state = old_state;
} else { } else {
IWL_DEBUG_TEMP(priv, IWL_DEBUG_TEMP(priv,
@ -473,8 +473,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force)
if (force) { if (force) {
IWL_DEBUG_TEMP(priv, IWL_DEBUG_TEMP(priv,
"Enter IWL_TI_CT_KILL\n"); "Enter IWL_TI_CT_KILL\n");
set_bit(STATUS_CT_KILL, set_bit(STATUS_CT_KILL, &priv->status);
&priv->shrd->status);
iwl_perform_ct_kill_task(priv, true); iwl_perform_ct_kill_task(priv, true);
} else { } else {
iwl_prepare_ct_kill_task(priv); 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); 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_priv *priv = container_of(work, struct iwl_priv, ct_enter);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 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; return;
if (!iwl_is_ready(priv->shrd)) if (!iwl_is_ready(priv))
return; return;
if (tt->state != IWL_TI_CT_KILL) { 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_priv *priv = container_of(work, struct iwl_priv, ct_exit);
struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 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; return;
if (!iwl_is_ready(priv->shrd)) if (!iwl_is_ready(priv))
return; return;
/* stop ct_kill_exit_tm timer */ /* 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) 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; return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature enter.\n"); 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) 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; return;
IWL_DEBUG_TEMP(priv, "Queueing critical temperature exit.\n"); 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); struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
s32 temp = priv->temperature; /* degrees CELSIUS except specified */ 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; return;
if (!priv->thermal_throttle.advanced_tt) 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) 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; return;
IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n"); IWL_DEBUG_TEMP(priv, "Queueing thermal throttling work.\n");

View File

@ -126,7 +126,7 @@ static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
u8 data_retry_limit; u8 data_retry_limit;
u8 rate_plcp; u8 rate_plcp;
if (priv->shrd->wowlan) { if (priv->wowlan) {
rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT; rts_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
data_retry_limit = IWLAGN_LOW_RETRY_LIMIT; data_retry_limit = IWLAGN_LOW_RETRY_LIMIT;
} else { } 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, static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
struct ieee80211_tx_info *info, struct ieee80211_tx_info *info,
struct iwl_tx_cmd *tx_cmd, struct iwl_tx_cmd *tx_cmd,
struct sk_buff *skb_frag, struct sk_buff *skb_frag)
int sta_id)
{ {
struct ieee80211_key_conf *keyconf = info->control.hw_key; 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 * 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_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
struct iwl_device_cmd *dev_cmd = NULL; struct iwl_device_cmd *dev_cmd = NULL;
struct iwl_tx_cmd *tx_cmd; struct iwl_tx_cmd *tx_cmd;
__le16 fc; __le16 fc;
u8 hdr_len; u8 hdr_len;
u16 len, seq_number = 0; u16 len, seq_number = 0;
u8 sta_id, tid = IWL_MAX_TID_COUNT; u8 sta_id, tid = IWL_MAX_TID_COUNT;
unsigned long flags;
bool is_agg = false; bool is_agg = false;
if (info->control.vif) if (info->control.vif)
ctx = iwl_rxon_ctx_from_vif(info->control.vif); ctx = iwl_rxon_ctx_from_vif(info->control.vif);
spin_lock_irqsave(&priv->shrd->lock, flags); if (iwl_is_rfkill(priv)) {
if (iwl_is_rfkill(priv->shrd)) {
IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
goto drop_unlock_priv; 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; sta_id = ctx->bcast_sta_id;
else { else {
/* Find index into station table for destination station */ /* 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) { if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
hdr->addr1); 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) if (info->flags & IEEE80211_TX_CTL_AMPDU)
is_agg = true; is_agg = true;
/* irqs already disabled/saved above when locking priv->shrd->lock */ dev_cmd = kmem_cache_alloc(iwl_tx_cmd_pool, GFP_ATOMIC);
spin_lock(&priv->shrd->sta_lock);
dev_cmd = kmem_cache_alloc(priv->tx_cmd_pool, GFP_ATOMIC);
if (unlikely(!dev_cmd)) if (unlikely(!dev_cmd))
goto drop_unlock_sta; goto drop_unlock_priv;
memset(dev_cmd, 0, sizeof(*dev_cmd)); memset(dev_cmd, 0, sizeof(*dev_cmd));
tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload; 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); tx_cmd->len = cpu_to_le16(len);
if (info->control.hw_key) 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 */ /* TODO need this for burst mode later on */
iwlagn_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id); 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[0] = ctx;
info->driver_data[1] = dev_cmd; info->driver_data[1] = dev_cmd;
spin_lock(&priv->sta_lock);
if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) {
u8 *qc = NULL; u8 *qc = NULL;
struct iwl_tid_data *tid_data; 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)) !ieee80211_has_morefrags(fc))
priv->tid_data[sta_id][tid].seq_number = seq_number; priv->tid_data[sta_id][tid].seq_number = seq_number;
spin_unlock(&priv->shrd->sta_lock); spin_unlock(&priv->sta_lock);
spin_unlock_irqrestore(&priv->shrd->lock, flags);
/* /*
* Avoid atomic ops if it isn't an associated client. * 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: drop_unlock_sta:
if (dev_cmd) if (dev_cmd)
kmem_cache_free(priv->tx_cmd_pool, dev_cmd); kmem_cache_free(iwl_tx_cmd_pool, dev_cmd);
spin_unlock(&priv->shrd->sta_lock); spin_unlock(&priv->sta_lock);
drop_unlock_priv: drop_unlock_priv:
spin_unlock_irqrestore(&priv->shrd->lock, flags);
return -1; 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 ieee80211_sta *sta, u16 tid)
{ {
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
unsigned long flags;
int sta_id; int sta_id;
sta_id = iwl_sta_id(sta); 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; return -ENXIO;
} }
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock_bh(&priv->sta_lock);
tid_data = &priv->tid_data[sta_id][tid]; 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 " IWL_WARN(priv, "Stopping AGG while state not ON "
"or starting for %d on %d (%d)\n", sta_id, tid, "or starting for %d on %d (%d)\n", sta_id, tid,
priv->tid_data[sta_id][tid].agg.state); priv->tid_data[sta_id][tid].agg.state);
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return 0; return 0;
} }
@ -490,7 +511,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
tid_data->next_reclaimed); tid_data->next_reclaimed);
priv->tid_data[sta_id][tid].agg.state = priv->tid_data[sta_id][tid].agg.state =
IWL_EMPTYING_HW_QUEUE_DELBA; IWL_EMPTYING_HW_QUEUE_DELBA;
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return 0; return 0;
} }
@ -499,14 +520,10 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
turn_off: turn_off:
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
/* do not restore/save irqs */ spin_unlock_bh(&priv->sta_lock);
spin_unlock(&priv->shrd->sta_lock);
spin_lock(&priv->shrd->lock);
iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); 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); ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
return 0; 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 ieee80211_sta *sta, u16 tid, u16 *ssn)
{ {
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
unsigned long flags;
int sta_id; int sta_id;
int ret; int ret;
@ -540,7 +556,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
if (ret) if (ret)
return 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 = &priv->tid_data[sta_id][tid];
tid_data->agg.ssn = SEQ_TO_SN(tid_data->seq_number); 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); ret = iwl_trans_tx_agg_alloc(trans(priv), sta_id, tid);
if (ret) { if (ret) {
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock_bh(&priv->sta_lock);
return ret; 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; 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; 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_station_priv *sta_priv = (void *) sta->drv_priv;
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
unsigned long flags;
u16 ssn; u16 ssn;
buf_size = min_t(int, buf_size, LINK_QUAL_AGG_FRAME_LIMIT_DEF); 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; 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, iwl_trans_tx_agg_setup(trans(priv), ctx->ctxid, sta_priv->sta_id, tid,
buf_size, ssn); 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 = sta_priv->max_agg_bufsize =
min(sta_priv->max_agg_bufsize, buf_size); min(sta_priv->max_agg_bufsize, buf_size);
if (cfg(priv)->ht_params && if (hw_params(priv).use_rts_for_aggregation) {
cfg(priv)->ht_params->use_rts_for_aggregation) {
/* /*
* switch to RTS/CTS if it is the prefer protection * switch to RTS/CTS if it is the prefer protection
* method for HT traffic * 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; struct ieee80211_vif *vif;
u8 *addr; u8 *addr;
lockdep_assert_held(&priv->shrd->sta_lock); lockdep_assert_held(&priv->sta_lock);
addr = priv->stations[sta_id].sta.sta.addr; addr = priv->stations[sta_id].sta.sta.addr;
ctx = priv->stations[sta_id].ctxid; 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) { if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
IWL_ERR(priv, "Tx flush command to flush out all frames\n"); 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); 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_rx_packet *pkt = rxb_addr(rxb);
u16 sequence = le16_to_cpu(pkt->hdr.sequence); u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence); int txq_id = SEQ_TO_QUEUE(sequence);
int cmd_index __maybe_unused = SEQ_TO_INDEX(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; struct ieee80211_hdr *hdr;
u32 status = le16_to_cpu(tx_resp->status.status); u32 status = le16_to_cpu(tx_resp->status.status);
u16 ssn = iwlagn_get_scd_ssn(tx_resp); 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 sta_id;
int freed; int freed;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
unsigned long flags;
struct sk_buff_head skbs; struct sk_buff_head skbs;
struct sk_buff *skb; struct sk_buff *skb;
struct iwl_rxon_context *ctx; 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) >> sta_id = (tx_resp->ra_tid & IWLAGN_TX_RES_RA_MSK) >>
IWLAGN_TX_RES_RA_POS; IWLAGN_TX_RES_RA_POS;
spin_lock_irqsave(&priv->shrd->sta_lock, flags); spin_lock(&priv->sta_lock);
if (is_agg) if (is_agg)
iwl_rx_reply_tx_agg(priv, tx_resp); iwl_rx_reply_tx_agg(priv, tx_resp);
__skb_queue_head_init(&skbs);
if (tx_resp->frame_count == 1) { if (tx_resp->frame_count == 1) {
u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl); u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
next_reclaimed = SEQ_TO_SN(next_reclaimed + 0x10); 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; next_reclaimed = ssn;
} }
__skb_queue_head_init(&skbs);
if (tid != IWL_TID_NON_QOS) { if (tid != IWL_TID_NON_QOS) {
priv->tid_data[sta_id][tid].next_reclaimed = priv->tid_data[sta_id][tid].next_reclaimed =
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 */ /*we can free until ssn % q.n_bd not inclusive */
WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid,
ssn, status, &skbs)); txq_id, ssn, &skbs));
iwlagn_check_ratid_empty(priv, sta_id, tid); iwlagn_check_ratid_empty(priv, sta_id, tid);
freed = 0; freed = 0;
while (!skb_queue_empty(&skbs)) {
skb = __skb_dequeue(&skbs); /* process frames */
skb_queue_walk(&skbs, skb) {
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
if (!ieee80211_is_data_qos(hdr->frame_control)) 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); info = IEEE80211_SKB_CB(skb);
ctx = info->driver_data[0]; ctx = info->driver_data[0];
kmem_cache_free(priv->tx_cmd_pool, kmem_cache_free(iwl_tx_cmd_pool,
(info->driver_data[1])); (info->driver_data[1]));
memset(&info->status, 0, sizeof(info->status)); 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 && if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
iwl_is_associated_ctx(ctx) && ctx->vif && iwl_is_associated_ctx(ctx) && ctx->vif &&
ctx->vif->type == NL80211_IFTYPE_STATION) { ctx->vif->type == NL80211_IFTYPE_STATION) {
ctx->last_tx_rejected = true; /* block and stop all queues */
iwl_trans_stop_queue(trans(priv), txq_id, priv->passive_no_rx = true;
"Tx on passive channel"); IWL_DEBUG_TX_QUEUES(priv, "stop all queues: "
"passive channel");
ieee80211_stop_queues(priv->hw);
IWL_DEBUG_TX_REPLY(priv, IWL_DEBUG_TX_REPLY(priv,
"TXQ %d status %s (0x%08x) " "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) if (!is_agg)
iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1); iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
ieee80211_tx_status_irqsafe(priv->hw, skb);
freed++; 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); 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; 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. * of frames sent via aggregation.
*/ */
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, 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_device_cmd *cmd)
{ {
struct iwl_rx_packet *pkt = rxb_addr(rxb); 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 iwl_ht_agg *agg;
struct sk_buff_head reclaimed_skbs; struct sk_buff_head reclaimed_skbs;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
unsigned long flags;
int sta_id; int sta_id;
int tid; int tid;
int freed; 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 */ * (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); 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, IWL_ERR(priv,
"BUG_ON scd_flow is bigger than number of queues\n"); "BUG_ON scd_flow is bigger than number of queues\n");
return 0; return 0;
@ -1150,12 +1169,12 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
tid = ba_resp->tid; tid = ba_resp->tid;
agg = &priv->tid_data[sta_id][tid].agg; 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(!agg->wait_for_ba)) {
if (unlikely(ba_resp->bitmap)) if (unlikely(ba_resp->bitmap))
IWL_ERR(priv, "Received BA when not expected\n"); IWL_ERR(priv, "Received BA when not expected\n");
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock(&priv->sta_lock);
return 0; 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 * block-ack window (we assume that they've been successfully
* transmitted ... if not, it's too late anyway). */ * transmitted ... if not, it's too late anyway). */
if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, if (iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow,
ba_resp_scd_ssn, 0, &reclaimed_skbs)) { ba_resp_scd_ssn, &reclaimed_skbs)) {
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags); spin_unlock(&priv->sta_lock);
return 0; return 0;
} }
@ -1202,9 +1221,8 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
iwlagn_check_ratid_empty(priv, sta_id, tid); iwlagn_check_ratid_empty(priv, sta_id, tid);
freed = 0; 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; hdr = (struct ieee80211_hdr *)skb->data;
if (ieee80211_is_data_qos(hdr->frame_control)) 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); WARN_ON_ONCE(1);
info = IEEE80211_SKB_CB(skb); 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) { if (freed == 1) {
/* this is the first skb we deliver in this batch */ /* 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, iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags,
info); 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; return 0;
} }

View File

@ -41,9 +41,7 @@
#include <asm/div64.h> #include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-io.h" #include "iwl-io.h"
@ -134,7 +132,7 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
* beacon contents. * beacon contents.
*/ */
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
if (!priv->beacon_ctx) { if (!priv->beacon_ctx) {
IWL_ERR(priv, "trying to build beacon w/o beacon context!\n"); 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.data[1] = priv->beacon_skb->data;
cmd.dataflags[1] = IWL_HCMD_DFL_NOCOPY; 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) 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); container_of(work, struct iwl_priv, beacon_update);
struct sk_buff *beacon; struct sk_buff *beacon;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (!priv->beacon_ctx) { if (!priv->beacon_ctx) {
IWL_ERR(priv, "updating beacon w/o beacon context!\n"); IWL_ERR(priv, "updating beacon w/o beacon context!\n");
goto out; goto out;
@ -238,7 +236,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
iwlagn_send_beacon_cmd(priv); iwlagn_send_beacon_cmd(priv);
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
} }
static void iwl_bg_bt_runtime_config(struct work_struct *work) 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 = struct iwl_priv *priv =
container_of(work, struct iwl_priv, bt_runtime_config); 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; return;
/* dont send host command if rf-kill is on */ /* dont send host command if rf-kill is on */
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
return; return;
iwlagn_send_advance_bt_config(priv); 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); container_of(work, struct iwl_priv, bt_full_concurrency);
struct iwl_rxon_context *ctx; 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; goto out;
/* dont send host command if rf-kill is on */ /* dont send host command if rf-kill is on */
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
goto out; goto out;
IWL_DEBUG_INFO(priv, "BT coex in %s mode\n", 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); iwlagn_send_advance_bt_config(priv);
out: 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; 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; return;
/* dont send host command if rf-kill is on */ /* dont send host command if rf-kill is on */
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
return; return;
iwl_send_statistics_request(priv, CMD_ASYNC, false); 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 */ /* Make sure device is powered up for SRAM reads */
spin_lock_irqsave(&trans(priv)->reg_lock, reg_flags); 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); spin_unlock_irqrestore(&trans(priv)->reg_lock, reg_flags);
return; return;
} }
/* Set starting address; reads will auto-increment */ /* Set starting address; reads will auto-increment */
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr); iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, ptr);
rmb();
/* /*
* Refuse to read more than would have fit into the log from * 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); ev = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); time = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
if (mode == 0) { 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 { } else {
data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); data = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
trace_iwlwifi_dev_ucode_cont_event(priv, time, trace_iwlwifi_dev_ucode_cont_event(
data, ev); trans(priv)->dev, time, data, ev);
} }
} }
/* Allow device to power down */ /* Allow device to power down */
@ -424,7 +422,7 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
else else
priv->event_log.wraps_once_count++; 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, num_wraps - priv->event_log.num_wraps,
next_entry, priv->event_log.next_entry); 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; 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; return;
if (priv->event_log.ucode_trace) { if (priv->event_log.ucode_trace) {
@ -479,18 +477,18 @@ static void iwl_bg_tx_flush(struct work_struct *work)
struct iwl_priv *priv = struct iwl_priv *priv =
container_of(work, struct iwl_priv, tx_flush); 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; return;
/* do nothing if rf-kill is on */ /* do nothing if rf-kill is on */
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
return; return;
IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n"); IWL_DEBUG_INFO(priv, "device request: flush all tx frames\n");
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); 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; 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_config cmd;
struct iwl_ct_kill_throttling_config adv_cmd; struct iwl_ct_kill_throttling_config adv_cmd;
unsigned long flags;
int ret = 0; int ret = 0;
spin_lock_irqsave(&priv->shrd->lock, flags);
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->shrd->lock, flags);
priv->thermal_throttle.ct_kill_toggle = false; priv->thermal_throttle.ct_kill_toggle = false;
if (cfg(priv)->base_params->support_ct_kill_exit) { 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 = adv_cmd.critical_temperature_exit =
cpu_to_le32(hw_params(priv).ct_kill_exit_threshold); 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, REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(adv_cmd), &adv_cmd); CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
if (ret) if (ret)
@ -582,7 +578,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
cmd.critical_temperature_R = cmd.critical_temperature_R =
cpu_to_le32(hw_params(priv).ct_kill_threshold); 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, REPLY_CT_KILL_CONFIG_CMD,
CMD_SYNC, sizeof(cmd), &cmd); CMD_SYNC, sizeof(cmd), &cmd);
if (ret) 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.is_enable = IWL_CALIB_RT_CFG_ALL;
calib_cfg_cmd.ucd_calib_cfg.once.start = cpu_to_le32(cfg); 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), .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); 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, TX_ANT_CONFIGURATION_CMD,
CMD_SYNC, CMD_SYNC,
sizeof(struct iwl_tx_ant_config_cmd), 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"); IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
/* After the ALIVE response, we can send host commands to the uCode */ /* 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 */ /* Enable watchdog to monitor the driver tx queues */
iwl_setup_watchdog(priv); iwl_setup_watchdog(priv);
if (iwl_is_rfkill(priv->shrd)) if (iwl_is_rfkill(priv))
return -ERFKILL; return -ERFKILL;
if (priv->event_log.ucode_trace) { 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->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS;
priv->cur_rssi_ctx = NULL; 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 */ /* 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); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return 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); BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
if (ret) if (ret)
return ret; return ret;
@ -701,9 +697,9 @@ int iwl_alive_start(struct iwl_priv *priv)
priv->active_rate = IWL_RATES_MASK; priv->active_rate = IWL_RATES_MASK;
/* Configure Tx antenna selection based on H/W config */ /* 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 *active_rxon =
(struct iwl_rxon_cmd *)&ctx->active; (struct iwl_rxon_cmd *)&ctx->active;
/* apply any changes in staging */ /* apply any changes in staging */
@ -718,12 +714,12 @@ int iwl_alive_start(struct iwl_priv *priv)
iwlagn_set_rxon_chain(priv, ctx); iwlagn_set_rxon_chain(priv, ctx);
} }
if (!priv->shrd->wowlan) { if (!priv->wowlan) {
/* WoWLAN ucode will not reply in the same way, skip it */ /* WoWLAN ucode will not reply in the same way, skip it */
iwl_reset_run_time_calib(priv); 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 */ /* Configure the adapter for unassociated operation */
ret = iwlagn_commit_rxon(priv, ctx); 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); 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) void iwl_down(struct iwl_priv *priv)
{ {
int exit_pending; int exit_pending;
IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); 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); iwl_scan_cancel_timeout(priv, 200);
@ -756,7 +786,7 @@ void iwl_down(struct iwl_priv *priv)
ieee80211_remain_on_channel_expired(priv->hw); ieee80211_remain_on_channel_expired(priv->hw);
exit_pending = 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 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
* to prevent rearm timer */ * to prevent rearm timer */
@ -781,23 +811,24 @@ void iwl_down(struct iwl_priv *priv)
/* Wipe out the EXIT_PENDING status bit if we are not actually /* Wipe out the EXIT_PENDING status bit if we are not actually
* exiting the module */ * exiting the module */
if (!exit_pending) if (!exit_pending)
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status); clear_bit(STATUS_EXIT_PENDING, &priv->status);
if (priv->mac80211_registered) if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw); ieee80211_stop_queues(priv->hw);
priv->ucode_loaded = false;
iwl_trans_stop_device(trans(priv)); iwl_trans_stop_device(trans(priv));
/* Clear out all status bits but a few that are stable across reset */ /* Clear out all status bits but a few that are stable across reset */
priv->shrd->status &= priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) <<
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
STATUS_RF_KILL_HW | STATUS_RF_KILL_HW |
test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status) << test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
STATUS_GEO_CONFIGURED | STATUS_GEO_CONFIGURED |
test_bit(STATUS_FW_ERROR, &priv->shrd->status) << test_bit(STATUS_EXIT_PENDING, &priv->status) <<
STATUS_FW_ERROR |
test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
STATUS_EXIT_PENDING; STATUS_EXIT_PENDING;
priv->shrd->status &=
test_bit(STATUS_FW_ERROR, &priv->shrd->status) <<
STATUS_FW_ERROR;
dev_kfree_skb(priv->beacon_skb); dev_kfree_skb(priv->beacon_skb);
priv->beacon_skb = NULL; priv->beacon_skb = NULL;
@ -814,11 +845,11 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, struct iwl_priv *priv = container_of(work, struct iwl_priv,
run_time_calib_work); run_time_calib_work);
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) ||
test_bit(STATUS_SCANNING, &priv->shrd->status)) { test_bit(STATUS_SCANNING, &priv->status)) {
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
return; return;
} }
@ -827,7 +858,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
iwl_sensitivity_calibration(priv); iwl_sensitivity_calibration(priv);
} }
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
} }
void iwlagn_prepare_restart(struct iwl_priv *priv) void iwlagn_prepare_restart(struct iwl_priv *priv)
@ -839,7 +870,7 @@ void iwlagn_prepare_restart(struct iwl_priv *priv)
u8 bt_status; u8 bt_status;
bool bt_is_sco; bool bt_is_sco;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
for_each_context(priv, ctx) for_each_context(priv, ctx)
ctx->vif = NULL; ctx->vif = NULL;
@ -873,13 +904,13 @@ static void iwl_bg_restart(struct work_struct *data)
{ {
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); 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; return;
if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) { if (test_and_clear_bit(STATUS_FW_ERROR, &priv->shrd->status)) {
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwlagn_prepare_restart(priv); iwlagn_prepare_restart(priv);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
iwl_cancel_deferred_work(priv); iwl_cancel_deferred_work(priv);
ieee80211_restart_hw(priv->hw); ieee80211_restart_hw(priv->hw);
} else { } else {
@ -894,7 +925,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv)
{ {
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; 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) if (!priv->hw_roc_setup)
return; return;
@ -917,9 +948,9 @@ static void iwlagn_disable_roc_work(struct work_struct *work)
struct iwl_priv *priv = container_of(work, struct iwl_priv, struct iwl_priv *priv = container_of(work, struct iwl_priv,
hw_roc_disable_work.work); hw_roc_disable_work.work);
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwlagn_disable_roc(priv); iwlagn_disable_roc(priv);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
} }
/***************************************************************************** /*****************************************************************************
@ -932,8 +963,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
{ {
priv->workqueue = create_singlethread_workqueue(DRV_NAME); priv->workqueue = create_singlethread_workqueue(DRV_NAME);
init_waitqueue_head(&priv->shrd->wait_command_queue);
INIT_WORK(&priv->restart, iwl_bg_restart); INIT_WORK(&priv->restart, iwl_bg_restart);
INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
@ -945,8 +974,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
iwl_setup_scan_deferred_work(priv); iwl_setup_scan_deferred_work(priv);
if (cfg(priv)->lib->bt_setup_deferred_work) if (cfg(priv)->bt_params)
cfg(priv)->lib->bt_setup_deferred_work(priv); iwlagn_bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic); init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv; priv->statistics_periodic.data = (unsigned long)priv;
@ -963,8 +992,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
void iwl_cancel_deferred_work(struct iwl_priv *priv) void iwl_cancel_deferred_work(struct iwl_priv *priv)
{ {
if (cfg(priv)->lib->cancel_deferred_work) if (cfg(priv)->bt_params)
cfg(priv)->lib->cancel_deferred_work(priv); iwlagn_bt_cancel_deferred_work(priv);
cancel_work_sync(&priv->run_time_calib_work); cancel_work_sync(&priv->run_time_calib_work);
cancel_work_sync(&priv->beacon_update); cancel_work_sync(&priv->beacon_update);
@ -979,8 +1008,7 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv)
del_timer_sync(&priv->ucode_trace); del_timer_sync(&priv->ucode_trace);
} }
static void iwl_init_hw_rates(struct iwl_priv *priv, static void iwl_init_hw_rates(struct ieee80211_rate *rates)
struct ieee80211_rate *rates)
{ {
int i; int i;
@ -1004,21 +1032,26 @@ static int iwl_init_drv(struct iwl_priv *priv)
{ {
int ret; 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_channels = NULL;
priv->ieee_rates = NULL; priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ; priv->band = IEEE80211_BAND_2GHZ;
priv->plcp_delta_threshold =
cfg(priv)->base_params->plcp_delta_threshold;
priv->iw_mode = NL80211_IFTYPE_STATION; priv->iw_mode = NL80211_IFTYPE_STATION;
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC; priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
priv->agg_tids_count = 0; priv->agg_tids_count = 0;
priv->ucode_owner = IWL_OWNERSHIP_DRIVER;
/* initialize force reset */ /* initialize force reset */
priv->force_reset[IWL_RF_RESET].reset_duration = priv->force_reset[IWL_RF_RESET].reset_duration =
IWL_DELAY_NEXT_FORCE_RF_RESET; IWL_DELAY_NEXT_FORCE_RF_RESET;
@ -1054,7 +1087,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
IWL_ERR(priv, "initializing geos failed: %d\n", ret); IWL_ERR(priv, "initializing geos failed: %d\n", ret);
goto err_free_channel_map; goto err_free_channel_map;
} }
iwl_init_hw_rates(priv, priv->ieee_rates); iwl_init_hw_rates(priv->ieee_rates);
return 0; return 0;
@ -1068,11 +1101,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
{ {
iwl_free_geos(priv); iwl_free_geos(priv);
iwl_free_channel_map(priv); iwl_free_channel_map(priv);
if (priv->tx_cmd_pool)
kmem_cache_destroy(priv->tx_cmd_pool);
kfree(priv->scan_cmd); kfree(priv->scan_cmd);
kfree(priv->beacon_cmd); kfree(priv->beacon_cmd);
kfree(rcu_dereference_raw(priv->noa_data)); kfree(rcu_dereference_raw(priv->noa_data));
iwl_calib_free_results(priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
kfree(priv->wowlan_sram); kfree(priv->wowlan_sram);
#endif #endif
@ -1084,6 +1116,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
static void iwl_set_hw_params(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) if (iwlagn_mod_params.amsdu_size_8K)
hw_params(priv).rx_page_order = hw_params(priv).rx_page_order =
get_order(IWL_RX_BUF_SIZE_8K); get_order(IWL_RX_BUF_SIZE_8K);
@ -1092,13 +1128,10 @@ static void iwl_set_hw_params(struct iwl_priv *priv)
get_order(IWL_RX_BUF_SIZE_4K); get_order(IWL_RX_BUF_SIZE_4K);
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_ALL) 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 = hw_params(priv).num_ampdu_queues =
cfg(priv)->base_params->num_of_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; hw_params(priv).wd_timeout = cfg(priv)->base_params->wd_timeout;
/* Device-specific setup */ /* Device-specific setup */
@ -1142,15 +1175,24 @@ static void iwl_debug_config(struct iwl_priv *priv)
#endif #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; int err = 0;
struct iwl_priv *priv; struct iwl_priv *priv;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct iwl_op_mode *op_mode; struct iwl_op_mode *op_mode;
u16 num_mac; u16 num_mac;
u32 ucode_flags; u32 ucode_flags;
struct iwl_trans_config trans_cfg;
static const u8 no_reclaim_cmds[] = {
REPLY_RX_PHY_CMD,
REPLY_RX,
REPLY_RX_MPDU_CMD,
REPLY_COMPRESSED_BA,
STATISTICS_NOTIFICATION,
REPLY_TX,
};
/************************ /************************
* 1. Allocating HW data * 1. Allocating HW data
@ -1167,9 +1209,34 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
op_mode->ops = &iwl_dvm_ops; op_mode->ops = &iwl_dvm_ops;
priv = IWL_OP_MODE_GET_DVM(op_mode); priv = IWL_OP_MODE_GET_DVM(op_mode);
priv->shrd = trans->shrd; 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;
trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
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. */ /* At this point both hw and priv are allocated. */
@ -1198,10 +1265,10 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
* we should init now * we should init now
*/ */
spin_lock_init(&trans(priv)->reg_lock); 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", IWL_INFO(priv, "Detected %s, REV=0x%X\n",
cfg(priv)->name, trans(priv)->hw_rev); cfg(priv)->name, trans(priv)->hw_rev);
@ -1211,9 +1278,8 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
goto out_free_traffic_mem; goto out_free_traffic_mem;
/***************** /*****************
* 4. Read EEPROM * 3. Read EEPROM
*****************/ *****************/
/* Read the EEPROM */
err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev); err = iwl_eeprom_init(trans(priv), trans(priv)->hw_rev);
/* Reset chip to save power until we load uCode during "up". */ /* Reset chip to save power until we load uCode during "up". */
iwl_trans_stop_hw(trans(priv)); iwl_trans_stop_hw(trans(priv));
@ -1225,7 +1291,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
if (err) if (err)
goto out_free_eeprom; goto out_free_eeprom;
err = iwl_eeprom_check_sku(priv); err = iwl_eeprom_init_hw_params(priv);
if (err) if (err)
goto out_free_eeprom; goto out_free_eeprom;
@ -1243,28 +1309,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); iwl_set_hw_params(priv);
ucode_flags = fw->ucode_capa.flags; if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE)) {
IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
#ifndef CONFIG_IWLWIFI_P2P
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
#endif
if (!(hw_params(priv).sku & EEPROM_SKU_CAP_IPAN_ENABLE))
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN; ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
/*
/* * if not PAN, then don't support P2P -- might be a uCode
* if not PAN, then don't support P2P -- might be a uCode * packaging bug or due to the eeprom check above
* packaging bug or due to the eeprom check above */
*/
if (!(ucode_flags & IWL_UCODE_TLV_FLAGS_PAN))
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_P2P; 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); err = iwl_init_drv(priv);
@ -1273,7 +1338,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
/* At this point both hw and priv are initialized. */ /* At this point both hw and priv are initialized. */
/******************** /********************
* 7. Setup services * 6. Setup services
********************/ ********************/
iwl_setup_deferred_work(priv); iwl_setup_deferred_work(priv);
iwl_setup_rx_handlers(priv); iwl_setup_rx_handlers(priv);
@ -1289,14 +1354,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
priv->new_scan_threshold_behaviour = priv->new_scan_threshold_behaviour =
!!(ucode_flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); !!(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 = priv->phy_calib_chain_noise_reset_cmd =
fw->ucode_capa.standard_phy_calibration_size; fw->ucode_capa.standard_phy_calibration_size;
priv->phy_calib_chain_noise_gain_cmd = priv->phy_calib_chain_noise_gain_cmd =
@ -1308,7 +1365,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans)
/************************************************** /**************************************************
* This is still part of probe() in a sense... * 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); err = iwlagn_mac_setup_register(priv, &fw->ucode_capa);
if (err) if (err)
@ -1340,28 +1397,19 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
{ {
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(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_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv); 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); iwl_testmode_cleanup(priv);
iwlagn_mac_unregister(priv); iwlagn_mac_unregister(priv);
iwl_tt_exit(priv); iwl_tt_exit(priv);
/*This will stop the queues, move the device to low power state */ /*This will stop the queues, move the device to low power state */
priv->ucode_loaded = false;
iwl_trans_stop_device(trans(priv)); iwl_trans_stop_device(trans(priv));
iwl_dealloc_ucode(nic(priv));
iwl_eeprom_free(priv->shrd); iwl_eeprom_free(priv->shrd);
/*netif_stop_queue(dev); */ /*netif_stop_queue(dev); */
@ -1381,6 +1429,60 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
ieee80211_free_hw(priv->hw); 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 = { const struct iwl_op_mode_ops iwl_dvm_ops = {
.start = iwl_op_mode_dvm_start, .start = iwl_op_mode_dvm_start,
.stop = iwl_op_mode_dvm_stop, .stop = iwl_op_mode_dvm_stop,
@ -1390,6 +1492,8 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
.hw_rf_kill = iwl_set_hw_rfkill_state, .hw_rf_kill = iwl_set_hw_rfkill_state,
.free_skb = iwl_free_skb, .free_skb = iwl_free_skb,
.nic_error = iwl_nic_error, .nic_error = iwl_nic_error,
.cmd_queue_full = iwl_cmd_queue_full,
.nic_config = iwl_nic_config,
}; };
/***************************************************************************** /*****************************************************************************
@ -1397,6 +1501,9 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
* driver and module entry point * driver and module entry point
* *
*****************************************************************************/ *****************************************************************************/
struct kmem_cache *iwl_tx_cmd_pool;
static int __init iwl_init(void) static int __init iwl_init(void)
{ {
@ -1404,20 +1511,27 @@ static int __init iwl_init(void)
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
pr_info(DRV_COPYRIGHT "\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(); ret = iwlagn_rate_control_register();
if (ret) { if (ret) {
pr_err("Unable to register rate control algorithm: %d\n", ret); pr_err("Unable to register rate control algorithm: %d\n", ret);
return ret; goto error_rc_register;
} }
ret = iwl_pci_register_driver(); ret = iwl_pci_register_driver();
if (ret) if (ret)
goto error_register; goto error_pci_register;
return ret; return ret;
error_register: error_pci_register:
iwlagn_rate_control_unregister(); iwlagn_rate_control_unregister();
error_rc_register:
kmem_cache_destroy(iwl_tx_cmd_pool);
return ret; return ret;
} }
@ -1425,6 +1539,7 @@ static void __exit iwl_exit(void)
{ {
iwl_pci_unregister_driver(); iwl_pci_unregister_driver();
iwlagn_rate_control_unregister(); iwlagn_rate_control_unregister();
kmem_cache_destroy(iwl_tx_cmd_pool);
} }
module_exit(iwl_exit); module_exit(iwl_exit);
@ -1438,8 +1553,6 @@ MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO); module_param_named(swcrypto, iwlagn_mod_params.sw_crypto, int, S_IRUGO);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); 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_param_named(11n_disable, iwlagn_mod_params.disable_11n, uint, S_IRUGO);
MODULE_PARM_DESC(11n_disable, MODULE_PARM_DESC(11n_disable,
"disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");

View File

@ -82,20 +82,26 @@ void iwl_cancel_deferred_work(struct iwl_priv *priv);
void iwlagn_prepare_restart(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); 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, 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); 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_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); 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 */ /* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void); struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv, 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); 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 */ /* RXON */
int iwlagn_set_pan_params(struct iwl_priv *priv); int iwlagn_set_pan_params(struct iwl_priv *priv);
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); 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 */ /* uCode */
int iwlagn_rx_calib_result(struct iwl_priv *priv, 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); 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 */ /* lib */
int iwlagn_send_tx_power(struct iwl_priv *priv); 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 #ifdef CONFIG_PM_SLEEP
int iwlagn_send_patterns(struct iwl_priv *priv, int iwlagn_send_patterns(struct iwl_priv *priv,
struct cfg80211_wowlan *wowlan); struct cfg80211_wowlan *wowlan);
int iwlagn_suspend(struct iwl_priv *priv, int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan);
struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
#endif #endif
/* rx */ /* 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, int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, u16 tid); struct ieee80211_sta *sta, u16 tid);
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, 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_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); struct iwl_device_cmd *cmd);
static inline u32 iwl_tx_status_to_mac80211(u32 status) static inline u32 iwl_tx_status_to_mac80211(u32 status)
@ -179,7 +193,7 @@ void iwlagn_disable_roc(struct iwl_priv *priv);
/* bt coex */ /* bt coex */
void iwlagn_send_advance_bt_config(struct iwl_priv *priv); void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
int iwlagn_bt_coex_profile_notif(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); struct iwl_device_cmd *cmd);
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv); void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
void iwlagn_bt_setup_deferred_work(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); struct ieee80211_sta *sta, u8 *sta_id_r);
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
const u8 *addr); 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, u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
const u8 *addr, bool is_ap, struct ieee80211_sta *sta); 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); u8 sta_id, struct iwl_link_quality_cmd *link_cmd);
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
struct iwl_link_quality_cmd *lq, u8 flags, bool init); 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_cmd_buffer *rxb,
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
struct iwl_device_cmd *cmd); 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) static inline int iwl_sta_id(struct ieee80211_sta *sta)
{ {
if (WARN_ON(!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; 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, int iwlagn_alloc_bcast_station(struct iwl_priv *priv,
struct iwl_rxon_context *ctx); struct iwl_rxon_context *ctx);
int iwlagn_add_bssid_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 */ /* eeprom */
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv);
void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac); void iwl_eeprom_get_mac(const struct iwl_shared *shrd, u8 *mac);
extern int iwl_alive_start(struct iwl_priv *priv); 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 #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__ */ #endif /* __iwl_agn_h__ */

View File

@ -68,46 +68,46 @@
* This file declares the config structures for all devices. * This file declares the config structures for all devices.
*/ */
extern struct iwl_cfg iwl5300_agn_cfg; extern const struct iwl_cfg iwl5300_agn_cfg;
extern struct iwl_cfg iwl5100_agn_cfg; extern const struct iwl_cfg iwl5100_agn_cfg;
extern struct iwl_cfg iwl5350_agn_cfg; extern const struct iwl_cfg iwl5350_agn_cfg;
extern struct iwl_cfg iwl5100_bgn_cfg; extern const struct iwl_cfg iwl5100_bgn_cfg;
extern struct iwl_cfg iwl5100_abg_cfg; extern const struct iwl_cfg iwl5100_abg_cfg;
extern struct iwl_cfg iwl5150_agn_cfg; extern const struct iwl_cfg iwl5150_agn_cfg;
extern struct iwl_cfg iwl5150_abg_cfg; extern const struct iwl_cfg iwl5150_abg_cfg;
extern struct iwl_cfg iwl6005_2agn_cfg; extern const struct iwl_cfg iwl6005_2agn_cfg;
extern struct iwl_cfg iwl6005_2abg_cfg; extern const struct iwl_cfg iwl6005_2abg_cfg;
extern struct iwl_cfg iwl6005_2bg_cfg; extern const struct iwl_cfg iwl6005_2bg_cfg;
extern struct iwl_cfg iwl6005_2agn_sff_cfg; extern const struct iwl_cfg iwl6005_2agn_sff_cfg;
extern struct iwl_cfg iwl6005_2agn_d_cfg; extern const struct iwl_cfg iwl6005_2agn_d_cfg;
extern struct iwl_cfg iwl6005_2agn_mow1_cfg; extern const struct iwl_cfg iwl6005_2agn_mow1_cfg;
extern struct iwl_cfg iwl6005_2agn_mow2_cfg; extern const struct iwl_cfg iwl6005_2agn_mow2_cfg;
extern struct iwl_cfg iwl1030_bgn_cfg; extern const struct iwl_cfg iwl1030_bgn_cfg;
extern struct iwl_cfg iwl1030_bg_cfg; extern const struct iwl_cfg iwl1030_bg_cfg;
extern struct iwl_cfg iwl6030_2agn_cfg; extern const struct iwl_cfg iwl6030_2agn_cfg;
extern struct iwl_cfg iwl6030_2abg_cfg; extern const struct iwl_cfg iwl6030_2abg_cfg;
extern struct iwl_cfg iwl6030_2bgn_cfg; extern const struct iwl_cfg iwl6030_2bgn_cfg;
extern struct iwl_cfg iwl6030_2bg_cfg; extern const struct iwl_cfg iwl6030_2bg_cfg;
extern struct iwl_cfg iwl6000i_2agn_cfg; extern const struct iwl_cfg iwl6000i_2agn_cfg;
extern struct iwl_cfg iwl6000i_2abg_cfg; extern const struct iwl_cfg iwl6000i_2abg_cfg;
extern struct iwl_cfg iwl6000i_2bg_cfg; extern const struct iwl_cfg iwl6000i_2bg_cfg;
extern struct iwl_cfg iwl6000_3agn_cfg; extern const struct iwl_cfg iwl6000_3agn_cfg;
extern struct iwl_cfg iwl6050_2agn_cfg; extern const struct iwl_cfg iwl6050_2agn_cfg;
extern struct iwl_cfg iwl6050_2abg_cfg; extern const struct iwl_cfg iwl6050_2abg_cfg;
extern struct iwl_cfg iwl6150_bgn_cfg; extern const struct iwl_cfg iwl6150_bgn_cfg;
extern struct iwl_cfg iwl6150_bg_cfg; extern const struct iwl_cfg iwl6150_bg_cfg;
extern struct iwl_cfg iwl1000_bgn_cfg; extern const struct iwl_cfg iwl1000_bgn_cfg;
extern struct iwl_cfg iwl1000_bg_cfg; extern const struct iwl_cfg iwl1000_bg_cfg;
extern struct iwl_cfg iwl100_bgn_cfg; extern const struct iwl_cfg iwl100_bgn_cfg;
extern struct iwl_cfg iwl100_bg_cfg; extern const struct iwl_cfg iwl100_bg_cfg;
extern struct iwl_cfg iwl130_bgn_cfg; extern const struct iwl_cfg iwl130_bgn_cfg;
extern struct iwl_cfg iwl130_bg_cfg; extern const struct iwl_cfg iwl130_bg_cfg;
extern struct iwl_cfg iwl2000_2bgn_cfg; extern const struct iwl_cfg iwl2000_2bgn_cfg;
extern struct iwl_cfg iwl2000_2bgn_d_cfg; extern const struct iwl_cfg iwl2000_2bgn_d_cfg;
extern struct iwl_cfg iwl2030_2bgn_cfg; extern const struct iwl_cfg iwl2030_2bgn_cfg;
extern struct iwl_cfg iwl6035_2agn_cfg; extern const struct iwl_cfg iwl6035_2agn_cfg;
extern struct iwl_cfg iwl105_bgn_cfg; extern const struct iwl_cfg iwl105_bgn_cfg;
extern struct iwl_cfg iwl105_bgn_d_cfg; extern const struct iwl_cfg iwl105_bgn_d_cfg;
extern struct iwl_cfg iwl135_bgn_cfg; extern const struct iwl_cfg iwl135_bgn_cfg;
#endif /* __iwl_pci_h__ */ #endif /* __iwl_pci_h__ */

View File

@ -69,22 +69,9 @@
#ifndef __iwl_commands_h__ #ifndef __iwl_commands_h__
#define __iwl_commands_h__ #define __iwl_commands_h__
#include <linux/etherdevice.h>
#include <linux/ieee80211.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 { enum {
REPLY_ALIVE = 0x1, REPLY_ALIVE = 0x1,
@ -213,48 +200,6 @@ enum {
/* iwl_cmd_header flags value */ /* iwl_cmd_header flags value */
#define IWL_CMD_FAILED_MSK 0x40 #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 * iwlagn rate_n_flags bit fields
* *
@ -3151,8 +3096,6 @@ struct iwl_enhance_sensitivity_cmd {
*/ */
/* Phy calibration command for series */ /* 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 { enum {
IWL_PHY_CALIBRATE_DC_CMD = 8, IWL_PHY_CALIBRATE_DC_CMD = 8,
IWL_PHY_CALIBRATE_LO_CMD = 9, IWL_PHY_CALIBRATE_LO_CMD = 9,
@ -3161,11 +3104,8 @@ enum {
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18, 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 /* This enum defines the bitmap of various calibrations to enable in both
* init ucode and runtime ucode through CALIBRATION_CFG_CMD. * init ucode and runtime ucode through CALIBRATION_CFG_CMD.
*/ */
@ -3905,50 +3845,6 @@ struct iwlagn_wowlan_kek_kck_material_cmd {
__le64 replay_ctr; __le64 replay_ctr;
} __packed; } __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) * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
*/ */

View File

@ -41,7 +41,6 @@
#include "iwl-shared.h" #include "iwl-shared.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-wifi.h"
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 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 || if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); 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; return 0;
} }
@ -137,7 +136,7 @@ int iwl_init_geos(struct iwl_priv *priv)
sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
sband->n_bitrates = IWL_RATE_COUNT_LEGACY - 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, iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ); IEEE80211_BAND_5GHZ);
@ -147,7 +146,7 @@ int iwl_init_geos(struct iwl_priv *priv)
sband->bitrates = rates; sband->bitrates = rates;
sband->n_bitrates = IWL_RATE_COUNT_LEGACY; 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, iwl_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ); IEEE80211_BAND_2GHZ);
@ -202,18 +201,18 @@ int iwl_init_geos(struct iwl_priv *priv)
priv->tx_power_next = max_tx_power; priv->tx_power_next = max_tx_power;
if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && 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. " IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
"Please send your %s to maintainer.\n", "Please send your %s to maintainer.\n",
trans(priv)->hw_id_str); 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", IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_2GHZ].n_channels,
priv->bands[IEEE80211_BAND_5GHZ].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; return 0;
} }
@ -225,7 +224,7 @@ void iwl_free_geos(struct iwl_priv *priv)
{ {
kfree(priv->ieee_channels); kfree(priv->ieee_channels);
kfree(priv->ieee_rates); 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, 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; 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)); 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), le32_to_cpu(ctx->timing.beacon_init_val),
le16_to_cpu(ctx->timing.atim_window)); 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); 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]; 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; return;
if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
&priv->shrd->status))
ieee80211_chswitch_done(ctx->vif, is_success); ieee80211_chswitch_done(ctx->vif, is_success);
} }
@ -836,23 +834,26 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
unsigned long reload_jiffies; unsigned long reload_jiffies;
#ifdef CONFIG_IWLWIFI_DEBUG #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); iwl_print_rx_config_cmd(priv, IWL_RXON_CTX_BSS);
#endif #endif
/* uCode is no longer loaded. */
priv->ucode_loaded = false;
/* Set the FW error flag -- cleared on iwl_down */ /* Set the FW error flag -- cleared on iwl_down */
set_bit(STATUS_FW_ERROR, &priv->shrd->status); set_bit(STATUS_FW_ERROR, &priv->shrd->status);
/* Cancel currently queued command. */ /* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status); 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 /* Keep the restart process from trying to send host
* commands by clearing the ready bit */ * 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); wake_up(&trans(priv)->wait_command_queue);
if (!ondemand) { if (!ondemand) {
/* /*
@ -875,7 +876,7 @@ static void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
priv->reload_count = 0; 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) { if (iwlagn_mod_params.restart_fw) {
IWL_DEBUG_FW_ERRORS(priv, IWL_DEBUG_FW_ERRORS(priv,
"Restarting adapter due to uCode error.\n"); "Restarting adapter due to uCode error.\n");
@ -893,7 +894,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
bool defer; bool defer;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; 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) if (priv->tx_power_user_lmt == tx_power && !force)
return 0; return 0;
@ -913,7 +914,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL; return -EINVAL;
} }
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
return -EIO; return -EIO;
/* scan complete and commit_rxon use tx_power_next value, /* scan complete and commit_rxon use tx_power_next value,
@ -921,7 +922,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
priv->tx_power_next = tx_power; priv->tx_power_next = tx_power;
/* do not set tx power when scanning or channel changing */ /* 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)); memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
if (defer && !force) { if (defer && !force) {
IWL_DEBUG_INFO(priv, "Deferring tx power set\n"); IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
@ -959,7 +960,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n", IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active"); (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)) CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n"); IWL_ERR(priv, "failed to send BT Coex Config\n");
} }
@ -972,12 +973,12 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
}; };
if (flags & CMD_ASYNC) 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, CMD_ASYNC,
sizeof(struct iwl_statistics_cmd), sizeof(struct iwl_statistics_cmd),
&statistics_cmd); &statistics_cmd);
else else
return iwl_trans_send_cmd_pdu(trans(priv), REPLY_STATISTICS_CMD, return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
CMD_SYNC, CMD_SYNC,
sizeof(struct iwl_statistics_cmd), sizeof(struct iwl_statistics_cmd),
&statistics_cmd); &statistics_cmd);
@ -1004,7 +1005,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
{ {
u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; 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) { if (!priv->tx_traffic) {
priv->tx_traffic = priv->tx_traffic =
kzalloc(traffic_size, GFP_KERNEL); kzalloc(traffic_size, GFP_KERNEL);
@ -1012,7 +1013,7 @@ int iwl_alloc_traffic_mem(struct iwl_priv *priv)
return -ENOMEM; return -ENOMEM;
} }
} }
if (iwl_get_debug_level(priv->shrd) & IWL_DL_RX) { if (iwl_have_debug_level(IWL_DL_RX)) {
if (!priv->rx_traffic) { if (!priv->rx_traffic) {
priv->rx_traffic = priv->rx_traffic =
kzalloc(traffic_size, GFP_KERNEL); kzalloc(traffic_size, GFP_KERNEL);
@ -1039,7 +1040,7 @@ void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
__le16 fc; __le16 fc;
u16 len; u16 len;
if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_TX))) if (likely(!iwl_have_debug_level(IWL_DL_TX)))
return; return;
if (!priv->tx_traffic) if (!priv->tx_traffic)
@ -1063,7 +1064,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
__le16 fc; __le16 fc;
u16 len; u16 len;
if (likely(!(iwl_get_debug_level(priv->shrd) & IWL_DL_RX))) if (likely(!iwl_have_debug_level(IWL_DL_RX)))
return; return;
if (!priv->rx_traffic) if (!priv->rx_traffic)
@ -1220,7 +1221,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) 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; return;
if (!iwl_is_any_associated(priv)) { if (!iwl_is_any_associated(priv)) {
@ -1245,7 +1246,7 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
{ {
struct iwl_force_reset *force_reset; 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; return -EINVAL;
if (mode >= IWL_MAX_FORCE_RESET) { if (mode >= IWL_MAX_FORCE_RESET) {
@ -1301,7 +1302,7 @@ int iwl_cmd_echo_test(struct iwl_priv *priv)
.flags = CMD_SYNC, .flags = CMD_SYNC,
}; };
ret = iwl_trans_send_cmd(trans(priv), &cmd); ret = iwl_dvm_send_cmd(priv, &cmd);
if (ret) if (ret)
IWL_ERR(priv, "echo testing fail: 0X%x\n", ret); IWL_ERR(priv, "echo testing fail: 0X%x\n", ret);
else else
@ -1335,30 +1336,20 @@ void iwl_bg_watchdog(unsigned long data)
int cnt; int cnt;
unsigned long timeout; unsigned long timeout;
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
if (iwl_is_rfkill(priv->shrd)) if (iwl_is_rfkill(priv))
return; return;
timeout = cfg(priv)->base_params->wd_timeout; timeout = hw_params(priv).wd_timeout;
if (timeout == 0) if (timeout == 0)
return; return;
/* monitor and check for stuck cmd queue */ /* monitor and check for stuck queues */
if (iwl_check_stuck_queue(priv, priv->shrd->cmd_queue)) for (cnt = 0; cnt < cfg(priv)->base_params->num_of_queues; cnt++)
return; if (iwl_check_stuck_queue(priv, cnt))
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;
}
}
mod_timer(&priv->watchdog, jiffies + mod_timer(&priv->watchdog, jiffies +
msecs_to_jiffies(IWL_WD_TICK(timeout))); msecs_to_jiffies(IWL_WD_TICK(timeout)));
@ -1366,7 +1357,7 @@ void iwl_bg_watchdog(unsigned long data)
void iwl_setup_watchdog(struct iwl_priv *priv) 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) { if (!iwlagn_mod_params.wd_disable) {
/* use system default */ /* use system default */
@ -1471,34 +1462,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); 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) wiphy_rfkill_set_hw_state(priv->hw->wiphy, state);
{
cfg(priv)->lib->nic_config(priv);
} }
void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) 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; struct ieee80211_tx_info *info;
info = IEEE80211_SKB_CB(skb); 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); 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);
}

View File

@ -77,12 +77,6 @@ struct iwl_cmd;
struct iwl_lib_ops { struct iwl_lib_ops {
/* set hw dependent parameters */ /* set hw dependent parameters */
void (*set_hw_params)(struct iwl_priv *priv); 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, int (*set_channel_switch)(struct iwl_priv *priv,
struct ieee80211_channel_switch *ch_switch); struct ieee80211_channel_switch *ch_switch);
/* device specific configuration */ /* device specific configuration */
@ -95,72 +89,6 @@ struct iwl_lib_ops {
void (*temperature)(struct iwl_priv *priv); 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 * * 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_force_scan_end(struct iwl_priv *priv);
void iwl_internal_short_hw_scan(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); 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_rx_scan_handlers(struct iwl_priv *priv);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv); void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
void iwl_cancel_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) #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 * * S e n d i n g H o s t C o m m a n d s *
*****************************************************/ *****************************************************/

View File

@ -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) #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, u32 level, bool limit, const char *function,
const char *fmt, ...) const char *fmt, ...)
{ {
@ -116,7 +116,7 @@ void __iwl_dbg(struct iwl_shared *shared, struct device *dev,
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
#ifdef CONFIG_IWLWIFI_DEBUG #ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_get_debug_level(shared) & level && if (iwl_have_debug_level(level) &&
(!limit || net_ratelimit())) (!limit || net_ratelimit()))
dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U', dev_err(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
function, &vaf); function, &vaf);

View File

@ -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) #define IWL_CRIT(m, f, a...) __iwl_crit(trans(m)->dev, f, ## a)
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING) #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, u32 level, bool limit, const char *function,
const char *fmt, ...); const char *fmt, ...);
#else #else
static inline void static inline void
__iwl_dbg(struct iwl_shared *shared, struct device *dev, __iwl_dbg(struct device *dev,
u32 level, bool limit, const char *function, u32 level, bool limit, const char *function,
const char *fmt, ...) const char *fmt, ...)
{} {}
@ -65,35 +65,19 @@ do { \
} while (0) } while (0)
#define IWL_DEBUG(m, level, fmt, args...) \ #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...) \ #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 #ifdef CONFIG_IWLWIFI_DEBUG
#define iwl_print_hex_dump(m, level, p, len) \ #define iwl_print_hex_dump(m, level, p, len) \
do { \ do { \
if (iwl_get_debug_level((m)->shrd) & level) \ if (iwl_have_debug_level(level)) \
print_hex_dump(KERN_DEBUG, "iwl data: ", \ print_hex_dump(KERN_DEBUG, "iwl data: ", \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0) } 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 #else
#define iwl_print_hex_dump(m, level, p, len) #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 */ #endif /* CONFIG_IWLWIFI_DEBUG */
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS

View File

@ -40,7 +40,6 @@
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-wifi.h"
/* create and remove of files */ /* create and remove of files */
#define DEBUGFS_ADD_FILE(name, parent, mode) do { \ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \
@ -231,16 +230,18 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
int pos = 0; int pos = 0;
int sram; int sram;
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
const struct fw_img *img;
size_t bufsz; size_t bufsz;
/* default is to dump the entire data segment */ /* default is to dump the entire data segment */
if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) { if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
struct iwl_nic *nic = nic(priv);
priv->dbgfs_sram_offset = 0x800000; priv->dbgfs_sram_offset = 0x800000;
if (nic->shrd->ucode_type == IWL_UCODE_INIT) if (!priv->ucode_loaded) {
priv->dbgfs_sram_len = nic->fw.ucode_init.data.len; IWL_ERR(priv, "No uCode has been loadded.\n");
else return -EINVAL;
priv->dbgfs_sram_len = nic->fw.ucode_rt.data.len; }
img = &priv->fw->img[priv->shrd->ucode_type];
priv->dbgfs_sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
} }
len = priv->dbgfs_sram_len; len = priv->dbgfs_sram_len;
@ -337,13 +338,14 @@ static ssize_t iwl_dbgfs_wowlan_sram_read(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct iwl_priv *priv = file->private_data; struct iwl_priv *priv = file->private_data;
const struct fw_img *img = &priv->fw->img[IWL_UCODE_WOWLAN];
if (!priv->wowlan_sram) if (!priv->wowlan_sram)
return -ENODATA; return -ENODATA;
return simple_read_from_buffer(user_buf, count, ppos, return simple_read_from_buffer(user_buf, count, ppos,
priv->wowlan_sram, priv->wowlan_sram,
nic(priv)->fw.ucode_wowlan.data.len); img->sec[IWL_UCODE_SECTION_DATA].len);
} }
static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
@ -456,7 +458,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
char *buf; char *buf;
ssize_t ret; ssize_t ret;
if (!test_bit(STATUS_GEO_CONFIGURED, &priv->shrd->status)) if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -527,32 +529,26 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
test_bit(STATUS_HCMD_ACTIVE, &priv->shrd->status)); 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", 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", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_CT_KILL:\t\t %d\n",
test_bit(STATUS_CT_KILL, &priv->shrd->status)); test_bit(STATUS_CT_KILL, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n",
test_bit(STATUS_INIT, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", 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", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
test_bit(STATUS_READY, &priv->shrd->status)); test_bit(STATUS_READY, &priv->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
test_bit(STATUS_TEMPERATURE, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", 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", 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", 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", 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", 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", 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", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
test_bit(STATUS_POWER_PMI, &priv->shrd->status)); test_bit(STATUS_POWER_PMI, &priv->shrd->status));
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
@ -758,14 +754,14 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
return -EINVAL; return -EINVAL;
if (!iwl_is_ready_rf(priv->shrd)) if (!iwl_is_ready_rf(priv))
return -EAGAIN; return -EAGAIN;
priv->power_data.debug_sleep_level_override = value; priv->power_data.debug_sleep_level_override = value;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwl_power_update_mode(priv, true); iwl_power_update_mode(priv, true);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
return count; return count;
} }
@ -836,7 +832,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
char *buf; char *buf;
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + 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; const u8 *ptr;
ssize_t ret; ssize_t ret;
@ -845,8 +841,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
IWL_ERR(priv, "Can not allocate buffer\n"); IWL_ERR(priv, "Can not allocate buffer\n");
return -ENOMEM; return -ENOMEM;
} }
if (priv->tx_traffic && if (priv->tx_traffic && iwl_have_debug_level(IWL_DL_TX)) {
(iwl_get_debug_level(priv->shrd) & IWL_DL_TX)) {
ptr = priv->tx_traffic; ptr = priv->tx_traffic;
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"Tx Traffic idx: %u\n", priv->tx_traffic_idx); "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
@ -864,8 +859,7 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
} }
} }
if (priv->rx_traffic && if (priv->rx_traffic && iwl_have_debug_level(IWL_DL_RX)) {
(iwl_get_debug_level(priv->shrd) & IWL_DL_RX)) {
ptr = priv->rx_traffic; ptr = priv->rx_traffic;
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"Rx Traffic idx: %u\n", priv->rx_traffic_idx); "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
@ -920,6 +914,8 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
int p = 0; int p = 0;
u32 flag; u32 flag;
lockdep_assert_held(&priv->statistics.lock);
flag = le32_to_cpu(priv->statistics.flag); flag = le32_to_cpu(priv->statistics.flag);
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
@ -953,7 +949,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_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht; 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; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -967,6 +963,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
* the last statistics notification from uCode * the last statistics notification from uCode
* might not reflect the current uCode activity * might not reflect the current uCode activity
*/ */
spin_lock_bh(&priv->statistics.lock);
ofdm = &priv->statistics.rx_ofdm; ofdm = &priv->statistics.rx_ofdm;
cck = &priv->statistics.rx_cck; cck = &priv->statistics.rx_cck;
general = &priv->statistics.rx_non_phy; general = &priv->statistics.rx_non_phy;
@ -1363,6 +1360,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
accum_ht->unsupport_mcs, accum_ht->unsupport_mcs,
delta_ht->unsupport_mcs, max_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); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
@ -1379,7 +1378,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
ssize_t ret; ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx; struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
if (!iwl_is_alive(priv->shrd)) if (!iwl_is_alive(priv))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1392,6 +1391,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
* the last statistics notification from uCode * the last statistics notification from uCode
* might not reflect the current uCode activity * might not reflect the current uCode activity
*/ */
spin_lock_bh(&priv->statistics.lock);
tx = &priv->statistics.tx; tx = &priv->statistics.tx;
accum_tx = &priv->accum_stats.tx; accum_tx = &priv->accum_stats.tx;
delta_tx = &priv->delta_stats.tx; delta_tx = &priv->delta_stats.tx;
@ -1541,19 +1542,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) { if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"tx power: (1/2 dB step)\n"); "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, pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna A:", fmt_hex, "antenna A:",
tx->tx_power.ant_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, pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna B:", fmt_hex, "antenna B:",
tx->tx_power.ant_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, pos += scnprintf(buf + pos, bufsz - pos,
fmt_hex, "antenna C:", fmt_hex, "antenna C:",
tx->tx_power.ant_c); tx->tx_power.ant_c);
} }
spin_unlock_bh(&priv->statistics.lock);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
@ -1573,7 +1580,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_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div; struct statistics_div *div, *accum_div, *delta_div, *max_div;
if (!iwl_is_alive(priv->shrd)) if (!iwl_is_alive(priv))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -1586,6 +1593,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
* the last statistics notification from uCode * the last statistics notification from uCode
* might not reflect the current uCode activity * might not reflect the current uCode activity
*/ */
spin_lock_bh(&priv->statistics.lock);
general = &priv->statistics.common; general = &priv->statistics.common;
dbg = &priv->statistics.common.dbg; dbg = &priv->statistics.common.dbg;
div = &priv->statistics.common.div; div = &priv->statistics.common.div;
@ -1670,6 +1680,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
accum_general->num_of_sos_states, accum_general->num_of_sos_states,
delta_general->num_of_sos_states, delta_general->num_of_sos_states,
max_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); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
@ -1686,16 +1699,16 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
ssize_t ret; ssize_t ret;
struct statistics_bt_activity *bt, *accum_bt; struct statistics_bt_activity *bt, *accum_bt;
if (!iwl_is_alive(priv->shrd)) if (!iwl_is_alive(priv))
return -EAGAIN; return -EAGAIN;
if (!priv->bt_enable_flag) if (!priv->bt_enable_flag)
return -EINVAL; return -EINVAL;
/* make request to uCode to retrieve statistics information */ /* 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); ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
if (ret) { if (ret) {
IWL_ERR(priv, IWL_ERR(priv,
@ -1713,6 +1726,9 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
* the last statistics notification from uCode * the last statistics notification from uCode
* might not reflect the current uCode activity * might not reflect the current uCode activity
*/ */
spin_lock_bh(&priv->statistics.lock);
bt = &priv->statistics.bt_activity; bt = &priv->statistics.bt_activity;
accum_bt = &priv->accum_stats.bt_activity; accum_bt = &priv->accum_stats.bt_activity;
@ -1758,6 +1774,8 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
le32_to_cpu(priv->statistics.num_bt_kills), le32_to_cpu(priv->statistics.num_bt_kills),
priv->statistics.accum_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); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf); kfree(buf);
return ret; return ret;
@ -1774,7 +1792,7 @@ static ssize_t iwl_dbgfs_reply_tx_error_read(struct file *file,
(sizeof(struct reply_agg_tx_error_statistics) * 24) + 200; (sizeof(struct reply_agg_tx_error_statistics) * 24) + 200;
ssize_t ret; ssize_t ret;
if (!iwl_is_alive(priv->shrd)) if (!iwl_is_alive(priv))
return -EAGAIN; return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL); buf = kzalloc(bufsz, GFP_KERNEL);
@ -2086,9 +2104,9 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
return -EFAULT; return -EFAULT;
/* make request to uCode to retrieve statistics information */ /* 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); iwl_send_statistics_request(priv, CMD_SYNC, true);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
return count; return count;
} }
@ -2132,7 +2150,7 @@ static ssize_t iwl_dbgfs_ucode_tracing_write(struct file *file,
if (trace) { if (trace) {
priv->event_log.ucode_trace = true; priv->event_log.ucode_trace = true;
if (iwl_is_alive(priv->shrd)) { if (iwl_is_alive(priv)) {
/* start collecting data now */ /* start collecting data now */
mod_timer(&priv->ucode_trace, jiffies); mod_timer(&priv->ucode_trace, jiffies);
} }
@ -2221,7 +2239,7 @@ static ssize_t iwl_dbgfs_plcp_delta_read(struct file *file,
const size_t bufsz = sizeof(buf); const size_t bufsz = sizeof(buf);
pos += scnprintf(buf + pos, bufsz - pos, "%u\n", 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); return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
} }
@ -2243,10 +2261,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
return -EINVAL; return -EINVAL;
if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) || if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX)) (plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
cfg(priv)->base_params->plcp_delta_threshold = priv->plcp_delta_threshold =
IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE; IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
else else
cfg(priv)->base_params->plcp_delta_threshold = plcp; priv->plcp_delta_threshold = plcp;
return count; return count;
} }
@ -2322,7 +2340,7 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
if (sscanf(buf, "%d", &flush) != 1) if (sscanf(buf, "%d", &flush) != 1)
return -EINVAL; return -EINVAL;
if (iwl_is_rfkill(priv->shrd)) if (iwl_is_rfkill(priv))
return -EFAULT; return -EFAULT;
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL); iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
@ -2348,7 +2366,7 @@ static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT) if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
timeout = IWL_DEF_WD_TIMEOUT; timeout = IWL_DEF_WD_TIMEOUT;
cfg(priv)->base_params->wd_timeout = timeout; hw_params(priv).wd_timeout = timeout;
iwl_setup_watchdog(priv); iwl_setup_watchdog(priv);
return count; return count;
} }
@ -2411,7 +2429,7 @@ static ssize_t iwl_dbgfs_protection_mode_read(struct file *file,
if (cfg(priv)->ht_params) if (cfg(priv)->ht_params)
pos += scnprintf(buf + pos, bufsz - pos, pos += scnprintf(buf + pos, bufsz - pos,
"use %s for aggregation\n", "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"); "rts/cts" : "cts-to-self");
else else
pos += scnprintf(buf + pos, bufsz - pos, "N/A"); pos += scnprintf(buf + pos, bufsz - pos, "N/A");
@ -2438,9 +2456,9 @@ static ssize_t iwl_dbgfs_protection_mode_write(struct file *file,
if (sscanf(buf, "%d", &rts) != 1) if (sscanf(buf, "%d", &rts) != 1)
return -EINVAL; return -EINVAL;
if (rts) if (rts)
cfg(priv)->ht_params->use_rts_for_aggregation = true; hw_params(priv).use_rts_for_aggregation = true;
else else
cfg(priv)->ht_params->use_rts_for_aggregation = false; hw_params(priv).use_rts_for_aggregation = false;
return count; return count;
} }
@ -2486,52 +2504,6 @@ DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
DEBUGFS_READ_FILE_OPS(reply_tx_error); DEBUGFS_READ_FILE_OPS(reply_tx_error);
DEBUGFS_WRITE_FILE_OPS(echo_test); 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 * Create the debugfs files and directories
* *
@ -2596,9 +2568,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(echo_test, dir_debug, S_IWUSR);
if (iwl_advanced_bt_coexist(priv)) if (iwl_advanced_bt_coexist(priv))
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR); 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, DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
&priv->disable_sens_cal); &priv->disable_sens_cal);

View File

@ -36,11 +36,10 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <net/ieee80211_radiotap.h> #include <linux/mutex.h>
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-csr.h" #include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-debug.h" #include "iwl-debug.h"
#include "iwl-agn-hw.h" #include "iwl-agn-hw.h"
#include "iwl-led.h" #include "iwl-led.h"
@ -50,6 +49,7 @@
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-shared.h" #include "iwl-shared.h"
#include "iwl-op-mode.h" #include "iwl-op-mode.h"
#include "iwl-notif-wait.h"
struct iwl_tx_queue; struct iwl_tx_queue;
@ -294,7 +294,6 @@ struct iwl_vif_priv {
struct iwl_sensitivity_ranges { struct iwl_sensitivity_ranges {
u16 min_nrg_cck; u16 min_nrg_cck;
u16 max_nrg_cck;
u16 nrg_th_cck; u16 nrg_th_cck;
u16 nrg_th_ofdm; u16 nrg_th_ofdm;
@ -670,11 +669,6 @@ struct iwl_rxon_context {
bool enabled, is_40mhz; bool enabled, is_40mhz;
u8 extension_chan_offset; u8 extension_chan_offset;
} ht; } ht;
u8 bssid[ETH_ALEN];
bool preauth_bssid;
bool last_tx_rejected;
}; };
enum iwl_scan_type { enum iwl_scan_type {
@ -718,29 +712,44 @@ struct iwl_priv {
/*data shared among all the driver's layers */ /*data shared among all the driver's layers */
struct iwl_shared *shrd; 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 */ /* ieee device used by generic ieee processing code */
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels; struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates; struct ieee80211_rate *ieee_rates;
struct kmem_cache *tx_cmd_pool;
struct list_head calib_results;
struct workqueue_struct *workqueue; struct workqueue_struct *workqueue;
enum ieee80211_band band; enum ieee80211_band band;
void (*pre_rx_handler)(struct iwl_priv *priv, 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, 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_device_cmd *cmd);
struct iwl_notif_wait_data notif_wait;
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
/* spectrum measurement report caching */ /* spectrum measurement report caching */
struct iwl_spectrum_notification measure_report; struct iwl_spectrum_notification measure_report;
u8 measurement_status; u8 measurement_status;
#define IWL_OWNERSHIP_DRIVER 0
#define IWL_OWNERSHIP_TM 1
u8 ucode_owner;
/* ucode beacon time */ /* ucode beacon time */
u32 ucode_beacon_time; u32 ucode_beacon_time;
int missed_beacon_threshold; int missed_beacon_threshold;
@ -760,12 +769,16 @@ struct iwl_priv {
/* firmware reload counter and timestamp */ /* firmware reload counter and timestamp */
unsigned long reload_jiffies; unsigned long reload_jiffies;
int reload_count; int reload_count;
bool ucode_loaded;
bool init_ucode_run; /* Don't run init uCode again */
/* we allocate array of iwl_channel_info for NIC's valid channels. /* we allocate array of iwl_channel_info for NIC's valid channels.
* Access via channel # using indirect index array */ * Access via channel # using indirect index array */
struct iwl_channel_info *channel_info; /* channel info array */ struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */ u8 channel_count; /* # of channels */
u8 plcp_delta_threshold;
/* thermal calibration */ /* thermal calibration */
s32 temperature; /* Celsius */ s32 temperature; /* Celsius */
s32 last_temperature; s32 last_temperature;
@ -788,6 +801,8 @@ struct iwl_priv {
bool new_scan_threshold_behaviour; bool new_scan_threshold_behaviour;
bool wowlan;
/* EEPROM MAC addresses */ /* EEPROM MAC addresses */
struct mac_address addresses[2]; struct mac_address addresses[2];
@ -845,6 +860,7 @@ struct iwl_priv {
struct statistics_bt_activity bt_activity; struct statistics_bt_activity bt_activity;
__le32 num_bt_kills, accum_num_bt_kills; __le32 num_bt_kills, accum_num_bt_kills;
#endif #endif
spinlock_t lock;
} statistics; } statistics;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
struct { struct {
@ -968,6 +984,7 @@ struct iwl_priv {
bool have_rekey_data; bool have_rekey_data;
}; /*iwl_priv */ }; /*iwl_priv */
extern struct kmem_cache *iwl_tx_cmd_pool;
extern struct iwl_mod_params iwlagn_mod_params; extern struct iwl_mod_params iwlagn_mod_params;
static inline struct iwl_rxon_context * static inline struct iwl_rxon_context *

View File

@ -41,130 +41,134 @@ static inline void trace_ ## name(proto) {}
static inline void trace_ ## name(proto) {} static inline void trace_ ## name(proto) {}
#endif #endif
#define PRIV_ENTRY __field(void *, priv) #define DEV_ENTRY __string(dev, dev_name(dev))
#define PRIV_ASSIGN __entry->priv = priv #define DEV_ASSIGN __assign_str(dev, dev_name(dev))
#undef TRACE_SYSTEM #undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_io #define TRACE_SYSTEM iwlwifi_io
TRACE_EVENT(iwlwifi_dev_ioread32, TRACE_EVENT(iwlwifi_dev_ioread32,
TP_PROTO(void *priv, u32 offs, u32 val), TP_PROTO(const struct device *dev, u32 offs, u32 val),
TP_ARGS(priv, offs, val), TP_ARGS(dev, offs, val),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, offs) __field(u32, offs)
__field(u32, val) __field(u32, val)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->offs = offs; __entry->offs = offs;
__entry->val = val; __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, TRACE_EVENT(iwlwifi_dev_iowrite8,
TP_PROTO(void *priv, u32 offs, u8 val), TP_PROTO(const struct device *dev, u32 offs, u8 val),
TP_ARGS(priv, offs, val), TP_ARGS(dev, offs, val),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, offs) __field(u32, offs)
__field(u8, val) __field(u8, val)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->offs = offs; __entry->offs = offs;
__entry->val = val; __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, TRACE_EVENT(iwlwifi_dev_iowrite32,
TP_PROTO(void *priv, u32 offs, u32 val), TP_PROTO(const struct device *dev, u32 offs, u32 val),
TP_ARGS(priv, offs, val), TP_ARGS(dev, offs, val),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, offs) __field(u32, offs)
__field(u32, val) __field(u32, val)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->offs = offs; __entry->offs = offs;
__entry->val = val; __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, TRACE_EVENT(iwlwifi_dev_irq,
TP_PROTO(void *priv), TP_PROTO(const struct device *dev),
TP_ARGS(priv), TP_ARGS(dev),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
), ),
/* TP_printk("") doesn't compile */ /* TP_printk("") doesn't compile */
TP_printk("%d", 0) TP_printk("%d", 0)
); );
TRACE_EVENT(iwlwifi_dev_ict_read, TRACE_EVENT(iwlwifi_dev_ict_read,
TP_PROTO(void *priv, u32 index, u32 value), TP_PROTO(const struct device *dev, u32 index, u32 value),
TP_ARGS(priv, index, value), TP_ARGS(dev, index, value),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, index) __field(u32, index)
__field(u32, value) __field(u32, value)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->index = index; __entry->index = index;
__entry->value = value; __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 #undef TRACE_SYSTEM
#define TRACE_SYSTEM iwlwifi_ucode #define TRACE_SYSTEM iwlwifi_ucode
TRACE_EVENT(iwlwifi_dev_ucode_cont_event, TRACE_EVENT(iwlwifi_dev_ucode_cont_event,
TP_PROTO(void *priv, u32 time, u32 data, u32 ev), TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
TP_ARGS(priv, time, data, ev), TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, time) __field(u32, time)
__field(u32, data) __field(u32, data)
__field(u32, ev) __field(u32, ev)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->time = time; __entry->time = time;
__entry->data = data; __entry->data = data;
__entry->ev = ev; __entry->ev = ev;
), ),
TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
__entry->priv, __entry->time, __entry->data, __entry->ev) __get_str(dev), __entry->time, __entry->data, __entry->ev)
); );
TRACE_EVENT(iwlwifi_dev_ucode_wrap_event, TRACE_EVENT(iwlwifi_dev_ucode_wrap_event,
TP_PROTO(void *priv, u32 wraps, u32 n_entry, u32 p_entry), TP_PROTO(const struct device *dev, u32 wraps, u32 n_entry, u32 p_entry),
TP_ARGS(priv, wraps, n_entry, p_entry), TP_ARGS(dev, wraps, n_entry, p_entry),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, wraps) __field(u32, wraps)
__field(u32, n_entry) __field(u32, n_entry)
__field(u32, p_entry) __field(u32, p_entry)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->wraps = wraps; __entry->wraps = wraps;
__entry->n_entry = n_entry; __entry->n_entry = n_entry;
__entry->p_entry = p_entry; __entry->p_entry = p_entry;
), ),
TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X", TP_printk("[%s] wraps=#%02d n=0x%X p=0x%X",
__entry->priv, __entry->wraps, __entry->n_entry, __get_str(dev), __entry->wraps, __entry->n_entry,
__entry->p_entry) __entry->p_entry)
); );
@ -232,52 +236,52 @@ TRACE_EVENT(iwlwifi_dbg,
#define TRACE_SYSTEM iwlwifi #define TRACE_SYSTEM iwlwifi
TRACE_EVENT(iwlwifi_dev_hcmd, 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 *hcmd0, size_t len0,
const void *hcmd1, size_t len1, const void *hcmd1, size_t len1,
const void *hcmd2, size_t len2), 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( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__dynamic_array(u8, hcmd0, len0) __dynamic_array(u8, hcmd0, len0)
__dynamic_array(u8, hcmd1, len1) __dynamic_array(u8, hcmd1, len1)
__dynamic_array(u8, hcmd2, len2) __dynamic_array(u8, hcmd2, len2)
__field(u32, flags) __field(u32, flags)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
memcpy(__get_dynamic_array(hcmd0), hcmd0, len0); memcpy(__get_dynamic_array(hcmd0), hcmd0, len0);
memcpy(__get_dynamic_array(hcmd1), hcmd1, len1); memcpy(__get_dynamic_array(hcmd1), hcmd1, len1);
memcpy(__get_dynamic_array(hcmd2), hcmd2, len2); memcpy(__get_dynamic_array(hcmd2), hcmd2, len2);
__entry->flags = flags; __entry->flags = flags;
), ),
TP_printk("[%p] hcmd %#.2x (%ssync)", TP_printk("[%s] hcmd %#.2x (%ssync)",
__entry->priv, ((u8 *)__get_dynamic_array(hcmd0))[0], __get_str(dev), ((u8 *)__get_dynamic_array(hcmd0))[0],
__entry->flags & CMD_ASYNC ? "a" : "") __entry->flags & CMD_ASYNC ? "a" : "")
); );
TRACE_EVENT(iwlwifi_dev_rx, TRACE_EVENT(iwlwifi_dev_rx,
TP_PROTO(void *priv, void *rxbuf, size_t len), TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
TP_ARGS(priv, rxbuf, len), TP_ARGS(dev, rxbuf, len),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__dynamic_array(u8, rxbuf, len) __dynamic_array(u8, rxbuf, len)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
memcpy(__get_dynamic_array(rxbuf), rxbuf, len); memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
), ),
TP_printk("[%p] RX cmd %#.2x", TP_printk("[%s] RX cmd %#.2x",
__entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4]) __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
); );
TRACE_EVENT(iwlwifi_dev_tx, 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 *buf0, size_t buf0_len,
void *buf1, size_t buf1_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( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(size_t, framelen) __field(size_t, framelen)
__dynamic_array(u8, tfd, tfdlen) __dynamic_array(u8, tfd, tfdlen)
@ -291,29 +295,28 @@ TRACE_EVENT(iwlwifi_dev_tx,
__dynamic_array(u8, buf1, buf1_len) __dynamic_array(u8, buf1, buf1_len)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->framelen = buf0_len + buf1_len; __entry->framelen = buf0_len + buf1_len;
memcpy(__get_dynamic_array(tfd), tfd, tfdlen); memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
memcpy(__get_dynamic_array(buf0), buf0, buf0_len); memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
memcpy(__get_dynamic_array(buf1), buf1, buf1_len); memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
), ),
TP_printk("[%p] TX %.2x (%zu bytes)", TP_printk("[%s] TX %.2x (%zu bytes)",
__entry->priv, __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
((u8 *)__get_dynamic_array(buf0))[0],
__entry->framelen) __entry->framelen)
); );
TRACE_EVENT(iwlwifi_dev_ucode_error, 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 data1, u32 data2, u32 line, u32 blink1,
u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time, u32 blink2, u32 ilink1, u32 ilink2, u32 bcon_time,
u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver, u32 gp1, u32 gp2, u32 gp3, u32 ucode_ver, u32 hw_ver,
u32 brd_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, blink1, blink2, ilink1, ilink2, bcon_time, gp1, gp2,
gp3, ucode_ver, hw_ver, brd_ver), gp3, ucode_ver, hw_ver, brd_ver),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, desc) __field(u32, desc)
__field(u32, tsf_low) __field(u32, tsf_low)
__field(u32, data1) __field(u32, data1)
@ -332,7 +335,7 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
__field(u32, brd_ver) __field(u32, brd_ver)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->desc = desc; __entry->desc = desc;
__entry->tsf_low = tsf_low; __entry->tsf_low = tsf_low;
__entry->data1 = data1; __entry->data1 = data1;
@ -350,11 +353,11 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
__entry->hw_ver = hw_ver; __entry->hw_ver = hw_ver;
__entry->brd_ver = brd_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 " "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X "
"bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X " "bcon_tm %010u gp 0x%08X 0x%08X 0x%08X uCode 0x%08X "
"hw 0x%08X brd 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->data1,
__entry->data2, __entry->line, __entry->blink1, __entry->data2, __entry->line, __entry->blink1,
__entry->blink2, __entry->ilink1, __entry->ilink2, __entry->blink2, __entry->ilink1, __entry->ilink2,
@ -364,23 +367,23 @@ TRACE_EVENT(iwlwifi_dev_ucode_error,
); );
TRACE_EVENT(iwlwifi_dev_ucode_event, TRACE_EVENT(iwlwifi_dev_ucode_event,
TP_PROTO(void *priv, u32 time, u32 data, u32 ev), TP_PROTO(const struct device *dev, u32 time, u32 data, u32 ev),
TP_ARGS(priv, time, data, ev), TP_ARGS(dev, time, data, ev),
TP_STRUCT__entry( TP_STRUCT__entry(
PRIV_ENTRY DEV_ENTRY
__field(u32, time) __field(u32, time)
__field(u32, data) __field(u32, data)
__field(u32, ev) __field(u32, ev)
), ),
TP_fast_assign( TP_fast_assign(
PRIV_ASSIGN; DEV_ASSIGN;
__entry->time = time; __entry->time = time;
__entry->data = data; __entry->data = data;
__entry->ev = ev; __entry->ev = ev;
), ),
TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u", TP_printk("[%s] EVT_LOGT:%010u:0x%08x:%04u",
__entry->priv, __entry->time, __entry->data, __entry->ev) __get_str(dev), __entry->time, __entry->data, __entry->ev)
); );
#endif /* __IWLWIFI_DEVICE_TRACE */ #endif /* __IWLWIFI_DEVICE_TRACE */

View File

@ -61,33 +61,916 @@
* *
*****************************************************************************/ *****************************************************************************/
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include "iwl-drv.h" #include "iwl-drv.h"
#include "iwl-trans.h" #include "iwl-trans.h"
#include "iwl-wifi.h" #include "iwl-shared.h"
#include "iwl-op-mode.h" #include "iwl-op-mode.h"
#include "iwl-agn-hw.h"
/* 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;
};
/*
* struct fw_sec: Just for the image parsing proccess.
* For the fw storage we are using struct fw_desc.
*/
struct fw_sec {
const void *data; /* the sec data */
size_t size; /* section size */
u32 offset; /* offset of writing in the device */
};
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)
{
int i;
for (i = 0; i < IWL_UCODE_SECTION_MAX; i++)
iwl_free_fw_desc(drv, &img->sec[i]);
}
static void iwl_dealloc_ucode(struct iwl_drv *drv)
{
int i;
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
}
static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
struct fw_sec *sec)
{
if (!sec || !sec->size) {
desc->v_addr = NULL;
return -EINVAL;
}
desc->v_addr = dma_alloc_coherent(trans(drv)->dev, sec->size,
&desc->p_addr, GFP_KERNEL);
if (!desc->v_addr)
return -ENOMEM;
desc->len = sec->size;
desc->offset = sec->offset;
memcpy(desc->v_addr, sec->data, sec->size);
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 fw_img_parsing {
struct fw_sec sec[IWL_UCODE_SECTION_MAX];
int sec_counter;
};
/*
* struct fw_sec_parsing: to extract fw section and it's offset from tlv
*/
struct fw_sec_parsing {
__le32 offset;
const u8 data[];
} __packed;
/**
* struct iwl_tlv_calib_data - parse the default calib data from TLV
*
* @ucode_type: the uCode to which the following default calib relates.
* @calib: default calibrations.
*/
struct iwl_tlv_calib_data {
__le32 ucode_type;
__le64 calib;
} __packed;
struct iwl_firmware_pieces {
struct fw_img_parsing img[IWL_UCODE_TYPE_MAX];
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
};
/*
* These functions are just to extract uCode section data from the pieces
* structure.
*/
static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec)
{
return &pieces->img[type].sec[sec];
}
static void set_sec_data(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec,
const void *data)
{
pieces->img[type].sec[sec].data = data;
}
static void set_sec_size(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec,
size_t size)
{
pieces->img[type].sec[sec].size = size;
}
static size_t get_sec_size(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec)
{
return pieces->img[type].sec[sec].size;
}
static void set_sec_offset(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec,
u32 offset)
{
pieces->img[type].sec[sec].offset = offset;
}
/*
* Gets uCode section from tlv.
*/
static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
const void *data, enum iwl_ucode_type type,
int size)
{
struct fw_img_parsing *img;
struct fw_sec *sec;
struct fw_sec_parsing *sec_parse;
if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
return -1;
sec_parse = (struct fw_sec_parsing *)data;
img = &pieces->img[type];
sec = &img->sec[img->sec_counter];
sec->offset = le32_to_cpu(sec_parse->offset);
sec->data = sec_parse->data;
++img->sec_counter;
return 0;
}
static int iwl_set_default_calib(struct iwl_drv *drv, const u8 *data)
{
struct iwl_tlv_calib_data *def_calib =
(struct iwl_tlv_calib_data *)data;
u32 ucode_type = le32_to_cpu(def_calib->ucode_type);
if (ucode_type >= IWL_UCODE_TYPE_MAX) {
IWL_ERR(drv, "Wrong ucode_type %u for default calibration.\n",
ucode_type);
return -EINVAL;
}
drv->fw.default_calib[ucode_type] = le64_to_cpu(def_calib->calib);
return 0;
}
static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_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);
set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
le32_to_cpu(ucode->u.v2.inst_size));
set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
le32_to_cpu(ucode->u.v2.data_size));
set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
le32_to_cpu(ucode->u.v2.init_size));
set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
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;
set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
le32_to_cpu(ucode->u.v1.inst_size));
set_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
le32_to_cpu(ucode->u.v1.data_size));
set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
le32_to_cpu(ucode->u.v1.init_size));
set_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
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 +
get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) +
get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) +
get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) +
get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA)) {
IWL_ERR(drv,
"uCode file size %d does not match expected size\n",
(int)ucode_raw->size);
return -EINVAL;
}
set_sec_data(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST, src);
src += get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST);
set_sec_offset(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST,
IWLAGN_RTC_INST_LOWER_BOUND);
set_sec_data(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA, src);
src += get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA);
set_sec_offset(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA,
IWLAGN_RTC_DATA_LOWER_BOUND);
set_sec_data(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST, src);
src += get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST);
set_sec_offset(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST,
IWLAGN_RTC_INST_LOWER_BOUND);
set_sec_data(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA, src);
src += get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA);
set_sec_offset(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA,
IWLAGN_RTC_DATA_LOWER_BOUND);
return 0;
}
static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
const struct firmware *ucode_raw,
struct iwl_firmware_pieces *pieces,
struct iwl_ucode_capabilities *capa)
{
struct iwl_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:
set_sec_data(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST, tlv_data);
set_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST, tlv_len);
set_sec_offset(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST,
IWLAGN_RTC_INST_LOWER_BOUND);
break;
case IWL_UCODE_TLV_DATA:
set_sec_data(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA, tlv_data);
set_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA, tlv_len);
set_sec_offset(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA,
IWLAGN_RTC_DATA_LOWER_BOUND);
break;
case IWL_UCODE_TLV_INIT:
set_sec_data(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_INST, tlv_data);
set_sec_size(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_INST, tlv_len);
set_sec_offset(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_INST,
IWLAGN_RTC_INST_LOWER_BOUND);
break;
case IWL_UCODE_TLV_INIT_DATA:
set_sec_data(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_DATA, tlv_data);
set_sec_size(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_DATA, tlv_len);
set_sec_offset(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_DATA,
IWLAGN_RTC_DATA_LOWER_BOUND);
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:
set_sec_data(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_INST, tlv_data);
set_sec_size(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_INST, tlv_len);
set_sec_offset(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_INST,
IWLAGN_RTC_INST_LOWER_BOUND);
break;
case IWL_UCODE_TLV_WOWLAN_DATA:
set_sec_data(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_DATA, tlv_data);
set_sec_size(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_DATA, tlv_len);
set_sec_offset(pieces, IWL_UCODE_WOWLAN,
IWL_UCODE_SECTION_DATA,
IWLAGN_RTC_DATA_LOWER_BOUND);
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;
case IWL_UCODE_TLV_SEC_RT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.mvm_fw = true;
break;
case IWL_UCODE_TLV_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len);
drv->fw.mvm_fw = true;
break;
case IWL_UCODE_TLV_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len);
drv->fw.mvm_fw = true;
break;
case IWL_UCODE_TLV_DEF_CALIB:
if (tlv_len != sizeof(struct iwl_tlv_calib_data))
goto invalid_tlv_len;
if (iwl_set_default_calib(drv, tlv_data))
goto tlv_error;
break;
case IWL_UCODE_TLV_PHY_SKU:
if (tlv_len != sizeof(u32))
goto invalid_tlv_len;
drv->fw.phy_config = 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);
tlv_error:
iwl_print_hex_dump(drv, IWL_DL_FW, tlv_data, tlv_len);
return -EINVAL;
}
static int alloc_pci_desc(struct iwl_drv *drv,
struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type)
{
int i;
for (i = 0;
i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i);
i++)
if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]),
get_sec(pieces, type, i)))
return -1;
return 0;
}
static int validate_sec_sizes(struct iwl_drv *drv,
struct iwl_firmware_pieces *pieces,
const struct iwl_cfg *cfg)
{
IWL_DEBUG_INFO(drv, "f/w package hdr runtime inst size = %Zd\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST));
IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA));
IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST));
IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA));
/* Verify that uCode images will fit in card's SRAM. */
if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) >
cfg->max_inst_size) {
IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST));
return -1;
}
if (get_sec_size(pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) >
cfg->max_data_size) {
IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA));
return -1;
}
if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST) >
cfg->max_inst_size) {
IWL_ERR(drv, "uCode init instr len %Zd too large to fit in\n",
get_sec_size(pieces, IWL_UCODE_INIT,
IWL_UCODE_SECTION_INST));
return -1;
}
if (get_sec_size(pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA) >
cfg->max_data_size) {
IWL_ERR(drv, "uCode init data len %Zd too large to fit in\n",
get_sec_size(pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA));
return -1;
}
return 0;
}
/**
* 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 iwl_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;
int i;
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",
get_sec_size(&pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST));
IWL_DEBUG_INFO(drv, "f/w package hdr runtime data size = %Zd\n",
get_sec_size(&pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA));
IWL_DEBUG_INFO(drv, "f/w package hdr init inst size = %Zd\n",
get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_INST));
IWL_DEBUG_INFO(drv, "f/w package hdr init data size = %Zd\n",
get_sec_size(&pieces, IWL_UCODE_INIT, IWL_UCODE_SECTION_DATA));
/* Verify that uCode images will fit in card's SRAM */
if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_INST) >
cfg->max_inst_size) {
IWL_ERR(drv, "uCode instr len %Zd too large to fit in\n",
get_sec_size(&pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_INST));
goto try_again;
}
if (get_sec_size(&pieces, IWL_UCODE_REGULAR, IWL_UCODE_SECTION_DATA) >
cfg->max_data_size) {
IWL_ERR(drv, "uCode data len %Zd too large to fit in\n",
get_sec_size(&pieces, IWL_UCODE_REGULAR,
IWL_UCODE_SECTION_DATA));
goto try_again;
}
/*
* In mvm uCode there is no difference between data and instructions
* sections.
*/
if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, cfg))
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 */
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
if (alloc_pci_desc(drv, &pieces, i))
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, 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)
{ {
struct iwl_drv *drv;
int ret; int ret;
shrd->cfg = cfg; shrd->cfg = cfg;
shrd->nic = kzalloc(sizeof(*shrd->nic), GFP_KERNEL); drv = kzalloc(sizeof(*drv), GFP_KERNEL);
if (!shrd->nic) { if (!drv) {
dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_nic"); dev_printk(KERN_ERR, trans->dev, "Couldn't allocate iwl_drv");
return -ENOMEM; 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) { if (ret) {
dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw"); dev_printk(KERN_ERR, trans->dev, "Couldn't request the fw");
kfree(shrd->nic); kfree(drv);
shrd->drv = NULL;
} }
return ret; return ret;
@ -95,9 +978,16 @@ int iwl_drv_start(struct iwl_shared *shrd,
void iwl_drv_stop(struct iwl_shared *shrd) void iwl_drv_stop(struct iwl_shared *shrd)
{ {
/* op_mode can be NULL if its start failed */ struct iwl_drv *drv = shrd->drv;
if (shrd->nic->op_mode)
iwl_op_mode_stop(shrd->nic->op_mode);
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;
} }

View File

@ -105,7 +105,7 @@
* function. * function.
*/ */
int iwl_drv_start(struct iwl_shared *shrd, 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 * iwl_drv_stop - stop the drv

View File

@ -75,6 +75,7 @@
#include "iwl-agn.h" #include "iwl-agn.h"
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-io.h" #include "iwl-io.h"
#include "iwl-prph.h"
/************************** EEPROM BANDS **************************** /************************** EEPROM BANDS ****************************
* *
@ -252,46 +253,46 @@ err:
} }
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; struct iwl_shared *shrd = priv->shrd;
u16 radio_cfg; u16 radio_cfg;
if (!cfg(priv)->sku) { hw_params(priv).sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP);
/* not using sku overwrite */ if (hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE &&
cfg(priv)->sku = iwl_eeprom_query16(shrd, EEPROM_SKU_CAP); !cfg(priv)->ht_params) {
if (cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE && IWL_ERR(priv, "Invalid 11n configuration\n");
!cfg(priv)->ht_params) { return -EINVAL;
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"); IWL_ERR(priv, "Invalid device sku\n");
return -EINVAL; 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) { radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG);
/* not using .cfg overwrite */
radio_cfg = iwl_eeprom_query16(shrd, EEPROM_RADIO_CONFIG); hw_params(priv).valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
cfg(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);
cfg(priv)->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
if (!cfg(priv)->valid_tx_ant || !cfg(priv)->valid_rx_ant) { /* check overrides (some devices have wrong EEPROM) */
IWL_ERR(priv, "Invalid chain (0x%X, 0x%X)\n", if (cfg(priv)->valid_tx_ant)
cfg(priv)->valid_tx_ant, hw_params(priv).valid_tx_ant = cfg(priv)->valid_tx_ant;
cfg(priv)->valid_rx_ant); if (cfg(priv)->valid_rx_ant)
return -EINVAL; hw_params(priv).valid_rx_ant = cfg(priv)->valid_rx_ant;
}
IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n", if (!hw_params(priv).valid_tx_ant || !hw_params(priv).valid_rx_ant) {
cfg(priv)->valid_tx_ant, cfg(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, IWL_INFO(priv, "Valid Tx ant: 0x%X, Valid Rx ant: 0x%X\n",
* EEPROM did not reflect the correct antenna setting hw_params(priv).valid_tx_ant, hw_params(priv).valid_rx_ant);
* so overwrite the valid tx/rx antenna from .cfg
*/
return 0; 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. * iwl_get_max_txpower_avg - get the highest tx power from all chains.
* find the highest tx power from all chains for the channel * 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, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
int element, s8 *max_txpower_in_half_dbm) 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) \ #define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
? # 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_shared *shrd = priv->shrd;
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp; 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 * driver need to process addition information
* to determine the max channel tx power limits * to determine the max channel tx power limits
*/ */
if (cfg(priv)->lib->eeprom_ops.update_enhanced_txpower) if (cfg(priv)->lib->eeprom_ops.enhanced_txpower)
cfg(priv)->lib->eeprom_ops.update_enhanced_txpower(priv); iwl_eeprom_enhanced_txpower(priv);
return 0; return 0;
} }

View File

@ -302,14 +302,14 @@ extern const u8 iwl_eeprom_band_1[14];
struct iwl_eeprom_ops { struct iwl_eeprom_ops {
const u32 regulatory_bands[7]; 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); int iwl_eeprom_init(struct iwl_trans *trans, u32 hw_rev);
void iwl_eeprom_free(struct iwl_shared *shrd); void iwl_eeprom_free(struct iwl_shared *shrd);
int iwl_eeprom_check_version(struct iwl_priv *priv); 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); 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); u16 iwl_eeprom_query16(const struct iwl_shared *shrd, size_t offset);
int iwl_init_channel_map(struct iwl_priv *priv); int iwl_init_channel_map(struct iwl_priv *priv);

View File

@ -60,8 +60,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef __iwl_ucode_h__ #ifndef __iwl_fw_file_h__
#define __iwl_ucode_h__ #define __iwl_fw_file_h__
#include <linux/netdevice.h> #include <linux/netdevice.h>
@ -124,22 +124,11 @@ enum iwl_ucode_tlv_type {
IWL_UCODE_TLV_WOWLAN_INST = 16, IWL_UCODE_TLV_WOWLAN_INST = 16,
IWL_UCODE_TLV_WOWLAN_DATA = 17, IWL_UCODE_TLV_WOWLAN_DATA = 17,
IWL_UCODE_TLV_FLAGS = 18, IWL_UCODE_TLV_FLAGS = 18,
}; IWL_UCODE_TLV_SEC_RT = 19,
IWL_UCODE_TLV_SEC_INIT = 20,
/** IWL_UCODE_TLV_SEC_WOWLAN = 21,
* enum iwl_ucode_tlv_flag - ucode API flags IWL_UCODE_TLV_DEF_CALIB = 22,
* @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously IWL_UCODE_TLV_PHY_SKU = 23,
* 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 { struct iwl_ucode_tlv {
@ -173,48 +162,4 @@ struct iwl_tlv_ucode_header {
u8 data[0]; u8 data[0];
}; };
struct iwl_ucode_capabilities { #endif /* __iwl_fw_file_h__ */
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__ */

View File

@ -60,52 +60,118 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*****************************************************************************/ *****************************************************************************/
#ifndef __iwl_wifi_h__ #ifndef __iwl_fw_h__
#define __iwl_wifi_h__ #define __iwl_fw_h__
#include <linux/types.h>
#include "iwl-shared.h"
#include "iwl-ucode.h"
#define UCODE_EXPERIMENTAL_INDEX 100
/** /**
* struct iwl_nic - nic common data * enum iwl_ucode_tlv_flag - ucode API flags
* @fw: the iwl_fw structure * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
* @shrd: pointer to common shared structure * was a separate TLV but moved here to save space.
* @op_mode: the running op_mode * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
* @fw_index: firmware revision to try loading * treats good CRC threshold as a boolean
* @firmware_name: composite filename of ucode file to load * @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
/**
* enum iwl_ucode_type
*
* The type of ucode.
*
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
IWL_UCODE_TYPE_MAX,
};
/*
* enumeration of ucode section.
* This enumeration is used for legacy tlv style (before 16.0 uCode).
*/
enum iwl_ucode_sec {
IWL_UCODE_SECTION_INST,
IWL_UCODE_SECTION_DATA,
};
/*
* For 16.0 uCode and above, there is no differentiation between sections,
* just an offset to the HW address.
*/
#define IWL_UCODE_SECTION_MAX 4
struct iwl_ucode_capabilities {
u32 max_probe_length;
u32 standard_phy_calibration_size;
u32 flags;
};
/* one for each uCode image (inst/data, init/runtime/wowlan) */
struct fw_desc {
dma_addr_t p_addr; /* hardware address */
void *v_addr; /* software address */
u32 len; /* size in bytes */
u32 offset; /* offset in the device */
};
struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX];
};
/* 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
* @img: ucode image like ucode_rt, ucode_init, ucode_wowlan.
* @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_ptr: event log offset for init ucode.
* @init_evtlog_size: event log size for init ucode. * @init_evtlog_size: event log size for init ucode.
* @init_errlog_ptr: error log offfset for init ucode. * @init_errlog_ptr: error log offfset for init ucode.
* @inst_evtlog_ptr: event log offset for runtime ucode. * @inst_evtlog_ptr: event log offset for runtime ucode.
* @inst_evtlog_size: event log size for runtime ucode. * @inst_evtlog_size: event log size for runtime ucode.
* @inst_errlog_ptr: error log offfset 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 {
struct iwl_fw fw; u32 ucode_ver;
struct iwl_shared *shrd; char fw_version[ETHTOOL_BUSINFO_LEN];
struct iwl_op_mode *op_mode;
int fw_index; /* firmware we're trying to load */ /* ucode images */
char firmware_name[25]; /* name of firmware file to load */ struct fw_img img[IWL_UCODE_TYPE_MAX];
struct iwl_ucode_capabilities ucode_capa;
bool enhance_sensitivity_table;
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
struct completion request_firmware_complete; u64 default_calib[IWL_UCODE_TYPE_MAX];
u32 phy_config;
bool mvm_fw;
}; };
#endif /* __iwl_fw_h__ */
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__ */

View File

@ -118,16 +118,17 @@ int iwl_grab_nic_access_silent(struct iwl_trans *trans)
return 0; 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); int ret = iwl_grab_nic_access_silent(trans);
if (ret) { if (unlikely(ret)) {
u32 val = iwl_read32(trans, CSR_GP_CNTRL); u32 val = iwl_read32(trans, CSR_GP_CNTRL);
IWL_ERR(trans, WARN_ONCE(1, "Timeout waiting for hardware access "
"MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); "(CSR_GP_CNTRL 0x%08x)\n", val);
return false;
} }
return ret; return true;
} }
void iwl_release_nic_access(struct iwl_trans *trans) 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); lockdep_assert_held(&trans->reg_lock);
__iwl_clear_bit(trans, CSR_GP_CNTRL, __iwl_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 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) 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; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, 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_write32(trans, reg, value);
iwl_release_nic_access(trans); 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) static inline u32 __iwl_read_prph(struct iwl_trans *trans, u32 reg)
{ {
iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); iwl_write32(trans, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
rmb();
return iwl_read32(trans, HBUS_TARG_PRPH_RDAT); 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, iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24))); ((addr & 0x0000FFFF) | (3 << 24)));
wmb();
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val); 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; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, 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_write_prph(trans, addr, val);
iwl_release_nic_access(trans); 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; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans); if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, reg, __iwl_read_prph(trans, reg) | mask); __iwl_write_prph(trans, reg,
iwl_release_nic_access(trans); __iwl_read_prph(trans, reg) | mask);
iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags); 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; unsigned long flags;
spin_lock_irqsave(&trans->reg_lock, flags); spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans); if (likely(iwl_grab_nic_access(trans))) {
__iwl_write_prph(trans, reg, __iwl_write_prph(trans, reg,
(__iwl_read_prph(trans, reg) & mask) | bits); (__iwl_read_prph(trans, reg) & mask) | bits);
iwl_release_nic_access(trans); iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags); 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; u32 val;
spin_lock_irqsave(&trans->reg_lock, flags); spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans); if (likely(iwl_grab_nic_access(trans))) {
val = __iwl_read_prph(trans, reg); val = __iwl_read_prph(trans, reg);
__iwl_write_prph(trans, reg, (val & ~mask)); __iwl_write_prph(trans, reg, (val & ~mask));
iwl_release_nic_access(trans); iwl_release_nic_access(trans);
}
spin_unlock_irqrestore(&trans->reg_lock, flags); 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; u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags); spin_lock_irqsave(&trans->reg_lock, flags);
iwl_grab_nic_access(trans); if (likely(iwl_grab_nic_access(trans))) {
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr); for (offs = 0; offs < words; offs++)
rmb(); vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(trans);
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); 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; u32 *vals = buf;
spin_lock_irqsave(&trans->reg_lock, flags); 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); iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
wmb();
for (offs = 0; offs < words; offs++) for (offs = 0; offs < words; offs++)
iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]); iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
iwl_release_nic_access(trans); iwl_release_nic_access(trans);

View File

@ -35,20 +35,20 @@
static inline void iwl_write8(struct iwl_trans *trans, u32 ofs, u8 val) 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); iwl_trans_write8(trans, ofs, val);
} }
static inline void iwl_write32(struct iwl_trans *trans, u32 ofs, u32 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); iwl_trans_write32(trans, ofs, val);
} }
static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs) static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
{ {
u32 val = iwl_trans_read32(trans, 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; return val;
} }
@ -61,7 +61,7 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
int timeout); int timeout);
int iwl_grab_nic_access_silent(struct iwl_trans *trans); 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); void iwl_release_nic_access(struct iwl_trans *trans);
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg); u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);

View File

@ -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, iwl_write32(trans(priv), CSR_LED_REG,
reg & CSR_LED_BSM_CTRL_MSK); 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 */ /* Set led pattern command */
@ -126,7 +126,7 @@ static int iwl_led_cmd(struct iwl_priv *priv,
}; };
int ret; int ret;
if (!test_bit(STATUS_READY, &priv->shrd->status)) if (!test_bit(STATUS_READY, &priv->status))
return -EBUSY; return -EBUSY;
if (priv->blink_on == on && priv->blink_off == off) if (priv->blink_on == on && priv->blink_off == off)

View File

@ -42,9 +42,7 @@
#include <asm/div64.h> #include <asm/div64.h>
#include "iwl-ucode.h"
#include "iwl-eeprom.h" #include "iwl-eeprom.h"
#include "iwl-wifi.h"
#include "iwl-dev.h" #include "iwl-dev.h"
#include "iwl-core.h" #include "iwl-core.h"
#include "iwl-io.h" #include "iwl-io.h"
@ -136,7 +134,7 @@ iwlagn_iface_combinations_p2p[] = {
* other mac80211 functions grouped here. * other mac80211 functions grouped here.
*/ */
int iwlagn_mac_setup_register(struct iwl_priv *priv, int iwlagn_mac_setup_register(struct iwl_priv *priv,
struct iwl_ucode_capabilities *capa) const struct iwl_ucode_capabilities *capa)
{ {
int ret; int ret;
struct ieee80211_hw *hw = priv->hw; 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 | hw->flags |= IEEE80211_HW_SUPPORTS_PS |
IEEE80211_HW_SUPPORTS_DYNAMIC_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 | hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_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) if (capa->flags & IWL_UCODE_TLV_FLAGS_MFP)
#endif /* !CONFIG_IWLWIFI_EXPERIMENTAL_MFP */
hw->flags |= IEEE80211_HW_MFP_CAPABLE; hw->flags |= IEEE80211_HW_MFP_CAPABLE;
hw->sta_data_size = sizeof(struct iwl_station_priv); 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_DISABLE_BEACON_HINTS |
WIPHY_FLAG_IBSS_RSN; WIPHY_FLAG_IBSS_RSN;
if (nic(priv)->fw.ucode_wowlan.code.len && if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
trans(priv)->ops->wowlan_suspend &&
device_can_wakeup(trans(priv)->dev)) { device_can_wakeup(trans(priv)->dev)) {
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_DISCONNECT |
@ -262,9 +264,9 @@ static int __iwl_up(struct iwl_priv *priv)
struct iwl_rxon_context *ctx; struct iwl_rxon_context *ctx;
int ret; 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"); IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
return -EIO; 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) { if (ret) {
IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret); IWL_ERR(priv, "Failed to run INIT ucode: %d\n", ret);
goto error; 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) { if (ret) {
IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret); IWL_ERR(priv, "Failed to start RT ucode: %d\n", ret);
goto error; goto error;
@ -295,9 +297,9 @@ static int __iwl_up(struct iwl_priv *priv)
return 0; return 0;
error: error:
set_bit(STATUS_EXIT_PENDING, &priv->shrd->status); set_bit(STATUS_EXIT_PENDING, &priv->status);
iwl_down(priv); 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"); IWL_ERR(priv, "Unable to initialize device.\n");
return ret; return ret;
@ -311,16 +313,16 @@ static int iwlagn_mac_start(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
/* we should be verifying the device is ready to be opened */ /* we should be verifying the device is ready to be opened */
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
ret = __iwl_up(priv); ret = __iwl_up(priv);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
if (ret) if (ret)
return ret; return ret;
IWL_DEBUG_INFO(priv, "Start UP work done.\n"); IWL_DEBUG_INFO(priv, "Start UP work done.\n");
/* Now we should be done, and the READY bit should be set. */ /* 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; ret = -EIO;
iwlagn_led_enable(priv); iwlagn_led_enable(priv);
@ -341,9 +343,9 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
priv->is_open = 0; priv->is_open = 0;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwl_down(priv); iwl_down(priv);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
iwl_cancel_deferred_work(priv); iwl_cancel_deferred_work(priv);
@ -368,7 +370,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
return; return;
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif) if (priv->contexts[IWL_RXON_CTX_BSS].vif != vif)
goto out; goto out;
@ -380,7 +382,7 @@ static void iwlagn_mac_set_rekey_data(struct ieee80211_hw *hw,
priv->have_rekey_data = true; priv->have_rekey_data = true;
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
@ -397,7 +399,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
return -EINVAL; return -EINVAL;
IWL_DEBUG_MAC80211(priv, "enter\n"); 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. */ /* Don't attempt WoWLAN when not associated, tear down instead. */
if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION || if (!ctx->vif || ctx->vif->type != NL80211_IFTYPE_STATION ||
@ -406,24 +408,22 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
goto out; goto out;
} }
ret = iwlagn_suspend(priv, hw, wowlan); ret = iwlagn_suspend(priv, wowlan);
if (ret) if (ret)
goto error; goto error;
device_set_wakeup_enable(trans(priv)->dev, true); device_set_wakeup_enable(trans(priv)->dev, true);
/* Now let the ucode operate on its own */ iwl_trans_wowlan_suspend(trans(priv));
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
goto out; goto out;
error: error:
priv->shrd->wowlan = false; priv->wowlan = false;
iwlagn_prepare_restart(priv); iwlagn_prepare_restart(priv);
ieee80211_restart_hw(priv->hw); ieee80211_restart_hw(priv->hw);
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return ret; return ret;
@ -437,9 +437,10 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
unsigned long flags; unsigned long flags;
u32 base, status = 0xffffffff; u32 base, status = 0xffffffff;
int ret = -EIO; int ret = -EIO;
const struct fw_img *img;
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR, iwl_write32(trans(priv), CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE); CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
@ -448,7 +449,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
if (iwlagn_hw_valid_rtc_data_addr(base)) { if (iwlagn_hw_valid_rtc_data_addr(base)) {
spin_lock_irqsave(&trans(priv)->reg_lock, flags); spin_lock_irqsave(&trans(priv)->reg_lock, flags);
ret = iwl_grab_nic_access_silent(trans(priv)); ret = iwl_grab_nic_access_silent(trans(priv));
if (ret == 0) { if (likely(ret == 0)) {
iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base); iwl_write32(trans(priv), HBUS_TARG_MEM_RADDR, base);
status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT); status = iwl_read32(trans(priv), HBUS_TARG_MEM_RDAT);
iwl_release_nic_access(trans(priv)); iwl_release_nic_access(trans(priv));
@ -457,17 +458,18 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
if (ret == 0) { if (ret == 0) {
struct iwl_nic *nic = nic(priv); img = &(priv->fw->img[IWL_UCODE_WOWLAN]);
if (!priv->wowlan_sram) if (!priv->wowlan_sram) {
priv->wowlan_sram = priv->wowlan_sram =
kzalloc(nic->fw.ucode_wowlan.data.len, kzalloc(img->sec[IWL_UCODE_SECTION_DATA].len,
GFP_KERNEL); GFP_KERNEL);
}
if (priv->wowlan_sram) if (priv->wowlan_sram)
_iwl_read_targ_mem_words( _iwl_read_targ_mem_words(
trans(priv), 0x800000, trans(priv), 0x800000,
priv->wowlan_sram, priv->wowlan_sram,
nic->fw.ucode_wowlan.data.len / 4); img->sec[IWL_UCODE_SECTION_DATA].len / 4);
} }
#endif #endif
} }
@ -475,7 +477,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
/* we'll clear ctx->vif during iwlagn_prepare_restart() */ /* we'll clear ctx->vif during iwlagn_prepare_restart() */
vif = ctx->vif; vif = ctx->vif;
priv->shrd->wowlan = false; priv->wowlan = false;
device_set_wakeup_enable(trans(priv)->dev, false); device_set_wakeup_enable(trans(priv)->dev, false);
@ -485,7 +487,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
iwl_connection_init_rx_config(priv, ctx); iwl_connection_init_rx_config(priv, ctx);
iwlagn_set_rxon_chain(priv, ctx); iwlagn_set_rxon_chain(priv, ctx);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
ieee80211_resume_disconnect(vif); ieee80211_resume_disconnect(vif);
@ -563,7 +565,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) if (cmd == DISABLE_KEY && key->hw_key_idx == WEP_INVALID_OFFSET)
return 0; return 0;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, 100); iwl_scan_cancel_timeout(priv, 100);
BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT); BUILD_BUG_ON(WEP_INVALID_OFFSET == IWLAGN_HW_KEY_DEFAULT);
@ -614,7 +616,7 @@ static int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
ret = -EINVAL; ret = -EINVAL;
} }
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return ret; return ret;
@ -633,11 +635,11 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
sta->addr, tid); sta->addr, tid);
if (!(cfg(priv)->sku & EEPROM_SKU_CAP_11N_ENABLE)) if (!(hw_params(priv).sku & EEPROM_SKU_CAP_11N_ENABLE))
return -EACCES; return -EACCES;
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
switch (action) { switch (action) {
case IEEE80211_AMPDU_RX_START: case IEEE80211_AMPDU_RX_START:
@ -649,8 +651,6 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP: case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT(priv, "stop Rx\n"); IWL_DEBUG_HT(priv, "stop Rx\n");
ret = iwl_sta_rx_agg_stop(priv, sta, tid); ret = iwl_sta_rx_agg_stop(priv, sta, tid);
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
ret = 0;
break; break;
case IEEE80211_AMPDU_TX_START: case IEEE80211_AMPDU_TX_START:
if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG) if (iwlagn_mod_params.disable_11n & IWL_DISABLE_HT_TXAGG)
@ -666,10 +666,8 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n", IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
priv->agg_tids_count); priv->agg_tids_count);
} }
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status)) if (!priv->agg_tids_count &&
ret = 0; hw_params(priv).use_rts_for_aggregation) {
if (!priv->agg_tids_count && cfg(priv)->ht_params &&
cfg(priv)->ht_params->use_rts_for_aggregation) {
/* /*
* switch off RTS/CTS if it was previously enabled * switch off RTS/CTS if it was previously enabled
*/ */
@ -683,7 +681,7 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size); ret = iwlagn_tx_agg_oper(priv, vif, sta, tid, buf_size);
break; break;
} }
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return ret; return ret;
} }
@ -696,12 +694,9 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
bool is_ap = vif->type == NL80211_IFTYPE_STATION; bool is_ap = vif->type == NL80211_IFTYPE_STATION;
int ret = 0; int ret;
u8 sta_id; 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", IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
sta->addr); sta->addr);
sta_priv->sta_id = IWL_INVALID_STATION; sta_priv->sta_id = IWL_INVALID_STATION;
@ -716,17 +711,119 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
IWL_ERR(priv, "Unable to add station %pM (%d)\n", IWL_ERR(priv, "Unable to add station %pM (%d)\n",
sta->addr, ret); sta->addr, ret);
/* Should we return success if return code is EEXIST ? */ /* Should we return success if return code is EEXIST ? */
goto out; return ret;
} }
sta_priv->sta_id = sta_id; sta_priv->sta_id = sta_id;
/* Initialize rate scaling */ return 0;
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", }
sta->addr);
iwl_rs_rate_init(priv, sta, sta_id); static int iwlagn_mac_sta_remove(struct ieee80211_hw *hw,
out: struct ieee80211_vif *vif,
mutex_unlock(&priv->shrd->mutex); 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"); IWL_DEBUG_MAC80211(priv, "leave\n");
return ret; return ret;
@ -753,14 +850,14 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n"); 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; goto out;
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) || if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
test_bit(STATUS_SCANNING, &priv->shrd->status) || test_bit(STATUS_SCANNING, &priv->status) ||
test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status)) test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
goto out; goto out;
if (!iwl_is_associated_ctx(ctx)) if (!iwl_is_associated_ctx(ctx))
@ -779,8 +876,6 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
goto out; goto out;
} }
spin_lock_irq(&priv->shrd->lock);
priv->current_ht_config.smps = conf->smps_mode; priv->current_ht_config.smps = conf->smps_mode;
/* Configure HT40 channels */ /* Configure HT40 channels */
@ -797,23 +892,21 @@ static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
iwl_set_rxon_ht(priv, ht_conf); iwl_set_rxon_ht(priv, ht_conf);
iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif); iwl_set_flags_for_band(priv, ctx, channel->band, ctx->vif);
spin_unlock_irq(&priv->shrd->lock);
iwl_set_rate(priv); iwl_set_rate(priv);
/* /*
* at this point, staging_rxon has the * at this point, staging_rxon has the
* configuration for channel switch * 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); priv->switch_channel = cpu_to_le16(ch);
if (cfg(priv)->lib->set_channel_switch(priv, ch_switch)) { 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; priv->switch_channel = 0;
ieee80211_chswitch_done(ctx->vif, false); ieee80211_chswitch_done(ctx->vif, false);
} }
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
@ -843,7 +936,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
#undef CHK #undef CHK
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
for_each_context(priv, ctx) { for_each_context(priv, ctx) {
ctx->staging.filter_flags &= ~filter_nand; ctx->staging.filter_flags &= ~filter_nand;
@ -855,7 +948,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 * Receiving all multicast frames is always enabled by the
@ -871,14 +964,14 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n"); 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"); IWL_DEBUG_TX(priv, "Aborting flush due to device shutdown\n");
goto done; goto done;
} }
if (iwl_is_rfkill(priv->shrd)) { if (iwl_is_rfkill(priv)) {
IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n"); IWL_DEBUG_TX(priv, "Aborting flush due to RF Kill\n");
goto done; goto done;
} }
@ -897,7 +990,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n"); IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
iwl_trans_wait_tx_queue_empty(trans(priv)); iwl_trans_wait_tx_queue_empty(trans(priv));
done: done:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
@ -917,9 +1010,9 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
return -EOPNOTSUPP; return -EOPNOTSUPP;
IWL_DEBUG_MAC80211(priv, "enter\n"); 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; err = -EBUSY;
goto out; goto out;
} }
@ -988,7 +1081,7 @@ static int iwlagn_mac_remain_on_channel(struct ieee80211_hw *hw,
iwlagn_disable_roc(priv); iwlagn_disable_roc(priv);
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return err; return err;
@ -1002,102 +1095,22 @@ static int iwlagn_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
return -EOPNOTSUPP; return -EOPNOTSUPP;
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwl_scan_cancel_timeout(priv, priv->hw_roc_duration); iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
iwlagn_disable_roc(priv); iwlagn_disable_roc(priv);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return 0; 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, static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event) enum ieee80211_rssi_event rssi_event)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (cfg(priv)->bt_params && if (cfg(priv)->bt_params &&
cfg(priv)->bt_params->advanced_bt_coexist) { cfg(priv)->bt_params->advanced_bt_coexist) {
@ -1112,7 +1125,7 @@ static void iwlagn_mac_rssi_callback(struct ieee80211_hw *hw,
"ignoring RSSI callback\n"); "ignoring RSSI callback\n");
} }
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
@ -1133,7 +1146,6 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
struct iwl_rxon_context *ctx = vif_priv->ctx; struct iwl_rxon_context *ctx = vif_priv->ctx;
unsigned long flags;
int q; int q;
if (WARN_ON(!ctx)) if (WARN_ON(!ctx))
@ -1141,7 +1153,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n"); 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"); IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
return -EIO; return -EIO;
} }
@ -1153,7 +1165,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
q = AC_NUM - 1 - queue; 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 = ctx->qos_data.def_qos_parm.ac[q].cw_min =
cpu_to_le16(params->cw_min); cpu_to_le16(params->cw_min);
@ -1165,7 +1177,7 @@ static int iwlagn_mac_conf_tx(struct ieee80211_hw *hw,
ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0; 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"); IWL_DEBUG_MAC80211(priv, "leave\n");
return 0; return 0;
@ -1193,7 +1205,7 @@ static int iwl_setup_interface(struct iwl_priv *priv,
struct ieee80211_vif *vif = ctx->vif; struct ieee80211_vif *vif = ctx->vif;
int err; int err;
lockdep_assert_held(&priv->shrd->mutex); lockdep_assert_held(&priv->mutex);
/* /*
* This variable will be correct only when there's just * This variable will be correct only when there's just
@ -1238,11 +1250,11 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
cancel_delayed_work_sync(&priv->hw_roc_disable_work); cancel_delayed_work_sync(&priv->hw_roc_disable_work);
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
iwlagn_disable_roc(priv); 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"); IWL_WARN(priv, "Try to add interface when device not ready\n");
err = -EINVAL; err = -EINVAL;
goto out; goto out;
@ -1285,7 +1297,7 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
ctx->vif = NULL; ctx->vif = NULL;
priv->iw_mode = NL80211_IFTYPE_STATION; priv->iw_mode = NL80211_IFTYPE_STATION;
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return err; return err;
@ -1297,7 +1309,7 @@ static void iwl_teardown_interface(struct iwl_priv *priv,
{ {
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif); 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) { if (priv->scan_vif == vif) {
iwl_scan_cancel_timeout(priv, 200); iwl_scan_cancel_timeout(priv, 200);
@ -1329,7 +1341,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
if (WARN_ON(ctx->vif != vif)) { if (WARN_ON(ctx->vif != vif)) {
struct iwl_rxon_context *tmp; struct iwl_rxon_context *tmp;
@ -1342,7 +1354,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
iwl_teardown_interface(priv, vif, false); iwl_teardown_interface(priv, vif, false);
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
@ -1364,9 +1376,9 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
newtype = ieee80211_iftype_p2p(newtype, newp2p); 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 * Huh? But wait ... this can maybe happen when
* we're in the middle of a firmware restart! * we're in the middle of a firmware restart!
@ -1428,7 +1440,7 @@ static int iwlagn_mac_change_interface(struct ieee80211_hw *hw,
err = 0; err = 0;
out: out:
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
return err; return err;
@ -1446,7 +1458,7 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
if (req->n_channels == 0) if (req->n_channels == 0)
return -EINVAL; return -EINVAL;
mutex_lock(&priv->shrd->mutex); mutex_lock(&priv->mutex);
/* /*
* If an internal scan is in progress, just set * If an internal scan is in progress, just set
@ -1475,47 +1487,20 @@ static int iwlagn_mac_hw_scan(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
mutex_unlock(&priv->shrd->mutex); mutex_unlock(&priv->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");
return ret; return ret;
} }
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{ {
unsigned long flags; struct iwl_addsta_cmd cmd = {
.mode = STA_CONTROL_MODIFY_MSK,
spin_lock_irqsave(&priv->shrd->sta_lock, flags); .station_flags_msk = STA_FLG_PWR_SAVE_MSK,
priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; .sta.sta_id = sta_id,
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);
iwl_send_add_sta(priv, &cmd, CMD_ASYNC);
} }
static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw, static void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
@ -1572,8 +1557,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
.ampdu_action = iwlagn_mac_ampdu_action, .ampdu_action = iwlagn_mac_ampdu_action,
.hw_scan = iwlagn_mac_hw_scan, .hw_scan = iwlagn_mac_hw_scan,
.sta_notify = iwlagn_mac_sta_notify, .sta_notify = iwlagn_mac_sta_notify,
.sta_add = iwlagn_mac_sta_add, .sta_state = iwlagn_mac_sta_state,
.sta_remove = iwlagn_mac_sta_remove,
.channel_switch = iwlagn_mac_channel_switch, .channel_switch = iwlagn_mac_channel_switch,
.flush = iwlagn_mac_flush, .flush = iwlagn_mac_flush,
.tx_last_beacon = iwlagn_mac_tx_last_beacon, .tx_last_beacon = iwlagn_mac_tx_last_beacon,
@ -1582,8 +1566,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
.rssi_callback = iwlagn_mac_rssi_callback, .rssi_callback = iwlagn_mac_rssi_callback,
CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd) CFG80211_TESTMODE_CMD(iwlagn_mac_testmode_cmd)
CFG80211_TESTMODE_DUMP(iwlagn_mac_testmode_dump) 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, .set_tim = iwlagn_mac_set_tim,
}; };

View 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(&notif_wait->notif_wait_lock);
INIT_LIST_HEAD(&notif_wait->notif_waits);
init_waitqueue_head(&notif_wait->notif_waitq);
}
void iwl_notification_wait_notify(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt)
{
if (!list_empty(&notif_wait->notif_waits)) {
struct iwl_notification_wait *w;
spin_lock(&notif_wait->notif_wait_lock);
list_for_each_entry(w, &notif_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(&notif_wait->notif_wait_lock);
wake_up_all(&notif_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(&notif_wait->notif_wait_lock, flags);
list_for_each_entry(wait_entry, &notif_wait->notif_waits, list)
wait_entry->aborted = true;
spin_unlock_irqrestore(&notif_wait->notif_wait_lock, flags);
wake_up_all(&notif_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(&notif_wait->notif_wait_lock);
list_add(&wait_entry->list, &notif_wait->notif_waits);
spin_unlock_bh(&notif_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(&notif_wait->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&notif_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(&notif_wait->notif_wait_lock);
list_del(&wait_entry->list);
spin_unlock_bh(&notif_wait->notif_wait_lock);
}

View File

@ -41,7 +41,6 @@
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in * notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution. * distribution.
* * Neither the name Intel Corporation nor the names of its * * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived * 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. * 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" #include "iwl-trans.h"
int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id, struct iwl_notif_wait_data {
u32 flags, u16 len, const void *data) struct list_head notif_waits;
{ spinlock_t notif_wait_lock;
struct iwl_host_cmd cmd = { wait_queue_head_t notif_waitq;
.id = id, };
.len = { len, },
.data = { data, },
.flags = flags,
};
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__ */

View File

@ -67,7 +67,8 @@ struct iwl_op_mode;
struct iwl_trans; struct iwl_trans;
struct sk_buff; struct sk_buff;
struct iwl_device_cmd; struct iwl_device_cmd;
struct iwl_rx_mem_buffer; struct iwl_rx_cmd_buffer;
struct iwl_fw;
/** /**
* DOC: Operational mode - what is it ? * DOC: Operational mode - what is it ?
@ -121,17 +122,23 @@ struct iwl_rx_mem_buffer;
* there are Tx packets pending in the transport layer. * there are Tx packets pending in the transport layer.
* Must be atomic * Must be atomic
* @nic_error: error notification. 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_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); 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); struct iwl_device_cmd *cmd);
void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac); void (*queue_full)(struct iwl_op_mode *op_mode, u8 ac);
void (*queue_not_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 (*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 (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
void (*nic_error)(struct iwl_op_mode *op_mode); 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, 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) struct iwl_device_cmd *cmd)
{ {
return op_mode->ops->rx(op_mode, rxb, 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); 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 * Op mode layers implementations
******************************************************/ ******************************************************/

View File

@ -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) 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_shared *shrd;
struct iwl_trans *iwl_trans; struct iwl_trans *iwl_trans;
int err; 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 #ifdef CONFIG_IWLWIFI_IDI
iwl_trans = iwl_trans_idi_alloc(shrd, pdev, ent); 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 #else
iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent); iwl_trans = iwl_trans_pcie_alloc(shrd, pdev, ent);
#endif
if (iwl_trans == NULL) { if (iwl_trans == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto out_free_bus; 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); pci_set_drvdata(pdev, iwl_trans);
err = iwl_drv_start(shrd, iwl_trans, cfg); err = iwl_drv_start(shrd, iwl_trans, cfg);
#endif
if (err) if (err)
goto out_free_trans; goto out_free_trans;

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