blob: 7e10f712ae4db60b98c2df6d31d499ff9914acd0 [file] [log] [blame]
Kalle Valobdcd8172011-07-18 00:22:30 +03001
2/*
3 * Copyright (c) 2011 Atheros Communications 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
Sam Leffler92ecbff2011-09-07 10:55:16 +030018#include <linux/of.h>
Kalle Valobdcd8172011-07-18 00:22:30 +030019#include <linux/mmc/sdio_func.h>
20#include "core.h"
21#include "cfg80211.h"
22#include "target.h"
23#include "debug.h"
24#include "hif-ops.h"
25
26unsigned int debug_mask;
Kalle Valo003353b0d2011-09-01 10:14:21 +030027static unsigned int testmode;
Kalle Valobdcd8172011-07-18 00:22:30 +030028
29module_param(debug_mask, uint, 0644);
Kalle Valo003353b0d2011-09-01 10:14:21 +030030module_param(testmode, uint, 0644);
Kalle Valobdcd8172011-07-18 00:22:30 +030031
32/*
33 * Include definitions here that can be used to tune the WLAN module
34 * behavior. Different customers can tune the behavior as per their needs,
35 * here.
36 */
37
38/*
39 * This configuration item enable/disable keepalive support.
40 * Keepalive support: In the absence of any data traffic to AP, null
41 * frames will be sent to the AP at periodic interval, to keep the association
42 * active. This configuration item defines the periodic interval.
43 * Use value of zero to disable keepalive support
44 * Default: 60 seconds
45 */
46#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
47
48/*
49 * This configuration item sets the value of disconnect timeout
50 * Firmware delays sending the disconnec event to the host for this
51 * timeout after is gets disconnected from the current AP.
52 * If the firmware successly roams within the disconnect timeout
53 * it sends a new connect event
54 */
55#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
56
57#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
58
Kalle Valobdcd8172011-07-18 00:22:30 +030059#define ATH6KL_DATA_OFFSET 64
60struct sk_buff *ath6kl_buf_alloc(int size)
61{
62 struct sk_buff *skb;
63 u16 reserved;
64
65 /* Add chacheline space at front and back of buffer */
66 reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
Vasanthakumar Thiagarajan1df94a82011-08-17 18:45:10 +053067 sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
Kalle Valobdcd8172011-07-18 00:22:30 +030068 skb = dev_alloc_skb(size + reserved);
69
70 if (skb)
71 skb_reserve(skb, reserved - L1_CACHE_BYTES);
72 return skb;
73}
74
75void ath6kl_init_profile_info(struct ath6kl *ar)
76{
77 ar->ssid_len = 0;
78 memset(ar->ssid, 0, sizeof(ar->ssid));
79
80 ar->dot11_auth_mode = OPEN_AUTH;
81 ar->auth_mode = NONE_AUTH;
82 ar->prwise_crypto = NONE_CRYPT;
83 ar->prwise_crypto_len = 0;
84 ar->grp_crypto = NONE_CRYPT;
Edward Lu38acde32011-08-30 21:58:06 +030085 ar->grp_crypto_len = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +030086 memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
87 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
88 memset(ar->bssid, 0, sizeof(ar->bssid));
89 ar->bss_ch = 0;
90 ar->nw_type = ar->next_mode = INFRA_NETWORK;
91}
92
93static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
94{
95 switch (ar->nw_type) {
96 case INFRA_NETWORK:
97 return HI_OPTION_FW_MODE_BSS_STA;
98 case ADHOC_NETWORK:
99 return HI_OPTION_FW_MODE_IBSS;
100 case AP_NETWORK:
101 return HI_OPTION_FW_MODE_AP;
102 default:
103 ath6kl_err("Unsupported interface type :%d\n", ar->nw_type);
104 return 0xff;
105 }
106}
107
Kalle Valobdcd8172011-07-18 00:22:30 +0300108static int ath6kl_set_host_app_area(struct ath6kl *ar)
109{
110 u32 address, data;
111 struct host_app_area host_app_area;
112
113 /* Fetch the address of the host_app_area_s
114 * instance in the host interest area */
115 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
Kevin Fang31024d92011-07-11 17:14:13 +0800116 address = TARG_VTOP(ar->target_type, address);
Kalle Valobdcd8172011-07-18 00:22:30 +0300117
Kalle Valoaddb44b2011-09-02 10:32:05 +0300118 if (ath6kl_diag_read32(ar, address, &data))
Kalle Valobdcd8172011-07-18 00:22:30 +0300119 return -EIO;
120
Kevin Fang31024d92011-07-11 17:14:13 +0800121 address = TARG_VTOP(ar->target_type, data);
Kalle Valobdcd8172011-07-18 00:22:30 +0300122 host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
Kalle Valoaddb44b2011-09-02 10:32:05 +0300123 if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
124 sizeof(struct host_app_area)))
Kalle Valobdcd8172011-07-18 00:22:30 +0300125 return -EIO;
126
127 return 0;
128}
129
130static inline void set_ac2_ep_map(struct ath6kl *ar,
131 u8 ac,
132 enum htc_endpoint_id ep)
133{
134 ar->ac2ep_map[ac] = ep;
135 ar->ep2ac_map[ep] = ac;
136}
137
138/* connect to a service */
139static int ath6kl_connectservice(struct ath6kl *ar,
140 struct htc_service_connect_req *con_req,
141 char *desc)
142{
143 int status;
144 struct htc_service_connect_resp response;
145
146 memset(&response, 0, sizeof(response));
147
Kalle Vaload226ec2011-08-10 09:49:12 +0300148 status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
Kalle Valobdcd8172011-07-18 00:22:30 +0300149 if (status) {
150 ath6kl_err("failed to connect to %s service status:%d\n",
151 desc, status);
152 return status;
153 }
154
155 switch (con_req->svc_id) {
156 case WMI_CONTROL_SVC:
157 if (test_bit(WMI_ENABLED, &ar->flag))
158 ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
159 ar->ctrl_ep = response.endpoint;
160 break;
161 case WMI_DATA_BE_SVC:
162 set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
163 break;
164 case WMI_DATA_BK_SVC:
165 set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
166 break;
167 case WMI_DATA_VI_SVC:
168 set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
169 break;
170 case WMI_DATA_VO_SVC:
171 set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
172 break;
173 default:
174 ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
175 return -EINVAL;
176 }
177
178 return 0;
179}
180
181static int ath6kl_init_service_ep(struct ath6kl *ar)
182{
183 struct htc_service_connect_req connect;
184
185 memset(&connect, 0, sizeof(connect));
186
187 /* these fields are the same for all service endpoints */
188 connect.ep_cb.rx = ath6kl_rx;
189 connect.ep_cb.rx_refill = ath6kl_rx_refill;
190 connect.ep_cb.tx_full = ath6kl_tx_queue_full;
191
192 /*
193 * Set the max queue depth so that our ath6kl_tx_queue_full handler
194 * gets called.
195 */
196 connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
197 connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
198 if (!connect.ep_cb.rx_refill_thresh)
199 connect.ep_cb.rx_refill_thresh++;
200
201 /* connect to control service */
202 connect.svc_id = WMI_CONTROL_SVC;
203 if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
204 return -EIO;
205
206 connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
207
208 /*
209 * Limit the HTC message size on the send path, although e can
210 * receive A-MSDU frames of 4K, we will only send ethernet-sized
211 * (802.3) frames on the send path.
212 */
213 connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
214
215 /*
216 * To reduce the amount of committed memory for larger A_MSDU
217 * frames, use the recv-alloc threshold mechanism for larger
218 * packets.
219 */
220 connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
221 connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
222
223 /*
224 * For the remaining data services set the connection flag to
225 * reduce dribbling, if configured to do so.
226 */
227 connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
228 connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
229 connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
230
231 connect.svc_id = WMI_DATA_BE_SVC;
232
233 if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
234 return -EIO;
235
236 /* connect to back-ground map this to WMI LOW_PRI */
237 connect.svc_id = WMI_DATA_BK_SVC;
238 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
239 return -EIO;
240
241 /* connect to Video service, map this to to HI PRI */
242 connect.svc_id = WMI_DATA_VI_SVC;
243 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
244 return -EIO;
245
246 /*
247 * Connect to VO service, this is currently not mapped to a WMI
248 * priority stream due to historical reasons. WMI originally
249 * defined 3 priorities over 3 mailboxes We can change this when
250 * WMI is reworked so that priorities are not dependent on
251 * mailboxes.
252 */
253 connect.svc_id = WMI_DATA_VO_SVC;
254 if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
255 return -EIO;
256
257 return 0;
258}
259
260static void ath6kl_init_control_info(struct ath6kl *ar)
261{
262 u8 ctr;
263
264 clear_bit(WMI_ENABLED, &ar->flag);
265 ath6kl_init_profile_info(ar);
266 ar->def_txkey_index = 0;
267 memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
268 ar->ch_hint = 0;
269 ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
270 ar->listen_intvl_b = 0;
271 ar->tx_pwr = 0;
272 clear_bit(SKIP_SCAN, &ar->flag);
273 set_bit(WMM_ENABLED, &ar->flag);
274 ar->intra_bss = 1;
275 memset(&ar->sc_params, 0, sizeof(ar->sc_params));
276 ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
277 ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
Vivek Natarajane5090442011-08-31 15:02:19 +0530278 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
Kalle Valobdcd8172011-07-18 00:22:30 +0300279
280 memset((u8 *)ar->sta_list, 0,
281 AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
282
283 spin_lock_init(&ar->mcastpsq_lock);
284
285 /* Init the PS queues */
286 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
287 spin_lock_init(&ar->sta_list[ctr].psq_lock);
288 skb_queue_head_init(&ar->sta_list[ctr].psq);
289 }
290
291 skb_queue_head_init(&ar->mcastpsq);
292
293 memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
294}
295
296/*
297 * Set HTC/Mbox operational parameters, this can only be called when the
298 * target is in the BMI phase.
299 */
300static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
301 u8 htc_ctrl_buf)
302{
303 int status;
304 u32 blk_size;
305
306 blk_size = ar->mbox_info.block_size;
307
308 if (htc_ctrl_buf)
309 blk_size |= ((u32)htc_ctrl_buf) << 16;
310
311 /* set the host interest area for the block size */
312 status = ath6kl_bmi_write(ar,
313 ath6kl_get_hi_item_addr(ar,
314 HI_ITEM(hi_mbox_io_block_sz)),
315 (u8 *)&blk_size,
316 4);
317 if (status) {
318 ath6kl_err("bmi_write_memory for IO block size failed\n");
319 goto out;
320 }
321
322 ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
323 blk_size,
324 ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));
325
326 if (mbox_isr_yield_val) {
327 /* set the host interest area for the mbox ISR yield limit */
328 status = ath6kl_bmi_write(ar,
329 ath6kl_get_hi_item_addr(ar,
330 HI_ITEM(hi_mbox_isr_yield_limit)),
331 (u8 *)&mbox_isr_yield_val,
332 4);
333 if (status) {
334 ath6kl_err("bmi_write_memory for yield limit failed\n");
335 goto out;
336 }
337 }
338
339out:
340 return status;
341}
342
343#define REG_DUMP_COUNT_AR6003 60
344#define REGISTER_DUMP_LEN_MAX 60
345
346static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
347{
348 u32 address;
349 u32 regdump_loc = 0;
350 int status;
351 u32 regdump_val[REGISTER_DUMP_LEN_MAX];
352 u32 i;
353
354 if (ar->target_type != TARGET_TYPE_AR6003)
355 return;
356
357 /* the reg dump pointer is copied to the host interest area */
358 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
Kevin Fang31024d92011-07-11 17:14:13 +0800359 address = TARG_VTOP(ar->target_type, address);
Kalle Valobdcd8172011-07-18 00:22:30 +0300360
361 /* read RAM location through diagnostic window */
Kalle Valoaddb44b2011-09-02 10:32:05 +0300362 status = ath6kl_diag_read32(ar, address, &regdump_loc);
Kalle Valobdcd8172011-07-18 00:22:30 +0300363
364 if (status || !regdump_loc) {
365 ath6kl_err("failed to get ptr to register dump area\n");
366 return;
367 }
368
369 ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
370 regdump_loc);
Kevin Fang31024d92011-07-11 17:14:13 +0800371 regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
Kalle Valobdcd8172011-07-18 00:22:30 +0300372
373 /* fetch register dump data */
Kalle Valoaddb44b2011-09-02 10:32:05 +0300374 status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
375 REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
Kalle Valobdcd8172011-07-18 00:22:30 +0300376
377 if (status) {
378 ath6kl_err("failed to get register dump\n");
379 return;
380 }
381 ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
382
383 for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
384 ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
385 i, regdump_val[i]);
386
387}
388
389void ath6kl_target_failure(struct ath6kl *ar)
390{
391 ath6kl_err("target asserted\n");
392
393 /* try dumping target assertion information (if any) */
394 ath6kl_dump_target_assert_info(ar);
395
396}
397
398static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
399{
400 int status = 0;
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300401 int ret;
Kalle Valobdcd8172011-07-18 00:22:30 +0300402
403 /*
404 * Configure the device for rx dot11 header rules. "0,0" are the
405 * default values. Required if checksum offload is needed. Set
406 * RxMetaVersion to 2.
407 */
408 if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
409 ar->rx_meta_ver, 0, 0)) {
410 ath6kl_err("unable to set the rx frame format\n");
411 status = -EIO;
412 }
413
414 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
415 if ((ath6kl_wmi_pmparams_cmd(ar->wmi, 0, 1, 0, 0, 1,
416 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
417 ath6kl_err("unable to set power save fail event policy\n");
418 status = -EIO;
419 }
420
421 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
422 if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, 0,
423 WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
424 ath6kl_err("unable to set barker preamble policy\n");
425 status = -EIO;
426 }
427
428 if (ath6kl_wmi_set_keepalive_cmd(ar->wmi,
429 WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
430 ath6kl_err("unable to set keep alive interval\n");
431 status = -EIO;
432 }
433
434 if (ath6kl_wmi_disctimeout_cmd(ar->wmi,
435 WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
436 ath6kl_err("unable to set disconnect timeout\n");
437 status = -EIO;
438 }
439
440 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
441 if (ath6kl_wmi_set_wmm_txop(ar->wmi, WMI_TXOP_DISABLED)) {
442 ath6kl_err("unable to set txop bursting\n");
443 status = -EIO;
444 }
445
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300446 if (ar->p2p) {
447 ret = ath6kl_wmi_info_req_cmd(ar->wmi,
448 P2P_FLAG_CAPABILITIES_REQ |
449 P2P_FLAG_MACADDR_REQ |
450 P2P_FLAG_HMODEL_REQ);
451 if (ret) {
452 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P "
453 "capabilities (%d) - assuming P2P not "
454 "supported\n", ret);
455 ar->p2p = 0;
456 }
457 }
458
459 if (ar->p2p) {
460 /* Enable Probe Request reporting for P2P */
461 ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, true);
462 if (ret) {
463 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
464 "Request reporting (%d)\n", ret);
465 }
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300466 }
467
Kalle Valobdcd8172011-07-18 00:22:30 +0300468 return status;
469}
470
471int ath6kl_configure_target(struct ath6kl *ar)
472{
473 u32 param, ram_reserved_size;
474 u8 fw_iftype;
475
476 fw_iftype = ath6kl_get_fw_iftype(ar);
477 if (fw_iftype == 0xff)
478 return -EINVAL;
479
480 /* Tell target which HTC version it is used*/
481 param = HTC_PROTOCOL_VERSION;
482 if (ath6kl_bmi_write(ar,
483 ath6kl_get_hi_item_addr(ar,
484 HI_ITEM(hi_app_host_interest)),
485 (u8 *)&param, 4) != 0) {
486 ath6kl_err("bmi_write_memory for htc version failed\n");
487 return -EIO;
488 }
489
490 /* set the firmware mode to STA/IBSS/AP */
491 param = 0;
492
493 if (ath6kl_bmi_read(ar,
494 ath6kl_get_hi_item_addr(ar,
495 HI_ITEM(hi_option_flag)),
496 (u8 *)&param, 4) != 0) {
497 ath6kl_err("bmi_read_memory for setting fwmode failed\n");
498 return -EIO;
499 }
500
501 param |= (1 << HI_OPTION_NUM_DEV_SHIFT);
502 param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT);
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300503 if (ar->p2p && fw_iftype == HI_OPTION_FW_MODE_BSS_STA) {
504 param |= HI_OPTION_FW_SUBMODE_P2PDEV <<
505 HI_OPTION_FW_SUBMODE_SHIFT;
506 }
Kalle Valobdcd8172011-07-18 00:22:30 +0300507 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
508 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
509
510 if (ath6kl_bmi_write(ar,
511 ath6kl_get_hi_item_addr(ar,
512 HI_ITEM(hi_option_flag)),
513 (u8 *)&param,
514 4) != 0) {
515 ath6kl_err("bmi_write_memory for setting fwmode failed\n");
516 return -EIO;
517 }
518
519 ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
520
521 /*
522 * Hardcode the address use for the extended board data
523 * Ideally this should be pre-allocate by the OS at boot time
524 * But since it is a new feature and board data is loaded
525 * at init time, we have to workaround this from host.
526 * It is difficult to patch the firmware boot code,
527 * but possible in theory.
528 */
529
Kalle Valo991b27e2011-09-07 10:55:17 +0300530 param = ar->hw.board_ext_data_addr;
531 ram_reserved_size = ar->hw.reserved_ram_size;
Kalle Valobdcd8172011-07-18 00:22:30 +0300532
Kalle Valo991b27e2011-09-07 10:55:17 +0300533 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
534 HI_ITEM(hi_board_ext_data)),
535 (u8 *)&param, 4) != 0) {
536 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
537 return -EIO;
538 }
539
540 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
541 HI_ITEM(hi_end_ram_reserve_sz)),
542 (u8 *)&ram_reserved_size, 4) != 0) {
543 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
544 return -EIO;
Kalle Valobdcd8172011-07-18 00:22:30 +0300545 }
546
547 /* set the block size for the target */
548 if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
549 /* use default number of control buffers */
550 return -EIO;
551
552 return 0;
553}
554
555struct ath6kl *ath6kl_core_alloc(struct device *sdev)
556{
557 struct net_device *dev;
558 struct ath6kl *ar;
559 struct wireless_dev *wdev;
560
561 wdev = ath6kl_cfg80211_init(sdev);
562 if (!wdev) {
563 ath6kl_err("ath6kl_cfg80211_init failed\n");
564 return NULL;
565 }
566
567 ar = wdev_priv(wdev);
568 ar->dev = sdev;
569 ar->wdev = wdev;
570 wdev->iftype = NL80211_IFTYPE_STATION;
571
Vasanthakumar Thiagarajand999ba32011-08-26 13:06:31 +0530572 if (ath6kl_debug_init(ar)) {
573 ath6kl_err("Failed to initialize debugfs\n");
574 ath6kl_cfg80211_deinit(ar);
575 return NULL;
576 }
577
Kalle Valobdcd8172011-07-18 00:22:30 +0300578 dev = alloc_netdev(0, "wlan%d", ether_setup);
579 if (!dev) {
580 ath6kl_err("no memory for network device instance\n");
581 ath6kl_cfg80211_deinit(ar);
582 return NULL;
583 }
584
585 dev->ieee80211_ptr = wdev;
586 SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
587 wdev->netdev = dev;
588 ar->sme_state = SME_DISCONNECTED;
Kalle Valobdcd8172011-07-18 00:22:30 +0300589
590 init_netdev(dev);
591
592 ar->net_dev = dev;
Raja Mani575b5f32011-07-19 19:27:33 +0530593 set_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +0300594
595 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
596
597 spin_lock_init(&ar->lock);
598
599 ath6kl_init_control_info(ar);
600 init_waitqueue_head(&ar->event_wq);
601 sema_init(&ar->sem, 1);
602 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
603
604 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
605
606 setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
607 (unsigned long) dev);
608
609 return ar;
610}
611
612int ath6kl_unavail_ev(struct ath6kl *ar)
613{
614 ath6kl_destroy(ar->net_dev, 1);
615
616 return 0;
617}
618
619/* firmware upload */
Kalle Valobdcd8172011-07-18 00:22:30 +0300620static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
621 u8 **fw, size_t *fw_len)
622{
623 const struct firmware *fw_entry;
624 int ret;
625
626 ret = request_firmware(&fw_entry, filename, ar->dev);
627 if (ret)
628 return ret;
629
630 *fw_len = fw_entry->size;
631 *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
632
633 if (*fw == NULL)
634 ret = -ENOMEM;
635
636 release_firmware(fw_entry);
637
638 return ret;
639}
640
Sam Leffler92ecbff2011-09-07 10:55:16 +0300641#ifdef CONFIG_OF
642static const char *get_target_ver_dir(const struct ath6kl *ar)
643{
644 switch (ar->version.target_ver) {
645 case AR6003_REV1_VERSION:
646 return "ath6k/AR6003/hw1.0";
647 case AR6003_REV2_VERSION:
648 return "ath6k/AR6003/hw2.0";
649 case AR6003_REV3_VERSION:
650 return "ath6k/AR6003/hw2.1.1";
651 }
652 ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
653 ar->version.target_ver);
654 return NULL;
655}
656
657/*
658 * Check the device tree for a board-id and use it to construct
659 * the pathname to the firmware file. Used (for now) to find a
660 * fallback to the "bdata.bin" file--typically a symlink to the
661 * appropriate board-specific file.
662 */
663static bool check_device_tree(struct ath6kl *ar)
664{
665 static const char *board_id_prop = "atheros,board-id";
666 struct device_node *node;
667 char board_filename[64];
668 const char *board_id;
669 int ret;
670
671 for_each_compatible_node(node, NULL, "atheros,ath6kl") {
672 board_id = of_get_property(node, board_id_prop, NULL);
673 if (board_id == NULL) {
674 ath6kl_warn("No \"%s\" property on %s node.\n",
675 board_id_prop, node->name);
676 continue;
677 }
678 snprintf(board_filename, sizeof(board_filename),
679 "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id);
680
681 ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
682 &ar->fw_board_len);
683 if (ret) {
684 ath6kl_err("Failed to get DT board file %s: %d\n",
685 board_filename, ret);
686 continue;
687 }
688 return true;
689 }
690 return false;
691}
692#else
693static bool check_device_tree(struct ath6kl *ar)
694{
695 return false;
696}
697#endif /* CONFIG_OF */
698
Kalle Valobdcd8172011-07-18 00:22:30 +0300699static int ath6kl_fetch_board_file(struct ath6kl *ar)
700{
701 const char *filename;
702 int ret;
703
Kalle Valo772c31e2011-09-07 10:55:16 +0300704 if (ar->fw_board != NULL)
705 return 0;
706
Kalle Valobdcd8172011-07-18 00:22:30 +0300707 switch (ar->version.target_ver) {
708 case AR6003_REV2_VERSION:
709 filename = AR6003_REV2_BOARD_DATA_FILE;
710 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800711 case AR6004_REV1_VERSION:
712 filename = AR6004_REV1_BOARD_DATA_FILE;
713 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300714 default:
715 filename = AR6003_REV3_BOARD_DATA_FILE;
716 break;
717 }
718
719 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
720 &ar->fw_board_len);
721 if (ret == 0) {
722 /* managed to get proper board file */
723 return 0;
724 }
725
Sam Leffler92ecbff2011-09-07 10:55:16 +0300726 if (check_device_tree(ar)) {
727 /* got board file from device tree */
728 return 0;
729 }
730
Kalle Valobdcd8172011-07-18 00:22:30 +0300731 /* there was no proper board file, try to use default instead */
732 ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
733 filename, ret);
734
735 switch (ar->version.target_ver) {
736 case AR6003_REV2_VERSION:
737 filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
738 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800739 case AR6004_REV1_VERSION:
740 filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
741 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300742 default:
743 filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
744 break;
745 }
746
747 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
748 &ar->fw_board_len);
749 if (ret) {
750 ath6kl_err("Failed to get default board file %s: %d\n",
751 filename, ret);
752 return ret;
753 }
754
755 ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
756 ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
757
758 return 0;
759}
760
Kalle Valo772c31e2011-09-07 10:55:16 +0300761static int ath6kl_fetch_otp_file(struct ath6kl *ar)
762{
763 const char *filename;
764 int ret;
765
766 if (ar->fw_otp != NULL)
767 return 0;
768
769 switch (ar->version.target_ver) {
770 case AR6003_REV2_VERSION:
771 filename = AR6003_REV2_OTP_FILE;
772 break;
773 case AR6004_REV1_VERSION:
774 ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
775 return 0;
776 break;
777 default:
778 filename = AR6003_REV3_OTP_FILE;
779 break;
780 }
781
782 ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
783 &ar->fw_otp_len);
784 if (ret) {
785 ath6kl_err("Failed to get OTP file %s: %d\n",
786 filename, ret);
787 return ret;
788 }
789
790 return 0;
791}
792
793static int ath6kl_fetch_fw_file(struct ath6kl *ar)
794{
795 const char *filename;
796 int ret;
797
798 if (ar->fw != NULL)
799 return 0;
800
801 if (testmode) {
802 switch (ar->version.target_ver) {
803 case AR6003_REV2_VERSION:
804 filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
805 break;
806 case AR6003_REV3_VERSION:
807 filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
808 break;
809 case AR6004_REV1_VERSION:
810 ath6kl_warn("testmode not supported with ar6004\n");
811 return -EOPNOTSUPP;
812 default:
813 ath6kl_warn("unknown target version: 0x%x\n",
814 ar->version.target_ver);
815 return -EINVAL;
816 }
817
818 set_bit(TESTMODE, &ar->flag);
819
820 goto get_fw;
821 }
822
823 switch (ar->version.target_ver) {
824 case AR6003_REV2_VERSION:
825 filename = AR6003_REV2_FIRMWARE_FILE;
826 break;
827 case AR6004_REV1_VERSION:
828 filename = AR6004_REV1_FIRMWARE_FILE;
829 break;
830 default:
831 filename = AR6003_REV3_FIRMWARE_FILE;
832 break;
833 }
834
835get_fw:
836 ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
837 if (ret) {
838 ath6kl_err("Failed to get firmware file %s: %d\n",
839 filename, ret);
840 return ret;
841 }
842
843 return 0;
844}
845
846static int ath6kl_fetch_patch_file(struct ath6kl *ar)
847{
848 const char *filename;
849 int ret;
850
851 switch (ar->version.target_ver) {
852 case AR6003_REV2_VERSION:
853 filename = AR6003_REV2_PATCH_FILE;
854 break;
855 case AR6004_REV1_VERSION:
856 /* FIXME: implement for AR6004 */
857 return 0;
858 break;
859 default:
860 filename = AR6003_REV3_PATCH_FILE;
861 break;
862 }
863
864 if (ar->fw_patch == NULL) {
865 ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
866 &ar->fw_patch_len);
867 if (ret) {
868 ath6kl_err("Failed to get patch file %s: %d\n",
869 filename, ret);
870 return ret;
871 }
872 }
873
874 return 0;
875}
876
Kalle Valo50d41232011-09-07 10:55:17 +0300877static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
Kalle Valo772c31e2011-09-07 10:55:16 +0300878{
879 int ret;
880
Kalle Valo772c31e2011-09-07 10:55:16 +0300881 ret = ath6kl_fetch_otp_file(ar);
882 if (ret)
883 return ret;
884
885 ret = ath6kl_fetch_fw_file(ar);
886 if (ret)
887 return ret;
888
889 ret = ath6kl_fetch_patch_file(ar);
890 if (ret)
891 return ret;
892
893 return 0;
894}
Kalle Valobdcd8172011-07-18 00:22:30 +0300895
Kalle Valo50d41232011-09-07 10:55:17 +0300896static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
897{
898 size_t magic_len, len, ie_len;
899 const struct firmware *fw;
900 struct ath6kl_fw_ie *hdr;
901 const char *filename;
902 const u8 *data;
Kalle Valo97e04962011-09-12 13:47:34 +0300903 int ret, ie_id, i, index, bit;
Kalle Valo8a137482011-09-07 10:55:17 +0300904 __le32 *val;
Kalle Valo50d41232011-09-07 10:55:17 +0300905
906 switch (ar->version.target_ver) {
907 case AR6003_REV2_VERSION:
908 filename = AR6003_REV2_FIRMWARE_2_FILE;
909 break;
910 case AR6003_REV3_VERSION:
911 filename = AR6003_REV3_FIRMWARE_2_FILE;
912 break;
913 case AR6004_REV1_VERSION:
914 filename = AR6004_REV1_FIRMWARE_2_FILE;
915 break;
916 default:
917 return -EOPNOTSUPP;
918 }
919
920 ret = request_firmware(&fw, filename, ar->dev);
921 if (ret)
922 return ret;
923
924 data = fw->data;
925 len = fw->size;
926
927 /* magic also includes the null byte, check that as well */
928 magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
929
930 if (len < magic_len) {
931 ret = -EINVAL;
932 goto out;
933 }
934
935 if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
936 ret = -EINVAL;
937 goto out;
938 }
939
940 len -= magic_len;
941 data += magic_len;
942
943 /* loop elements */
944 while (len > sizeof(struct ath6kl_fw_ie)) {
945 /* hdr is unaligned! */
946 hdr = (struct ath6kl_fw_ie *) data;
947
948 ie_id = le32_to_cpup(&hdr->id);
949 ie_len = le32_to_cpup(&hdr->len);
950
951 len -= sizeof(*hdr);
952 data += sizeof(*hdr);
953
954 if (len < ie_len) {
955 ret = -EINVAL;
956 goto out;
957 }
958
959 switch (ie_id) {
960 case ATH6KL_FW_IE_OTP_IMAGE:
961 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
962
963 if (ar->fw_otp == NULL) {
964 ret = -ENOMEM;
965 goto out;
966 }
967
968 ar->fw_otp_len = ie_len;
969 break;
970 case ATH6KL_FW_IE_FW_IMAGE:
971 ar->fw = kmemdup(data, ie_len, GFP_KERNEL);
972
973 if (ar->fw == NULL) {
974 ret = -ENOMEM;
975 goto out;
976 }
977
978 ar->fw_len = ie_len;
979 break;
980 case ATH6KL_FW_IE_PATCH_IMAGE:
981 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
982
983 if (ar->fw_patch == NULL) {
984 ret = -ENOMEM;
985 goto out;
986 }
987
988 ar->fw_patch_len = ie_len;
989 break;
Kalle Valo8a137482011-09-07 10:55:17 +0300990 case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
991 val = (__le32 *) data;
992 ar->hw.reserved_ram_size = le32_to_cpup(val);
993 break;
Kalle Valo97e04962011-09-12 13:47:34 +0300994 case ATH6KL_FW_IE_CAPABILITIES:
995 for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
996 index = ALIGN(i, 8) / 8;
997 bit = i % 8;
998
999 if (data[index] & (1 << bit))
1000 __set_bit(i, ar->fw_capabilities);
1001 }
1002 break;
Kalle Valo50d41232011-09-07 10:55:17 +03001003 default:
1004 ath6kl_dbg(ATH6KL_DBG_TRC, "Unknown fw ie: %u\n",
1005 le32_to_cpup(&hdr->id));
1006 break;
1007 }
1008
1009 len -= ie_len;
1010 data += ie_len;
1011 };
1012
1013 ret = 0;
1014out:
1015 release_firmware(fw);
1016
1017 return ret;
1018}
1019
1020static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1021{
1022 int ret;
1023
1024 ret = ath6kl_fetch_board_file(ar);
1025 if (ret)
1026 return ret;
1027
1028 ret = ath6kl_fetch_fw_api2(ar);
1029 if (ret == 0)
1030 /* fw api 2 found, use it */
1031 return 0;
1032
1033 ret = ath6kl_fetch_fw_api1(ar);
1034 if (ret)
1035 return ret;
1036
1037 return 0;
1038}
1039
Kalle Valobdcd8172011-07-18 00:22:30 +03001040static int ath6kl_upload_board_file(struct ath6kl *ar)
1041{
1042 u32 board_address, board_ext_address, param;
Kevin Fang31024d92011-07-11 17:14:13 +08001043 u32 board_data_size, board_ext_data_size;
Kalle Valobdcd8172011-07-18 00:22:30 +03001044 int ret;
1045
Kalle Valo772c31e2011-09-07 10:55:16 +03001046 if (WARN_ON(ar->fw_board == NULL))
1047 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001048
Kevin Fang31024d92011-07-11 17:14:13 +08001049 /*
1050 * Determine where in Target RAM to write Board Data.
1051 * For AR6004, host determine Target RAM address for
1052 * writing board data.
1053 */
1054 if (ar->target_type == TARGET_TYPE_AR6004) {
1055 board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
1056 ath6kl_bmi_write(ar,
1057 ath6kl_get_hi_item_addr(ar,
1058 HI_ITEM(hi_board_data)),
1059 (u8 *) &board_address, 4);
1060 } else {
1061 ath6kl_bmi_read(ar,
1062 ath6kl_get_hi_item_addr(ar,
1063 HI_ITEM(hi_board_data)),
1064 (u8 *) &board_address, 4);
1065 }
1066
Kalle Valobdcd8172011-07-18 00:22:30 +03001067 ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n",
1068 board_address);
1069
1070 /* determine where in target ram to write extended board data */
1071 ath6kl_bmi_read(ar,
1072 ath6kl_get_hi_item_addr(ar,
1073 HI_ITEM(hi_board_ext_data)),
1074 (u8 *) &board_ext_address, 4);
1075
1076 ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n",
1077 board_ext_address);
1078
1079 if (board_ext_address == 0) {
1080 ath6kl_err("Failed to get board file target address.\n");
1081 return -EINVAL;
1082 }
1083
Kevin Fang31024d92011-07-11 17:14:13 +08001084 switch (ar->target_type) {
1085 case TARGET_TYPE_AR6003:
1086 board_data_size = AR6003_BOARD_DATA_SZ;
1087 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1088 break;
1089 case TARGET_TYPE_AR6004:
1090 board_data_size = AR6004_BOARD_DATA_SZ;
1091 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1092 break;
1093 default:
1094 WARN_ON(1);
1095 return -EINVAL;
1096 break;
1097 }
1098
1099 if (ar->fw_board_len == (board_data_size +
1100 board_ext_data_size)) {
1101
Kalle Valobdcd8172011-07-18 00:22:30 +03001102 /* write extended board data */
1103 ret = ath6kl_bmi_write(ar, board_ext_address,
Kevin Fang31024d92011-07-11 17:14:13 +08001104 ar->fw_board + board_data_size,
1105 board_ext_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001106 if (ret) {
1107 ath6kl_err("Failed to write extended board data: %d\n",
1108 ret);
1109 return ret;
1110 }
1111
1112 /* record that extended board data is initialized */
Kevin Fang31024d92011-07-11 17:14:13 +08001113 param = (board_ext_data_size << 16) | 1;
1114
Kalle Valobdcd8172011-07-18 00:22:30 +03001115 ath6kl_bmi_write(ar,
1116 ath6kl_get_hi_item_addr(ar,
1117 HI_ITEM(hi_board_ext_data_config)),
1118 (unsigned char *) &param, 4);
1119 }
1120
Kevin Fang31024d92011-07-11 17:14:13 +08001121 if (ar->fw_board_len < board_data_size) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001122 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1123 ret = -EINVAL;
1124 return ret;
1125 }
1126
1127 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
Kevin Fang31024d92011-07-11 17:14:13 +08001128 board_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001129
1130 if (ret) {
1131 ath6kl_err("Board file bmi write failed: %d\n", ret);
1132 return ret;
1133 }
1134
1135 /* record the fact that Board Data IS initialized */
1136 param = 1;
1137 ath6kl_bmi_write(ar,
1138 ath6kl_get_hi_item_addr(ar,
1139 HI_ITEM(hi_board_data_initialized)),
1140 (u8 *)&param, 4);
1141
1142 return ret;
1143}
1144
1145static int ath6kl_upload_otp(struct ath6kl *ar)
1146{
Kalle Valobdcd8172011-07-18 00:22:30 +03001147 u32 address, param;
1148 int ret;
1149
Kalle Valo772c31e2011-09-07 10:55:16 +03001150 if (WARN_ON(ar->fw_otp == NULL))
1151 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001152
Kalle Valoa01ac412011-09-07 10:55:17 +03001153 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001154
1155 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1156 ar->fw_otp_len);
1157 if (ret) {
1158 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1159 return ret;
1160 }
1161
Kalle Valo639d0b82011-09-12 12:48:09 +03001162 /* read firmware start address */
1163 ret = ath6kl_bmi_read(ar,
1164 ath6kl_get_hi_item_addr(ar,
1165 HI_ITEM(hi_app_start)),
1166 (u8 *) &address, sizeof(address));
1167
1168 if (ret) {
1169 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1170 return ret;
1171 }
1172
1173 ar->hw.app_start_override_addr = address;
1174
Kalle Valobdcd8172011-07-18 00:22:30 +03001175 /* execute the OTP code */
1176 param = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001177 ath6kl_bmi_execute(ar, address, &param);
1178
1179 return ret;
1180}
1181
1182static int ath6kl_upload_firmware(struct ath6kl *ar)
1183{
Kalle Valobdcd8172011-07-18 00:22:30 +03001184 u32 address;
1185 int ret;
1186
Kalle Valo772c31e2011-09-07 10:55:16 +03001187 if (WARN_ON(ar->fw == NULL))
1188 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001189
Kalle Valoa01ac412011-09-07 10:55:17 +03001190 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001191
1192 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1193
1194 if (ret) {
1195 ath6kl_err("Failed to write firmware: %d\n", ret);
1196 return ret;
1197 }
1198
Kevin Fang31024d92011-07-11 17:14:13 +08001199 /*
1200 * Set starting address for firmware
1201 * Don't need to setup app_start override addr on AR6004
1202 */
1203 if (ar->target_type != TARGET_TYPE_AR6004) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001204 address = ar->hw.app_start_override_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001205 ath6kl_bmi_set_app_start(ar, address);
1206 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001207 return ret;
1208}
1209
1210static int ath6kl_upload_patch(struct ath6kl *ar)
1211{
Kalle Valobdcd8172011-07-18 00:22:30 +03001212 u32 address, param;
1213 int ret;
1214
Kalle Valo772c31e2011-09-07 10:55:16 +03001215 if (WARN_ON(ar->fw_patch == NULL))
1216 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001217
Kalle Valoa01ac412011-09-07 10:55:17 +03001218 address = ar->hw.dataset_patch_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001219
1220 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1221 if (ret) {
1222 ath6kl_err("Failed to write patch file: %d\n", ret);
1223 return ret;
1224 }
1225
1226 param = address;
1227 ath6kl_bmi_write(ar,
1228 ath6kl_get_hi_item_addr(ar,
1229 HI_ITEM(hi_dset_list_head)),
1230 (unsigned char *) &param, 4);
1231
1232 return 0;
1233}
1234
1235static int ath6kl_init_upload(struct ath6kl *ar)
1236{
1237 u32 param, options, sleep, address;
1238 int status = 0;
1239
Kevin Fang31024d92011-07-11 17:14:13 +08001240 if (ar->target_type != TARGET_TYPE_AR6003 &&
1241 ar->target_type != TARGET_TYPE_AR6004)
Kalle Valobdcd8172011-07-18 00:22:30 +03001242 return -EINVAL;
1243
1244 /* temporarily disable system sleep */
1245 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1246 status = ath6kl_bmi_reg_read(ar, address, &param);
1247 if (status)
1248 return status;
1249
1250 options = param;
1251
1252 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1253 status = ath6kl_bmi_reg_write(ar, address, param);
1254 if (status)
1255 return status;
1256
1257 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1258 status = ath6kl_bmi_reg_read(ar, address, &param);
1259 if (status)
1260 return status;
1261
1262 sleep = param;
1263
1264 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1265 status = ath6kl_bmi_reg_write(ar, address, param);
1266 if (status)
1267 return status;
1268
1269 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1270 options, sleep);
1271
1272 /* program analog PLL register */
Kevin Fang31024d92011-07-11 17:14:13 +08001273 /* no need to control 40/44MHz clock on AR6004 */
1274 if (ar->target_type != TARGET_TYPE_AR6004) {
1275 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1276 0xF9104001);
Kalle Valobdcd8172011-07-18 00:22:30 +03001277
Kevin Fang31024d92011-07-11 17:14:13 +08001278 if (status)
1279 return status;
Kalle Valobdcd8172011-07-18 00:22:30 +03001280
Kevin Fang31024d92011-07-11 17:14:13 +08001281 /* Run at 80/88MHz by default */
1282 param = SM(CPU_CLOCK_STANDARD, 1);
1283
1284 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1285 status = ath6kl_bmi_reg_write(ar, address, param);
1286 if (status)
1287 return status;
1288 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001289
1290 param = 0;
1291 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1292 param = SM(LPO_CAL_ENABLE, 1);
1293 status = ath6kl_bmi_reg_write(ar, address, param);
1294 if (status)
1295 return status;
1296
1297 /* WAR to avoid SDIO CRC err */
1298 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1299 ath6kl_err("temporary war to avoid sdio crc error\n");
1300
1301 param = 0x20;
1302
1303 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1304 status = ath6kl_bmi_reg_write(ar, address, param);
1305 if (status)
1306 return status;
1307
1308 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1309 status = ath6kl_bmi_reg_write(ar, address, param);
1310 if (status)
1311 return status;
1312
1313 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1314 status = ath6kl_bmi_reg_write(ar, address, param);
1315 if (status)
1316 return status;
1317
1318 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1319 status = ath6kl_bmi_reg_write(ar, address, param);
1320 if (status)
1321 return status;
1322 }
1323
1324 /* write EEPROM data to Target RAM */
1325 status = ath6kl_upload_board_file(ar);
1326 if (status)
1327 return status;
1328
1329 /* transfer One time Programmable data */
1330 status = ath6kl_upload_otp(ar);
1331 if (status)
1332 return status;
1333
1334 /* Download Target firmware */
1335 status = ath6kl_upload_firmware(ar);
1336 if (status)
1337 return status;
1338
1339 status = ath6kl_upload_patch(ar);
1340 if (status)
1341 return status;
1342
1343 /* Restore system sleep */
1344 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1345 status = ath6kl_bmi_reg_write(ar, address, sleep);
1346 if (status)
1347 return status;
1348
1349 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1350 param = options | 0x20;
1351 status = ath6kl_bmi_reg_write(ar, address, param);
1352 if (status)
1353 return status;
1354
1355 /* Configure GPIO AR6003 UART */
1356 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1357 status = ath6kl_bmi_write(ar,
1358 ath6kl_get_hi_item_addr(ar,
1359 HI_ITEM(hi_dbg_uart_txpin)),
1360 (u8 *)&param, 4);
1361
1362 return status;
1363}
1364
Kalle Valoa01ac412011-09-07 10:55:17 +03001365static int ath6kl_init_hw_params(struct ath6kl *ar)
1366{
1367 switch (ar->version.target_ver) {
1368 case AR6003_REV2_VERSION:
1369 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1370 ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001371 ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
1372 ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001373 break;
1374 case AR6003_REV3_VERSION:
1375 ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
1376 ar->hw.app_load_addr = 0x1234;
Kalle Valo991b27e2011-09-07 10:55:17 +03001377 ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
1378 ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001379 break;
1380 case AR6004_REV1_VERSION:
1381 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1382 ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001383 ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
1384 ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001385 break;
1386 default:
1387 ath6kl_err("Unsupported hardware version: 0x%x\n",
1388 ar->version.target_ver);
1389 return -EINVAL;
1390 }
1391
1392 return 0;
1393}
1394
Kalle Valobdcd8172011-07-18 00:22:30 +03001395static int ath6kl_init(struct net_device *dev)
1396{
1397 struct ath6kl *ar = ath6kl_priv(dev);
1398 int status = 0;
1399 s32 timeleft;
1400
1401 if (!ar)
1402 return -EIO;
1403
1404 /* Do we need to finish the BMI phase */
1405 if (ath6kl_bmi_done(ar)) {
1406 status = -EIO;
1407 goto ath6kl_init_done;
1408 }
1409
1410 /* Indicate that WMI is enabled (although not ready yet) */
1411 set_bit(WMI_ENABLED, &ar->flag);
Vasanthakumar Thiagarajan28657852011-07-21 12:00:49 +05301412 ar->wmi = ath6kl_wmi_init(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001413 if (!ar->wmi) {
1414 ath6kl_err("failed to initialize wmi\n");
1415 status = -EIO;
1416 goto ath6kl_init_done;
1417 }
1418
1419 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1420
1421 /*
1422 * The reason we have to wait for the target here is that the
1423 * driver layer has to init BMI in order to set the host block
1424 * size.
1425 */
Kalle Vaload226ec2011-08-10 09:49:12 +03001426 if (ath6kl_htc_wait_target(ar->htc_target)) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001427 status = -EIO;
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301428 goto err_node_cleanup;
Kalle Valobdcd8172011-07-18 00:22:30 +03001429 }
1430
1431 if (ath6kl_init_service_ep(ar)) {
1432 status = -EIO;
1433 goto err_cleanup_scatter;
1434 }
1435
1436 /* setup access class priority mappings */
1437 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1438 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1439 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1440 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1441
1442 /* give our connected endpoints some buffers */
1443 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1444 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1445
1446 /* allocate some buffers that handle larger AMSDU frames */
1447 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1448
1449 /* setup credit distribution */
1450 ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
1451
1452 ath6kl_cookie_init(ar);
1453
1454 /* start HTC */
Kalle Vaload226ec2011-08-10 09:49:12 +03001455 status = ath6kl_htc_start(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001456
1457 if (status) {
1458 ath6kl_cookie_cleanup(ar);
1459 goto err_rxbuf_cleanup;
1460 }
1461
1462 /* Wait for Wmi event to be ready */
1463 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1464 test_bit(WMI_READY,
1465 &ar->flag),
1466 WMI_TIMEOUT);
1467
1468 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1469 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1470 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1471 status = -EIO;
1472 goto err_htc_stop;
1473 }
1474
1475 if (!timeleft || signal_pending(current)) {
1476 ath6kl_err("wmi is not ready or wait was interrupted\n");
1477 status = -EIO;
1478 goto err_htc_stop;
1479 }
1480
1481 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1482
1483 /* communicate the wmi protocol verision to the target */
1484 if ((ath6kl_set_host_app_area(ar)) != 0)
1485 ath6kl_err("unable to set the host app area\n");
1486
1487 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1488 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1489
1490 status = ath6kl_target_config_wlan_params(ar);
1491 if (!status)
1492 goto ath6kl_init_done;
1493
1494err_htc_stop:
Kalle Vaload226ec2011-08-10 09:49:12 +03001495 ath6kl_htc_stop(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001496err_rxbuf_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001497 ath6kl_htc_flush_rx_buf(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001498 ath6kl_cleanup_amsdu_rxbufs(ar);
1499err_cleanup_scatter:
1500 ath6kl_hif_cleanup_scatter(ar);
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301501err_node_cleanup:
Kalle Valobdcd8172011-07-18 00:22:30 +03001502 ath6kl_wmi_shutdown(ar->wmi);
1503 clear_bit(WMI_ENABLED, &ar->flag);
1504 ar->wmi = NULL;
1505
1506ath6kl_init_done:
1507 return status;
1508}
1509
1510int ath6kl_core_init(struct ath6kl *ar)
1511{
1512 int ret = 0;
1513 struct ath6kl_bmi_target_info targ_info;
1514
1515 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1516 if (!ar->ath6kl_wq)
1517 return -ENOMEM;
1518
1519 ret = ath6kl_bmi_init(ar);
1520 if (ret)
1521 goto err_wq;
1522
1523 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1524 if (ret)
1525 goto err_bmi_cleanup;
1526
1527 ar->version.target_ver = le32_to_cpu(targ_info.version);
1528 ar->target_type = le32_to_cpu(targ_info.type);
1529 ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
1530
Kalle Valoa01ac412011-09-07 10:55:17 +03001531 ret = ath6kl_init_hw_params(ar);
1532 if (ret)
1533 goto err_bmi_cleanup;
1534
Kalle Valobdcd8172011-07-18 00:22:30 +03001535 ret = ath6kl_configure_target(ar);
1536 if (ret)
1537 goto err_bmi_cleanup;
1538
Kalle Vaload226ec2011-08-10 09:49:12 +03001539 ar->htc_target = ath6kl_htc_create(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001540
1541 if (!ar->htc_target) {
1542 ret = -ENOMEM;
1543 goto err_bmi_cleanup;
1544 }
1545
1546 ar->aggr_cntxt = aggr_init(ar->net_dev);
1547 if (!ar->aggr_cntxt) {
1548 ath6kl_err("failed to initialize aggr\n");
1549 ret = -ENOMEM;
1550 goto err_htc_cleanup;
1551 }
1552
Kalle Valo772c31e2011-09-07 10:55:16 +03001553 ret = ath6kl_fetch_firmwares(ar);
1554 if (ret)
1555 goto err_htc_cleanup;
1556
Kalle Valobdcd8172011-07-18 00:22:30 +03001557 ret = ath6kl_init_upload(ar);
1558 if (ret)
1559 goto err_htc_cleanup;
1560
1561 ret = ath6kl_init(ar->net_dev);
1562 if (ret)
1563 goto err_htc_cleanup;
1564
1565 /* This runs the init function if registered */
1566 ret = register_netdev(ar->net_dev);
1567 if (ret) {
1568 ath6kl_err("register_netdev failed\n");
1569 ath6kl_destroy(ar->net_dev, 0);
1570 return ret;
1571 }
1572
1573 set_bit(NETDEV_REGISTERED, &ar->flag);
1574
1575 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1576 __func__, ar->net_dev->name, ar->net_dev, ar);
1577
1578 return ret;
1579
1580err_htc_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001581 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001582err_bmi_cleanup:
1583 ath6kl_bmi_cleanup(ar);
1584err_wq:
1585 destroy_workqueue(ar->ath6kl_wq);
1586 return ret;
1587}
1588
1589void ath6kl_stop_txrx(struct ath6kl *ar)
1590{
1591 struct net_device *ndev = ar->net_dev;
1592
1593 if (!ndev)
1594 return;
1595
1596 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1597
1598 if (down_interruptible(&ar->sem)) {
1599 ath6kl_err("down_interruptible failed\n");
1600 return;
1601 }
1602
1603 if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
1604 ath6kl_stop_endpoint(ndev, false, true);
1605
Raja Mani575b5f32011-07-19 19:27:33 +05301606 clear_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001607}
1608
1609/*
1610 * We need to differentiate between the surprise and planned removal of the
1611 * device because of the following consideration:
1612 *
1613 * - In case of surprise removal, the hcd already frees up the pending
1614 * for the device and hence there is no need to unregister the function
1615 * driver inorder to get these requests. For planned removal, the function
1616 * driver has to explicitly unregister itself to have the hcd return all the
1617 * pending requests before the data structures for the devices are freed up.
1618 * Note that as per the current implementation, the function driver will
1619 * end up releasing all the devices since there is no API to selectively
1620 * release a particular device.
1621 *
1622 * - Certain commands issued to the target can be skipped for surprise
1623 * removal since they will anyway not go through.
1624 */
1625void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
1626{
1627 struct ath6kl *ar;
1628
1629 if (!dev || !ath6kl_priv(dev)) {
1630 ath6kl_err("failed to get device structure\n");
1631 return;
1632 }
1633
1634 ar = ath6kl_priv(dev);
1635
1636 destroy_workqueue(ar->ath6kl_wq);
1637
1638 if (ar->htc_target)
Kalle Vaload226ec2011-08-10 09:49:12 +03001639 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001640
1641 aggr_module_destroy(ar->aggr_cntxt);
1642
1643 ath6kl_cookie_cleanup(ar);
1644
1645 ath6kl_cleanup_amsdu_rxbufs(ar);
1646
1647 ath6kl_bmi_cleanup(ar);
1648
Kalle Valobdf53962011-09-02 10:32:04 +03001649 ath6kl_debug_cleanup(ar);
1650
Kalle Valobdcd8172011-07-18 00:22:30 +03001651 if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
1652 unregister_netdev(dev);
1653 clear_bit(NETDEV_REGISTERED, &ar->flag);
1654 }
1655
1656 free_netdev(dev);
1657
Raja Mani19703572011-08-04 19:26:30 +05301658 kfree(ar->fw_board);
1659 kfree(ar->fw_otp);
1660 kfree(ar->fw);
1661 kfree(ar->fw_patch);
1662
Kalle Valobdcd8172011-07-18 00:22:30 +03001663 ath6kl_cfg80211_deinit(ar);
1664}