Skip to content

Commit 5e3dd15

Browse files
committed
ath10k: mac80211 driver for Qualcomm Atheros 802.11ac CQA98xx devices
Here's a new mac80211 driver for Qualcomm Atheros 802.11ac QCA98xx devices. A major difference from ath9k is that there's now a firmware and that's why we had to implement a new driver. The wiki page for the driver is: http://wireless.kernel.org/en/users/Drivers/ath10k The driver has had many authors, they are listed here alphabetically: Bartosz Markowski <[email protected]> Janusz Dziedzic <[email protected]> Kalle Valo <[email protected]> Marek Kwaczynski <[email protected]> Marek Puzyniak <[email protected]> Michal Kazior <[email protected]> Sujith Manoharan <[email protected]> Signed-off-by: Kalle Valo <[email protected]>
1 parent 8b3e7be commit 5e3dd15

File tree

32 files changed

+22094
-0
lines changed

32 files changed

+22094
-0
lines changed

drivers/net/wireless/ath/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@ source "drivers/net/wireless/ath/carl9170/Kconfig"
3131
source "drivers/net/wireless/ath/ath6kl/Kconfig"
3232
source "drivers/net/wireless/ath/ar5523/Kconfig"
3333
source "drivers/net/wireless/ath/wil6210/Kconfig"
34+
source "drivers/net/wireless/ath/ath10k/Kconfig"
3435

3536
endif

drivers/net/wireless/ath/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ obj-$(CONFIG_CARL9170) += carl9170/
44
obj-$(CONFIG_ATH6KL) += ath6kl/
55
obj-$(CONFIG_AR5523) += ar5523/
66
obj-$(CONFIG_WIL6210) += wil6210/
7+
obj-$(CONFIG_ATH10K) += ath10k/
78

