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