cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}