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 18 int 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 37 int 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 89 int 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 104 int 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 131 int 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 147 int 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 162 int 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 173 int 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 184 int wl1251_hw_init_power_auth(struct wl1251 *wl) 185 { 186 return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); 187 } 188 189 int 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_obj(struct wl1251_acx_mem_map); 198 if (!wl->target_mem_map) { 199 wl1251_error("couldn't allocate target memory map"); 200 return -ENOMEM; 201 } 202 203 /* we now ask for the firmware built memory map */ 204 ret = wl1251_acx_mem_map(wl, wl->target_mem_map, 205 sizeof(struct wl1251_acx_mem_map)); 206 if (ret < 0) { 207 wl1251_error("couldn't retrieve firmware memory map"); 208 kfree(wl->target_mem_map); 209 wl->target_mem_map = NULL; 210 return ret; 211 } 212 213 return 0; 214 } 215 216 static int wl1251_hw_init_txq_fill(u8 qid, 217 struct acx_tx_queue_qos_config *config, 218 u32 num_blocks) 219 { 220 config->qid = qid; 221 222 switch (qid) { 223 case QOS_AC_BE: 224 config->high_threshold = 225 (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; 226 config->low_threshold = 227 (QOS_TX_LOW_BE_DEF * num_blocks) / 100; 228 break; 229 case QOS_AC_BK: 230 config->high_threshold = 231 (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; 232 config->low_threshold = 233 (QOS_TX_LOW_BK_DEF * num_blocks) / 100; 234 break; 235 case QOS_AC_VI: 236 config->high_threshold = 237 (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; 238 config->low_threshold = 239 (QOS_TX_LOW_VI_DEF * num_blocks) / 100; 240 break; 241 case QOS_AC_VO: 242 config->high_threshold = 243 (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; 244 config->low_threshold = 245 (QOS_TX_LOW_VO_DEF * num_blocks) / 100; 246 break; 247 default: 248 wl1251_error("Invalid TX queue id: %d", qid); 249 return -EINVAL; 250 } 251 252 return 0; 253 } 254 255 static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) 256 { 257 struct acx_tx_queue_qos_config *config; 258 struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; 259 int ret, i; 260 261 wl1251_debug(DEBUG_ACX, "acx tx queue config"); 262 263 config = kzalloc_obj(*config); 264 if (!config) { 265 ret = -ENOMEM; 266 goto out; 267 } 268 269 for (i = 0; i < MAX_NUM_OF_AC; i++) { 270 ret = wl1251_hw_init_txq_fill(i, config, 271 wl_mem_map->num_tx_mem_blocks); 272 if (ret < 0) 273 goto out; 274 275 ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG, 276 config, sizeof(*config)); 277 if (ret < 0) 278 goto out; 279 } 280 281 wl1251_acx_ac_cfg(wl, AC_BE, CWMIN_BE, CWMAX_BE, AIFS_DIFS, TXOP_BE); 282 wl1251_acx_ac_cfg(wl, AC_BK, CWMIN_BK, CWMAX_BK, AIFS_DIFS, TXOP_BK); 283 wl1251_acx_ac_cfg(wl, AC_VI, CWMIN_VI, CWMAX_VI, AIFS_DIFS, TXOP_VI); 284 wl1251_acx_ac_cfg(wl, AC_VO, CWMIN_VO, CWMAX_VO, AIFS_DIFS, TXOP_VO); 285 286 out: 287 kfree(config); 288 return ret; 289 } 290 291 static int wl1251_hw_init_data_path_config(struct wl1251 *wl) 292 { 293 int ret; 294 295 /* asking for the data path parameters */ 296 wl->data_path = kzalloc_obj(struct acx_data_path_params_resp); 297 if (!wl->data_path) 298 return -ENOMEM; 299 300 ret = wl1251_acx_data_path_params(wl, wl->data_path); 301 if (ret < 0) { 302 kfree(wl->data_path); 303 wl->data_path = NULL; 304 return ret; 305 } 306 307 return 0; 308 } 309 310 311 int wl1251_hw_init(struct wl1251 *wl) 312 { 313 struct wl1251_acx_mem_map *wl_mem_map; 314 int ret; 315 316 ret = wl1251_hw_init_hwenc_config(wl); 317 if (ret < 0) 318 return ret; 319 320 /* Template settings */ 321 ret = wl1251_hw_init_templates_config(wl); 322 if (ret < 0) 323 return ret; 324 325 /* Default memory configuration */ 326 ret = wl1251_hw_init_mem_config(wl); 327 if (ret < 0) 328 return ret; 329 330 /* Default data path configuration */ 331 ret = wl1251_hw_init_data_path_config(wl); 332 if (ret < 0) 333 goto out_free_memmap; 334 335 /* RX config */ 336 ret = wl1251_hw_init_rx_config(wl, 337 RX_CFG_PROMISCUOUS | RX_CFG_TSF, 338 RX_FILTER_OPTION_DEF); 339 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, 340 RX_FILTER_OPTION_FILTER_ALL); */ 341 if (ret < 0) 342 goto out_free_data_path; 343 344 /* TX queues config */ 345 ret = wl1251_hw_init_tx_queue_config(wl); 346 if (ret < 0) 347 goto out_free_data_path; 348 349 /* PHY layer config */ 350 ret = wl1251_hw_init_phy_config(wl); 351 if (ret < 0) 352 goto out_free_data_path; 353 354 /* Initialize connection monitoring thresholds */ 355 ret = wl1251_acx_conn_monit_params(wl); 356 if (ret < 0) 357 goto out_free_data_path; 358 359 /* Beacon filtering */ 360 ret = wl1251_hw_init_beacon_filter(wl); 361 if (ret < 0) 362 goto out_free_data_path; 363 364 /* Bluetooth WLAN coexistence */ 365 ret = wl1251_hw_init_pta(wl); 366 if (ret < 0) 367 goto out_free_data_path; 368 369 /* Energy detection */ 370 ret = wl1251_hw_init_energy_detection(wl); 371 if (ret < 0) 372 goto out_free_data_path; 373 374 /* Beacons and broadcast settings */ 375 ret = wl1251_hw_init_beacon_broadcast(wl); 376 if (ret < 0) 377 goto out_free_data_path; 378 379 /* Enable rx data path */ 380 ret = wl1251_cmd_data_path_rx(wl, wl->channel, 1); 381 if (ret < 0) 382 goto out_free_data_path; 383 384 /* Enable tx data path */ 385 ret = wl1251_cmd_data_path_tx(wl, wl->channel, 1); 386 if (ret < 0) 387 goto out_free_data_path; 388 389 /* Default power state */ 390 ret = wl1251_hw_init_power_auth(wl); 391 if (ret < 0) 392 goto out_free_data_path; 393 394 wl_mem_map = wl->target_mem_map; 395 wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", 396 wl_mem_map->num_tx_mem_blocks, 397 wl->data_path->tx_control_addr, 398 wl_mem_map->num_rx_mem_blocks, 399 wl->data_path->rx_control_addr); 400 401 return 0; 402 403 out_free_data_path: 404 kfree(wl->data_path); 405 406 out_free_memmap: 407 kfree(wl->target_mem_map); 408 409 return ret; 410 } 411