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

cmd.c (11489B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include "cmd.h"
      3
      4#include <linux/module.h>
      5#include <linux/slab.h>
      6#include <linux/etherdevice.h>
      7
      8#include "wl1251.h"
      9#include "reg.h"
     10#include "io.h"
     11#include "ps.h"
     12#include "acx.h"
     13
     14/**
     15 * wl1251_cmd_send - Send command to firmware
     16 *
     17 * @wl: wl struct
     18 * @id: command id
     19 * @buf: buffer containing the command, must work with dma
     20 * @len: length of the buffer
     21 */
     22int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
     23{
     24	struct wl1251_cmd_header *cmd;
     25	unsigned long timeout;
     26	u32 intr;
     27	int ret = 0;
     28
     29	cmd = buf;
     30	cmd->id = id;
     31	cmd->status = 0;
     32
     33	WARN_ON(len % 4 != 0);
     34
     35	wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);
     36
     37	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
     38
     39	timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT);
     40
     41	intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
     42	while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) {
     43		if (time_after(jiffies, timeout)) {
     44			wl1251_error("command complete timeout");
     45			ret = -ETIMEDOUT;
     46			goto out;
     47		}
     48
     49		msleep(1);
     50
     51		intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
     52	}
     53
     54	wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
     55			   WL1251_ACX_INTR_CMD_COMPLETE);
     56
     57out:
     58	return ret;
     59}
     60
     61/**
     62 * wl1251_cmd_test - Send test command to firmware
     63 *
     64 * @wl: wl struct
     65 * @buf: buffer containing the command, with all headers, must work with dma
     66 * @buf_len: length of the buffer
     67 * @answer: is answer needed
     68 */
     69int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
     70{
     71	int ret;
     72
     73	wl1251_debug(DEBUG_CMD, "cmd test");
     74
     75	ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len);
     76
     77	if (ret < 0) {
     78		wl1251_warning("TEST command failed");
     79		return ret;
     80	}
     81
     82	if (answer) {
     83		struct wl1251_command *cmd_answer;
     84
     85		/*
     86		 * The test command got in, we can read the answer.
     87		 * The answer would be a wl1251_command, where the
     88		 * parameter array contains the actual answer.
     89		 */
     90		wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
     91
     92		cmd_answer = buf;
     93
     94		if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
     95			wl1251_error("TEST command answer error: %d",
     96				     cmd_answer->header.status);
     97	}
     98
     99	return 0;
    100}
    101
    102/**
    103 * wl1251_cmd_interrogate - Read acx from firmware
    104 *
    105 * @wl: wl struct
    106 * @id: acx id
    107 * @buf: buffer for the response, including all headers, must work with dma
    108 * @len: length of buf
    109 */
    110int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
    111{
    112	struct acx_header *acx = buf;
    113	int ret;
    114
    115	wl1251_debug(DEBUG_CMD, "cmd interrogate");
    116
    117	acx->id = id;
    118
    119	/* payload length, does not include any headers */
    120	acx->len = len - sizeof(*acx);
    121
    122	ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
    123	if (ret < 0) {
    124		wl1251_error("INTERROGATE command failed");
    125		goto out;
    126	}
    127
    128	/* the interrogate command got in, we can read the answer */
    129	wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);
    130
    131	acx = buf;
    132	if (acx->cmd.status != CMD_STATUS_SUCCESS)
    133		wl1251_error("INTERROGATE command error: %d",
    134			     acx->cmd.status);
    135
    136out:
    137	return ret;
    138}
    139
    140/**
    141 * wl1251_cmd_configure - Write acx value to firmware
    142 *
    143 * @wl: wl struct
    144 * @id: acx id
    145 * @buf: buffer containing acx, including all headers, must work with dma
    146 * @len: length of buf
    147 */
    148int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len)
    149{
    150	struct acx_header *acx = buf;
    151	int ret;
    152
    153	wl1251_debug(DEBUG_CMD, "cmd configure");
    154
    155	acx->id = id;
    156
    157	/* payload length, does not include any headers */
    158	acx->len = len - sizeof(*acx);
    159
    160	ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len);
    161	if (ret < 0) {
    162		wl1251_warning("CONFIGURE command NOK");
    163		return ret;
    164	}
    165
    166	return 0;
    167}
    168
    169int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
    170		   void *bitmap, u16 bitmap_len, u8 bitmap_control)
    171{
    172	struct wl1251_cmd_vbm_update *vbm;
    173	int ret;
    174
    175	wl1251_debug(DEBUG_CMD, "cmd vbm");
    176
    177	vbm = kzalloc(sizeof(*vbm), GFP_KERNEL);
    178	if (!vbm)
    179		return -ENOMEM;
    180
    181	/* Count and period will be filled by the target */
    182	vbm->tim.bitmap_ctrl = bitmap_control;
    183	if (bitmap_len > PARTIAL_VBM_MAX) {
    184		wl1251_warning("cmd vbm len is %d B, truncating to %d",
    185			       bitmap_len, PARTIAL_VBM_MAX);
    186		bitmap_len = PARTIAL_VBM_MAX;
    187	}
    188	memcpy(vbm->tim.pvb_field, bitmap, bitmap_len);
    189	vbm->tim.identity = identity;
    190	vbm->tim.length = bitmap_len + 3;
    191
    192	vbm->len = cpu_to_le16(bitmap_len + 5);
    193
    194	ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm));
    195	if (ret < 0) {
    196		wl1251_error("VBM command failed");
    197		goto out;
    198	}
    199
    200out:
    201	kfree(vbm);
    202	return ret;
    203}
    204
    205int wl1251_cmd_data_path_rx(struct wl1251 *wl, u8 channel, bool enable)
    206{
    207	struct cmd_enabledisable_path *cmd;
    208	int ret;
    209	u16 cmd_rx;
    210
    211	wl1251_debug(DEBUG_CMD, "cmd data path");
    212
    213	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    214	if (!cmd)
    215		return -ENOMEM;
    216
    217	cmd->channel = channel;
    218
    219	if (enable)
    220		cmd_rx = CMD_ENABLE_RX;
    221	else
    222		cmd_rx = CMD_DISABLE_RX;
    223
    224	ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
    225	if (ret < 0) {
    226		wl1251_error("rx %s cmd for channel %d failed",
    227			     enable ? "start" : "stop", channel);
    228		goto out;
    229	}
    230
    231	wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d",
    232		     enable ? "start" : "stop", channel);
    233
    234out:
    235	kfree(cmd);
    236	return ret;
    237}
    238
    239int wl1251_cmd_data_path_tx(struct wl1251 *wl, u8 channel, bool enable)
    240{
    241	struct cmd_enabledisable_path *cmd;
    242	int ret;
    243	u16 cmd_tx;
    244
    245	wl1251_debug(DEBUG_CMD, "cmd data path");
    246
    247	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    248	if (!cmd)
    249		return -ENOMEM;
    250
    251	cmd->channel = channel;
    252
    253	if (enable)
    254		cmd_tx = CMD_ENABLE_TX;
    255	else
    256		cmd_tx = CMD_DISABLE_TX;
    257
    258	ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
    259	if (ret < 0)
    260		wl1251_error("tx %s cmd for channel %d failed",
    261			     enable ? "start" : "stop", channel);
    262	else
    263		wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d",
    264			     enable ? "start" : "stop", channel);
    265
    266	kfree(cmd);
    267	return ret;
    268}
    269
    270int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
    271		    u16 beacon_interval, u8 dtim_interval)
    272{
    273	struct cmd_join *join;
    274	int ret, i;
    275	u8 *bssid;
    276
    277	join = kzalloc(sizeof(*join), GFP_KERNEL);
    278	if (!join)
    279		return -ENOMEM;
    280
    281	wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
    282		     bss_type == BSS_TYPE_IBSS ? " ibss" : "",
    283		     channel, beacon_interval, dtim_interval);
    284
    285	/* Reverse order BSSID */
    286	bssid = (u8 *) &join->bssid_lsb;
    287	for (i = 0; i < ETH_ALEN; i++)
    288		bssid[i] = wl->bssid[ETH_ALEN - i - 1];
    289
    290	join->rx_config_options = wl->rx_config;
    291	join->rx_filter_options = wl->rx_filter;
    292
    293	join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
    294		RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
    295
    296	join->beacon_interval = beacon_interval;
    297	join->dtim_interval = dtim_interval;
    298	join->bss_type = bss_type;
    299	join->channel = channel;
    300	join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;
    301
    302	ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
    303	if (ret < 0) {
    304		wl1251_error("failed to initiate cmd join");
    305		goto out;
    306	}
    307
    308out:
    309	kfree(join);
    310	return ret;
    311}
    312
    313int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
    314{
    315	struct wl1251_cmd_ps_params *ps_params = NULL;
    316	int ret = 0;
    317
    318	wl1251_debug(DEBUG_CMD, "cmd set ps mode");
    319
    320	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
    321	if (!ps_params)
    322		return -ENOMEM;
    323
    324	ps_params->ps_mode = ps_mode;
    325	ps_params->send_null_data = 1;
    326	ps_params->retries = 5;
    327	ps_params->hang_over_period = 128;
    328	ps_params->null_data_rate = 1; /* 1 Mbps */
    329
    330	ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
    331			      sizeof(*ps_params));
    332	if (ret < 0) {
    333		wl1251_error("cmd set_ps_mode failed");
    334		goto out;
    335	}
    336
    337out:
    338	kfree(ps_params);
    339	return ret;
    340}
    341
    342int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
    343			   size_t len)
    344{
    345	struct cmd_read_write_memory *cmd;
    346	int ret = 0;
    347
    348	wl1251_debug(DEBUG_CMD, "cmd read memory");
    349
    350	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    351	if (!cmd)
    352		return -ENOMEM;
    353
    354	WARN_ON(len > MAX_READ_SIZE);
    355	len = min_t(size_t, len, MAX_READ_SIZE);
    356
    357	cmd->addr = addr;
    358	cmd->size = len;
    359
    360	ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
    361	if (ret < 0) {
    362		wl1251_error("read memory command failed: %d", ret);
    363		goto out;
    364	}
    365
    366	/* the read command got in, we can now read the answer */
    367	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
    368
    369	if (cmd->header.status != CMD_STATUS_SUCCESS)
    370		wl1251_error("error in read command result: %d",
    371			     cmd->header.status);
    372
    373	memcpy(answer, cmd->value, len);
    374
    375out:
    376	kfree(cmd);
    377	return ret;
    378}
    379
    380int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id,
    381			    void *buf, size_t buf_len)
    382{
    383	struct wl1251_cmd_packet_template *cmd;
    384	size_t cmd_len;
    385	int ret = 0;
    386
    387	wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id);
    388
    389	WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE);
    390	buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE);
    391	cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4);
    392
    393	cmd = kzalloc(cmd_len, GFP_KERNEL);
    394	if (!cmd)
    395		return -ENOMEM;
    396
    397	cmd->size = cpu_to_le16(buf_len);
    398
    399	if (buf)
    400		memcpy(cmd->data, buf, buf_len);
    401
    402	ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len);
    403	if (ret < 0) {
    404		wl1251_warning("cmd set_template failed: %d", ret);
    405		goto out;
    406	}
    407
    408out:
    409	kfree(cmd);
    410	return ret;
    411}
    412
    413int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len,
    414		    struct ieee80211_channel *channels[],
    415		    unsigned int n_channels, unsigned int n_probes)
    416{
    417	struct wl1251_cmd_scan *cmd;
    418	int i, ret = 0;
    419
    420	wl1251_debug(DEBUG_CMD, "cmd scan channels %d", n_channels);
    421
    422	WARN_ON(n_channels > SCAN_MAX_NUM_OF_CHANNELS);
    423
    424	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    425	if (!cmd)
    426		return -ENOMEM;
    427
    428	cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
    429	cmd->params.rx_filter_options = cpu_to_le32(CFG_RX_PRSP_EN |
    430						    CFG_RX_MGMT_EN |
    431						    CFG_RX_BCN_EN);
    432	cmd->params.scan_options = 0;
    433	/*
    434	 * Use high priority scan when not associated to prevent fw issue
    435	 * causing never-ending scans (sometimes 20+ minutes).
    436	 * Note: This bug may be caused by the fw's DTIM handling.
    437	 */
    438	if (is_zero_ether_addr(wl->bssid))
    439		cmd->params.scan_options |= cpu_to_le16(WL1251_SCAN_OPT_PRIORITY_HIGH);
    440	cmd->params.num_channels = n_channels;
    441	cmd->params.num_probe_requests = n_probes;
    442	cmd->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */
    443	cmd->params.tid_trigger = 0;
    444
    445	for (i = 0; i < n_channels; i++) {
    446		cmd->channels[i].min_duration =
    447			cpu_to_le32(WL1251_SCAN_MIN_DURATION);
    448		cmd->channels[i].max_duration =
    449			cpu_to_le32(WL1251_SCAN_MAX_DURATION);
    450		memset(&cmd->channels[i].bssid_lsb, 0xff, 4);
    451		memset(&cmd->channels[i].bssid_msb, 0xff, 2);
    452		cmd->channels[i].early_termination = 0;
    453		cmd->channels[i].tx_power_att = 0;
    454		cmd->channels[i].channel = channels[i]->hw_value;
    455	}
    456
    457	if (ssid) {
    458		int len = clamp_val(ssid_len, 0, IEEE80211_MAX_SSID_LEN);
    459
    460		cmd->params.ssid_len = len;
    461		memcpy(cmd->params.ssid, ssid, len);
    462	}
    463
    464	ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd));
    465	if (ret < 0) {
    466		wl1251_error("cmd scan failed: %d", ret);
    467		goto out;
    468	}
    469
    470	wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
    471
    472	if (cmd->header.status != CMD_STATUS_SUCCESS) {
    473		wl1251_error("cmd scan status wasn't success: %d",
    474			     cmd->header.status);
    475		ret = -EIO;
    476		goto out;
    477	}
    478
    479out:
    480	kfree(cmd);
    481	return ret;
    482}
    483
    484int wl1251_cmd_trigger_scan_to(struct wl1251 *wl, u32 timeout)
    485{
    486	struct wl1251_cmd_trigger_scan_to *cmd;
    487	int ret;
    488
    489	wl1251_debug(DEBUG_CMD, "cmd trigger scan to");
    490
    491	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
    492	if (!cmd)
    493		return -ENOMEM;
    494
    495	cmd->timeout = timeout;
    496
    497	ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, cmd, sizeof(*cmd));
    498	if (ret < 0) {
    499		wl1251_error("cmd trigger scan to failed: %d", ret);
    500		goto out;
    501	}
    502
    503out:
    504	kfree(cmd);
    505	return ret;
    506}