blob: e2a29b25884c42ae72cd3a5179f9b053aa716cab [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 Valo003353b2011-09-01 10:14:21 +030027static unsigned int testmode;
Kalle Valobdcd8172011-07-18 00:22:30 +030028
29module_param(debug_mask, uint, 0644);
Kalle Valo003353b2011-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;
589 ar->auto_auth_stage = AUTH_IDLE;
590
591 init_netdev(dev);
592
593 ar->net_dev = dev;
Raja Mani575b5f32011-07-19 19:27:33 +0530594 set_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +0300595
596 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
597
598 spin_lock_init(&ar->lock);
599
600 ath6kl_init_control_info(ar);
601 init_waitqueue_head(&ar->event_wq);
602 sema_init(&ar->sem, 1);
603 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
604
605 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
606
607 setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
608 (unsigned long) dev);
609
610 return ar;
611}
612
613int ath6kl_unavail_ev(struct ath6kl *ar)
614{
615 ath6kl_destroy(ar->net_dev, 1);
616
617 return 0;
618}
619
620/* firmware upload */
Kalle Valobdcd8172011-07-18 00:22:30 +0300621static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
622 u8 **fw, size_t *fw_len)
623{
624 const struct firmware *fw_entry;
625 int ret;
626
627 ret = request_firmware(&fw_entry, filename, ar->dev);
628 if (ret)
629 return ret;
630
631 *fw_len = fw_entry->size;
632 *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
633
634 if (*fw == NULL)
635 ret = -ENOMEM;
636
637 release_firmware(fw_entry);
638
639 return ret;
640}
641
Sam Leffler92ecbff2011-09-07 10:55:16 +0300642#ifdef CONFIG_OF
643static const char *get_target_ver_dir(const struct ath6kl *ar)
644{
645 switch (ar->version.target_ver) {
646 case AR6003_REV1_VERSION:
647 return "ath6k/AR6003/hw1.0";
648 case AR6003_REV2_VERSION:
649 return "ath6k/AR6003/hw2.0";
650 case AR6003_REV3_VERSION:
651 return "ath6k/AR6003/hw2.1.1";
652 }
653 ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
654 ar->version.target_ver);
655 return NULL;
656}
657
658/*
659 * Check the device tree for a board-id and use it to construct
660 * the pathname to the firmware file. Used (for now) to find a
661 * fallback to the "bdata.bin" file--typically a symlink to the
662 * appropriate board-specific file.
663 */
664static bool check_device_tree(struct ath6kl *ar)
665{
666 static const char *board_id_prop = "atheros,board-id";
667 struct device_node *node;
668 char board_filename[64];
669 const char *board_id;
670 int ret;
671
672 for_each_compatible_node(node, NULL, "atheros,ath6kl") {
673 board_id = of_get_property(node, board_id_prop, NULL);
674 if (board_id == NULL) {
675 ath6kl_warn("No \"%s\" property on %s node.\n",
676 board_id_prop, node->name);
677 continue;
678 }
679 snprintf(board_filename, sizeof(board_filename),
680 "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id);
681
682 ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
683 &ar->fw_board_len);
684 if (ret) {
685 ath6kl_err("Failed to get DT board file %s: %d\n",
686 board_filename, ret);
687 continue;
688 }
689 return true;
690 }
691 return false;
692}
693#else
694static bool check_device_tree(struct ath6kl *ar)
695{
696 return false;
697}
698#endif /* CONFIG_OF */
699
Kalle Valobdcd8172011-07-18 00:22:30 +0300700static int ath6kl_fetch_board_file(struct ath6kl *ar)
701{
702 const char *filename;
703 int ret;
704
Kalle Valo772c31e2011-09-07 10:55:16 +0300705 if (ar->fw_board != NULL)
706 return 0;
707
Kalle Valobdcd8172011-07-18 00:22:30 +0300708 switch (ar->version.target_ver) {
709 case AR6003_REV2_VERSION:
710 filename = AR6003_REV2_BOARD_DATA_FILE;
711 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800712 case AR6004_REV1_VERSION:
713 filename = AR6004_REV1_BOARD_DATA_FILE;
714 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300715 default:
716 filename = AR6003_REV3_BOARD_DATA_FILE;
717 break;
718 }
719
720 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
721 &ar->fw_board_len);
722 if (ret == 0) {
723 /* managed to get proper board file */
724 return 0;
725 }
726
Sam Leffler92ecbff2011-09-07 10:55:16 +0300727 if (check_device_tree(ar)) {
728 /* got board file from device tree */
729 return 0;
730 }
731
Kalle Valobdcd8172011-07-18 00:22:30 +0300732 /* there was no proper board file, try to use default instead */
733 ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
734 filename, ret);
735
736 switch (ar->version.target_ver) {
737 case AR6003_REV2_VERSION:
738 filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
739 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800740 case AR6004_REV1_VERSION:
741 filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
742 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300743 default:
744 filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
745 break;
746 }
747
748 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
749 &ar->fw_board_len);
750 if (ret) {
751 ath6kl_err("Failed to get default board file %s: %d\n",
752 filename, ret);
753 return ret;
754 }
755
756 ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
757 ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
758
759 return 0;
760}
761
Kalle Valo772c31e2011-09-07 10:55:16 +0300762static int ath6kl_fetch_otp_file(struct ath6kl *ar)
763{
764 const char *filename;
765 int ret;
766
767 if (ar->fw_otp != NULL)
768 return 0;
769
770 switch (ar->version.target_ver) {
771 case AR6003_REV2_VERSION:
772 filename = AR6003_REV2_OTP_FILE;
773 break;
774 case AR6004_REV1_VERSION:
775 ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
776 return 0;
777 break;
778 default:
779 filename = AR6003_REV3_OTP_FILE;
780 break;
781 }
782
783 ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
784 &ar->fw_otp_len);
785 if (ret) {
786 ath6kl_err("Failed to get OTP file %s: %d\n",
787 filename, ret);
788 return ret;
789 }
790
791 return 0;
792}
793
794static int ath6kl_fetch_fw_file(struct ath6kl *ar)
795{
796 const char *filename;
797 int ret;
798
799 if (ar->fw != NULL)
800 return 0;
801
802 if (testmode) {
803 switch (ar->version.target_ver) {
804 case AR6003_REV2_VERSION:
805 filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
806 break;
807 case AR6003_REV3_VERSION:
808 filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
809 break;
810 case AR6004_REV1_VERSION:
811 ath6kl_warn("testmode not supported with ar6004\n");
812 return -EOPNOTSUPP;
813 default:
814 ath6kl_warn("unknown target version: 0x%x\n",
815 ar->version.target_ver);
816 return -EINVAL;
817 }
818
819 set_bit(TESTMODE, &ar->flag);
820
821 goto get_fw;
822 }
823
824 switch (ar->version.target_ver) {
825 case AR6003_REV2_VERSION:
826 filename = AR6003_REV2_FIRMWARE_FILE;
827 break;
828 case AR6004_REV1_VERSION:
829 filename = AR6004_REV1_FIRMWARE_FILE;
830 break;
831 default:
832 filename = AR6003_REV3_FIRMWARE_FILE;
833 break;
834 }
835
836get_fw:
837 ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
838 if (ret) {
839 ath6kl_err("Failed to get firmware file %s: %d\n",
840 filename, ret);
841 return ret;
842 }
843
844 return 0;
845}
846
847static int ath6kl_fetch_patch_file(struct ath6kl *ar)
848{
849 const char *filename;
850 int ret;
851
852 switch (ar->version.target_ver) {
853 case AR6003_REV2_VERSION:
854 filename = AR6003_REV2_PATCH_FILE;
855 break;
856 case AR6004_REV1_VERSION:
857 /* FIXME: implement for AR6004 */
858 return 0;
859 break;
860 default:
861 filename = AR6003_REV3_PATCH_FILE;
862 break;
863 }
864
865 if (ar->fw_patch == NULL) {
866 ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
867 &ar->fw_patch_len);
868 if (ret) {
869 ath6kl_err("Failed to get patch file %s: %d\n",
870 filename, ret);
871 return ret;
872 }
873 }
874
875 return 0;
876}
877
Kalle Valo50d41232011-09-07 10:55:17 +0300878static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
Kalle Valo772c31e2011-09-07 10:55:16 +0300879{
880 int ret;
881
Kalle Valo772c31e2011-09-07 10:55:16 +0300882 ret = ath6kl_fetch_otp_file(ar);
883 if (ret)
884 return ret;
885
886 ret = ath6kl_fetch_fw_file(ar);
887 if (ret)
888 return ret;
889
890 ret = ath6kl_fetch_patch_file(ar);
891 if (ret)
892 return ret;
893
894 return 0;
895}
Kalle Valobdcd8172011-07-18 00:22:30 +0300896
Kalle Valo50d41232011-09-07 10:55:17 +0300897static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
898{
899 size_t magic_len, len, ie_len;
900 const struct firmware *fw;
901 struct ath6kl_fw_ie *hdr;
902 const char *filename;
903 const u8 *data;
904 int ret, ie_id;
Kalle Valo8a137482011-09-07 10:55:17 +0300905 __le32 *val;
Kalle Valo50d41232011-09-07 10:55:17 +0300906
907 switch (ar->version.target_ver) {
908 case AR6003_REV2_VERSION:
909 filename = AR6003_REV2_FIRMWARE_2_FILE;
910 break;
911 case AR6003_REV3_VERSION:
912 filename = AR6003_REV3_FIRMWARE_2_FILE;
913 break;
914 case AR6004_REV1_VERSION:
915 filename = AR6004_REV1_FIRMWARE_2_FILE;
916 break;
917 default:
918 return -EOPNOTSUPP;
919 }
920
921 ret = request_firmware(&fw, filename, ar->dev);
922 if (ret)
923 return ret;
924
925 data = fw->data;
926 len = fw->size;
927
928 /* magic also includes the null byte, check that as well */
929 magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
930
931 if (len < magic_len) {
932 ret = -EINVAL;
933 goto out;
934 }
935
936 if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
937 ret = -EINVAL;
938 goto out;
939 }
940
941 len -= magic_len;
942 data += magic_len;
943
944 /* loop elements */
945 while (len > sizeof(struct ath6kl_fw_ie)) {
946 /* hdr is unaligned! */
947 hdr = (struct ath6kl_fw_ie *) data;
948
949 ie_id = le32_to_cpup(&hdr->id);
950 ie_len = le32_to_cpup(&hdr->len);
951
952 len -= sizeof(*hdr);
953 data += sizeof(*hdr);
954
955 if (len < ie_len) {
956 ret = -EINVAL;
957 goto out;
958 }
959
960 switch (ie_id) {
961 case ATH6KL_FW_IE_OTP_IMAGE:
962 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
963
964 if (ar->fw_otp == NULL) {
965 ret = -ENOMEM;
966 goto out;
967 }
968
969 ar->fw_otp_len = ie_len;
970 break;
971 case ATH6KL_FW_IE_FW_IMAGE:
972 ar->fw = kmemdup(data, ie_len, GFP_KERNEL);
973
974 if (ar->fw == NULL) {
975 ret = -ENOMEM;
976 goto out;
977 }
978
979 ar->fw_len = ie_len;
980 break;
981 case ATH6KL_FW_IE_PATCH_IMAGE:
982 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
983
984 if (ar->fw_patch == NULL) {
985 ret = -ENOMEM;
986 goto out;
987 }
988
989 ar->fw_patch_len = ie_len;
990 break;
Kalle Valo8a137482011-09-07 10:55:17 +0300991 case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
992 val = (__le32 *) data;
993 ar->hw.reserved_ram_size = le32_to_cpup(val);
994 break;
Kalle Valo50d41232011-09-07 10:55:17 +0300995 default:
996 ath6kl_dbg(ATH6KL_DBG_TRC, "Unknown fw ie: %u\n",
997 le32_to_cpup(&hdr->id));
998 break;
999 }
1000
1001 len -= ie_len;
1002 data += ie_len;
1003 };
1004
1005 ret = 0;
1006out:
1007 release_firmware(fw);
1008
1009 return ret;
1010}
1011
1012static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1013{
1014 int ret;
1015
1016 ret = ath6kl_fetch_board_file(ar);
1017 if (ret)
1018 return ret;
1019
1020 ret = ath6kl_fetch_fw_api2(ar);
1021 if (ret == 0)
1022 /* fw api 2 found, use it */
1023 return 0;
1024
1025 ret = ath6kl_fetch_fw_api1(ar);
1026 if (ret)
1027 return ret;
1028
1029 return 0;
1030}
1031
Kalle Valobdcd8172011-07-18 00:22:30 +03001032static int ath6kl_upload_board_file(struct ath6kl *ar)
1033{
1034 u32 board_address, board_ext_address, param;
Kevin Fang31024d92011-07-11 17:14:13 +08001035 u32 board_data_size, board_ext_data_size;
Kalle Valobdcd8172011-07-18 00:22:30 +03001036 int ret;
1037
Kalle Valo772c31e2011-09-07 10:55:16 +03001038 if (WARN_ON(ar->fw_board == NULL))
1039 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001040
Kevin Fang31024d92011-07-11 17:14:13 +08001041 /*
1042 * Determine where in Target RAM to write Board Data.
1043 * For AR6004, host determine Target RAM address for
1044 * writing board data.
1045 */
1046 if (ar->target_type == TARGET_TYPE_AR6004) {
1047 board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
1048 ath6kl_bmi_write(ar,
1049 ath6kl_get_hi_item_addr(ar,
1050 HI_ITEM(hi_board_data)),
1051 (u8 *) &board_address, 4);
1052 } else {
1053 ath6kl_bmi_read(ar,
1054 ath6kl_get_hi_item_addr(ar,
1055 HI_ITEM(hi_board_data)),
1056 (u8 *) &board_address, 4);
1057 }
1058
Kalle Valobdcd8172011-07-18 00:22:30 +03001059 ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n",
1060 board_address);
1061
1062 /* determine where in target ram to write extended board data */
1063 ath6kl_bmi_read(ar,
1064 ath6kl_get_hi_item_addr(ar,
1065 HI_ITEM(hi_board_ext_data)),
1066 (u8 *) &board_ext_address, 4);
1067
1068 ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n",
1069 board_ext_address);
1070
1071 if (board_ext_address == 0) {
1072 ath6kl_err("Failed to get board file target address.\n");
1073 return -EINVAL;
1074 }
1075
Kevin Fang31024d92011-07-11 17:14:13 +08001076 switch (ar->target_type) {
1077 case TARGET_TYPE_AR6003:
1078 board_data_size = AR6003_BOARD_DATA_SZ;
1079 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1080 break;
1081 case TARGET_TYPE_AR6004:
1082 board_data_size = AR6004_BOARD_DATA_SZ;
1083 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1084 break;
1085 default:
1086 WARN_ON(1);
1087 return -EINVAL;
1088 break;
1089 }
1090
1091 if (ar->fw_board_len == (board_data_size +
1092 board_ext_data_size)) {
1093
Kalle Valobdcd8172011-07-18 00:22:30 +03001094 /* write extended board data */
1095 ret = ath6kl_bmi_write(ar, board_ext_address,
Kevin Fang31024d92011-07-11 17:14:13 +08001096 ar->fw_board + board_data_size,
1097 board_ext_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001098 if (ret) {
1099 ath6kl_err("Failed to write extended board data: %d\n",
1100 ret);
1101 return ret;
1102 }
1103
1104 /* record that extended board data is initialized */
Kevin Fang31024d92011-07-11 17:14:13 +08001105 param = (board_ext_data_size << 16) | 1;
1106
Kalle Valobdcd8172011-07-18 00:22:30 +03001107 ath6kl_bmi_write(ar,
1108 ath6kl_get_hi_item_addr(ar,
1109 HI_ITEM(hi_board_ext_data_config)),
1110 (unsigned char *) &param, 4);
1111 }
1112
Kevin Fang31024d92011-07-11 17:14:13 +08001113 if (ar->fw_board_len < board_data_size) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001114 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1115 ret = -EINVAL;
1116 return ret;
1117 }
1118
1119 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
Kevin Fang31024d92011-07-11 17:14:13 +08001120 board_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001121
1122 if (ret) {
1123 ath6kl_err("Board file bmi write failed: %d\n", ret);
1124 return ret;
1125 }
1126
1127 /* record the fact that Board Data IS initialized */
1128 param = 1;
1129 ath6kl_bmi_write(ar,
1130 ath6kl_get_hi_item_addr(ar,
1131 HI_ITEM(hi_board_data_initialized)),
1132 (u8 *)&param, 4);
1133
1134 return ret;
1135}
1136
1137static int ath6kl_upload_otp(struct ath6kl *ar)
1138{
Kalle Valobdcd8172011-07-18 00:22:30 +03001139 u32 address, param;
1140 int ret;
1141
Kalle Valo772c31e2011-09-07 10:55:16 +03001142 if (WARN_ON(ar->fw_otp == NULL))
1143 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001144
Kalle Valoa01ac412011-09-07 10:55:17 +03001145 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001146
1147 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1148 ar->fw_otp_len);
1149 if (ret) {
1150 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1151 return ret;
1152 }
1153
Kalle Valo639d0b82011-09-12 12:48:09 +03001154 /* read firmware start address */
1155 ret = ath6kl_bmi_read(ar,
1156 ath6kl_get_hi_item_addr(ar,
1157 HI_ITEM(hi_app_start)),
1158 (u8 *) &address, sizeof(address));
1159
1160 if (ret) {
1161 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1162 return ret;
1163 }
1164
1165 ar->hw.app_start_override_addr = address;
1166
Kalle Valobdcd8172011-07-18 00:22:30 +03001167 /* execute the OTP code */
1168 param = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001169 ath6kl_bmi_execute(ar, address, &param);
1170
1171 return ret;
1172}
1173
1174static int ath6kl_upload_firmware(struct ath6kl *ar)
1175{
Kalle Valobdcd8172011-07-18 00:22:30 +03001176 u32 address;
1177 int ret;
1178
Kalle Valo772c31e2011-09-07 10:55:16 +03001179 if (WARN_ON(ar->fw == NULL))
1180 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001181
Kalle Valoa01ac412011-09-07 10:55:17 +03001182 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001183
1184 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1185
1186 if (ret) {
1187 ath6kl_err("Failed to write firmware: %d\n", ret);
1188 return ret;
1189 }
1190
Kevin Fang31024d92011-07-11 17:14:13 +08001191 /*
1192 * Set starting address for firmware
1193 * Don't need to setup app_start override addr on AR6004
1194 */
1195 if (ar->target_type != TARGET_TYPE_AR6004) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001196 address = ar->hw.app_start_override_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001197 ath6kl_bmi_set_app_start(ar, address);
1198 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001199 return ret;
1200}
1201
1202static int ath6kl_upload_patch(struct ath6kl *ar)
1203{
Kalle Valobdcd8172011-07-18 00:22:30 +03001204 u32 address, param;
1205 int ret;
1206
Kalle Valo772c31e2011-09-07 10:55:16 +03001207 if (WARN_ON(ar->fw_patch == NULL))
1208 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001209
Kalle Valoa01ac412011-09-07 10:55:17 +03001210 address = ar->hw.dataset_patch_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001211
1212 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1213 if (ret) {
1214 ath6kl_err("Failed to write patch file: %d\n", ret);
1215 return ret;
1216 }
1217
1218 param = address;
1219 ath6kl_bmi_write(ar,
1220 ath6kl_get_hi_item_addr(ar,
1221 HI_ITEM(hi_dset_list_head)),
1222 (unsigned char *) &param, 4);
1223
1224 return 0;
1225}
1226
1227static int ath6kl_init_upload(struct ath6kl *ar)
1228{
1229 u32 param, options, sleep, address;
1230 int status = 0;
1231
Kevin Fang31024d92011-07-11 17:14:13 +08001232 if (ar->target_type != TARGET_TYPE_AR6003 &&
1233 ar->target_type != TARGET_TYPE_AR6004)
Kalle Valobdcd8172011-07-18 00:22:30 +03001234 return -EINVAL;
1235
1236 /* temporarily disable system sleep */
1237 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1238 status = ath6kl_bmi_reg_read(ar, address, &param);
1239 if (status)
1240 return status;
1241
1242 options = param;
1243
1244 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1245 status = ath6kl_bmi_reg_write(ar, address, param);
1246 if (status)
1247 return status;
1248
1249 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1250 status = ath6kl_bmi_reg_read(ar, address, &param);
1251 if (status)
1252 return status;
1253
1254 sleep = param;
1255
1256 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1257 status = ath6kl_bmi_reg_write(ar, address, param);
1258 if (status)
1259 return status;
1260
1261 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1262 options, sleep);
1263
1264 /* program analog PLL register */
Kevin Fang31024d92011-07-11 17:14:13 +08001265 /* no need to control 40/44MHz clock on AR6004 */
1266 if (ar->target_type != TARGET_TYPE_AR6004) {
1267 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1268 0xF9104001);
Kalle Valobdcd8172011-07-18 00:22:30 +03001269
Kevin Fang31024d92011-07-11 17:14:13 +08001270 if (status)
1271 return status;
Kalle Valobdcd8172011-07-18 00:22:30 +03001272
Kevin Fang31024d92011-07-11 17:14:13 +08001273 /* Run at 80/88MHz by default */
1274 param = SM(CPU_CLOCK_STANDARD, 1);
1275
1276 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1277 status = ath6kl_bmi_reg_write(ar, address, param);
1278 if (status)
1279 return status;
1280 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001281
1282 param = 0;
1283 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1284 param = SM(LPO_CAL_ENABLE, 1);
1285 status = ath6kl_bmi_reg_write(ar, address, param);
1286 if (status)
1287 return status;
1288
1289 /* WAR to avoid SDIO CRC err */
1290 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1291 ath6kl_err("temporary war to avoid sdio crc error\n");
1292
1293 param = 0x20;
1294
1295 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1296 status = ath6kl_bmi_reg_write(ar, address, param);
1297 if (status)
1298 return status;
1299
1300 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1301 status = ath6kl_bmi_reg_write(ar, address, param);
1302 if (status)
1303 return status;
1304
1305 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1306 status = ath6kl_bmi_reg_write(ar, address, param);
1307 if (status)
1308 return status;
1309
1310 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1311 status = ath6kl_bmi_reg_write(ar, address, param);
1312 if (status)
1313 return status;
1314 }
1315
1316 /* write EEPROM data to Target RAM */
1317 status = ath6kl_upload_board_file(ar);
1318 if (status)
1319 return status;
1320
1321 /* transfer One time Programmable data */
1322 status = ath6kl_upload_otp(ar);
1323 if (status)
1324 return status;
1325
1326 /* Download Target firmware */
1327 status = ath6kl_upload_firmware(ar);
1328 if (status)
1329 return status;
1330
1331 status = ath6kl_upload_patch(ar);
1332 if (status)
1333 return status;
1334
1335 /* Restore system sleep */
1336 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1337 status = ath6kl_bmi_reg_write(ar, address, sleep);
1338 if (status)
1339 return status;
1340
1341 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1342 param = options | 0x20;
1343 status = ath6kl_bmi_reg_write(ar, address, param);
1344 if (status)
1345 return status;
1346
1347 /* Configure GPIO AR6003 UART */
1348 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1349 status = ath6kl_bmi_write(ar,
1350 ath6kl_get_hi_item_addr(ar,
1351 HI_ITEM(hi_dbg_uart_txpin)),
1352 (u8 *)&param, 4);
1353
1354 return status;
1355}
1356
Kalle Valoa01ac412011-09-07 10:55:17 +03001357static int ath6kl_init_hw_params(struct ath6kl *ar)
1358{
1359 switch (ar->version.target_ver) {
1360 case AR6003_REV2_VERSION:
1361 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1362 ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001363 ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
1364 ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001365 break;
1366 case AR6003_REV3_VERSION:
1367 ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
1368 ar->hw.app_load_addr = 0x1234;
Kalle Valo991b27e2011-09-07 10:55:17 +03001369 ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
1370 ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001371 break;
1372 case AR6004_REV1_VERSION:
1373 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1374 ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001375 ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
1376 ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001377 break;
1378 default:
1379 ath6kl_err("Unsupported hardware version: 0x%x\n",
1380 ar->version.target_ver);
1381 return -EINVAL;
1382 }
1383
1384 return 0;
1385}
1386
Kalle Valobdcd8172011-07-18 00:22:30 +03001387static int ath6kl_init(struct net_device *dev)
1388{
1389 struct ath6kl *ar = ath6kl_priv(dev);
1390 int status = 0;
1391 s32 timeleft;
1392
1393 if (!ar)
1394 return -EIO;
1395
1396 /* Do we need to finish the BMI phase */
1397 if (ath6kl_bmi_done(ar)) {
1398 status = -EIO;
1399 goto ath6kl_init_done;
1400 }
1401
1402 /* Indicate that WMI is enabled (although not ready yet) */
1403 set_bit(WMI_ENABLED, &ar->flag);
Vasanthakumar Thiagarajan28657852011-07-21 12:00:49 +05301404 ar->wmi = ath6kl_wmi_init(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001405 if (!ar->wmi) {
1406 ath6kl_err("failed to initialize wmi\n");
1407 status = -EIO;
1408 goto ath6kl_init_done;
1409 }
1410
1411 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1412
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301413 wlan_node_table_init(&ar->scan_table);
1414
Kalle Valobdcd8172011-07-18 00:22:30 +03001415 /*
1416 * The reason we have to wait for the target here is that the
1417 * driver layer has to init BMI in order to set the host block
1418 * size.
1419 */
Kalle Vaload226ec2011-08-10 09:49:12 +03001420 if (ath6kl_htc_wait_target(ar->htc_target)) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001421 status = -EIO;
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301422 goto err_node_cleanup;
Kalle Valobdcd8172011-07-18 00:22:30 +03001423 }
1424
1425 if (ath6kl_init_service_ep(ar)) {
1426 status = -EIO;
1427 goto err_cleanup_scatter;
1428 }
1429
1430 /* setup access class priority mappings */
1431 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1432 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1433 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1434 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1435
1436 /* give our connected endpoints some buffers */
1437 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1438 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1439
1440 /* allocate some buffers that handle larger AMSDU frames */
1441 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1442
1443 /* setup credit distribution */
1444 ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
1445
1446 ath6kl_cookie_init(ar);
1447
1448 /* start HTC */
Kalle Vaload226ec2011-08-10 09:49:12 +03001449 status = ath6kl_htc_start(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001450
1451 if (status) {
1452 ath6kl_cookie_cleanup(ar);
1453 goto err_rxbuf_cleanup;
1454 }
1455
1456 /* Wait for Wmi event to be ready */
1457 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1458 test_bit(WMI_READY,
1459 &ar->flag),
1460 WMI_TIMEOUT);
1461
1462 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1463 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1464 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1465 status = -EIO;
1466 goto err_htc_stop;
1467 }
1468
1469 if (!timeleft || signal_pending(current)) {
1470 ath6kl_err("wmi is not ready or wait was interrupted\n");
1471 status = -EIO;
1472 goto err_htc_stop;
1473 }
1474
1475 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1476
1477 /* communicate the wmi protocol verision to the target */
1478 if ((ath6kl_set_host_app_area(ar)) != 0)
1479 ath6kl_err("unable to set the host app area\n");
1480
1481 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1482 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1483
1484 status = ath6kl_target_config_wlan_params(ar);
1485 if (!status)
1486 goto ath6kl_init_done;
1487
1488err_htc_stop:
Kalle Vaload226ec2011-08-10 09:49:12 +03001489 ath6kl_htc_stop(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001490err_rxbuf_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001491 ath6kl_htc_flush_rx_buf(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001492 ath6kl_cleanup_amsdu_rxbufs(ar);
1493err_cleanup_scatter:
1494 ath6kl_hif_cleanup_scatter(ar);
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301495err_node_cleanup:
1496 wlan_node_table_cleanup(&ar->scan_table);
Kalle Valobdcd8172011-07-18 00:22:30 +03001497 ath6kl_wmi_shutdown(ar->wmi);
1498 clear_bit(WMI_ENABLED, &ar->flag);
1499 ar->wmi = NULL;
1500
1501ath6kl_init_done:
1502 return status;
1503}
1504
1505int ath6kl_core_init(struct ath6kl *ar)
1506{
1507 int ret = 0;
1508 struct ath6kl_bmi_target_info targ_info;
1509
1510 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1511 if (!ar->ath6kl_wq)
1512 return -ENOMEM;
1513
1514 ret = ath6kl_bmi_init(ar);
1515 if (ret)
1516 goto err_wq;
1517
1518 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1519 if (ret)
1520 goto err_bmi_cleanup;
1521
1522 ar->version.target_ver = le32_to_cpu(targ_info.version);
1523 ar->target_type = le32_to_cpu(targ_info.type);
1524 ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
1525
Kalle Valoa01ac412011-09-07 10:55:17 +03001526 ret = ath6kl_init_hw_params(ar);
1527 if (ret)
1528 goto err_bmi_cleanup;
1529
Kalle Valobdcd8172011-07-18 00:22:30 +03001530 ret = ath6kl_configure_target(ar);
1531 if (ret)
1532 goto err_bmi_cleanup;
1533
Kalle Vaload226ec2011-08-10 09:49:12 +03001534 ar->htc_target = ath6kl_htc_create(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001535
1536 if (!ar->htc_target) {
1537 ret = -ENOMEM;
1538 goto err_bmi_cleanup;
1539 }
1540
1541 ar->aggr_cntxt = aggr_init(ar->net_dev);
1542 if (!ar->aggr_cntxt) {
1543 ath6kl_err("failed to initialize aggr\n");
1544 ret = -ENOMEM;
1545 goto err_htc_cleanup;
1546 }
1547
Kalle Valo772c31e2011-09-07 10:55:16 +03001548 ret = ath6kl_fetch_firmwares(ar);
1549 if (ret)
1550 goto err_htc_cleanup;
1551
Kalle Valobdcd8172011-07-18 00:22:30 +03001552 ret = ath6kl_init_upload(ar);
1553 if (ret)
1554 goto err_htc_cleanup;
1555
1556 ret = ath6kl_init(ar->net_dev);
1557 if (ret)
1558 goto err_htc_cleanup;
1559
1560 /* This runs the init function if registered */
1561 ret = register_netdev(ar->net_dev);
1562 if (ret) {
1563 ath6kl_err("register_netdev failed\n");
1564 ath6kl_destroy(ar->net_dev, 0);
1565 return ret;
1566 }
1567
1568 set_bit(NETDEV_REGISTERED, &ar->flag);
1569
1570 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1571 __func__, ar->net_dev->name, ar->net_dev, ar);
1572
1573 return ret;
1574
1575err_htc_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001576 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001577err_bmi_cleanup:
1578 ath6kl_bmi_cleanup(ar);
1579err_wq:
1580 destroy_workqueue(ar->ath6kl_wq);
1581 return ret;
1582}
1583
1584void ath6kl_stop_txrx(struct ath6kl *ar)
1585{
1586 struct net_device *ndev = ar->net_dev;
1587
1588 if (!ndev)
1589 return;
1590
1591 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1592
1593 if (down_interruptible(&ar->sem)) {
1594 ath6kl_err("down_interruptible failed\n");
1595 return;
1596 }
1597
1598 if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
1599 ath6kl_stop_endpoint(ndev, false, true);
1600
Raja Mani575b5f32011-07-19 19:27:33 +05301601 clear_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001602}
1603
1604/*
1605 * We need to differentiate between the surprise and planned removal of the
1606 * device because of the following consideration:
1607 *
1608 * - In case of surprise removal, the hcd already frees up the pending
1609 * for the device and hence there is no need to unregister the function
1610 * driver inorder to get these requests. For planned removal, the function
1611 * driver has to explicitly unregister itself to have the hcd return all the
1612 * pending requests before the data structures for the devices are freed up.
1613 * Note that as per the current implementation, the function driver will
1614 * end up releasing all the devices since there is no API to selectively
1615 * release a particular device.
1616 *
1617 * - Certain commands issued to the target can be skipped for surprise
1618 * removal since they will anyway not go through.
1619 */
1620void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
1621{
1622 struct ath6kl *ar;
1623
1624 if (!dev || !ath6kl_priv(dev)) {
1625 ath6kl_err("failed to get device structure\n");
1626 return;
1627 }
1628
1629 ar = ath6kl_priv(dev);
1630
1631 destroy_workqueue(ar->ath6kl_wq);
1632
1633 if (ar->htc_target)
Kalle Vaload226ec2011-08-10 09:49:12 +03001634 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001635
1636 aggr_module_destroy(ar->aggr_cntxt);
1637
1638 ath6kl_cookie_cleanup(ar);
1639
1640 ath6kl_cleanup_amsdu_rxbufs(ar);
1641
1642 ath6kl_bmi_cleanup(ar);
1643
Kalle Valobdf53962011-09-02 10:32:04 +03001644 ath6kl_debug_cleanup(ar);
1645
Kalle Valobdcd8172011-07-18 00:22:30 +03001646 if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
1647 unregister_netdev(dev);
1648 clear_bit(NETDEV_REGISTERED, &ar->flag);
1649 }
1650
1651 free_netdev(dev);
1652
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301653 wlan_node_table_cleanup(&ar->scan_table);
1654
Raja Mani19703572011-08-04 19:26:30 +05301655 kfree(ar->fw_board);
1656 kfree(ar->fw_otp);
1657 kfree(ar->fw);
1658 kfree(ar->fw_patch);
1659
Kalle Valobdcd8172011-07-18 00:22:30 +03001660 ath6kl_cfg80211_deinit(ar);
1661}