1/* 2 * This file is part of wl1271 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * 6 * Contact: Luciano Coelho <luciano.coelho@nokia.com> 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * version 2 as published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 20 * 02110-1301 USA 21 * 22 */ 23 24#include <linux/kernel.h> 25#include <linux/module.h> 26#include <linux/slab.h> 27 28#include "wl1271_init.h" 29#include "wl12xx_80211.h" 30#include "wl1271_acx.h" 31#include "wl1271_cmd.h" 32#include "wl1271_reg.h" 33 34static int wl1271_init_hwenc_config(struct wl1271 *wl) 35{ 36 int ret; 37 38 ret = wl1271_acx_feature_cfg(wl); 39 if (ret < 0) { 40 wl1271_warning("couldn't set feature config"); 41 return ret; 42 } 43 44 ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key); 45 if (ret < 0) { 46 wl1271_warning("couldn't set default key"); 47 return ret; 48 } 49 50 return 0; 51} 52 53int wl1271_init_templates_config(struct wl1271 *wl) 54{ 55 int ret, i; 56 57 /* send empty templates for fw memory reservation */ 58 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, 59 sizeof(struct wl12xx_probe_req_template), 60 0, WL1271_RATE_AUTOMATIC); 61 if (ret < 0) 62 return ret; 63 64 if (wl1271_11a_enabled()) { 65 size_t size = sizeof(struct wl12xx_probe_req_template); 66 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, 67 NULL, size, 0, 68 WL1271_RATE_AUTOMATIC); 69 if (ret < 0) 70 return ret; 71 } 72 73 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, 74 sizeof(struct wl12xx_null_data_template), 75 0, WL1271_RATE_AUTOMATIC); 76 if (ret < 0) 77 return ret; 78 79 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, 80 sizeof(struct wl12xx_ps_poll_template), 81 0, WL1271_RATE_AUTOMATIC); 82 if (ret < 0) 83 return ret; 84 85 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, 86 sizeof 87 (struct wl12xx_qos_null_data_template), 88 0, WL1271_RATE_AUTOMATIC); 89 if (ret < 0) 90 return ret; 91 92 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, 93 sizeof 94 (struct wl12xx_probe_resp_template), 95 0, WL1271_RATE_AUTOMATIC); 96 if (ret < 0) 97 return ret; 98 99 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, 100 sizeof 101 (struct wl12xx_beacon_template), 102 0, WL1271_RATE_AUTOMATIC); 103 if (ret < 0) 104 return ret; 105 106 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { 107 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, 108 WL1271_CMD_TEMPL_MAX_SIZE, i, 109 WL1271_RATE_AUTOMATIC); 110 if (ret < 0) 111 return ret; 112 } 113 114 return 0; 115} 116 117static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) 118{ 119 int ret; 120 121 ret = wl1271_acx_rx_msdu_life_time(wl); 122 if (ret < 0) 123 return ret; 124 125 ret = wl1271_acx_rx_config(wl, config, filter); 126 if (ret < 0) 127 return ret; 128 129 return 0; 130} 131 132int wl1271_init_phy_config(struct wl1271 *wl) 133{ 134 int ret; 135 136 ret = wl1271_acx_pd_threshold(wl); 137 if (ret < 0) 138 return ret; 139 140 ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME); 141 if (ret < 0) 142 return ret; 143 144 ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0); 145 if (ret < 0) 146 return ret; 147 148 ret = wl1271_acx_service_period_timeout(wl); 149 if (ret < 0) 150 return ret; 151 152 ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold); 153 if (ret < 0) 154 return ret; 155 156 return 0; 157} 158 159static int wl1271_init_beacon_filter(struct wl1271 *wl) 160{ 161 int ret; 162 163 /* disable beacon filtering at this stage */ 164 ret = wl1271_acx_beacon_filter_opt(wl, false); 165 if (ret < 0) 166 return ret; 167 168 ret = wl1271_acx_beacon_filter_table(wl); 169 if (ret < 0) 170 return ret; 171 172 return 0; 173} 174 175int wl1271_init_pta(struct wl1271 *wl) 176{ 177 int ret; 178 179 ret = wl1271_acx_sg_cfg(wl); 180 if (ret < 0) 181 return ret; 182 183 ret = wl1271_acx_sg_enable(wl, wl->sg_enabled); 184 if (ret < 0) 185 return ret; 186 187 return 0; 188} 189 190int wl1271_init_energy_detection(struct wl1271 *wl) 191{ 192 int ret; 193 194 ret = wl1271_acx_cca_threshold(wl); 195 if (ret < 0) 196 return ret; 197 198 return 0; 199} 200 201static int wl1271_init_beacon_broadcast(struct wl1271 *wl) 202{ 203 int ret; 204 205 ret = wl1271_acx_bcn_dtim_options(wl); 206 if (ret < 0) 207 return ret; 208 209 return 0; 210} 211 212int wl1271_hw_init(struct wl1271 *wl) 213{ 214 struct conf_tx_ac_category *conf_ac; 215 struct conf_tx_tid *conf_tid; 216 int ret, i; 217 218 ret = wl1271_cmd_general_parms(wl); 219 if (ret < 0) 220 return ret; 221 222 ret = wl1271_cmd_radio_parms(wl); 223 if (ret < 0) 224 return ret; 225 226 /* Template settings */ 227 ret = wl1271_init_templates_config(wl); 228 if (ret < 0) 229 return ret; 230 231 /* Default memory configuration */ 232 ret = wl1271_acx_init_mem_config(wl); 233 if (ret < 0) 234 return ret; 235 236 /* RX config */ 237 ret = wl1271_init_rx_config(wl, 238 RX_CFG_PROMISCUOUS | RX_CFG_TSF, 239 RX_FILTER_OPTION_DEF); 240 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, 241 RX_FILTER_OPTION_FILTER_ALL); */ 242 if (ret < 0) 243 goto out_free_memmap; 244 245 /* PHY layer config */ 246 ret = wl1271_init_phy_config(wl); 247 if (ret < 0) 248 goto out_free_memmap; 249 250 ret = wl1271_acx_dco_itrim_params(wl); 251 if (ret < 0) 252 goto out_free_memmap; 253 254 /* Initialize connection monitoring thresholds */ 255 ret = wl1271_acx_conn_monit_params(wl, false); 256 if (ret < 0) 257 goto out_free_memmap; 258 259 /* Beacon filtering */ 260 ret = wl1271_init_beacon_filter(wl); 261 if (ret < 0) 262 goto out_free_memmap; 263 264 /* Configure TX patch complete interrupt behavior */ 265 ret = wl1271_acx_tx_config_options(wl); 266 if (ret < 0) 267 goto out_free_memmap; 268 269 /* RX complete interrupt pacing */ 270 ret = wl1271_acx_init_rx_interrupt(wl); 271 if (ret < 0) 272 goto out_free_memmap; 273 274 /* Bluetooth WLAN coexistence */ 275 ret = wl1271_init_pta(wl); 276 if (ret < 0) 277 goto out_free_memmap; 278 279 /* Energy detection */ 280 ret = wl1271_init_energy_detection(wl); 281 if (ret < 0) 282 goto out_free_memmap; 283 284 /* Beacons and boradcast settings */ 285 ret = wl1271_init_beacon_broadcast(wl); 286 if (ret < 0) 287 goto out_free_memmap; 288 289 /* Default fragmentation threshold */ 290 ret = wl1271_acx_frag_threshold(wl); 291 if (ret < 0) 292 goto out_free_memmap; 293 294 /* Default TID configuration */ 295 for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { 296 conf_tid = &wl->conf.tx.tid_conf[i]; 297 ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, 298 conf_tid->channel_type, 299 conf_tid->tsid, 300 conf_tid->ps_scheme, 301 conf_tid->ack_policy, 302 conf_tid->apsd_conf[0], 303 conf_tid->apsd_conf[1]); 304 if (ret < 0) 305 goto out_free_memmap; 306 } 307 308 /* Default AC configuration */ 309 for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { 310 conf_ac = &wl->conf.tx.ac_conf[i]; 311 ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, 312 conf_ac->cw_max, conf_ac->aifsn, 313 conf_ac->tx_op_limit); 314 if (ret < 0) 315 goto out_free_memmap; 316 } 317 318 /* Configure TX rate classes */ 319 ret = wl1271_acx_rate_policies(wl); 320 if (ret < 0) 321 goto out_free_memmap; 322 323 /* Enable data path */ 324 ret = wl1271_cmd_data_path(wl, 1); 325 if (ret < 0) 326 goto out_free_memmap; 327 328 /* Configure for ELP power saving */ 329 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); 330 if (ret < 0) 331 goto out_free_memmap; 332 333 /* Configure HW encryption */ 334 ret = wl1271_init_hwenc_config(wl); 335 if (ret < 0) 336 goto out_free_memmap; 337 338 /* configure PM */ 339 ret = wl1271_acx_pm_config(wl); 340 if (ret < 0) 341 goto out_free_memmap; 342 343 /* disable all keep-alive templates */ 344 for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { 345 ret = wl1271_acx_keep_alive_config(wl, i, 346 ACX_KEEP_ALIVE_TPL_INVALID); 347 if (ret < 0) 348 goto out_free_memmap; 349 } 350 351 /* disable the keep-alive feature */ 352 ret = wl1271_acx_keep_alive_mode(wl, false); 353 if (ret < 0) 354 goto out_free_memmap; 355 356 /* Configure rssi/snr averaging weights */ 357 ret = wl1271_acx_rssi_snr_avg_weights(wl); 358 if (ret < 0) 359 goto out_free_memmap; 360 361 return 0; 362 363 out_free_memmap: 364 kfree(wl->target_mem_map); 365 wl->target_mem_map = NULL; 366 367 return ret; 368} 369