Back to home page

OSCL-LXR

 
 

    


0001 
0002 /*
0003  * Copyright (c) 2011 Atheros Communications Inc.
0004  * Copyright (c) 2011-2012 Qualcomm Atheros, Inc.
0005  *
0006  * Permission to use, copy, modify, and/or distribute this software for any
0007  * purpose with or without fee is hereby granted, provided that the above
0008  * copyright notice and this permission notice appear in all copies.
0009  *
0010  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0011  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0012  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0013  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0014  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0015  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0016  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0017  */
0018 
0019 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0020 
0021 #include <linux/moduleparam.h>
0022 #include <linux/errno.h>
0023 #include <linux/export.h>
0024 #include <linux/of.h>
0025 #include <linux/mmc/sdio_func.h>
0026 #include <linux/vmalloc.h>
0027 
0028 #include "core.h"
0029 #include "cfg80211.h"
0030 #include "target.h"
0031 #include "debug.h"
0032 #include "hif-ops.h"
0033 #include "htc-ops.h"
0034 
0035 static const struct ath6kl_hw hw_list[] = {
0036     {
0037         .id             = AR6003_HW_2_0_VERSION,
0038         .name               = "ar6003 hw 2.0",
0039         .dataset_patch_addr     = 0x57e884,
0040         .app_load_addr          = 0x543180,
0041         .board_ext_data_addr        = 0x57e500,
0042         .reserved_ram_size      = 6912,
0043         .refclk_hz          = 26000000,
0044         .uarttx_pin         = 8,
0045         .flags              = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
0046 
0047         /* hw2.0 needs override address hardcoded */
0048         .app_start_override_addr    = 0x944C00,
0049 
0050         .fw = {
0051             .dir        = AR6003_HW_2_0_FW_DIR,
0052             .otp        = AR6003_HW_2_0_OTP_FILE,
0053             .fw     = AR6003_HW_2_0_FIRMWARE_FILE,
0054             .tcmd       = AR6003_HW_2_0_TCMD_FIRMWARE_FILE,
0055             .patch      = AR6003_HW_2_0_PATCH_FILE,
0056         },
0057 
0058         .fw_board       = AR6003_HW_2_0_BOARD_DATA_FILE,
0059         .fw_default_board   = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE,
0060     },
0061     {
0062         .id             = AR6003_HW_2_1_1_VERSION,
0063         .name               = "ar6003 hw 2.1.1",
0064         .dataset_patch_addr     = 0x57ff74,
0065         .app_load_addr          = 0x1234,
0066         .board_ext_data_addr        = 0x542330,
0067         .reserved_ram_size      = 512,
0068         .refclk_hz          = 26000000,
0069         .uarttx_pin         = 8,
0070         .testscript_addr        = 0x57ef74,
0071         .flags              = ATH6KL_HW_SDIO_CRC_ERROR_WAR,
0072 
0073         .fw = {
0074             .dir        = AR6003_HW_2_1_1_FW_DIR,
0075             .otp        = AR6003_HW_2_1_1_OTP_FILE,
0076             .fw     = AR6003_HW_2_1_1_FIRMWARE_FILE,
0077             .tcmd       = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE,
0078             .patch      = AR6003_HW_2_1_1_PATCH_FILE,
0079             .utf        = AR6003_HW_2_1_1_UTF_FIRMWARE_FILE,
0080             .testscript = AR6003_HW_2_1_1_TESTSCRIPT_FILE,
0081         },
0082 
0083         .fw_board       = AR6003_HW_2_1_1_BOARD_DATA_FILE,
0084         .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE,
0085     },
0086     {
0087         .id             = AR6004_HW_1_0_VERSION,
0088         .name               = "ar6004 hw 1.0",
0089         .dataset_patch_addr     = 0x57e884,
0090         .app_load_addr          = 0x1234,
0091         .board_ext_data_addr        = 0x437000,
0092         .reserved_ram_size      = 19456,
0093         .board_addr         = 0x433900,
0094         .refclk_hz          = 26000000,
0095         .uarttx_pin         = 11,
0096         .flags              = 0,
0097 
0098         .fw = {
0099             .dir        = AR6004_HW_1_0_FW_DIR,
0100             .fw     = AR6004_HW_1_0_FIRMWARE_FILE,
0101         },
0102 
0103         .fw_board       = AR6004_HW_1_0_BOARD_DATA_FILE,
0104         .fw_default_board   = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE,
0105     },
0106     {
0107         .id             = AR6004_HW_1_1_VERSION,
0108         .name               = "ar6004 hw 1.1",
0109         .dataset_patch_addr     = 0x57e884,
0110         .app_load_addr          = 0x1234,
0111         .board_ext_data_addr        = 0x437000,
0112         .reserved_ram_size      = 11264,
0113         .board_addr         = 0x43d400,
0114         .refclk_hz          = 40000000,
0115         .uarttx_pin         = 11,
0116         .flags              = 0,
0117         .fw = {
0118             .dir        = AR6004_HW_1_1_FW_DIR,
0119             .fw     = AR6004_HW_1_1_FIRMWARE_FILE,
0120         },
0121 
0122         .fw_board       = AR6004_HW_1_1_BOARD_DATA_FILE,
0123         .fw_default_board   = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE,
0124     },
0125     {
0126         .id             = AR6004_HW_1_2_VERSION,
0127         .name               = "ar6004 hw 1.2",
0128         .dataset_patch_addr     = 0x436ecc,
0129         .app_load_addr          = 0x1234,
0130         .board_ext_data_addr        = 0x437000,
0131         .reserved_ram_size      = 9216,
0132         .board_addr         = 0x435c00,
0133         .refclk_hz          = 40000000,
0134         .uarttx_pin         = 11,
0135         .flags              = 0,
0136 
0137         .fw = {
0138             .dir        = AR6004_HW_1_2_FW_DIR,
0139             .fw     = AR6004_HW_1_2_FIRMWARE_FILE,
0140         },
0141         .fw_board       = AR6004_HW_1_2_BOARD_DATA_FILE,
0142         .fw_default_board   = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE,
0143     },
0144     {
0145         .id             = AR6004_HW_1_3_VERSION,
0146         .name               = "ar6004 hw 1.3",
0147         .dataset_patch_addr     = 0x437860,
0148         .app_load_addr          = 0x1234,
0149         .board_ext_data_addr        = 0x437000,
0150         .reserved_ram_size      = 7168,
0151         .board_addr         = 0x436400,
0152         .refclk_hz                      = 0,
0153         .uarttx_pin                     = 11,
0154         .flags              = 0,
0155 
0156         .fw = {
0157             .dir            = AR6004_HW_1_3_FW_DIR,
0158             .fw             = AR6004_HW_1_3_FIRMWARE_FILE,
0159             .tcmd           = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
0160             .utf        = AR6004_HW_1_3_UTF_FIRMWARE_FILE,
0161             .testscript = AR6004_HW_1_3_TESTSCRIPT_FILE,
0162         },
0163 
0164         .fw_board               = AR6004_HW_1_3_BOARD_DATA_FILE,
0165         .fw_default_board       = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
0166     },
0167     {
0168         .id             = AR6004_HW_3_0_VERSION,
0169         .name               = "ar6004 hw 3.0",
0170         .dataset_patch_addr     = 0,
0171         .app_load_addr          = 0x1234,
0172         .board_ext_data_addr        = 0,
0173         .reserved_ram_size      = 7168,
0174         .board_addr         = 0x436400,
0175         .testscript_addr        = 0,
0176         .uarttx_pin         = 11,
0177         .flags              = 0,
0178 
0179         .fw = {
0180             .dir        = AR6004_HW_3_0_FW_DIR,
0181             .fw     = AR6004_HW_3_0_FIRMWARE_FILE,
0182             .tcmd           = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
0183             .utf        = AR6004_HW_3_0_UTF_FIRMWARE_FILE,
0184             .testscript = AR6004_HW_3_0_TESTSCRIPT_FILE,
0185         },
0186 
0187         .fw_board       = AR6004_HW_3_0_BOARD_DATA_FILE,
0188         .fw_default_board   = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
0189     },
0190 };
0191 
0192 /*
0193  * Include definitions here that can be used to tune the WLAN module
0194  * behavior. Different customers can tune the behavior as per their needs,
0195  * here.
0196  */
0197 
0198 /*
0199  * This configuration item enable/disable keepalive support.
0200  * Keepalive support: In the absence of any data traffic to AP, null
0201  * frames will be sent to the AP at periodic interval, to keep the association
0202  * active. This configuration item defines the periodic interval.
0203  * Use value of zero to disable keepalive support
0204  * Default: 60 seconds
0205  */
0206 #define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
0207 
0208 /*
0209  * This configuration item sets the value of disconnect timeout
0210  * Firmware delays sending the disconnec event to the host for this
0211  * timeout after is gets disconnected from the current AP.
0212  * If the firmware successly roams within the disconnect timeout
0213  * it sends a new connect event
0214  */
0215 #define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
0216 
0217 
0218 #define ATH6KL_DATA_OFFSET    64
0219 struct sk_buff *ath6kl_buf_alloc(int size)
0220 {
0221     struct sk_buff *skb;
0222     u16 reserved;
0223 
0224     /* Add chacheline space at front and back of buffer */
0225     reserved = roundup((2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
0226            sizeof(struct htc_packet) + ATH6KL_HTC_ALIGN_BYTES, 4);
0227     skb = dev_alloc_skb(size + reserved);
0228 
0229     if (skb)
0230         skb_reserve(skb, reserved - L1_CACHE_BYTES);
0231     return skb;
0232 }
0233 
0234 void ath6kl_init_profile_info(struct ath6kl_vif *vif)
0235 {
0236     vif->ssid_len = 0;
0237     memset(vif->ssid, 0, sizeof(vif->ssid));
0238 
0239     vif->dot11_auth_mode = OPEN_AUTH;
0240     vif->auth_mode = NONE_AUTH;
0241     vif->prwise_crypto = NONE_CRYPT;
0242     vif->prwise_crypto_len = 0;
0243     vif->grp_crypto = NONE_CRYPT;
0244     vif->grp_crypto_len = 0;
0245     memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
0246     memset(vif->req_bssid, 0, sizeof(vif->req_bssid));
0247     memset(vif->bssid, 0, sizeof(vif->bssid));
0248     vif->bss_ch = 0;
0249 }
0250 
0251 static int ath6kl_set_host_app_area(struct ath6kl *ar)
0252 {
0253     u32 address, data;
0254     struct host_app_area host_app_area;
0255 
0256     /* Fetch the address of the host_app_area_s
0257      * instance in the host interest area */
0258     address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
0259     address = TARG_VTOP(ar->target_type, address);
0260 
0261     if (ath6kl_diag_read32(ar, address, &data))
0262         return -EIO;
0263 
0264     address = TARG_VTOP(ar->target_type, data);
0265     host_app_area.wmi_protocol_ver = cpu_to_le32(WMI_PROTOCOL_VERSION);
0266     if (ath6kl_diag_write(ar, address, (u8 *) &host_app_area,
0267                   sizeof(struct host_app_area)))
0268         return -EIO;
0269 
0270     return 0;
0271 }
0272 
0273 static inline void set_ac2_ep_map(struct ath6kl *ar,
0274                   u8 ac,
0275                   enum htc_endpoint_id ep)
0276 {
0277     ar->ac2ep_map[ac] = ep;
0278     ar->ep2ac_map[ep] = ac;
0279 }
0280 
0281 /* connect to a service */
0282 static int ath6kl_connectservice(struct ath6kl *ar,
0283                  struct htc_service_connect_req  *con_req,
0284                  char *desc)
0285 {
0286     int status;
0287     struct htc_service_connect_resp response;
0288 
0289     memset(&response, 0, sizeof(response));
0290 
0291     status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
0292     if (status) {
0293         ath6kl_err("failed to connect to %s service status:%d\n",
0294                desc, status);
0295         return status;
0296     }
0297 
0298     switch (con_req->svc_id) {
0299     case WMI_CONTROL_SVC:
0300         if (test_bit(WMI_ENABLED, &ar->flag))
0301             ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
0302         ar->ctrl_ep = response.endpoint;
0303         break;
0304     case WMI_DATA_BE_SVC:
0305         set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
0306         break;
0307     case WMI_DATA_BK_SVC:
0308         set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
0309         break;
0310     case WMI_DATA_VI_SVC:
0311         set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
0312         break;
0313     case WMI_DATA_VO_SVC:
0314         set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
0315         break;
0316     default:
0317         ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
0318         return -EINVAL;
0319     }
0320 
0321     return 0;
0322 }
0323 
0324 static int ath6kl_init_service_ep(struct ath6kl *ar)
0325 {
0326     struct htc_service_connect_req connect;
0327 
0328     memset(&connect, 0, sizeof(connect));
0329 
0330     /* these fields are the same for all service endpoints */
0331     connect.ep_cb.tx_comp_multi = ath6kl_tx_complete;
0332     connect.ep_cb.rx = ath6kl_rx;
0333     connect.ep_cb.rx_refill = ath6kl_rx_refill;
0334     connect.ep_cb.tx_full = ath6kl_tx_queue_full;
0335 
0336     /*
0337      * Set the max queue depth so that our ath6kl_tx_queue_full handler
0338      * gets called.
0339     */
0340     connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
0341     connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
0342     if (!connect.ep_cb.rx_refill_thresh)
0343         connect.ep_cb.rx_refill_thresh++;
0344 
0345     /* connect to control service */
0346     connect.svc_id = WMI_CONTROL_SVC;
0347     if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
0348         return -EIO;
0349 
0350     connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
0351 
0352     /*
0353      * Limit the HTC message size on the send path, although e can
0354      * receive A-MSDU frames of 4K, we will only send ethernet-sized
0355      * (802.3) frames on the send path.
0356      */
0357     connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
0358 
0359     /*
0360      * To reduce the amount of committed memory for larger A_MSDU
0361      * frames, use the recv-alloc threshold mechanism for larger
0362      * packets.
0363      */
0364     connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
0365     connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
0366 
0367     /*
0368      * For the remaining data services set the connection flag to
0369      * reduce dribbling, if configured to do so.
0370      */
0371     connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
0372     connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
0373     connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
0374 
0375     connect.svc_id = WMI_DATA_BE_SVC;
0376 
0377     if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
0378         return -EIO;
0379 
0380     /* connect to back-ground map this to WMI LOW_PRI */
0381     connect.svc_id = WMI_DATA_BK_SVC;
0382     if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
0383         return -EIO;
0384 
0385     /* connect to Video service, map this to HI PRI */
0386     connect.svc_id = WMI_DATA_VI_SVC;
0387     if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
0388         return -EIO;
0389 
0390     /*
0391      * Connect to VO service, this is currently not mapped to a WMI
0392      * priority stream due to historical reasons. WMI originally
0393      * defined 3 priorities over 3 mailboxes We can change this when
0394      * WMI is reworked so that priorities are not dependent on
0395      * mailboxes.
0396      */
0397     connect.svc_id = WMI_DATA_VO_SVC;
0398     if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
0399         return -EIO;
0400 
0401     return 0;
0402 }
0403 
0404 void ath6kl_init_control_info(struct ath6kl_vif *vif)
0405 {
0406     ath6kl_init_profile_info(vif);
0407     vif->def_txkey_index = 0;
0408     memset(vif->wep_key_list, 0, sizeof(vif->wep_key_list));
0409     vif->ch_hint = 0;
0410 }
0411 
0412 /*
0413  * Set HTC/Mbox operational parameters, this can only be called when the
0414  * target is in the BMI phase.
0415  */
0416 static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
0417                  u8 htc_ctrl_buf)
0418 {
0419     int status;
0420     u32 blk_size;
0421 
0422     blk_size = ar->mbox_info.block_size;
0423 
0424     if (htc_ctrl_buf)
0425         blk_size |=  ((u32)htc_ctrl_buf) << 16;
0426 
0427     /* set the host interest area for the block size */
0428     status = ath6kl_bmi_write_hi32(ar, hi_mbox_io_block_sz, blk_size);
0429     if (status) {
0430         ath6kl_err("bmi_write_memory for IO block size failed\n");
0431         goto out;
0432     }
0433 
0434     ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
0435            blk_size,
0436            ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));
0437 
0438     if (mbox_isr_yield_val) {
0439         /* set the host interest area for the mbox ISR yield limit */
0440         status = ath6kl_bmi_write_hi32(ar, hi_mbox_isr_yield_limit,
0441                            mbox_isr_yield_val);
0442         if (status) {
0443             ath6kl_err("bmi_write_memory for yield limit failed\n");
0444             goto out;
0445         }
0446     }
0447 
0448 out:
0449     return status;
0450 }
0451 
0452 static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
0453 {
0454     int ret;
0455 
0456     /*
0457      * Configure the device for rx dot11 header rules. "0,0" are the
0458      * default values. Required if checksum offload is needed. Set
0459      * RxMetaVersion to 2.
0460      */
0461     ret = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, idx,
0462                          ar->rx_meta_ver, 0, 0);
0463     if (ret) {
0464         ath6kl_err("unable to set the rx frame format: %d\n", ret);
0465         return ret;
0466     }
0467 
0468     if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN) {
0469         ret = ath6kl_wmi_pmparams_cmd(ar->wmi, idx, 0, 1, 0, 0, 1,
0470                           IGNORE_PS_FAIL_DURING_SCAN);
0471         if (ret) {
0472             ath6kl_err("unable to set power save fail event policy: %d\n",
0473                    ret);
0474             return ret;
0475         }
0476     }
0477 
0478     if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER)) {
0479         ret = ath6kl_wmi_set_lpreamble_cmd(ar->wmi, idx, 0,
0480                            WMI_FOLLOW_BARKER_IN_ERP);
0481         if (ret) {
0482             ath6kl_err("unable to set barker preamble policy: %d\n",
0483                    ret);
0484             return ret;
0485         }
0486     }
0487 
0488     ret = ath6kl_wmi_set_keepalive_cmd(ar->wmi, idx,
0489                        WLAN_CONFIG_KEEP_ALIVE_INTERVAL);
0490     if (ret) {
0491         ath6kl_err("unable to set keep alive interval: %d\n", ret);
0492         return ret;
0493     }
0494 
0495     ret = ath6kl_wmi_disctimeout_cmd(ar->wmi, idx,
0496                      WLAN_CONFIG_DISCONNECT_TIMEOUT);
0497     if (ret) {
0498         ath6kl_err("unable to set disconnect timeout: %d\n", ret);
0499         return ret;
0500     }
0501 
0502     if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST)) {
0503         ret = ath6kl_wmi_set_wmm_txop(ar->wmi, idx, WMI_TXOP_DISABLED);
0504         if (ret) {
0505             ath6kl_err("unable to set txop bursting: %d\n", ret);
0506             return ret;
0507         }
0508     }
0509 
0510     if (ar->p2p && (ar->vif_max == 1 || idx)) {
0511         ret = ath6kl_wmi_info_req_cmd(ar->wmi, idx,
0512                           P2P_FLAG_CAPABILITIES_REQ |
0513                           P2P_FLAG_MACADDR_REQ |
0514                           P2P_FLAG_HMODEL_REQ);
0515         if (ret) {
0516             ath6kl_dbg(ATH6KL_DBG_TRC,
0517                    "failed to request P2P capabilities (%d) - assuming P2P not supported\n",
0518                    ret);
0519             ar->p2p = false;
0520         }
0521     }
0522 
0523     if (ar->p2p && (ar->vif_max == 1 || idx)) {
0524         /* Enable Probe Request reporting for P2P */
0525         ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true);
0526         if (ret) {
0527             ath6kl_dbg(ATH6KL_DBG_TRC,
0528                    "failed to enable Probe Request reporting (%d)\n",
0529                    ret);
0530         }
0531     }
0532 
0533     return ret;
0534 }
0535 
0536 int ath6kl_configure_target(struct ath6kl *ar)
0537 {
0538     u32 param, ram_reserved_size;
0539     u8 fw_iftype, fw_mode = 0, fw_submode = 0;
0540     int i, status;
0541 
0542     param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG);
0543     if (ath6kl_bmi_write_hi32(ar, hi_serial_enable, param)) {
0544         ath6kl_err("bmi_write_memory for uart debug failed\n");
0545         return -EIO;
0546     }
0547 
0548     /*
0549      * Note: Even though the firmware interface type is
0550      * chosen as BSS_STA for all three interfaces, can
0551      * be configured to IBSS/AP as long as the fw submode
0552      * remains normal mode (0 - AP, STA and IBSS). But
0553      * due to an target assert in firmware only one interface is
0554      * configured for now.
0555      */
0556     fw_iftype = HI_OPTION_FW_MODE_BSS_STA;
0557 
0558     for (i = 0; i < ar->vif_max; i++)
0559         fw_mode |= fw_iftype << (i * HI_OPTION_FW_MODE_BITS);
0560 
0561     /*
0562      * Submodes when fw does not support dynamic interface
0563      * switching:
0564      *      vif[0] - AP/STA/IBSS
0565      *      vif[1] - "P2P dev"/"P2P GO"/"P2P Client"
0566      *      vif[2] - "P2P dev"/"P2P GO"/"P2P Client"
0567      * Otherwise, All the interface are initialized to p2p dev.
0568      */
0569 
0570     if (test_bit(ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX,
0571              ar->fw_capabilities)) {
0572         for (i = 0; i < ar->vif_max; i++)
0573             fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
0574                 (i * HI_OPTION_FW_SUBMODE_BITS);
0575     } else {
0576         for (i = 0; i < ar->max_norm_iface; i++)
0577             fw_submode |= HI_OPTION_FW_SUBMODE_NONE <<
0578                 (i * HI_OPTION_FW_SUBMODE_BITS);
0579 
0580         for (i = ar->max_norm_iface; i < ar->vif_max; i++)
0581             fw_submode |= HI_OPTION_FW_SUBMODE_P2PDEV <<
0582                 (i * HI_OPTION_FW_SUBMODE_BITS);
0583 
0584         if (ar->p2p && ar->vif_max == 1)
0585             fw_submode = HI_OPTION_FW_SUBMODE_P2PDEV;
0586     }
0587 
0588     if (ath6kl_bmi_write_hi32(ar, hi_app_host_interest,
0589                   HTC_PROTOCOL_VERSION) != 0) {
0590         ath6kl_err("bmi_write_memory for htc version failed\n");
0591         return -EIO;
0592     }
0593 
0594     /* set the firmware mode to STA/IBSS/AP */
0595     param = 0;
0596 
0597     if (ath6kl_bmi_read_hi32(ar, hi_option_flag, &param) != 0) {
0598         ath6kl_err("bmi_read_memory for setting fwmode failed\n");
0599         return -EIO;
0600     }
0601 
0602     param |= (ar->vif_max << HI_OPTION_NUM_DEV_SHIFT);
0603     param |= fw_mode << HI_OPTION_FW_MODE_SHIFT;
0604     param |= fw_submode << HI_OPTION_FW_SUBMODE_SHIFT;
0605 
0606     param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
0607     param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
0608 
0609     if (ath6kl_bmi_write_hi32(ar, hi_option_flag, param) != 0) {
0610         ath6kl_err("bmi_write_memory for setting fwmode failed\n");
0611         return -EIO;
0612     }
0613 
0614     ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
0615 
0616     /*
0617      * Hardcode the address use for the extended board data
0618      * Ideally this should be pre-allocate by the OS at boot time
0619      * But since it is a new feature and board data is loaded
0620      * at init time, we have to workaround this from host.
0621      * It is difficult to patch the firmware boot code,
0622      * but possible in theory.
0623      */
0624 
0625     if ((ar->target_type == TARGET_TYPE_AR6003) ||
0626         (ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
0627         (ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
0628         param = ar->hw.board_ext_data_addr;
0629         ram_reserved_size = ar->hw.reserved_ram_size;
0630 
0631         if (ath6kl_bmi_write_hi32(ar, hi_board_ext_data, param) != 0) {
0632             ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
0633             return -EIO;
0634         }
0635 
0636         if (ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz,
0637                       ram_reserved_size) != 0) {
0638             ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
0639             return -EIO;
0640         }
0641     }
0642 
0643     /* set the block size for the target */
0644     if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
0645         /* use default number of control buffers */
0646         return -EIO;
0647 
0648     /* Configure GPIO AR600x UART */
0649     status = ath6kl_bmi_write_hi32(ar, hi_dbg_uart_txpin,
0650                        ar->hw.uarttx_pin);
0651     if (status)
0652         return status;
0653 
0654     /* Only set the baud rate if we're actually doing debug */
0655     if (ar->conf_flags & ATH6KL_CONF_UART_DEBUG) {
0656         status = ath6kl_bmi_write_hi32(ar, hi_desired_baud_rate,
0657                            ar->hw.uarttx_rate);
0658         if (status)
0659             return status;
0660     }
0661 
0662     /* Configure target refclk_hz */
0663     if (ar->hw.refclk_hz != 0) {
0664         status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
0665                            ar->hw.refclk_hz);
0666         if (status)
0667             return status;
0668     }
0669 
0670     return 0;
0671 }
0672 
0673 /* firmware upload */
0674 static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
0675              u8 **fw, size_t *fw_len)
0676 {
0677     const struct firmware *fw_entry;
0678     int ret;
0679 
0680     ret = request_firmware(&fw_entry, filename, ar->dev);
0681     if (ret)
0682         return ret;
0683 
0684     *fw_len = fw_entry->size;
0685     *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
0686 
0687     if (*fw == NULL)
0688         ret = -ENOMEM;
0689 
0690     release_firmware(fw_entry);
0691 
0692     return ret;
0693 }
0694 
0695 #ifdef CONFIG_OF
0696 /*
0697  * Check the device tree for a board-id and use it to construct
0698  * the pathname to the firmware file.  Used (for now) to find a
0699  * fallback to the "bdata.bin" file--typically a symlink to the
0700  * appropriate board-specific file.
0701  */
0702 static bool check_device_tree(struct ath6kl *ar)
0703 {
0704     static const char *board_id_prop = "atheros,board-id";
0705     struct device_node *node;
0706     char board_filename[64];
0707     const char *board_id;
0708     int ret;
0709 
0710     for_each_compatible_node(node, NULL, "atheros,ath6kl") {
0711         board_id = of_get_property(node, board_id_prop, NULL);
0712         if (board_id == NULL) {
0713             ath6kl_warn("No \"%s\" property on %pOFn node.\n",
0714                     board_id_prop, node);
0715             continue;
0716         }
0717         snprintf(board_filename, sizeof(board_filename),
0718              "%s/bdata.%s.bin", ar->hw.fw.dir, board_id);
0719 
0720         ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board,
0721                     &ar->fw_board_len);
0722         if (ret) {
0723             ath6kl_err("Failed to get DT board file %s: %d\n",
0724                    board_filename, ret);
0725             continue;
0726         }
0727         of_node_put(node);
0728         return true;
0729     }
0730     return false;
0731 }
0732 #else
0733 static bool check_device_tree(struct ath6kl *ar)
0734 {
0735     return false;
0736 }
0737 #endif /* CONFIG_OF */
0738 
0739 static int ath6kl_fetch_board_file(struct ath6kl *ar)
0740 {
0741     const char *filename;
0742     int ret;
0743 
0744     if (ar->fw_board != NULL)
0745         return 0;
0746 
0747     if (WARN_ON(ar->hw.fw_board == NULL))
0748         return -EINVAL;
0749 
0750     filename = ar->hw.fw_board;
0751 
0752     ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
0753                 &ar->fw_board_len);
0754     if (ret == 0) {
0755         /* managed to get proper board file */
0756         return 0;
0757     }
0758 
0759     if (check_device_tree(ar)) {
0760         /* got board file from device tree */
0761         return 0;
0762     }
0763 
0764     /* there was no proper board file, try to use default instead */
0765     ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
0766             filename, ret);
0767 
0768     filename = ar->hw.fw_default_board;
0769 
0770     ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
0771                 &ar->fw_board_len);
0772     if (ret) {
0773         ath6kl_err("Failed to get default board file %s: %d\n",
0774                filename, ret);
0775         return ret;
0776     }
0777 
0778     ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
0779     ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
0780 
0781     return 0;
0782 }
0783 
0784 static int ath6kl_fetch_otp_file(struct ath6kl *ar)
0785 {
0786     char filename[100];
0787     int ret;
0788 
0789     if (ar->fw_otp != NULL)
0790         return 0;
0791 
0792     if (ar->hw.fw.otp == NULL) {
0793         ath6kl_dbg(ATH6KL_DBG_BOOT,
0794                "no OTP file configured for this hw\n");
0795         return 0;
0796     }
0797 
0798     snprintf(filename, sizeof(filename), "%s/%s",
0799          ar->hw.fw.dir, ar->hw.fw.otp);
0800 
0801     ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
0802                 &ar->fw_otp_len);
0803     if (ret) {
0804         ath6kl_err("Failed to get OTP file %s: %d\n",
0805                filename, ret);
0806         return ret;
0807     }
0808 
0809     return 0;
0810 }
0811 
0812 static int ath6kl_fetch_testmode_file(struct ath6kl *ar)
0813 {
0814     char filename[100];
0815     int ret;
0816 
0817     if (ar->testmode == 0)
0818         return 0;
0819 
0820     ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", ar->testmode);
0821 
0822     if (ar->testmode == 2) {
0823         if (ar->hw.fw.utf == NULL) {
0824             ath6kl_warn("testmode 2 not supported\n");
0825             return -EOPNOTSUPP;
0826         }
0827 
0828         snprintf(filename, sizeof(filename), "%s/%s",
0829              ar->hw.fw.dir, ar->hw.fw.utf);
0830     } else {
0831         if (ar->hw.fw.tcmd == NULL) {
0832             ath6kl_warn("testmode 1 not supported\n");
0833             return -EOPNOTSUPP;
0834         }
0835 
0836         snprintf(filename, sizeof(filename), "%s/%s",
0837              ar->hw.fw.dir, ar->hw.fw.tcmd);
0838     }
0839 
0840     set_bit(TESTMODE, &ar->flag);
0841 
0842     ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
0843     if (ret) {
0844         ath6kl_err("Failed to get testmode %d firmware file %s: %d\n",
0845                ar->testmode, filename, ret);
0846         return ret;
0847     }
0848 
0849     return 0;
0850 }
0851 
0852 static int ath6kl_fetch_fw_file(struct ath6kl *ar)
0853 {
0854     char filename[100];
0855     int ret;
0856 
0857     if (ar->fw != NULL)
0858         return 0;
0859 
0860     /* FIXME: remove WARN_ON() as we won't support FW API 1 for long */
0861     if (WARN_ON(ar->hw.fw.fw == NULL))
0862         return -EINVAL;
0863 
0864     snprintf(filename, sizeof(filename), "%s/%s",
0865          ar->hw.fw.dir, ar->hw.fw.fw);
0866 
0867     ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
0868     if (ret) {
0869         ath6kl_err("Failed to get firmware file %s: %d\n",
0870                filename, ret);
0871         return ret;
0872     }
0873 
0874     return 0;
0875 }
0876 
0877 static int ath6kl_fetch_patch_file(struct ath6kl *ar)
0878 {
0879     char filename[100];
0880     int ret;
0881 
0882     if (ar->fw_patch != NULL)
0883         return 0;
0884 
0885     if (ar->hw.fw.patch == NULL)
0886         return 0;
0887 
0888     snprintf(filename, sizeof(filename), "%s/%s",
0889          ar->hw.fw.dir, ar->hw.fw.patch);
0890 
0891     ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
0892                 &ar->fw_patch_len);
0893     if (ret) {
0894         ath6kl_err("Failed to get patch file %s: %d\n",
0895                filename, ret);
0896         return ret;
0897     }
0898 
0899     return 0;
0900 }
0901 
0902 static int ath6kl_fetch_testscript_file(struct ath6kl *ar)
0903 {
0904     char filename[100];
0905     int ret;
0906 
0907     if (ar->testmode != 2)
0908         return 0;
0909 
0910     if (ar->fw_testscript != NULL)
0911         return 0;
0912 
0913     if (ar->hw.fw.testscript == NULL)
0914         return 0;
0915 
0916     snprintf(filename, sizeof(filename), "%s/%s",
0917          ar->hw.fw.dir, ar->hw.fw.testscript);
0918 
0919     ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript,
0920                 &ar->fw_testscript_len);
0921     if (ret) {
0922         ath6kl_err("Failed to get testscript file %s: %d\n",
0923                filename, ret);
0924         return ret;
0925     }
0926 
0927     return 0;
0928 }
0929 
0930 static int ath6kl_fetch_fw_api1(struct ath6kl *ar)
0931 {
0932     int ret;
0933 
0934     ret = ath6kl_fetch_otp_file(ar);
0935     if (ret)
0936         return ret;
0937 
0938     ret = ath6kl_fetch_fw_file(ar);
0939     if (ret)
0940         return ret;
0941 
0942     ret = ath6kl_fetch_patch_file(ar);
0943     if (ret)
0944         return ret;
0945 
0946     ret = ath6kl_fetch_testscript_file(ar);
0947     if (ret)
0948         return ret;
0949 
0950     return 0;
0951 }
0952 
0953 static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
0954 {
0955     size_t magic_len, len, ie_len;
0956     const struct firmware *fw;
0957     struct ath6kl_fw_ie *hdr;
0958     char filename[100];
0959     const u8 *data;
0960     int ret, ie_id, i, index, bit;
0961     __le32 *val;
0962 
0963     snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name);
0964 
0965     ret = request_firmware(&fw, filename, ar->dev);
0966     if (ret) {
0967         ath6kl_err("Failed request firmware, rv: %d\n", ret);
0968         return ret;
0969     }
0970 
0971     data = fw->data;
0972     len = fw->size;
0973 
0974     /* magic also includes the null byte, check that as well */
0975     magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
0976 
0977     if (len < magic_len) {
0978         ath6kl_err("Magic length is invalid, len: %zd  magic_len: %zd\n",
0979                len, magic_len);
0980         ret = -EINVAL;
0981         goto out;
0982     }
0983 
0984     if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
0985         ath6kl_err("Magic is invalid, magic_len: %zd\n",
0986                magic_len);
0987         ret = -EINVAL;
0988         goto out;
0989     }
0990 
0991     len -= magic_len;
0992     data += magic_len;
0993 
0994     /* loop elements */
0995     while (len > sizeof(struct ath6kl_fw_ie)) {
0996         /* hdr is unaligned! */
0997         hdr = (struct ath6kl_fw_ie *) data;
0998 
0999         ie_id = le32_to_cpup(&hdr->id);
1000         ie_len = le32_to_cpup(&hdr->len);
1001 
1002         len -= sizeof(*hdr);
1003         data += sizeof(*hdr);
1004 
1005         ath6kl_dbg(ATH6KL_DBG_BOOT, "ie-id: %d  len: %zd (0x%zx)\n",
1006                ie_id, ie_len, ie_len);
1007 
1008         if (len < ie_len) {
1009             ath6kl_err("IE len is invalid, len: %zd  ie_len: %zd  ie-id: %d\n",
1010                    len, ie_len, ie_id);
1011             ret = -EINVAL;
1012             goto out;
1013         }
1014 
1015         switch (ie_id) {
1016         case ATH6KL_FW_IE_FW_VERSION:
1017             strlcpy(ar->wiphy->fw_version, data,
1018                 min(sizeof(ar->wiphy->fw_version), ie_len+1));
1019 
1020             ath6kl_dbg(ATH6KL_DBG_BOOT,
1021                    "found fw version %s\n",
1022                     ar->wiphy->fw_version);
1023             break;
1024         case ATH6KL_FW_IE_OTP_IMAGE:
1025             ath6kl_dbg(ATH6KL_DBG_BOOT, "found otp image ie (%zd B)\n",
1026                    ie_len);
1027 
1028             ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
1029 
1030             if (ar->fw_otp == NULL) {
1031                 ath6kl_err("fw_otp cannot be allocated\n");
1032                 ret = -ENOMEM;
1033                 goto out;
1034             }
1035 
1036             ar->fw_otp_len = ie_len;
1037             break;
1038         case ATH6KL_FW_IE_FW_IMAGE:
1039             ath6kl_dbg(ATH6KL_DBG_BOOT, "found fw image ie (%zd B)\n",
1040                    ie_len);
1041 
1042             /* in testmode we already might have a fw file */
1043             if (ar->fw != NULL)
1044                 break;
1045 
1046             ar->fw = vmalloc(ie_len);
1047 
1048             if (ar->fw == NULL) {
1049                 ath6kl_err("fw storage cannot be allocated, len: %zd\n", ie_len);
1050                 ret = -ENOMEM;
1051                 goto out;
1052             }
1053 
1054             memcpy(ar->fw, data, ie_len);
1055             ar->fw_len = ie_len;
1056             break;
1057         case ATH6KL_FW_IE_PATCH_IMAGE:
1058             ath6kl_dbg(ATH6KL_DBG_BOOT, "found patch image ie (%zd B)\n",
1059                    ie_len);
1060 
1061             ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
1062 
1063             if (ar->fw_patch == NULL) {
1064                 ath6kl_err("fw_patch storage cannot be allocated, len: %zd\n", ie_len);
1065                 ret = -ENOMEM;
1066                 goto out;
1067             }
1068 
1069             ar->fw_patch_len = ie_len;
1070             break;
1071         case ATH6KL_FW_IE_RESERVED_RAM_SIZE:
1072             val = (__le32 *) data;
1073             ar->hw.reserved_ram_size = le32_to_cpup(val);
1074 
1075             ath6kl_dbg(ATH6KL_DBG_BOOT,
1076                    "found reserved ram size ie %d\n",
1077                    ar->hw.reserved_ram_size);
1078             break;
1079         case ATH6KL_FW_IE_CAPABILITIES:
1080             ath6kl_dbg(ATH6KL_DBG_BOOT,
1081                    "found firmware capabilities ie (%zd B)\n",
1082                    ie_len);
1083 
1084             for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
1085                 index = i / 8;
1086                 bit = i % 8;
1087 
1088                 if (index == ie_len)
1089                     break;
1090 
1091                 if (data[index] & (1 << bit))
1092                     __set_bit(i, ar->fw_capabilities);
1093             }
1094 
1095             ath6kl_dbg_dump(ATH6KL_DBG_BOOT, "capabilities", "",
1096                     ar->fw_capabilities,
1097                     sizeof(ar->fw_capabilities));
1098             break;
1099         case ATH6KL_FW_IE_PATCH_ADDR:
1100             if (ie_len != sizeof(*val))
1101                 break;
1102 
1103             val = (__le32 *) data;
1104             ar->hw.dataset_patch_addr = le32_to_cpup(val);
1105 
1106             ath6kl_dbg(ATH6KL_DBG_BOOT,
1107                    "found patch address ie 0x%x\n",
1108                    ar->hw.dataset_patch_addr);
1109             break;
1110         case ATH6KL_FW_IE_BOARD_ADDR:
1111             if (ie_len != sizeof(*val))
1112                 break;
1113 
1114             val = (__le32 *) data;
1115             ar->hw.board_addr = le32_to_cpup(val);
1116 
1117             ath6kl_dbg(ATH6KL_DBG_BOOT,
1118                    "found board address ie 0x%x\n",
1119                    ar->hw.board_addr);
1120             break;
1121         case ATH6KL_FW_IE_VIF_MAX:
1122             if (ie_len != sizeof(*val))
1123                 break;
1124 
1125             val = (__le32 *) data;
1126             ar->vif_max = min_t(unsigned int, le32_to_cpup(val),
1127                         ATH6KL_VIF_MAX);
1128 
1129             if (ar->vif_max > 1 && !ar->p2p)
1130                 ar->max_norm_iface = 2;
1131 
1132             ath6kl_dbg(ATH6KL_DBG_BOOT,
1133                    "found vif max ie %d\n", ar->vif_max);
1134             break;
1135         default:
1136             ath6kl_dbg(ATH6KL_DBG_BOOT, "Unknown fw ie: %u\n",
1137                    le32_to_cpup(&hdr->id));
1138             break;
1139         }
1140 
1141         len -= ie_len;
1142         data += ie_len;
1143     }
1144 
1145     ret = 0;
1146 out:
1147     release_firmware(fw);
1148 
1149     return ret;
1150 }
1151 
1152 int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
1153 {
1154     int ret;
1155 
1156     ret = ath6kl_fetch_board_file(ar);
1157     if (ret)
1158         return ret;
1159 
1160     ret = ath6kl_fetch_testmode_file(ar);
1161     if (ret)
1162         return ret;
1163 
1164     ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
1165     if (ret == 0) {
1166         ar->fw_api = 5;
1167         goto out;
1168     }
1169 
1170     ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
1171     if (ret == 0) {
1172         ar->fw_api = 4;
1173         goto out;
1174     }
1175 
1176     ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE);
1177     if (ret == 0) {
1178         ar->fw_api = 3;
1179         goto out;
1180     }
1181 
1182     ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API2_FILE);
1183     if (ret == 0) {
1184         ar->fw_api = 2;
1185         goto out;
1186     }
1187 
1188     ret = ath6kl_fetch_fw_api1(ar);
1189     if (ret)
1190         return ret;
1191 
1192     ar->fw_api = 1;
1193 
1194 out:
1195     ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api %d\n", ar->fw_api);
1196 
1197     return 0;
1198 }
1199 
1200 static int ath6kl_upload_board_file(struct ath6kl *ar)
1201 {
1202     u32 board_address, board_ext_address, param;
1203     u32 board_data_size, board_ext_data_size;
1204     int ret;
1205 
1206     if (WARN_ON(ar->fw_board == NULL))
1207         return -ENOENT;
1208 
1209     /*
1210      * Determine where in Target RAM to write Board Data.
1211      * For AR6004, host determine Target RAM address for
1212      * writing board data.
1213      */
1214     if (ar->hw.board_addr != 0) {
1215         board_address = ar->hw.board_addr;
1216         ath6kl_bmi_write_hi32(ar, hi_board_data,
1217                       board_address);
1218     } else {
1219         ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
1220         if (ret) {
1221             ath6kl_err("Failed to get board file target address.\n");
1222             return ret;
1223         }
1224     }
1225 
1226     /* determine where in target ram to write extended board data */
1227     ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
1228     if (ret) {
1229         ath6kl_err("Failed to get extended board file target address.\n");
1230         return ret;
1231     }
1232 
1233     if (ar->target_type == TARGET_TYPE_AR6003 &&
1234         board_ext_address == 0) {
1235         ath6kl_err("Failed to get board file target address.\n");
1236         return -EINVAL;
1237     }
1238 
1239     switch (ar->target_type) {
1240     case TARGET_TYPE_AR6003:
1241         board_data_size = AR6003_BOARD_DATA_SZ;
1242         board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ;
1243         if (ar->fw_board_len > (board_data_size + board_ext_data_size))
1244             board_ext_data_size = AR6003_BOARD_EXT_DATA_SZ_V2;
1245         break;
1246     case TARGET_TYPE_AR6004:
1247         board_data_size = AR6004_BOARD_DATA_SZ;
1248         board_ext_data_size = AR6004_BOARD_EXT_DATA_SZ;
1249         break;
1250     default:
1251         WARN_ON(1);
1252         return -EINVAL;
1253     }
1254 
1255     if (board_ext_address &&
1256         ar->fw_board_len == (board_data_size + board_ext_data_size)) {
1257         /* write extended board data */
1258         ath6kl_dbg(ATH6KL_DBG_BOOT,
1259                "writing extended board data to 0x%x (%d B)\n",
1260                board_ext_address, board_ext_data_size);
1261 
1262         ret = ath6kl_bmi_write(ar, board_ext_address,
1263                        ar->fw_board + board_data_size,
1264                        board_ext_data_size);
1265         if (ret) {
1266             ath6kl_err("Failed to write extended board data: %d\n",
1267                    ret);
1268             return ret;
1269         }
1270 
1271         /* record that extended board data is initialized */
1272         param = (board_ext_data_size << 16) | 1;
1273 
1274         ath6kl_bmi_write_hi32(ar, hi_board_ext_data_config, param);
1275     }
1276 
1277     if (ar->fw_board_len < board_data_size) {
1278         ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
1279         ret = -EINVAL;
1280         return ret;
1281     }
1282 
1283     ath6kl_dbg(ATH6KL_DBG_BOOT, "writing board file to 0x%x (%d B)\n",
1284            board_address, board_data_size);
1285 
1286     ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
1287                    board_data_size);
1288 
1289     if (ret) {
1290         ath6kl_err("Board file bmi write failed: %d\n", ret);
1291         return ret;
1292     }
1293 
1294     /* record the fact that Board Data IS initialized */
1295     if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
1296         (ar->version.target_ver == AR6004_HW_3_0_VERSION))
1297         param = board_data_size;
1298     else
1299         param = 1;
1300 
1301     ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
1302 
1303     return ret;
1304 }
1305 
1306 static int ath6kl_upload_otp(struct ath6kl *ar)
1307 {
1308     u32 address, param;
1309     bool from_hw = false;
1310     int ret;
1311 
1312     if (ar->fw_otp == NULL)
1313         return 0;
1314 
1315     address = ar->hw.app_load_addr;
1316 
1317     ath6kl_dbg(ATH6KL_DBG_BOOT, "writing otp to 0x%x (%zd B)\n", address,
1318            ar->fw_otp_len);
1319 
1320     ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
1321                        ar->fw_otp_len);
1322     if (ret) {
1323         ath6kl_err("Failed to upload OTP file: %d\n", ret);
1324         return ret;
1325     }
1326 
1327     /* read firmware start address */
1328     ret = ath6kl_bmi_read_hi32(ar, hi_app_start, &address);
1329 
1330     if (ret) {
1331         ath6kl_err("Failed to read hi_app_start: %d\n", ret);
1332         return ret;
1333     }
1334 
1335     if (ar->hw.app_start_override_addr == 0) {
1336         ar->hw.app_start_override_addr = address;
1337         from_hw = true;
1338     }
1339 
1340     ath6kl_dbg(ATH6KL_DBG_BOOT, "app_start_override_addr%s 0x%x\n",
1341            from_hw ? " (from hw)" : "",
1342            ar->hw.app_start_override_addr);
1343 
1344     /* execute the OTP code */
1345     ath6kl_dbg(ATH6KL_DBG_BOOT, "executing OTP at 0x%x\n",
1346            ar->hw.app_start_override_addr);
1347     param = 0;
1348     ath6kl_bmi_execute(ar, ar->hw.app_start_override_addr, &param);
1349 
1350     return ret;
1351 }
1352 
1353 static int ath6kl_upload_firmware(struct ath6kl *ar)
1354 {
1355     u32 address;
1356     int ret;
1357 
1358     if (WARN_ON(ar->fw == NULL))
1359         return 0;
1360 
1361     address = ar->hw.app_load_addr;
1362 
1363     ath6kl_dbg(ATH6KL_DBG_BOOT, "writing firmware to 0x%x (%zd B)\n",
1364            address, ar->fw_len);
1365 
1366     ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
1367 
1368     if (ret) {
1369         ath6kl_err("Failed to write firmware: %d\n", ret);
1370         return ret;
1371     }
1372 
1373     /*
1374      * Set starting address for firmware
1375      * Don't need to setup app_start override addr on AR6004
1376      */
1377     if (ar->target_type != TARGET_TYPE_AR6004) {
1378         address = ar->hw.app_start_override_addr;
1379         ath6kl_bmi_set_app_start(ar, address);
1380     }
1381     return ret;
1382 }
1383 
1384 static int ath6kl_upload_patch(struct ath6kl *ar)
1385 {
1386     u32 address;
1387     int ret;
1388 
1389     if (ar->fw_patch == NULL)
1390         return 0;
1391 
1392     address = ar->hw.dataset_patch_addr;
1393 
1394     ath6kl_dbg(ATH6KL_DBG_BOOT, "writing patch to 0x%x (%zd B)\n",
1395            address, ar->fw_patch_len);
1396 
1397     ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
1398     if (ret) {
1399         ath6kl_err("Failed to write patch file: %d\n", ret);
1400         return ret;
1401     }
1402 
1403     ath6kl_bmi_write_hi32(ar, hi_dset_list_head, address);
1404 
1405     return 0;
1406 }
1407 
1408 static int ath6kl_upload_testscript(struct ath6kl *ar)
1409 {
1410     u32 address;
1411     int ret;
1412 
1413     if (ar->testmode != 2)
1414         return 0;
1415 
1416     if (ar->fw_testscript == NULL)
1417         return 0;
1418 
1419     address = ar->hw.testscript_addr;
1420 
1421     ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n",
1422            address, ar->fw_testscript_len);
1423 
1424     ret = ath6kl_bmi_write(ar, address, ar->fw_testscript,
1425         ar->fw_testscript_len);
1426     if (ret) {
1427         ath6kl_err("Failed to write testscript file: %d\n", ret);
1428         return ret;
1429     }
1430 
1431     ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
1432 
1433     if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
1434         (ar->version.target_ver != AR6004_HW_3_0_VERSION))
1435         ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
1436 
1437     ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
1438 
1439     return 0;
1440 }
1441 
1442 static int ath6kl_init_upload(struct ath6kl *ar)
1443 {
1444     u32 param, options, sleep, address;
1445     int status = 0;
1446 
1447     if (ar->target_type != TARGET_TYPE_AR6003 &&
1448         ar->target_type != TARGET_TYPE_AR6004)
1449         return -EINVAL;
1450 
1451     /* temporarily disable system sleep */
1452     address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1453     status = ath6kl_bmi_reg_read(ar, address, &param);
1454     if (status)
1455         return status;
1456 
1457     options = param;
1458 
1459     param |= ATH6KL_OPTION_SLEEP_DISABLE;
1460     status = ath6kl_bmi_reg_write(ar, address, param);
1461     if (status)
1462         return status;
1463 
1464     address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1465     status = ath6kl_bmi_reg_read(ar, address, &param);
1466     if (status)
1467         return status;
1468 
1469     sleep = param;
1470 
1471     param |= SM(SYSTEM_SLEEP_DISABLE, 1);
1472     status = ath6kl_bmi_reg_write(ar, address, param);
1473     if (status)
1474         return status;
1475 
1476     ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
1477            options, sleep);
1478 
1479     /* program analog PLL register */
1480     /* no need to control 40/44MHz clock on AR6004 */
1481     if (ar->target_type != TARGET_TYPE_AR6004) {
1482         status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
1483                           0xF9104001);
1484 
1485         if (status)
1486             return status;
1487 
1488         /* Run at 80/88MHz by default */
1489         param = SM(CPU_CLOCK_STANDARD, 1);
1490 
1491         address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
1492         status = ath6kl_bmi_reg_write(ar, address, param);
1493         if (status)
1494             return status;
1495     }
1496 
1497     param = 0;
1498     address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
1499     param = SM(LPO_CAL_ENABLE, 1);
1500     status = ath6kl_bmi_reg_write(ar, address, param);
1501     if (status)
1502         return status;
1503 
1504     /* WAR to avoid SDIO CRC err */
1505     if (ar->hw.flags & ATH6KL_HW_SDIO_CRC_ERROR_WAR) {
1506         ath6kl_err("temporary war to avoid sdio crc error\n");
1507 
1508         param = 0x28;
1509         address = GPIO_BASE_ADDRESS + GPIO_PIN9_ADDRESS;
1510         status = ath6kl_bmi_reg_write(ar, address, param);
1511         if (status)
1512             return status;
1513 
1514         param = 0x20;
1515 
1516         address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
1517         status = ath6kl_bmi_reg_write(ar, address, param);
1518         if (status)
1519             return status;
1520 
1521         address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
1522         status = ath6kl_bmi_reg_write(ar, address, param);
1523         if (status)
1524             return status;
1525 
1526         address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
1527         status = ath6kl_bmi_reg_write(ar, address, param);
1528         if (status)
1529             return status;
1530 
1531         address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
1532         status = ath6kl_bmi_reg_write(ar, address, param);
1533         if (status)
1534             return status;
1535     }
1536 
1537     /* write EEPROM data to Target RAM */
1538     status = ath6kl_upload_board_file(ar);
1539     if (status)
1540         return status;
1541 
1542     /* transfer One time Programmable data */
1543     status = ath6kl_upload_otp(ar);
1544     if (status)
1545         return status;
1546 
1547     /* Download Target firmware */
1548     status = ath6kl_upload_firmware(ar);
1549     if (status)
1550         return status;
1551 
1552     status = ath6kl_upload_patch(ar);
1553     if (status)
1554         return status;
1555 
1556     /* Download the test script */
1557     status = ath6kl_upload_testscript(ar);
1558     if (status)
1559         return status;
1560 
1561     /* Restore system sleep */
1562     address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1563     status = ath6kl_bmi_reg_write(ar, address, sleep);
1564     if (status)
1565         return status;
1566 
1567     address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1568     param = options | 0x20;
1569     status = ath6kl_bmi_reg_write(ar, address, param);
1570     if (status)
1571         return status;
1572 
1573     return status;
1574 }
1575 
1576 int ath6kl_init_hw_params(struct ath6kl *ar)
1577 {
1578     const struct ath6kl_hw *hw;
1579     int i;
1580 
1581     for (i = 0; i < ARRAY_SIZE(hw_list); i++) {
1582         hw = &hw_list[i];
1583 
1584         if (hw->id == ar->version.target_ver)
1585             break;
1586     }
1587 
1588     if (i == ARRAY_SIZE(hw_list)) {
1589         ath6kl_err("Unsupported hardware version: 0x%x\n",
1590                ar->version.target_ver);
1591         return -EINVAL;
1592     }
1593 
1594     ar->hw = *hw;
1595 
1596     ath6kl_dbg(ATH6KL_DBG_BOOT,
1597            "target_ver 0x%x target_type 0x%x dataset_patch 0x%x app_load_addr 0x%x\n",
1598            ar->version.target_ver, ar->target_type,
1599            ar->hw.dataset_patch_addr, ar->hw.app_load_addr);
1600     ath6kl_dbg(ATH6KL_DBG_BOOT,
1601            "app_start_override_addr 0x%x board_ext_data_addr 0x%x reserved_ram_size 0x%x",
1602            ar->hw.app_start_override_addr, ar->hw.board_ext_data_addr,
1603            ar->hw.reserved_ram_size);
1604     ath6kl_dbg(ATH6KL_DBG_BOOT,
1605            "refclk_hz %d uarttx_pin %d",
1606            ar->hw.refclk_hz, ar->hw.uarttx_pin);
1607 
1608     return 0;
1609 }
1610 
1611 static const char *ath6kl_init_get_hif_name(enum ath6kl_hif_type type)
1612 {
1613     switch (type) {
1614     case ATH6KL_HIF_TYPE_SDIO:
1615         return "sdio";
1616     case ATH6KL_HIF_TYPE_USB:
1617         return "usb";
1618     }
1619 
1620     return NULL;
1621 }
1622 
1623 
1624 static const struct fw_capa_str_map {
1625     int id;
1626     const char *name;
1627 } fw_capa_map[] = {
1628     { ATH6KL_FW_CAPABILITY_HOST_P2P, "host-p2p" },
1629     { ATH6KL_FW_CAPABILITY_SCHED_SCAN, "sched-scan" },
1630     { ATH6KL_FW_CAPABILITY_STA_P2PDEV_DUPLEX, "sta-p2pdev-duplex" },
1631     { ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, "inactivity-timeout" },
1632     { ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, "rsn-cap-override" },
1633     { ATH6KL_FW_CAPABILITY_WOW_MULTICAST_FILTER, "wow-mc-filter" },
1634     { ATH6KL_FW_CAPABILITY_BMISS_ENHANCE, "bmiss-enhance" },
1635     { ATH6KL_FW_CAPABILITY_SCHED_SCAN_MATCH_LIST, "sscan-match-list" },
1636     { ATH6KL_FW_CAPABILITY_RSSI_SCAN_THOLD, "rssi-scan-thold" },
1637     { ATH6KL_FW_CAPABILITY_CUSTOM_MAC_ADDR, "custom-mac-addr" },
1638     { ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY, "tx-err-notify" },
1639     { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
1640     { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
1641     { ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
1642     { ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
1643     { ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
1644     { ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
1645     { ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
1646     { ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
1647 };
1648 
1649 static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
1650 {
1651     int i;
1652 
1653     for (i = 0; i < ARRAY_SIZE(fw_capa_map); i++) {
1654         if (fw_capa_map[i].id == id)
1655             return fw_capa_map[i].name;
1656     }
1657 
1658     return "<unknown>";
1659 }
1660 
1661 static void ath6kl_init_get_fwcaps(struct ath6kl *ar, char *buf, size_t buf_len)
1662 {
1663     u8 *data = (u8 *) ar->fw_capabilities;
1664     size_t trunc_len, len = 0;
1665     int i, index, bit;
1666     char *trunc = "...";
1667 
1668     for (i = 0; i < ATH6KL_FW_CAPABILITY_MAX; i++) {
1669         index = i / 8;
1670         bit = i % 8;
1671 
1672         if (index >= sizeof(ar->fw_capabilities) * 4)
1673             break;
1674 
1675         if (buf_len - len < 4) {
1676             ath6kl_warn("firmware capability buffer too small!\n");
1677 
1678             /* add "..." to the end of string */
1679             trunc_len = strlen(trunc) + 1;
1680             strncpy(buf + buf_len - trunc_len, trunc, trunc_len);
1681 
1682             return;
1683         }
1684 
1685         if (data[index] & (1 << bit)) {
1686             len += scnprintf(buf + len, buf_len - len, "%s,",
1687                         ath6kl_init_get_fw_capa_name(i));
1688         }
1689     }
1690 
1691     /* overwrite the last comma */
1692     if (len > 0)
1693         len--;
1694 
1695     buf[len] = '\0';
1696 }
1697 
1698 static int ath6kl_init_hw_reset(struct ath6kl *ar)
1699 {
1700     ath6kl_dbg(ATH6KL_DBG_BOOT, "cold resetting the device");
1701 
1702     return ath6kl_diag_write32(ar, RESET_CONTROL_ADDRESS,
1703                    cpu_to_le32(RESET_CONTROL_COLD_RST));
1704 }
1705 
1706 static int __ath6kl_init_hw_start(struct ath6kl *ar)
1707 {
1708     long timeleft;
1709     int ret, i;
1710     char buf[200];
1711 
1712     ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
1713 
1714     ret = ath6kl_hif_power_on(ar);
1715     if (ret)
1716         return ret;
1717 
1718     ret = ath6kl_configure_target(ar);
1719     if (ret)
1720         goto err_power_off;
1721 
1722     ret = ath6kl_init_upload(ar);
1723     if (ret)
1724         goto err_power_off;
1725 
1726     /* Do we need to finish the BMI phase */
1727     ret = ath6kl_bmi_done(ar);
1728     if (ret)
1729         goto err_power_off;
1730 
1731     /*
1732      * The reason we have to wait for the target here is that the
1733      * driver layer has to init BMI in order to set the host block
1734      * size.
1735      */
1736     ret = ath6kl_htc_wait_target(ar->htc_target);
1737 
1738     if (ret == -ETIMEDOUT) {
1739         /*
1740          * Most likely USB target is in odd state after reboot and
1741          * needs a reset. A cold reset makes the whole device
1742          * disappear from USB bus and initialisation starts from
1743          * beginning.
1744          */
1745         ath6kl_warn("htc wait target timed out, resetting device\n");
1746         ath6kl_init_hw_reset(ar);
1747         goto err_power_off;
1748     } else if (ret) {
1749         ath6kl_err("htc wait target failed: %d\n", ret);
1750         goto err_power_off;
1751     }
1752 
1753     ret = ath6kl_init_service_ep(ar);
1754     if (ret) {
1755         ath6kl_err("Endpoint service initialization failed: %d\n", ret);
1756         goto err_cleanup_scatter;
1757     }
1758 
1759     /* setup credit distribution */
1760     ath6kl_htc_credit_setup(ar->htc_target, &ar->credit_state_info);
1761 
1762     /* start HTC */
1763     ret = ath6kl_htc_start(ar->htc_target);
1764     if (ret) {
1765         /* FIXME: call this */
1766         ath6kl_cookie_cleanup(ar);
1767         goto err_cleanup_scatter;
1768     }
1769 
1770     /* Wait for Wmi event to be ready */
1771     timeleft = wait_event_interruptible_timeout(ar->event_wq,
1772                             test_bit(WMI_READY,
1773                                  &ar->flag),
1774                             WMI_TIMEOUT);
1775     if (timeleft <= 0) {
1776         clear_bit(WMI_READY, &ar->flag);
1777         ath6kl_err("wmi is not ready or wait was interrupted: %ld\n",
1778                timeleft);
1779         ret = -EIO;
1780         goto err_htc_stop;
1781     }
1782 
1783     ath6kl_dbg(ATH6KL_DBG_BOOT, "firmware booted\n");
1784 
1785     if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
1786         ath6kl_info("%s %s fw %s api %d%s\n",
1787                 ar->hw.name,
1788                 ath6kl_init_get_hif_name(ar->hif_type),
1789                 ar->wiphy->fw_version,
1790                 ar->fw_api,
1791                 test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
1792         ath6kl_init_get_fwcaps(ar, buf, sizeof(buf));
1793         ath6kl_info("firmware supports: %s\n", buf);
1794     }
1795 
1796     if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1797         ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1798                ATH6KL_ABI_VERSION, ar->version.abi_ver);
1799         ret = -EIO;
1800         goto err_htc_stop;
1801     }
1802 
1803     ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1804 
1805     /* communicate the wmi protocol verision to the target */
1806     /* FIXME: return error */
1807     if ((ath6kl_set_host_app_area(ar)) != 0)
1808         ath6kl_err("unable to set the host app area\n");
1809 
1810     for (i = 0; i < ar->vif_max; i++) {
1811         ret = ath6kl_target_config_wlan_params(ar, i);
1812         if (ret)
1813             goto err_htc_stop;
1814     }
1815 
1816     return 0;
1817 
1818 err_htc_stop:
1819     ath6kl_htc_stop(ar->htc_target);
1820 err_cleanup_scatter:
1821     ath6kl_hif_cleanup_scatter(ar);
1822 err_power_off:
1823     ath6kl_hif_power_off(ar);
1824 
1825     return ret;
1826 }
1827 
1828 int ath6kl_init_hw_start(struct ath6kl *ar)
1829 {
1830     int err;
1831 
1832     err = __ath6kl_init_hw_start(ar);
1833     if (err)
1834         return err;
1835     ar->state = ATH6KL_STATE_ON;
1836     return 0;
1837 }
1838 
1839 static int __ath6kl_init_hw_stop(struct ath6kl *ar)
1840 {
1841     int ret;
1842 
1843     ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
1844 
1845     ath6kl_htc_stop(ar->htc_target);
1846 
1847     ath6kl_hif_stop(ar);
1848 
1849     ath6kl_bmi_reset(ar);
1850 
1851     ret = ath6kl_hif_power_off(ar);
1852     if (ret)
1853         ath6kl_warn("failed to power off hif: %d\n", ret);
1854 
1855     return 0;
1856 }
1857 
1858 int ath6kl_init_hw_stop(struct ath6kl *ar)
1859 {
1860     int err;
1861 
1862     err = __ath6kl_init_hw_stop(ar);
1863     if (err)
1864         return err;
1865     ar->state = ATH6KL_STATE_OFF;
1866     return 0;
1867 }
1868 
1869 void ath6kl_init_hw_restart(struct ath6kl *ar)
1870 {
1871     clear_bit(WMI_READY, &ar->flag);
1872 
1873     ath6kl_cfg80211_stop_all(ar);
1874 
1875     if (__ath6kl_init_hw_stop(ar)) {
1876         ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to stop during fw error recovery\n");
1877         return;
1878     }
1879 
1880     if (__ath6kl_init_hw_start(ar)) {
1881         ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Failed to restart during fw error recovery\n");
1882         return;
1883     }
1884 }
1885 
1886 void ath6kl_stop_txrx(struct ath6kl *ar)
1887 {
1888     struct ath6kl_vif *vif, *tmp_vif;
1889     int i;
1890 
1891     set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1892 
1893     if (down_interruptible(&ar->sem)) {
1894         ath6kl_err("down_interruptible failed\n");
1895         return;
1896     }
1897 
1898     for (i = 0; i < AP_MAX_NUM_STA; i++)
1899         aggr_reset_state(ar->sta_list[i].aggr_conn);
1900 
1901     spin_lock_bh(&ar->list_lock);
1902     list_for_each_entry_safe(vif, tmp_vif, &ar->vif_list, list) {
1903         list_del(&vif->list);
1904         spin_unlock_bh(&ar->list_lock);
1905         ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag));
1906         rtnl_lock();
1907         wiphy_lock(ar->wiphy);
1908         ath6kl_cfg80211_vif_cleanup(vif);
1909         wiphy_unlock(ar->wiphy);
1910         rtnl_unlock();
1911         spin_lock_bh(&ar->list_lock);
1912     }
1913     spin_unlock_bh(&ar->list_lock);
1914 
1915     clear_bit(WMI_READY, &ar->flag);
1916 
1917     if (ar->fw_recovery.enable)
1918         del_timer_sync(&ar->fw_recovery.hb_timer);
1919 
1920     /*
1921      * After wmi_shudown all WMI events will be dropped. We
1922      * need to cleanup the buffers allocated in AP mode and
1923      * give disconnect notification to stack, which usually
1924      * happens in the disconnect_event. Simulate the disconnect
1925      * event by calling the function directly. Sometimes
1926      * disconnect_event will be received when the debug logs
1927      * are collected.
1928      */
1929     ath6kl_wmi_shutdown(ar->wmi);
1930 
1931     clear_bit(WMI_ENABLED, &ar->flag);
1932     if (ar->htc_target) {
1933         ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
1934         ath6kl_htc_stop(ar->htc_target);
1935     }
1936 
1937     /*
1938      * Try to reset the device if we can. The driver may have been
1939      * configure NOT to reset the target during a debug session.
1940      */
1941     ath6kl_init_hw_reset(ar);
1942 
1943     up(&ar->sem);
1944 }
1945 EXPORT_SYMBOL(ath6kl_stop_txrx);