aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43legacy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43legacy')
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig12
-rw-r--r--drivers/net/wireless/b43legacy/Makefile2
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h150
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c13
-rw-r--r--drivers/net/wireless/b43legacy/dma.c734
-rw-r--r--drivers/net/wireless/b43legacy/dma.h133
-rw-r--r--drivers/net/wireless/b43legacy/ilt.c2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c24
-rw-r--r--drivers/net/wireless/b43legacy/leds.h2
-rw-r--r--drivers/net/wireless/b43legacy/main.c1365
-rw-r--r--drivers/net/wireless/b43legacy/main.h2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c68
-rw-r--r--drivers/net/wireless/b43legacy/phy.h2
-rw-r--r--drivers/net/wireless/b43legacy/pio.c68
-rw-r--r--drivers/net/wireless/b43legacy/pio.h18
-rw-r--r--drivers/net/wireless/b43legacy/radio.c44
-rw-r--r--drivers/net/wireless/b43legacy/radio.h2
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c180
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h54
-rw-r--r--drivers/net/wireless/b43legacy/sysfs.c4
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c189
-rw-r--r--drivers/net/wireless/b43legacy/xmit.h16
22 files changed, 1424 insertions, 1660 deletions
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 13c65faf024..1ffa28835c5 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -1,9 +1,8 @@
config B43LEGACY
tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
- depends on SSB_POSSIBLE && MAC80211 && WLAN_80211
+ depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
select SSB
select FW_LOADER
- select HW_RANDOM
---help---
b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the
@@ -43,12 +42,11 @@ config B43LEGACY_LEDS
depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
default y
-# RFKILL support
-# This config option automatically enables b43legacy RFKILL support,
-# if it's possible.
-config B43LEGACY_RFKILL
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43LEGACY_HWRNG
bool
- depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
+ depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY)
default y
config B43LEGACY_DEBUG
diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile
index 80cdb73bd14..227a77e8436 100644
--- a/drivers/net/wireless/b43legacy/Makefile
+++ b/drivers/net/wireless/b43legacy/Makefile
@@ -6,7 +6,7 @@ b43legacy-y += radio.o
b43legacy-y += sysfs.o
b43legacy-y += xmit.o
# b43 RFKILL button support
-b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o
+b43legacy-y += rfkill.o
# b43legacy LED support
b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
# b43legacy debugging
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 93d45b71799..482476fdb1f 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -8,13 +8,13 @@
#include <linux/stringify.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include <linux/io.h>
#include <linux/ssb/ssb.h>
#include <linux/ssb/ssb_driver_chipcommon.h>
+#include <linux/completion.h>
-#include <linux/wireless.h>
#include <net/mac80211.h>
#include "debugfs.h"
@@ -23,14 +23,8 @@
#include "phy.h"
-/* The unique identifier of the firmware that's officially supported by this
- * driver version. */
-#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10"
-
#define B43legacy_IRQWAIT_MAX_RETRIES 20
-#define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */
-
/* MMIO offsets */
#define B43legacy_MMIO_DMA0_REASON 0x20
#define B43legacy_MMIO_DMA0_IRQ_MASK 0x24
@@ -59,7 +53,8 @@
#define B43legacy_MMIO_XMITSTAT_1 0x174
#define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
#define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
-
+#define B43legacy_MMIO_TSF_CFP_REP 0x188
+#define B43legacy_MMIO_TSF_CFP_START 0x18C
/* 32-bit DMA */
#define B43legacy_MMIO_DMA32_BASE0 0x200
#define B43legacy_MMIO_DMA32_BASE1 0x220
@@ -97,6 +92,7 @@
#define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A
#define B43legacy_MMIO_GPIO_CONTROL 0x49C
#define B43legacy_MMIO_GPIO_MASK 0x49E
+#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612
#define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */
#define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */
@@ -130,19 +126,31 @@
#define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */
/* SHM_SHARED crypto engine */
#define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */
-/* SHM_SHARED beacon variables */
+/* SHM_SHARED beacon/AP variables */
+#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */
+#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
+#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
+#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
+#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */
#define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */
/* SHM_SHARED ACK/CTS control */
#define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */
/* SHM_SHARED probe response variables */
-#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
+#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */
#define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
+#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
/* SHM_SHARED rate tables */
+#define B43legacy_SHM_SH_OFDMDIRECT 0x0480 /* Pointer to OFDM direct map */
+#define B43legacy_SHM_SH_OFDMBASIC 0x04A0 /* Pointer to OFDM basic rate map */
+#define B43legacy_SHM_SH_CCKDIRECT 0x04C0 /* Pointer to CCK direct map */
+#define B43legacy_SHM_SH_CCKBASIC 0x04E0 /* Pointer to CCK basic rate map */
/* SHM_SHARED microcode soft registers */
#define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
#define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
#define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */
#define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */
+#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */
+#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */
#define B43legacy_UCODEFLAGS_OFFSET 0x005E
@@ -199,6 +207,13 @@
#define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */
#define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */
+/* MAC Command bitfield */
+#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */
+#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */
+#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
+#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */
+#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */
+
/* 802.11 core specific TM State Low flags */
#define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */
@@ -238,7 +253,6 @@
#define B43legacy_IRQ_ALL 0xFFFFFFFF
#define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \
- B43legacy_IRQ_BEACON | \
B43legacy_IRQ_TBTT_INDI | \
B43legacy_IRQ_ATIM_END | \
B43legacy_IRQ_PMQ | \
@@ -317,15 +331,7 @@ enum {
# undef assert
#endif
#ifdef CONFIG_B43LEGACY_DEBUG
-# define B43legacy_WARN_ON(expr) \
- do { \
- if (unlikely((expr))) { \
- printk(KERN_INFO PFX "Test (%s) failed at:" \
- " %s:%d:%s()\n", \
- #expr, __FILE__, \
- __LINE__, __FUNCTION__); \
- } \
- } while (0)
+# define B43legacy_WARN_ON(x) WARN_ON(x)
# define B43legacy_BUG_ON(expr) \
do { \
if (unlikely((expr))) { \
@@ -336,7 +342,9 @@ enum {
} while (0)
# define B43legacy_DEBUG 1
#else
-# define B43legacy_WARN_ON(x) do { /* nothing */ } while (0)
+/* This will evaluate the argument even if debugging is disabled. */
+static inline bool __b43legacy_warn_on_dummy(bool x) { return x; }
+# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x)))
# define B43legacy_BUG_ON(x) do { /* nothing */ } while (0)
# define B43legacy_DEBUG 0
#endif
@@ -360,7 +368,7 @@ struct b43legacy_fw_header {
/* Size of the data. For ucode and PCM this is in bytes.
* For IV this is number-of-ivs. */
__be32 size;
-} __attribute__((__packed__));
+} __packed;
/* Initial Value file format */
#define B43legacy_IV_OFFSET_MASK 0x7FFF
@@ -370,8 +378,8 @@ struct b43legacy_iv {
union {
__be16 d16;
__be32 d32;
- } data __attribute__((__packed__));
-} __attribute__((__packed__));
+ } data __packed;
+} __packed;
#define B43legacy_PHYMODE(phytype) (1 << (phytype))
#define B43legacy_PHYMODE_B B43legacy_PHYMODE \
@@ -392,10 +400,6 @@ struct b43legacy_phy {
u8 possible_phymodes;
/* GMODE bit enabled in MACCTL? */
bool gmode;
- /* Possible ieee80211 subsystem hwmodes for this PHY.
- * Which mode is selected, depends on thr GMODE enabled bit */
-#define B43legacy_MAX_PHYHWMODES 2
- struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES];
/* Analog Type */
u8 analog;
@@ -480,7 +484,7 @@ struct b43legacy_phy {
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
- * Each value in the stack is layed out as follows:
+ * Each value in the stack is laid out as follows:
* bit 0-11: offset
* bit 12-15: register ID
* bit 16-32: value
@@ -524,6 +528,8 @@ struct b43legacy_dma {
struct b43legacy_dmaring *rx_ring0;
struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */
+
+ u32 translation; /* Routing bits */
};
/* Data structures for PIO transmission, per 80211 core. */
@@ -555,8 +561,16 @@ struct b43legacy_key {
u8 algorithm;
};
+#define B43legacy_QOS_QUEUE_NUM 4
+
struct b43legacy_wldev;
+/* QOS parameters for a queue. */
+struct b43legacy_qos_params {
+ /* The QOS parameters */
+ struct ieee80211_tx_queue_params p;
+};
+
/* Data structure for the WLAN parts (802.11 cores) of the b43legacy chip. */
struct b43legacy_wl {
/* Pointer to the active wireless device on this chip */
@@ -568,6 +582,9 @@ struct b43legacy_wl {
struct mutex mutex; /* locks wireless core state */
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)
* at a time. General information about this interface follows.
*/
@@ -586,18 +603,38 @@ struct b43legacy_wl {
/* Stats about the wireless interface */
struct ieee80211_low_level_stats ieee_stats;
+#ifdef CONFIG_B43LEGACY_HWRNG
struct hwrng rng;
u8 rng_initialized;
char rng_name[30 + 1];
-
- /* The RF-kill button */
- struct b43legacy_rfkill rfkill;
+#endif
/* List of all wireless devices on this chip */
struct list_head devlist;
u8 nr_devs;
bool radiotap_enabled;
+ bool radio_enabled;
+
+ /* The beacon we are currently using (AP or IBSS mode).
+ * This beacon stuff is protected by the irq_lock. */
+ struct sk_buff *current_beacon;
+ bool beacon0_uploaded;
+ bool beacon1_uploaded;
+ bool beacon_templates_virgin; /* Never wrote the templates? */
+ struct work_struct beacon_update_trigger;
+ /* The current QOS parameters for the 4 queues. */
+ struct b43legacy_qos_params qos_params[B43legacy_QOS_QUEUE_NUM];
+
+ /* Packet transmit work */
+ struct work_struct tx_work;
+
+ /* Queue of packets to be transmitted. */
+ struct sk_buff_head tx_queue[B43legacy_QOS_QUEUE_NUM];
+
+ /* Flag that implement the queues stopping. */
+ bool tx_queue_stopped[B43legacy_QOS_QUEUE_NUM];
+
};
/* Pointers to the firmware data and meta information about it. */
@@ -649,9 +686,8 @@ struct b43legacy_wldev {
bool __using_pio; /* Using pio rather than dma. */
bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
- bool reg124_set_0x4; /* Variable to keep track of IRQ. */
+ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
bool short_preamble; /* TRUE if using short preamble. */
- bool short_slot; /* TRUE if using short slot timing. */
bool radio_hw_enable; /* State of radio hardware enable bit. */
/* PHY/Radio device. */
@@ -675,8 +711,8 @@ struct b43legacy_wldev {
/* Reason code of the last interrupt. */
u32 irq_reason;
u32 dma_reason[6];
- /* saved irq enable/disable state bitfield. */
- u32 irq_savedstate;
+ /* The currently active generic-interrupt mask. */
+ u32 irq_mask;
/* Link Quality calculation context. */
struct b43legacy_noise_calculation noisecalc;
/* if > 0 MAC is suspended. if == 0 MAC is enabled. */
@@ -696,11 +732,12 @@ struct b43legacy_wldev {
u8 max_nr_keys;
struct b43legacy_key key[58];
- /* Cached beacon template while uploading the template. */
- struct sk_buff *cached_beacon;
-
/* Firmware data */
struct b43legacy_firmware fw;
+ const struct firmware *fwp; /* needed to pass fw pointer */
+
+ /* completion struct for firmware loading */
+ struct completion fw_load_complete;
/* Devicelist in struct b43legacy_wl (all 802.11 cores) */
struct list_head list;
@@ -801,36 +838,19 @@ struct b43legacy_lopair *b43legacy_get_lopair(struct b43legacy_phy *phy,
/* Message printing */
-void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
-void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...);
+__printf(2, 3)
+void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...);
#if B43legacy_DEBUG
-void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
- __attribute__((format(printf, 2, 3)));
+__printf(2, 3)
+void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...);
#else /* DEBUG */
# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0)
#endif /* DEBUG */
-
-/** Limit a value between two limits */
-#ifdef limit_value
-# undef limit_value
-#endif
-#define limit_value(value, min, max) \
- ({ \
- typeof(value) __value = (value); \
- typeof(value) __min = (min); \
- typeof(value) __max = (max); \
- if (__value < __min) \
- __value = __min; \
- else if (__value > __max) \
- __value = __max; \
- __value; \
- })
-
/* Macros for printing a value in Q5.2 format */
#define Q52_FMT "%u.%u"
#define Q52_ARG(q52) ((q52) / 4), (((q52) & 3) * 100 / 4)
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 03ce0821a60..1965edb765a 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -4,7 +4,7 @@
debugfs driver debugging code
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
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
@@ -197,12 +197,6 @@ static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size
#undef fappend
-static int b43legacy_debugfs_open(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
@@ -211,7 +205,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
struct b43legacy_dfs_file *dfile;
ssize_t uninitialized_var(ret);
char *buf;
- const size_t bufsize = 1024 * 128;
+ const size_t bufsize = 1024 * 16; /* 16 KiB buffer */
const size_t buforder = get_order(bufsize);
int err = 0;
@@ -331,9 +325,10 @@ out_unlock:
.read = _read, \
.write = _write, \
.fops = { \
- .open = b43legacy_debugfs_open, \
+ .open = simple_open, \
.read = b43legacy_debugfs_read, \
.write = b43legacy_debugfs_write, \
+ .llseek = generic_file_llseek, \
}, \
.file_struct_offset = offsetof(struct b43legacy_dfsentry, \
file_##name), \
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index e87b427d5e4..b2ed1795130 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -4,7 +4,7 @@
DMA ringbuffer and descriptor allocation/management
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Some code in this file is derived from the b44.c driver
Copyright (C) 2002 David S. Miller
@@ -37,14 +37,14 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
+#include <linux/slab.h>
#include <net/dst.h>
/* 32bit DMA ops. */
static
-struct b43legacy_dmadesc_generic *op32_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta **meta)
+struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
+ int slot,
+ struct b43legacy_dmadesc_meta **meta)
{
struct b43legacy_dmadesc32 *desc;
@@ -52,11 +52,11 @@ struct b43legacy_dmadesc_generic *op32_idx2desc(
desc = ring->descbase;
desc = &(desc[slot]);
- return (struct b43legacy_dmadesc_generic *)desc;
+ return desc;
}
static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
dma_addr_t dmaaddr, u16 bufsize,
int start, int end, int irq)
{
@@ -66,13 +66,13 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
u32 addr;
u32 addrext;
- slot = (int)(&(desc->dma32) - descbase);
+ slot = (int)(desc - descbase);
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
- addr |= ssb_dma_translation(ring->dev->dev);
+ addr |= ring->dev->dma.translation;
ctl = (bufsize - ring->frameoffset)
& B43legacy_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
@@ -86,8 +86,8 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
& B43legacy_DMA32_DCTL_ADDREXT_MASK;
- desc->dma32.control = cpu_to_le32(ctl);
- desc->dma32.address = cpu_to_le32(addr);
+ desc->control = cpu_to_le32(ctl);
+ desc->address = cpu_to_le32(addr);
}
static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
@@ -127,121 +127,6 @@ static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
(u32)(slot * sizeof(struct b43legacy_dmadesc32)));
}
-static const struct b43legacy_dma_ops dma32_ops = {
- .idx2desc = op32_idx2desc,
- .fill_descriptor = op32_fill_descriptor,
- .poke_tx = op32_poke_tx,
- .tx_suspend = op32_tx_suspend,
- .tx_resume = op32_tx_resume,
- .get_current_rxslot = op32_get_current_rxslot,
- .set_current_rxslot = op32_set_current_rxslot,
-};
-
-/* 64bit DMA ops. */
-static
-struct b43legacy_dmadesc_generic *op64_idx2desc(
- struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta)
-{
- struct b43legacy_dmadesc64 *desc;
-
- *meta = &(ring->meta[slot]);
- desc = ring->descbase;
- desc = &(desc[slot]);
-
- return (struct b43legacy_dmadesc_generic *)desc;
-}
-
-static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq)
-{
- struct b43legacy_dmadesc64 *descbase = ring->descbase;
- int slot;
- u32 ctl0 = 0;
- u32 ctl1 = 0;
- u32 addrlo;
- u32 addrhi;
- u32 addrext;
-
- slot = (int)(&(desc->dma64) - descbase);
- B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
-
- addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
- addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
- addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ssb_dma_translation(ring->dev->dev);
- if (slot == ring->nr_slots - 1)
- ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
- if (start)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMESTART;
- if (end)
- ctl0 |= B43legacy_DMA64_DCTL0_FRAMEEND;
- if (irq)
- ctl0 |= B43legacy_DMA64_DCTL0_IRQ;
- ctl1 |= (bufsize - ring->frameoffset)
- & B43legacy_DMA64_DCTL1_BYTECNT;
- ctl1 |= (addrext << B43legacy_DMA64_DCTL1_ADDREXT_SHIFT)
- & B43legacy_DMA64_DCTL1_ADDREXT_MASK;
-
- desc->dma64.control0 = cpu_to_le32(ctl0);
- desc->dma64.control1 = cpu_to_le32(ctl1);
- desc->dma64.address_low = cpu_to_le32(addrlo);
- desc->dma64.address_high = cpu_to_le32(addrhi);
-}
-
-static void op64_poke_tx(struct b43legacy_dmaring *ring, int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static void op64_tx_suspend(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- | B43legacy_DMA64_TXSUSPEND);
-}
-
-static void op64_tx_resume(struct b43legacy_dmaring *ring)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
- & ~B43legacy_DMA64_TXSUSPEND);
-}
-
-static int op64_get_current_rxslot(struct b43legacy_dmaring *ring)
-{
- u32 val;
-
- val = b43legacy_dma_read(ring, B43legacy_DMA64_RXSTATUS);
- val &= B43legacy_DMA64_RXSTATDPTR;
-
- return (val / sizeof(struct b43legacy_dmadesc64));
-}
-
-static void op64_set_current_rxslot(struct b43legacy_dmaring *ring,
- int slot)
-{
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
-}
-
-static const struct b43legacy_dma_ops dma64_ops = {
- .idx2desc = op64_idx2desc,
- .fill_descriptor = op64_fill_descriptor,
- .poke_tx = op64_poke_tx,
- .tx_suspend = op64_tx_suspend,
- .tx_resume = op64_tx_resume,
- .get_current_rxslot = op64_get_current_rxslot,
- .set_current_rxslot = op64_set_current_rxslot,
-};
-
-
static inline int free_slots(struct b43legacy_dmaring *ring)
{
return (ring->nr_slots - ring->used_slots);
@@ -357,14 +242,6 @@ return 0;
static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
int controller_idx)
{
- static const u16 map64[] = {
- B43legacy_MMIO_DMA64_BASE0,
- B43legacy_MMIO_DMA64_BASE1,
- B43legacy_MMIO_DMA64_BASE2,
- B43legacy_MMIO_DMA64_BASE3,
- B43legacy_MMIO_DMA64_BASE4,
- B43legacy_MMIO_DMA64_BASE5,
- };
static const u16 map32[] = {
B43legacy_MMIO_DMA32_BASE0,
B43legacy_MMIO_DMA32_BASE1,
@@ -374,11 +251,6 @@ static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
B43legacy_MMIO_DMA32_BASE5,
};
- if (type == B43legacy_DMA_64BIT) {
- B43legacy_WARN_ON(!(controller_idx >= 0 &&
- controller_idx < ARRAY_SIZE(map64)));
- return map64[controller_idx];
- }
B43legacy_WARN_ON(!(controller_idx >= 0 &&
controller_idx < ARRAY_SIZE(map32)));
return map32[controller_idx];
@@ -393,13 +265,13 @@ dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring,
dma_addr_t dmaaddr;
if (tx)
- dmaaddr = dma_map_single(ring->dev->dev->dev,
- buf, len,
- DMA_TO_DEVICE);
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+ buf, len,
+ DMA_TO_DEVICE);
else
- dmaaddr = dma_map_single(ring->dev->dev->dev,
- buf, len,
- DMA_FROM_DEVICE);
+ dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
+ buf, len,
+ DMA_FROM_DEVICE);
return dmaaddr;
}
@@ -411,13 +283,13 @@ void unmap_descbuffer(struct b43legacy_dmaring *ring,
int tx)
{
if (tx)
- dma_unmap_single(ring->dev->dev->dev,
- addr, len,
- DMA_TO_DEVICE);
+ dma_unmap_single(ring->dev->dev->dma_dev,
+ addr, len,
+ DMA_TO_DEVICE);
else
- dma_unmap_single(ring->dev->dev->dev,
- addr, len,
- DMA_FROM_DEVICE);
+ dma_unmap_single(ring->dev->dev->dma_dev,
+ addr, len,
+ DMA_FROM_DEVICE);
}
static inline
@@ -427,7 +299,7 @@ void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring,
{
B43legacy_WARN_ON(ring->tx);
- dma_sync_single_for_cpu(ring->dev->dev->dev,
+ dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -438,7 +310,7 @@ void sync_descbuffer_for_device(struct b43legacy_dmaring *ring,
{
B43legacy_WARN_ON(ring->tx);
- dma_sync_single_for_device(ring->dev->dev->dev,
+ dma_sync_single_for_device(ring->dev->dev->dma_dev,
addr, len, DMA_FROM_DEVICE);
}
@@ -458,25 +330,19 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
static int alloc_ringmemory(struct b43legacy_dmaring *ring)
{
- struct device *dev = ring->dev->dev->dev;
-
- ring->descbase = dma_alloc_coherent(dev, B43legacy_DMA_RINGMEMSIZE,
- &(ring->dmabase), GFP_KERNEL);
- if (!ring->descbase) {
- b43legacyerr(ring->dev->wl, "DMA ringmemory allocation"
- " failed\n");
+ /* GFP flags must match the flags in free_ringmemory()! */
+ ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
+ B43legacy_DMA_RINGMEMSIZE,
+ &(ring->dmabase), GFP_KERNEL);
+ if (!ring->descbase)
return -ENOMEM;
- }
- memset(ring->descbase, 0, B43legacy_DMA_RINGMEMSIZE);
return 0;
}
static void free_ringmemory(struct b43legacy_dmaring *ring)
{
- struct device *dev = ring->dev->dev->dev;
-
- dma_free_coherent(dev, B43legacy_DMA_RINGMEMSIZE,
+ dma_free_coherent(ring->dev->dev->dma_dev, B43legacy_DMA_RINGMEMSIZE,
ring->descbase, ring->dmabase);
}
@@ -491,25 +357,15 @@ static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
might_sleep();
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL;
+ offset = B43legacy_DMA32_RXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS;
+ offset = B43legacy_DMA32_RXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_RXSTAT;
- if (value == B43legacy_DMA64_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_RXSTATE;
- if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_RXSTATE;
+ if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -533,43 +389,24 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
might_sleep();
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED ||
- value == B43legacy_DMA64_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA64_TXSTAT_STOPPED)
- break;
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
- value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
- value == B43legacy_DMA32_TXSTAT_STOPPED)
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
+ value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
+ value == B43legacy_DMA32_TXSTAT_STOPPED)
+ break;
msleep(1);
}
- offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL :
- B43legacy_DMA32_TXCTL;
+ offset = B43legacy_DMA32_TXCTL;
b43legacy_write32(dev, mmio_base + offset, 0);
for (i = 0; i < 10; i++) {
- offset = (type == B43legacy_DMA_64BIT) ?
- B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
+ offset = B43legacy_DMA32_TXSTATUS;
value = b43legacy_read32(dev, mmio_base + offset);
- if (type == B43legacy_DMA_64BIT) {
- value &= B43legacy_DMA64_TXSTAT;
- if (value == B43legacy_DMA64_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
- } else {
- value &= B43legacy_DMA32_TXSTATE;
- if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
- i = -1;
- break;
- }
+ value &= B43legacy_DMA32_TXSTATE;
+ if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
+ i = -1;
+ break;
}
msleep(1);
}
@@ -585,32 +422,36 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
/* Check if a DMA mapping address is invalid. */
static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
- dma_addr_t addr,
- size_t buffersize)
+ dma_addr_t addr,
+ size_t buffersize,
+ bool dma_to_device)
{
- if (unlikely(dma_mapping_error(addr)))
+ if (unlikely(dma_mapping_error(ring->dev->dev->dma_dev, addr)))
return 1;
switch (ring->type) {
case B43legacy_DMA_30BIT:
if ((u64)addr + buffersize > (1ULL << 30))
- return 1;
+ goto address_error;
break;
case B43legacy_DMA_32BIT:
if ((u64)addr + buffersize > (1ULL << 32))
- return 1;
- break;
- case B43legacy_DMA_64BIT:
- /* Currently we can't have addresses beyond 64 bits in the kernel. */
+ goto address_error;
break;
}
/* The address is OK. */
return 0;
+
+address_error:
+ /* We can't support this address. Unmap it again. */
+ unmap_descbuffer(ring, addr, buffersize, dma_to_device);
+
+ return 1;
}
static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
+ struct b43legacy_dmadesc32 *desc,
struct b43legacy_dmadesc_meta *meta,
gfp_t gfp_flags)
{
@@ -626,7 +467,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
return -ENOMEM;
dmaaddr = map_descbuffer(ring, skb->data,
ring->rx_buffersize, 0);
- if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
+ if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
/* ugh. try to realloc in zone_dma */
gfp_flags |= GFP_DMA;
@@ -639,15 +480,14 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
ring->rx_buffersize, 0);
}
- if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
+ if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
dev_kfree_skb_any(skb);
return -EIO;
}
meta->skb = skb;
meta->dmaaddr = dmaaddr;
- ring->ops->fill_descriptor(ring, desc, dmaaddr,
- ring->rx_buffersize, 0, 0, 0);
+ op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
rxhdr->frame_len = 0;
@@ -664,11 +504,11 @@ static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
{
int i;
int err = -ENOMEM;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
if (err) {
@@ -685,7 +525,7 @@ out:
err_unwind:
for (i--; i >= 0; i--) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ desc = op32_idx2desc(ring, i, &meta);
unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
dev_kfree_skb(meta->skb);
@@ -702,84 +542,36 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
- u32 trans = ssb_dma_translation(ring->dev->dev);
+ u32 trans = ring->dev->dma.translation;
+ u32 ringbase = (u32)(ring->dmabase);
if (ring->tx) {
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA64_TXENABLE;
- value |= (addrext << B43legacy_DMA64_TXADDREXT_SHIFT)
- & B43legacy_DMA64_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI,
- ((ringbase >> 32)
- & ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = B43legacy_DMA32_TXENABLE;
- value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
- & B43legacy_DMA32_TXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- }
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = B43legacy_DMA32_TXENABLE;
+ value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
+ & B43legacy_DMA32_TXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
} else {
err = alloc_initial_descbuffers(ring);
if (err)
goto out;
- if (ring->type == B43legacy_DMA_64BIT) {
- u64 ringbase = (u64)(ring->dmabase);
-
- addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA64_RXFROFF_SHIFT);
- value |= B43legacy_DMA64_RXENABLE;
- value |= (addrext << B43legacy_DMA64_RXADDREXT_SHIFT)
- & B43legacy_DMA64_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA64_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO,
- (ringbase & 0xFFFFFFFF));
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI,
- ((ringbase >> 32) &
- ~SSB_DMA_TRANSLATION_MASK) |
- trans);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
- 200);
- } else {
- u32 ringbase = (u32)(ring->dmabase);
-
- addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
- >> SSB_DMA_TRANSLATION_SHIFT;
- value = (ring->frameoffset <<
- B43legacy_DMA32_RXFROFF_SHIFT);
- value |= B43legacy_DMA32_RXENABLE;
- value |= (addrext <<
- B43legacy_DMA32_RXADDREXT_SHIFT)
- & B43legacy_DMA32_RXADDREXT_MASK;
- b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL,
- value);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
- (ringbase &
- ~SSB_DMA_TRANSLATION_MASK)
- | trans);
- b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
- 200);
- }
+
+ addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
+ >> SSB_DMA_TRANSLATION_SHIFT;
+ value = (ring->frameoffset <<
+ B43legacy_DMA32_RXFROFF_SHIFT);
+ value |= B43legacy_DMA32_RXENABLE;
+ value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
+ & B43legacy_DMA32_RXADDREXT_MASK;
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
+ (ringbase & ~SSB_DMA_TRANSLATION_MASK)
+ | trans);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
}
out:
@@ -792,32 +584,23 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
if (ring->tx) {
b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
} else {
b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
ring->type);
- if (ring->type == B43legacy_DMA_64BIT) {
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0);
- b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0);
- } else
- b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
+ b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
}
}
static void free_all_descbuffers(struct b43legacy_dmaring *ring)
{
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
int i;
if (!ring->used_slots)
return;
for (i = 0; i < ring->nr_slots; i++) {
- desc = ring->ops->idx2desc(ring, i, &meta);
+ op32_idx2desc(ring, i, &meta);
if (!meta->skb) {
B43legacy_WARN_ON(!ring->tx);
@@ -838,9 +621,6 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
u32 tmp;
u16 mmio_base;
- tmp = b43legacy_read32(dev, SSB_TMSHIGH);
- if (tmp & SSB_TMSHIGH_DMA64)
- return DMA_64BIT_MASK;
mmio_base = b43legacy_dmacontroller_base(0, 0);
b43legacy_write32(dev,
mmio_base + B43legacy_DMA32_TXCTL,
@@ -848,9 +628,19 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
tmp = b43legacy_read32(dev, mmio_base +
B43legacy_DMA32_TXCTL);
if (tmp & B43legacy_DMA32_TXADDREXT_MASK)
- return DMA_32BIT_MASK;
+ return DMA_BIT_MASK(32);
- return DMA_30BIT_MASK;
+ return DMA_BIT_MASK(30);
+}
+
+static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
+{
+ if (dmamask == DMA_BIT_MASK(30))
+ return B43legacy_DMA_30BIT;
+ if (dmamask == DMA_BIT_MASK(32))
+ return B43legacy_DMA_32BIT;
+ B43legacy_WARN_ON(1);
+ return B43legacy_DMA_30BIT;
}
/* Main initialization function. */
@@ -869,6 +659,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
if (!ring)
goto out;
ring->type = type;
+ ring->dev = dev;
nr_slots = B43legacy_RXRING_SLOTS;
if (for_tx)
@@ -886,12 +677,12 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
goto err_kfree_meta;
/* test for ability to dma to txhdr_cache */
- dma_test = dma_map_single(dev->dev->dev, ring->txhdr_cache,
- sizeof(struct b43legacy_txhdr_fw3),
- DMA_TO_DEVICE);
+ dma_test = dma_map_single(dev->dev->dma_dev, ring->txhdr_cache,
+ sizeof(struct b43legacy_txhdr_fw3),
+ DMA_TO_DEVICE);
if (b43legacy_dma_mapping_error(ring, dma_test,
- sizeof(struct b43legacy_txhdr_fw3))) {
+ sizeof(struct b43legacy_txhdr_fw3), 1)) {
/* ugh realloc */
kfree(ring->txhdr_cache);
ring->txhdr_cache = kcalloc(nr_slots,
@@ -900,31 +691,26 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = dma_map_single(dev->dev->dev,
+ dma_test = dma_map_single(dev->dev->dma_dev,
ring->txhdr_cache,
sizeof(struct b43legacy_txhdr_fw3),
DMA_TO_DEVICE);
if (b43legacy_dma_mapping_error(ring, dma_test,
- sizeof(struct b43legacy_txhdr_fw3)))
+ sizeof(struct b43legacy_txhdr_fw3), 1))
goto err_kfree_txhdr_cache;
}
- dma_unmap_single(dev->dev->dev,
- dma_test, sizeof(struct b43legacy_txhdr_fw3),
+ dma_unmap_single(dev->dev->dma_dev, dma_test,
+ sizeof(struct b43legacy_txhdr_fw3),
DMA_TO_DEVICE);
}
- ring->dev = dev;
ring->nr_slots = nr_slots;
ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
ring->index = controller_index;
- if (type == B43legacy_DMA_64BIT)
- ring->ops = &dma64_ops;
- else
- ring->ops = &dma32_ops;
if (for_tx) {
- ring->tx = 1;
+ ring->tx = true;
ring->current_slot = -1;
} else {
if (ring->index == 0) {
@@ -936,7 +722,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
} else
B43legacy_WARN_ON(1);
}
- spin_lock_init(&ring->lock);
#ifdef CONFIG_B43LEGACY_DEBUG
ring->last_injected_overflow = jiffies;
#endif
@@ -1012,6 +797,43 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev)
dma->tx_ring0 = NULL;
}
+static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask)
+{
+ u64 orig_mask = mask;
+ bool fallback = false;
+ int err;
+
+ /* Try to set the DMA mask. If it fails, try falling back to a
+ * lower mask, as we can always also support a lower one. */
+ while (1) {
+ err = dma_set_mask_and_coherent(dev->dev->dma_dev, mask);
+ if (!err)
+ break;
+ if (mask == DMA_BIT_MASK(64)) {
+ mask = DMA_BIT_MASK(32);
+ fallback = true;
+ continue;
+ }
+ if (mask == DMA_BIT_MASK(32)) {
+ mask = DMA_BIT_MASK(30);
+ fallback = true;
+ continue;
+ }
+ b43legacyerr(dev->wl, "The machine/kernel does not support "
+ "the required %u-bit DMA mask\n",
+ (unsigned int)dma_mask_to_engine_type(orig_mask));
+ return -EOPNOTSUPP;
+ }
+ if (fallback) {
+ b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-"
+ "bit\n",
+ (unsigned int)dma_mask_to_engine_type(orig_mask),
+ (unsigned int)dma_mask_to_engine_type(mask));
+ }
+
+ return 0;
+}
+
int b43legacy_dma_init(struct b43legacy_wldev *dev)
{
struct b43legacy_dma *dma = &dev->dma;
@@ -1021,26 +843,13 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
enum b43legacy_dmatype type;
dmamask = supported_dma_mask(dev);
- switch (dmamask) {
- default:
- B43legacy_WARN_ON(1);
- case DMA_30BIT_MASK:
- type = B43legacy_DMA_30BIT;
- break;
- case DMA_32BIT_MASK:
- type = B43legacy_DMA_32BIT;
- break;
- case DMA_64BIT_MASK:
- type = B43legacy_DMA_64BIT;
- break;
- }
-
- err = ssb_dma_set_mask(dev->dev, dmamask);
+ type = dma_mask_to_engine_type(dmamask);
+ err = b43legacy_dma_set_mask(dev, dmamask);
if (err) {
#ifdef CONFIG_B43LEGACY_PIO
b43legacywarn(dev->wl, "DMA for this device not supported. "
"Falling back to PIO\n");
- dev->__using_pio = 1;
+ dev->__using_pio = true;
return -EAGAIN;
#else
b43legacyerr(dev->wl, "DMA for this device not supported and "
@@ -1048,6 +857,7 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev)
return -EOPNOTSUPP;
#endif
}
+ dma->translation = ssb_dma_translation(dev->dev);
err = -ENOMEM;
/* setup TX DMA channels. */
@@ -1198,14 +1008,14 @@ struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev,
}
static int dma_tx_fragment(struct b43legacy_dmaring *ring,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+ struct sk_buff **in_skb)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
+ struct sk_buff *skb = *in_skb;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
int slot, old_top_slot, old_used_slots;
int err;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_dmadesc_meta *meta_hdr;
struct sk_buff *bounce_skb;
@@ -1218,13 +1028,13 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
/* Get a slot for the header. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta_hdr);
+ desc = op32_idx2desc(ring, slot, &meta_hdr);
memset(meta_hdr, 0, sizeof(*meta_hdr));
header = &(ring->txhdr_cache[slot * sizeof(
struct b43legacy_txhdr_fw3)]);
err = b43legacy_generate_txhdr(ring->dev, header,
- skb->data, skb->len, ctl,
+ skb->data, skb->len, info,
generate_cookie(ring, slot));
if (unlikely(err)) {
ring->current_slot = old_top_slot;
@@ -1235,27 +1045,26 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
sizeof(struct b43legacy_txhdr_fw3), 1);
if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr,
- sizeof(struct b43legacy_txhdr_fw3))) {
+ sizeof(struct b43legacy_txhdr_fw3), 1)) {
ring->current_slot = old_top_slot;
ring->used_slots = old_used_slots;
return -EIO;
}
- ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
/* Get a slot for the payload. */
slot = request_slot(ring);
- desc = ops->idx2desc(ring, slot, &meta);
+ desc = op32_idx2desc(ring, slot, &meta);
memset(meta, 0, sizeof(*meta));
- memcpy(&meta->txstat.control, ctl, sizeof(*ctl));
meta->skb = skb;
- meta->is_last_fragment = 1;
+ meta->is_last_fragment = true;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
/* create a bounce buffer in zone_dma on mapping failure. */
- if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
- bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+ if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+ bounce_skb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
if (!bounce_skb) {
ring->current_slot = old_top_slot;
ring->used_slots = old_used_slots;
@@ -1264,11 +1073,17 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
}
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+ bounce_skb->dev = skb->dev;
+ skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+ info = IEEE80211_SKB_CB(bounce_skb);
+
dev_kfree_skb_any(skb);
skb = bounce_skb;
+ *in_skb = bounce_skb;
meta->skb = skb;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
- if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
+ if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
ring->current_slot = old_top_slot;
ring->used_slots = old_used_slots;
err = -EIO;
@@ -1276,12 +1091,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
}
}
- ops->fill_descriptor(ring, desc, meta->dmaaddr,
+ op32_fill_descriptor(ring, desc, meta->dmaaddr,
skb->len, 0, 1, 1);
wmb(); /* previous stuff MUST be done */
/* Now transfer the whole frame. */
- ops->poke_tx(ring, next_slot(ring, slot));
+ op32_poke_tx(ring, next_slot(ring, slot));
return 0;
out_free_bounce:
@@ -1316,74 +1131,91 @@ int should_inject_overflow(struct b43legacy_dmaring *ring)
}
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+ struct sk_buff *skb)
{
struct b43legacy_dmaring *ring;
int err = 0;
- unsigned long flags;
- ring = priority_to_txring(dev, ctl->queue);
- spin_lock_irqsave(&ring->lock, flags);
+ ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
B43legacy_WARN_ON(!ring->tx);
- if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
- b43legacywarn(dev->wl, "DMA queue overflow\n");
- err = -ENOSPC;
- goto out_unlock;
+
+ if (unlikely(ring->stopped)) {
+ /* We get here only because of a bug in mac80211.
+ * Because of a race, one packet may be queued after
+ * the queue is stopped, thus we got called when we shouldn't.
+ * For now, just refuse the transmit. */
+ if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+ b43legacyerr(dev->wl, "Packet after queue stopped\n");
+ return -ENOSPC;
}
- /* Check if the queue was stopped in mac80211,
- * but we got called nevertheless.
- * That would be a mac80211 bug. */
- B43legacy_BUG_ON(ring->stopped);
- err = dma_tx_fragment(ring, skb, ctl);
+ if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) {
+ /* If we get here, we have a real error with the queue
+ * full, but queues not stopped. */
+ b43legacyerr(dev->wl, "DMA queue overflow\n");
+ return -ENOSPC;
+ }
+
+ /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+ * into the skb data or cb now. */
+ err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
dev_kfree_skb_any(skb);
- err = 0;
- goto out_unlock;
+ return 0;
}
if (unlikely(err)) {
b43legacyerr(dev->wl, "DMA tx mapping failure\n");
- goto out_unlock;
+ return err;
}
- ring->nr_tx_packets++;
if ((free_slots(ring) < SLOTS_PER_PACKET) ||
should_inject_overflow(ring)) {
/* This TX ring is full. */
- ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring));
- ring->stopped = 1;
+ unsigned int skb_mapping = skb_get_queue_mapping(skb);
+ ieee80211_stop_queue(dev->wl->hw, skb_mapping);
+ dev->wl->tx_queue_stopped[skb_mapping] = 1;
+ ring->stopped = true;
if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
b43legacydbg(dev->wl, "Stopped TX ring %d\n",
ring->index);
}
-out_unlock:
- spin_unlock_irqrestore(&ring->lock, flags);
-
return err;
}
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status)
{
- const struct b43legacy_dma_ops *ops;
struct b43legacy_dmaring *ring;
- struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
+ int retry_limit;
int slot;
+ int firstused;
ring = parse_cookie(dev, status->cookie, &slot);
if (unlikely(!ring))
return;
- B43legacy_WARN_ON(!irqs_disabled());
- spin_lock(&ring->lock);
-
B43legacy_WARN_ON(!ring->tx);
- ops = ring->ops;
+
+ /* Sanity check: TX packets are processed in-order on one ring.
+ * Check if the slot deduced from the cookie really is the first
+ * used slot. */
+ firstused = ring->current_slot - ring->used_slots + 1;
+ if (firstused < 0)
+ firstused = ring->nr_slots + firstused;
+ if (unlikely(slot != firstused)) {
+ /* This possibly is a firmware bug and will result in
+ * malfunction, memory leaks and/or stall of DMA functionality.
+ */
+ b43legacydbg(dev->wl, "Out of order TX status report on DMA "
+ "ring %d. Expected %d, but got %d\n",
+ ring->index, firstused, slot);
+ return;
+ }
+
while (1) {
B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
- desc = ops->idx2desc(ring, slot, &meta);
+ op32_idx2desc(ring, slot, &meta);
if (meta->skb)
unmap_descbuffer(ring, meta->dmaaddr,
@@ -1394,26 +1226,46 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
1);
if (meta->is_last_fragment) {
- B43legacy_WARN_ON(!meta->skb);
+ struct ieee80211_tx_info *info;
+ BUG_ON(!meta->skb);
+ info = IEEE80211_SKB_CB(meta->skb);
+
+ /* preserve the confiured retry limit before clearing the status
+ * The xmit function has overwritten the rc's value with the actual
+ * retry limit done by the hardware */
+ retry_limit = info->status.rates[0].count;
+ ieee80211_tx_info_clear_status(info);
+
+ if (status->acked)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+ /*
+ * If the short retries (RTS, not data frame) have exceeded
+ * the limit, the hw will not have tried the selected rate,
+ * but will have used the fallback rate instead.
+ * Don't let the rate control count attempts for the selected
+ * rate in this case, otherwise the statistics will be off.
+ */
+ info->status.rates[0].count = 0;
+ info->status.rates[1].count = status->frame_count;
+ } else {
+ if (status->frame_count > retry_limit) {
+ info->status.rates[0].count = retry_limit;
+ info->status.rates[1].count = status->frame_count -
+ retry_limit;
+
+ } else {
+ info->status.rates[0].count = status->frame_count;
+ info->status.rates[1].idx = -1;
+ }
+ }
+
/* Call back to inform the ieee80211 subsystem about the
* status of the transmission.
* Some fields of txstat are already filled in dma_tx().
*/
- if (status->acked) {
- meta->txstat.flags |= IEEE80211_TX_STATUS_ACK;
- } else {
- if (!(meta->txstat.control.flags
- & IEEE80211_TXCTL_NO_ACK))
- meta->txstat.excessive_retries = 1;
- }
- if (status->frame_count == 0) {
- /* The frame was not transmitted at all. */
- meta->txstat.retry_count = 0;
- } else
- meta->txstat.retry_count = status->frame_count
- - 1;
- ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb,
- &(meta->txstat));
+ ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
/* skb is freed by ieee80211_tx_status_irqsafe() */
meta->skb = NULL;
} else {
@@ -1433,42 +1285,27 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
dev->stats.last_tx = jiffies;
if (ring->stopped) {
B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET);
- ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring));
- ring->stopped = 0;
- if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
- b43legacydbg(dev->wl, "Woke up TX ring %d\n",
- ring->index);
+ ring->stopped = false;
}
- spin_unlock(&ring->lock);
-}
-
-void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
- const int nr_queues = dev->wl->hw->queues;
- struct b43legacy_dmaring *ring;
- struct ieee80211_tx_queue_stats_data *data;
- unsigned long flags;
- int i;
-
- for (i = 0; i < nr_queues; i++) {
- data = &(stats->data[i]);
- ring = priority_to_txring(dev, i);
-
- spin_lock_irqsave(&ring->lock, flags);
- data->len = ring->used_slots / SLOTS_PER_PACKET;
- data->limit = ring->nr_slots / SLOTS_PER_PACKET;
- data->count = ring->nr_tx_packets;
- spin_unlock_irqrestore(&ring->lock, flags);
+ if (dev->wl->tx_queue_stopped[ring->queue_prio]) {
+ dev->wl->tx_queue_stopped[ring->queue_prio] = 0;
+ } else {
+ /* If the driver queue is running wake the corresponding
+ * mac80211 queue. */
+ ieee80211_wake_queue(dev->wl->hw, ring->queue_prio);
+ if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE))
+ b43legacydbg(dev->wl, "Woke up TX ring %d\n",
+ ring->index);
}
+ /* Add work to the queue. */
+ ieee80211_queue_work(dev->wl->hw, &dev->wl->tx_work);
}
static void dma_rx(struct b43legacy_dmaring *ring,
int *slot)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
- struct b43legacy_dmadesc_generic *desc;
+ struct b43legacy_dmadesc32 *desc;
struct b43legacy_dmadesc_meta *meta;
struct b43legacy_rxhdr_fw3 *rxhdr;
struct sk_buff *skb;
@@ -1476,7 +1313,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
int err;
dma_addr_t dmaaddr;
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
skb = meta->skb;
@@ -1528,7 +1365,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
s32 tmp = len;
while (1) {
- desc = ops->idx2desc(ring, *slot, &meta);
+ desc = op32_idx2desc(ring, *slot, &meta);
/* recycle the descriptor buffer. */
sync_descbuffer_for_device(ring, meta->dmaaddr,
ring->rx_buffersize);
@@ -1565,13 +1402,12 @@ drop:
void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
{
- const struct b43legacy_dma_ops *ops = ring->ops;
int slot;
int current_slot;
int used_slots = 0;
B43legacy_WARN_ON(ring->tx);
- current_slot = ops->get_current_rxslot(ring);
+ current_slot = op32_get_current_rxslot(ring);
B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
ring->nr_slots));
@@ -1580,28 +1416,20 @@ void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
dma_rx(ring, &slot);
update_max_used_slots(ring, ++used_slots);
}
- ops->set_current_rxslot(ring, slot);
+ op32_set_current_rxslot(ring, slot);
ring->current_slot = slot;
}
static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_suspend(ring);
- spin_unlock_irqrestore(&ring->lock, flags);
+ op32_tx_suspend(ring);
}
static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
{
- unsigned long flags;
-
- spin_lock_irqsave(&ring->lock, flags);
B43legacy_WARN_ON(!ring->tx);
- ring->ops->tx_resume(ring);
- spin_unlock_irqrestore(&ring->lock, flags);
+ op32_tx_resume(ring);
}
void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev)
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index 2dd488c5be2..c3282f906bc 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -5,7 +5,7 @@
#include <linux/spinlock.h>
#include <linux/workqueue.h>
#include <linux/linkage.h>
-#include <asm/atomic.h>
+#include <linux/atomic.h>
#include "b43legacy.h"
@@ -72,7 +72,7 @@
struct b43legacy_dmadesc32 {
__le32 control;
__le32 address;
-} __attribute__((__packed__));
+} __packed;
#define B43legacy_DMA32_DCTL_BYTECNT 0x00001FFF
#define B43legacy_DMA32_DCTL_ADDREXT_MASK 0x00030000
#define B43legacy_DMA32_DCTL_ADDREXT_SHIFT 16
@@ -82,90 +82,6 @@ struct b43legacy_dmadesc32 {
#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000
-
-/*** 64-bit DMA Engine. ***/
-
-/* 64-bit DMA controller registers. */
-#define B43legacy_DMA64_TXCTL 0x00
-#define B43legacy_DMA64_TXENABLE 0x00000001
-#define B43legacy_DMA64_TXSUSPEND 0x00000002
-#define B43legacy_DMA64_TXLOOPBACK 0x00000004
-#define B43legacy_DMA64_TXFLUSH 0x00000010
-#define B43legacy_DMA64_TXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_TXADDREXT_SHIFT 16
-#define B43legacy_DMA64_TXINDEX 0x04
-#define B43legacy_DMA64_TXRINGLO 0x08
-#define B43legacy_DMA64_TXRINGHI 0x0C
-#define B43legacy_DMA64_TXSTATUS 0x10
-#define B43legacy_DMA64_TXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_TXSTAT 0xF0000000
-#define B43legacy_DMA64_TXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_TXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_TXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_TXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_TXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_TXERROR 0x14
-#define B43legacy_DMA64_TXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_TXERR 0xF0000000
-#define B43legacy_DMA64_TXERR_NOERR 0x00000000
-#define B43legacy_DMA64_TXERR_PROT 0x10000000
-#define B43legacy_DMA64_TXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_TXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_TXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_TXERR_CORE 0x50000000
-#define B43legacy_DMA64_RXCTL 0x20
-#define B43legacy_DMA64_RXENABLE 0x00000001
-#define B43legacy_DMA64_RXFROFF_MASK 0x000000FE
-#define B43legacy_DMA64_RXFROFF_SHIFT 1
-#define B43legacy_DMA64_RXDIRECTFIFO 0x00000100
-#define B43legacy_DMA64_RXADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_RXADDREXT_SHIFT 16
-#define B43legacy_DMA64_RXINDEX 0x24
-#define B43legacy_DMA64_RXRINGLO 0x28
-#define B43legacy_DMA64_RXRINGHI 0x2C
-#define B43legacy_DMA64_RXSTATUS 0x30
-#define B43legacy_DMA64_RXSTATDPTR 0x00001FFF
-#define B43legacy_DMA64_RXSTAT 0xF0000000
-#define B43legacy_DMA64_RXSTAT_DISABLED 0x00000000
-#define B43legacy_DMA64_RXSTAT_ACTIVE 0x10000000
-#define B43legacy_DMA64_RXSTAT_IDLEWAIT 0x20000000
-#define B43legacy_DMA64_RXSTAT_STOPPED 0x30000000
-#define B43legacy_DMA64_RXSTAT_SUSP 0x40000000
-#define B43legacy_DMA64_RXERROR 0x34
-#define B43legacy_DMA64_RXERRDPTR 0x0001FFFF
-#define B43legacy_DMA64_RXERR 0xF0000000
-#define B43legacy_DMA64_RXERR_NOERR 0x00000000
-#define B43legacy_DMA64_RXERR_PROT 0x10000000
-#define B43legacy_DMA64_RXERR_UNDERRUN 0x20000000
-#define B43legacy_DMA64_RXERR_TRANSFER 0x30000000
-#define B43legacy_DMA64_RXERR_DESCREAD 0x40000000
-#define B43legacy_DMA64_RXERR_CORE 0x50000000
-
-/* 64-bit DMA descriptor. */
-struct b43legacy_dmadesc64 {
- __le32 control0;
- __le32 control1;
- __le32 address_low;
- __le32 address_high;
-} __attribute__((__packed__));
-#define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000
-#define B43legacy_DMA64_DCTL0_IRQ 0x20000000
-#define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000
-#define B43legacy_DMA64_DCTL0_FRAMESTART 0x80000000
-#define B43legacy_DMA64_DCTL1_BYTECNT 0x00001FFF
-#define B43legacy_DMA64_DCTL1_ADDREXT_MASK 0x00030000
-#define B43legacy_DMA64_DCTL1_ADDREXT_SHIFT 16
-
-
-
-struct b43legacy_dmadesc_generic {
- union {
- struct b43legacy_dmadesc32 dma32;
- struct b43legacy_dmadesc64 dma64;
- } __attribute__((__packed__));
-} __attribute__((__packed__));
-
-
/* Misc DMA constants */
#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE
#define B43legacy_DMA0_RX_FRAMEOFFSET 30
@@ -195,38 +111,14 @@ struct b43legacy_dmadesc_meta {
dma_addr_t dmaaddr;
/* ieee80211 TX status. Only used once per 802.11 frag. */
bool is_last_fragment;
- struct ieee80211_tx_status txstat;
-};
-
-struct b43legacy_dmaring;
-
-/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
-struct b43legacy_dma_ops {
- struct b43legacy_dmadesc_generic * (*idx2desc)
- (struct b43legacy_dmaring *ring,
- int slot,
- struct b43legacy_dmadesc_meta
- **meta);
- void (*fill_descriptor)(struct b43legacy_dmaring *ring,
- struct b43legacy_dmadesc_generic *desc,
- dma_addr_t dmaaddr, u16 bufsize,
- int start, int end, int irq);
- void (*poke_tx)(struct b43legacy_dmaring *ring, int slot);
- void (*tx_suspend)(struct b43legacy_dmaring *ring);
- void (*tx_resume)(struct b43legacy_dmaring *ring);
- int (*get_current_rxslot)(struct b43legacy_dmaring *ring);
- void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot);
};
enum b43legacy_dmatype {
B43legacy_DMA_30BIT = 30,
B43legacy_DMA_32BIT = 32,
- B43legacy_DMA_64BIT = 64,
};
struct b43legacy_dmaring {
- /* Lowlevel DMA ops. */
- const struct b43legacy_dma_ops *ops;
/* Kernel virtual base address of the ring memory. */
void *descbase;
/* Meta data about all descriptors. */
@@ -244,8 +136,6 @@ struct b43legacy_dmaring {
int used_slots;
/* Currently used slot in the ring. */
int current_slot;
- /* Total number of packets sent. Statistics only. */
- unsigned int nr_tx_packets;
/* Frameoffset in octets. */
u32 frameoffset;
/* Descriptor buffer size. */
@@ -260,8 +150,9 @@ struct b43legacy_dmaring {
enum b43legacy_dmatype type;
/* Boolean. Is this ring stopped at ieee80211 level? */
bool stopped;
- /* Lock, only used for TX. */
- spinlock_t lock;
+ /* The QOS priority assigned to this ring. Only used for TX rings.
+ * This is the mac80211 "queue" value. */
+ u8 queue_prio;
struct b43legacy_wldev *dev;
#ifdef CONFIG_B43LEGACY_DEBUG
/* Maximum number of used slots. */
@@ -293,12 +184,8 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev);
void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev);
void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev);
-void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats);
-
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl);
+ struct sk_buff *skb);
void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status);
@@ -317,14 +204,8 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev)
{
}
static inline
-void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
-}
-static inline
int b43legacy_dma_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+ struct sk_buff *skb)
{
return 0;
}
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index a849078aea6..ee5682e5420 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index cacb786d971..fd4565389c7 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -5,7 +5,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -28,6 +28,7 @@
#include "b43legacy.h"
#include "leds.h"
+#include "rfkill.h"
static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
@@ -86,7 +87,8 @@ static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
static int b43legacy_register_led(struct b43legacy_wldev *dev,
struct b43legacy_led *led,
- const char *name, char *default_trigger,
+ const char *name,
+ const char *default_trigger,
u8 led_index, bool activelow)
{
int err;
@@ -146,12 +148,12 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev,
case B43legacy_LED_TRANSFER:
case B43legacy_LED_APTRANSFER:
snprintf(name, sizeof(name),
- "b43legacy-%s:tx", wiphy_name(hw->wiphy));
+ "b43legacy-%s::tx", wiphy_name(hw->wiphy));
b43legacy_register_led(dev, &dev->led_tx, name,
ieee80211_get_tx_led_name(hw),
led_index, activelow);
snprintf(name, sizeof(name),
- "b43legacy-%s:rx", wiphy_name(hw->wiphy));
+ "b43legacy-%s::rx", wiphy_name(hw->wiphy));
b43legacy_register_led(dev, &dev->led_rx, name,
ieee80211_get_rx_led_name(hw),
led_index, activelow);
@@ -161,18 +163,18 @@ static void b43legacy_map_led(struct b43legacy_wldev *dev,
case B43legacy_LED_RADIO_B:
case B43legacy_LED_MODE_BG:
snprintf(name, sizeof(name),
- "b43legacy-%s:radio", wiphy_name(hw->wiphy));
+ "b43legacy-%s::radio", wiphy_name(hw->wiphy));
b43legacy_register_led(dev, &dev->led_radio, name,
- b43legacy_rfkill_led_name(dev),
+ ieee80211_get_radio_led_name(hw),
led_index, activelow);
- /* Sync the RF-kill LED state with the switch state. */
- if (dev->radio_hw_enable)
+ /* Sync the RF-kill LED state with radio and switch states. */
+ if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
b43legacy_led_turn_on(dev, led_index, activelow);
break;
case B43legacy_LED_WEIRD:
case B43legacy_LED_ASSOC:
snprintf(name, sizeof(name),
- "b43legacy-%s:assoc", wiphy_name(hw->wiphy));
+ "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
b43legacy_register_led(dev, &dev->led_assoc, name,
ieee80211_get_assoc_led_name(hw),
led_index, activelow);
@@ -201,11 +203,11 @@ void b43legacy_leds_init(struct b43legacy_wldev *dev)
if (sprom[i] == 0xFF) {
/* There is no LED information in the SPROM
* for this LED. Hardcode it here. */
- activelow = 0;
+ activelow = false;
switch (i) {
case 0:
behaviour = B43legacy_LED_ACTIVITY;
- activelow = 1;
+ activelow = true;
if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
behaviour = B43legacy_LED_RADIO_ALL;
break;
diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h
index 82167a90088..9ff6750dc57 100644
--- a/drivers/net/wireless/b43legacy/leds.h
+++ b/drivers/net/wireless/b43legacy/leds.h
@@ -45,7 +45,7 @@ enum b43legacy_led_behaviour {
void b43legacy_leds_init(struct b43legacy_wldev *dev);
void b43legacy_leds_exit(struct b43legacy_wldev *dev);
-#else /* CONFIG_B43EGACY_LEDS */
+#else /* CONFIG_B43LEGACY_LEDS */
/* LED support disabled */
struct b43legacy_led {
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 5f3f34e1dbf..1aec2146a2b 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
- * Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
* Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -31,15 +31,15 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
-#include <linux/version.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
+#include <linux/sched.h>
#include <linux/skbuff.h>
#include <linux/dma-mapping.h>
+#include <linux/slab.h>
#include <net/dst.h>
#include <asm/unaligned.h>
@@ -60,7 +60,8 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
+MODULE_FIRMWARE("b43legacy/ucode2.fw");
+MODULE_FIRMWARE("b43legacy/ucode4.fw");
#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
static int modparam_pio;
@@ -95,28 +96,29 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl);
* data in there. This data is the same for all devices, so we don't
* get concurrency issues */
#define RATETAB_ENT(_rateid, _flags) \
- { \
- .rate = B43legacy_RATE_TO_100KBPS(_rateid), \
- .val = (_rateid), \
- .val2 = (_rateid), \
- .flags = (_flags), \
+ { \
+ .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \
+ .hw_value = (_rateid), \
+ .flags = (_flags), \
}
+/*
+ * NOTE: When changing this, sync with xmit.c's
+ * b43legacy_plcp_get_bitrate_idx_* functions!
+ */
static struct ieee80211_rate __b43legacy_ratetable[] = {
- RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK),
- RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2),
- RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2),
- RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2),
- RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM),
- RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM),
+ RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0),
+ RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE),
+ RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0),
+ RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0),
};
-#define b43legacy_a_ratetable (__b43legacy_ratetable + 4)
-#define b43legacy_a_ratetable_size 8
#define b43legacy_b_ratetable (__b43legacy_ratetable + 0)
#define b43legacy_b_ratetable_size 4
#define b43legacy_g_ratetable (__b43legacy_ratetable + 0)
@@ -124,14 +126,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = {
#define CHANTAB_ENT(_chanid, _freq) \
{ \
- .chan = (_chanid), \
- .freq = (_freq), \
- .val = (_chanid), \
- .flag = IEEE80211_CHAN_W_SCAN | \
- IEEE80211_CHAN_W_ACTIVE_SCAN | \
- IEEE80211_CHAN_W_IBSS, \
- .power_level = 0x0A, \
- .antenna_max = 0xFF, \
+ .center_freq = (_freq), \
+ .hw_value = (_chanid), \
}
static struct ieee80211_channel b43legacy_bg_chantable[] = {
CHANTAB_ENT(1, 2412),
@@ -149,7 +145,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = {
CHANTAB_ENT(13, 2472),
CHANTAB_ENT(14, 2484),
};
-#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable)
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = {
+ .channels = b43legacy_bg_chantable,
+ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+ .bitrates = b43legacy_b_ratetable,
+ .n_bitrates = b43legacy_b_ratetable_size,
+};
+
+static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = {
+ .channels = b43legacy_bg_chantable,
+ .n_channels = ARRAY_SIZE(b43legacy_bg_chantable),
+ .bitrates = b43legacy_g_ratetable,
+ .n_bitrates = b43legacy_g_ratetable_size,
+};
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev);
static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev);
@@ -170,52 +179,75 @@ static int b43legacy_ratelimit(struct b43legacy_wl *wl)
void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (!b43legacy_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_INFO "b43legacy-%s: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_INFO "b43legacy-%s: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (!b43legacy_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_ERR "b43legacy-%s ERROR: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_ERR "b43legacy-%s ERROR: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
if (!b43legacy_ratelimit(wl))
return;
+
va_start(args, fmt);
- printk(KERN_WARNING "b43legacy-%s warning: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_WARNING "b43legacy-%s warning: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
#if B43legacy_DEBUG
void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...)
{
+ struct va_format vaf;
va_list args;
va_start(args, fmt);
- printk(KERN_DEBUG "b43legacy-%s debug: ",
- (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan");
- vprintk(fmt, args);
+
+ vaf.fmt = fmt;
+ vaf.va = &args;
+
+ printk(KERN_DEBUG "b43legacy-%s debug: %pV",
+ (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan", &vaf);
+
va_end(args);
}
#endif /* DEBUG */
@@ -569,42 +601,11 @@ static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev)
{
b43legacy_set_slot_time(dev, 9);
- dev->short_slot = 1;
}
static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
{
b43legacy_set_slot_time(dev, 20);
- dev->short_slot = 0;
-}
-
-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43legacy_interrupt_enable(struct b43legacy_wldev *dev,
- u32 mask)
-{
- u32 old_mask;
-
- old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask |
- mask);
-
- return old_mask;
-}
-
-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43legacy_interrupt_disable(struct b43legacy_wldev *dev,
- u32 mask)
-{
- u32 old_mask;
-
- old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
-
- return old_mask;
}
/* Synchronize IRQ top- and bottom-half.
@@ -721,9 +722,9 @@ void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags)
macctl &= ~B43legacy_MACCTL_GMODE;
if (flags & B43legacy_TMSLOW_GMODE) {
macctl |= B43legacy_MACCTL_GMODE;
- dev->phy.gmode = 1;
+ dev->phy.gmode = true;
} else
- dev->phy.gmode = 0;
+ dev->phy.gmode = false;
macctl |= B43legacy_MACCTL_IHR_ENABLED;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
}
@@ -797,9 +798,8 @@ static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
{
b43legacy_jssi_write(dev, 0x7F7F7F7F);
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
- b43legacy_read32(dev,
- B43legacy_MMIO_MACCMD)
- | (1 << 4));
+ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+ | B43legacy_MACCMD_BGNOISE);
B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
dev->phy.channel);
}
@@ -811,7 +811,7 @@ static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev)
if (dev->noisecalc.calculation_running)
return;
dev->noisecalc.channel_at_start = dev->phy.channel;
- dev->noisecalc.calculation_running = 1;
+ dev->noisecalc.calculation_running = true;
dev->noisecalc.nr_samples = 0;
b43legacy_generate_noise_sample(dev);
@@ -839,10 +839,10 @@ static void handle_irq_noise(struct b43legacy_wldev *dev)
/* Get the noise samples. */
B43legacy_WARN_ON(dev->noisecalc.nr_samples >= 8);
i = dev->noisecalc.nr_samples;
- noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
- noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
+ noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1);
dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]];
dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]];
dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]];
@@ -873,7 +873,7 @@ static void handle_irq_noise(struct b43legacy_wldev *dev)
dev->stats.link_noise = average;
drop_calculation:
- dev->noisecalc.calculation_running = 0;
+ dev->noisecalc.calculation_running = false;
return;
}
generate_new:
@@ -882,24 +882,24 @@ generate_new:
static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
{
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) {
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) {
/* TODO: PS TBTT */
} else {
if (1/*FIXME: the last PSpoll frame was sent successfully */)
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
- dev->reg124_set_0x4 = 0;
- if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
- dev->reg124_set_0x4 = 1;
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+ dev->dfq_valid = true;
}
static void handle_irq_atim_end(struct b43legacy_wldev *dev)
{
- if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
- return;
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
- b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
- | 0x4);
+ if (dev->dfq_valid) {
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
+ | B43legacy_MACCMD_DFQ_VALID);
+ dev->dfq_valid = false;
+ }
}
static void handle_irq_pmq(struct b43legacy_wldev *dev)
@@ -951,36 +951,114 @@ static void b43legacy_write_template_common(struct b43legacy_wldev *dev,
size + sizeof(struct b43legacy_plcp_hdr6));
}
+/* Convert a b43legacy antenna number value to the PHY TX control value. */
+static u16 b43legacy_antenna_to_phyctl(int antenna)
+{
+ switch (antenna) {
+ case B43legacy_ANTENNA0:
+ return B43legacy_TX4_PHY_ANT0;
+ case B43legacy_ANTENNA1:
+ return B43legacy_TX4_PHY_ANT1;
+ }
+ return B43legacy_TX4_PHY_ANTLAST;
+}
+
static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
u16 ram_offset,
- u16 shm_size_offset, u8 rate)
+ u16 shm_size_offset)
{
- int len;
- const u8 *data;
- B43legacy_WARN_ON(!dev->cached_beacon);
- len = min((size_t)dev->cached_beacon->len,
+ unsigned int i, len, variable_len;
+ const struct ieee80211_mgmt *bcn;
+ const u8 *ie;
+ bool tim_found = false;
+ unsigned int rate;
+ u16 ctl;
+ int antenna;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
+
+ bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
+ len = min_t(size_t, dev->wl->current_beacon->len,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
- data = (const u8 *)(dev->cached_beacon->data);
- b43legacy_write_template_common(dev, data,
- len, ram_offset,
+ rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
+
+ b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
shm_size_offset, rate);
+
+ /* Write the PHY TX control parameters. */
+ antenna = B43legacy_ANTENNA_DEFAULT;
+ antenna = b43legacy_antenna_to_phyctl(antenna);
+ ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_BEACPHYCTL);
+ /* We can't send beacons with short preamble. Would get PHY errors. */
+ ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL;
+ ctl &= ~B43legacy_TX4_PHY_ANT;
+ ctl &= ~B43legacy_TX4_PHY_ENC;
+ ctl |= antenna;
+ ctl |= B43legacy_TX4_PHY_ENC_CCK;
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_BEACPHYCTL, ctl);
+
+ /* Find the position of the TIM and the DTIM_period value
+ * and write them to SHM. */
+ ie = bcn->u.beacon.variable;
+ variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ for (i = 0; i < variable_len - 2; ) {
+ uint8_t ie_id, ie_len;
+
+ ie_id = ie[i];
+ ie_len = ie[i + 1];
+ if (ie_id == 5) {
+ u16 tim_position;
+ u16 dtim_period;
+ /* This is the TIM Information Element */
+
+ /* Check whether the ie_len is in the beacon data range. */
+ if (variable_len < ie_len + 2 + i)
+ break;
+ /* A valid TIM is at least 4 bytes long. */
+ if (ie_len < 4)
+ break;
+ tim_found = true;
+
+ tim_position = sizeof(struct b43legacy_plcp_hdr6);
+ tim_position += offsetof(struct ieee80211_mgmt,
+ u.beacon.variable);
+ tim_position += i;
+
+ dtim_period = ie[i + 3];
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_TIMPOS, tim_position);
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_DTIMP, dtim_period);
+ break;
+ }
+ i += ie_len + 2;
+ }
+ if (!tim_found) {
+ b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
+ "beacon template packet. AP or IBSS operation "
+ "may be broken.\n");
+ } else
+ b43legacydbg(dev->wl, "Updated beacon template\n");
}
static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
u16 shm_offset, u16 size,
- u8 rate)
+ struct ieee80211_rate *rate)
{
struct b43legacy_plcp_hdr4 plcp;
u32 tmp;
__le16 dur;
plcp.data = 0;
- b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
+ b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
+ IEEE80211_BAND_2GHZ,
size,
- B43legacy_RATE_TO_100KBPS(rate));
+ rate);
/* Write PLCP in two parts and timing for packet transfer */
tmp = le32_to_cpu(plcp.data);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset,
@@ -997,45 +1075,44 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
* 2) Patching duration field
* 3) Stripping TIM
*/
-static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
- u16 *dest_size, u8 rate)
+static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
+ u16 *dest_size,
+ struct ieee80211_rate *rate)
{
const u8 *src_data;
u8 *dest_data;
- u16 src_size;
- u16 elem_size;
- u16 src_pos;
- u16 dest_pos;
+ u16 src_size, elem_size, src_pos, dest_pos;
__le16 dur;
struct ieee80211_hdr *hdr;
+ size_t ie_start;
+
+ src_size = dev->wl->current_beacon->len;
+ src_data = (const u8 *)dev->wl->current_beacon->data;
- B43legacy_WARN_ON(!dev->cached_beacon);
- src_size = dev->cached_beacon->len;
- src_data = (const u8 *)dev->cached_beacon->data;
+ /* Get the start offset of the variable IEs in the packet. */
+ ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt,
+ u.beacon.variable));
- if (unlikely(src_size < 0x24)) {
- b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: "
- "invalid beacon\n");
+ if (B43legacy_WARN_ON(src_size < ie_start))
return NULL;
- }
dest_data = kmalloc(src_size, GFP_ATOMIC);
if (unlikely(!dest_data))
return NULL;
- /* 0x24 is offset of first variable-len Information-Element
- * in beacon frame.
- */
- memcpy(dest_data, src_data, 0x24);
- src_pos = 0x24;
- dest_pos = 0x24;
- for (; src_pos < src_size - 2; src_pos += elem_size) {
+ /* Copy the static data and all Information Elements, except the TIM. */
+ memcpy(dest_data, src_data, ie_start);
+ src_pos = ie_start;
+ dest_pos = ie_start;
+ for ( ; src_pos < src_size - 2; src_pos += elem_size) {
elem_size = src_data[src_pos + 1] + 2;
- if (src_data[src_pos] != 0x05) { /* TIM */
- memcpy(dest_data + dest_pos, src_data + src_pos,
- elem_size);
- dest_pos += elem_size;
+ if (src_data[src_pos] == 5) {
+ /* This is the TIM. */
+ continue;
}
+ memcpy(dest_data + dest_pos, src_data + src_pos, elem_size);
+ dest_pos += elem_size;
}
*dest_size = dest_pos;
hdr = (struct ieee80211_hdr *)dest_data;
@@ -1045,8 +1122,9 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
+ IEEE80211_BAND_2GHZ,
*dest_size,
- B43legacy_RATE_TO_100KBPS(rate));
+ rate);
hdr->duration_id = dur;
return dest_data;
@@ -1054,13 +1132,13 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
u16 ram_offset,
- u16 shm_size_offset, u8 rate)
+ u16 shm_size_offset,
+ struct ieee80211_rate *rate)
{
- u8 *probe_resp_data;
+ const u8 *probe_resp_data;
u16 size;
- B43legacy_WARN_ON(!dev->cached_beacon);
- size = dev->cached_beacon->len;
+ size = dev->wl->current_beacon->len;
probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate);
if (unlikely(!probe_resp_data))
return;
@@ -1069,131 +1147,156 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
* all possible basic rates
*/
b43legacy_write_probe_resp_plcp(dev, 0x31A, size,
- B43legacy_CCK_RATE_1MB);
+ &b43legacy_b_ratetable[0]);
b43legacy_write_probe_resp_plcp(dev, 0x32C, size,
- B43legacy_CCK_RATE_2MB);
+ &b43legacy_b_ratetable[1]);
b43legacy_write_probe_resp_plcp(dev, 0x33E, size,
- B43legacy_CCK_RATE_5MB);
+ &b43legacy_b_ratetable[2]);
b43legacy_write_probe_resp_plcp(dev, 0x350, size,
- B43legacy_CCK_RATE_11MB);
+ &b43legacy_b_ratetable[3]);
- size = min((size_t)size,
+ size = min_t(size_t, size,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
b43legacy_write_template_common(dev, probe_resp_data,
size, ram_offset,
- shm_size_offset, rate);
+ shm_size_offset, rate->hw_value);
kfree(probe_resp_data);
}
-static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev,
- struct sk_buff *beacon)
+static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev)
{
- if (dev->cached_beacon)
- kfree_skb(dev->cached_beacon);
- dev->cached_beacon = beacon;
+ struct b43legacy_wl *wl = dev->wl;
- return 0;
+ if (wl->beacon0_uploaded)
+ return;
+ b43legacy_write_beacon_template(dev, 0x68, 0x18);
+ /* FIXME: Probe resp upload doesn't really belong here,
+ * but we don't use that feature anyway. */
+ b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+ &__b43legacy_ratetable[3]);
+ wl->beacon0_uploaded = true;
}
-static void b43legacy_update_templates(struct b43legacy_wldev *dev)
+static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
{
- u32 status;
-
- B43legacy_WARN_ON(!dev->cached_beacon);
-
- b43legacy_write_beacon_template(dev, 0x68, 0x18,
- B43legacy_CCK_RATE_1MB);
- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
- B43legacy_CCK_RATE_1MB);
- b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
- B43legacy_CCK_RATE_11MB);
+ struct b43legacy_wl *wl = dev->wl;
- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
- status |= 0x03;
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
+ if (wl->beacon1_uploaded)
+ return;
+ b43legacy_write_beacon_template(dev, 0x468, 0x1A);
+ wl->beacon1_uploaded = true;
}
-static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
- struct sk_buff *beacon)
+static void handle_irq_beacon(struct b43legacy_wldev *dev)
{
- int err;
+ struct b43legacy_wl *wl = dev->wl;
+ u32 cmd, beacon0_valid, beacon1_valid;
- err = b43legacy_refresh_cached_beacon(dev, beacon);
- if (unlikely(err))
+ if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
return;
- b43legacy_update_templates(dev);
-}
-static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
- const u8 *ssid, u8 ssid_len)
-{
- u32 tmp;
- u16 i;
- u16 len;
-
- len = min((u16)ssid_len, (u16)0x100);
- for (i = 0; i < len; i += sizeof(u32)) {
- tmp = (u32)(ssid[i + 0]);
- if (i + 1 < len)
- tmp |= (u32)(ssid[i + 1]) << 8;
- if (i + 2 < len)
- tmp |= (u32)(ssid[i + 2]) << 16;
- if (i + 3 < len)
- tmp |= (u32)(ssid[i + 3]) << 24;
- b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
- 0x380 + i, tmp);
+ /* This is the bottom half of the asynchronous beacon update. */
+
+ /* Ignore interrupt in the future. */
+ dev->irq_mask &= ~B43legacy_IRQ_BEACON;
+
+ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+ beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
+ beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID);
+
+ /* Schedule interrupt manually, if busy. */
+ if (beacon0_valid && beacon1_valid) {
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
+ dev->irq_mask |= B43legacy_IRQ_BEACON;
+ return;
+ }
+
+ if (unlikely(wl->beacon_templates_virgin)) {
+ /* We never uploaded a beacon before.
+ * Upload both templates now, but only mark one valid. */
+ wl->beacon_templates_virgin = false;
+ b43legacy_upload_beacon0(dev);
+ b43legacy_upload_beacon1(dev);
+ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+ cmd |= B43legacy_MACCMD_BEACON0_VALID;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+ } else {
+ if (!beacon0_valid) {
+ b43legacy_upload_beacon0(dev);
+ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+ cmd |= B43legacy_MACCMD_BEACON0_VALID;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+ } else if (!beacon1_valid) {
+ b43legacy_upload_beacon1(dev);
+ cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+ cmd |= B43legacy_MACCMD_BEACON1_VALID;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+ }
}
- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
- 0x48, len);
}
-static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
- u16 beacon_int)
+static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
{
- b43legacy_time_lock(dev);
- if (dev->dev->id.revision >= 3)
- b43legacy_write32(dev, 0x188, (beacon_int << 16));
- else {
- b43legacy_write16(dev, 0x606, (beacon_int >> 6));
- b43legacy_write16(dev, 0x610, beacon_int);
+ struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+ beacon_update_trigger);
+ struct b43legacy_wldev *dev;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
+ spin_lock_irq(&wl->irq_lock);
+ /* Update beacon right away or defer to IRQ. */
+ handle_irq_beacon(dev);
+ /* The handler might have updated the IRQ mask. */
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+ dev->irq_mask);
+ mmiowb();
+ spin_unlock_irq(&wl->irq_lock);
}
- b43legacy_time_unlock(dev);
+ mutex_unlock(&wl->mutex);
}
-static void handle_irq_beacon(struct b43legacy_wldev *dev)
+/* Asynchronously update the packet templates in template RAM.
+ * Locking: Requires wl->irq_lock to be locked. */
+static void b43legacy_update_templates(struct b43legacy_wl *wl)
{
- u32 status;
+ struct sk_buff *beacon;
+ /* This is the top half of the ansynchronous beacon update. The bottom
+ * half is the beacon IRQ. Beacon update must be asynchronous to avoid
+ * sending an invalid beacon. This can happen for example, if the
+ * firmware transmits a beacon while we are updating it. */
- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ /* We could modify the existing beacon and set the aid bit in the TIM
+ * field, but that would probably require resizing and moving of data
+ * within the beacon template. Simply request a new beacon and let
+ * mac80211 do the hard work. */
+ beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+ if (unlikely(!beacon))
return;
- dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
- status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+ if (wl->current_beacon)
+ dev_kfree_skb_any(wl->current_beacon);
+ wl->current_beacon = beacon;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
+ ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
+}
- if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
- /* ACK beacon IRQ. */
- b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
- B43legacy_IRQ_BEACON);
- dev->irq_savedstate |= B43legacy_IRQ_BEACON;
- if (dev->cached_beacon)
- kfree_skb(dev->cached_beacon);
- dev->cached_beacon = NULL;
- return;
- }
- if (!(status & 0x1)) {
- b43legacy_write_beacon_template(dev, 0x68, 0x18,
- B43legacy_CCK_RATE_1MB);
- status |= 0x1;
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
- status);
- }
- if (!(status & 0x2)) {
- b43legacy_write_beacon_template(dev, 0x468, 0x1A,
- B43legacy_CCK_RATE_1MB);
- status |= 0x2;
- b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
- status);
+static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
+ u16 beacon_int)
+{
+ b43legacy_time_lock(dev);
+ if (dev->dev->id.revision >= 3) {
+ b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP,
+ (beacon_int << 16));
+ b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START,
+ (beacon_int << 10));
+ } else {
+ b43legacy_write16(dev, 0x606, (beacon_int >> 6));
+ b43legacy_write16(dev, 0x610, beacon_int);
}
+ b43legacy_time_unlock(dev);
+ b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
}
static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
@@ -1292,7 +1395,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
if (reason & B43legacy_IRQ_TX_OK)
handle_irq_transmit_status(dev);
- b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
}
@@ -1344,18 +1447,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
struct b43legacy_wldev *dev = dev_id;
u32 reason;
- if (!dev)
- return IRQ_NONE;
+ B43legacy_WARN_ON(!dev);
spin_lock(&dev->wl->irq_lock);
- if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+ if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
+ /* This can only happen on shared IRQ lines. */
goto out;
reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
if (reason == 0xffffffff) /* shared IRQ */
goto out;
ret = IRQ_HANDLED;
- reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
+ reason &= dev->irq_mask;
if (!reason)
goto out;
@@ -1379,10 +1482,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
& 0x0000DC00;
b43legacy_interrupt_ack(dev, reason);
- /* disable all IRQs. They are enabled again in the bottom half. */
- dev->irq_savedstate = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- /* save the reason code and call our bottom half. */
+ /* Disable all IRQs. They are enabled again in the bottom half. */
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+ /* Save the reason code and call our bottom half. */
dev->irq_reason = reason;
tasklet_schedule(&dev->isr_tasklet);
out:
@@ -1406,14 +1508,22 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev)
static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
{
- b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/"
+ b43legacyerr(wl, "You must go to http://wireless.kernel.org/en/users/"
"Drivers/b43#devicefirmware "
"and download the correct firmware (version 3).\n");
}
+static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
+{
+ struct b43legacy_wldev *dev = context;
+
+ dev->fwp = firmware;
+ complete(&dev->fw_load_complete);
+}
+
static int do_request_fw(struct b43legacy_wldev *dev,
const char *name,
- const struct firmware **fw)
+ const struct firmware **fw, bool async)
{
char path[sizeof(modparam_fwpostfix) + 32];
struct b43legacy_fw_header *hdr;
@@ -1426,7 +1536,24 @@ static int do_request_fw(struct b43legacy_wldev *dev,
snprintf(path, ARRAY_SIZE(path),
"b43legacy%s/%s.fw",
modparam_fwpostfix, name);
- err = request_firmware(fw, path, dev->dev->dev);
+ b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
+ if (async) {
+ init_completion(&dev->fw_load_complete);
+ err = request_firmware_nowait(THIS_MODULE, 1, path,
+ dev->dev->dev, GFP_KERNEL,
+ dev, b43legacy_fw_cb);
+ if (err) {
+ b43legacyerr(dev->wl, "Unable to load firmware\n");
+ return err;
+ }
+ /* stall here until fw ready */
+ wait_for_completion(&dev->fw_load_complete);
+ if (!dev->fwp)
+ err = -EINVAL;
+ *fw = dev->fwp;
+ } else {
+ err = request_firmware(fw, path, dev->dev->dev);
+ }
if (err) {
b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
"or load failed.\n", path);
@@ -1457,15 +1584,20 @@ err_format:
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;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -1473,7 +1605,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
filename = "ucode4";
else
filename = "ucode5";
- err = do_request_fw(dev, filename, &fw->ucode);
+ err = do_request_fw(dev, filename, &fw->ucode, true);
if (err)
goto err_load;
}
@@ -1482,12 +1614,13 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
filename = "pcm4";
else
filename = "pcm5";
- err = do_request_fw(dev, filename, &fw->pcm);
+ err = do_request_fw(dev, filename, &fw->pcm, false);
if (err)
goto err_load;
}
if (!fw->initvals) {
switch (dev->phy.type) {
+ case B43legacy_PHYTYPE_B:
case B43legacy_PHYTYPE_G:
if ((rev >= 5) && (rev <= 10))
filename = "b0g0initvals5";
@@ -1499,12 +1632,13 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals);
+ err = do_request_fw(dev, filename, &fw->initvals, false);
if (err)
goto err_load;
}
if (!fw->initvals_band) {
switch (dev->phy.type) {
+ case B43legacy_PHYTYPE_B:
case B43legacy_PHYTYPE_G:
if ((rev >= 5) && (rev <= 10))
filename = "b0g0bsinitvals5";
@@ -1518,12 +1652,18 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals_band);
+ err = do_request_fw(dev, filename, &fw->initvals_band, false);
if (err)
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:
b43legacy_print_fw_helptext(dev->wl);
@@ -1537,11 +1677,12 @@ err_no_initvals:
error:
b43legacy_release_firmware(dev);
- return err;
+ return;
}
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
{
+ struct wiphy *wiphy = dev->wl->hw->wiphy;
const size_t hdr_len = sizeof(struct b43legacy_fw_header);
const __be32 *data;
unsigned int i;
@@ -1651,6 +1792,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
+ snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u",
+ dev->fw.rev, dev->fw.patch);
+ wiphy->hw_version = dev->dev->id.coreid;
+
return 0;
error:
@@ -1690,7 +1835,7 @@ static int b43legacy_write_initvals(struct b43legacy_wldev *dev,
goto err_format;
array_size -= sizeof(iv->data.d32);
- value = be32_to_cpu(get_unaligned(&iv->data.d32));
+ value = get_unaligned_be32(&iv->data.d32);
b43legacy_write32(dev, offset, value);
iv = (const struct b43legacy_iv *)((const uint8_t *)iv +
@@ -1800,7 +1945,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
return 0;
ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,
(ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)
- & mask) | set);
+ & ~mask) | set);
return 0;
}
@@ -1840,7 +1985,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
/* Re-enable IRQs. */
spin_lock_irq(&dev->wl->irq_lock);
- b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+ dev->irq_mask);
spin_unlock_irq(&dev->wl->irq_lock);
}
}
@@ -1859,10 +2005,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
/* Mask IRQs before suspending MAC. Otherwise
* the MAC stays busy and won't suspend. */
spin_lock_irq(&dev->wl->irq_lock);
- tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
spin_unlock_irq(&dev->wl->irq_lock);
b43legacy_synchronize_irq(dev);
- dev->irq_savedstate = tmp;
b43legacy_power_saving_ctl_bits(dev, -1, 1);
b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
@@ -1899,9 +2044,9 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
ctl &= ~B43legacy_MACCTL_BEACPROMISC;
ctl |= B43legacy_MACCTL_INFRA;
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
ctl |= B43legacy_MACCTL_AP;
- else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
+ else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))
ctl &= ~B43legacy_MACCTL_INFRA;
if (wl->filter_flags & FIF_CONTROL)
@@ -2046,9 +2191,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_INFRA;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
- err = b43legacy_request_firmware(dev);
- if (err)
- goto out;
err = b43legacy_upload_microcode(dev);
if (err)
goto out; /* firmware is released later */
@@ -2125,7 +2267,7 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
value32 = ssb_read32(dev->dev, SSB_TMSLOW);
- value32 |= 0x00100000;
+ value32 |= B43legacy_TMSLOW_MACPHYCLKEN;
ssb_write32(dev->dev, SSB_TMSLOW, value32);
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
@@ -2199,7 +2341,7 @@ static void do_periodic_work(struct b43legacy_wldev *dev)
/* Periodic work locking policy:
* The whole periodic work handler is protected by
* wl->mutex. If another lock is needed somewhere in the
- * pwork callchain, it's aquired in-place, where it's needed.
+ * pwork callchain, it's acquired in-place, where it's needed.
*/
static void b43legacy_periodic_work_handler(struct work_struct *work)
{
@@ -2223,7 +2365,7 @@ out_requeue:
delay = msecs_to_jiffies(50);
else
delay = round_jiffies_relative(HZ * 15);
- queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
+ ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay);
out:
mutex_unlock(&wl->mutex);
}
@@ -2234,7 +2376,7 @@ static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
dev->periodic_state = 0;
INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler);
- queue_delayed_work(dev->wl->hw->workqueue, work, 0);
+ ieee80211_queue_delayed_work(dev->wl->hw, work, 0);
}
/* Validate access to the chip (SHM) */
@@ -2285,6 +2427,7 @@ static void b43legacy_security_init(struct b43legacy_wldev *dev)
dev->max_nr_keys - 8);
}
+#ifdef CONFIG_B43LEGACY_HWRNG
static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
{
struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv;
@@ -2300,17 +2443,21 @@ static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
return (sizeof(u16));
}
+#endif
static void b43legacy_rng_exit(struct b43legacy_wl *wl)
{
+#ifdef CONFIG_B43LEGACY_HWRNG
if (wl->rng_initialized)
hwrng_unregister(&wl->rng);
+#endif
}
static int b43legacy_rng_init(struct b43legacy_wl *wl)
{
- int err;
+ int err = 0;
+#ifdef CONFIG_B43LEGACY_HWRNG
snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
"%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
wl->rng.name = wl->rng_name;
@@ -2324,63 +2471,76 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
"number generator (%d)\n", err);
}
+#endif
return err;
}
-static int b43legacy_op_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+static void b43legacy_tx_work(struct work_struct *work)
{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- int err = -ENODEV;
- unsigned long flags;
+ struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+ tx_work);
+ struct b43legacy_wldev *dev;
+ struct sk_buff *skb;
+ int queue_num;
+ int err = 0;
- if (unlikely(!dev))
- goto out;
- if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
- goto out;
- /* DMA-TX is done without a global lock. */
- if (b43legacy_using_pio(dev)) {
- spin_lock_irqsave(&wl->irq_lock, flags);
- err = b43legacy_pio_tx(dev, skb, ctl);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- } else
- err = b43legacy_dma_tx(dev, skb, ctl);
-out:
- if (unlikely(err))
- return NETDEV_TX_BUSY;
- return NETDEV_TX_OK;
-}
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
-static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
- int queue,
- const struct ieee80211_tx_queue_params *params)
-{
- return 0;
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ while (skb_queue_len(&wl->tx_queue[queue_num])) {
+ skb = skb_dequeue(&wl->tx_queue[queue_num]);
+ if (b43legacy_using_pio(dev))
+ err = b43legacy_pio_tx(dev, skb);
+ else
+ err = b43legacy_dma_tx(dev, skb);
+ if (err == -ENOSPC) {
+ wl->tx_queue_stopped[queue_num] = 1;
+ ieee80211_stop_queue(wl->hw, queue_num);
+ skb_queue_head(&wl->tx_queue[queue_num], skb);
+ break;
+ }
+ if (unlikely(err))
+ dev_kfree_skb(skb); /* Drop it */
+ err = 0;
+ }
+
+ if (!err)
+ wl->tx_queue_stopped[queue_num] = 0;
+ }
+
+ mutex_unlock(&wl->mutex);
}
-static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
+static void b43legacy_op_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- unsigned long flags;
- int err = -ENODEV;
- if (!dev)
- goto out;
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (likely(b43legacy_status(dev) >= B43legacy_STAT_STARTED)) {
- if (b43legacy_using_pio(dev))
- b43legacy_pio_get_tx_stats(dev, stats);
- else
- b43legacy_dma_get_tx_stats(dev, stats);
- err = 0;
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
+ dev_kfree_skb_any(skb);
+ return;
}
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-out:
- return err;
+ B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+ skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+ if (!wl->tx_queue_stopped[skb->queue_mapping])
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
+ else
+ ieee80211_stop_queue(wl->hw, skb->queue_mapping);
+}
+
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ return 0;
}
static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
@@ -2420,7 +2580,7 @@ static int find_wldev_for_phymode(struct b43legacy_wl *wl,
if (d->phy.possible_phymodes & phymode) {
/* Ok, this device supports the PHY-mode.
* Set the gmode bit. */
- *gmode = 1;
+ *gmode = true;
*dev = d;
return 0;
@@ -2453,10 +2613,10 @@ static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev)
static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
unsigned int new_mode)
{
- struct b43legacy_wldev *up_dev;
+ struct b43legacy_wldev *uninitialized_var(up_dev);
struct b43legacy_wldev *down_dev;
int err;
- bool gmode = 0;
+ bool gmode = false;
int prev_status;
err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
@@ -2499,7 +2659,7 @@ static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
if (prev_status >= B43legacy_STAT_STARTED) {
err = b43legacy_wireless_core_start(up_dev);
if (err) {
- b43legacyerr(wl, "Fatal: Coult not start device for "
+ b43legacyerr(wl, "Fatal: Could not start device for "
"newly selected %s-PHY mode\n",
phymode_to_string(new_mode));
b43legacy_wireless_core_exit(up_dev);
@@ -2519,45 +2679,53 @@ init_failure:
return err;
}
-static int b43legacy_antenna_from_ieee80211(u8 antenna)
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
{
- switch (antenna) {
- case 0: /* default/diversity */
- return B43legacy_ANTENNA_DEFAULT;
- case 1: /* Antenna 0 */
- return B43legacy_ANTENNA0;
- case 2: /* Antenna 1 */
- return B43legacy_ANTENNA1;
- default:
- return B43legacy_ANTENNA_DEFAULT;
- }
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
}
static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+ u32 changed)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
struct b43legacy_phy *phy;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
- int antenna_rx;
int err = 0;
- u32 savedirqs;
- antenna_tx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_tx);
- antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
+ antenna_tx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ phy = &dev->phy;
+
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ b43legacy_set_retry_limits(dev,
+ conf->short_frame_max_tx_count,
+ conf->long_frame_max_tx_count);
+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+ if (!changed)
+ goto out_unlock_mutex;
/* Switch the PHY mode (if necessary). */
- switch (conf->phymode) {
- case MODE_IEEE80211B:
- new_phymode = B43legacy_PHYMODE_B;
- break;
- case MODE_IEEE80211G:
- new_phymode = B43legacy_PHYMODE_G;
+ switch (conf->chandef.chan->band) {
+ case IEEE80211_BAND_2GHZ:
+ if (phy->type == B43legacy_PHYTYPE_B)
+ new_phymode = B43legacy_PHYMODE_B;
+ else
+ new_phymode = B43legacy_PHYMODE_G;
break;
default:
B43legacy_WARN_ON(1);
@@ -2565,8 +2733,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
err = b43legacy_switch_phymode(wl, new_phymode);
if (err)
goto out_unlock_mutex;
- dev = wl->current_dev;
- phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@@ -2576,26 +2742,17 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags);
goto out_unlock_mutex;
}
- savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
spin_unlock_irqrestore(&wl->irq_lock, flags);
b43legacy_synchronize_irq(dev);
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel_val != phy->channel)
- b43legacy_radio_selectchannel(dev, conf->channel_val, 0);
-
- /* Enable/Disable ShortSlot timing. */
- if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
- != dev->short_slot) {
- B43legacy_WARN_ON(phy->type != B43legacy_PHYTYPE_G);
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
- b43legacy_short_slot_timing_enable(dev);
- else
- b43legacy_short_slot_timing_disable(dev);
- }
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
+ 0);
- dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+ dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
@@ -2608,13 +2765,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
/* Antennas for RX and management frame TX. */
b43legacy_mgmtframe_txantenna(dev, antenna_tx);
- /* Update templates for AP mode. */
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
- b43legacy_set_beacon_int(dev, conf->beacon_int);
-
-
- if (!!conf->radio_enabled != phy->radio_on) {
- if (conf->radio_enabled) {
+ if (wl->radio_enabled != phy->radio_on) {
+ if (wl->radio_enabled) {
b43legacy_radio_turn_on(dev);
b43legacyinfo(dev->wl, "Radio turned on by software\n");
if (!dev->radio_hw_enable)
@@ -2630,7 +2782,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
}
spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_interrupt_enable(dev, savedirqs);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
mmiowb();
spin_unlock_irqrestore(&wl->irq_lock, flags);
out_unlock_mutex:
@@ -2639,11 +2791,126 @@ out_unlock_mutex:
return err;
}
+static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates)
+{
+ struct ieee80211_supported_band *sband =
+ dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+ struct ieee80211_rate *rate;
+ int i;
+ u16 basic, direct, offset, basic_offset, rateptr;
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ rate = &sband->bitrates[i];
+
+ if (b43legacy_is_cck_rate(rate->hw_value)) {
+ direct = B43legacy_SHM_SH_CCKDIRECT;
+ basic = B43legacy_SHM_SH_CCKBASIC;
+ offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+ offset &= 0xF;
+ } else {
+ direct = B43legacy_SHM_SH_OFDMDIRECT;
+ basic = B43legacy_SHM_SH_OFDMBASIC;
+ offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+ offset &= 0xF;
+ }
+
+ rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+ if (b43legacy_is_cck_rate(rate->hw_value)) {
+ basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+ basic_offset &= 0xF;
+ } else {
+ basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+ basic_offset &= 0xF;
+ }
+
+ /*
+ * Get the pointer that we need to point to
+ * from the direct map
+ */
+ rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+ direct + 2 * basic_offset);
+ /* and write it to the basic map */
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ basic + 2 * offset, rateptr);
+ }
+}
+
+static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf,
+ u32 changed)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev;
+ unsigned long flags;
+
+ mutex_lock(&wl->mutex);
+ B43legacy_WARN_ON(wl->vif != vif);
+
+ dev = wl->current_dev;
+
+ /* Disable IRQs while reconfiguring the device.
+ * This makes it possible to drop the spinlock throughout
+ * the reconfiguration process. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ goto out_unlock_mutex;
+ }
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
+
+ if (changed & BSS_CHANGED_BSSID) {
+ b43legacy_synchronize_irq(dev);
+
+ if (conf->bssid)
+ memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+ else
+ memset(wl->bssid, 0, ETH_ALEN);
+ }
+
+ if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
+ if (changed & BSS_CHANGED_BEACON &&
+ (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+ b43legacy_update_templates(wl);
+
+ if (changed & BSS_CHANGED_BSSID)
+ b43legacy_write_mac_bssid_templates(dev);
+ }
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ b43legacy_mac_suspend(dev);
+
+ if (changed & BSS_CHANGED_BEACON_INT &&
+ (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
+ b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
+ b43legacy_set_beacon_int(dev, conf->beacon_int);
+
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ b43legacy_update_basic_rates(dev, conf->basic_rates);
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ if (conf->use_short_slot)
+ b43legacy_short_slot_timing_enable(dev);
+ else
+ b43legacy_short_slot_timing_disable(dev);
+ }
+
+ b43legacy_mac_enable(dev);
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
+ /* XXX: why? */
+ mmiowb();
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ out_unlock_mutex:
+ mutex_unlock(&wl->mutex);
+}
+
static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
- unsigned int *fflags,
- int mc_count,
- struct dev_addr_list *mc_list)
+ unsigned int *fflags,u64 multicast)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2678,43 +2945,12 @@ static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
-static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_if_conf *conf)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- unsigned long flags;
-
- if (!dev)
- return -ENODEV;
- mutex_lock(&wl->mutex);
- spin_lock_irqsave(&wl->irq_lock, flags);
- B43legacy_WARN_ON(wl->vif != vif);
- if (conf->bssid)
- memcpy(wl->bssid, conf->bssid, ETH_ALEN);
- else
- memset(wl->bssid, 0, ETH_ALEN);
- if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
- B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
- b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
- if (conf->beacon)
- b43legacy_refresh_templates(dev, conf->beacon);
- }
- b43legacy_write_mac_bssid_templates(dev);
- }
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- mutex_unlock(&wl->mutex);
-
- return 0;
-}
-
/* Locking: wl->mutex */
static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
{
struct b43legacy_wl *wl = dev->wl;
unsigned long flags;
+ int queue_num;
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
return;
@@ -2723,8 +2959,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
* setting the status to INITIALIZED, as the interrupt handler
* won't care about IRQs then. */
spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
spin_unlock_irqrestore(&wl->irq_lock, flags);
b43legacy_synchronize_irq(dev);
@@ -2735,11 +2970,16 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
/* Must unlock as it would otherwise deadlock. No races here.
* Cancel the possibly running self-rearming periodic work. */
cancel_delayed_work_sync(&dev->periodic_work);
+ cancel_work_sync(&wl->tx_work);
mutex_lock(&wl->mutex);
- ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
+ /* Drain all TX queues. */
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ while (skb_queue_len(&wl->tx_queue[queue_num]))
+ dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
+ }
- b43legacy_mac_suspend(dev);
+b43legacy_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43legacydbg(wl, "Wireless interface stopped\n");
}
@@ -2760,12 +3000,12 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
goto out;
}
/* We are ready to run. */
+ ieee80211_wake_queues(dev->wl->hw);
b43legacy_set_status(dev, B43legacy_STAT_STARTED);
/* Start data flow (TX/RX) */
b43legacy_mac_enable(dev);
- b43legacy_interrupt_enable(dev, dev->irq_savedstate);
- ieee80211_start_queues(dev->wl->hw);
+ b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
/* Start maintenance work */
b43legacy_periodic_tasks_setup(dev);
@@ -2806,7 +3046,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
break;
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -2881,12 +3121,12 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
/* Assume the radio is enabled. If it's not enabled, the state will
* immediately get fixed on the first periodic work run. */
- dev->radio_hw_enable = 1;
+ dev->radio_hw_enable = true;
phy->savedpctlreg = 0xFFFF;
- phy->aci_enable = 0;
- phy->aci_wlan_automatic = 0;
- phy->aci_hw_rssi = 0;
+ phy->aci_enable = false;
+ phy->aci_wlan_automatic = false;
+ phy->aci_hw_rssi = false;
lo = phy->_lo_pairs;
if (lo)
@@ -2918,7 +3158,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
{
/* Flags */
- dev->reg124_set_0x4 = 0;
+ dev->dfq_valid = false;
/* Stats */
memset(&dev->stats, 0, sizeof(dev->stats));
@@ -2928,7 +3168,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
/* IRQ related flags */
dev->irq_reason = 0;
memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
- dev->irq_savedstate = B43legacy_IRQ_MASKTEMPLATE;
+ dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;
dev->mac_suspended = 1;
@@ -2936,52 +3176,38 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
memset(&dev->noisecalc, 0, sizeof(dev->noisecalc));
}
-static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
-{
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- struct ssb_bus *bus = dev->dev->bus;
- u32 tmp;
+static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
+ bool idle) {
+ u16 pu_delay = 1050;
- if (bus->pcicore.dev &&
- bus->pcicore.dev->id.coreid == SSB_DEV_PCI &&
- bus->pcicore.dev->id.revision <= 5) {
- /* IMCFGLO timeouts workaround. */
- tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
- tmp &= ~SSB_IMCFGLO_REQTO;
- tmp &= ~SSB_IMCFGLO_SERTO;
- switch (bus->bustype) {
- case SSB_BUSTYPE_PCI:
- case SSB_BUSTYPE_PCMCIA:
- tmp |= 0x32;
- break;
- case SSB_BUSTYPE_SSB:
- tmp |= 0x53;
- break;
- }
- ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
- }
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle)
+ pu_delay = 500;
+ if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8))
+ pu_delay = max(pu_delay, (u16)2400);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_SPUWKUP, pu_delay);
}
-/* Write the short and long frame retry limit values. */
-static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
- unsigned int short_retry,
- unsigned int long_retry)
+/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */
+static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev)
{
- /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter. */
- short_retry = min(short_retry, (unsigned int)0xF);
- long_retry = min(long_retry, (unsigned int)0xF);
+ u16 pretbtt;
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+ /* The time value is in microseconds. */
+ if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
+ pretbtt = 2;
+ else
+ pretbtt = 250;
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ B43legacy_SHM_SH_PRETBTT, pretbtt);
+ b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt);
}
/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
{
- struct b43legacy_wl *wl = dev->wl;
struct b43legacy_phy *phy = &dev->phy;
u32 macctl;
@@ -2996,12 +3222,6 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_PSM_JMP0;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
- mutex_unlock(&wl->mutex);
- /* Must unlock as it would otherwise deadlock. No races here.
- * Cancel possibly pending workqueues. */
- cancel_work_sync(&dev->restart_work);
- mutex_lock(&wl->mutex);
-
b43legacy_leds_exit(dev);
b43legacy_rng_exit(dev->wl);
b43legacy_pio_free(dev);
@@ -3013,6 +3233,11 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
kfree(phy->tssi2dbm);
kfree(phy->lo_control);
phy->lo_control = NULL;
+ if (dev->wl->current_beacon) {
+ dev_kfree_skb_any(dev->wl->current_beacon);
+ dev->wl->current_beacon = NULL;
+ }
+
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(dev->dev->bus);
}
@@ -3039,9 +3264,9 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- phy->aci_enable = 0;
- phy->aci_wlan_automatic = 0;
- phy->aci_hw_rssi = 0;
+ phy->aci_enable = false;
+ phy->aci_wlan_automatic = false;
+ phy->aci_hw_rssi = false;
phy->antenna_diversity = 0xFFFF;
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
@@ -3094,7 +3319,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
/* Enable IRQ routing to this device. */
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
- b43legacy_imcfglo_timeouts_workaround(dev);
prepare_phy_data_for_init(dev);
b43legacy_phy_calibrate(dev);
err = b43legacy_chip_init(dev);
@@ -3158,15 +3382,14 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
if (err)
goto err_chip_exit;
- b43legacy_write16(dev, 0x0612, 0x0050);
- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050);
- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
+ b43legacy_set_synth_pu_delay(dev, 1);
ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
b43legacy_upload_card_macaddress(dev);
b43legacy_security_init(dev);
b43legacy_rng_init(wl);
+ ieee80211_wake_queues(dev->wl->hw);
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
b43legacy_leds_init(dev);
@@ -3187,7 +3410,7 @@ err_kfree_lo_control:
}
static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+ struct ieee80211_vif *vif)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -3196,26 +3419,28 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
/* TODO: allow WDS/AP devices to coexist */
- if (conf->type != IEEE80211_IF_TYPE_AP &&
- conf->type != IEEE80211_IF_TYPE_STA &&
- conf->type != IEEE80211_IF_TYPE_WDS &&
- conf->type != IEEE80211_IF_TYPE_IBSS)
+ if (vif->type != NL80211_IFTYPE_AP &&
+ vif->type != NL80211_IFTYPE_STATION &&
+ vif->type != NL80211_IFTYPE_WDS &&
+ vif->type != NL80211_IFTYPE_ADHOC)
return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
if (wl->operating)
goto out_mutex_unlock;
- b43legacydbg(wl, "Adding Interface type %d\n", conf->type);
+ b43legacydbg(wl, "Adding Interface type %d\n", vif->type);
dev = wl->current_dev;
- wl->operating = 1;
- wl->vif = conf->vif;
- wl->if_type = conf->type;
- memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+ wl->operating = true;
+ wl->vif = vif;
+ wl->if_type = vif->type;
+ memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_adjust_opmode(dev);
+ b43legacy_set_pretbtt(dev);
+ b43legacy_set_synth_pu_delay(dev, 0);
b43legacy_upload_card_macaddress(dev);
spin_unlock_irqrestore(&wl->irq_lock, flags);
@@ -3227,21 +3452,21 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
}
static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+ struct ieee80211_vif *vif)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
unsigned long flags;
- b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
+ b43legacydbg(wl, "Removing Interface type %d\n", vif->type);
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(!wl->operating);
- B43legacy_WARN_ON(wl->vif != conf->vif);
+ B43legacy_WARN_ON(wl->vif != vif);
wl->vif = NULL;
- wl->operating = 0;
+ wl->operating = false;
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_adjust_opmode(dev);
@@ -3258,11 +3483,6 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
struct b43legacy_wldev *dev = wl->current_dev;
int did_init = 0;
int err = 0;
- bool do_rfkill_exit = 0;
-
- /* First register RFkill.
- * LEDs that are registered later depend on it. */
- b43legacy_rfkill_init(dev);
/* Kill all old instance specific information to make sure
* the card won't use it in the short timeframe between start
@@ -3270,15 +3490,17 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
memset(wl->bssid, 0, ETH_ALEN);
memset(wl->mac_addr, 0, ETH_ALEN);
wl->filter_flags = 0;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
+ wl->beacon_templates_virgin = true;
+ wl->radio_enabled = true;
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
err = b43legacy_wireless_core_init(dev);
- if (err) {
- do_rfkill_exit = 1;
+ if (err)
goto out_mutex_unlock;
- }
did_init = 1;
}
@@ -3287,17 +3509,15 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
if (err) {
if (did_init)
b43legacy_wireless_core_exit(dev);
- do_rfkill_exit = 1;
goto out_mutex_unlock;
}
}
+ wiphy_rfkill_start_polling(hw->wiphy);
+
out_mutex_unlock:
mutex_unlock(&wl->mutex);
- if (do_rfkill_exit)
- b43legacy_rfkill_exit(dev);
-
return err;
}
@@ -3306,35 +3526,44 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
- b43legacy_rfkill_exit(dev);
+ cancel_work_sync(&(wl->beacon_update_trigger));
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
b43legacy_wireless_core_stop(dev);
b43legacy_wireless_core_exit(dev);
+ wl->radio_enabled = false;
mutex_unlock(&wl->mutex);
}
-static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry_limit,
- u32 long_retry_limit)
+static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta, bool set)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev;
- int err = 0;
+ unsigned long flags;
- mutex_lock(&wl->mutex);
- dev = wl->current_dev;
- if (unlikely(!dev ||
- (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
- err = -ENODEV;
- goto out_unlock;
- }
- b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
-out_unlock:
- mutex_unlock(&wl->mutex);
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_update_templates(wl);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
- return err;
+ return 0;
+}
+
+static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
+ struct survey_info *survey)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev = wl->current_dev;
+ struct ieee80211_conf *conf = &hw->conf;
+
+ if (idx != 0)
+ return -ENOENT;
+
+ survey->channel = conf->chandef.chan;
+ survey->filled = SURVEY_INFO_NOISE_DBM;
+ survey->noise = dev->stats.link_noise;
+
+ return 0;
}
static const struct ieee80211_ops b43legacy_hw_ops = {
@@ -3343,13 +3572,14 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.add_interface = b43legacy_op_add_interface,
.remove_interface = b43legacy_op_remove_interface,
.config = b43legacy_op_dev_config,
- .config_interface = b43legacy_op_config_interface,
+ .bss_info_changed = b43legacy_op_bss_info_changed,
.configure_filter = b43legacy_op_configure_filter,
.get_stats = b43legacy_op_get_stats,
- .get_tx_stats = b43legacy_op_get_tx_stats,
.start = b43legacy_op_start,
.stop = b43legacy_op_stop,
- .set_retry_limit = b43legacy_op_set_retry_limit,
+ .set_tim = b43legacy_op_beacon_set_tim,
+ .get_survey = b43legacy_op_get_survey,
+ .rfkill_poll = b43legacy_rfkill_poll,
};
/* Hard-reset the chip. Do not call this directly.
@@ -3386,6 +3616,8 @@ static void b43legacy_chip_reset(struct work_struct *work)
}
}
out:
+ if (err)
+ wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
if (err)
b43legacyerr(wl, "Controller restart FAILED\n");
@@ -3398,48 +3630,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev,
int have_gphy)
{
struct ieee80211_hw *hw = dev->wl->hw;
- struct ieee80211_hw_mode *mode;
struct b43legacy_phy *phy = &dev->phy;
- int cnt = 0;
- int err;
phy->possible_phymodes = 0;
- for (; 1; cnt++) {
- if (have_bphy) {
- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
- mode = &phy->hwmodes[cnt];
-
- mode->mode = MODE_IEEE80211B;
- mode->num_channels = b43legacy_bg_chantable_size;
- mode->channels = b43legacy_bg_chantable;
- mode->num_rates = b43legacy_b_ratetable_size;
- mode->rates = b43legacy_b_ratetable;
- err = ieee80211_register_hwmode(hw, mode);
- if (err)
- return err;
-
- phy->possible_phymodes |= B43legacy_PHYMODE_B;
- have_bphy = 0;
- continue;
- }
- if (have_gphy) {
- B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES);
- mode = &phy->hwmodes[cnt];
-
- mode->mode = MODE_IEEE80211G;
- mode->num_channels = b43legacy_bg_chantable_size;
- mode->channels = b43legacy_bg_chantable;
- mode->num_rates = b43legacy_g_ratetable_size;
- mode->rates = b43legacy_g_ratetable;
- err = ieee80211_register_hwmode(hw, mode);
- if (err)
- return err;
-
- phy->possible_phymodes |= B43legacy_PHYMODE_G;
- have_gphy = 0;
- continue;
- }
- break;
+ if (have_bphy) {
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &b43legacy_band_2GHz_BPHY;
+ phy->possible_phymodes |= B43legacy_PHYMODE_B;
+ }
+
+ if (have_gphy) {
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+ &b43legacy_band_2GHz_GPHY;
+ phy->possible_phymodes |= B43legacy_PHYMODE_G;
}
return 0;
@@ -3456,7 +3659,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
{
struct b43legacy_wl *wl = dev->wl;
struct ssb_bus *bus = dev->dev->bus;
- struct pci_dev *pdev = bus->host_pci;
+ struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
int err;
int have_bphy = 0;
int have_gphy = 0;
@@ -3488,6 +3691,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
have_bphy = 1;
dev->phy.gmode = (have_gphy || have_bphy);
+ dev->phy.radio_on = true;
tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
@@ -3547,9 +3751,11 @@ static void b43legacy_one_core_detach(struct ssb_device *dev)
struct b43legacy_wldev *wldev;
struct b43legacy_wl *wl;
+ /* Do not cancel ieee80211-workqueue based work here.
+ * See comment in b43legacy_remove(). */
+
wldev = ssb_get_drvdata(dev);
wl = wldev->wl;
- cancel_work_sync(&wldev->restart_work);
b43legacy_debugfs_remove_device(wldev);
b43legacy_wireless_core_detach(wldev);
list_del(&wldev->list);
@@ -3562,26 +3768,8 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
struct b43legacy_wl *wl)
{
struct b43legacy_wldev *wldev;
- struct pci_dev *pdev;
int err = -ENOMEM;
- if (!list_empty(&wl->devlist)) {
- /* We are not the first core on this chip. */
- pdev = dev->bus->host_pci;
- /* Only special chips support more than one wireless
- * core, although some of the other chips have more than
- * one wireless core as well. Check for this and
- * bail out early.
- */
- if (!pdev ||
- ((pdev->device != 0x4321) &&
- (pdev->device != 0x4313) &&
- (pdev->device != 0x431A))) {
- b43legacydbg(wl, "Ignoring unconnected 802.11 core\n");
- return -ENODEV;
- }
- }
-
wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
if (!wldev)
goto out;
@@ -3594,7 +3782,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
(void (*)(unsigned long))b43legacy_interrupt_tasklet,
(unsigned long)wldev);
if (modparam_pio)
- wldev->__using_pio = 1;
+ wldev->__using_pio = true;
INIT_LIST_HEAD(&wldev->list);
err = b43legacy_wireless_core_attach(wldev);
@@ -3618,7 +3806,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus)
/* boardflags workarounds */
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E &&
- bus->boardinfo.rev > 0x40)
+ bus->sprom.board_rev > 0x40)
bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
}
@@ -3637,6 +3825,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
struct ieee80211_hw *hw;
struct b43legacy_wl *wl;
int err = -ENOMEM;
+ int queue_num;
b43legacy_sprom_fixup(dev->bus);
@@ -3647,12 +3836,15 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
}
/* fill hw info */
- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
- IEEE80211_HW_RX_INCLUDES_FCS;
- hw->max_signal = 100;
- hw->max_rssi = -110;
- hw->max_noise = -110;
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_SIGNAL_DBM;
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_WDS) |
+ BIT(NL80211_IFTYPE_ADHOC);
hw->queues = 1; /* FIXME: hardware has more queues */
+ hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
@@ -3667,9 +3859,18 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
spin_lock_init(&wl->leds_lock);
mutex_init(&wl->mutex);
INIT_LIST_HEAD(&wl->devlist);
+ INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
+ INIT_WORK(&wl->tx_work, b43legacy_tx_work);
+
+ /* Initialize queues and flags. */
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ skb_queue_head_init(&wl->tx_queue[queue_num]);
+ wl->tx_queue_stopped[queue_num] = 0;
+ }
ssb_set_devtypedata(dev, wl);
- b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+ b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+ dev->bus->chip_id, dev->id.revision);
err = 0;
out:
return err;
@@ -3696,17 +3897,13 @@ static int b43legacy_probe(struct ssb_device *dev,
if (err)
goto err_wireless_exit;
- if (first) {
- err = ieee80211_register_hw(wl->hw);
- if (err)
- goto err_one_core_detach;
- }
+ /* setup and start work to load firmware */
+ INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
+ schedule_work(&wl->firmware_load);
out:
return err;
-err_one_core_detach:
- b43legacy_one_core_detach(dev);
err_wireless_exit:
if (first)
b43legacy_wireless_exit(dev, wl);
@@ -3718,7 +3915,15 @@ static void b43legacy_remove(struct ssb_device *dev)
struct b43legacy_wl *wl = ssb_get_devtypedata(dev);
struct b43legacy_wldev *wldev = ssb_get_drvdata(dev);
+ /* We must cancel any work here before unregistering from ieee80211,
+ * as the ieee80211 unreg will destroy the workqueue. */
+ cancel_work_sync(&wldev->restart_work);
+ cancel_work_sync(&wl->firmware_load);
+ complete(&wldev->fw_load_complete);
+
B43legacy_WARN_ON(!wl);
+ if (!wldev->fw.ucode)
+ return; /* NULL if fw never loaded */
if (wl->current_dev == wldev)
ieee80211_unregister_hw(wl->hw);
@@ -3739,7 +3944,7 @@ void b43legacy_controller_restart(struct b43legacy_wldev *dev,
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
return;
b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason);
- queue_work(dev->wl->hw->workqueue, &dev->restart_work);
+ ieee80211_queue_work(dev->wl->hw, &dev->restart_work);
}
#ifdef CONFIG_PM
@@ -3788,10 +3993,10 @@ static int b43legacy_resume(struct ssb_device *dev)
goto out;
}
}
- mutex_unlock(&wl->mutex);
b43legacydbg(wl, "Device resumed.\n");
out:
+ mutex_unlock(&wl->mutex);
return err;
}
@@ -3811,7 +4016,7 @@ static struct ssb_driver b43legacy_ssb_driver = {
static void b43legacy_print_driverinfo(void)
{
- const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "",
+ const char *feat_pci = "", *feat_leds = "",
*feat_pio = "", *feat_dma = "";
#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT
@@ -3820,9 +4025,6 @@ static void b43legacy_print_driverinfo(void)
#ifdef CONFIG_B43LEGACY_LEDS
feat_leds = "L";
#endif
-#ifdef CONFIG_B43LEGACY_RFKILL
- feat_rfkill = "R";
-#endif
#ifdef CONFIG_B43LEGACY_PIO
feat_pio = "I";
#endif
@@ -3830,9 +4032,8 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
- "[ Features: %s%s%s%s%s, Firmware-ID: "
- B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
- feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);
+ "[ Features: %s%s%s%s ]\n",
+ feat_pci, feat_leds, feat_pio, feat_dma);
}
static int __init b43legacy_init(void)
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 1f0e2e379b0..b74a058d7ba 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 8e5c09b8187..995c7d0c212 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -31,6 +31,8 @@
#include <linux/delay.h>
#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
#include <linux/types.h>
#include "b43legacy.h"
@@ -103,7 +105,7 @@ void b43legacy_phy_lock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_suspend(dev);
} else {
- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, 1);
}
}
@@ -118,7 +120,7 @@ void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
if (dev->dev->id.revision < 3) {
b43legacy_mac_enable(dev);
} else {
- if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
}
@@ -151,7 +153,7 @@ void b43legacy_phy_calibrate(struct b43legacy_wldev *dev)
phy->calibrated = 1;
}
-/* intialize B PHY power control
+/* initialize B PHY power control
* as described in http://bcm-specs.sipsolutions.net/InitPowerControl
*/
static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev)
@@ -406,7 +408,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
if (is_bcm_board_vendor(dev) &&
(dev->dev->bus->boardinfo.type == 0x0416) &&
- (dev->dev->bus->boardinfo.rev == 0x0017))
+ (dev->dev->bus->sprom.board_rev == 0x0017))
return;
b43legacy_ilt_write(dev, 0x5001, 0x0002);
@@ -422,7 +424,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev)
if (is_bcm_board_vendor(dev) &&
(dev->dev->bus->boardinfo.type == 0x0416) &&
- (dev->dev->bus->boardinfo.rev == 0x0017))
+ (dev->dev->bus->sprom.board_rev == 0x0017))
return;
b43legacy_ilt_write(dev, 0x0401, 0x0002);
@@ -595,12 +597,14 @@ static void b43legacy_phy_initb5(struct b43legacy_wldev *dev)
0x0035) & 0xFFC0) | 0x0064);
b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
0x005D) & 0xFF80) | 0x000A);
+ b43legacy_phy_write(dev, 0x5B, 0x0000);
+ b43legacy_phy_write(dev, 0x5C, 0x0000);
}
if (dev->bad_frames_preempt)
b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD,
b43legacy_phy_read(dev,
- B43legacy_PHY_RADIO_BITFIELD) | (1 << 11));
+ B43legacy_PHY_RADIO_BITFIELD) | (1 << 12));
if (phy->analog == 1) {
b43legacy_phy_write(dev, 0x0026, 0xCE00);
@@ -753,7 +757,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_radio_write16(dev, 0x0050, 0x0020);
}
if (phy->radio_rev <= 2) {
- b43legacy_radio_write16(dev, 0x007C, 0x0020);
+ b43legacy_radio_write16(dev, 0x0050, 0x0020);
b43legacy_radio_write16(dev, 0x005A, 0x0070);
b43legacy_radio_write16(dev, 0x005B, 0x007B);
b43legacy_radio_write16(dev, 0x005C, 0x00B0);
@@ -771,7 +775,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x002A, 0x8AC0);
b43legacy_phy_write(dev, 0x0038, 0x0668);
b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
- if (phy->radio_rev <= 5)
+ if (phy->radio_rev == 4 || phy->radio_rev == 5)
b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev,
0x005D) & 0xFF80) | 0x0003);
if (phy->radio_rev <= 2)
@@ -1010,7 +1014,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_initb5(dev);
else
b43legacy_phy_initb6(dev);
- if (phy->rev >= 2 || phy->gmode)
+ if (phy->rev >= 2 && phy->gmode)
b43legacy_phy_inita(dev);
if (phy->rev >= 2) {
@@ -1025,18 +1029,22 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0811, 0x0400);
b43legacy_phy_write(dev, 0x0015, 0x00C0);
}
- if (phy->rev >= 2 || phy->gmode) {
+ if (phy->gmode) {
tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF;
- if (tmp == 3 || tmp == 5) {
+ if (tmp == 3) {
+ b43legacy_phy_write(dev, 0x04C2, 0x1816);
+ b43legacy_phy_write(dev, 0x04C3, 0x8606);
+ }
+ if (tmp == 4 || tmp == 5) {
b43legacy_phy_write(dev, 0x04C2, 0x1816);
b43legacy_phy_write(dev, 0x04C3, 0x8006);
- if (tmp == 5)
- b43legacy_phy_write(dev, 0x04CC,
- (b43legacy_phy_read(dev,
- 0x04CC) & 0x00FF) |
- 0x1F00);
+ b43legacy_phy_write(dev, 0x04CC,
+ (b43legacy_phy_read(dev,
+ 0x04CC) & 0x00FF) |
+ 0x1F00);
}
- b43legacy_phy_write(dev, 0x047E, 0x0078);
+ if (phy->rev >= 2)
+ b43legacy_phy_write(dev, 0x047E, 0x0078);
}
if (phy->radio_rev == 8) {
b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801)
@@ -1078,7 +1086,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
else
b43legacy_phy_write(dev, 0x002F, 0x0202);
}
- if (phy->gmode || phy->rev >= 2) {
+ if (phy->gmode) {
b43legacy_phy_lo_adjust(dev, 0);
b43legacy_phy_write(dev, 0x080F, 0x8078);
}
@@ -1088,7 +1096,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
* Essentially, what we do here is resetting all NRSSI LT
- * entries to -32 (see the limit_value() in nrssi_hw_update())
+ * entries to -32 (see the clamp_val() in nrssi_hw_update())
*/
b43legacy_nrssi_hw_update(dev, 0xFFFF);
b43legacy_calc_nrssi_threshold(dev);
@@ -1290,12 +1298,10 @@ void b43legacy_lo_write(struct b43legacy_wldev *dev,
/* Sanity check. */
if (pair->low < -8 || pair->low > 8 ||
pair->high < -8 || pair->high > 8) {
- struct b43legacy_phy *phy = &dev->phy;
b43legacydbg(dev->wl,
"WARNING: Writing invalid LOpair "
- "(low: %d, high: %d, index: %lu)\n",
- pair->low, pair->high,
- (unsigned long)(pair - phy->_lo_pairs));
+ "(low: %d, high: %d)\n",
+ pair->low, pair->high);
dump_stack();
}
#endif
@@ -1756,7 +1762,7 @@ static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi)
switch (phy->type) {
case B43legacy_PHYTYPE_B:
case B43legacy_PHYTYPE_G:
- tmp = limit_value(tmp, 0x00, 0x3F);
+ tmp = clamp_val(tmp, 0x00, 0x3F);
dbm = phy->tssi2dbm[tmp];
break;
default:
@@ -1854,12 +1860,12 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
* which accounts for the factor of 4 */
#define REG_MAX_PWR 20
max_pwr = min(REG_MAX_PWR * 4
- - dev->dev->bus->sprom.antenna_gain.ghz24.a0
+ - dev->dev->bus->sprom.antenna_gain.a0
- 0x6, max_pwr);
/* find the desired power in Q5.2 - power_level is in dBm
* and limit it - max_pwr is already in Q5.2 */
- desired_pwr = limit_value(phy->power_level << 2, 0, max_pwr);
+ desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr);
if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER))
b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT
" dBm, Desired TX power output: " Q52_FMT
@@ -1905,7 +1911,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
radio_attenuation++;
}
}
- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
+ baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
txpower = phy->txctl1;
if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) {
@@ -1933,8 +1939,8 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
}
/* Save the control values */
phy->txctl1 = txpower;
- baseband_attenuation = limit_value(baseband_attenuation, 0, 11);
- radio_attenuation = limit_value(radio_attenuation, 0, 9);
+ baseband_attenuation = clamp_val(baseband_attenuation, 0, 11);
+ radio_attenuation = clamp_val(radio_attenuation, 0, 9);
phy->rfatt = radio_attenuation;
phy->bbatt = baseband_attenuation;
@@ -1979,7 +1985,7 @@ s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2)
f = q;
i++;
} while (delta >= 2);
- entry[index] = limit_value(b43legacy_tssi2dbm_ad(m1 * f, 8192),
+ entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192),
-127, 128);
return 0;
}
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index ecbe409f9a9..831a7a4760e 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index bcdd54eb2ed..282eedec675 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -4,7 +4,7 @@
PIO Transmission
- Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005 Michael Buesch <m@bues.ch>
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
@@ -29,6 +29,7 @@
#include "xmit.h"
#include <linux/delay.h>
+#include <linux/slab.h>
static void tx_start(struct b43legacy_pioqueue *queue)
@@ -196,7 +197,7 @@ static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue,
B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0);
err = b43legacy_generate_txhdr(queue->dev,
txhdr, skb->data, skb->len,
- &packet->txstat.control,
+ IEEE80211_SKB_CB(skb),
generate_cookie(queue, packet));
if (err)
return err;
@@ -381,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)
{
struct b43legacy_pio_txpacket *packet, *tmp_packet;
- tasklet_disable(&queue->txtask);
+ tasklet_kill(&queue->txtask);
list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
free_txpacket(packet, 0);
@@ -443,7 +444,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev)
pio->queue3 = queue;
if (dev->dev->id.revision < 3)
- dev->irq_savedstate |= B43legacy_IRQ_PIO_WORKAROUND;
+ dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND;
b43legacydbg(dev->wl, "PIO initialized\n");
err = 0;
@@ -463,8 +464,7 @@ err_destroy0:
}
int b43legacy_pio_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+ struct sk_buff *skb)
{
struct b43legacy_pioqueue *queue = dev->pio.queue1;
struct b43legacy_pio_txpacket *packet;
@@ -476,12 +476,8 @@ int b43legacy_pio_tx(struct b43legacy_wldev *dev,
list);
packet->skb = skb;
- memset(&packet->txstat, 0, sizeof(packet->txstat));
- memcpy(&packet->txstat.control, ctl, sizeof(*ctl));
-
list_move_tail(&packet->list, &queue->txqueue);
queue->nr_txfree--;
- queue->nr_tx_packets++;
B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS);
tasklet_schedule(&queue->txtask);
@@ -494,6 +490,8 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
{
struct b43legacy_pioqueue *queue;
struct b43legacy_pio_txpacket *packet;
+ struct ieee80211_tx_info *info;
+ int retry_limit;
queue = parse_cookie(dev, status->cookie, &packet);
B43legacy_WARN_ON(!queue);
@@ -505,11 +503,39 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
queue->tx_devq_used -= (packet->skb->len +
sizeof(struct b43legacy_txhdr_fw3));
+ info = IEEE80211_SKB_CB(packet->skb);
+
+ /* preserve the confiured retry limit before clearing the status
+ * The xmit function has overwritten the rc's value with the actual
+ * retry limit done by the hardware */
+ retry_limit = info->status.rates[0].count;
+ ieee80211_tx_info_clear_status(info);
+
if (status->acked)
- packet->txstat.flags |= IEEE80211_TX_STATUS_ACK;
- packet->txstat.retry_count = status->frame_count - 1;
- ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb,
- &(packet->txstat));
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+ /*
+ * If the short retries (RTS, not data frame) have exceeded
+ * the limit, the hw will not have tried the selected rate,
+ * but will have used the fallback rate instead.
+ * Don't let the rate control count attempts for the selected
+ * rate in this case, otherwise the statistics will be off.
+ */
+ info->status.rates[0].count = 0;
+ info->status.rates[1].count = status->frame_count;
+ } else {
+ if (status->frame_count > retry_limit) {
+ info->status.rates[0].count = retry_limit;
+ info->status.rates[1].count = status->frame_count -
+ retry_limit;
+
+ } else {
+ info->status.rates[0].count = status->frame_count;
+ info->status.rates[1].idx = -1;
+ }
+ }
+ ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb);
packet->skb = NULL;
free_txpacket(packet, 1);
@@ -520,20 +546,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
tasklet_schedule(&queue->txtask);
}
-void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
- struct b43legacy_pio *pio = &dev->pio;
- struct b43legacy_pioqueue *queue;
- struct ieee80211_tx_queue_stats_data *data;
-
- queue = pio->queue1;
- data = &(stats->data[0]);
- data->len = B43legacy_PIO_MAXTXPACKETS - queue->nr_txfree;
- data->limit = B43legacy_PIO_MAXTXPACKETS;
- data->count = queue->nr_tx_packets;
-}
-
static void pio_rx_error(struct b43legacy_pioqueue *queue,
int clear_buffers,
const char *error)
diff --git a/drivers/net/wireless/b43legacy/pio.h b/drivers/net/wireless/b43legacy/pio.h
index 5bfed0c4003..8e6773ea6e7 100644
--- a/drivers/net/wireless/b43legacy/pio.h
+++ b/drivers/net/wireless/b43legacy/pio.h
@@ -41,7 +41,6 @@ struct b43legacy_xmitstatus;
struct b43legacy_pio_txpacket {
struct b43legacy_pioqueue *queue;
struct sk_buff *skb;
- struct ieee80211_tx_status txstat;
struct list_head list;
};
@@ -75,10 +74,6 @@ struct b43legacy_pioqueue {
* posted to the device. We are waiting for the txstatus.
*/
struct list_head txrunning;
- /* Total number or packets sent.
- * (This counter can obviously wrap).
- */
- unsigned int nr_tx_packets;
struct tasklet_struct txtask;
struct b43legacy_pio_txpacket
tx_packets_cache[B43legacy_PIO_MAXTXPACKETS];
@@ -104,12 +99,9 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev);
void b43legacy_pio_free(struct b43legacy_wldev *dev);
int b43legacy_pio_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl);
+ struct sk_buff *skb);
void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
const struct b43legacy_txstatus *status);
-void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats);
void b43legacy_pio_rx(struct b43legacy_pioqueue *queue);
/* Suspend TX queue in hardware. */
@@ -132,8 +124,7 @@ void b43legacy_pio_free(struct b43legacy_wldev *dev)
}
static inline
int b43legacy_pio_tx(struct b43legacy_wldev *dev,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+ struct sk_buff *skb)
{
return 0;
}
@@ -143,11 +134,6 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
{
}
static inline
-void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
-}
-static inline
void b43legacy_pio_rx(struct b43legacy_pioqueue *queue)
{
}
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index 955832e8654..89617769039 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -357,7 +357,7 @@ void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val)
for (i = 0; i < 64; i++) {
tmp = b43legacy_nrssi_hw_read(dev, i);
tmp -= val;
- tmp = limit_value(tmp, -32, 31);
+ tmp = clamp_val(tmp, -32, 31);
b43legacy_nrssi_hw_write(dev, i, tmp);
}
}
@@ -375,7 +375,7 @@ void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev)
tmp = (i - delta) * phy->nrssislope;
tmp /= 0x10000;
tmp += 0x3A;
- tmp = limit_value(tmp, 0, 0x3F);
+ tmp = clamp_val(tmp, 0, 0x3F);
phy->nrssi_lt[i] = tmp;
}
}
@@ -839,7 +839,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
} else
threshold = phy->nrssi[1] - 5;
- threshold = limit_value(threshold, 0, 0x3E);
+ threshold = clamp_val(threshold, 0, 0x3E);
b43legacy_phy_read(dev, 0x0020); /* dummy read */
b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8)
| 0x001C);
@@ -892,7 +892,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
else
a += 32;
a = a >> 6;
- a = limit_value(a, -31, 31);
+ a = clamp_val(a, -31, 31);
b = b * (phy->nrssi[1] - phy->nrssi[0]);
b += (phy->nrssi[0] << 6);
@@ -901,7 +901,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
else
b += 32;
b = b >> 6;
- b = limit_value(b, -31, 31);
+ b = clamp_val(b, -31, 31);
tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000;
tmp_u16 |= ((u32)b & 0x0000003F);
@@ -1067,7 +1067,7 @@ b43legacy_radio_interference_mitigation_enable(struct b43legacy_wldev *dev,
if (b43legacy_phy_read(dev, 0x0033) & 0x0800)
break;
- phy->aci_enable = 1;
+ phy->aci_enable = true;
phy_stacksave(B43legacy_PHY_RADIO_BITFIELD);
phy_stacksave(B43legacy_PHY_G_CRS);
@@ -1279,7 +1279,7 @@ b43legacy_radio_interference_mitigation_disable(struct b43legacy_wldev *dev,
if (!(b43legacy_phy_read(dev, 0x0033) & 0x0800))
break;
- phy->aci_enable = 0;
+ phy->aci_enable = false;
phy_stackrestore(B43legacy_PHY_RADIO_BITFIELD);
phy_stackrestore(B43legacy_PHY_G_CRS);
@@ -1346,10 +1346,10 @@ int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev,
(phy->rev == 0) || (!phy->gmode))
return -ENODEV;
- phy->aci_wlan_automatic = 0;
+ phy->aci_wlan_automatic = false;
switch (mode) {
case B43legacy_RADIO_INTERFMODE_AUTOWLAN:
- phy->aci_wlan_automatic = 1;
+ phy->aci_wlan_automatic = true;
if (phy->aci_enable)
mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN;
else
@@ -1371,8 +1371,8 @@ int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev,
currentmode);
if (mode == B43legacy_RADIO_INTERFMODE_NONE) {
- phy->aci_enable = 0;
- phy->aci_hw_rssi = 0;
+ phy->aci_enable = false;
+ phy->aci_hw_rssi = false;
} else
b43legacy_radio_interference_mitigation_enable(dev, mode);
phy->interfmode = mode;
@@ -1905,7 +1905,7 @@ void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower)
u16 dac;
u16 ilt;
- txpower = limit_value(txpower, 0, 63);
+ txpower = clamp_val(txpower, 0, 63);
pamp = b43legacy_get_txgain_freq_power_amp(txpower);
pamp <<= 5;
@@ -1998,7 +1998,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
if (phy->type == B43legacy_PHYTYPE_G) {
if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type == 0x421 &&
- dev->dev->bus->boardinfo.rev >= 30)
+ dev->dev->bus->sprom.board_rev >= 30)
att = 3;
else if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type == 0x416)
@@ -2008,7 +2008,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
} else {
if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type == 0x421 &&
- dev->dev->bus->boardinfo.rev >= 30)
+ dev->dev->bus->sprom.board_rev >= 30)
att = 7;
else
att = 6;
@@ -2018,7 +2018,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
if (phy->type == B43legacy_PHYTYPE_G) {
if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type == 0x421 &&
- dev->dev->bus->boardinfo.rev >= 30)
+ dev->dev->bus->sprom.board_rev >= 30)
att = 3;
else if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type ==
@@ -2052,9 +2052,9 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev)
}
if (is_bcm_board_vendor(dev) &&
dev->dev->bus->boardinfo.type == 0x421) {
- if (dev->dev->bus->boardinfo.rev < 0x43)
+ if (dev->dev->bus->sprom.board_rev < 0x43)
att = 2;
- else if (dev->dev->bus->boardinfo.rev < 0x51)
+ else if (dev->dev->bus->sprom.board_rev < 0x51)
att = 3;
}
if (att == 0xFFFF)
@@ -2102,7 +2102,7 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
phy->radio_off_context.rfover);
b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
phy->radio_off_context.rfoverval);
- phy->radio_off_context.valid = 0;
+ phy->radio_off_context.valid = false;
}
channel = phy->channel;
err = b43legacy_radio_selectchannel(dev,
@@ -2113,7 +2113,7 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
default:
B43legacy_BUG_ON(1);
}
- phy->radio_on = 1;
+ phy->radio_on = true;
}
void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force)
@@ -2131,14 +2131,14 @@ void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force)
if (!force) {
phy->radio_off_context.rfover = rfover;
phy->radio_off_context.rfoverval = rfoverval;
- phy->radio_off_context.valid = 1;
+ phy->radio_off_context.valid = true;
}
b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
rfoverval & 0xFF73);
} else
b43legacy_phy_write(dev, 0x0015, 0xAA00);
- phy->radio_on = 0;
+ phy->radio_on = false;
b43legacydbg(dev->wl, "Radio initialized\n");
}
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index ec4de2811c5..bccb3d7da68 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -4,7 +4,7 @@
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
Stefano Brivio <stefano.brivio@polimi.it>
- Michael Buesch <mbuesch@freenet.de>
+ Michael Buesch <m@bues.ch>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index d178dfbb1c9..c4559bcbc70 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
RFKILL support
- Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2007 Michael Buesch <m@bues.ch>
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
@@ -22,21 +22,25 @@
*/
-#include "rfkill.h"
#include "radio.h"
#include "b43legacy.h"
-#include <linux/kmod.h>
-
/* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
{
- if (dev->phy.rev >= 3) {
+ if (dev->dev->id.revision >= 3) {
if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
& B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
return 1;
} else {
+ /* To prevent CPU fault on PPC, do not read a register
+ * unless the interface is started; however, on resume
+ * for hibernation, this routine is entered early. When
+ * that happens, unconditionally return TRUE.
+ */
+ if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
+ return 1;
if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
& B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
return 1;
@@ -45,161 +49,43 @@ static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
}
/* The poll callback for the hardware button. */
-static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw)
{
- struct b43legacy_wldev *dev = poll_dev->private;
- struct b43legacy_wl *wl = dev->wl;
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev = wl->current_dev;
+ struct ssb_bus *bus = dev->dev->bus;
bool enabled;
- bool report_change = 0;
+ bool brought_up = false;
mutex_lock(&wl->mutex);
if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
- mutex_unlock(&wl->mutex);
- return;
+ if (ssb_bus_powerup(bus, 0)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+ ssb_device_enable(dev->dev, 0);
+ brought_up = true;
}
+
enabled = b43legacy_is_hw_radio_enabled(dev);
+
if (unlikely(enabled != dev->radio_hw_enable)) {
dev->radio_hw_enable = enabled;
- report_change = 1;
b43legacyinfo(wl, "Radio hardware status changed to %s\n",
enabled ? "ENABLED" : "DISABLED");
- }
- mutex_unlock(&wl->mutex);
-
- /* send the radio switch event to the system - note both a key press
- * and a release are required */
- if (unlikely(report_change)) {
- input_report_key(poll_dev->input, KEY_WLAN, 1);
- input_report_key(poll_dev->input, KEY_WLAN, 0);
- }
-}
-
-/* Called when the RFKILL toggled in software.
- * This is called without locking. */
-static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state)
-{
- struct b43legacy_wldev *dev = data;
- struct b43legacy_wl *wl = dev->wl;
- int err = -EBUSY;
-
- if (!wl->rfkill.registered)
- return 0;
-
- mutex_lock(&wl->mutex);
- if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
- goto out_unlock;
- err = 0;
- switch (state) {
- case RFKILL_STATE_ON:
- if (!dev->radio_hw_enable) {
- /* No luck. We can't toggle the hardware RF-kill
- * button from software. */
- err = -EBUSY;
- goto out_unlock;
+ wiphy_rfkill_set_hw_state(hw->wiphy, !enabled);
+ if (enabled != dev->phy.radio_on) {
+ if (enabled)
+ b43legacy_radio_turn_on(dev);
+ else
+ b43legacy_radio_turn_off(dev, 0);
}
- if (!dev->phy.radio_on)
- b43legacy_radio_turn_on(dev);
- break;
- case RFKILL_STATE_OFF:
- if (dev->phy.radio_on)
- b43legacy_radio_turn_off(dev, 0);
- break;
}
-out_unlock:
- mutex_unlock(&wl->mutex);
-
- return err;
-}
-
-char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
-{
- struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
-
- if (!rfk->registered)
- return NULL;
- return rfkill_get_led_name(rfk->rfkill);
-}
-
-void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
-{
- struct b43legacy_wl *wl = dev->wl;
- struct b43legacy_rfkill *rfk = &(wl->rfkill);
- int err;
-
- rfk->registered = 0;
-
- rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
- if (!rfk->rfkill)
- goto out_error;
- snprintf(rfk->name, sizeof(rfk->name),
- "b43legacy-%s", wiphy_name(wl->hw->wiphy));
- rfk->rfkill->name = rfk->name;
- rfk->rfkill->state = RFKILL_STATE_ON;
- rfk->rfkill->data = dev;
- rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
- rfk->rfkill->user_claim_unsupported = 1;
-
- rfk->poll_dev = input_allocate_polled_device();
- if (!rfk->poll_dev) {
- rfkill_free(rfk->rfkill);
- goto err_freed_rfk;
+ if (brought_up) {
+ ssb_device_disable(dev->dev, 0);
+ ssb_bus_may_powerdown(bus);
}
- rfk->poll_dev->private = dev;
- rfk->poll_dev->poll = b43legacy_rfkill_poll;
- rfk->poll_dev->poll_interval = 1000; /* msecs */
-
- rfk->poll_dev->input->name = rfk->name;
- rfk->poll_dev->input->id.bustype = BUS_HOST;
- rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
- rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
- set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
-
- err = rfkill_register(rfk->rfkill);
- if (err)
- goto err_free_polldev;
-
-#ifdef CONFIG_RFKILL_INPUT_MODULE
- /* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
- * Try to load the module. */
- err = request_module("rfkill-input");
- if (err)
- b43legacywarn(wl, "Failed to load the rfkill-input module."
- "The built-in radio LED will not work.\n");
-#endif /* CONFIG_RFKILL_INPUT */
-
- err = input_register_polled_device(rfk->poll_dev);
- if (err)
- goto err_unreg_rfk;
-
- rfk->registered = 1;
-
- return;
-err_unreg_rfk:
- rfkill_unregister(rfk->rfkill);
-err_free_polldev:
- input_free_polled_device(rfk->poll_dev);
- rfk->poll_dev = NULL;
-err_freed_rfk:
- rfk->rfkill = NULL;
-out_error:
- rfk->registered = 0;
- b43legacywarn(wl, "RF-kill button init failed\n");
-}
-
-void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
-{
- struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
-
- if (!rfk->registered)
- return;
- rfk->registered = 0;
-
- input_unregister_polled_device(rfk->poll_dev);
- rfkill_unregister(rfk->rfkill);
- input_free_polled_device(rfk->poll_dev);
- rfk->poll_dev = NULL;
- rfk->rfkill = NULL;
+ mutex_unlock(&wl->mutex);
}
-
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
index 11150a8032f..75585571c54 100644
--- a/drivers/net/wireless/b43legacy/rfkill.h
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -1,59 +1,11 @@
#ifndef B43legacy_RFKILL_H_
#define B43legacy_RFKILL_H_
+struct ieee80211_hw;
struct b43legacy_wldev;
-#ifdef CONFIG_B43LEGACY_RFKILL
+void b43legacy_rfkill_poll(struct ieee80211_hw *hw);
-#include <linux/rfkill.h>
-#include <linux/workqueue.h>
-#include <linux/input-polldev.h>
-
-
-
-struct b43legacy_rfkill {
- /* The RFKILL subsystem data structure */
- struct rfkill *rfkill;
- /* The poll device for the RFKILL input button */
- struct input_polled_dev *poll_dev;
- /* Did initialization succeed? Used for freeing. */
- bool registered;
- /* The unique name of this rfkill switch */
- char name[sizeof("b43legacy-phy4294967295")];
-};
-
-/* The init function returns void, because we are not interested
- * in failing the b43 init process when rfkill init failed. */
-void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
-void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
-
-char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
-
-
-#else /* CONFIG_B43LEGACY_RFKILL */
-/* No RFKILL support. */
-
-struct b43legacy_rfkill {
- /* empty */
-};
-
-static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
-{
-}
-static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
-{
-}
-static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
-{
- return NULL;
-}
-
-#endif /* CONFIG_B43LEGACY_RFKILL */
+bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev);
#endif /* B43legacy_RFKILL_H_ */
diff --git a/drivers/net/wireless/b43legacy/sysfs.c b/drivers/net/wireless/b43legacy/sysfs.c
index 56c384fa9b1..2a1da15c913 100644
--- a/drivers/net/wireless/b43legacy/sysfs.c
+++ b/drivers/net/wireless/b43legacy/sysfs.c
@@ -4,7 +4,7 @@
SYSFS support routines
- Copyright (c) 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2006 Michael Buesch <m@bues.ch>
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
@@ -42,7 +42,7 @@ static int get_integer(const char *buf, size_t count)
if (count == 0)
goto out;
- count = min(count, (size_t)10);
+ count = min_t(size_t, count, 10);
memcpy(tmp, buf, count);
ret = simple_strtol(tmp, NULL, 10);
out:
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index d84408a82db..34bf3f0b729 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -6,7 +6,7 @@
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
- Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ Copyright (C) 2005, 2006 Michael Buesch <m@bues.ch>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
Copyright (C) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -37,45 +37,48 @@
/* Extract the bitrate out of a CCK PLCP header. */
-static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp)
+static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp)
{
switch (plcp->raw[0]) {
case 0x0A:
- return B43legacy_CCK_RATE_1MB;
+ return 0;
case 0x14:
- return B43legacy_CCK_RATE_2MB;
+ return 1;
case 0x37:
- return B43legacy_CCK_RATE_5MB;
+ return 2;
case 0x6E:
- return B43legacy_CCK_RATE_11MB;
+ return 3;
}
B43legacy_BUG_ON(1);
- return 0;
+ return -1;
}
/* Extract the bitrate out of an OFDM PLCP header. */
-static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp)
+static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp,
+ bool aphy)
{
+ int base = aphy ? 0 : 4;
+
switch (plcp->raw[0] & 0xF) {
case 0xB:
- return B43legacy_OFDM_RATE_6MB;
+ return base + 0;
case 0xF:
- return B43legacy_OFDM_RATE_9MB;
+ return base + 1;
case 0xA:
- return B43legacy_OFDM_RATE_12MB;
+ return base + 2;
case 0xE:
- return B43legacy_OFDM_RATE_18MB;
+ return base + 3;
case 0x9:
- return B43legacy_OFDM_RATE_24MB;
+ return base + 4;
case 0xD:
- return B43legacy_OFDM_RATE_36MB;
+ return base + 5;
case 0x8:
- return B43legacy_OFDM_RATE_48MB;
+ return base + 6;
case 0xC:
- return B43legacy_OFDM_RATE_54MB;
+ return base + 7;
}
B43legacy_BUG_ON(1);
- return 0;
+ return -1;
}
u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate)
@@ -185,35 +188,37 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
struct b43legacy_txhdr_fw3 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_control *txctl,
+ struct ieee80211_tx_info *info,
u16 cookie)
{
const struct ieee80211_hdr *wlhdr;
- int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT));
- u16 fctl;
+ int use_encryption = !!info->control.hw_key;
u8 rate;
- u8 rate_fb;
+ struct ieee80211_rate *rate_fb;
int rate_ofdm;
int rate_fb_ofdm;
unsigned int plcp_fragment_len;
u32 mac_ctl = 0;
u16 phy_ctl = 0;
+ struct ieee80211_rate *tx_rate;
+ struct ieee80211_tx_rate *rates;
wlhdr = (const struct ieee80211_hdr *)fragment_data;
- fctl = le16_to_cpu(wlhdr->frame_control);
memset(txhdr, 0, sizeof(*txhdr));
- rate = txctl->tx_rate;
+ tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info);
+
+ rate = tx_rate->hw_value;
rate_ofdm = b43legacy_is_ofdm_rate(rate);
- rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate;
- rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb);
+ rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate;
+ rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value);
txhdr->mac_frame_ctl = wlhdr->frame_control;
- memcpy(txhdr->tx_receiver, wlhdr->addr1, 6);
+ memcpy(txhdr->tx_receiver, wlhdr->addr1, ETH_ALEN);
/* Calculate duration for fallback rate */
- if ((rate_fb == rate) ||
+ if ((rate_fb->hw_value == rate) ||
(wlhdr->duration_id & cpu_to_le16(0x8000)) ||
(wlhdr->duration_id == cpu_to_le16(0))) {
/* If the fallback rate equals the normal rate or the
@@ -221,16 +226,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
* use the original dur_id field. */
txhdr->dur_fb = wlhdr->duration_id;
} else {
- int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- txctl->vif,
+ info->control.vif,
+ info->band,
fragment_len,
- fbrate_base100kbps);
+ rate_fb);
}
plcp_fragment_len = fragment_len + FCS_LEN;
if (use_encryption) {
- u8 key_idx = (u16)(txctl->key_idx);
+ u8 key_idx = info->control.hw_key->hw_key_idx;
struct b43legacy_key *key;
int wlhdr_len;
size_t iv_len;
@@ -240,7 +245,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
if (key->enabled) {
/* Hardware appends ICV. */
- plcp_fragment_len += txctl->icv_len;
+ plcp_fragment_len += info->control.hw_key->icv_len;
key_idx = b43legacy_kidx_to_fw(dev, key_idx);
mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) &
@@ -248,8 +253,8 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
mac_ctl |= (key->algorithm <<
B43legacy_TX4_MAC_KEYALG_SHIFT) &
B43legacy_TX4_MAC_KEYALG;
- wlhdr_len = ieee80211_get_hdrlen(fctl);
- iv_len = min((size_t)txctl->iv_len,
+ wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control);
+ iv_len = min_t(size_t, info->control.hw_key->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len);
} else {
@@ -264,72 +269,67 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
(&txhdr->plcp), plcp_fragment_len,
rate);
- b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
- (&txhdr->plcp_fb), plcp_fragment_len,
- rate_fb);
+ b43legacy_generate_plcp_hdr(&txhdr->plcp_fb, plcp_fragment_len,
+ rate_fb->hw_value);
/* PHY TX Control word */
if (rate_ofdm)
- phy_ctl |= B43legacy_TX4_PHY_OFDM;
- if (dev->short_preamble)
+ phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
- switch (txctl->antenna_sel_tx) {
- case 0:
- phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
- break;
- case 1:
- phy_ctl |= B43legacy_TX4_PHY_ANT0;
- break;
- case 2:
- phy_ctl |= B43legacy_TX4_PHY_ANT1;
- break;
- default:
- B43legacy_BUG_ON(1);
- }
+ phy_ctl |= B43legacy_TX4_PHY_ANTLAST;
/* MAC control */
- if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
+ rates = info->control.rates;
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43legacy_TX4_MAC_ACK;
- if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
- ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
- if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43legacy_TX4_MAC_STMSDU;
if (rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
- if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
+
+ /* Overwrite rates[0].count to make the retry calculation
+ * in the tx status easier. need the actual retry limit to
+ * detect whether the fallback rate was used.
+ */
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+ rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
+ } else {
+ rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+ }
/* Generate the RTS or CTS-to-self frame */
- if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
- (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)) {
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
struct ieee80211_hdr *hdr;
int rts_rate;
int rts_rate_fb;
- int rts_rate_ofdm;
int rts_rate_fb_ofdm;
- rts_rate = txctl->rts_cts_rate;
- rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate);
+ rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value;
rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb);
if (rts_rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
- if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
ieee80211_ctstoself_get(dev->wl->hw,
- txctl->vif,
+ info->control.vif,
fragment_data,
- fragment_len, txctl,
+ fragment_len, info,
(struct ieee80211_cts *)
(txhdr->rts_frame));
mac_ctl |= B43legacy_TX4_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
ieee80211_rts_get(dev->wl->hw,
- txctl->vif,
- fragment_data, fragment_len, txctl,
+ info->control.vif,
+ fragment_data, fragment_len, info,
(struct ieee80211_rts *)
(txhdr->rts_frame));
mac_ctl |= B43legacy_TX4_MAC_SENDRTS;
@@ -339,8 +339,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
(&txhdr->rts_plcp),
len, rts_rate);
- b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *)
- (&txhdr->rts_plcp_fb),
+ b43legacy_generate_plcp_hdr(&txhdr->rts_plcp_fb,
len, rts_rate_fb);
hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
txhdr->rts_dur_fb = hdr->duration_id;
@@ -360,12 +359,12 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
u8 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_control *txctl,
+ struct ieee80211_tx_info *info,
u16 cookie)
{
return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
fragment_data, fragment_len,
- txctl, cookie);
+ info, cookie);
}
static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
@@ -437,7 +436,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
struct b43legacy_plcp_hdr6 *plcp;
struct ieee80211_hdr *wlhdr;
const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr;
- u16 fctl;
+ __le16 fctl;
u16 phystat0;
u16 phystat3;
u16 chanstat;
@@ -475,7 +474,7 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
goto drop;
}
wlhdr = (struct ieee80211_hdr *)(skb->data);
- fctl = le16_to_cpu(wlhdr->frame_control);
+ fctl = wlhdr->frame_control;
if ((macstat & B43legacy_RX_MAC_DEC) &&
!(macstat & B43legacy_RX_MAC_DECERR)) {
@@ -494,11 +493,11 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
/* Remove PROTECTED flag to mark it as decrypted. */
- B43legacy_WARN_ON(!(fctl & IEEE80211_FCTL_PROTECTED));
- fctl &= ~IEEE80211_FCTL_PROTECTED;
- wlhdr->frame_control = cpu_to_le16(fctl);
+ B43legacy_WARN_ON(!ieee80211_has_protected(fctl));
+ fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ wlhdr->frame_control = fctl;
- wlhdr_len = ieee80211_get_hdrlen(fctl);
+ wlhdr_len = ieee80211_hdrlen(fctl);
if (unlikely(skb->len < (wlhdr_len + 3))) {
b43legacydbg(dev->wl, "RX: Packet size"
" underrun3\n");
@@ -530,25 +529,26 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
}
}
- status.ssi = b43legacy_rssi_postprocess(dev, jssi,
+ status.signal = b43legacy_rssi_postprocess(dev, jssi,
(phystat0 & B43legacy_RX_PHYST0_OFDM),
(phystat0 & B43legacy_RX_PHYST0_GAINCTL),
(phystat3 & B43legacy_RX_PHYST3_TRSTATE));
- status.noise = dev->stats.link_noise;
- status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI;
+ /* change to support A PHY */
if (phystat0 & B43legacy_RX_PHYST0_OFDM)
- status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp);
+ status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
else
- status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
+ status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp);
status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
/*
- * If monitors are present get full 64-bit timestamp. This
- * code assumes we get to process the packet within 16 bits
- * of timestamp, i.e. about 65 milliseconds after the PHY
- * received the first symbol.
+ * All frames on monitor interfaces and beacons always need a full
+ * 64-bit timestamp. Monitor interfaces need it for diagnostic
+ * purposes and beacons for IBSS merging.
+ * This code assumes we get to process the packet within 16 bits
+ * of timestamp, i.e. about 65 milliseconds after the PHY received
+ * the first symbol.
*/
- if (dev->wl->radiotap_enabled) {
+ if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
u16 low_mactime_now;
b43legacy_tsf_read(dev, &status.mactime);
@@ -557,29 +557,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
status.mactime += mactime;
if (low_mactime_now <= mactime)
status.mactime -= 0x10000;
- status.flag |= RX_FLAG_TSFT;
+ status.flag |= RX_FLAG_MACTIME_START;
}
chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
B43legacy_RX_CHAN_ID_SHIFT;
switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) {
case B43legacy_PHYTYPE_B:
- status.phymode = MODE_IEEE80211B;
- status.freq = chanid + 2400;
- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
- break;
case B43legacy_PHYTYPE_G:
- status.phymode = MODE_IEEE80211G;
+ status.band = IEEE80211_BAND_2GHZ;
status.freq = chanid + 2400;
- status.channel = b43legacy_freq_to_channel_bg(chanid + 2400);
break;
default:
b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n",
chanstat);
}
- dev->stats.last_rx = jiffies;
- ieee80211_rx_irqsafe(dev->wl->hw, skb, &status);
+ memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
+ ieee80211_rx_irqsafe(dev->wl->hw, skb);
return;
drop:
@@ -624,7 +619,7 @@ void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev,
tmp = hw->count;
status.frame_count = (tmp >> 4);
status.rts_count = (tmp & 0x0F);
- tmp = hw->flags;
+ tmp = hw->flags << 1;
status.supp_reason = ((tmp & 0x1C) >> 2);
status.pm_indicated = !!(tmp & 0x80);
status.intermediate = !!(tmp & 0x40);
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h
index bab47928a0c..289db00a4a7 100644
--- a/drivers/net/wireless/b43legacy/xmit.h
+++ b/drivers/net/wireless/b43legacy/xmit.h
@@ -9,8 +9,8 @@
union { \
__le32 data; \
__u8 raw[size]; \
- } __attribute__((__packed__)); \
- } __attribute__((__packed__))
+ } __packed; \
+ } __packed
/* struct b43legacy_plcp_hdr4 */
_b43legacy_declare_plcp_hdr(4);
@@ -39,7 +39,7 @@ struct b43legacy_txhdr_fw3 {
struct b43legacy_plcp_hdr6 rts_plcp; /* RTS PLCP */
__u8 rts_frame[18]; /* The RTS frame (if used) */
struct b43legacy_plcp_hdr6 plcp;
-} __attribute__((__packed__));
+} __packed;
/* MAC TX control */
#define B43legacy_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */
@@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 {
#define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */
/* PHY TX control word */
-#define B43legacy_TX4_PHY_OFDM 0x0001 /* Data frame rate type */
+#define B43legacy_TX4_PHY_ENC 0x0003 /* Data frame encoding */
+#define B43legacy_TX4_PHY_ENC_CCK 0x0000 /* CCK */
+#define B43legacy_TX4_PHY_ENC_OFDM 0x0001 /* Data frame rate type */
#define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
#define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */
#define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */
@@ -80,7 +82,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
u8 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_control *txctl,
+ struct ieee80211_tx_info *info,
u16 cookie);
@@ -121,7 +123,7 @@ struct b43legacy_hwtxstatus {
__le16 seq;
u8 phy_stat;
PAD_BYTES(1);
-} __attribute__((__packed__));
+} __packed;
/* Receive header for v3 firmware. */
@@ -136,7 +138,7 @@ struct b43legacy_rxhdr_fw3 {
__le16 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
-} __attribute__((__packed__));
+} __packed;
/* PHY RX Status 0 */