static void __iomem *wil_ioc_addr(struct wil6210_priv *wil, uint32_t addr, uint32_t size, enum wil_memio_op op) { void __iomem *a; u32 off; switch (op & wil_mmio_addr_mask) { case wil_mmio_addr_linker: a = wmi_buffer(wil, cpu_to_le32(addr)); break; case wil_mmio_addr_ahb: a = wmi_addr(wil, addr); break; case wil_mmio_addr_bar: a = wmi_addr(wil, addr + WIL6210_FW_HOST_OFF); break; default: wil_err(wil, "Unsupported address mode, op = 0x%08x\n", op); return NULL; } off = a - wil->csr; if (size >= WIL6210_MEM_SIZE - off) { wil_err(wil, "Requested block does not fit into memory: " "off = 0x%08x size = 0x%08x\n", off, size); return NULL; } return a; }
int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, struct wil6210_mbox_hdr *hdr) { void __iomem *src = wmi_buffer(wil, ptr); if (!src) return -EINVAL; wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); return 0; }
static int wil_memread_debugfs_show(struct seq_file *s, void *data) { struct wil6210_priv *wil = s->private; void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); if (a) seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, readl(a)); else seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); return 0; }
/* memory rw */ static ssize_t wil_read_file_mem(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { char kbuf[30]; struct wil6210_priv *wil = file->private_data; void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); if (a) snprintf(kbuf, sizeof(kbuf), "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); else snprintf(kbuf, sizeof(kbuf), "[0x%08x] = INVALID\n", mem_addr); return simple_read_from_buffer(user_buf, count, ppos, kbuf, sizeof(kbuf)); }
static ssize_t wil_write_file_mem(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { ssize_t rc; int n; char *kbuf; ulong val; struct wil6210_priv *wil = file->private_data; void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); if (!a) return -EINVAL; if (*ppos != 0) return -EINVAL; kbuf = kmalloc(count + 1, GFP_KERNEL); if (!kbuf) return -ENOMEM; rc = simple_write_to_buffer(kbuf, count, ppos, buf, count); if (rc < 0) { kfree(kbuf); return rc; } kbuf[count] = '\0'; n = sscanf(kbuf, "%li", &val); kfree(kbuf); if (n != 1) return -EINVAL; iowrite32(val, a); wmb(); /* make sure write propagated to HW */ return rc; }
static void wil_print_ring(struct seq_file *s, const char *prefix, void __iomem *off) { struct wil6210_priv *wil = s->private; struct wil6210_mbox_ring r; int rsize; uint i; wil_halp_vote(wil); wil_memcpy_fromio_32(&r, off, sizeof(r)); wil_mbox_ring_le2cpus(&r); /* * we just read memory block from NIC. This memory may be * garbage. Check validity before using it. */ rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); seq_printf(s, "ring %s = {\n", prefix); seq_printf(s, " base = 0x%08x\n", r.base); seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); seq_printf(s, " tail = 0x%08x\n", r.tail); seq_printf(s, " head = 0x%08x\n", r.head); seq_printf(s, " entry size = %d\n", r.entry_size); if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", sizeof(struct wil6210_mbox_ring_desc)); goto out; } if (!wmi_addr(wil, r.base) || !wmi_addr(wil, r.tail) || !wmi_addr(wil, r.head)) { seq_puts(s, " ??? pointers are garbage?\n"); goto out; } for (i = 0; i < rsize; i++) { struct wil6210_mbox_ring_desc d; struct wil6210_mbox_hdr hdr; size_t delta = i * sizeof(d); void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; wil_memcpy_fromio_32(&d, x, sizeof(d)); seq_printf(s, " [%2x] %s %s%s 0x%08x", i, d.sync ? "F" : "E", (r.tail - r.base == delta) ? "t" : " ", (r.head - r.base == delta) ? "h" : " ", le32_to_cpu(d.addr)); if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { u16 len = le16_to_cpu(hdr.len); seq_printf(s, " -> %04x %04x %04x %02x\n", le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), hdr.flags); if (len <= MAX_MBOXITEM_SIZE) { unsigned char databuf[MAX_MBOXITEM_SIZE]; void __iomem *src = wmi_buffer(wil, d.addr) + sizeof(struct wil6210_mbox_hdr); /* * No need to check @src for validity - * we already validated @d.addr while * reading header */ wil_memcpy_fromio_32(databuf, src, len); wil_seq_hexdump(s, databuf, len, " : "); } } else { seq_puts(s, "\n"); } } out: seq_puts(s, "}\n"); wil_halp_unvote(wil); }