blob: 2ee6a5eced651bcd2c8b1bbb1bb65f56d6d8e039 [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 Valobdcd8172011-07-18 00:22:30 +030030
31module_param(debug_mask, uint, 0644);
Kalle Valo003353b0d2011-09-01 10:14:21 +030032module_param(testmode, uint, 0644);
Kalle Valobdcd8172011-07-18 00:22:30 +030033
34/*
35 * Include definitions here that can be used to tune the WLAN module
36 * behavior. Different customers can tune the behavior as per their needs,
37 * here.
38 */
39
40/*
41 * This configuration item enable/disable keepalive support.
42 * Keepalive support: In the absence of any data traffic to AP, null
43 * frames will be sent to the AP at periodic interval, to keep the association
44 * active. This configuration item defines the periodic interval.
45 * Use value of zero to disable keepalive support
46 * Default: 60 seconds
47 */
48#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
49
50/*
51 * This configuration item sets the value of disconnect timeout
52 * Firmware delays sending the disconnec event to the host for this
53 * timeout after is gets disconnected from the current AP.
54 * If the firmware successly roams within the disconnect timeout
55 * it sends a new connect event
56 */
57#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
58
59#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
60
Kalle Valobdcd8172011-07-18 00:22:30 +030061#define ATH6KL_DATA_OFFSET 64
62struct sk_buff *ath6kl_buf_alloc(int size)
63{
64 struct sk_buff *skb;
65 u16 reserved;
66
67 /* Add chacheline space at front and back of buffer */
68 reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
Vasanthakumar Thiagarajan1df94a82011-08-17 18:45:10 +053069 sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES;
Kalle Valobdcd8172011-07-18 00:22:30 +030070 skb = dev_alloc_skb(size + reserved);
71
72 if (skb)
73 skb_reserve(skb, reserved - L1_CACHE_BYTES);
74 return skb;
75}
76
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +053077void ath6kl_init_profile_info(struct ath6kl_vif *vif)
Kalle Valobdcd8172011-07-18 00:22:30 +030078{
Vasanthakumar Thiagarajan34503342011-10-25 19:34:02 +053079 vif->ssid_len = 0;
80 memset(vif->ssid, 0, sizeof(vif->ssid));
81
82 vif->dot11_auth_mode = OPEN_AUTH;
83 vif->auth_mode = NONE_AUTH;
84 vif->prwise_crypto = NONE_CRYPT;
85 vif->prwise_crypto_len = 0;
86 vif->grp_crypto = NONE_CRYPT;
87 vif->grp_crypto_len = 0;
Vasanthakumar Thiagarajan6f2a73f2011-10-25 19:34:06 +053088 memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
Vasanthakumar Thiagarajan8c8b65e2011-10-25 19:34:04 +053089 memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
90 memset(vif->bssid, 0, sizeof(vif->bssid));
Vasanthakumar Thiagarajanf74bac52011-10-25 19:34:05 +053091 vif->bss_ch = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +030092}
93
Kalle Valobdcd8172011-07-18 00:22:30 +030094static int ath6kl_set_host_app_area(struct ath6kl *ar)
95{
96 u32 address, data;
97 struct host_app_area host_app_area;
98
99 /* Fetch the address of the host_app_area_s
100 * instance in the host interest area */
101 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
Kevin Fang31024d92011-07-11 17:14:13 +0800102 address = TARG_VTOP(ar->target_type, address);
Kalle Valobdcd8172011-07-18 00:22:30 +0300103
Kalle Valoaddb44b2011-09-02 10:32:05 +0300104 if (ath6kl_diag_read32(ar, address, &data))
Kalle Valobdcd8172011-07-18 00:22:30 +0300105 return -EIO;
106
Kevin Fang31024d92011-07-11 17:14:13 +0800107 address = TARG_VTOP(ar->target_type, data);
Kalle Valocbf49a62011-10-05 12:23:17 +0300108 host_app_area.wmi_protocol_ver = cpu_to_le32(WMI_PROTOCOL_VERSION);
Kalle Valoaddb44b2011-09-02 10:32:05 +0300109 if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
110 sizeof(struct host_app_area)))
Kalle Valobdcd8172011-07-18 00:22:30 +0300111 return -EIO;
112
113 return 0;
114}
115
116static inline void set_ac2_ep_map(struct ath6kl *ar,
117 u8 ac,
118 enum htc_endpoint_id ep)
119{
120 ar->ac2ep_map[ac] = ep;
121 ar->ep2ac_map[ep] = ac;
122}
123
124/* connect to a service */
125static int ath6kl_connectservice(struct ath6kl *ar,
126 struct htc_service_connect_req *con_req,
127 char *desc)
128{
129 int status;
130 struct htc_service_connect_resp response;
131
132 memset(&response, 0, sizeof(response));
133
Kalle Vaload226ec2011-08-10 09:49:12 +0300134 status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
Kalle Valobdcd8172011-07-18 00:22:30 +0300135 if (status) {
136 ath6kl_err("failed to connect to %s service status:%d\n",
137 desc, status);
138 return status;
139 }
140
141 switch (con_req->svc_id) {
142 case WMI_CONTROL_SVC:
143 if (test_bit(WMI_ENABLED, &ar->flag))
144 ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
145 ar->ctrl_ep = response.endpoint;
146 break;
147 case WMI_DATA_BE_SVC:
148 set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
149 break;
150 case WMI_DATA_BK_SVC:
151 set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
152 break;
153 case WMI_DATA_VI_SVC:
154 set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
155 break;
156 case WMI_DATA_VO_SVC:
157 set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
158 break;
159 default:
160 ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
161 return -EINVAL;
162 }
163
164 return 0;
165}
166
167static int ath6kl_init_service_ep(struct ath6kl *ar)
168{
169 struct htc_service_connect_req connect;
170
171 memset(&connect, 0, sizeof(connect));
172
173 /* these fields are the same for all service endpoints */
174 connect.ep_cb.rx = ath6kl_rx;
175 connect.ep_cb.rx_refill = ath6kl_rx_refill;
176 connect.ep_cb.tx_full = ath6kl_tx_queue_full;
177
178 /*
179 * Set the max queue depth so that our ath6kl_tx_queue_full handler
180 * gets called.
181 */
182 connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
183 connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
184 if (!connect.ep_cb.rx_refill_thresh)
185 connect.ep_cb.rx_refill_thresh++;
186
187 /* connect to control service */
188 connect.svc_id = WMI_CONTROL_SVC;
189 if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
190 return -EIO;
191
192 connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
193
194 /*
195 * Limit the HTC message size on the send path, although e can
196 * receive A-MSDU frames of 4K, we will only send ethernet-sized
197 * (802.3) frames on the send path.
198 */
199 connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
200
201 /*
202 * To reduce the amount of committed memory for larger A_MSDU
203 * frames, use the recv-alloc threshold mechanism for larger
204 * packets.
205 */
206 connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
207 connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
208
209 /*
210 * For the remaining data services set the connection flag to
211 * reduce dribbling, if configured to do so.
212 */
213 connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
214 connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
215 connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
216
217 connect.svc_id = WMI_DATA_BE_SVC;
218
219 if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
220 return -EIO;
221
222 /* connect to back-ground map this to WMI LOW_PRI */
223 connect.svc_id = WMI_DATA_BK_SVC;
224 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
225 return -EIO;
226
227 /* connect to Video service, map this to to HI PRI */
228 connect.svc_id = WMI_DATA_VI_SVC;
229 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
230 return -EIO;
231
232 /*
233 * Connect to VO service, this is currently not mapped to a WMI
234 * priority stream due to historical reasons. WMI originally
235 * defined 3 priorities over 3 mailboxes We can change this when
236 * WMI is reworked so that priorities are not dependent on
237 * mailboxes.
238 */
239 connect.svc_id = WMI_DATA_VO_SVC;
240 if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
241 return -EIO;
242
243 return 0;
244}
245
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +0530246void ath6kl_init_control_info(struct ath6kl_vif *vif)
Kalle Valobdcd8172011-07-18 00:22:30 +0300247{
Vasanthakumar Thiagarajane29f25f2011-10-25 19:34:15 +0530248 ath6kl_init_profile_info(vif);
Vasanthakumar Thiagarajan34503342011-10-25 19:34:02 +0530249 vif->def_txkey_index = 0;
Vasanthakumar Thiagarajan6f2a73f2011-10-25 19:34:06 +0530250 memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
Vasanthakumar Thiagarajanf74bac52011-10-25 19:34:05 +0530251 vif->ch_hint = 0;
Kalle Valobdcd8172011-07-18 00:22:30 +0300252}
253
254/*
255 * Set HTC/Mbox operational parameters, this can only be called when the
256 * target is in the BMI phase.
257 */
258static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
259 u8 htc_ctrl_buf)
260{
261 int status;
262 u32 blk_size;
263
264 blk_size = ar->mbox_info.block_size;
265
266 if (htc_ctrl_buf)
267 blk_size |= ((u32)htc_ctrl_buf) << 16;
268
269 /* set the host interest area for the block size */
270 status = ath6kl_bmi_write(ar,
271 ath6kl_get_hi_item_addr(ar,
272 HI_ITEM(hi_mbox_io_block_sz)),
273 (u8 *)&blk_size,
274 4);
275 if (status) {
276 ath6kl_err("bmi_write_memory for IO block size failed\n");
277 goto out;
278 }
279
280 ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
281 blk_size,
282 ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));
283
284 if (mbox_isr_yield_val) {
285 /* set the host interest area for the mbox ISR yield limit */
286 status = ath6kl_bmi_write(ar,
287 ath6kl_get_hi_item_addr(ar,
288 HI_ITEM(hi_mbox_isr_yield_limit)),
289 (u8 *)&mbox_isr_yield_val,
290 4);
291 if (status) {
292 ath6kl_err("bmi_write_memory for yield limit failed\n");
293 goto out;
294 }
295 }
296
297out:
298 return status;
299}
300
301#define REG_DUMP_COUNT_AR6003 60
302#define REGISTER_DUMP_LEN_MAX 60
303
304static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
305{
306 u32 address;
307 u32 regdump_loc = 0;
308 int status;
309 u32 regdump_val[REGISTER_DUMP_LEN_MAX];
310 u32 i;
311
312 if (ar->target_type != TARGET_TYPE_AR6003)
313 return;
314
315 /* the reg dump pointer is copied to the host interest area */
316 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
Kevin Fang31024d92011-07-11 17:14:13 +0800317 address = TARG_VTOP(ar->target_type, address);
Kalle Valobdcd8172011-07-18 00:22:30 +0300318
319 /* read RAM location through diagnostic window */
Kalle Valoaddb44b2011-09-02 10:32:05 +0300320 status = ath6kl_diag_read32(ar, address, &regdump_loc);
Kalle Valobdcd8172011-07-18 00:22:30 +0300321
322 if (status || !regdump_loc) {
323 ath6kl_err("failed to get ptr to register dump area\n");
324 return;
325 }
326
327 ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
328 regdump_loc);
Kevin Fang31024d92011-07-11 17:14:13 +0800329 regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
Kalle Valobdcd8172011-07-18 00:22:30 +0300330
331 /* fetch register dump data */
Kalle Valoaddb44b2011-09-02 10:32:05 +0300332 status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
333 REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
Kalle Valobdcd8172011-07-18 00:22:30 +0300334
335 if (status) {
336 ath6kl_err("failed to get register dump\n");
337 return;
338 }
339 ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
340
341 for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
342 ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
343 i, regdump_val[i]);
344
345}
346
347void ath6kl_target_failure(struct ath6kl *ar)
348{
349 ath6kl_err("target asserted\n");
350
351 /* try dumping target assertion information (if any) */
352 ath6kl_dump_target_assert_info(ar);
353
354}
355
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530356static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
Kalle Valobdcd8172011-07-18 00:22:30 +0300357{
358 int status = 0;
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300359 int ret;
Kalle Valobdcd8172011-07-18 00:22:30 +0300360
361 /*
362 * Configure the device for rx dot11 header rules. "0,0" are the
363 * default values. Required if checksum offload is needed. Set
364 * RxMetaVersion to 2.
365 */
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530366 if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300367 ar->rx_meta_ver, 0, 0)) {
368 ath6kl_err("unable to set the rx frame format\n");
369 status = -EIO;
370 }
371
372 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530373 if ((ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
Kalle Valobdcd8172011-07-18 00:22:30 +0300374 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
375 ath6kl_err("unable to set power save fail event policy\n");
376 status = -EIO;
377 }
378
379 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530380 if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
Kalle Valobdcd8172011-07-18 00:22:30 +0300381 WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
382 ath6kl_err("unable to set barker preamble policy\n");
383 status = -EIO;
384 }
385
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530386 if (ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300387 WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
388 ath6kl_err("unable to set keep alive interval\n");
389 status = -EIO;
390 }
391
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530392 if (ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
Kalle Valobdcd8172011-07-18 00:22:30 +0300393 WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
394 ath6kl_err("unable to set disconnect timeout\n");
395 status = -EIO;
396 }
397
398 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530399 if (ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED)) {
Kalle Valobdcd8172011-07-18 00:22:30 +0300400 ath6kl_err("unable to set txop bursting\n");
401 status = -EIO;
402 }
403
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530404 /*
405 * FIXME: Make sure p2p configurations are not applied to
406 * non-p2p capable interfaces when multivif support is enabled.
407 */
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300408 if (ar->p2p) {
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530409 ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300410 P2P_FLAG_CAPABILITIES_REQ |
411 P2P_FLAG_MACADDR_REQ |
412 P2P_FLAG_HMODEL_REQ);
413 if (ret) {
414 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P "
415 "capabilities (%d) - assuming P2P not "
416 "supported\n", ret);
417 ar->p2p = 0;
418 }
419 }
420
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530421 /*
422 * FIXME: Make sure p2p configurations are not applied to
423 * non-p2p capable interfaces when multivif support is enabled.
424 */
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300425 if (ar->p2p) {
426 /* Enable Probe Request reporting for P2P */
Vasanthakumar Thiagarajan0ce59442011-10-25 19:34:25 +0530427 ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
Jouni Malinen6bbc7c32011-09-05 17:38:47 +0300428 if (ret) {
429 ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe "
430 "Request reporting (%d)\n", ret);
431 }
Jouni Malinen4dea08e2011-08-30 21:57:57 +0300432 }
433
Kalle Valobdcd8172011-07-18 00:22:30 +0300434 return status;
435}
436
437int ath6kl_configure_target(struct ath6kl *ar)
438{
439 u32 param, ram_reserved_size;
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530440 u8 fw_iftype, fw_mode = 0, fw_submode = 0;
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530441 int i;
Kalle Valobdcd8172011-07-18 00:22:30 +0300442
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530443 /*
444 * Note: Even though the firmware interface type is
445 * chosen as BSS_STA for all three interfaces, can
446 * be configured to IBSS/AP as long as the fw submode
447 * remains normal mode (0 - AP, STA and IBSS). But
448 * due to an target assert in firmware only one interface is
449 * configured for now.
450 */
Vasanthakumar Thiagarajandd3751f2011-10-25 19:33:59 +0530451 fw_iftype = HI_OPTION_FW_MODE_BSS_STA;
Kalle Valobdcd8172011-07-18 00:22:30 +0300452
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530453 for (i = 0; i < MAX_NUM_VIF; i++)
454 fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
455
456 /*
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530457 * By default, submodes :
458 * vif[0] - AP/STA/IBSS
459 * vif[1] - "P2P dev"/"P2P GO"/"P2P Client"
460 * vif[2] - "P2P dev"/"P2P GO"/"P2P Client"
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530461 */
Vasanthakumar Thiagarajan3226f68a2011-10-25 19:34:24 +0530462
463 for (i = 0; i < ar->max_norm_iface; i++)
464 fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
465 (i * HI_OPTION_FW_SUBMODE_BITS);
466
467 for (i = ar->max_norm_iface; i < MAX_NUM_VIF; i++)
468 fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
469 (i * HI_OPTION_FW_SUBMODE_BITS);
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530470
471 /*
472 * FIXME: This needs to be removed once the multivif
473 * support is enabled.
474 */
475 if (ar->p2p)
476 fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530477
Kalle Valobdcd8172011-07-18 00:22:30 +0300478 param = HTC_PROTOCOL_VERSION;
479 if (ath6kl_bmi_write(ar,
480 ath6kl_get_hi_item_addr(ar,
481 HI_ITEM(hi_app_host_interest)),
482 (u8 *)&param, 4) != 0) {
483 ath6kl_err("bmi_write_memory for htc version failed\n");
484 return -EIO;
485 }
486
487 /* set the firmware mode to STA/IBSS/AP */
488 param = 0;
489
490 if (ath6kl_bmi_read(ar,
491 ath6kl_get_hi_item_addr(ar,
492 HI_ITEM(hi_option_flag)),
493 (u8 *)&param, 4) != 0) {
494 ath6kl_err("bmi_read_memory for setting fwmode failed\n");
495 return -EIO;
496 }
497
Vasanthakumar Thiagarajan7b858322011-10-25 19:34:22 +0530498 param |= (MAX_NUM_VIF << HI_OPTION_NUM_DEV_SHIFT);
499 param |= fw_mode << HI_OPTION_FW_MODE_SHIFT;
500 param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT;
501
Kalle Valobdcd8172011-07-18 00:22:30 +0300502 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
503 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
504
505 if (ath6kl_bmi_write(ar,
506 ath6kl_get_hi_item_addr(ar,
507 HI_ITEM(hi_option_flag)),
508 (u8 *)&param,
509 4) != 0) {
510 ath6kl_err("bmi_write_memory for setting fwmode failed\n");
511 return -EIO;
512 }
513
514 ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
515
516 /*
517 * Hardcode the address use for the extended board data
518 * Ideally this should be pre-allocate by the OS at boot time
519 * But since it is a new feature and board data is loaded
520 * at init time, we have to workaround this from host.
521 * It is difficult to patch the firmware boot code,
522 * but possible in theory.
523 */
524
Kalle Valo991b27e2011-09-07 10:55:17 +0300525 param = ar->hw.board_ext_data_addr;
526 ram_reserved_size = ar->hw.reserved_ram_size;
Kalle Valobdcd8172011-07-18 00:22:30 +0300527
Kalle Valo991b27e2011-09-07 10:55:17 +0300528 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
529 HI_ITEM(hi_board_ext_data)),
530 (u8 *)&param, 4) != 0) {
531 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
532 return -EIO;
533 }
534
535 if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar,
536 HI_ITEM(hi_end_ram_reserve_sz)),
537 (u8 *)&ram_reserved_size, 4) != 0) {
538 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
539 return -EIO;
Kalle Valobdcd8172011-07-18 00:22:30 +0300540 }
541
542 /* set the block size for the target */
543 if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
544 /* use default number of control buffers */
545 return -EIO;
546
547 return 0;
548}
549
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +0530550void ath6kl_core_free(struct ath6kl *ar)
Kalle Valobdcd8172011-07-18 00:22:30 +0300551{
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +0530552 wiphy_free(ar->wiphy);
Kalle Valobdcd8172011-07-18 00:22:30 +0300553}
554
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530555void ath6kl_core_cleanup(struct ath6kl *ar)
Kalle Valobdcd8172011-07-18 00:22:30 +0300556{
Kalle Valob2e75692011-10-27 18:48:14 +0300557 ath6kl_hif_power_off(ar);
558
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530559 destroy_workqueue(ar->ath6kl_wq);
Kalle Valobdcd8172011-07-18 00:22:30 +0300560
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +0530561 if (ar->htc_target)
562 ath6kl_htc_cleanup(ar->htc_target);
563
564 ath6kl_cookie_cleanup(ar);
565
566 ath6kl_cleanup_amsdu_rxbufs(ar);
567
568 ath6kl_bmi_cleanup(ar);
569
570 ath6kl_debug_cleanup(ar);
571
572 kfree(ar->fw_board);
573 kfree(ar->fw_otp);
574 kfree(ar->fw);
575 kfree(ar->fw_patch);
576
577 ath6kl_deinit_ieee80211_hw(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +0300578}
579
580/* firmware upload */
Kalle Valobdcd8172011-07-18 00:22:30 +0300581static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
582 u8 **fw, size_t *fw_len)
583{
584 const struct firmware *fw_entry;
585 int ret;
586
587 ret = request_firmware(&fw_entry, filename, ar->dev);
588 if (ret)
589 return ret;
590
591 *fw_len = fw_entry->size;
592 *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
593
594 if (*fw == NULL)
595 ret = -ENOMEM;
596
597 release_firmware(fw_entry);
598
599 return ret;
600}
601
Sam Leffler92ecbff2011-09-07 10:55:16 +0300602#ifdef CONFIG_OF
603static const char *get_target_ver_dir(const struct ath6kl *ar)
604{
605 switch (ar->version.target_ver) {
606 case AR6003_REV1_VERSION:
607 return "ath6k/AR6003/hw1.0";
608 case AR6003_REV2_VERSION:
609 return "ath6k/AR6003/hw2.0";
610 case AR6003_REV3_VERSION:
611 return "ath6k/AR6003/hw2.1.1";
612 }
613 ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__,
614 ar->version.target_ver);
615 return NULL;
616}
617
618/*
619 * Check the device tree for a board-id and use it to construct
620 * the pathname to the firmware file. Used (for now) to find a
621 * fallback to the "bdata.bin" file--typically a symlink to the
622 * appropriate board-specific file.
623 */
624static bool check_device_tree(struct ath6kl *ar)
625{
626 static const char *board_id_prop = "atheros,board-id";
627 struct device_node *node;
628 char board_filename[64];
629 const char *board_id;
630 int ret;
631
632 for_each_compatible_node(node, NULL, "atheros,ath6kl") {
633 board_id = of_get_property(node, board_id_prop, NULL);
634 if (board_id == NULL) {
635 ath6kl_warn("No \"%s\" property on %s node.\n",
636 board_id_prop, node->name);
637 continue;
638 }
639 snprintf(board_filename, sizeof(board_filename),
640 "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id);
641
642 ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
643 &ar->fw_board_len);
644 if (ret) {
645 ath6kl_err("Failed to get DT board file %s: %d\n",
646 board_filename, ret);
647 continue;
648 }
649 return true;
650 }
651 return false;
652}
653#else
654static bool check_device_tree(struct ath6kl *ar)
655{
656 return false;
657}
658#endif /* CONFIG_OF */
659
Kalle Valobdcd8172011-07-18 00:22:30 +0300660static int ath6kl_fetch_board_file(struct ath6kl *ar)
661{
662 const char *filename;
663 int ret;
664
Kalle Valo772c31e2011-09-07 10:55:16 +0300665 if (ar->fw_board != NULL)
666 return 0;
667
Kalle Valobdcd8172011-07-18 00:22:30 +0300668 switch (ar->version.target_ver) {
669 case AR6003_REV2_VERSION:
670 filename = AR6003_REV2_BOARD_DATA_FILE;
671 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800672 case AR6004_REV1_VERSION:
673 filename = AR6004_REV1_BOARD_DATA_FILE;
674 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300675 default:
676 filename = AR6003_REV3_BOARD_DATA_FILE;
677 break;
678 }
679
680 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
681 &ar->fw_board_len);
682 if (ret == 0) {
683 /* managed to get proper board file */
684 return 0;
685 }
686
Sam Leffler92ecbff2011-09-07 10:55:16 +0300687 if (check_device_tree(ar)) {
688 /* got board file from device tree */
689 return 0;
690 }
691
Kalle Valobdcd8172011-07-18 00:22:30 +0300692 /* there was no proper board file, try to use default instead */
693 ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
694 filename, ret);
695
696 switch (ar->version.target_ver) {
697 case AR6003_REV2_VERSION:
698 filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
699 break;
Kevin Fang31024d92011-07-11 17:14:13 +0800700 case AR6004_REV1_VERSION:
701 filename = AR6004_REV1_DEFAULT_BOARD_DATA_FILE;
702 break;
Kalle Valobdcd8172011-07-18 00:22:30 +0300703 default:
704 filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
705 break;
706 }
707
708 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
709 &ar->fw_board_len);
710 if (ret) {
711 ath6kl_err("Failed to get default board file %s: %d\n",
712 filename, ret);
713 return ret;
714 }
715
716 ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
717 ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
718
719 return 0;
720}
721
Kalle Valo772c31e2011-09-07 10:55:16 +0300722static int ath6kl_fetch_otp_file(struct ath6kl *ar)
723{
724 const char *filename;
725 int ret;
726
727 if (ar->fw_otp != NULL)
728 return 0;
729
730 switch (ar->version.target_ver) {
731 case AR6003_REV2_VERSION:
732 filename = AR6003_REV2_OTP_FILE;
733 break;
734 case AR6004_REV1_VERSION:
735 ath6kl_dbg(ATH6KL_DBG_TRC, "AR6004 doesn't need OTP file\n");
736 return 0;
737 break;
738 default:
739 filename = AR6003_REV3_OTP_FILE;
740 break;
741 }
742
743 ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
744 &ar->fw_otp_len);
745 if (ret) {
746 ath6kl_err("Failed to get OTP file %s: %d\n",
747 filename, ret);
748 return ret;
749 }
750
751 return 0;
752}
753
754static int ath6kl_fetch_fw_file(struct ath6kl *ar)
755{
756 const char *filename;
757 int ret;
758
759 if (ar->fw != NULL)
760 return 0;
761
762 if (testmode) {
763 switch (ar->version.target_ver) {
764 case AR6003_REV2_VERSION:
765 filename = AR6003_REV2_TCMD_FIRMWARE_FILE;
766 break;
767 case AR6003_REV3_VERSION:
768 filename = AR6003_REV3_TCMD_FIRMWARE_FILE;
769 break;
770 case AR6004_REV1_VERSION:
771 ath6kl_warn("testmode not supported with ar6004\n");
772 return -EOPNOTSUPP;
773 default:
774 ath6kl_warn("unknown target version: 0x%x\n",
775 ar->version.target_ver);
776 return -EINVAL;
777 }
778
779 set_bit(TESTMODE, &ar->flag);
780
781 goto get_fw;
782 }
783
784 switch (ar->version.target_ver) {
785 case AR6003_REV2_VERSION:
786 filename = AR6003_REV2_FIRMWARE_FILE;
787 break;
788 case AR6004_REV1_VERSION:
789 filename = AR6004_REV1_FIRMWARE_FILE;
790 break;
791 default:
792 filename = AR6003_REV3_FIRMWARE_FILE;
793 break;
794 }
795
796get_fw:
797 ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
798 if (ret) {
799 ath6kl_err("Failed to get firmware file %s: %d\n",
800 filename, ret);
801 return ret;
802 }
803
804 return 0;
805}
806
807static int ath6kl_fetch_patch_file(struct ath6kl *ar)
808{
809 const char *filename;
810 int ret;
811
812 switch (ar->version.target_ver) {
813 case AR6003_REV2_VERSION:
814 filename = AR6003_REV2_PATCH_FILE;
815 break;
816 case AR6004_REV1_VERSION:
817 /* FIXME: implement for AR6004 */
818 return 0;
819 break;
820 default:
821 filename = AR6003_REV3_PATCH_FILE;
822 break;
823 }
824
825 if (ar->fw_patch == NULL) {
826 ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
827 &ar->fw_patch_len);
828 if (ret) {
829 ath6kl_err("Failed to get patch file %s: %d\n",
830 filename, ret);
831 return ret;
832 }
833 }
834
835 return 0;
836}
837
Kalle Valo50d41232011-09-07 10:55:17 +0300838static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
Kalle Valo772c31e2011-09-07 10:55:16 +0300839{
840 int ret;
841
Kalle Valo772c31e2011-09-07 10:55:16 +0300842 ret = ath6kl_fetch_otp_file(ar);
843 if (ret)
844 return ret;
845
846 ret = ath6kl_fetch_fw_file(ar);
847 if (ret)
848 return ret;
849
850 ret = ath6kl_fetch_patch_file(ar);
851 if (ret)
852 return ret;
853
854 return 0;
855}
Kalle Valobdcd8172011-07-18 00:22:30 +0300856
Kalle Valo50d41232011-09-07 10:55:17 +0300857static int ath6kl_fetch_fw_api2(struct ath6kl *ar)
858{
859 size_t magic_len, len, ie_len;
860 const struct firmware *fw;
861 struct ath6kl_fw_ie *hdr;
862 const char *filename;
863 const u8 *data;
Kalle Valo97e04962011-09-12 13:47:34 +0300864 int ret, ie_id, i, index, bit;
Kalle Valo8a137482011-09-07 10:55:17 +0300865 __le32 *val;
Kalle Valo50d41232011-09-07 10:55:17 +0300866
867 switch (ar->version.target_ver) {
868 case AR6003_REV2_VERSION:
869 filename = AR6003_REV2_FIRMWARE_2_FILE;
870 break;
871 case AR6003_REV3_VERSION:
872 filename = AR6003_REV3_FIRMWARE_2_FILE;
873 break;
874 case AR6004_REV1_VERSION:
875 filename = AR6004_REV1_FIRMWARE_2_FILE;
876 break;
877 default:
878 return -EOPNOTSUPP;
879 }
880
881 ret = request_firmware(&fw, filename, ar->dev);
882 if (ret)
883 return ret;
884
885 data = fw->data;
886 len = fw->size;
887
888 /* magic also includes the null byte, check that as well */
889 magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
890
891 if (len < magic_len) {
892 ret = -EINVAL;
893 goto out;
894 }
895
896 if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
897 ret = -EINVAL;
898 goto out;
899 }
900
901 len -= magic_len;
902 data += magic_len;
903
904 /* loop elements */
905 while (len > sizeof(struct ath6kl_fw_ie)) {
906 /* hdr is unaligned! */
907 hdr = (struct ath6kl_fw_ie *) data;
908
909 ie_id = le32_to_cpup(&hdr->id);
910 ie_len = le32_to_cpup(&hdr->len);
911
912 len -= sizeof(*hdr);
913 data += sizeof(*hdr);
914
915 if (len < ie_len) {
916 ret = -EINVAL;
917 goto out;
918 }
919
920 switch (ie_id) {
921 case ATH6KL_FW_IE_OTP_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300922 ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300923 ie_len);
924
Kalle Valo50d41232011-09-07 10:55:17 +0300925 ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
926
927 if (ar->fw_otp == NULL) {
928 ret = -ENOMEM;
929 goto out;
930 }
931
932 ar->fw_otp_len = ie_len;
933 break;
934 case ATH6KL_FW_IE_FW_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300935 ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300936 ie_len);
937
Kalle Valo50d41232011-09-07 10:55:17 +0300938 ar->fw = kmemdup(data, ie_len, GFP_KERNEL);
939
940 if (ar->fw == NULL) {
941 ret = -ENOMEM;
942 goto out;
943 }
944
945 ar->fw_len = ie_len;
946 break;
947 case ATH6KL_FW_IE_PATCH_IMAGE:
Kalle Valoef548622011-10-01 09:43:09 +0300948 ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300949 ie_len);
950
Kalle Valo50d41232011-09-07 10:55:17 +0300951 ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
952
953 if (ar->fw_patch == NULL) {
954 ret = -ENOMEM;
955 goto out;
956 }
957
958 ar->fw_patch_len = ie_len;
959 break;
Kalle Valo8a137482011-09-07 10:55:17 +0300960 case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
961 val = (__le32 *) data;
962 ar->hw.reserved_ram_size = le32_to_cpup(val);
Kalle Valo6bc36432011-09-27 14:31:11 +0300963
964 ath6kl_dbg(ATH6KL_DBG_BOOT,
965 "found reserved ram size ie 0x%d\n",
966 ar->hw.reserved_ram_size);
Kalle Valo8a137482011-09-07 10:55:17 +0300967 break;
Kalle Valo97e04962011-09-12 13:47:34 +0300968 case ATH6KL_FW_IE_CAPABILITIES:
Kalle Valo6bc36432011-09-27 14:31:11 +0300969 ath6kl_dbg(ATH6KL_DBG_BOOT,
Kalle Valoef548622011-10-01 09:43:09 +0300970 "found firmware capabilities ie (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +0300971 ie_len);
972
Kalle Valo97e04962011-09-12 13:47:34 +0300973 for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
974 index = ALIGN(i, 8) / 8;
975 bit = i % 8;
976
977 if (data[index] & (1 << bit))
978 __set_bit(i, ar->fw_capabilities);
979 }
Kalle Valo6bc36432011-09-27 14:31:11 +0300980
981 ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "",
982 ar->fw_capabilities,
983 sizeof(ar->fw_capabilities));
Kalle Valo97e04962011-09-12 13:47:34 +0300984 break;
Kalle Valo1b4304d2011-09-27 11:05:26 +0300985 case ATH6KL_FW_IE_PATCH_ADDR:
986 if (ie_len != sizeof(*val))
987 break;
988
989 val = (__le32 *) data;
990 ar->hw.dataset_patch_addr = le32_to_cpup(val);
Kalle Valo6bc36432011-09-27 14:31:11 +0300991
992 ath6kl_dbg(ATH6KL_DBG_BOOT,
993 "found patch address ie 0x%d\n",
994 ar->hw.dataset_patch_addr);
Kalle Valo1b4304d2011-09-27 11:05:26 +0300995 break;
Kalle Valo50d41232011-09-07 10:55:17 +0300996 default:
Kalle Valo6bc36432011-09-27 14:31:11 +0300997 ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n",
Kalle Valo50d41232011-09-07 10:55:17 +0300998 le32_to_cpup(&hdr->id));
999 break;
1000 }
1001
1002 len -= ie_len;
1003 data += ie_len;
1004 };
1005
1006 ret = 0;
1007out:
1008 release_firmware(fw);
1009
1010 return ret;
1011}
1012
1013static int ath6kl_fetch_firmwares(struct ath6kl *ar)
1014{
1015 int ret;
1016
1017 ret = ath6kl_fetch_board_file(ar);
1018 if (ret)
1019 return ret;
1020
1021 ret = ath6kl_fetch_fw_api2(ar);
Kalle Valo6bc36432011-09-27 14:31:11 +03001022 if (ret == 0) {
1023 ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n");
Kalle Valo50d41232011-09-07 10:55:17 +03001024 return 0;
Kalle Valo6bc36432011-09-27 14:31:11 +03001025 }
Kalle Valo50d41232011-09-07 10:55:17 +03001026
1027 ret = ath6kl_fetch_fw_api1(ar);
1028 if (ret)
1029 return ret;
1030
Kalle Valo6bc36432011-09-27 14:31:11 +03001031 ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n");
1032
Kalle Valo50d41232011-09-07 10:55:17 +03001033 return 0;
1034}
1035
Kalle Valobdcd8172011-07-18 00:22:30 +03001036static int ath6kl_upload_board_file(struct ath6kl *ar)
1037{
1038 u32 board_address, board_ext_address, param;
Kevin Fang31024d92011-07-11 17:14:13 +08001039 u32 board_data_size, board_ext_data_size;
Kalle Valobdcd8172011-07-18 00:22:30 +03001040 int ret;
1041
Kalle Valo772c31e2011-09-07 10:55:16 +03001042 if (WARN_ON(ar->fw_board == NULL))
1043 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001044
Kevin Fang31024d92011-07-11 17:14:13 +08001045 /*
1046 * Determine where in Target RAM to write Board Data.
1047 * For AR6004, host determine Target RAM address for
1048 * writing board data.
1049 */
1050 if (ar->target_type == TARGET_TYPE_AR6004) {
1051 board_address = AR6004_REV1_BOARD_DATA_ADDRESS;
1052 ath6kl_bmi_write(ar,
1053 ath6kl_get_hi_item_addr(ar,
1054 HI_ITEM(hi_board_data)),
1055 (u8 *) &board_address, 4);
1056 } else {
1057 ath6kl_bmi_read(ar,
1058 ath6kl_get_hi_item_addr(ar,
1059 HI_ITEM(hi_board_data)),
1060 (u8 *) &board_address, 4);
1061 }
1062
Kalle Valobdcd8172011-07-18 00:22:30 +03001063 /* determine where in target ram to write extended board data */
1064 ath6kl_bmi_read(ar,
1065 ath6kl_get_hi_item_addr(ar,
1066 HI_ITEM(hi_board_ext_data)),
1067 (u8 *) &board_ext_address, 4);
1068
Kalle Valobdcd8172011-07-18 00:22:30 +03001069 if (board_ext_address == 0) {
1070 ath6kl_err("Failed to get board file target address.\n");
1071 return -EINVAL;
1072 }
1073
Kevin Fang31024d92011-07-11 17:14:13 +08001074 switch (ar->target_type) {
1075 case TARGET_TYPE_AR6003:
1076 board_data_size = AR6003_BOARD_DATA_SZ;
1077 board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1078 break;
1079 case TARGET_TYPE_AR6004:
1080 board_data_size = AR6004_BOARD_DATA_SZ;
1081 board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1082 break;
1083 default:
1084 WARN_ON(1);
1085 return -EINVAL;
1086 break;
1087 }
1088
1089 if (ar->fw_board_len == (board_data_size +
1090 board_ext_data_size)) {
1091
Kalle Valobdcd8172011-07-18 00:22:30 +03001092 /* write extended board data */
Kalle Valo6bc36432011-09-27 14:31:11 +03001093 ath6kl_dbg(ATH6KL_DBG_BOOT,
1094 "writing extended board data to 0x%x (%d B)\n",
1095 board_ext_address, board_ext_data_size);
1096
Kalle Valobdcd8172011-07-18 00:22:30 +03001097 ret = ath6kl_bmi_write(ar, board_ext_address,
Kevin Fang31024d92011-07-11 17:14:13 +08001098 ar->fw_board + board_data_size,
1099 board_ext_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001100 if (ret) {
1101 ath6kl_err("Failed to write extended board data: %d\n",
1102 ret);
1103 return ret;
1104 }
1105
1106 /* record that extended board data is initialized */
Kevin Fang31024d92011-07-11 17:14:13 +08001107 param = (board_ext_data_size << 16) | 1;
1108
Kalle Valobdcd8172011-07-18 00:22:30 +03001109 ath6kl_bmi_write(ar,
1110 ath6kl_get_hi_item_addr(ar,
1111 HI_ITEM(hi_board_ext_data_config)),
1112 (unsigned char *) &param, 4);
1113 }
1114
Kevin Fang31024d92011-07-11 17:14:13 +08001115 if (ar->fw_board_len < board_data_size) {
Kalle Valobdcd8172011-07-18 00:22:30 +03001116 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1117 ret = -EINVAL;
1118 return ret;
1119 }
1120
Kalle Valo6bc36432011-09-27 14:31:11 +03001121 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n",
1122 board_address, board_data_size);
1123
Kalle Valobdcd8172011-07-18 00:22:30 +03001124 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
Kevin Fang31024d92011-07-11 17:14:13 +08001125 board_data_size);
Kalle Valobdcd8172011-07-18 00:22:30 +03001126
1127 if (ret) {
1128 ath6kl_err("Board file bmi write failed: %d\n", ret);
1129 return ret;
1130 }
1131
1132 /* record the fact that Board Data IS initialized */
1133 param = 1;
1134 ath6kl_bmi_write(ar,
1135 ath6kl_get_hi_item_addr(ar,
1136 HI_ITEM(hi_board_data_initialized)),
1137 (u8 *)&param, 4);
1138
1139 return ret;
1140}
1141
1142static int ath6kl_upload_otp(struct ath6kl *ar)
1143{
Kalle Valobdcd8172011-07-18 00:22:30 +03001144 u32 address, param;
Kalle Valobef26a72011-10-12 09:58:28 +03001145 bool from_hw = false;
Kalle Valobdcd8172011-07-18 00:22:30 +03001146 int ret;
1147
Kalle Valo772c31e2011-09-07 10:55:16 +03001148 if (WARN_ON(ar->fw_otp == NULL))
1149 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001150
Kalle Valoa01ac412011-09-07 10:55:17 +03001151 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001152
Kalle Valoef548622011-10-01 09:43:09 +03001153 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address,
Kalle Valo6bc36432011-09-27 14:31:11 +03001154 ar->fw_otp_len);
1155
Kalle Valobdcd8172011-07-18 00:22:30 +03001156 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1157 ar->fw_otp_len);
1158 if (ret) {
1159 ath6kl_err("Failed to upload OTP file: %d\n", ret);
1160 return ret;
1161 }
1162
Kalle Valo639d0b82011-09-12 12:48:09 +03001163 /* read firmware start address */
1164 ret = ath6kl_bmi_read(ar,
1165 ath6kl_get_hi_item_addr(ar,
1166 HI_ITEM(hi_app_start)),
1167 (u8 *) &address, sizeof(address));
1168
1169 if (ret) {
1170 ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1171 return ret;
1172 }
1173
Kalle Valobef26a72011-10-12 09:58:28 +03001174 if (ar->hw.app_start_override_addr == 0) {
1175 ar->hw.app_start_override_addr = address;
1176 from_hw = true;
1177 }
Kalle Valo639d0b82011-09-12 12:48:09 +03001178
Kalle Valobef26a72011-10-12 09:58:28 +03001179 ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr%s 0x%x\n",
1180 from_hw ? " (from hw)" : "",
Kalle Valo6bc36432011-09-27 14:31:11 +03001181 ar->hw.app_start_override_addr);
1182
Kalle Valobdcd8172011-07-18 00:22:30 +03001183 /* execute the OTP code */
Kalle Valobef26a72011-10-12 09:58:28 +03001184 ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n",
1185 ar->hw.app_start_override_addr);
Kalle Valobdcd8172011-07-18 00:22:30 +03001186 param = 0;
Kalle Valobef26a72011-10-12 09:58:28 +03001187 ath6kl_bmi_execute(ar, ar->hw.app_start_override_addr, &param);
Kalle Valobdcd8172011-07-18 00:22:30 +03001188
1189 return ret;
1190}
1191
1192static int ath6kl_upload_firmware(struct ath6kl *ar)
1193{
Kalle Valobdcd8172011-07-18 00:22:30 +03001194 u32 address;
1195 int ret;
1196
Kalle Valo772c31e2011-09-07 10:55:16 +03001197 if (WARN_ON(ar->fw == NULL))
1198 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001199
Kalle Valoa01ac412011-09-07 10:55:17 +03001200 address = ar->hw.app_load_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001201
Kalle Valoef548622011-10-01 09:43:09 +03001202 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +03001203 address, ar->fw_len);
1204
Kalle Valobdcd8172011-07-18 00:22:30 +03001205 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1206
1207 if (ret) {
1208 ath6kl_err("Failed to write firmware: %d\n", ret);
1209 return ret;
1210 }
1211
Kevin Fang31024d92011-07-11 17:14:13 +08001212 /*
1213 * Set starting address for firmware
1214 * Don't need to setup app_start override addr on AR6004
1215 */
1216 if (ar->target_type != TARGET_TYPE_AR6004) {
Kalle Valoa01ac412011-09-07 10:55:17 +03001217 address = ar->hw.app_start_override_addr;
Kevin Fang31024d92011-07-11 17:14:13 +08001218 ath6kl_bmi_set_app_start(ar, address);
1219 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001220 return ret;
1221}
1222
1223static int ath6kl_upload_patch(struct ath6kl *ar)
1224{
Kalle Valobdcd8172011-07-18 00:22:30 +03001225 u32 address, param;
1226 int ret;
1227
Kalle Valo772c31e2011-09-07 10:55:16 +03001228 if (WARN_ON(ar->fw_patch == NULL))
1229 return -ENOENT;
Kalle Valobdcd8172011-07-18 00:22:30 +03001230
Kalle Valoa01ac412011-09-07 10:55:17 +03001231 address = ar->hw.dataset_patch_addr;
Kalle Valobdcd8172011-07-18 00:22:30 +03001232
Kalle Valoef548622011-10-01 09:43:09 +03001233 ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n",
Kalle Valo6bc36432011-09-27 14:31:11 +03001234 address, ar->fw_patch_len);
1235
Kalle Valobdcd8172011-07-18 00:22:30 +03001236 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1237 if (ret) {
1238 ath6kl_err("Failed to write patch file: %d\n", ret);
1239 return ret;
1240 }
1241
1242 param = address;
1243 ath6kl_bmi_write(ar,
1244 ath6kl_get_hi_item_addr(ar,
1245 HI_ITEM(hi_dset_list_head)),
1246 (unsigned char *) &param, 4);
1247
1248 return 0;
1249}
1250
1251static int ath6kl_init_upload(struct ath6kl *ar)
1252{
1253 u32 param, options, sleep, address;
1254 int status = 0;
1255
Kevin Fang31024d92011-07-11 17:14:13 +08001256 if (ar->target_type != TARGET_TYPE_AR6003 &&
1257 ar->target_type != TARGET_TYPE_AR6004)
Kalle Valobdcd8172011-07-18 00:22:30 +03001258 return -EINVAL;
1259
1260 /* temporarily disable system sleep */
1261 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1262 status = ath6kl_bmi_reg_read(ar, address, &param);
1263 if (status)
1264 return status;
1265
1266 options = param;
1267
1268 param |= ATH6KL_OPTION_SLEEP_DISABLE;
1269 status = ath6kl_bmi_reg_write(ar, address, param);
1270 if (status)
1271 return status;
1272
1273 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1274 status = ath6kl_bmi_reg_read(ar, address, &param);
1275 if (status)
1276 return status;
1277
1278 sleep = param;
1279
1280 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1281 status = ath6kl_bmi_reg_write(ar, address, param);
1282 if (status)
1283 return status;
1284
1285 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1286 options, sleep);
1287
1288 /* program analog PLL register */
Kevin Fang31024d92011-07-11 17:14:13 +08001289 /* no need to control 40/44MHz clock on AR6004 */
1290 if (ar->target_type != TARGET_TYPE_AR6004) {
1291 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1292 0xF9104001);
Kalle Valobdcd8172011-07-18 00:22:30 +03001293
Kevin Fang31024d92011-07-11 17:14:13 +08001294 if (status)
1295 return status;
Kalle Valobdcd8172011-07-18 00:22:30 +03001296
Kevin Fang31024d92011-07-11 17:14:13 +08001297 /* Run at 80/88MHz by default */
1298 param = SM(CPU_CLOCK_STANDARD, 1);
1299
1300 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1301 status = ath6kl_bmi_reg_write(ar, address, param);
1302 if (status)
1303 return status;
1304 }
Kalle Valobdcd8172011-07-18 00:22:30 +03001305
1306 param = 0;
1307 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1308 param = SM(LPO_CAL_ENABLE, 1);
1309 status = ath6kl_bmi_reg_write(ar, address, param);
1310 if (status)
1311 return status;
1312
1313 /* WAR to avoid SDIO CRC err */
1314 if (ar->version.target_ver == AR6003_REV2_VERSION) {
1315 ath6kl_err("temporary war to avoid sdio crc error\n");
1316
1317 param = 0x20;
1318
1319 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1320 status = ath6kl_bmi_reg_write(ar, address, param);
1321 if (status)
1322 return status;
1323
1324 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1325 status = ath6kl_bmi_reg_write(ar, address, param);
1326 if (status)
1327 return status;
1328
1329 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1330 status = ath6kl_bmi_reg_write(ar, address, param);
1331 if (status)
1332 return status;
1333
1334 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1335 status = ath6kl_bmi_reg_write(ar, address, param);
1336 if (status)
1337 return status;
1338 }
1339
1340 /* write EEPROM data to Target RAM */
1341 status = ath6kl_upload_board_file(ar);
1342 if (status)
1343 return status;
1344
1345 /* transfer One time Programmable data */
1346 status = ath6kl_upload_otp(ar);
1347 if (status)
1348 return status;
1349
1350 /* Download Target firmware */
1351 status = ath6kl_upload_firmware(ar);
1352 if (status)
1353 return status;
1354
1355 status = ath6kl_upload_patch(ar);
1356 if (status)
1357 return status;
1358
1359 /* Restore system sleep */
1360 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1361 status = ath6kl_bmi_reg_write(ar, address, sleep);
1362 if (status)
1363 return status;
1364
1365 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1366 param = options | 0x20;
1367 status = ath6kl_bmi_reg_write(ar, address, param);
1368 if (status)
1369 return status;
1370
1371 /* Configure GPIO AR6003 UART */
1372 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1373 status = ath6kl_bmi_write(ar,
1374 ath6kl_get_hi_item_addr(ar,
1375 HI_ITEM(hi_dbg_uart_txpin)),
1376 (u8 *)&param, 4);
1377
1378 return status;
1379}
1380
Kalle Valoa01ac412011-09-07 10:55:17 +03001381static int ath6kl_init_hw_params(struct ath6kl *ar)
1382{
1383 switch (ar->version.target_ver) {
1384 case AR6003_REV2_VERSION:
1385 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1386 ar->hw.app_load_addr = AR6003_REV2_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001387 ar->hw.board_ext_data_addr = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
1388 ar->hw.reserved_ram_size = AR6003_REV2_RAM_RESERVE_SIZE;
Kalle Valobef26a72011-10-12 09:58:28 +03001389
1390 /* hw2.0 needs override address hardcoded */
1391 ar->hw.app_start_override_addr = 0x944C00;
1392
Kalle Valoa01ac412011-09-07 10:55:17 +03001393 break;
1394 case AR6003_REV3_VERSION:
1395 ar->hw.dataset_patch_addr = AR6003_REV3_DATASET_PATCH_ADDRESS;
1396 ar->hw.app_load_addr = 0x1234;
Kalle Valo991b27e2011-09-07 10:55:17 +03001397 ar->hw.board_ext_data_addr = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
1398 ar->hw.reserved_ram_size = AR6003_REV3_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001399 break;
1400 case AR6004_REV1_VERSION:
1401 ar->hw.dataset_patch_addr = AR6003_REV2_DATASET_PATCH_ADDRESS;
1402 ar->hw.app_load_addr = AR6003_REV3_APP_LOAD_ADDRESS;
Kalle Valo991b27e2011-09-07 10:55:17 +03001403 ar->hw.board_ext_data_addr = AR6004_REV1_BOARD_EXT_DATA_ADDRESS;
1404 ar->hw.reserved_ram_size = AR6004_REV1_RAM_RESERVE_SIZE;
Kalle Valoa01ac412011-09-07 10:55:17 +03001405 break;
1406 default:
1407 ath6kl_err("Unsupported hardware version: 0x%x\n",
1408 ar->version.target_ver);
1409 return -EINVAL;
1410 }
1411
Kalle Valo6bc36432011-09-27 14:31:11 +03001412 ath6kl_dbg(ATH6KL_DBG_BOOT,
1413 "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n",
1414 ar->version.target_ver, ar->target_type,
1415 ar->hw.dataset_patch_addr, ar->hw.app_load_addr);
1416 ath6kl_dbg(ATH6KL_DBG_BOOT,
1417 "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x",
1418 ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr,
1419 ar->hw.reserved_ram_size);
1420
Kalle Valoa01ac412011-09-07 10:55:17 +03001421 return 0;
1422}
1423
Kalle Valo20459ee2011-10-27 18:48:37 +03001424static int ath6kl_hw_start(struct ath6kl *ar)
1425{
1426 long timeleft;
1427 int ret, i;
1428
1429 ret = ath6kl_hif_power_on(ar);
1430 if (ret)
1431 return ret;
1432
1433 ret = ath6kl_configure_target(ar);
1434 if (ret)
1435 goto err_power_off;
1436
1437 ret = ath6kl_init_upload(ar);
1438 if (ret)
1439 goto err_power_off;
1440
1441 /* Do we need to finish the BMI phase */
1442 /* FIXME: return error from ath6kl_bmi_done() */
1443 if (ath6kl_bmi_done(ar)) {
1444 ret = -EIO;
1445 goto err_power_off;
1446 }
1447
1448 /*
1449 * The reason we have to wait for the target here is that the
1450 * driver layer has to init BMI in order to set the host block
1451 * size.
1452 */
1453 if (ath6kl_htc_wait_target(ar->htc_target)) {
1454 ret = -EIO;
1455 goto err_power_off;
1456 }
1457
1458 if (ath6kl_init_service_ep(ar)) {
1459 ret = -EIO;
1460 goto err_cleanup_scatter;
1461 }
1462
1463 /* setup credit distribution */
1464 ath6kl_credit_setup(ar->htc_target, &ar->credit_state_info);
1465
1466 /* start HTC */
1467 ret = ath6kl_htc_start(ar->htc_target);
1468 if (ret) {
1469 /* FIXME: call this */
1470 ath6kl_cookie_cleanup(ar);
1471 goto err_cleanup_scatter;
1472 }
1473
1474 /* Wait for Wmi event to be ready */
1475 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1476 test_bit(WMI_READY,
1477 &ar->flag),
1478 WMI_TIMEOUT);
1479
1480 ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n");
1481
1482 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1483 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1484 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1485 ret = -EIO;
1486 goto err_htc_stop;
1487 }
1488
1489 if (!timeleft || signal_pending(current)) {
1490 ath6kl_err("wmi is not ready or wait was interrupted\n");
1491 ret = -EIO;
1492 goto err_htc_stop;
1493 }
1494
1495 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1496
1497 /* communicate the wmi protocol verision to the target */
1498 /* FIXME: return error */
1499 if ((ath6kl_set_host_app_area(ar)) != 0)
1500 ath6kl_err("unable to set the host app area\n");
1501
1502 for (i = 0; i < MAX_NUM_VIF; i++) {
1503 ret = ath6kl_target_config_wlan_params(ar, i);
1504 if (ret)
1505 goto err_htc_stop;
1506 }
1507
1508 return 0;
1509
1510err_htc_stop:
1511 ath6kl_htc_stop(ar->htc_target);
1512err_cleanup_scatter:
1513 ath6kl_hif_cleanup_scatter(ar);
1514err_power_off:
1515 ath6kl_hif_power_off(ar);
1516
1517 return ret;
1518}
1519
Kalle Valobdcd8172011-07-18 00:22:30 +03001520int ath6kl_core_init(struct ath6kl *ar)
1521{
Kalle Valobdcd8172011-07-18 00:22:30 +03001522 struct ath6kl_bmi_target_info targ_info;
Kalle Valo61448a92011-10-27 18:48:29 +03001523 struct net_device *ndev;
Kalle Valo20459ee2011-10-27 18:48:37 +03001524 int ret = 0, i;
Kalle Valobdcd8172011-07-18 00:22:30 +03001525
1526 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1527 if (!ar->ath6kl_wq)
1528 return -ENOMEM;
1529
1530 ret = ath6kl_bmi_init(ar);
1531 if (ret)
1532 goto err_wq;
1533
Kalle Valo20459ee2011-10-27 18:48:37 +03001534 /*
1535 * Turn on power to get hardware (target) version and leave power
1536 * on delibrately as we will boot the hardware anyway within few
1537 * seconds.
1538 */
Kalle Valob2e75692011-10-27 18:48:14 +03001539 ret = ath6kl_hif_power_on(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001540 if (ret)
1541 goto err_bmi_cleanup;
1542
Kalle Valob2e75692011-10-27 18:48:14 +03001543 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1544 if (ret)
1545 goto err_power_off;
1546
Kalle Valobdcd8172011-07-18 00:22:30 +03001547 ar->version.target_ver = le32_to_cpu(targ_info.version);
1548 ar->target_type = le32_to_cpu(targ_info.type);
Vasanthakumar Thiagarajanbe98e3a2011-10-25 19:33:57 +05301549 ar->wiphy->hw_version = le32_to_cpu(targ_info.version);
Kalle Valobdcd8172011-07-18 00:22:30 +03001550
Kalle Valoa01ac412011-09-07 10:55:17 +03001551 ret = ath6kl_init_hw_params(ar);
1552 if (ret)
Kalle Valob2e75692011-10-27 18:48:14 +03001553 goto err_power_off;
Kalle Valoa01ac412011-09-07 10:55:17 +03001554
Kalle Vaload226ec2011-08-10 09:49:12 +03001555 ar->htc_target = ath6kl_htc_create(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001556
1557 if (!ar->htc_target) {
1558 ret = -ENOMEM;
Kalle Valob2e75692011-10-27 18:48:14 +03001559 goto err_power_off;
Kalle Valobdcd8172011-07-18 00:22:30 +03001560 }
1561
Kalle Valo772c31e2011-09-07 10:55:16 +03001562 ret = ath6kl_fetch_firmwares(ar);
1563 if (ret)
1564 goto err_htc_cleanup;
1565
Kalle Valo61448a92011-10-27 18:48:29 +03001566 /* FIXME: we should free all firmwares in the error cases below */
1567
Kalle Valo61448a92011-10-27 18:48:29 +03001568 /* Indicate that WMI is enabled (although not ready yet) */
1569 set_bit(WMI_ENABLED, &ar->flag);
1570 ar->wmi = ath6kl_wmi_init(ar);
1571 if (!ar->wmi) {
1572 ath6kl_err("failed to initialize wmi\n");
1573 ret = -EIO;
1574 goto err_htc_cleanup;
1575 }
1576
1577 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1578
1579 ret = ath6kl_register_ieee80211_hw(ar);
1580 if (ret)
1581 goto err_node_cleanup;
1582
1583 ret = ath6kl_debug_init(ar);
1584 if (ret) {
1585 wiphy_unregister(ar->wiphy);
1586 goto err_node_cleanup;
1587 }
1588
1589 for (i = 0; i < MAX_NUM_VIF; i++)
1590 ar->avail_idx_map |= BIT(i);
1591
1592 rtnl_lock();
1593
1594 /* Add an initial station interface */
1595 ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
1596 INFRA_NETWORK);
1597
1598 rtnl_unlock();
1599
1600 if (!ndev) {
1601 ath6kl_err("Failed to instantiate a network device\n");
1602 ret = -ENOMEM;
1603 wiphy_unregister(ar->wiphy);
1604 goto err_debug_init;
1605 }
1606
1607
1608 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1609 __func__, ndev->name, ndev, ar);
1610
Kalle Valo61448a92011-10-27 18:48:29 +03001611 /* setup access class priority mappings */
1612 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1613 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1614 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1615 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1616
1617 /* give our connected endpoints some buffers */
1618 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1619 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1620
1621 /* allocate some buffers that handle larger AMSDU frames */
1622 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1623
Kalle Valo61448a92011-10-27 18:48:29 +03001624 ath6kl_cookie_init(ar);
1625
Kalle Valo61448a92011-10-27 18:48:29 +03001626 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1627 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1628
1629 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
1630 WIPHY_FLAG_HAVE_AP_SME;
1631
Kalle Valo20459ee2011-10-27 18:48:37 +03001632 ret = ath6kl_hw_start(ar);
1633 if (ret) {
1634 ath6kl_err("Failed to boot hardware: %d\n", ret);
1635 goto err_rxbuf_cleanup;
Kalle Valo61448a92011-10-27 18:48:29 +03001636 }
1637
1638 /*
1639 * Set mac address which is received in ready event
1640 * FIXME: Move to ath6kl_interface_add()
1641 */
1642 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
Kalle Valobdcd8172011-07-18 00:22:30 +03001643
Kalle Valobdcd8172011-07-18 00:22:30 +03001644 return ret;
1645
Kalle Valo61448a92011-10-27 18:48:29 +03001646err_rxbuf_cleanup:
1647 ath6kl_htc_flush_rx_buf(ar->htc_target);
1648 ath6kl_cleanup_amsdu_rxbufs(ar);
Kalle Valo61448a92011-10-27 18:48:29 +03001649 rtnl_lock();
1650 ath6kl_deinit_if_data(netdev_priv(ndev));
1651 rtnl_unlock();
1652 wiphy_unregister(ar->wiphy);
1653err_debug_init:
1654 ath6kl_debug_cleanup(ar);
1655err_node_cleanup:
1656 ath6kl_wmi_shutdown(ar->wmi);
1657 clear_bit(WMI_ENABLED, &ar->flag);
1658 ar->wmi = NULL;
Kalle Valobdcd8172011-07-18 00:22:30 +03001659err_htc_cleanup:
Kalle Vaload226ec2011-08-10 09:49:12 +03001660 ath6kl_htc_cleanup(ar->htc_target);
Kalle Valob2e75692011-10-27 18:48:14 +03001661err_power_off:
1662 ath6kl_hif_power_off(ar);
Kalle Valobdcd8172011-07-18 00:22:30 +03001663err_bmi_cleanup:
1664 ath6kl_bmi_cleanup(ar);
1665err_wq:
1666 destroy_workqueue(ar->ath6kl_wq);
Vasanthakumar Thiagarajan8dafb702011-10-25 19:33:58 +05301667
Kalle Valobdcd8172011-07-18 00:22:30 +03001668 return ret;
1669}
1670
Vasanthakumar Thiagarajan55055972011-10-25 19:34:23 +05301671void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready)
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301672{
1673 static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1674 bool discon_issued;
1675
1676 netif_stop_queue(vif->ndev);
1677
1678 clear_bit(WLAN_ENABLED, &vif->flags);
1679
1680 if (wmi_ready) {
1681 discon_issued = test_bit(CONNECTED, &vif->flags) ||
1682 test_bit(CONNECT_PEND, &vif->flags);
1683 ath6kl_disconnect(vif);
1684 del_timer(&vif->disconnect_timer);
1685
1686 if (discon_issued)
1687 ath6kl_disconnect_event(vif, DISCONNECT_CMD,
1688 (vif->nw_type & AP_NETWORK) ?
1689 bcast_mac : vif->bssid,
1690 0, NULL, 0);
1691 }
1692
1693 if (vif->scan_req) {
1694 cfg80211_scan_done(vif->scan_req, true);
1695 vif->scan_req = NULL;
1696 }
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301697}
1698
Kalle Valobdcd8172011-07-18 00:22:30 +03001699void ath6kl_stop_txrx(struct ath6kl *ar)
1700{
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301701 struct ath6kl_vif *vif, *tmp_vif;
Kalle Valobdcd8172011-07-18 00:22:30 +03001702
1703 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1704
1705 if (down_interruptible(&ar->sem)) {
1706 ath6kl_err("down_interruptible failed\n");
1707 return;
1708 }
1709
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301710 spin_lock(&ar->list_lock);
1711 list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
1712 list_del(&vif->list);
1713 spin_unlock(&ar->list_lock);
1714 ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag));
Vasanthakumar Thiagarajan27929722011-10-25 19:34:21 +05301715 rtnl_lock();
1716 ath6kl_deinit_if_data(vif);
1717 rtnl_unlock();
Vasanthakumar Thiagarajan990bd912011-10-25 19:34:20 +05301718 spin_lock(&ar->list_lock);
1719 }
1720 spin_unlock(&ar->list_lock);
Kalle Valobdcd8172011-07-18 00:22:30 +03001721
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301722 clear_bit(WMI_READY, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001723
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301724 /*
1725 * After wmi_shudown all WMI events will be dropped. We
1726 * need to cleanup the buffers allocated in AP mode and
1727 * give disconnect notification to stack, which usually
1728 * happens in the disconnect_event. Simulate the disconnect
1729 * event by calling the function directly. Sometimes
1730 * disconnect_event will be received when the debug logs
1731 * are collected.
1732 */
1733 ath6kl_wmi_shutdown(ar->wmi);
Kalle Valobdcd8172011-07-18 00:22:30 +03001734
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301735 clear_bit(WMI_ENABLED, &ar->flag);
1736 if (ar->htc_target) {
1737 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
1738 ath6kl_htc_stop(ar->htc_target);
Kalle Valobdcd8172011-07-18 00:22:30 +03001739 }
1740
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301741 /*
1742 * Try to reset the device if we can. The driver may have been
1743 * configure NOT to reset the target during a debug session.
1744 */
1745 ath6kl_dbg(ATH6KL_DBG_TRC,
1746 "attempting to reset target on instance destroy\n");
1747 ath6kl_reset_device(ar, ar->target_type, true, true);
Kalle Valobdcd8172011-07-18 00:22:30 +03001748
Vasanthakumar Thiagarajan6db8fa52011-10-25 19:34:16 +05301749 clear_bit(WLAN_ENABLED, &ar->flag);
Kalle Valobdcd8172011-07-18 00:22:30 +03001750}