Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 266579
b: refs/heads/master
c: 91d57de
h: refs/heads/master
i:
  266577: 6b35656
  266575: 338e0e4
v: v3
  • Loading branch information
Vasanthakumar Thiagarajan authored and Kalle Valo committed Sep 2, 2011
1 parent c9c9074 commit b5e24ef
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: bc07ddb29a7b71ad009bcd84bee4c93908cf22b6
refs/heads/master: 91d57de5adfc40184ef7cb8974104459c5211add
1 change: 1 addition & 0 deletions trunk/drivers/net/wireless/ath/ath6kl/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ struct ath6kl {
spinlock_t fwlog_lock;
void *fwlog_tmp;
u32 fwlog_mask;
unsigned int dbgfs_diag_reg;
} debug;
#endif /* CONFIG_ATH6KL_DEBUG */
};
Expand Down
192 changes: 192 additions & 0 deletions trunk/drivers/net/wireless/ath/ath6kl/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ int ath6kl_printk(const char *level, const char *fmt, ...)
}

#ifdef CONFIG_ATH6KL_DEBUG

#define REG_OUTPUT_LEN_PER_LINE 25
#define REGTYPE_STR_LEN 100

struct ath6kl_diag_reg_info {
u32 reg_start;
u32 reg_end;
const char *reg_info;
};

static const struct ath6kl_diag_reg_info diag_reg[] = {
{ 0x20000, 0x200fc, "General DMA and Rx registers" },
{ 0x28000, 0x28900, "MAC PCU register & keycache" },
{ 0x20800, 0x20a40, "QCU" },
{ 0x21000, 0x212f0, "DCU" },
{ 0x4000, 0x42e4, "RTC" },
{ 0x540000, 0x540000 + (256 * 1024), "RAM" },
{ 0x29800, 0x2B210, "Base Band" },
{ 0x1C000, 0x1C748, "Analog" },
};

void ath6kl_dump_registers(struct ath6kl_device *dev,
struct ath6kl_irq_proc_registers *irq_proc_reg,
struct ath6kl_irq_enable_reg *irq_enable_reg)
Expand Down Expand Up @@ -528,6 +549,171 @@ static const struct file_operations fops_credit_dist_stats = {
.llseek = default_llseek,
};

static unsigned long ath6kl_get_num_reg(void)
{
int i;
unsigned long n_reg = 0;

for (i = 0; i < ARRAY_SIZE(diag_reg); i++)
n_reg = n_reg +
(diag_reg[i].reg_end - diag_reg[i].reg_start) / 4 + 1;

return n_reg;
}

static bool ath6kl_dbg_is_diag_reg_valid(u32 reg_addr)
{
int i;

for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
if (reg_addr >= diag_reg[i].reg_start &&
reg_addr <= diag_reg[i].reg_end)
return true;
}

return false;
}

static ssize_t ath6kl_regread_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
u8 buf[50];
unsigned int len = 0;

if (ar->debug.dbgfs_diag_reg)
len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n",
ar->debug.dbgfs_diag_reg);
else
len += scnprintf(buf + len, sizeof(buf) - len,
"All diag registers\n");

return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}

static ssize_t ath6kl_regread_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath6kl *ar = file->private_data;
u8 buf[50];
unsigned int len;
unsigned long reg_addr;

len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;

buf[len] = '\0';

if (strict_strtoul(buf, 0, &reg_addr))
return -EINVAL;

if ((reg_addr % 4) != 0)
return -EINVAL;

if (reg_addr && !ath6kl_dbg_is_diag_reg_valid(reg_addr))
return -EINVAL;

ar->debug.dbgfs_diag_reg = reg_addr;

return count;
}

static const struct file_operations fops_diag_reg_read = {
.read = ath6kl_regread_read,
.write = ath6kl_regread_write,
.open = ath6kl_debugfs_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

static int ath6kl_regdump_open(struct inode *inode, struct file *file)
{
struct ath6kl *ar = inode->i_private;
u8 *buf;
unsigned long int reg_len;
unsigned int len = 0, n_reg;
u32 addr;
__le32 reg_val;
int i, status;

/* Dump all the registers if no register is specified */
if (!ar->debug.dbgfs_diag_reg)
n_reg = ath6kl_get_num_reg();
else
n_reg = 1;

reg_len = n_reg * REG_OUTPUT_LEN_PER_LINE;
if (n_reg > 1)
reg_len += REGTYPE_STR_LEN;

buf = vmalloc(reg_len);
if (!buf)
return -ENOMEM;

if (n_reg == 1) {
addr = ar->debug.dbgfs_diag_reg;

status = ath6kl_diag_read32(ar,
TARG_VTOP(ar->target_type, addr),
(u32 *)&reg_val);
if (status)
goto fail_reg_read;

len += scnprintf(buf + len, reg_len - len,
"0x%06x 0x%08x\n", addr, le32_to_cpu(reg_val));
goto done;
}

for (i = 0; i < ARRAY_SIZE(diag_reg); i++) {
len += scnprintf(buf + len, reg_len - len,
"%s\n", diag_reg[i].reg_info);
for (addr = diag_reg[i].reg_start;
addr <= diag_reg[i].reg_end; addr += 4) {
status = ath6kl_diag_read32(ar,
TARG_VTOP(ar->target_type, addr),
(u32 *)&reg_val);
if (status)
goto fail_reg_read;

len += scnprintf(buf + len, reg_len - len,
"0x%06x 0x%08x\n",
addr, le32_to_cpu(reg_val));
}
}

done:
file->private_data = buf;
return 0;

fail_reg_read:
ath6kl_warn("Unable to read memory:%u\n", addr);
vfree(buf);
return -EIO;
}

static ssize_t ath6kl_regdump_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
u8 *buf = file->private_data;
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}

static int ath6kl_regdump_release(struct inode *inode, struct file *file)
{
vfree(file->private_data);
return 0;
}

static const struct file_operations fops_reg_dump = {
.open = ath6kl_regdump_open,
.read = ath6kl_regdump_read,
.release = ath6kl_regdump_release,
.owner = THIS_MODULE,
.llseek = default_llseek,
};

int ath6kl_debug_init(struct ath6kl *ar)
{
ar->debug.fwlog_buf.buf = vmalloc(ATH6KL_FWLOG_SIZE);
Expand Down Expand Up @@ -568,6 +754,12 @@ int ath6kl_debug_init(struct ath6kl *ar)
debugfs_create_file("fwlog_mask", S_IRUSR | S_IWUSR, ar->debugfs_phy,
ar, &fops_fwlog_mask);

debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR, ar->debugfs_phy, ar,
&fops_diag_reg_read);

debugfs_create_file("reg_dump", S_IRUSR, ar->debugfs_phy, ar,
&fops_reg_dump);

return 0;
}

Expand Down

0 comments on commit b5e24ef

Please sign in to comment.