blob: acfe79a0f1a133b49d2d5610aca2ff692045631f [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
Stephen Rothwellc6efe5782011-09-28 18:32:34 +100018#include <linux/moduleparam.h>
Sangwook Leef7830202011-10-26 16:28:38 +010019#include <linux/errno.h>
Sam Leffler92ecbff2011-09-07 10:55:16 +030020#include <linux/of.h>
Kalle Valobdcd8172011-07-18 00:22:30 +030021#include <linux/mmc/sdio_func.h>
22#include "core.h"
23#include "cfg80211.h"
24#include "target.h"
25#include "debug.h"
26#include "hif-ops.h"
27
28unsigned int debug_mask;
Kalle Valo003353b0d2011-09-01 10:14:21 +030029static unsigned int testmode;
Kalle Valo8277de12011-11-03 12:18:31 +020030static bool suspend_cutpower;
Kalle Valobdcd8172011-07-18 00:22:30 +030031
32module_param(debug_mask, uint, 0644);
Kalle Valo003353b0d2011-09-01 10:14:21 +030033module_param(testmode, uint, 0644);
Kalle Valo8277de12011-11-03 12:18:31 +020034module_param(suspend_cutpower, bool, 0444);
Kalle Valobdcd8172011-07-18 00:22:30 +030035
Kalle Valo856f4b312011-11-14 19:30:29 +020036static const struct ath6kl_hw hw_list[] = {
37 {
38 .id = AR6003_REV2_VERSION,
Kalle Valo293badf2011-11-14 19:30:54 +020039 .name = "ar6003 hw 2.0",
Kalle Valo856f4b312011-11-14 19:30:29 +020040 .dataset_patch_addr = 0x57e884,
41 .app_load_addr = 0x543180,
42 .board_ext_data_addr = 0x57e500,
43 .reserved_ram_size = 6912,
44
45 /* hw2.0 needs override address hardcoded */
46 .app_start_override_addr = 0x944C00,
47 },
48 {
49 .id = AR6003_REV3_VERSION,
Kalle Valo293badf2011-11-14 19:30:54 +020050 .name = "ar6003 hw 2.1.1",
Kalle Valo856f4b312011-11-14 19:30:29 +020051 .dataset_patch_addr = 0x57ff74,
52 .app_load_addr = 0x1234,
53 .board_ext_data_addr = 0x542330,
54 .reserved_ram_size = 512,
55 },
56 {
57 .id = AR6004_REV1_VERSION,
Kalle Valo293badf2011-11-14 19:30:54 +020058 .name = "ar6004 hw 1.0",
Kalle Valo856f4b312011-11-14 19:30:29 +020059 .dataset_patch_addr = 0x57e884,
60 .app_load_addr = 0x1234,
61 .board_ext_data_addr = 0x437000,
62 .reserved_ram_size = 19456,
Kalle Valo0d4d72b2011-11-14 19:30:39 +020063 .board_addr = 0x433900,
Kalle Valo856f4b312011-11-14 19:30:29 +020064 },
65 {
66 .id = AR6004_REV2_VERSION,
Kalle Valo293badf2011-11-14 19:30:54 +020067 .name = "ar6004 hw 1.1",
Kalle Valo856f4b312011-11-14 19:30:29 +020068 .dataset_patch_addr = 0x57e884,
69 .app_load_addr = 0x1234,
70 .board_ext_data_addr = 0x437000,
71 .reserved_ram_size = 11264,
Kalle Valo0d4d72b2011-11-14 19:30:39 +020072 .board_addr = 0x43d400,
Kalle Valo856f4b312011-11-14 19:30:29 +020073 },
74};
75
Kalle Valobdcd8172011-07-18 00:22:30 +030076/*
77 * Include definitions here that can be used to tune the WLAN module
78 * behavior. Different customers can tune the behavior as per their needs,
79 * here.
80 */
81
82/*
83 * This configuration item enable/disable keepalive support.
84 * Keepalive support: In the absence of any data traffic to AP, null
85 * frames will be sent to the AP at periodic interval, to keep the association
86 * active. This configuration item defines the periodic interval.
87 * Use value of zero to disable keepalive support
88 * Default: 60 seconds
89 */
90#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
91
92/*
93 * This configuration item sets the value of disconnect timeout
94 * Firmware delays sending the disconnec event to the host for this
95 * timeout after is gets disconnected from the current AP.
96 * If the firmware successly roams within the disconnect timeout
97 * it sends a new connect event
98 */
99#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
100
101#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
102
Kalle Valobdcd8172011-07-18 00:22:30 +0300103#define ATH6KL_DATA_OFFSET 64
104struct sk_buff *ath6kl_buf_alloc(int size)
105{
106 struct sk_buff *skb;
107 u16 reserved;
108
109 /* Add chacheline space at front and back of buffer */
110 reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
Vasanthakumar Thiagarajan1df94a82011-08-17 18:45:10 +0530111 sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
Kalle Valobdcd8172011-07-18 00:22:30 +0300112 skb = dev_alloc_skb(size + reserved);
113
114 if (skb)
115 skb_reserve(skb, reserved - L1_CACHE_BYTES);
116 return skb;
117}
118
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +0530119void ath6kl_init_profile_info(struct ath6kl_vif *vif)
Kalle Valobdcd8172011-07-18 00:22:30 +0300120{
Vasanthakumar Thiagarajan34503342011-10-25 19:34:02 +0530121 vif->ssid_len = 0;
122 memset(vif->ssid, 0, sizeof(vif->ssid));
123
124 vif->dot11_auth_mode = OPEN_AUTH;
125 vif->auth_mode = NONE_AUTH;
126 vif->prwise_crypto = NONE_CRYPT;
127 vif->prwise_crypto_len = 0;
128 vif->grp_crypto = NONE_CRYPT;
129 vif->grp_crypto_len = 0;
Vasanthakumar Thiagarajan6f2a73f2011-10-25 19:34:06 +0530130 memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
Vasanthakumar Thiagarajan8c8b65e2011-10-25 19:34:04 +0530131 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
132 memset(vif->bssid, 0, sizeof(vif->bssid));
Vasanthakumar Thiagarajanf74bac52011-10-25 19:34:05 +0530133 vif->bss_ch = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +0300134}
135
Kalle Valobdcd8172011-07-18 00:22:30 +0300136static int ath6kl_set_host_app_area(struct ath6kl *ar)
137{
138 u32 address, data;
139 struct host_app_area host_app_area;
140
141 /* Fetch the address of the host_app_area_s
142 * instance in the host interest area */
143 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
Kevin Fang31024d92011-07-11 17:14:13 +0800144 address = TARG_VTOP(ar->target_type, address);
Kalle Valobdcd8172011-07-18 00:22:30 +0300145
Kalle Valoaddb44b2011-09-02 10:32:05 +0300146 if (ath6kl_diag_read32(ar, address, &data))
Kalle Valobdcd8172011-07-18 00:22:30 +0300147 return -EIO;
148
Kevin Fang31024d92011-07-11 17:14:13 +0800149 address = TARG_VTOP(ar->target_type, data);
Kalle Valocbf49a62011-10-05 12:23:17 +0300150 host_app_area.wmi_protocol_ver = cpu_to_le32(WMI_PROTOCOL_VERSION);
Kalle Valoaddb44b2011-09-02 10:32:05 +0300151 if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
152 sizeof(struct host_app_area)))
Kalle Valobdcd8172011-07-18 00:22:30 +0300153 return -EIO;
154
155 return 0;
156}
157
158static inline void set_ac2_ep_map(struct ath6kl *ar,
159 u8 ac,
160 enum htc_endpoint_id ep)
161{
162 ar->ac2ep_map[ac] = ep;
163 ar->ep2ac_map[ep] = ac;
164}
165
166/* connect to a service */
167static int ath6kl_connectservice(struct ath6kl *ar,
168 struct htc_service_connect_req *con_req,
169 char *desc)
170{
171 int status;
172 struct htc_service_connect_resp response;
173
174 memset(&response, 0, sizeof(response));
175
Kalle Vaload226ec2011-08-10 09:49:12 +0300176 status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
Kalle Valobdcd8172011-07-18 00:22:30 +0300177 if (status) {
178 ath6kl_err("failed to connect to %s service status:%d\n",
179 desc, status);
180 return status;
181 }
182
183 switch (con_req->svc_id) {
184 case WMI_CONTROL_SVC:
185 if (test_bit(WMI_ENABLED, &ar->flag))
186 ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
187 ar->ctrl_ep = response.endpoint;
188 break;
189 case WMI_DATA_BE_SVC:
190 set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
191 break;
192 case WMI_DATA_BK_SVC:
193 set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
194 break;
195 case WMI_DATA_VI_SVC:
196 set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
197 break;
198 case WMI_DATA_VO_SVC:
199 set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
200 break;
201 default:
202 ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
203 return -EINVAL;
204 }
205
206 return 0;
207}
208
209static int ath6kl_init_service_ep(struct ath6kl *ar)
210{
211 struct htc_service_connect_req connect;
212
213 memset(&connect, 0, sizeof(connect));
214
215 /* these fields are the same for all service endpoints */
216 connect.ep_cb.rx = ath6kl_rx;
217 connect.ep_cb.rx_refill = ath6kl_rx_refill;
218 connect.ep_cb.tx_full = ath6kl_tx_queue_full;
219
220 /*
221 * Set the max queue depth so that our ath6kl_tx_queue_full handler
222 * gets called.
223 */
224 connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
225 connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
226 if (!connect.ep_cb.rx_refill_thresh)
227 connect.ep_cb.rx_refill_thresh++;
228
229 /* connect to control service */
230 connect.svc_id = WMI_CONTROL_SVC;
231 if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
232 return -EIO;
233
234 connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
235
236 /*
237 * Limit the HTC message size on the send path, although e can
238 * receive A-MSDU frames of 4K, we will only send ethernet-sized
239 * (802.3) frames on the send path.
240 */
241 connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
242
243 /*
244 * To reduce the amount of committed memory for larger A_MSDU
245 * frames, use the recv-alloc threshold mechanism for larger
246 * packets.
247 */
248 connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
249 connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
250
251 /*
252 * For the remaining data services set the connection flag to
253 * reduce dribbling, if configured to do so.
254 */
255 connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
256 connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
257 connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
258
259 connect.svc_id = WMI_DATA_BE_SVC;
260
261 if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
262 return -EIO;
263
264 /* connect to back-ground map this to WMI LOW_PRI */
265 connect.svc_id = WMI_DATA_BK_SVC;
266 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
267 return -EIO;
268
269 /* connect to Video service, map this to to HI PRI */
270 connect.svc_id = WMI_DATA_VI_SVC;
271 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
272 return -EIO;
273
274 /*
275 * Connect to VO service, this is currently not mapped to a WMI
276 * priority stream due to historical reasons. WMI originally
277 * defined 3 priorities over 3 mailboxes We can change this when
278 * WMI is reworked so that priorities are not dependent on
279 * mailboxes.
280 */
281 connect.svc_id = WMI_DATA_VO_SVC;
282 if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
283 return -EIO;
284
285 return 0;
286}
287
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +0530288void ath6kl_init_control_info(struct ath6kl_vif *vif)
Kalle Valobdcd8172011-07-18 00:22:30 +0300289{
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +0530290 ath6kl_init_profile_info(vif);
Vasanthakumar Thiagarajan34503342011-10-25 19:34:02 +0530291 vif->def_txkey_index = 0;
Vasanthakumar Thiagarajan6f2a73f2011-10-25 19:34:06 +0530292 memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
Vasanthakumar Thiagarajanf74bac52011-10-25 19:34:05 +0530293 vif->ch_hint = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +0300294}
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
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530343static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
Kalle Valobdcd8172011-07-18 00:22:30 +0300344{
345 int status = 0;
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300346 int ret;
Kalle Valobdcd8172011-07-18 00:22:30 +0300347
348 /*
349 * Configure the device for rx dot11 header rules. "0,0" are the
350 * default values. Required if checksum offload is needed. Set
351 * RxMetaVersion to 2.
352 */
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530353 if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300354 ar->rx_meta_ver, 0, 0)) {
355 ath6kl_err("unable to set the rx frame format\n");
356 status = -EIO;
357 }
358
359 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530360 if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
Kalle Valobdcd8172011-07-18 00:22:30 +0300361 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
362 ath6kl_err("unable to set power save fail event policy\n");
363 status = -EIO;
364 }
365
366 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530367 if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
Kalle Valobdcd8172011-07-18 00:22:30 +0300368 WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
369 ath6kl_err("unable to set barker preamble policy\n");
370 status = -EIO;
371 }
372
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530373 if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300374 WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
375 ath6kl_err("unable to set keep alive interval\n");
376 status = -EIO;
377 }
378
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530379 if (ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300380 WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
381 ath6kl_err("unable to set disconnect timeout\n");
382 status = -EIO;
383 }
384
385 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530386 if (ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED)) {
Kalle Valobdcd8172011-07-18 00:22:30 +0300387 ath6kl_err("unable to set txop bursting\n");
388 status = -EIO;
389 }
390
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530391 /*
392 * FIXME: Make sure p2p configurations are not applied to
393 * non-p2p capable interfaces when multivif support is enabled.
394 */
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300395 if (ar->p2p) {
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530396 ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300397 P2P_FLAG_CAPABILITIES_REQ |
398 P2P_FLAG_MACADDR_REQ |
399 P2P_FLAG_HMODEL_REQ);
400 if (ret) {
401 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P "
402 "capabilities (%d) - assuming P2P not "
403 "supported\n", ret);
404 ar->p2p = 0;
405 }
406 }
407
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530408 /*
409 * FIXME: Make sure p2p configurations are not applied to
410 * non-p2p capable interfaces when multivif support is enabled.
411 */
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300412 if (ar->p2p) {
413 /* Enable Probe Request reporting for P2P */
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530414 ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300415 if (ret) {
416 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
417 "Request reporting (%d)\n", ret);
418 }
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300419 }
420
Kalle Valobdcd8172011-07-18 00:22:30 +0300421 return status;
422}
423
424int ath6kl_configure_target(struct ath6kl *ar)
425{
426 u32 param, ram_reserved_size;
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530427 u8 fw_iftype, fw_mode = 0, fw_submode = 0;
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530428 int i;
Kalle Valobdcd8172011-07-18 00:22:30 +0300429
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530430 /*
431 * Note: Even though the firmware interface type is
432 * chosen as BSS_STA for all three interfaces, can
433 * be configured to IBSS/AP as long as the fw submode
434 * remains normal mode (0 - AP, STA and IBSS). But
435 * due to an target assert in firmware only one interface is
436 * configured for now.
437 */
Vasanthakumar Thiagarajandd3751f2011-10-25 19:33:59 +0530438 fw_iftype = HI_OPTION_FW_MODE_BSS_STA;
Kalle Valobdcd8172011-07-18 00:22:30 +0300439
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530440 for (i = 0; i < MAX_NUM_VIF; i++)
441 fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
442
443 /*
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530444 * By default, submodes :
445 * vif[0] - AP/STA/IBSS
446 * vif[1] - "P2P dev"/"P2P GO"/"P2P Client"
447 * vif[2] - "P2P dev"/"P2P GO"/"P2P Client"
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530448 */
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530449
450 for (i = 0; i < ar->max_norm_iface; i++)
451 fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
452 (i * HI_OPTION_FW_SUBMODE_BITS);
453
454 for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++)
455 fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
456 (i * HI_OPTION_FW_SUBMODE_BITS);
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530457
458 /*
459 * FIXME: This needs to be removed once the multivif
460 * support is enabled.
461 */
462 if (ar->p2p)
463 fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530464
Kalle Valobdcd8172011-07-18 00:22:30 +0300465 param = HTC_PROTOCOL_VERSION;
466 if (ath6kl_bmi_write(ar,
467 ath6kl_get_hi_item_addr(ar,
468 HI_ITEM(hi_app_host_interest)),
469 (u8 *)&param, 4) != 0) {
470 ath6kl_err("bmi_write_memory for htc version failed\n");
471 return -EIO;
472 }
473
474 /* set the firmware mode to STA/IBSS/AP */
475 param = 0;
476
477 if (ath6kl_bmi_read(ar,
478 ath6kl_get_hi_item_addr(ar,
479 HI_ITEM(hi_option_flag)),
480 (u8 *)&param, 4) != 0) {
481 ath6kl_err("bmi_read_memory for setting fwmode failed\n");
482 return -EIO;
483 }
484
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530485 param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT);
486 param |= fw_mode << HI_OPTION_FW_MODE_SHIFT;
487 param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT;
488
Kalle Valobdcd8172011-07-18 00:22:30 +0300489 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
490 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
491
492 if (ath6kl_bmi_write(ar,
493 ath6kl_get_hi_item_addr(ar,
494 HI_ITEM(hi_option_flag)),
495 (u8 *)&param,
496 4) != 0) {
497 ath6kl_err("bmi_write_memory for setting fwmode failed\n");
498 return -EIO;
499 }
500
501 ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
502
503 /*
504 * Hardcode the address use for the extended board data
505 * Ideally this should be pre-allocate by the OS at boot time
506 * But since it is a new feature and board data is loaded
507 * at init time, we have to workaround this from host.
508 * It is difficult to patch the firmware boot code,
509 * but possible in theory.
510 */
511
Kalle Valo991b27e2011-09-07 10:55:17 +0300512 param = ar->hw.board_ext_data_addr;
513 ram_reserved_size = ar->hw.reserved_ram_size;
Kalle Valobdcd8172011-07-18 00:22:30 +0300514
Kalle Valo991b27e2011-09-07 10:55:17 +0300515 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
516 HI_ITEM(hi_board_ext_data)),
517 (u8 *)&param, 4) != 0) {
518 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
519 return -EIO;
520 }
521
522 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
523 HI_ITEM(hi_end_ram_reserve_sz)),
524 (u8 *)&ram_reserved_size, 4) != 0) {
525 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
526 return -EIO;
Kalle Valobdcd8172011-07-18 00:22:30 +0300527 }
528
529 /* set the block size for the target */
530 if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
531 /* use default number of control buffers */
532 return -EIO;
533
534 return 0;
535}
536
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +0530537void ath6kl_core_free(struct ath6kl *ar)
Kalle Valobdcd8172011-07-18 00:22:30 +0300538{
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +0530539 wiphy_free(ar->wiphy);
Kalle Valobdcd8172011-07-18 00:22:30 +0300540}
541
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530542void ath6kl_core_cleanup(struct ath6kl *ar)
Kalle Valobdcd8172011-07-18 00:22:30 +0300543{
Kalle Valob2e75692011-10-27 18:48:14 +0300544 ath6kl_hif_power_off(ar);
545
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530546 destroy_workqueue(ar->ath6kl_wq);
Kalle Valobdcd8172011-07-18 00:22:30 +0300547
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530548 if (ar->htc_target)
549 ath6kl_htc_cleanup(ar->htc_target);
550
551 ath6kl_cookie_cleanup(ar);
552
553 ath6kl_cleanup_amsdu_rxbufs(ar);
554
555 ath6kl_bmi_cleanup(ar);
556
557 ath6kl_debug_cleanup(ar);
558
559 kfree(ar->fw_board);
560 kfree(ar->fw_otp);
561 kfree(ar->fw);
562 kfree(ar->fw_patch);
563
564 ath6kl_deinit_ieee80211_hw(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +0300565}
566
567/* firmware upload */
Kalle Valobdcd8172011-07-18 00:22:30 +0300568static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
569 u8 **fw, size_t *fw_len)
570{
571 const struct firmware *fw_entry;
572 int ret;
573
574 ret = request_firmware(&fw_entry, filename, ar->dev);
575 if (ret)
576 return ret;
577
578 *fw_len = fw_entry->size;
579 *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
580
581 if (*fw == NULL)
582 ret = -ENOMEM;
583
584 release_firmware(fw_entry);
585
586 return ret;
587}
588
Sam Leffler92ecbff2011-09-07 10:55:16 +0300589#ifdef CONFIG_OF
590static const char *get_target_ver_dir(const struct ath6kl *ar)
591{
592 switch (ar->version.target_ver) {
593 case AR6003_REV1_VERSION:
594 return "ath6k/AR6003/hw1.0";
595 case AR6003_REV2_VERSION:
596 return "ath6k/AR6003/hw2.0";
597 case AR6003_REV3_VERSION:
598 return "ath6k/AR6003/hw2.1.1";
599 }
600 ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
601 ar->version.target_ver);
602 return NULL;
603}
604
605/*
606 * Check the device tree for a board-id and use it to construct
607 * the pathname to the firmware file. Used (for now) to find a
608 * fallback to the "bdata.bin" file--typically a symlink to the
609 * appropriate board-specific file.
610 */
611static bool check_device_tree(struct ath6kl *ar)
612{
613 static const char *board_id_prop = "atheros,board-id";
614 struct device_node *node;
615 char board_filename[64];
616 const char *board_id;
617 int ret;
618
619 for_each_compatible_node(node, NULL, "atheros,ath6kl") {
620 board_id = of_get_property(node, board_id_prop, NULL);
621 if (board_id == NULL) {
622 ath6kl_warn("No \"%s\" property on %s node.\n",
623 board_id_prop, node->name);
624 continue;
625 }
626 snprintf(board_filename, sizeof(board_filename),
627 "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id);
628
629 ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
630 &ar->fw_board_len);
631 if (ret) {
632 ath6kl_err("Failed to get DT board file %s: %d\n",
633 board_filename, ret);
634 continue;
635 }
636 return true;
637 }
638 return false;
639}
640#else
641static bool check_device_tree(struct ath6kl *ar)
642{
643 return false;
644}
645#endif /* CONFIG_OF */
646
Kalle Valobdcd8172011-07-18 00:22:30 +0300647static int ath6kl_fetch_board_file(struct ath6kl *ar)
648{
649 const char *filename;
650 int ret;
651
Kalle Valo772c31e2011-09-07 10:55:16 +0300652 if (ar->fw_board != NULL)
653 return 0;
654
Kalle Valobdcd8172011-07-18 00:22:30 +0300655 switch (ar->version.target_ver) {
656 case AR6003_REV2_VERSION:
657 filename = AR6003_REV2_BOARD_DATA_FILE;
658 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800659 case AR6004_REV1_VERSION:
660 filename = AR6004_REV1_BOARD_DATA_FILE;
661 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300662 default:
663 filename = AR6003_REV3_BOARD_DATA_FILE;
664 break;
665 }
666
667 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
668 &ar->fw_board_len);
669 if (ret == 0) {
670 /* managed to get proper board file */
671 return 0;
672 }
673
Sam Leffler92ecbff2011-09-07 10:55:16 +0300674 if (check_device_tree(ar)) {
675 /* got board file from device tree */
676 return 0;
677 }
678
Kalle Valobdcd8172011-07-18 00:22:30 +0300679 /* there was no proper board file, try to use default instead */
680 ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
681 filename, ret);
682
683 switch (ar->version.target_ver) {
684 case AR6003_REV2_VERSION:
685 filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
686 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800687 case AR6004_REV1_VERSION:
688 filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
689 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300690 default:
691 filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
692 break;
693 }
694
695 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
696 &ar->fw_board_len);
697 if (ret) {
698 ath6kl_err("Failed to get default board file %s: %d\n",
699 filename, ret);
700 return ret;
701 }
702
703 ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
704 ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
705
706 return 0;
707}
708
Kalle Valo772c31e2011-09-07 10:55:16 +0300709static int ath6kl_fetch_otp_file(struct ath6kl *ar)
710{
711 const char *filename;
712 int ret;
713
714 if (ar->fw_otp != NULL)
715 return 0;
716
717 switch (ar->version.target_ver) {
718 case AR6003_REV2_VERSION:
719 filename = AR6003_REV2_OTP_FILE;
720 break;
721 case AR6004_REV1_VERSION:
722 ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
723 return 0;
724 break;
725 default:
726 filename = AR6003_REV3_OTP_FILE;
727 break;
728 }
729
730 ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
731 &ar->fw_otp_len);
732 if (ret) {
733 ath6kl_err("Failed to get OTP file %s: %d\n",
734 filename, ret);
735 return ret;
736 }
737
738 return 0;
739}
740
741static int ath6kl_fetch_fw_file(struct ath6kl *ar)
742{
743 const char *filename;
744 int ret;
745
746 if (ar->fw != NULL)
747 return 0;
748
749 if (testmode) {
750 switch (ar->version.target_ver) {
751 case AR6003_REV2_VERSION:
752 filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
753 break;
754 case AR6003_REV3_VERSION:
755 filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
756 break;
757 case AR6004_REV1_VERSION:
758 ath6kl_warn("testmode not supported with ar6004\n");
759 return -EOPNOTSUPP;
760 default:
761 ath6kl_warn("unknown target version: 0x%x\n",
762 ar->version.target_ver);
763 return -EINVAL;
764 }
765
766 set_bit(TESTMODE, &ar->flag);
767
768 goto get_fw;
769 }
770
771 switch (ar->version.target_ver) {
772 case AR6003_REV2_VERSION:
773 filename = AR6003_REV2_FIRMWARE_FILE;
774 break;
775 case AR6004_REV1_VERSION:
776 filename = AR6004_REV1_FIRMWARE_FILE;
777 break;
778 default:
779 filename = AR6003_REV3_FIRMWARE_FILE;
780 break;
781 }
782
783get_fw:
784 ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
785 if (ret) {
786 ath6kl_err("Failed to get firmware file %s: %d\n",
787 filename, ret);
788 return ret;
789 }
790
791 return 0;
792}
793
794static int ath6kl_fetch_patch_file(struct ath6kl *ar)
795{
796 const char *filename;
797 int ret;
798
799 switch (ar->version.target_ver) {
800 case AR6003_REV2_VERSION:
801 filename = AR6003_REV2_PATCH_FILE;
802 break;
803 case AR6004_REV1_VERSION:
804 /* FIXME: implement for AR6004 */
805 return 0;
806 break;
807 default:
808 filename = AR6003_REV3_PATCH_FILE;
809 break;
810 }
811
812 if (ar->fw_patch == NULL) {
813 ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
814 &ar->fw_patch_len);
815 if (ret) {
816 ath6kl_err("Failed to get patch file %s: %d\n",
817 filename, ret);
818 return ret;
819 }
820 }
821
822 return 0;
823}
824
Kalle Valo50d41232011-09-07 10:55:17 +0300825static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
Kalle Valo772c31e2011-09-07 10:55:16 +0300826{
827 int ret;
828
Kalle Valo772c31e2011-09-07 10:55:16 +0300829 ret = ath6kl_fetch_otp_file(ar);
830 if (ret)
831 return ret;
832
833 ret = ath6kl_fetch_fw_file(ar);
834 if (ret)
835 return ret;
836
837 ret = ath6kl_fetch_patch_file(ar);
838 if (ret)
839 return ret;
840
841 return 0;
842}
Kalle Valobdcd8172011-07-18 00:22:30 +0300843
Kalle Valo50d41232011-09-07 10:55:17 +0300844static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
845{
846 size_t magic_len, len, ie_len;
847 const struct firmware *fw;
848 struct ath6kl_fw_ie *hdr;
849 const char *filename;
850 const u8 *data;
Kalle Valo97e04962011-09-12 13:47:34 +0300851 int ret, ie_id, i, index, bit;
Kalle Valo8a137482011-09-07 10:55:17 +0300852 __le32 *val;
Kalle Valo50d41232011-09-07 10:55:17 +0300853
854 switch (ar->version.target_ver) {
855 case AR6003_REV2_VERSION:
856 filename = AR6003_REV2_FIRMWARE_2_FILE;
857 break;
858 case AR6003_REV3_VERSION:
859 filename = AR6003_REV3_FIRMWARE_2_FILE;
860 break;
861 case AR6004_REV1_VERSION:
862 filename = AR6004_REV1_FIRMWARE_2_FILE;
863 break;
Kalle Valo50e27402011-11-11 12:18:06 +0200864 case AR6004_REV2_VERSION:
865 filename = AR6004_REV2_FIRMWARE_2_FILE;
866 break;
Kalle Valo50d41232011-09-07 10:55:17 +0300867 default:
868 return -EOPNOTSUPP;
869 }
870
871 ret = request_firmware(&fw, filename, ar->dev);
872 if (ret)
873 return ret;
874
875 data = fw->data;
876 len = fw->size;
877
878 /* magic also includes the null byte, check that as well */
879 magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
880
881 if (len < magic_len) {
882 ret = -EINVAL;
883 goto out;
884 }
885
886 if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
887 ret = -EINVAL;
888 goto out;
889 }
890
891 len -= magic_len;
892 data += magic_len;
893
894 /* loop elements */
895 while (len > sizeof(struct ath6kl_fw_ie)) {
896 /* hdr is unaligned! */
897 hdr = (struct ath6kl_fw_ie *) data;
898
899 ie_id = le32_to_cpup(&hdr->id);
900 ie_len = le32_to_cpup(&hdr->len);
901
902 len -= sizeof(*hdr);
903 data += sizeof(*hdr);
904
905 if (len < ie_len) {
906 ret = -EINVAL;
907 goto out;
908 }
909
910 switch (ie_id) {
911 case ATH6KL_FW_IE_OTP_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300912 ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300913 ie_len);
914
Kalle Valo50d41232011-09-07 10:55:17 +0300915 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
916
917 if (ar->fw_otp == NULL) {
918 ret = -ENOMEM;
919 goto out;
920 }
921
922 ar->fw_otp_len = ie_len;
923 break;
924 case ATH6KL_FW_IE_FW_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300925 ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300926 ie_len);
927
Kalle Valo50d41232011-09-07 10:55:17 +0300928 ar->fw = kmemdup(data, ie_len, GFP_KERNEL);
929
930 if (ar->fw == NULL) {
931 ret = -ENOMEM;
932 goto out;
933 }
934
935 ar->fw_len = ie_len;
936 break;
937 case ATH6KL_FW_IE_PATCH_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300938 ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300939 ie_len);
940
Kalle Valo50d41232011-09-07 10:55:17 +0300941 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
942
943 if (ar->fw_patch == NULL) {
944 ret = -ENOMEM;
945 goto out;
946 }
947
948 ar->fw_patch_len = ie_len;
949 break;
Kalle Valo8a137482011-09-07 10:55:17 +0300950 case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
951 val = (__le32 *) data;
952 ar->hw.reserved_ram_size = le32_to_cpup(val);
Kalle Valo6bc36432011-09-27 14:31:11 +0300953
954 ath6kl_dbg(ATH6KL_DBG_BOOT,
955 "found reserved ram size ie 0x%d\n",
956 ar->hw.reserved_ram_size);
Kalle Valo8a137482011-09-07 10:55:17 +0300957 break;
Kalle Valo97e04962011-09-12 13:47:34 +0300958 case ATH6KL_FW_IE_CAPABILITIES:
Kalle Valo6bc36432011-09-27 14:31:11 +0300959 ath6kl_dbg(ATH6KL_DBG_BOOT,
Kalle Valoef548622011-10-01 09:43:09 +0300960 "found firmware capabilities ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300961 ie_len);
962
Kalle Valo97e04962011-09-12 13:47:34 +0300963 for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
964 index = ALIGN(i, 8) / 8;
965 bit = i % 8;
966
967 if (data[index] & (1 << bit))
968 __set_bit(i, ar->fw_capabilities);
969 }
Kalle Valo6bc36432011-09-27 14:31:11 +0300970
971 ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "",
972 ar->fw_capabilities,
973 sizeof(ar->fw_capabilities));
Kalle Valo97e04962011-09-12 13:47:34 +0300974 break;
Kalle Valo1b4304d2011-09-27 11:05:26 +0300975 case ATH6KL_FW_IE_PATCH_ADDR:
976 if (ie_len != sizeof(*val))
977 break;
978
979 val = (__le32 *) data;
980 ar->hw.dataset_patch_addr = le32_to_cpup(val);
Kalle Valo6bc36432011-09-27 14:31:11 +0300981
982 ath6kl_dbg(ATH6KL_DBG_BOOT,
Kalle Valo03ef0252011-11-14 19:30:47 +0200983 "found patch address ie 0x%x\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300984 ar->hw.dataset_patch_addr);
Kalle Valo1b4304d2011-09-27 11:05:26 +0300985 break;
Kalle Valo03ef0252011-11-14 19:30:47 +0200986 case ATH6KL_FW_IE_BOARD_ADDR:
987 if (ie_len != sizeof(*val))
988 break;
989
990 val = (__le32 *) data;
991 ar->hw.board_addr = le32_to_cpup(val);
992
993 ath6kl_dbg(ATH6KL_DBG_BOOT,
994 "found board address ie 0x%x\n",
995 ar->hw.board_addr);
996 break;
Kalle Valo50d41232011-09-07 10:55:17 +0300997 default:
Kalle Valo6bc36432011-09-27 14:31:11 +0300998 ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n",
Kalle Valo50d41232011-09-07 10:55:17 +0300999 le32_to_cpup(&hdr->id));
1000 break;
1001 }
1002
1003 len -= ie_len;
1004 data += ie_len;
1005 };
1006
1007 ret = 0;
1008out:
1009 release_firmware(fw);
1010
1011 return ret;
1012}
1013
1014static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1015{
1016 int ret;
1017
1018 ret = ath6kl_fetch_board_file(ar);
1019 if (ret)
1020 return ret;
1021
1022 ret = ath6kl_fetch_fw_api2(ar);
Kalle Valo6bc36432011-09-27 14:31:11 +03001023 if (ret == 0) {
1024 ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n");
Kalle Valo50d41232011-09-07 10:55:17 +03001025 return 0;
Kalle Valo6bc36432011-09-27 14:31:11 +03001026 }
Kalle Valo50d41232011-09-07 10:55:17 +03001027
1028 ret = ath6kl_fetch_fw_api1(ar);
1029 if (ret)
1030 return ret;
1031
Kalle Valo6bc36432011-09-27 14:31:11 +03001032 ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n");
1033
Kalle Valo50d41232011-09-07 10:55:17 +03001034 return 0;
1035}
1036
Kalle Valobdcd8172011-07-18 00:22:30 +03001037static int ath6kl_upload_board_file(struct ath6kl *ar)
1038{
1039 u32 board_address, board_ext_address, param;
Kevin Fang31024d92011-07-11 17:14:13 +08001040 u32 board_data_size, board_ext_data_size;
Kalle Valobdcd8172011-07-18 00:22:30 +03001041 int ret;
1042
Kalle Valo772c31e2011-09-07 10:55:16 +03001043 if (WARN_ON(ar->fw_board == NULL))
1044 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001045
Kevin Fang31024d92011-07-11 17:14:13 +08001046 /*
1047 * Determine where in Target RAM to write Board Data.
1048 * For AR6004, host determine Target RAM address for
1049 * writing board data.
1050 */
Kalle Valo0d4d72b2011-11-14 19:30:39 +02001051 if (ar->hw.board_addr != 0) {
1052 board_address = ar->hw.board_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001053 ath6kl_bmi_write(ar,
1054 ath6kl_get_hi_item_addr(ar,
1055 HI_ITEM(hi_board_data)),
1056 (u8 *) &board_address, 4);
1057 } else {
1058 ath6kl_bmi_read(ar,
1059 ath6kl_get_hi_item_addr(ar,
1060 HI_ITEM(hi_board_data)),
1061 (u8 *) &board_address, 4);
1062 }
1063
Kalle Valobdcd8172011-07-18 00:22:30 +03001064 /* determine where in target ram to write extended board data */
1065 ath6kl_bmi_read(ar,
1066 ath6kl_get_hi_item_addr(ar,
1067 HI_ITEM(hi_board_ext_data)),
1068 (u8 *) &board_ext_address, 4);
1069
Kalle Valo50e27402011-11-11 12:18:06 +02001070 if (ar->target_type == TARGET_TYPE_AR6003 &&
1071 board_ext_address == 0) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001072 ath6kl_err("Failed to get board file target address.\n");
1073 return -EINVAL;
1074 }
1075
Kevin Fang31024d92011-07-11 17:14:13 +08001076 switch (ar->target_type) {
1077 case TARGET_TYPE_AR6003:
1078 board_data_size = AR6003_BOARD_DATA_SZ;
1079 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1080 break;
1081 case TARGET_TYPE_AR6004:
1082 board_data_size = AR6004_BOARD_DATA_SZ;
1083 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1084 break;
1085 default:
1086 WARN_ON(1);
1087 return -EINVAL;
1088 break;
1089 }
1090
Kalle Valo50e27402011-11-11 12:18:06 +02001091 if (board_ext_address &&
1092 ar->fw_board_len == (board_data_size + board_ext_data_size)) {
Kevin Fang31024d92011-07-11 17:14:13 +08001093
Kalle Valobdcd8172011-07-18 00:22:30 +03001094 /* write extended board data */
Kalle Valo6bc36432011-09-27 14:31:11 +03001095 ath6kl_dbg(ATH6KL_DBG_BOOT,
1096 "writing extended board data to 0x%x (%d B)\n",
1097 board_ext_address, board_ext_data_size);
1098
Kalle Valobdcd8172011-07-18 00:22:30 +03001099 ret = ath6kl_bmi_write(ar, board_ext_address,
Kevin Fang31024d92011-07-11 17:14:13 +08001100 ar->fw_board + board_data_size,
1101 board_ext_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001102 if (ret) {
1103 ath6kl_err("Failed to write extended board data: %d\n",
1104 ret);
1105 return ret;
1106 }
1107
1108 /* record that extended board data is initialized */
Kevin Fang31024d92011-07-11 17:14:13 +08001109 param = (board_ext_data_size << 16) | 1;
1110
Kalle Valobdcd8172011-07-18 00:22:30 +03001111 ath6kl_bmi_write(ar,
1112 ath6kl_get_hi_item_addr(ar,
1113 HI_ITEM(hi_board_ext_data_config)),
1114 (unsigned char *) &param, 4);
1115 }
1116
Kevin Fang31024d92011-07-11 17:14:13 +08001117 if (ar->fw_board_len < board_data_size) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001118 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1119 ret = -EINVAL;
1120 return ret;
1121 }
1122
Kalle Valo6bc36432011-09-27 14:31:11 +03001123 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n",
1124 board_address, board_data_size);
1125
Kalle Valobdcd8172011-07-18 00:22:30 +03001126 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
Kevin Fang31024d92011-07-11 17:14:13 +08001127 board_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001128
1129 if (ret) {
1130 ath6kl_err("Board file bmi write failed: %d\n", ret);
1131 return ret;
1132 }
1133
1134 /* record the fact that Board Data IS initialized */
1135 param = 1;
1136 ath6kl_bmi_write(ar,
1137 ath6kl_get_hi_item_addr(ar,
1138 HI_ITEM(hi_board_data_initialized)),
1139 (u8 *)&param, 4);
1140
1141 return ret;
1142}
1143
1144static int ath6kl_upload_otp(struct ath6kl *ar)
1145{
Kalle Valobdcd8172011-07-18 00:22:30 +03001146 u32 address, param;
Kalle Valobef26a72011-10-12 09:58:28 +03001147 bool from_hw = false;
Kalle Valobdcd8172011-07-18 00:22:30 +03001148 int ret;
1149
Kalle Valo50e27402011-11-11 12:18:06 +02001150 if (ar->fw_otp == NULL)
1151 return 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001152
Kalle Valoa01ac412011-09-07 10:55:17 +03001153 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001154
Kalle Valoef548622011-10-01 09:43:09 +03001155 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address,
Kalle Valo6bc36432011-09-27 14:31:11 +03001156 ar->fw_otp_len);
1157
Kalle Valobdcd8172011-07-18 00:22:30 +03001158 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1159 ar->fw_otp_len);
1160 if (ret) {
1161 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1162 return ret;
1163 }
1164
Kalle Valo639d0b82011-09-12 12:48:09 +03001165 /* read firmware start address */
1166 ret = ath6kl_bmi_read(ar,
1167 ath6kl_get_hi_item_addr(ar,
1168 HI_ITEM(hi_app_start)),
1169 (u8 *) &address, sizeof(address));
1170
1171 if (ret) {
1172 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1173 return ret;
1174 }
1175
Kalle Valobef26a72011-10-12 09:58:28 +03001176 if (ar->hw.app_start_override_addr == 0) {
1177 ar->hw.app_start_override_addr = address;
1178 from_hw = true;
1179 }
Kalle Valo639d0b82011-09-12 12:48:09 +03001180
Kalle Valobef26a72011-10-12 09:58:28 +03001181 ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr%s 0x%x\n",
1182 from_hw ? " (from hw)" : "",
Kalle Valo6bc36432011-09-27 14:31:11 +03001183 ar->hw.app_start_override_addr);
1184
Kalle Valobdcd8172011-07-18 00:22:30 +03001185 /* execute the OTP code */
Kalle Valobef26a72011-10-12 09:58:28 +03001186 ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n",
1187 ar->hw.app_start_override_addr);
Kalle Valobdcd8172011-07-18 00:22:30 +03001188 param = 0;
Kalle Valobef26a72011-10-12 09:58:28 +03001189 ath6kl_bmi_execute(ar, ar->hw.app_start_override_addr, &param);
Kalle Valobdcd8172011-07-18 00:22:30 +03001190
1191 return ret;
1192}
1193
1194static int ath6kl_upload_firmware(struct ath6kl *ar)
1195{
Kalle Valobdcd8172011-07-18 00:22:30 +03001196 u32 address;
1197 int ret;
1198
Kalle Valo772c31e2011-09-07 10:55:16 +03001199 if (WARN_ON(ar->fw == NULL))
Kalle Valo50e27402011-11-11 12:18:06 +02001200 return 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001201
Kalle Valoa01ac412011-09-07 10:55:17 +03001202 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001203
Kalle Valoef548622011-10-01 09:43:09 +03001204 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +03001205 address, ar->fw_len);
1206
Kalle Valobdcd8172011-07-18 00:22:30 +03001207 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1208
1209 if (ret) {
1210 ath6kl_err("Failed to write firmware: %d\n", ret);
1211 return ret;
1212 }
1213
Kevin Fang31024d92011-07-11 17:14:13 +08001214 /*
1215 * Set starting address for firmware
1216 * Don't need to setup app_start override addr on AR6004
1217 */
1218 if (ar->target_type != TARGET_TYPE_AR6004) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001219 address = ar->hw.app_start_override_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001220 ath6kl_bmi_set_app_start(ar, address);
1221 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001222 return ret;
1223}
1224
1225static int ath6kl_upload_patch(struct ath6kl *ar)
1226{
Kalle Valobdcd8172011-07-18 00:22:30 +03001227 u32 address, param;
1228 int ret;
1229
Kalle Valo50e27402011-11-11 12:18:06 +02001230 if (ar->fw_patch == NULL)
1231 return 0;
Kalle Valobdcd8172011-07-18 00:22:30 +03001232
Kalle Valoa01ac412011-09-07 10:55:17 +03001233 address = ar->hw.dataset_patch_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001234
Kalle Valoef548622011-10-01 09:43:09 +03001235 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +03001236 address, ar->fw_patch_len);
1237
Kalle Valobdcd8172011-07-18 00:22:30 +03001238 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1239 if (ret) {
1240 ath6kl_err("Failed to write patch file: %d\n", ret);
1241 return ret;
1242 }
1243
1244 param = address;
1245 ath6kl_bmi_write(ar,
1246 ath6kl_get_hi_item_addr(ar,
1247 HI_ITEM(hi_dset_list_head)),
1248 (unsigned char *) &param, 4);
1249
1250 return 0;
1251}
1252
1253static int ath6kl_init_upload(struct ath6kl *ar)
1254{
1255 u32 param, options, sleep, address;
1256 int status = 0;
1257
Kevin Fang31024d92011-07-11 17:14:13 +08001258 if (ar->target_type != TARGET_TYPE_AR6003 &&
1259 ar->target_type != TARGET_TYPE_AR6004)
Kalle Valobdcd8172011-07-18 00:22:30 +03001260 return -EINVAL;
1261
1262 /* temporarily disable system sleep */
1263 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1264 status = ath6kl_bmi_reg_read(ar, address, &param);
1265 if (status)
1266 return status;
1267
1268 options = param;
1269
1270 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1271 status = ath6kl_bmi_reg_write(ar, address, param);
1272 if (status)
1273 return status;
1274
1275 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1276 status = ath6kl_bmi_reg_read(ar, address, &param);
1277 if (status)
1278 return status;
1279
1280 sleep = param;
1281
1282 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1283 status = ath6kl_bmi_reg_write(ar, address, param);
1284 if (status)
1285 return status;
1286
1287 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1288 options, sleep);
1289
1290 /* program analog PLL register */
Kevin Fang31024d92011-07-11 17:14:13 +08001291 /* no need to control 40/44MHz clock on AR6004 */
1292 if (ar->target_type != TARGET_TYPE_AR6004) {
1293 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1294 0xF9104001);
Kalle Valobdcd8172011-07-18 00:22:30 +03001295
Kevin Fang31024d92011-07-11 17:14:13 +08001296 if (status)
1297 return status;
Kalle Valobdcd8172011-07-18 00:22:30 +03001298
Kevin Fang31024d92011-07-11 17:14:13 +08001299 /* Run at 80/88MHz by default */
1300 param = SM(CPU_CLOCK_STANDARD, 1);
1301
1302 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1303 status = ath6kl_bmi_reg_write(ar, address, param);
1304 if (status)
1305 return status;
1306 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001307
1308 param = 0;
1309 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1310 param = SM(LPO_CAL_ENABLE, 1);
1311 status = ath6kl_bmi_reg_write(ar, address, param);
1312 if (status)
1313 return status;
1314
1315 /* WAR to avoid SDIO CRC err */
1316 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1317 ath6kl_err("temporary war to avoid sdio crc error\n");
1318
1319 param = 0x20;
1320
1321 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1322 status = ath6kl_bmi_reg_write(ar, address, param);
1323 if (status)
1324 return status;
1325
1326 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1327 status = ath6kl_bmi_reg_write(ar, address, param);
1328 if (status)
1329 return status;
1330
1331 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1332 status = ath6kl_bmi_reg_write(ar, address, param);
1333 if (status)
1334 return status;
1335
1336 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1337 status = ath6kl_bmi_reg_write(ar, address, param);
1338 if (status)
1339 return status;
1340 }
1341
1342 /* write EEPROM data to Target RAM */
1343 status = ath6kl_upload_board_file(ar);
1344 if (status)
1345 return status;
1346
1347 /* transfer One time Programmable data */
1348 status = ath6kl_upload_otp(ar);
1349 if (status)
1350 return status;
1351
1352 /* Download Target firmware */
1353 status = ath6kl_upload_firmware(ar);
1354 if (status)
1355 return status;
1356
1357 status = ath6kl_upload_patch(ar);
1358 if (status)
1359 return status;
1360
1361 /* Restore system sleep */
1362 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1363 status = ath6kl_bmi_reg_write(ar, address, sleep);
1364 if (status)
1365 return status;
1366
1367 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1368 param = options | 0x20;
1369 status = ath6kl_bmi_reg_write(ar, address, param);
1370 if (status)
1371 return status;
1372
1373 /* Configure GPIO AR6003 UART */
1374 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1375 status = ath6kl_bmi_write(ar,
1376 ath6kl_get_hi_item_addr(ar,
1377 HI_ITEM(hi_dbg_uart_txpin)),
1378 (u8 *)&param, 4);
1379
1380 return status;
1381}
1382
Kalle Valoa01ac412011-09-07 10:55:17 +03001383static int ath6kl_init_hw_params(struct ath6kl *ar)
1384{
Kalle Valo856f4b312011-11-14 19:30:29 +02001385 const struct ath6kl_hw *hw;
1386 int i;
Kalle Valobef26a72011-10-12 09:58:28 +03001387
Kalle Valo856f4b312011-11-14 19:30:29 +02001388 for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
1389 hw = &hw_list[i];
Kalle Valobef26a72011-10-12 09:58:28 +03001390
Kalle Valo856f4b312011-11-14 19:30:29 +02001391 if (hw->id == ar->version.target_ver)
1392 break;
1393 }
1394
1395 if (i == ARRAY_SIZE(hw_list)) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001396 ath6kl_err("Unsupported hardware version: 0x%x\n",
1397 ar->version.target_ver);
1398 return -EINVAL;
1399 }
1400
Kalle Valo856f4b312011-11-14 19:30:29 +02001401 ar->hw = *hw;
1402
Kalle Valo6bc36432011-09-27 14:31:11 +03001403 ath6kl_dbg(ATH6KL_DBG_BOOT,
1404 "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n",
1405 ar->version.target_ver, ar->target_type,
1406 ar->hw.dataset_patch_addr, ar->hw.app_load_addr);
1407 ath6kl_dbg(ATH6KL_DBG_BOOT,
1408 "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x",
1409 ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr,
1410 ar->hw.reserved_ram_size);
1411
Kalle Valoa01ac412011-09-07 10:55:17 +03001412 return 0;
1413}
1414
Kalle Valo293badf2011-11-14 19:30:54 +02001415static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
1416{
1417 switch (type) {
1418 case ATH6KL_HIF_TYPE_SDIO:
1419 return "sdio";
1420 case ATH6KL_HIF_TYPE_USB:
1421 return "usb";
1422 }
1423
1424 return NULL;
1425}
1426
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001427int ath6kl_init_hw_start(struct ath6kl *ar)
Kalle Valo20459ee2011-10-27 18:48:37 +03001428{
1429 long timeleft;
1430 int ret, i;
1431
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001432 ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
1433
Kalle Valo20459ee2011-10-27 18:48:37 +03001434 ret = ath6kl_hif_power_on(ar);
1435 if (ret)
1436 return ret;
1437
1438 ret = ath6kl_configure_target(ar);
1439 if (ret)
1440 goto err_power_off;
1441
1442 ret = ath6kl_init_upload(ar);
1443 if (ret)
1444 goto err_power_off;
1445
1446 /* Do we need to finish the BMI phase */
1447 /* FIXME: return error from ath6kl_bmi_done() */
1448 if (ath6kl_bmi_done(ar)) {
1449 ret = -EIO;
1450 goto err_power_off;
1451 }
1452
1453 /*
1454 * The reason we have to wait for the target here is that the
1455 * driver layer has to init BMI in order to set the host block
1456 * size.
1457 */
1458 if (ath6kl_htc_wait_target(ar->htc_target)) {
1459 ret = -EIO;
1460 goto err_power_off;
1461 }
1462
1463 if (ath6kl_init_service_ep(ar)) {
1464 ret = -EIO;
1465 goto err_cleanup_scatter;
1466 }
1467
1468 /* setup credit distribution */
1469 ath6kl_credit_setup(ar->htc_target, &ar->credit_state_info);
1470
1471 /* start HTC */
1472 ret = ath6kl_htc_start(ar->htc_target);
1473 if (ret) {
1474 /* FIXME: call this */
1475 ath6kl_cookie_cleanup(ar);
1476 goto err_cleanup_scatter;
1477 }
1478
1479 /* Wait for Wmi event to be ready */
1480 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1481 test_bit(WMI_READY,
1482 &ar->flag),
1483 WMI_TIMEOUT);
1484
1485 ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n");
1486
Kalle Valo293badf2011-11-14 19:30:54 +02001487
1488 if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
1489 ath6kl_info("%s %s fw %s%s\n",
1490 ar->hw.name,
1491 ath6kl_init_get_hif_name(ar->hif_type),
1492 ar->wiphy->fw_version,
1493 test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
1494 }
1495
Kalle Valo20459ee2011-10-27 18:48:37 +03001496 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1497 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1498 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1499 ret = -EIO;
1500 goto err_htc_stop;
1501 }
1502
1503 if (!timeleft || signal_pending(current)) {
1504 ath6kl_err("wmi is not ready or wait was interrupted\n");
1505 ret = -EIO;
1506 goto err_htc_stop;
1507 }
1508
1509 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1510
1511 /* communicate the wmi protocol verision to the target */
1512 /* FIXME: return error */
1513 if ((ath6kl_set_host_app_area(ar)) != 0)
1514 ath6kl_err("unable to set the host app area\n");
1515
1516 for (i = 0; i < MAX_NUM_VIF; i++) {
1517 ret = ath6kl_target_config_wlan_params(ar, i);
1518 if (ret)
1519 goto err_htc_stop;
1520 }
1521
Kalle Valo76a9fbe2011-11-01 08:44:28 +02001522 ar->state = ATH6KL_STATE_ON;
1523
Kalle Valo20459ee2011-10-27 18:48:37 +03001524 return 0;
1525
1526err_htc_stop:
1527 ath6kl_htc_stop(ar->htc_target);
1528err_cleanup_scatter:
1529 ath6kl_hif_cleanup_scatter(ar);
1530err_power_off:
1531 ath6kl_hif_power_off(ar);
1532
1533 return ret;
1534}
1535
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001536int ath6kl_init_hw_stop(struct ath6kl *ar)
1537{
1538 int ret;
1539
1540 ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
1541
1542 ath6kl_htc_stop(ar->htc_target);
1543
1544 ath6kl_hif_stop(ar);
1545
1546 ath6kl_bmi_reset(ar);
1547
1548 ret = ath6kl_hif_power_off(ar);
1549 if (ret)
1550 ath6kl_warn("failed to power off hif: %d\n", ret);
1551
Kalle Valo76a9fbe2011-11-01 08:44:28 +02001552 ar->state = ATH6KL_STATE_OFF;
1553
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001554 return 0;
1555}
1556
Kalle Valobdcd8172011-07-18 00:22:30 +03001557int ath6kl_core_init(struct ath6kl *ar)
1558{
Kalle Valobdcd8172011-07-18 00:22:30 +03001559 struct ath6kl_bmi_target_info targ_info;
Kalle Valo61448a92011-10-27 18:48:29 +03001560 struct net_device *ndev;
Kalle Valo20459ee2011-10-27 18:48:37 +03001561 int ret = 0, i;
Kalle Valobdcd8172011-07-18 00:22:30 +03001562
1563 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1564 if (!ar->ath6kl_wq)
1565 return -ENOMEM;
1566
1567 ret = ath6kl_bmi_init(ar);
1568 if (ret)
1569 goto err_wq;
1570
Kalle Valo20459ee2011-10-27 18:48:37 +03001571 /*
1572 * Turn on power to get hardware (target) version and leave power
1573 * on delibrately as we will boot the hardware anyway within few
1574 * seconds.
1575 */
Kalle Valob2e75692011-10-27 18:48:14 +03001576 ret = ath6kl_hif_power_on(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001577 if (ret)
1578 goto err_bmi_cleanup;
1579
Kalle Valob2e75692011-10-27 18:48:14 +03001580 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1581 if (ret)
1582 goto err_power_off;
1583
Kalle Valobdcd8172011-07-18 00:22:30 +03001584 ar->version.target_ver = le32_to_cpu(targ_info.version);
1585 ar->target_type = le32_to_cpu(targ_info.type);
Vasanthakumar Thiagarajanbe98e3a2011-10-25 19:33:57 +05301586 ar->wiphy->hw_version = le32_to_cpu(targ_info.version);
Kalle Valobdcd8172011-07-18 00:22:30 +03001587
Kalle Valoa01ac412011-09-07 10:55:17 +03001588 ret = ath6kl_init_hw_params(ar);
1589 if (ret)
Kalle Valob2e75692011-10-27 18:48:14 +03001590 goto err_power_off;
Kalle Valoa01ac412011-09-07 10:55:17 +03001591
Kalle Vaload226ec2011-08-10 09:49:12 +03001592 ar->htc_target = ath6kl_htc_create(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001593
1594 if (!ar->htc_target) {
1595 ret = -ENOMEM;
Kalle Valob2e75692011-10-27 18:48:14 +03001596 goto err_power_off;
Kalle Valobdcd8172011-07-18 00:22:30 +03001597 }
1598
Kalle Valo772c31e2011-09-07 10:55:16 +03001599 ret = ath6kl_fetch_firmwares(ar);
1600 if (ret)
1601 goto err_htc_cleanup;
1602
Kalle Valo61448a92011-10-27 18:48:29 +03001603 /* FIXME: we should free all firmwares in the error cases below */
1604
Kalle Valo61448a92011-10-27 18:48:29 +03001605 /* Indicate that WMI is enabled (although not ready yet) */
1606 set_bit(WMI_ENABLED, &ar->flag);
1607 ar->wmi = ath6kl_wmi_init(ar);
1608 if (!ar->wmi) {
1609 ath6kl_err("failed to initialize wmi\n");
1610 ret = -EIO;
1611 goto err_htc_cleanup;
1612 }
1613
1614 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1615
1616 ret = ath6kl_register_ieee80211_hw(ar);
1617 if (ret)
1618 goto err_node_cleanup;
1619
1620 ret = ath6kl_debug_init(ar);
1621 if (ret) {
1622 wiphy_unregister(ar->wiphy);
1623 goto err_node_cleanup;
1624 }
1625
1626 for (i = 0; i < MAX_NUM_VIF; i++)
1627 ar->avail_idx_map |= BIT(i);
1628
1629 rtnl_lock();
1630
1631 /* Add an initial station interface */
1632 ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
1633 INFRA_NETWORK);
1634
1635 rtnl_unlock();
1636
1637 if (!ndev) {
1638 ath6kl_err("Failed to instantiate a network device\n");
1639 ret = -ENOMEM;
1640 wiphy_unregister(ar->wiphy);
1641 goto err_debug_init;
1642 }
1643
1644
1645 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1646 __func__, ndev->name, ndev, ar);
1647
Kalle Valo61448a92011-10-27 18:48:29 +03001648 /* setup access class priority mappings */
1649 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1650 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1651 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1652 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1653
1654 /* give our connected endpoints some buffers */
1655 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1656 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1657
1658 /* allocate some buffers that handle larger AMSDU frames */
1659 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1660
Kalle Valo61448a92011-10-27 18:48:29 +03001661 ath6kl_cookie_init(ar);
1662
Kalle Valo61448a92011-10-27 18:48:29 +03001663 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1664 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1665
Kalle Valo8277de12011-11-03 12:18:31 +02001666 if (suspend_cutpower)
1667 ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER;
1668
Kalle Valo61448a92011-10-27 18:48:29 +03001669 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
1670 WIPHY_FLAG_HAVE_AP_SME;
1671
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001672 set_bit(FIRST_BOOT, &ar->flag);
1673
1674 ret = ath6kl_init_hw_start(ar);
Kalle Valo20459ee2011-10-27 18:48:37 +03001675 if (ret) {
Kalle Valo5fe4dff2011-10-30 21:16:15 +02001676 ath6kl_err("Failed to start hardware: %d\n", ret);
Kalle Valo20459ee2011-10-27 18:48:37 +03001677 goto err_rxbuf_cleanup;
Kalle Valo61448a92011-10-27 18:48:29 +03001678 }
1679
1680 /*
1681 * Set mac address which is received in ready event
1682 * FIXME: Move to ath6kl_interface_add()
1683 */
1684 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
Kalle Valobdcd8172011-07-18 00:22:30 +03001685
Kalle Valobdcd8172011-07-18 00:22:30 +03001686 return ret;
1687
Kalle Valo61448a92011-10-27 18:48:29 +03001688err_rxbuf_cleanup:
1689 ath6kl_htc_flush_rx_buf(ar->htc_target);
1690 ath6kl_cleanup_amsdu_rxbufs(ar);
Kalle Valo61448a92011-10-27 18:48:29 +03001691 rtnl_lock();
1692 ath6kl_deinit_if_data(netdev_priv(ndev));
1693 rtnl_unlock();
1694 wiphy_unregister(ar->wiphy);
1695err_debug_init:
1696 ath6kl_debug_cleanup(ar);
1697err_node_cleanup:
1698 ath6kl_wmi_shutdown(ar->wmi);
1699 clear_bit(WMI_ENABLED, &ar->flag);
1700 ar->wmi = NULL;
Kalle Valobdcd8172011-07-18 00:22:30 +03001701err_htc_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001702 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valob2e75692011-10-27 18:48:14 +03001703err_power_off:
1704 ath6kl_hif_power_off(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001705err_bmi_cleanup:
1706 ath6kl_bmi_cleanup(ar);
1707err_wq:
1708 destroy_workqueue(ar->ath6kl_wq);
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +05301709
Kalle Valobdcd8172011-07-18 00:22:30 +03001710 return ret;
1711}
1712
Vasanthakumar Thiagarajan55055972011-10-25 19:34:23 +05301713void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301714{
1715 static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1716 bool discon_issued;
1717
1718 netif_stop_queue(vif->ndev);
1719
1720 clear_bit(WLAN_ENABLED, &vif->flags);
1721
1722 if (wmi_ready) {
1723 discon_issued = test_bit(CONNECTED, &vif->flags) ||
1724 test_bit(CONNECT_PEND, &vif->flags);
1725 ath6kl_disconnect(vif);
1726 del_timer(&vif->disconnect_timer);
1727
1728 if (discon_issued)
1729 ath6kl_disconnect_event(vif, DISCONNECT_CMD,
1730 (vif->nw_type & AP_NETWORK) ?
1731 bcast_mac : vif->bssid,
1732 0, NULL, 0);
1733 }
1734
1735 if (vif->scan_req) {
1736 cfg80211_scan_done(vif->scan_req, true);
1737 vif->scan_req = NULL;
1738 }
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301739}
1740
Kalle Valobdcd8172011-07-18 00:22:30 +03001741void ath6kl_stop_txrx(struct ath6kl *ar)
1742{
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301743 struct ath6kl_vif *vif, *tmp_vif;
Kalle Valobdcd8172011-07-18 00:22:30 +03001744
1745 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1746
1747 if (down_interruptible(&ar->sem)) {
1748 ath6kl_err("down_interruptible failed\n");
1749 return;
1750 }
1751
Vasanthakumar Thiagarajan11f6e402011-11-01 16:38:50 +05301752 spin_lock_bh(&ar->list_lock);
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301753 list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
1754 list_del(&vif->list);
Vasanthakumar Thiagarajan11f6e402011-11-01 16:38:50 +05301755 spin_unlock_bh(&ar->list_lock);
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301756 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
Vasanthakumar Thiagarajan27929722011-10-25 19:34:21 +05301757 rtnl_lock();
1758 ath6kl_deinit_if_data(vif);
1759 rtnl_unlock();
Vasanthakumar Thiagarajan11f6e402011-11-01 16:38:50 +05301760 spin_lock_bh(&ar->list_lock);
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301761 }
Vasanthakumar Thiagarajan11f6e402011-11-01 16:38:50 +05301762 spin_unlock_bh(&ar->list_lock);
Kalle Valobdcd8172011-07-18 00:22:30 +03001763
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301764 clear_bit(WMI_READY, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001765
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301766 /*
1767 * After wmi_shudown all WMI events will be dropped. We
1768 * need to cleanup the buffers allocated in AP mode and
1769 * give disconnect notification to stack, which usually
1770 * happens in the disconnect_event. Simulate the disconnect
1771 * event by calling the function directly. Sometimes
1772 * disconnect_event will be received when the debug logs
1773 * are collected.
1774 */
1775 ath6kl_wmi_shutdown(ar->wmi);
Kalle Valobdcd8172011-07-18 00:22:30 +03001776
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301777 clear_bit(WMI_ENABLED, &ar->flag);
1778 if (ar->htc_target) {
1779 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
1780 ath6kl_htc_stop(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001781 }
1782
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301783 /*
1784 * Try to reset the device if we can. The driver may have been
1785 * configure NOT to reset the target during a debug session.
1786 */
1787 ath6kl_dbg(ATH6KL_DBG_TRC,
1788 "attempting to reset target on instance destroy\n");
1789 ath6kl_reset_device(ar, ar->target_type, true, true);
Kalle Valobdcd8172011-07-18 00:22:30 +03001790
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301791 clear_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001792}