summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-06-28 22:57:58 -0700
committerDavid S. Miller <davem@davemloft.net>2008-06-28 22:57:58 -0700
commit28f49d8fec19833672a6a813bfde0068fee50bc9 (patch)
tree6905c5cabc063e44b891ae0af5b5d7cce69e6e71 /drivers/net/wireless/b43
parent332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (diff)
parentff28bd94e307c67abb1bccda5d3a9018bd798e08 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/b43')
-rw-r--r--drivers/net/wireless/b43/b43.h2
-rw-r--r--drivers/net/wireless/b43/debugfs.c359
-rw-r--r--drivers/net/wireless/b43/debugfs.h23
-rw-r--r--drivers/net/wireless/b43/dma.c65
-rw-r--r--drivers/net/wireless/b43/main.c86
-rw-r--r--drivers/net/wireless/b43/main.h4
-rw-r--r--drivers/net/wireless/b43/pio.c2
-rw-r--r--drivers/net/wireless/b43/rfkill.c7
-rw-r--r--drivers/net/wireless/b43/xmit.c17
9 files changed, 465 insertions, 100 deletions
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 532365f5ece..edcdfa36645 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -441,6 +441,8 @@ enum {
#define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */
#define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */
+/* The firmware register that contains the watchdog counter. */
+#define B43_WATCHDOG_REG 1
/* Device specific rate values.
* The actual values defined here are (rate_in_mbps * 2).
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 210e2789c1c..29851bc1101 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -74,70 +74,327 @@ struct b43_dfs_file * fops_to_dfs_file(struct b43_wldev *dev,
} while (0)
-/* wl->irq_lock is locked */
-static ssize_t tsf_read_file(struct b43_wldev *dev,
- char *buf, size_t bufsize)
+/* The biggest address values for SHM access from the debugfs files. */
+#define B43_MAX_SHM_ROUTING 4
+#define B43_MAX_SHM_ADDR 0xFFFF
+
+static ssize_t shm16read__read_file(struct b43_wldev *dev,
+ char *buf, size_t bufsize)
{
ssize_t count = 0;
- u64 tsf;
+ unsigned int routing, addr;
+ u16 val;
- b43_tsf_read(dev, &tsf);
- fappend("0x%08x%08x\n",
- (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
- (unsigned int)(tsf & 0xFFFFFFFFULL));
+ routing = dev->dfsentry->shm16read_routing_next;
+ addr = dev->dfsentry->shm16read_addr_next;
+ if ((routing > B43_MAX_SHM_ROUTING) ||
+ (addr > B43_MAX_SHM_ADDR))
+ return -EDESTADDRREQ;
+
+ val = b43_shm_read16(dev, routing, addr);
+ fappend("0x%04X\n", val);
return count;
}
-/* wl->irq_lock is locked */
-static int tsf_write_file(struct b43_wldev *dev,
- const char *buf, size_t count)
+static int shm16read__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
{
- u64 tsf;
+ unsigned int routing, addr;
+ int res;
- if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1)
+ res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
+ if (res != 2)
return -EINVAL;
- b43_tsf_write(dev, tsf);
+ if (routing > B43_MAX_SHM_ROUTING)
+ return -EADDRNOTAVAIL;
+ if (addr > B43_MAX_SHM_ADDR)
+ return -EADDRNOTAVAIL;
+ if (routing == B43_SHM_SHARED) {
+ if ((addr % 2) != 0)
+ return -EADDRNOTAVAIL;
+ }
+
+ dev->dfsentry->shm16read_routing_next = routing;
+ dev->dfsentry->shm16read_addr_next = addr;
return 0;
}
-/* wl->irq_lock is locked */
-static ssize_t ucode_regs_read_file(struct b43_wldev *dev,
+static int shm16write__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int routing, addr, mask, set;
+ u16 val;
+ int res;
+ unsigned long flags;
+
+ res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
+ &routing, &addr, &mask, &set);
+ if (res != 4)
+ return -EINVAL;
+ if (routing > B43_MAX_SHM_ROUTING)
+ return -EADDRNOTAVAIL;
+ if (addr > B43_MAX_SHM_ADDR)
+ return -EADDRNOTAVAIL;
+ if (routing == B43_SHM_SHARED) {
+ if ((addr % 2) != 0)
+ return -EADDRNOTAVAIL;
+ }
+ if ((mask > 0xFFFF) || (set > 0xFFFF))
+ return -E2BIG;
+
+ spin_lock_irqsave(&dev->wl->shm_lock, flags);
+ if (mask == 0)
+ val = 0;
+ else
+ val = __b43_shm_read16(dev, routing, addr);
+ val &= mask;
+ val |= set;
+ __b43_shm_write16(dev, routing, addr, val);
+ spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
+
+ return 0;
+}
+
+static ssize_t shm32read__read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
- int i;
+ unsigned int routing, addr;
+ u32 val;
+
+ routing = dev->dfsentry->shm32read_routing_next;
+ addr = dev->dfsentry->shm32read_addr_next;
+ if ((routing > B43_MAX_SHM_ROUTING) ||
+ (addr > B43_MAX_SHM_ADDR))
+ return -EDESTADDRREQ;
- for (i = 0; i < 64; i++) {
- fappend("r%d = 0x%04x\n", i,
- b43_shm_read16(dev, B43_SHM_SCRATCH, i));
+ val = b43_shm_read32(dev, routing, addr);
+ fappend("0x%08X\n", val);
+
+ return count;
+}
+
+static int shm32read__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int routing, addr;
+ int res;
+
+ res = sscanf(buf, "0x%X 0x%X", &routing, &addr);
+ if (res != 2)
+ return -EINVAL;
+ if (routing > B43_MAX_SHM_ROUTING)
+ return -EADDRNOTAVAIL;
+ if (addr > B43_MAX_SHM_ADDR)
+ return -EADDRNOTAVAIL;
+ if (routing == B43_SHM_SHARED) {
+ if ((addr % 2) != 0)
+ return -EADDRNOTAVAIL;
+ }
+
+ dev->dfsentry->shm32read_routing_next = routing;
+ dev->dfsentry->shm32read_addr_next = addr;
+
+ return 0;
+}
+
+static int shm32write__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int routing, addr, mask, set;
+ u32 val;
+ int res;
+ unsigned long flags;
+
+ res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X",
+ &routing, &addr, &mask, &set);
+ if (res != 4)
+ return -EINVAL;
+ if (routing > B43_MAX_SHM_ROUTING)
+ return -EADDRNOTAVAIL;
+ if (addr > B43_MAX_SHM_ADDR)
+ return -EADDRNOTAVAIL;
+ if (routing == B43_SHM_SHARED) {
+ if ((addr % 2) != 0)
+ return -EADDRNOTAVAIL;
}
+ if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
+ return -E2BIG;
+
+ spin_lock_irqsave(&dev->wl->shm_lock, flags);
+ if (mask == 0)
+ val = 0;
+ else
+ val = __b43_shm_read32(dev, routing, addr);
+ val &= mask;
+ val |= set;
+ __b43_shm_write32(dev, routing, addr, val);
+ spin_unlock_irqrestore(&dev->wl->shm_lock, flags);
+
+ return 0;
+}
+
+/* The biggest MMIO address that we allow access to from the debugfs files. */
+#define B43_MAX_MMIO_ACCESS (0xF00 - 1)
+
+static ssize_t mmio16read__read_file(struct b43_wldev *dev,
+ char *buf, size_t bufsize)
+{
+ ssize_t count = 0;
+ unsigned int addr;
+ u16 val;
+
+ addr = dev->dfsentry->mmio16read_next;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EDESTADDRREQ;
+
+ val = b43_read16(dev, addr);
+ fappend("0x%04X\n", val);
+
+ return count;
+}
+
+static int mmio16read__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int addr;
+ int res;
+
+ res = sscanf(buf, "0x%X", &addr);
+ if (res != 1)
+ return -EINVAL;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EADDRNOTAVAIL;
+ if ((addr % 2) != 0)
+ return -EINVAL;
+
+ dev->dfsentry->mmio16read_next = addr;
+
+ return 0;
+}
+
+static int mmio16write__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int addr, mask, set;
+ int res;
+ u16 val;
+
+ res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
+ if (res != 3)
+ return -EINVAL;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EADDRNOTAVAIL;
+ if ((mask > 0xFFFF) || (set > 0xFFFF))
+ return -E2BIG;
+ if ((addr % 2) != 0)
+ return -EINVAL;
+
+ if (mask == 0)
+ val = 0;
+ else
+ val = b43_read16(dev, addr);
+ val &= mask;
+ val |= set;
+ b43_write16(dev, addr, val);
+
+ return 0;
+}
+
+static ssize_t mmio32read__read_file(struct b43_wldev *dev,
+ char *buf, size_t bufsize)
+{
+ ssize_t count = 0;
+ unsigned int addr;
+ u32 val;
+
+ addr = dev->dfsentry->mmio32read_next;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EDESTADDRREQ;
+
+ val = b43_read32(dev, addr);
+ fappend("0x%08X\n", val);
return count;
}
+static int mmio32read__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int addr;
+ int res;
+
+ res = sscanf(buf, "0x%X", &addr);
+ if (res != 1)
+ return -EINVAL;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EADDRNOTAVAIL;
+ if ((addr % 4) != 0)
+ return -EINVAL;
+
+ dev->dfsentry->mmio32read_next = addr;
+
+ return 0;
+}
+
+static int mmio32write__write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ unsigned int addr, mask, set;
+ int res;
+ u32 val;
+
+ res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set);
+ if (res != 3)
+ return -EINVAL;
+ if (addr > B43_MAX_MMIO_ACCESS)
+ return -EADDRNOTAVAIL;
+ if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF))
+ return -E2BIG;
+ if ((addr % 4) != 0)
+ return -EINVAL;
+
+ if (mask == 0)
+ val = 0;
+ else
+ val = b43_read32(dev, addr);
+ val &= mask;
+ val |= set;
+ b43_write32(dev, addr, val);
+
+ return 0;
+}
+
/* wl->irq_lock is locked */
-static ssize_t shm_read_file(struct b43_wldev *dev,
+static ssize_t tsf_read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
ssize_t count = 0;
- int i;
- u16 tmp;
- __le16 *le16buf = (__le16 *)buf;
+ u64 tsf;
- for (i = 0; i < 0x1000; i++) {
- if (bufsize < sizeof(tmp))
- break;
- tmp = b43_shm_read16(dev, B43_SHM_SHARED, 2 * i);
- le16buf[i] = cpu_to_le16(tmp);
- count += sizeof(tmp);
- bufsize -= sizeof(tmp);
- }
+ b43_tsf_read(dev, &tsf);
+ fappend("0x%08x%08x\n",
+ (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32),
+ (unsigned int)(tsf & 0xFFFFFFFFULL));
return count;
}
+/* wl->irq_lock is locked */
+static int tsf_write_file(struct b43_wldev *dev,
+ const char *buf, size_t count)
+{
+ u64 tsf;
+
+ if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1)
+ return -EINVAL;
+ b43_tsf_write(dev, tsf);
+
+ return 0;
+}
+
static ssize_t txstat_read_file(struct b43_wldev *dev,
char *buf, size_t bufsize)
{
@@ -496,9 +753,15 @@ out_unlock:
.take_irqlock = _take_irqlock, \
}
+B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file, 1);
+B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file, 1);
+B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file, 1);
+B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file, 1);
+B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file, 1);
+B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file, 1);
+B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file, 1);
+B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file, 1);
B43_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1);
-B43_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1);
-B43_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1);
B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0);
B43_DEBUGFS_FOPS(txpower_g, txpower_g_read_file, txpower_g_write_file, 0);
B43_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1);
@@ -538,6 +801,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0);
add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
+ add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
#undef add_dyn_dbg
}
@@ -584,6 +848,13 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
return;
}
+ e->mmio16read_next = 0xFFFF; /* invalid address */
+ e->mmio32read_next = 0xFFFF; /* invalid address */
+ e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */
+ e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */
+ e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */
+ e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */
+
#define ADD_FILE(name, mode) \
do { \
struct dentry *d; \
@@ -596,9 +867,15 @@ void b43_debugfs_add_device(struct b43_wldev *dev)
} while (0)
+ ADD_FILE(shm16read, 0600);
+ ADD_FILE(shm16write, 0200);
+ ADD_FILE(shm32read, 0600);
+ ADD_FILE(shm32write, 0200);
+ ADD_FILE(mmio16read, 0600);
+ ADD_FILE(mmio16write, 0200);
+ ADD_FILE(mmio32read, 0600);
+ ADD_FILE(mmio32write, 0200);
ADD_FILE(tsf, 0600);
- ADD_FILE(ucode_regs, 0400);
- ADD_FILE(shm, 0400);
ADD_FILE(txstat, 0400);
ADD_FILE(txpower_g, 0600);
ADD_FILE(restart, 0200);
@@ -620,9 +897,15 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
return;
b43_remove_dynamic_debug(dev);
+ debugfs_remove(e->file_shm16read.dentry);
+ debugfs_remove(e->file_shm16write.dentry);
+ debugfs_remove(e->file_shm32read.dentry);
+ debugfs_remove(e->file_shm32write.dentry);
+ debugfs_remove(e->file_mmio16read.dentry);
+ debugfs_remove(e->file_mmio16write.dentry);
+ debugfs_remove(e->file_mmio32read.dentry);
+ debugfs_remove(e->file_mmio32write.dentry);
debugfs_remove(e->file_tsf.dentry);
- debugfs_remove(e->file_ucode_regs.dentry);
- debugfs_remove(e->file_shm.dentry);
debugfs_remove(e->file_txstat.dentry);
debugfs_remove(e->file_txpower_g.dentry);
debugfs_remove(e->file_restart.dentry);
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index c75cff4151d..22ffd02ba55 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -11,6 +11,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
B43_DBG_PWORK_FAST,
B43_DBG_PWORK_STOP,
B43_DBG_LO,
+ B43_DBG_FIRMWARE,
__B43_NR_DYNDBG,
};
@@ -36,9 +37,15 @@ struct b43_dfsentry {
struct b43_wldev *dev;
struct dentry *subdir;
+ struct b43_dfs_file file_shm16read;
+ struct b43_dfs_file file_shm16write;
+ struct b43_dfs_file file_shm32read;
+ struct b43_dfs_file file_shm32write;
+ struct b43_dfs_file file_mmio16read;
+ struct b43_dfs_file file_mmio16write;
+ struct b43_dfs_file file_mmio32read;
+ struct b43_dfs_file file_mmio32write;
struct b43_dfs_file file_tsf;
- struct b43_dfs_file file_ucode_regs;
- struct b43_dfs_file file_shm;
struct b43_dfs_file file_txstat;
struct b43_dfs_file file_txpower_g;
struct b43_dfs_file file_restart;
@@ -46,6 +53,18 @@ struct b43_dfsentry {
struct b43_txstatus_log txstatlog;
+ /* The cached address for the next mmio16read file read */
+ u16 mmio16read_next;
+ /* The cached address for the next mmio32read file read */
+ u16 mmio32read_next;
+
+ /* The cached address for the next shm16read file read */
+ u32 shm16read_routing_next;
+ u32 shm16read_addr_next;
+ /* The cached address for the next shm32read file read */
+ u32 shm32read_routing_next;
+ u32 shm32read_addr_next;
+
/* Enabled/Disabled list for the dynamic debugging features. */
u32 dyn_debug[__B43_NR_DYNDBG];
/* Dentries for the dynamic debugging entries. */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 8a09a1db08d..098f886976f 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -328,11 +328,11 @@ static inline
dma_addr_t dmaaddr;
if (tx) {
- dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
- buf, len, DMA_TO_DEVICE);
+ dmaaddr = ssb_dma_map_single(ring->dev->dev,
+ buf, len, DMA_TO_DEVICE);
} else {
- dmaaddr = dma_map_single(ring->dev->dev->dma_dev,
- buf, len, DMA_FROM_DEVICE);
+ dmaaddr = ssb_dma_map_single(ring->dev->dev,
+ buf, len, DMA_FROM_DEVICE);
}
return dmaaddr;
@@ -343,11 +343,11 @@ static inline
dma_addr_t addr, size_t len, int tx)
{
if (tx) {
- dma_unmap_single(ring->dev->dev->dma_dev,
- addr, len, DMA_TO_DEVICE);
+ ssb_dma_unmap_single(ring->dev->dev,
+ addr, len, DMA_TO_DEVICE);
} else {
- dma_unmap_single(ring->dev->dev->dma_dev,
- addr, len, DMA_FROM_DEVICE);
+ ssb_dma_unmap_single(ring->dev->dev,
+ addr, len, DMA_FROM_DEVICE);
}
}
@@ -356,8 +356,8 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_cpu(ring->dev->dev->dma_dev,
- addr, len, DMA_FROM_DEVICE);
+ ssb_dma_sync_single_for_cpu(ring->dev->dev,
+ addr, len, DMA_FROM_DEVICE);
}
static inline
@@ -365,8 +365,8 @@ static inline
dma_addr_t addr, size_t len)
{
B43_WARN_ON(ring->tx);
- dma_sync_single_for_device(ring->dev->dev->dma_dev,
- addr, len, DMA_FROM_DEVICE);
+ ssb_dma_sync_single_for_device(ring->dev->dev,
+ addr, len, DMA_FROM_DEVICE);
}
static inline
@@ -381,7 +381,6 @@ static inline
static int alloc_ringmemory(struct b43_dmaring *ring)
{
- struct device *dma_dev = ring->dev->dev->dma_dev;
gfp_t flags = GFP_KERNEL;
/* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
@@ -392,11 +391,14 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
* For unknown reasons - possibly a hardware error - the BCM4311 rev
* 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
* which accounts for the GFP_DMA flag below.
+ *
+ * The flags here must match the flags in free_ringmemory below!
*/
if (ring->type == B43_DMA_64BIT)
flags |= GFP_DMA;
- ring->descbase = dma_alloc_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
- &(ring->dmabase), flags);
+ ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev,
+ B43_DMA_RINGMEMSIZE,
+ &(ring->dmabase), flags);
if (!ring->descbase) {
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
return -ENOMEM;
@@ -408,10 +410,13 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
static void free_ringmemory(struct b43_dmaring *ring)
{
- struct device *dma_dev = ring->dev->dev->dma_dev;
+ gfp_t flags = GFP_KERNEL;
+
+ if (ring->type == B43_DMA_64BIT)
+ flags |= GFP_DMA;
- dma_free_coherent(dma_dev, B43_DMA_RINGMEMSIZE,
- ring->descbase, ring->dmabase);
+ ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE,
+ ring->descbase, ring->dmabase, flags);
}
/* Reset the RX DMA channel */
@@ -518,7 +523,7 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
dma_addr_t addr,
size_t buffersize, bool dma_to_device)
{
- if (unlikely(dma_mapping_error(addr)))
+ if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr)))
return 1;
switch (ring->type) {
@@ -844,10 +849,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
goto err_kfree_meta;
/* test for ability to dma to txhdr_cache */
- dma_test = dma_map_single(dev->dev->dma_dev,
- ring->txhdr_cache,
- b43_txhdr_size(dev),
- DMA_TO_DEVICE);
+ dma_test = ssb_dma_map_single(dev->dev,
+ ring->txhdr_cache,
+ b43_txhdr_size(dev),
+ DMA_TO_DEVICE);
if (b43_dma_mapping_error(ring, dma_test,
b43_txhdr_size(dev), 1)) {
@@ -859,10 +864,10 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = dma_map_single(dev->dev->dma_dev,
- ring->txhdr_cache,
- b43_txhdr_size(dev),
- DMA_TO_DEVICE);
+ dma_test = ssb_dma_map_single(dev->dev,
+ ring->txhdr_cache,
+ b43_txhdr_size(dev),
+ DMA_TO_DEVICE);
if (b43_dma_mapping_error(ring, dma_test,
b43_txhdr_size(dev), 1)) {
@@ -873,9 +878,9 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
}
}
- dma_unmap_single(dev->dev->dma_dev,
- dma_test, b43_txhdr_size(dev),
- DMA_TO_DEVICE);
+ ssb_dma_unmap_single(dev->dev,
+ dma_test, b43_txhdr_size(dev),
+ DMA_TO_DEVICE);
}
err = alloc_ringmemory(ring);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 704dd3551ff..9d2eb273b72 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -373,13 +373,10 @@ static inline void b43_shm_control_word(struct b43_wldev *dev,
b43_write32(dev, B43_MMIO_SHM_CONTROL, control);
}
-u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
+u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
{
- struct b43_wl *wl = dev->wl;
- unsigned long flags;
u32 ret;
- spin_lock_irqsave(&wl->shm_lock, flags);
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
@@ -397,18 +394,26 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
b43_shm_control_word(dev, routing, offset);
ret = b43_read32(dev, B43_MMIO_SHM_DATA);
out:
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-
return ret;
}
-u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
+u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
{
struct b43_wl *wl = dev->wl;
unsigned long flags;
- u16 ret;
+ u32 ret;
spin_lock_irqsave(&wl->shm_lock, flags);
+ ret = __b43_shm_read32(dev, routing, offset);
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
+
+ return ret;
+}
+
+u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
+{
+ u16 ret;
+
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
@@ -423,17 +428,24 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
b43_shm_control_word(dev, routing, offset);
ret = b43_read16(dev, B43_MMIO_SHM_DATA);
out:
- spin_unlock_irqrestore(&wl->shm_lock, flags);
-
return ret;
}
-void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
+u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset)
{
struct b43_wl *wl = dev->wl;
unsigned long flags;
+ u16 ret;
spin_lock_irqsave(&wl->shm_lock, flags);
+ ret = __b43_shm_read16(dev, routing, offset);
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
+
+ return ret;
+}
+
+void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
+{
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
@@ -443,35 +455,47 @@ void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
(value >> 16) & 0xffff);
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
- goto out;
+ return;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
b43_write32(dev, B43_MMIO_SHM_DATA, value);
-out:
- spin_unlock_irqrestore(&wl->shm_lock, flags);
}
-void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
+void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
{
struct b43_wl *wl = dev->wl;
unsigned long flags;
spin_lock_irqsave(&wl->shm_lock, flags);
+ __b43_shm_write32(dev, routing, offset, value);
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
+}
+
+void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
+{
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
/* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2);
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);
- goto out;
+ return;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
b43_write16(dev, B43_MMIO_SHM_DATA, value);
-out:
+}
+
+void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
+{
+ struct b43_wl *wl = dev->wl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->shm_lock, flags);
+ __b43_shm_write16(dev, routing, offset, value);
spin_unlock_irqrestore(&wl->shm_lock, flags);
}
@@ -2463,6 +2487,19 @@ static void b43_gpio_cleanup(struct b43_wldev *dev)
/* http://bcm-specs.sipsolutions.net/EnableMac */
void b43_mac_enable(struct b43_wldev *dev)
{
+ if (b43_debug(dev, B43_DBG_FIRMWARE)) {
+ u16 fwstate;
+
+ fwstate = b43_shm_read16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_UCODESTAT);
+ if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) &&
+ (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) {
+ b43err(dev->wl, "b43_mac_enable(): The firmware "
+ "should be suspended, but current state is %u\n",
+ fwstate);
+ }
+ }
+
dev->mac_suspended--;
B43_WARN_ON(dev->mac_suspended < 0);
if (dev->mac_suspended == 0) {
@@ -2783,6 +2820,21 @@ static void b43_periodic_every30sec(struct b43_wldev *dev)
static void b43_periodic_every15sec(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ u16 wdr;
+
+ if (dev->fw.opensource) {
+ /* Check if the firmware is still alive.
+ * It will reset the watchdog counter to 0 in its idle loop. */
+ wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG);
+ if (unlikely(wdr)) {
+ b43err(dev->wl, "Firmware watchdog: The firmware died!\n");
+ b43_controller_restart(dev, "Firmware watchdog");
+ return;
+ } else {
+ b43_shm_write16(dev, B43_SHM_SCRATCH,
+ B43_WATCHDOG_REG, 1);
+ }
+ }
if (phy->type == B43_PHYTYPE_G) {
//TODO: update_aci_moving_average
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index dad23c42b42..f871a252cb5 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -95,9 +95,13 @@ void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
+u32 __b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset);
u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
+u16 __b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset);
void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
+void __b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value);
void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
+void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value);
u64 b43_hf_read(struct b43_wldev *dev);
void b43_hf_write(struct b43_wldev *dev, u64 value);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 8b1555d95f1..40159126759 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -586,7 +586,7 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
spin_lock(&q->lock); /* IRQs are already disabled. */
- info = (void *)pack->skb;
+ info = IEEE80211_SKB_CB(pack->skb);
memset(&info->status, 0, sizeof(info->status));
b43_fill_txstatus_report(info, status);
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 11f53cb1139..4cca203992e 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -88,7 +88,7 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
goto out_unlock;
err = 0;
switch (state) {
- case RFKILL_STATE_ON:
+ case RFKILL_STATE_UNBLOCKED:
if (!dev->radio_hw_enable) {
/* No luck. We can't toggle the hardware RF-kill
* button from software. */
@@ -98,10 +98,13 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state)
if (!dev->phy.radio_on)
b43_radio_turn_on(dev);
break;
- case RFKILL_STATE_OFF:
+ case RFKILL_STATE_SOFT_BLOCKED:
if (dev->phy.radio_on)
b43_radio_turn_off(dev, 0);
break;
+ default:
+ b43warn(wl, "Received unexpected rfkill state %d.\n", state);
+ break;
}
out_unlock:
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index f9e1cff2aec..bf6f6c1ed4c 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -193,7 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
const struct ieee80211_hdr *wlhdr =
(const struct ieee80211_hdr *)fragment_data;
int use_encryption = (!(info->flags & IEEE80211_TX_CTL_DO_NOT_ENCRYPT));
- u16 fctl = le16_to_cpu(wlhdr->frame_control);
+ __le16 fctl = wlhdr->frame_control;
struct ieee80211_rate *fbrate;
u8 rate, rate_fb;
int rate_ofdm, rate_fb_ofdm;
@@ -259,7 +259,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
B43_TXH_MAC_KEYIDX;
mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
B43_TXH_MAC_KEYALG;
- wlhdr_len = ieee80211_get_hdrlen(fctl);
+ wlhdr_len = ieee80211_hdrlen(fctl);
iv_len = min((size_t) info->control.iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
@@ -317,8 +317,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
/* MAC control */
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43_TXH_MAC_ACK;
- if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
- ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
+ if (!ieee80211_is_pspoll(fctl))
mac_ctl |= B43_TXH_MAC_HWSEQ;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43_TXH_MAC_STMSDU;
@@ -509,7 +508,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
struct b43_plcp_hdr6 *plcp;
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
- u16 fctl;
+ __le16 fctl;
u16 phystat0, phystat3, chanstat, mactime;
u32 macstat;
u16 chanid;
@@ -549,7 +548,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
goto drop;
}
wlhdr = (struct ieee80211_hdr *)(skb->data);
- fctl = le16_to_cpu(wlhdr->frame_control);
+ fctl = wlhdr->frame_control;
if (macstat & B43_RX_MAC_DEC) {
unsigned int keyidx;
@@ -564,7 +563,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
B43_WARN_ON(keyidx >= dev->max_nr_keys);
if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
- wlhdr_len = ieee80211_get_hdrlen(fctl);
+ wlhdr_len = ieee80211_hdrlen(fctl);
if (unlikely(skb->len < (wlhdr_len + 3))) {
b43dbg(dev->wl,
"RX: Packet size underrun (3)\n");
@@ -604,9 +603,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
* of timestamp, i.e. about 65 milliseconds after the PHY received
* the first symbol.
*/
- if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE))
- == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) ||
- dev->wl->radiotap_enabled) {
+ if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) {
u16 low_mactime_now;
b43_tsf_read(dev, &status.mactime);