blob: e9785feeea17f1cbaaeca97661f28565a38040bb [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;
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 Valo1b4304d2011-09-27 11:05:26 +03001003 case ATH6KL_FW_IE_PATCH_ADDR:
1004 if (ie_len != sizeof(*val))
1005 break;
1006
1007 val = (__le32 *) data;
1008 ar->hw.dataset_patch_addr = le32_to_cpup(val);
1009 break;
Kalle Valo50d41232011-09-07 10:55:17 +03001010 default:
1011 ath6kl_dbg(ATH6KL_DBG_TRC, "Unknown fw ie: %u\n",
1012 le32_to_cpup(&hdr->id));
1013 break;
1014 }
1015
1016 len -= ie_len;
1017 data += ie_len;
1018 };
1019
1020 ret = 0;
1021out:
1022 release_firmware(fw);
1023
1024 return ret;
1025}
1026
1027static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1028{
1029 int ret;
1030
1031 ret = ath6kl_fetch_board_file(ar);
1032 if (ret)
1033 return ret;
1034
1035 ret = ath6kl_fetch_fw_api2(ar);
1036 if (ret == 0)
1037 /* fw api 2 found, use it */
1038 return 0;
1039
1040 ret = ath6kl_fetch_fw_api1(ar);
1041 if (ret)
1042 return ret;
1043
1044 return 0;
1045}
1046
Kalle Valobdcd8172011-07-18 00:22:30 +03001047static int ath6kl_upload_board_file(struct ath6kl *ar)
1048{
1049 u32 board_address, board_ext_address, param;
Kevin Fang31024d92011-07-11 17:14:13 +08001050 u32 board_data_size, board_ext_data_size;
Kalle Valobdcd8172011-07-18 00:22:30 +03001051 int ret;
1052
Kalle Valo772c31e2011-09-07 10:55:16 +03001053 if (WARN_ON(ar->fw_board == NULL))
1054 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001055
Kevin Fang31024d92011-07-11 17:14:13 +08001056 /*
1057 * Determine where in Target RAM to write Board Data.
1058 * For AR6004, host determine Target RAM address for
1059 * writing board data.
1060 */
1061 if (ar->target_type == TARGET_TYPE_AR6004) {
1062 board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
1063 ath6kl_bmi_write(ar,
1064 ath6kl_get_hi_item_addr(ar,
1065 HI_ITEM(hi_board_data)),
1066 (u8 *) &board_address, 4);
1067 } else {
1068 ath6kl_bmi_read(ar,
1069 ath6kl_get_hi_item_addr(ar,
1070 HI_ITEM(hi_board_data)),
1071 (u8 *) &board_address, 4);
1072 }
1073
Kalle Valobdcd8172011-07-18 00:22:30 +03001074 ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n",
1075 board_address);
1076
1077 /* determine where in target ram to write extended board data */
1078 ath6kl_bmi_read(ar,
1079 ath6kl_get_hi_item_addr(ar,
1080 HI_ITEM(hi_board_ext_data)),
1081 (u8 *) &board_ext_address, 4);
1082
1083 ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n",
1084 board_ext_address);
1085
1086 if (board_ext_address == 0) {
1087 ath6kl_err("Failed to get board file target address.\n");
1088 return -EINVAL;
1089 }
1090
Kevin Fang31024d92011-07-11 17:14:13 +08001091 switch (ar->target_type) {
1092 case TARGET_TYPE_AR6003:
1093 board_data_size = AR6003_BOARD_DATA_SZ;
1094 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1095 break;
1096 case TARGET_TYPE_AR6004:
1097 board_data_size = AR6004_BOARD_DATA_SZ;
1098 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1099 break;
1100 default:
1101 WARN_ON(1);
1102 return -EINVAL;
1103 break;
1104 }
1105
1106 if (ar->fw_board_len == (board_data_size +
1107 board_ext_data_size)) {
1108
Kalle Valobdcd8172011-07-18 00:22:30 +03001109 /* write extended board data */
1110 ret = ath6kl_bmi_write(ar, board_ext_address,
Kevin Fang31024d92011-07-11 17:14:13 +08001111 ar->fw_board + board_data_size,
1112 board_ext_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001113 if (ret) {
1114 ath6kl_err("Failed to write extended board data: %d\n",
1115 ret);
1116 return ret;
1117 }
1118
1119 /* record that extended board data is initialized */
Kevin Fang31024d92011-07-11 17:14:13 +08001120 param = (board_ext_data_size << 16) | 1;
1121
Kalle Valobdcd8172011-07-18 00:22:30 +03001122 ath6kl_bmi_write(ar,
1123 ath6kl_get_hi_item_addr(ar,
1124 HI_ITEM(hi_board_ext_data_config)),
1125 (unsigned char *) &param, 4);
1126 }
1127
Kevin Fang31024d92011-07-11 17:14:13 +08001128 if (ar->fw_board_len < board_data_size) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001129 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1130 ret = -EINVAL;
1131 return ret;
1132 }
1133
1134 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
Kevin Fang31024d92011-07-11 17:14:13 +08001135 board_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001136
1137 if (ret) {
1138 ath6kl_err("Board file bmi write failed: %d\n", ret);
1139 return ret;
1140 }
1141
1142 /* record the fact that Board Data IS initialized */
1143 param = 1;
1144 ath6kl_bmi_write(ar,
1145 ath6kl_get_hi_item_addr(ar,
1146 HI_ITEM(hi_board_data_initialized)),
1147 (u8 *)&param, 4);
1148
1149 return ret;
1150}
1151
1152static int ath6kl_upload_otp(struct ath6kl *ar)
1153{
Kalle Valobdcd8172011-07-18 00:22:30 +03001154 u32 address, param;
1155 int ret;
1156
Kalle Valo772c31e2011-09-07 10:55:16 +03001157 if (WARN_ON(ar->fw_otp == NULL))
1158 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001159
Kalle Valoa01ac412011-09-07 10:55:17 +03001160 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001161
1162 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1163 ar->fw_otp_len);
1164 if (ret) {
1165 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1166 return ret;
1167 }
1168
Kalle Valo639d0b82011-09-12 12:48:09 +03001169 /* read firmware start address */
1170 ret = ath6kl_bmi_read(ar,
1171 ath6kl_get_hi_item_addr(ar,
1172 HI_ITEM(hi_app_start)),
1173 (u8 *) &address, sizeof(address));
1174
1175 if (ret) {
1176 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1177 return ret;
1178 }
1179
1180 ar->hw.app_start_override_addr = address;
1181
Kalle Valobdcd8172011-07-18 00:22:30 +03001182 /* execute the OTP code */
1183 param = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001184 ath6kl_bmi_execute(ar, address, &param);
1185
1186 return ret;
1187}
1188
1189static int ath6kl_upload_firmware(struct ath6kl *ar)
1190{
Kalle Valobdcd8172011-07-18 00:22:30 +03001191 u32 address;
1192 int ret;
1193
Kalle Valo772c31e2011-09-07 10:55:16 +03001194 if (WARN_ON(ar->fw == NULL))
1195 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001196
Kalle Valoa01ac412011-09-07 10:55:17 +03001197 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001198
1199 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1200
1201 if (ret) {
1202 ath6kl_err("Failed to write firmware: %d\n", ret);
1203 return ret;
1204 }
1205
Kevin Fang31024d92011-07-11 17:14:13 +08001206 /*
1207 * Set starting address for firmware
1208 * Don't need to setup app_start override addr on AR6004
1209 */
1210 if (ar->target_type != TARGET_TYPE_AR6004) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001211 address = ar->hw.app_start_override_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001212 ath6kl_bmi_set_app_start(ar, address);
1213 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001214 return ret;
1215}
1216
1217static int ath6kl_upload_patch(struct ath6kl *ar)
1218{
Kalle Valobdcd8172011-07-18 00:22:30 +03001219 u32 address, param;
1220 int ret;
1221
Kalle Valo772c31e2011-09-07 10:55:16 +03001222 if (WARN_ON(ar->fw_patch == NULL))
1223 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001224
Kalle Valoa01ac412011-09-07 10:55:17 +03001225 address = ar->hw.dataset_patch_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001226
1227 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1228 if (ret) {
1229 ath6kl_err("Failed to write patch file: %d\n", ret);
1230 return ret;
1231 }
1232
1233 param = address;
1234 ath6kl_bmi_write(ar,
1235 ath6kl_get_hi_item_addr(ar,
1236 HI_ITEM(hi_dset_list_head)),
1237 (unsigned char *) &param, 4);
1238
1239 return 0;
1240}
1241
1242static int ath6kl_init_upload(struct ath6kl *ar)
1243{
1244 u32 param, options, sleep, address;
1245 int status = 0;
1246
Kevin Fang31024d92011-07-11 17:14:13 +08001247 if (ar->target_type != TARGET_TYPE_AR6003 &&
1248 ar->target_type != TARGET_TYPE_AR6004)
Kalle Valobdcd8172011-07-18 00:22:30 +03001249 return -EINVAL;
1250
1251 /* temporarily disable system sleep */
1252 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1253 status = ath6kl_bmi_reg_read(ar, address, &param);
1254 if (status)
1255 return status;
1256
1257 options = param;
1258
1259 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1260 status = ath6kl_bmi_reg_write(ar, address, param);
1261 if (status)
1262 return status;
1263
1264 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1265 status = ath6kl_bmi_reg_read(ar, address, &param);
1266 if (status)
1267 return status;
1268
1269 sleep = param;
1270
1271 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1272 status = ath6kl_bmi_reg_write(ar, address, param);
1273 if (status)
1274 return status;
1275
1276 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1277 options, sleep);
1278
1279 /* program analog PLL register */
Kevin Fang31024d92011-07-11 17:14:13 +08001280 /* no need to control 40/44MHz clock on AR6004 */
1281 if (ar->target_type != TARGET_TYPE_AR6004) {
1282 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1283 0xF9104001);
Kalle Valobdcd8172011-07-18 00:22:30 +03001284
Kevin Fang31024d92011-07-11 17:14:13 +08001285 if (status)
1286 return status;
Kalle Valobdcd8172011-07-18 00:22:30 +03001287
Kevin Fang31024d92011-07-11 17:14:13 +08001288 /* Run at 80/88MHz by default */
1289 param = SM(CPU_CLOCK_STANDARD, 1);
1290
1291 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1292 status = ath6kl_bmi_reg_write(ar, address, param);
1293 if (status)
1294 return status;
1295 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001296
1297 param = 0;
1298 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1299 param = SM(LPO_CAL_ENABLE, 1);
1300 status = ath6kl_bmi_reg_write(ar, address, param);
1301 if (status)
1302 return status;
1303
1304 /* WAR to avoid SDIO CRC err */
1305 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1306 ath6kl_err("temporary war to avoid sdio crc error\n");
1307
1308 param = 0x20;
1309
1310 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1311 status = ath6kl_bmi_reg_write(ar, address, param);
1312 if (status)
1313 return status;
1314
1315 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1316 status = ath6kl_bmi_reg_write(ar, address, param);
1317 if (status)
1318 return status;
1319
1320 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1321 status = ath6kl_bmi_reg_write(ar, address, param);
1322 if (status)
1323 return status;
1324
1325 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1326 status = ath6kl_bmi_reg_write(ar, address, param);
1327 if (status)
1328 return status;
1329 }
1330
1331 /* write EEPROM data to Target RAM */
1332 status = ath6kl_upload_board_file(ar);
1333 if (status)
1334 return status;
1335
1336 /* transfer One time Programmable data */
1337 status = ath6kl_upload_otp(ar);
1338 if (status)
1339 return status;
1340
1341 /* Download Target firmware */
1342 status = ath6kl_upload_firmware(ar);
1343 if (status)
1344 return status;
1345
1346 status = ath6kl_upload_patch(ar);
1347 if (status)
1348 return status;
1349
1350 /* Restore system sleep */
1351 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1352 status = ath6kl_bmi_reg_write(ar, address, sleep);
1353 if (status)
1354 return status;
1355
1356 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1357 param = options | 0x20;
1358 status = ath6kl_bmi_reg_write(ar, address, param);
1359 if (status)
1360 return status;
1361
1362 /* Configure GPIO AR6003 UART */
1363 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1364 status = ath6kl_bmi_write(ar,
1365 ath6kl_get_hi_item_addr(ar,
1366 HI_ITEM(hi_dbg_uart_txpin)),
1367 (u8 *)&param, 4);
1368
1369 return status;
1370}
1371
Kalle Valoa01ac412011-09-07 10:55:17 +03001372static int ath6kl_init_hw_params(struct ath6kl *ar)
1373{
1374 switch (ar->version.target_ver) {
1375 case AR6003_REV2_VERSION:
1376 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1377 ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001378 ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
1379 ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001380 break;
1381 case AR6003_REV3_VERSION:
1382 ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
1383 ar->hw.app_load_addr = 0x1234;
Kalle Valo991b27e2011-09-07 10:55:17 +03001384 ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
1385 ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001386 break;
1387 case AR6004_REV1_VERSION:
1388 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1389 ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001390 ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
1391 ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001392 break;
1393 default:
1394 ath6kl_err("Unsupported hardware version: 0x%x\n",
1395 ar->version.target_ver);
1396 return -EINVAL;
1397 }
1398
1399 return 0;
1400}
1401
Kalle Valobdcd8172011-07-18 00:22:30 +03001402static int ath6kl_init(struct net_device *dev)
1403{
1404 struct ath6kl *ar = ath6kl_priv(dev);
1405 int status = 0;
1406 s32 timeleft;
1407
1408 if (!ar)
1409 return -EIO;
1410
1411 /* Do we need to finish the BMI phase */
1412 if (ath6kl_bmi_done(ar)) {
1413 status = -EIO;
1414 goto ath6kl_init_done;
1415 }
1416
1417 /* Indicate that WMI is enabled (although not ready yet) */
1418 set_bit(WMI_ENABLED, &ar->flag);
Vasanthakumar Thiagarajan28657852011-07-21 12:00:49 +05301419 ar->wmi = ath6kl_wmi_init(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001420 if (!ar->wmi) {
1421 ath6kl_err("failed to initialize wmi\n");
1422 status = -EIO;
1423 goto ath6kl_init_done;
1424 }
1425
1426 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1427
1428 /*
1429 * The reason we have to wait for the target here is that the
1430 * driver layer has to init BMI in order to set the host block
1431 * size.
1432 */
Kalle Vaload226ec2011-08-10 09:49:12 +03001433 if (ath6kl_htc_wait_target(ar->htc_target)) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001434 status = -EIO;
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301435 goto err_node_cleanup;
Kalle Valobdcd8172011-07-18 00:22:30 +03001436 }
1437
1438 if (ath6kl_init_service_ep(ar)) {
1439 status = -EIO;
1440 goto err_cleanup_scatter;
1441 }
1442
1443 /* setup access class priority mappings */
1444 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1445 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1446 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1447 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1448
1449 /* give our connected endpoints some buffers */
1450 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1451 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1452
1453 /* allocate some buffers that handle larger AMSDU frames */
1454 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1455
1456 /* setup credit distribution */
1457 ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
1458
1459 ath6kl_cookie_init(ar);
1460
1461 /* start HTC */
Kalle Vaload226ec2011-08-10 09:49:12 +03001462 status = ath6kl_htc_start(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001463
1464 if (status) {
1465 ath6kl_cookie_cleanup(ar);
1466 goto err_rxbuf_cleanup;
1467 }
1468
1469 /* Wait for Wmi event to be ready */
1470 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1471 test_bit(WMI_READY,
1472 &ar->flag),
1473 WMI_TIMEOUT);
1474
1475 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1476 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1477 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1478 status = -EIO;
1479 goto err_htc_stop;
1480 }
1481
1482 if (!timeleft || signal_pending(current)) {
1483 ath6kl_err("wmi is not ready or wait was interrupted\n");
1484 status = -EIO;
1485 goto err_htc_stop;
1486 }
1487
1488 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1489
1490 /* communicate the wmi protocol verision to the target */
1491 if ((ath6kl_set_host_app_area(ar)) != 0)
1492 ath6kl_err("unable to set the host app area\n");
1493
1494 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1495 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1496
Vivek Natarajan011a36e2011-09-19 13:29:16 +05301497 ar->wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
1498
Kalle Valobdcd8172011-07-18 00:22:30 +03001499 status = ath6kl_target_config_wlan_params(ar);
1500 if (!status)
1501 goto ath6kl_init_done;
1502
1503err_htc_stop:
Kalle Vaload226ec2011-08-10 09:49:12 +03001504 ath6kl_htc_stop(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001505err_rxbuf_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001506 ath6kl_htc_flush_rx_buf(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001507 ath6kl_cleanup_amsdu_rxbufs(ar);
1508err_cleanup_scatter:
1509 ath6kl_hif_cleanup_scatter(ar);
Vasanthakumar Thiagarajan852bd9d2011-07-21 14:24:54 +05301510err_node_cleanup:
Kalle Valobdcd8172011-07-18 00:22:30 +03001511 ath6kl_wmi_shutdown(ar->wmi);
1512 clear_bit(WMI_ENABLED, &ar->flag);
1513 ar->wmi = NULL;
1514
1515ath6kl_init_done:
1516 return status;
1517}
1518
1519int ath6kl_core_init(struct ath6kl *ar)
1520{
1521 int ret = 0;
1522 struct ath6kl_bmi_target_info targ_info;
1523
1524 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1525 if (!ar->ath6kl_wq)
1526 return -ENOMEM;
1527
1528 ret = ath6kl_bmi_init(ar);
1529 if (ret)
1530 goto err_wq;
1531
1532 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1533 if (ret)
1534 goto err_bmi_cleanup;
1535
1536 ar->version.target_ver = le32_to_cpu(targ_info.version);
1537 ar->target_type = le32_to_cpu(targ_info.type);
1538 ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
1539
Kalle Valoa01ac412011-09-07 10:55:17 +03001540 ret = ath6kl_init_hw_params(ar);
1541 if (ret)
1542 goto err_bmi_cleanup;
1543
Kalle Valobdcd8172011-07-18 00:22:30 +03001544 ret = ath6kl_configure_target(ar);
1545 if (ret)
1546 goto err_bmi_cleanup;
1547
Kalle Vaload226ec2011-08-10 09:49:12 +03001548 ar->htc_target = ath6kl_htc_create(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001549
1550 if (!ar->htc_target) {
1551 ret = -ENOMEM;
1552 goto err_bmi_cleanup;
1553 }
1554
1555 ar->aggr_cntxt = aggr_init(ar->net_dev);
1556 if (!ar->aggr_cntxt) {
1557 ath6kl_err("failed to initialize aggr\n");
1558 ret = -ENOMEM;
1559 goto err_htc_cleanup;
1560 }
1561
Kalle Valo772c31e2011-09-07 10:55:16 +03001562 ret = ath6kl_fetch_firmwares(ar);
1563 if (ret)
1564 goto err_htc_cleanup;
1565
Kalle Valobdcd8172011-07-18 00:22:30 +03001566 ret = ath6kl_init_upload(ar);
1567 if (ret)
1568 goto err_htc_cleanup;
1569
1570 ret = ath6kl_init(ar->net_dev);
1571 if (ret)
1572 goto err_htc_cleanup;
1573
1574 /* This runs the init function if registered */
1575 ret = register_netdev(ar->net_dev);
1576 if (ret) {
1577 ath6kl_err("register_netdev failed\n");
1578 ath6kl_destroy(ar->net_dev, 0);
1579 return ret;
1580 }
1581
1582 set_bit(NETDEV_REGISTERED, &ar->flag);
1583
1584 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1585 __func__, ar->net_dev->name, ar->net_dev, ar);
1586
1587 return ret;
1588
1589err_htc_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001590 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001591err_bmi_cleanup:
1592 ath6kl_bmi_cleanup(ar);
1593err_wq:
1594 destroy_workqueue(ar->ath6kl_wq);
1595 return ret;
1596}
1597
1598void ath6kl_stop_txrx(struct ath6kl *ar)
1599{
1600 struct net_device *ndev = ar->net_dev;
1601
1602 if (!ndev)
1603 return;
1604
1605 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1606
1607 if (down_interruptible(&ar->sem)) {
1608 ath6kl_err("down_interruptible failed\n");
1609 return;
1610 }
1611
1612 if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
1613 ath6kl_stop_endpoint(ndev, false, true);
1614
Raja Mani575b5f32011-07-19 19:27:33 +05301615 clear_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001616}
1617
1618/*
1619 * We need to differentiate between the surprise and planned removal of the
1620 * device because of the following consideration:
1621 *
1622 * - In case of surprise removal, the hcd already frees up the pending
1623 * for the device and hence there is no need to unregister the function
1624 * driver inorder to get these requests. For planned removal, the function
1625 * driver has to explicitly unregister itself to have the hcd return all the
1626 * pending requests before the data structures for the devices are freed up.
1627 * Note that as per the current implementation, the function driver will
1628 * end up releasing all the devices since there is no API to selectively
1629 * release a particular device.
1630 *
1631 * - Certain commands issued to the target can be skipped for surprise
1632 * removal since they will anyway not go through.
1633 */
1634void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
1635{
1636 struct ath6kl *ar;
1637
1638 if (!dev || !ath6kl_priv(dev)) {
1639 ath6kl_err("failed to get device structure\n");
1640 return;
1641 }
1642
1643 ar = ath6kl_priv(dev);
1644
1645 destroy_workqueue(ar->ath6kl_wq);
1646
1647 if (ar->htc_target)
Kalle Vaload226ec2011-08-10 09:49:12 +03001648 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001649
1650 aggr_module_destroy(ar->aggr_cntxt);
1651
1652 ath6kl_cookie_cleanup(ar);
1653
1654 ath6kl_cleanup_amsdu_rxbufs(ar);
1655
1656 ath6kl_bmi_cleanup(ar);
1657
Kalle Valobdf53962011-09-02 10:32:04 +03001658 ath6kl_debug_cleanup(ar);
1659
Kalle Valobdcd8172011-07-18 00:22:30 +03001660 if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
1661 unregister_netdev(dev);
1662 clear_bit(NETDEV_REGISTERED, &ar->flag);
1663 }
1664
1665 free_netdev(dev);
1666
Raja Mani19703572011-08-04 19:26:30 +05301667 kfree(ar->fw_board);
1668 kfree(ar->fw_otp);
1669 kfree(ar->fw);
1670 kfree(ar->fw_patch);
1671
Kalle Valobdcd8172011-07-18 00:22:30 +03001672 ath6kl_cfg80211_deinit(ar);
1673}