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