ath6kl: refactor firmware ext data addr and reserved ram handling size
[deliverable/linux.git] / drivers / net / wireless / ath / ath6kl / init.c
CommitLineData
bdcd8170
KV
1
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
92ecbff4 18#include <linux/of.h>
bdcd8170
KV
19#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;
003353b0 27static unsigned int testmode;
bdcd8170
KV
28
29module_param(debug_mask, uint, 0644);
003353b0 30module_param(testmode, uint, 0644);
bdcd8170
KV
31
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
bdcd8170
KV
59#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 +
1df94a85 67 sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
bdcd8170
KV
68 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;
38acde3c 85 ar->grp_crypto_len = 0;
bdcd8170
KV
86 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
bdcd8170
KV
108static 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));
31024d99 116 address = TARG_VTOP(ar->target_type, address);
bdcd8170 117
addb44be 118 if (ath6kl_diag_read32(ar, address, &data))
bdcd8170
KV
119 return -EIO;
120
31024d99 121 address = TARG_VTOP(ar->target_type, data);
bdcd8170 122 host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
addb44be
KV
123 if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
124 sizeof(struct host_app_area)))
bdcd8170
KV
125 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
ad226ec2 148 status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
bdcd8170
KV
149 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;
e5090444 278 ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD;
bdcd8170
KV
279
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));
31024d99 359 address = TARG_VTOP(ar->target_type, address);
bdcd8170
KV
360
361 /* read RAM location through diagnostic window */
addb44be 362 status = ath6kl_diag_read32(ar, address, &regdump_loc);
bdcd8170
KV
363
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);
31024d99 371 regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
bdcd8170
KV
372
373 /* fetch register dump data */
addb44be
KV
374 status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
375 REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
bdcd8170
KV
376
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;
4dea08e0 401 int ret;
bdcd8170
KV
402
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
6bbc7c35
JM
446 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 }
4dea08e0
JM
466 }
467
bdcd8170
KV
468 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);
6bbc7c35
JM
503 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 }
bdcd8170
KV
507 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
991b27ea
KV
530 param = ar->hw.board_ext_data_addr;
531 ram_reserved_size = ar->hw.reserved_ram_size;
bdcd8170 532
991b27ea
KV
533 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;
bdcd8170
KV
545 }
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
d999ba3e
VT
572 if (ath6kl_debug_init(ar)) {
573 ath6kl_err("Failed to initialize debugfs\n");
574 ath6kl_cfg80211_deinit(ar);
575 return NULL;
576 }
577
bdcd8170
KV
578 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;
575b5f34 594 set_bit(WLAN_ENABLED, &ar->flag);
bdcd8170
KV
595
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 */
bdcd8170
KV
621static 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
92ecbff4
SL
642#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
bdcd8170
KV
700static int ath6kl_fetch_board_file(struct ath6kl *ar)
701{
702 const char *filename;
703 int ret;
704
772c31ee
KV
705 if (ar->fw_board != NULL)
706 return 0;
707
bdcd8170
KV
708 switch (ar->version.target_ver) {
709 case AR6003_REV2_VERSION:
710 filename = AR6003_REV2_BOARD_DATA_FILE;
711 break;
31024d99
KF
712 case AR6004_REV1_VERSION:
713 filename = AR6004_REV1_BOARD_DATA_FILE;
714 break;
bdcd8170
KV
715 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
92ecbff4
SL
727 if (check_device_tree(ar)) {
728 /* got board file from device tree */
729 return 0;
730 }
731
bdcd8170
KV
732 /* 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;
31024d99
KF
740 case AR6004_REV1_VERSION:
741 filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
742 break;
bdcd8170
KV
743 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
772c31ee
KV
762static 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
50d41234 878static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
772c31ee
KV
879{
880 int ret;
881
772c31ee
KV
882 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}
bdcd8170 896
50d41234
KV
897static 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;
905
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;
990 default:
991 ath6kl_dbg(ATH6KL_DBG_TRC, "Unknown fw ie: %u\n",
992 le32_to_cpup(&hdr->id));
993 break;
994 }
995
996 len -= ie_len;
997 data += ie_len;
998 };
999
1000 ret = 0;
1001out:
1002 release_firmware(fw);
1003
1004 return ret;
1005}
1006
1007static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1008{
1009 int ret;
1010
1011 ret = ath6kl_fetch_board_file(ar);
1012 if (ret)
1013 return ret;
1014
1015 ret = ath6kl_fetch_fw_api2(ar);
1016 if (ret == 0)
1017 /* fw api 2 found, use it */
1018 return 0;
1019
1020 ret = ath6kl_fetch_fw_api1(ar);
1021 if (ret)
1022 return ret;
1023
1024 return 0;
1025}
1026
bdcd8170
KV
1027static int ath6kl_upload_board_file(struct ath6kl *ar)
1028{
1029 u32 board_address, board_ext_address, param;
31024d99 1030 u32 board_data_size, board_ext_data_size;
bdcd8170
KV
1031 int ret;
1032
772c31ee
KV
1033 if (WARN_ON(ar->fw_board == NULL))
1034 return -ENOENT;
bdcd8170 1035
31024d99
KF
1036 /*
1037 * Determine where in Target RAM to write Board Data.
1038 * For AR6004, host determine Target RAM address for
1039 * writing board data.
1040 */
1041 if (ar->target_type == TARGET_TYPE_AR6004) {
1042 board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
1043 ath6kl_bmi_write(ar,
1044 ath6kl_get_hi_item_addr(ar,
1045 HI_ITEM(hi_board_data)),
1046 (u8 *) &board_address, 4);
1047 } else {
1048 ath6kl_bmi_read(ar,
1049 ath6kl_get_hi_item_addr(ar,
1050 HI_ITEM(hi_board_data)),
1051 (u8 *) &board_address, 4);
1052 }
1053
bdcd8170
KV
1054 ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n",
1055 board_address);
1056
1057 /* determine where in target ram to write extended board data */
1058 ath6kl_bmi_read(ar,
1059 ath6kl_get_hi_item_addr(ar,
1060 HI_ITEM(hi_board_ext_data)),
1061 (u8 *) &board_ext_address, 4);
1062
1063 ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n",
1064 board_ext_address);
1065
1066 if (board_ext_address == 0) {
1067 ath6kl_err("Failed to get board file target address.\n");
1068 return -EINVAL;
1069 }
1070
31024d99
KF
1071 switch (ar->target_type) {
1072 case TARGET_TYPE_AR6003:
1073 board_data_size = AR6003_BOARD_DATA_SZ;
1074 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1075 break;
1076 case TARGET_TYPE_AR6004:
1077 board_data_size = AR6004_BOARD_DATA_SZ;
1078 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1079 break;
1080 default:
1081 WARN_ON(1);
1082 return -EINVAL;
1083 break;
1084 }
1085
1086 if (ar->fw_board_len == (board_data_size +
1087 board_ext_data_size)) {
1088
bdcd8170
KV
1089 /* write extended board data */
1090 ret = ath6kl_bmi_write(ar, board_ext_address,
31024d99
KF
1091 ar->fw_board + board_data_size,
1092 board_ext_data_size);
bdcd8170
KV
1093 if (ret) {
1094 ath6kl_err("Failed to write extended board data: %d\n",
1095 ret);
1096 return ret;
1097 }
1098
1099 /* record that extended board data is initialized */
31024d99
KF
1100 param = (board_ext_data_size << 16) | 1;
1101
bdcd8170
KV
1102 ath6kl_bmi_write(ar,
1103 ath6kl_get_hi_item_addr(ar,
1104 HI_ITEM(hi_board_ext_data_config)),
1105 (unsigned char *) &param, 4);
1106 }
1107
31024d99 1108 if (ar->fw_board_len < board_data_size) {
bdcd8170
KV
1109 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1110 ret = -EINVAL;
1111 return ret;
1112 }
1113
1114 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
31024d99 1115 board_data_size);
bdcd8170
KV
1116
1117 if (ret) {
1118 ath6kl_err("Board file bmi write failed: %d\n", ret);
1119 return ret;
1120 }
1121
1122 /* record the fact that Board Data IS initialized */
1123 param = 1;
1124 ath6kl_bmi_write(ar,
1125 ath6kl_get_hi_item_addr(ar,
1126 HI_ITEM(hi_board_data_initialized)),
1127 (u8 *)&param, 4);
1128
1129 return ret;
1130}
1131
1132static int ath6kl_upload_otp(struct ath6kl *ar)
1133{
bdcd8170
KV
1134 u32 address, param;
1135 int ret;
1136
772c31ee
KV
1137 if (WARN_ON(ar->fw_otp == NULL))
1138 return -ENOENT;
bdcd8170 1139
a01ac414 1140 address = ar->hw.app_load_addr;
bdcd8170
KV
1141
1142 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1143 ar->fw_otp_len);
1144 if (ret) {
1145 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1146 return ret;
1147 }
1148
1149 /* execute the OTP code */
1150 param = 0;
a01ac414 1151 address = ar->hw.app_start_override_addr;
bdcd8170
KV
1152 ath6kl_bmi_execute(ar, address, &param);
1153
1154 return ret;
1155}
1156
1157static int ath6kl_upload_firmware(struct ath6kl *ar)
1158{
bdcd8170
KV
1159 u32 address;
1160 int ret;
1161
772c31ee
KV
1162 if (WARN_ON(ar->fw == NULL))
1163 return -ENOENT;
bdcd8170 1164
a01ac414 1165 address = ar->hw.app_load_addr;
bdcd8170
KV
1166
1167 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1168
1169 if (ret) {
1170 ath6kl_err("Failed to write firmware: %d\n", ret);
1171 return ret;
1172 }
1173
31024d99
KF
1174 /*
1175 * Set starting address for firmware
1176 * Don't need to setup app_start override addr on AR6004
1177 */
1178 if (ar->target_type != TARGET_TYPE_AR6004) {
a01ac414 1179 address = ar->hw.app_start_override_addr;
31024d99
KF
1180 ath6kl_bmi_set_app_start(ar, address);
1181 }
bdcd8170
KV
1182 return ret;
1183}
1184
1185static int ath6kl_upload_patch(struct ath6kl *ar)
1186{
bdcd8170
KV
1187 u32 address, param;
1188 int ret;
1189
772c31ee
KV
1190 if (WARN_ON(ar->fw_patch == NULL))
1191 return -ENOENT;
bdcd8170 1192
a01ac414 1193 address = ar->hw.dataset_patch_addr;
bdcd8170
KV
1194
1195 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1196 if (ret) {
1197 ath6kl_err("Failed to write patch file: %d\n", ret);
1198 return ret;
1199 }
1200
1201 param = address;
1202 ath6kl_bmi_write(ar,
1203 ath6kl_get_hi_item_addr(ar,
1204 HI_ITEM(hi_dset_list_head)),
1205 (unsigned char *) &param, 4);
1206
1207 return 0;
1208}
1209
1210static int ath6kl_init_upload(struct ath6kl *ar)
1211{
1212 u32 param, options, sleep, address;
1213 int status = 0;
1214
31024d99
KF
1215 if (ar->target_type != TARGET_TYPE_AR6003 &&
1216 ar->target_type != TARGET_TYPE_AR6004)
bdcd8170
KV
1217 return -EINVAL;
1218
1219 /* temporarily disable system sleep */
1220 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1221 status = ath6kl_bmi_reg_read(ar, address, &param);
1222 if (status)
1223 return status;
1224
1225 options = param;
1226
1227 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1228 status = ath6kl_bmi_reg_write(ar, address, param);
1229 if (status)
1230 return status;
1231
1232 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1233 status = ath6kl_bmi_reg_read(ar, address, &param);
1234 if (status)
1235 return status;
1236
1237 sleep = param;
1238
1239 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1240 status = ath6kl_bmi_reg_write(ar, address, param);
1241 if (status)
1242 return status;
1243
1244 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1245 options, sleep);
1246
1247 /* program analog PLL register */
31024d99
KF
1248 /* no need to control 40/44MHz clock on AR6004 */
1249 if (ar->target_type != TARGET_TYPE_AR6004) {
1250 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1251 0xF9104001);
bdcd8170 1252
31024d99
KF
1253 if (status)
1254 return status;
bdcd8170 1255
31024d99
KF
1256 /* Run at 80/88MHz by default */
1257 param = SM(CPU_CLOCK_STANDARD, 1);
1258
1259 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1260 status = ath6kl_bmi_reg_write(ar, address, param);
1261 if (status)
1262 return status;
1263 }
bdcd8170
KV
1264
1265 param = 0;
1266 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1267 param = SM(LPO_CAL_ENABLE, 1);
1268 status = ath6kl_bmi_reg_write(ar, address, param);
1269 if (status)
1270 return status;
1271
1272 /* WAR to avoid SDIO CRC err */
1273 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1274 ath6kl_err("temporary war to avoid sdio crc error\n");
1275
1276 param = 0x20;
1277
1278 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1279 status = ath6kl_bmi_reg_write(ar, address, param);
1280 if (status)
1281 return status;
1282
1283 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1284 status = ath6kl_bmi_reg_write(ar, address, param);
1285 if (status)
1286 return status;
1287
1288 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1289 status = ath6kl_bmi_reg_write(ar, address, param);
1290 if (status)
1291 return status;
1292
1293 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1294 status = ath6kl_bmi_reg_write(ar, address, param);
1295 if (status)
1296 return status;
1297 }
1298
1299 /* write EEPROM data to Target RAM */
1300 status = ath6kl_upload_board_file(ar);
1301 if (status)
1302 return status;
1303
1304 /* transfer One time Programmable data */
1305 status = ath6kl_upload_otp(ar);
1306 if (status)
1307 return status;
1308
1309 /* Download Target firmware */
1310 status = ath6kl_upload_firmware(ar);
1311 if (status)
1312 return status;
1313
1314 status = ath6kl_upload_patch(ar);
1315 if (status)
1316 return status;
1317
1318 /* Restore system sleep */
1319 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1320 status = ath6kl_bmi_reg_write(ar, address, sleep);
1321 if (status)
1322 return status;
1323
1324 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1325 param = options | 0x20;
1326 status = ath6kl_bmi_reg_write(ar, address, param);
1327 if (status)
1328 return status;
1329
1330 /* Configure GPIO AR6003 UART */
1331 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1332 status = ath6kl_bmi_write(ar,
1333 ath6kl_get_hi_item_addr(ar,
1334 HI_ITEM(hi_dbg_uart_txpin)),
1335 (u8 *)&param, 4);
1336
1337 return status;
1338}
1339
a01ac414
KV
1340static int ath6kl_init_hw_params(struct ath6kl *ar)
1341{
1342 switch (ar->version.target_ver) {
1343 case AR6003_REV2_VERSION:
1344 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1345 ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
1346 ar->hw.app_start_override_addr = AR6003_REV2_APP_START_OVERRIDE;
991b27ea
KV
1347 ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
1348 ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
a01ac414
KV
1349 break;
1350 case AR6003_REV3_VERSION:
1351 ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
1352 ar->hw.app_load_addr = 0x1234;
1353 ar->hw.app_start_override_addr = AR6003_REV3_APP_START_OVERRIDE;
991b27ea
KV
1354 ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
1355 ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
a01ac414
KV
1356 break;
1357 case AR6004_REV1_VERSION:
1358 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1359 ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
1360 ar->hw.app_start_override_addr = AR6003_REV3_APP_START_OVERRIDE;
991b27ea
KV
1361 ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
1362 ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
a01ac414
KV
1363 break;
1364 default:
1365 ath6kl_err("Unsupported hardware version: 0x%x\n",
1366 ar->version.target_ver);
1367 return -EINVAL;
1368 }
1369
1370 return 0;
1371}
1372
bdcd8170
KV
1373static int ath6kl_init(struct net_device *dev)
1374{
1375 struct ath6kl *ar = ath6kl_priv(dev);
1376 int status = 0;
1377 s32 timeleft;
1378
1379 if (!ar)
1380 return -EIO;
1381
1382 /* Do we need to finish the BMI phase */
1383 if (ath6kl_bmi_done(ar)) {
1384 status = -EIO;
1385 goto ath6kl_init_done;
1386 }
1387
1388 /* Indicate that WMI is enabled (although not ready yet) */
1389 set_bit(WMI_ENABLED, &ar->flag);
2865785e 1390 ar->wmi = ath6kl_wmi_init(ar);
bdcd8170
KV
1391 if (!ar->wmi) {
1392 ath6kl_err("failed to initialize wmi\n");
1393 status = -EIO;
1394 goto ath6kl_init_done;
1395 }
1396
1397 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1398
852bd9d9
VT
1399 wlan_node_table_init(&ar->scan_table);
1400
bdcd8170
KV
1401 /*
1402 * The reason we have to wait for the target here is that the
1403 * driver layer has to init BMI in order to set the host block
1404 * size.
1405 */
ad226ec2 1406 if (ath6kl_htc_wait_target(ar->htc_target)) {
bdcd8170 1407 status = -EIO;
852bd9d9 1408 goto err_node_cleanup;
bdcd8170
KV
1409 }
1410
1411 if (ath6kl_init_service_ep(ar)) {
1412 status = -EIO;
1413 goto err_cleanup_scatter;
1414 }
1415
1416 /* setup access class priority mappings */
1417 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1418 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1419 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1420 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1421
1422 /* give our connected endpoints some buffers */
1423 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1424 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1425
1426 /* allocate some buffers that handle larger AMSDU frames */
1427 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1428
1429 /* setup credit distribution */
1430 ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
1431
1432 ath6kl_cookie_init(ar);
1433
1434 /* start HTC */
ad226ec2 1435 status = ath6kl_htc_start(ar->htc_target);
bdcd8170
KV
1436
1437 if (status) {
1438 ath6kl_cookie_cleanup(ar);
1439 goto err_rxbuf_cleanup;
1440 }
1441
1442 /* Wait for Wmi event to be ready */
1443 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1444 test_bit(WMI_READY,
1445 &ar->flag),
1446 WMI_TIMEOUT);
1447
1448 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1449 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1450 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1451 status = -EIO;
1452 goto err_htc_stop;
1453 }
1454
1455 if (!timeleft || signal_pending(current)) {
1456 ath6kl_err("wmi is not ready or wait was interrupted\n");
1457 status = -EIO;
1458 goto err_htc_stop;
1459 }
1460
1461 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1462
1463 /* communicate the wmi protocol verision to the target */
1464 if ((ath6kl_set_host_app_area(ar)) != 0)
1465 ath6kl_err("unable to set the host app area\n");
1466
1467 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1468 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1469
1470 status = ath6kl_target_config_wlan_params(ar);
1471 if (!status)
1472 goto ath6kl_init_done;
1473
1474err_htc_stop:
ad226ec2 1475 ath6kl_htc_stop(ar->htc_target);
bdcd8170 1476err_rxbuf_cleanup:
ad226ec2 1477 ath6kl_htc_flush_rx_buf(ar->htc_target);
bdcd8170
KV
1478 ath6kl_cleanup_amsdu_rxbufs(ar);
1479err_cleanup_scatter:
1480 ath6kl_hif_cleanup_scatter(ar);
852bd9d9
VT
1481err_node_cleanup:
1482 wlan_node_table_cleanup(&ar->scan_table);
bdcd8170
KV
1483 ath6kl_wmi_shutdown(ar->wmi);
1484 clear_bit(WMI_ENABLED, &ar->flag);
1485 ar->wmi = NULL;
1486
1487ath6kl_init_done:
1488 return status;
1489}
1490
1491int ath6kl_core_init(struct ath6kl *ar)
1492{
1493 int ret = 0;
1494 struct ath6kl_bmi_target_info targ_info;
1495
1496 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1497 if (!ar->ath6kl_wq)
1498 return -ENOMEM;
1499
1500 ret = ath6kl_bmi_init(ar);
1501 if (ret)
1502 goto err_wq;
1503
1504 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1505 if (ret)
1506 goto err_bmi_cleanup;
1507
1508 ar->version.target_ver = le32_to_cpu(targ_info.version);
1509 ar->target_type = le32_to_cpu(targ_info.type);
1510 ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
1511
a01ac414
KV
1512 ret = ath6kl_init_hw_params(ar);
1513 if (ret)
1514 goto err_bmi_cleanup;
1515
bdcd8170
KV
1516 ret = ath6kl_configure_target(ar);
1517 if (ret)
1518 goto err_bmi_cleanup;
1519
ad226ec2 1520 ar->htc_target = ath6kl_htc_create(ar);
bdcd8170
KV
1521
1522 if (!ar->htc_target) {
1523 ret = -ENOMEM;
1524 goto err_bmi_cleanup;
1525 }
1526
1527 ar->aggr_cntxt = aggr_init(ar->net_dev);
1528 if (!ar->aggr_cntxt) {
1529 ath6kl_err("failed to initialize aggr\n");
1530 ret = -ENOMEM;
1531 goto err_htc_cleanup;
1532 }
1533
772c31ee
KV
1534 ret = ath6kl_fetch_firmwares(ar);
1535 if (ret)
1536 goto err_htc_cleanup;
1537
bdcd8170
KV
1538 ret = ath6kl_init_upload(ar);
1539 if (ret)
1540 goto err_htc_cleanup;
1541
1542 ret = ath6kl_init(ar->net_dev);
1543 if (ret)
1544 goto err_htc_cleanup;
1545
1546 /* This runs the init function if registered */
1547 ret = register_netdev(ar->net_dev);
1548 if (ret) {
1549 ath6kl_err("register_netdev failed\n");
1550 ath6kl_destroy(ar->net_dev, 0);
1551 return ret;
1552 }
1553
1554 set_bit(NETDEV_REGISTERED, &ar->flag);
1555
1556 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1557 __func__, ar->net_dev->name, ar->net_dev, ar);
1558
1559 return ret;
1560
1561err_htc_cleanup:
ad226ec2 1562 ath6kl_htc_cleanup(ar->htc_target);
bdcd8170
KV
1563err_bmi_cleanup:
1564 ath6kl_bmi_cleanup(ar);
1565err_wq:
1566 destroy_workqueue(ar->ath6kl_wq);
1567 return ret;
1568}
1569
1570void ath6kl_stop_txrx(struct ath6kl *ar)
1571{
1572 struct net_device *ndev = ar->net_dev;
1573
1574 if (!ndev)
1575 return;
1576
1577 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1578
1579 if (down_interruptible(&ar->sem)) {
1580 ath6kl_err("down_interruptible failed\n");
1581 return;
1582 }
1583
1584 if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
1585 ath6kl_stop_endpoint(ndev, false, true);
1586
575b5f34 1587 clear_bit(WLAN_ENABLED, &ar->flag);
bdcd8170
KV
1588}
1589
1590/*
1591 * We need to differentiate between the surprise and planned removal of the
1592 * device because of the following consideration:
1593 *
1594 * - In case of surprise removal, the hcd already frees up the pending
1595 * for the device and hence there is no need to unregister the function
1596 * driver inorder to get these requests. For planned removal, the function
1597 * driver has to explicitly unregister itself to have the hcd return all the
1598 * pending requests before the data structures for the devices are freed up.
1599 * Note that as per the current implementation, the function driver will
1600 * end up releasing all the devices since there is no API to selectively
1601 * release a particular device.
1602 *
1603 * - Certain commands issued to the target can be skipped for surprise
1604 * removal since they will anyway not go through.
1605 */
1606void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
1607{
1608 struct ath6kl *ar;
1609
1610 if (!dev || !ath6kl_priv(dev)) {
1611 ath6kl_err("failed to get device structure\n");
1612 return;
1613 }
1614
1615 ar = ath6kl_priv(dev);
1616
1617 destroy_workqueue(ar->ath6kl_wq);
1618
1619 if (ar->htc_target)
ad226ec2 1620 ath6kl_htc_cleanup(ar->htc_target);
bdcd8170
KV
1621
1622 aggr_module_destroy(ar->aggr_cntxt);
1623
1624 ath6kl_cookie_cleanup(ar);
1625
1626 ath6kl_cleanup_amsdu_rxbufs(ar);
1627
1628 ath6kl_bmi_cleanup(ar);
1629
bdf5396b
KV
1630 ath6kl_debug_cleanup(ar);
1631
bdcd8170
KV
1632 if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
1633 unregister_netdev(dev);
1634 clear_bit(NETDEV_REGISTERED, &ar->flag);
1635 }
1636
1637 free_netdev(dev);
1638
852bd9d9
VT
1639 wlan_node_table_cleanup(&ar->scan_table);
1640
19703573
RM
1641 kfree(ar->fw_board);
1642 kfree(ar->fw_otp);
1643 kfree(ar->fw);
1644 kfree(ar->fw_patch);
1645
bdcd8170
KV
1646 ath6kl_cfg80211_deinit(ar);
1647}
This page took 0.109944 seconds and 5 git commands to generate.