diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-28 22:57:58 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-28 22:57:58 -0700 |
commit | 28f49d8fec19833672a6a813bfde0068fee50bc9 (patch) | |
tree | 6905c5cabc063e44b891ae0af5b5d7cce69e6e71 /drivers/net/wireless/b43 | |
parent | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (diff) | |
parent | ff28bd94e307c67abb1bccda5d3a9018bd798e08 (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.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.c | 359 | ||||
-rw-r--r-- | drivers/net/wireless/b43/debugfs.h | 23 | ||||
-rw-r--r-- | drivers/net/wireless/b43/dma.c | 65 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.c | 86 | ||||
-rw-r--r-- | drivers/net/wireless/b43/main.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/b43/pio.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/b43/rfkill.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/b43/xmit.c | 17 |
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); |