2 * Copyright (c) 2014 Qualcomm Atheros, Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/uaccess.h>
20 #include <uapi/linux/wil6210_uapi.h>
22 #define wil_hex_dump_ioctl(prefix_str, buf, len) \
23 print_hex_dump_debug("DBG[IOC ]" prefix_str, \
24 DUMP_PREFIX_OFFSET, 16, 1, buf, len, true)
25 #define wil_dbg_ioctl(wil, fmt, arg...) wil_dbg(wil, "DBG[IOC ]" fmt, ##arg)
27 static void __iomem
*wil_ioc_addr(struct wil6210_priv
*wil
, uint32_t addr
,
28 uint32_t size
, enum wil_memio_op op
)
33 switch (op
& wil_mmio_addr_mask
) {
34 case wil_mmio_addr_linker
:
35 a
= wmi_buffer(wil
, cpu_to_le32(addr
));
37 case wil_mmio_addr_ahb
:
38 a
= wmi_addr(wil
, addr
);
40 case wil_mmio_addr_bar
:
41 a
= wmi_addr(wil
, addr
+ WIL6210_FW_HOST_OFF
);
44 wil_err(wil
, "Unsupported address mode, op = 0x%08x\n", op
);
49 if (size
>= WIL6210_MEM_SIZE
- off
) {
50 wil_err(wil
, "Requested block does not fit into memory: "
51 "off = 0x%08x size = 0x%08x\n", off
, size
);
58 static int wil_ioc_memio_dword(struct wil6210_priv
*wil
, void __user
*data
)
62 bool need_copy
= false;
64 if (copy_from_user(&io
, data
, sizeof(io
)))
67 wil_dbg_ioctl(wil
, "IO: addr = 0x%08x val = 0x%08x op = 0x%08x\n",
68 io
.addr
, io
.val
, io
.op
);
70 a
= wil_ioc_addr(wil
, io
.addr
, sizeof(u32
), io
.op
);
72 wil_err(wil
, "invalid address 0x%08x, op = 0x%08x\n", io
.addr
,
77 switch (io
.op
& wil_mmio_op_mask
) {
84 wmb(); /* make sure write propagated to HW */
87 wil_err(wil
, "Unsupported operation, op = 0x%08x\n", io
.op
);
92 wil_dbg_ioctl(wil
, "IO done: addr = 0x%08x"
93 " val = 0x%08x op = 0x%08x\n",
94 io
.addr
, io
.val
, io
.op
);
95 if (copy_to_user(data
, &io
, sizeof(io
)))
102 static int wil_ioc_memio_block(struct wil6210_priv
*wil
, void __user
*data
)
104 struct wil_memio_block io
;
109 if (copy_from_user(&io
, data
, sizeof(io
)))
112 wil_dbg_ioctl(wil
, "IO: addr = 0x%08x size = 0x%08x op = 0x%08x\n",
113 io
.addr
, io
.size
, io
.op
);
117 wil_err(wil
, "size is not multiple of 4: 0x%08x\n", io
.size
);
121 a
= wil_ioc_addr(wil
, io
.addr
, io
.size
, io
.op
);
123 wil_err(wil
, "invalid address 0x%08x, op = 0x%08x\n", io
.addr
,
128 block
= kmalloc(io
.size
, GFP_USER
);
133 switch (io
.op
& wil_mmio_op_mask
) {
135 wil_memcpy_fromio_32(block
, a
, io
.size
);
136 wil_hex_dump_ioctl("Read ", block
, io
.size
);
137 if (copy_to_user(io
.block
, block
, io
.size
)) {
143 if (copy_from_user(block
, io
.block
, io
.size
)) {
147 wil_memcpy_toio_32(a
, block
, io
.size
);
148 wmb(); /* make sure write propagated to HW */
149 wil_hex_dump_ioctl("Write ", block
, io
.size
);
152 wil_err(wil
, "Unsupported operation, op = 0x%08x\n", io
.op
);
162 int wil_ioctl(struct wil6210_priv
*wil
, void __user
*data
, int cmd
)
165 case WIL_IOCTL_MEMIO
:
166 return wil_ioc_memio_dword(wil
, data
);
167 case WIL_IOCTL_MEMIO_BLOCK
:
168 return wil_ioc_memio_block(wil
, data
);
170 wil_dbg_ioctl(wil
, "Unsupported IOCTL 0x%04x\n", cmd
);