89
obj-$(CONFIG_ATH_COMMON) += ath.o
910

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
config ATH10K
2+
tristate "Atheros 802.11ac wireless cards support"
3+
depends on MAC80211
4+
select ATH_COMMON
5+
---help---
6+
This module adds support for wireless adapters based on
7+
Atheros IEEE 802.11ac family of chipsets.
8+
9+
If you choose to build a module, it'll be called ath10k.
10+
11+
config ATH10K_PCI
12+
tristate "Atheros ath10k PCI support"
13+
depends on ATH10K && PCI
14+
---help---
15+
This module adds support for PCIE bus
16+
17+
config ATH10K_DEBUG
18+
bool "Atheros ath10k debugging"
19+
depends on ATH10K
20+
---help---
21+
Enables debug support
22+
23+
If unsure, say Y to make it easier to debug problems.
24+
25+
config ATH10K_DEBUGFS
26+
bool "Atheros ath10k debugfs support"
27+
depends on ATH10K
28+
---help---
29+
Enabled debugfs support
30+
31+
If unsure, say Y to make it easier to debug problems.
32+
33+
config ATH10K_TRACING
34+
bool "Atheros ath10k tracing support"
35+
depends on ATH10K
36+
depends on EVENT_TRACING
37+
---help---
38+
Select this to ath10k use tracing infrastructure.
39+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
obj-$(CONFIG_ATH10K) += ath10k_core.o
2+
ath10k_core-y += mac.o \
3+
debug.o \
4+
core.o \
5+
htc.o \
6+
htt.o \
7+
htt_rx.o \
8+
htt_tx.o \
9+
txrx.o \
10+
wmi.o \
11+
bmi.o
12+
13+
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
14+
15+
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
16+
ath10k_pci-y += pci.o \
17+
ce.o
18+
19+
# for tracing framework to find trace.h
20+
CFLAGS_trace.o := -I$(src)
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/*
2+
* Copyright (c) 2005-2011 Atheros Communications Inc.
3+
* Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
4+
*
5+
* Permission to use, copy, modify, and/or distribute this software for any
6+
* purpose with or without fee is hereby granted, provided that the above
7+
* copyright notice and this permission notice appear in all copies.
8+
*
9+
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16+
*/
17+
18+
#include "bmi.h"
19+
#include "hif.h"
20+
#include "debug.h"
21+
#include "htc.h"
22+
23+
int ath10k_bmi_done(struct ath10k *ar)
24+
{
25+
struct bmi_cmd cmd;
26+
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done);
27+
int ret;
28+
29+
if (ar->bmi.done_sent) {
30+
ath10k_dbg(ATH10K_DBG_CORE, "%s skipped\n", __func__);
31+
return 0;
32+
}
33+
34+
ar->bmi.done_sent = true;
35+
cmd.id = __cpu_to_le32(BMI_DONE);
36+
37+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
38+
if (ret) {
39+
ath10k_warn("unable to write to the device: %d\n", ret);
40+
return ret;
41+
}
42+
43+
ath10k_dbg(ATH10K_DBG_CORE, "BMI done\n");
44+
return 0;
45+
}
46+
47+
int ath10k_bmi_get_target_info(struct ath10k *ar,
48+
struct bmi_target_info *target_info)
49+
{
50+
struct bmi_cmd cmd;
51+
union bmi_resp resp;
52+
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info);
53+
u32 resplen = sizeof(resp.get_target_info);
54+
int ret;
55+
56+
if (ar->bmi.done_sent) {
57+
ath10k_warn("BMI Get Target Info Command disallowed\n");
58+
return -EBUSY;
59+
}
60+
61+
cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
62+
63+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
64+
if (ret) {
65+
ath10k_warn("unable to get target info from device\n");
66+
return ret;
67+
}
68+
69+
if (resplen < sizeof(resp.get_target_info)) {
70+
ath10k_warn("invalid get_target_info response length (%d)\n",
71+
resplen);
72+
return -EIO;
73+
}
74+
75+
target_info->version = __le32_to_cpu(resp.get_target_info.version);
76+
target_info->type = __le32_to_cpu(resp.get_target_info.type);
77+
return 0;
78+
}
79+
80+
int ath10k_bmi_read_memory(struct ath10k *ar,
81+
u32 address, void *buffer, u32 length)
82+
{
83+
struct bmi_cmd cmd;
84+
union bmi_resp resp;
85+
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_mem);
86+
u32 rxlen;
87+
int ret;
88+
89+
if (ar->bmi.done_sent) {
90+
ath10k_warn("command disallowed\n");
91+
return -EBUSY;
92+
}
93+
94+
ath10k_dbg(ATH10K_DBG_CORE,
95+
"%s: (device: 0x%p, address: 0x%x, length: %d)\n",
96+
__func__, ar, address, length);
97+
98+
while (length) {
99+
rxlen = min_t(u32, length, BMI_MAX_DATA_SIZE);
100+
101+
cmd.id = __cpu_to_le32(BMI_READ_MEMORY);
102+
cmd.read_mem.addr = __cpu_to_le32(address);
103+
cmd.read_mem.len = __cpu_to_le32(rxlen);
104+
105+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
106+
&resp, &rxlen);
107+
if (ret) {
108+
ath10k_warn("unable to read from the device\n");
109+
return ret;
110+
}
111+
112+
memcpy(buffer, resp.read_mem.payload, rxlen);
113+
address += rxlen;
114+
buffer += rxlen;
115+
length -= rxlen;
116+
}
117+
118+
return 0;
119+
}
120+
121+
int ath10k_bmi_write_memory(struct ath10k *ar,
122+
u32 address, const void *buffer, u32 length)
123+
{
124+
struct bmi_cmd cmd;
125+
u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.write_mem);
126+
u32 txlen;
127+
int ret;
128+
129+
if (ar->bmi.done_sent) {
130+
ath10k_warn("command disallowed\n");
131+
return -EBUSY;
132+
}
133+
134+
ath10k_dbg(ATH10K_DBG_CORE,
135+
"%s: (device: 0x%p, address: 0x%x, length: %d)\n",
136+
__func__, ar, address, length);
137+
138+
while (length) {
139+
txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen);
140+
141+
/* copy before roundup to avoid reading beyond buffer*/
142+
memcpy(cmd.write_mem.payload, buffer, txlen);
143+
txlen = roundup(txlen, 4);
144+
145+
cmd.id = __cpu_to_le32(BMI_WRITE_MEMORY);
146+
cmd.write_mem.addr = __cpu_to_le32(address);
147+
cmd.write_mem.len = __cpu_to_le32(txlen);
148+
149+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
150+
NULL, NULL);
151+
if (ret) {
152+
ath10k_warn("unable to write to the device\n");
153+
return ret;
154+
}
155+
156+
/* fixup roundup() so `length` zeroes out for last chunk */
157+
txlen = min(txlen, length);
158+
159+
address += txlen;
160+
buffer += txlen;
161+
length -= txlen;
162+
}
163+
164+
return 0;
165+
}
166+
167+
int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param)
168+
{
169+
struct bmi_cmd cmd;
170+
union bmi_resp resp;
171+
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.execute);
172+
u32 resplen = sizeof(resp.execute);
173+
int ret;
174+
175+
if (ar->bmi.done_sent) {
176+
ath10k_warn("command disallowed\n");
177+
return -EBUSY;
178+
}
179+
180+
ath10k_dbg(ATH10K_DBG_CORE,
181+
"%s: (device: 0x%p, address: 0x%x, param: %d)\n",
182+
__func__, ar, address, *param);
183+
184+
cmd.id = __cpu_to_le32(BMI_EXECUTE);
185+
cmd.execute.addr = __cpu_to_le32(address);
186+
cmd.execute.param = __cpu_to_le32(*param);
187+
188+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
189+
if (ret) {
190+
ath10k_warn("unable to read from the device\n");
191+
return ret;
192+
}
193+
194+
if (resplen < sizeof(resp.execute)) {
195+
ath10k_warn("invalid execute response length (%d)\n",
196+
resplen);
197+
return ret;
198+
}
199+
200+
*param = __le32_to_cpu(resp.execute.result);
201+
return 0;
202+
}
203+
204+
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
205+
{
206+
struct bmi_cmd cmd;
207+
u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.lz_data);
208+
u32 txlen;
209+
int ret;
210+
211+
if (ar->bmi.done_sent) {
212+
ath10k_warn("command disallowed\n");
213+
return -EBUSY;
214+
}
215+
216+
while (length) {
217+
txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen);
218+
219+
WARN_ON_ONCE(txlen & 3);
220+
221+
cmd.id = __cpu_to_le32(BMI_LZ_DATA);
222+
cmd.lz_data.len = __cpu_to_le32(txlen);
223+
memcpy(cmd.lz_data.payload, buffer, txlen);
224+
225+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
226+
NULL, NULL);
227+
if (ret) {
228+
ath10k_warn("unable to write to the device\n");
229+
return ret;
230+
}
231+
232+
buffer += txlen;
233+
length -= txlen;
234+
}
235+
236+
return 0;
237+
}
238+
239+
int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address)
240+
{
241+
struct bmi_cmd cmd;
242+
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start);
243+
int ret;
244+
245+
if (ar->bmi.done_sent) {
246+
ath10k_warn("command disallowed\n");
247+
return -EBUSY;
248+
}
249+
250+
cmd.id = __cpu_to_le32(BMI_LZ_STREAM_START);
251+
cmd.lz_start.addr = __cpu_to_le32(address);
252+
253+
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
254+
if (ret) {
255+
ath10k_warn("unable to Start LZ Stream to the device\n");
256+
return ret;
257+
}
258+
259+
return 0;
260+
}
261+
262+
int ath10k_bmi_fast_download(struct ath10k *ar,
263+
u32 address, const void *buffer, u32 length)
264+
{
265+
u8 trailer[4] = {};
266+
u32 head_len = rounddown(length, 4);
267+
u32 trailer_len = length - head_len;
268+
int ret;
269+
270+
ret = ath10k_bmi_lz_stream_start(ar, address);
271+
if (ret)
272+
return ret;
273+
274+
/* copy the last word into a zero padded buffer */
275+
if (trailer_len > 0)
276+
memcpy(trailer, buffer + head_len, trailer_len);
277+
278+
ret = ath10k_bmi_lz_data(ar, buffer, head_len);
279+
if (ret)
280+
return ret;
281+
282+
if (trailer_len > 0)
283+
ret = ath10k_bmi_lz_data(ar, trailer, 4);
284+
285+
if (ret != 0)
286+
return ret;
287+
288+
/*
289+
* Close compressed stream and open a new (fake) one.
290+
* This serves mainly to flush Target caches.
291+
*/
292+
ret = ath10k_bmi_lz_stream_start(ar, 0x00);
293+
294+
return ret;
295+
}

0 commit comments

Comments
 (0)