summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/debugfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/debugfs.c')
-rw-r--r--drivers/net/wireless/b43/debugfs.c359
1 files changed, 321 insertions, 38 deletions
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);