1/* 2 * This file is part of wl1251 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * 6 * Contact: Kalle Valo <kalle.valo@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 "wl1251_init.h" 29#include "wl12xx_80211.h" 30#include "wl1251_acx.h" 31#include "wl1251_cmd.h" 32#include "wl1251_reg.h" 33 34int wl1251_hw_init_hwenc_config(struct wl1251 *wl) 35{ 36 int ret; 37 38 ret = wl1251_acx_feature_cfg(wl); 39 if (ret < 0) { 40 wl1251_warning("couldn't set feature config"); 41 return ret; 42 } 43 44 ret = wl1251_acx_default_key(wl, wl->default_key); 45 if (ret < 0) { 46 wl1251_warning("couldn't set default key"); 47 return ret; 48 } 49 50 return 0; 51} 52 53int wl1251_hw_init_templates_config(struct wl1251 *wl) 54{ 55 int ret; 56 u8 partial_vbm[PARTIAL_VBM_MAX]; 57 58 /* send empty templates for fw memory reservation */ 59 ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL, 60 sizeof(struct wl12xx_probe_req_template)); 61 if (ret < 0) 62 return ret; 63 64 ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL, 65 sizeof(struct wl12xx_null_data_template)); 66 if (ret < 0) 67 return ret; 68 69 ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL, 70 sizeof(struct wl12xx_ps_poll_template)); 71 if (ret < 0) 72 return ret; 73 74 ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL, 75 sizeof 76 (struct wl12xx_qos_null_data_template)); 77 if (ret < 0) 78 return ret; 79 80 ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL, 81 sizeof 82 (struct wl12xx_probe_resp_template)); 83 if (ret < 0) 84 return ret; 85 86 ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL, 87 sizeof 88 (struct wl12xx_beacon_template)); 89 if (ret < 0) 90 return ret; 91 92 /* tim templates, first reserve space then allocate an empty one */ 93 memset(partial_vbm, 0, PARTIAL_VBM_MAX); 94 ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0); 95 if (ret < 0) 96 return ret; 97 98 ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0); 99 if (ret < 0) 100 return ret; 101 102 return 0; 103} 104 105int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter) 106{ 107 int ret; 108 109 ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); 110 if (ret < 0) 111 return ret; 112 113 ret = wl1251_acx_rx_config(wl, config, filter); 114 if (ret < 0) 115 return ret; 116 117 return 0; 118} 119 120int wl1251_hw_init_phy_config(struct wl1251 *wl) 121{ 122 int ret; 123 124 ret = wl1251_acx_pd_threshold(wl); 125 if (ret < 0) 126 return ret; 127 128 ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME); 129 if (ret < 0) 130 return ret; 131 132 ret = wl1251_acx_group_address_tbl(wl); 133 if (ret < 0) 134 return ret; 135 136 ret = wl1251_acx_service_period_timeout(wl); 137 if (ret < 0) 138 return ret; 139 140 ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); 141 if (ret < 0) 142 return ret; 143 144 return 0; 145} 146 147int wl1251_hw_init_beacon_filter(struct wl1251 *wl) 148{ 149 int ret; 150 151 /* disable beacon filtering at this stage */ 152 ret = wl1251_acx_beacon_filter_opt(wl, false); 153 if (ret < 0) 154 return ret; 155 156 ret = wl1251_acx_beacon_filter_table(wl); 157 if (ret < 0) 158 return ret; 159 160 return 0; 161} 162 163int wl1251_hw_init_pta(struct wl1251 *wl) 164{ 165 int ret; 166 167 ret = wl1251_acx_sg_enable(wl); 168 if (ret < 0) 169 return ret; 170 171 ret = wl1251_acx_sg_cfg(wl); 172 if (ret < 0) 173 return ret; 174 175 return 0; 176} 177 178int wl1251_hw_init_energy_detection(struct wl1251 *wl) 179{ 180 int ret; 181 182 ret = wl1251_acx_cca_threshold(wl); 183 if (ret < 0) 184 return ret; 185 186 return 0; 187} 188 189int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl) 190{ 191 int ret; 192 193 ret = wl1251_acx_bcn_dtim_options(wl); 194 if (ret < 0) 195 return ret; 196 197 return 0; 198} 199 200int wl1251_hw_init_power_auth(struct wl1251 *wl) 201{ 202 return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); 203} 204 205int wl1251_hw_init_mem_config(struct wl1251 *wl) 206{ 207 int ret; 208 209 ret = wl1251_acx_mem_cfg(wl); 210 if (ret < 0) 211 return ret; 212 213 wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), 214 GFP_KERNEL); 215 if (!wl->target_mem_map) { 216 wl1251_error("couldn't allocate target memory map"); 217 return -ENOMEM; 218 } 219 220 /* we now ask for the firmware built memory map */ 221 ret = wl1251_acx_mem_map(wl, wl->target_mem_map, 222 sizeof(struct wl1251_acx_mem_map)); 223 if (ret < 0) { 224 wl1251_error("couldn't retrieve firmware memory map"); 225 kfree(wl->target_mem_map); 226 wl->target_mem_map = NULL; 227 return ret; 228 } 229 230 return 0; 231} 232 233static int wl1251_hw_init_txq_fill(u8 qid, 234 struct acx_tx_queue_qos_config *config, 235 u32 num_blocks) 236{ 237 config->qid = qid; 238 239 switch (qid) { 240 case QOS_AC_BE: 241 config->high_threshold = 242 (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; 243 config->low_threshold = 244 (QOS_TX_LOW_BE_DEF * num_blocks) / 100; 245 break; 246 case QOS_AC_BK: 247 config->high_threshold = 248 (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; 249 config->low_threshold = 250 (QOS_TX_LOW_BK_DEF * num_blocks) / 100; 251 break; 252 case QOS_AC_VI: 253 config->high_threshold = 254 (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; 255 config->low_threshold = 256 (QOS_TX_LOW_VI_DEF * num_blocks) / 100; 257 break; 258 case QOS_AC_VO: 259 config->high_threshold = 260 (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; 261 config->low_threshold = 262 (QOS_TX_LOW_VO_DEF * num_blocks) / 100; 263 break; 264 default: 265 wl1251_error("Invalid TX queue id: %d", qid); 266 return -EINVAL; 267 } 268 269 return 0; 270} 271 272static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) 273{ 274 struct acx_tx_queue_qos_config *config; 275 struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; 276 int ret, i; 277 278 wl1251_debug(DEBUG_ACX, "acx tx queue config"); 279 280 config = kzalloc(sizeof(*config), GFP_KERNEL); 281 if (!config) { 282 ret = -ENOMEM; 283 goto out; 284 } 285 286 for (i = 0; i < MAX_NUM_OF_AC; i++) { 287 ret = wl1251_hw_init_txq_fill(i, config, 288 wl_mem_map->num_tx_mem_blocks); 289 if (ret < 0) 290 goto out; 291 292 ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG, 293 config, sizeof(*config)); 294 if (ret < 0) 295 goto out; 296 } 297 298 wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); 299 wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); 300 wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); 301 wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); 302 303out: 304 kfree(config); 305 return ret; 306} 307 308static int wl1251_hw_init_data_path_config(struct wl1251 *wl) 309{ 310 int ret; 311 312 /* asking for the data path parameters */ 313 wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), 314 GFP_KERNEL); 315 if (!wl->data_path) { 316 wl1251_error("Couldnt allocate data path parameters"); 317 return -ENOMEM; 318 } 319 320 ret = wl1251_acx_data_path_params(wl, wl->data_path); 321 if (ret < 0) { 322 kfree(wl->data_path); 323 wl->data_path = NULL; 324 return ret; 325 } 326 327 return 0; 328} 329 330 331int wl1251_hw_init(struct wl1251 *wl) 332{ 333 struct wl1251_acx_mem_map *wl_mem_map; 334 int ret; 335 336 ret = wl1251_hw_init_hwenc_config(wl); 337 if (ret < 0) 338 return ret; 339 340 /* Template settings */ 341 ret = wl1251_hw_init_templates_config(wl); 342 if (ret < 0) 343 return ret; 344 345 /* Default memory configuration */ 346 ret = wl1251_hw_init_mem_config(wl); 347 if (ret < 0) 348 return ret; 349 350 /* Default data path configuration */ 351 ret = wl1251_hw_init_data_path_config(wl); 352 if (ret < 0) 353 goto out_free_memmap; 354 355 /* RX config */ 356 ret = wl1251_hw_init_rx_config(wl, 357 RX_CFG_PROMISCUOUS | RX_CFG_TSF, 358 RX_FILTER_OPTION_DEF); 359 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, 360 RX_FILTER_OPTION_FILTER_ALL); */ 361 if (ret < 0) 362 goto out_free_data_path; 363 364 /* TX queues config */ 365 ret = wl1251_hw_init_tx_queue_config(wl); 366 if (ret < 0) 367 goto out_free_data_path; 368 369 /* PHY layer config */ 370 ret = wl1251_hw_init_phy_config(wl); 371 if (ret < 0) 372 goto out_free_data_path; 373 374 /* Initialize connection monitoring thresholds */ 375 ret = wl1251_acx_conn_monit_params(wl); 376 if (ret < 0) 377 goto out_free_data_path; 378 379 /* Beacon filtering */ 380 ret = wl1251_hw_init_beacon_filter(wl); 381 if (ret < 0) 382 goto out_free_data_path; 383 384 /* Bluetooth WLAN coexistence */ 385 ret = wl1251_hw_init_pta(wl); 386 if (ret < 0) 387 goto out_free_data_path; 388 389 /* Energy detection */ 390 ret = wl1251_hw_init_energy_detection(wl); 391 if (ret < 0) 392 goto out_free_data_path; 393 394 /* Beacons and boradcast settings */ 395 ret = wl1251_hw_init_beacon_broadcast(wl); 396 if (ret < 0) 397 goto out_free_data_path; 398 399 /* Enable data path */ 400 ret = wl1251_cmd_data_path(wl, wl->channel, 1); 401 if (ret < 0) 402 goto out_free_data_path; 403 404 /* Default power state */ 405 ret = wl1251_hw_init_power_auth(wl); 406 if (ret < 0) 407 goto out_free_data_path; 408 409 wl_mem_map = wl->target_mem_map; 410 wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", 411 wl_mem_map->num_tx_mem_blocks, 412 wl->data_path->tx_control_addr, 413 wl_mem_map->num_rx_mem_blocks, 414 wl->data_path->rx_control_addr); 415 416 return 0; 417 418 out_free_data_path: 419 kfree(wl->data_path); 420 421 out_free_memmap: 422 kfree(wl->target_mem_map); 423 424 return ret; 425} 426