All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jerome Pouiller <Jerome.Pouiller@silabs.com>
To: linux-wireless@vger.kernel.org, netdev@vger.kernel.org,
	Kalle Valo <kvalo@codeaurora.org>
Cc: devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"David S . Miller" <davem@davemloft.net>,
	devicetree@vger.kernel.org, "Rob Herring" <robh+dt@kernel.org>,
	linux-mmc@vger.kernel.org, "Pali Rohár" <pali@kernel.org>,
	"Ulf Hansson" <ulf.hansson@linaro.org>,
	"Jérôme Pouiller" <jerome.pouiller@silabs.com>
Subject: [PATCH v9 13/24] wfx: add hif_tx*.c/hif_tx*.h
Date: Tue, 11 Jan 2022 18:14:13 +0100	[thread overview]
Message-ID: <20220111171424.862764-14-Jerome.Pouiller@silabs.com> (raw)
In-Reply-To: <20220111171424.862764-1-Jerome.Pouiller@silabs.com>

From: Jérôme Pouiller <jerome.pouiller@silabs.com>

Signed-off-by: Jérôme Pouiller <jerome.pouiller@silabs.com>
---
 drivers/net/wireless/silabs/wfx/hif_tx.c     | 492 +++++++++++++++++++
 drivers/net/wireless/silabs/wfx/hif_tx.h     |  61 +++
 drivers/net/wireless/silabs/wfx/hif_tx_mib.c | 308 ++++++++++++
 drivers/net/wireless/silabs/wfx/hif_tx_mib.h |  48 ++
 4 files changed, 909 insertions(+)
 create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx.c
 create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx.h
 create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx_mib.c
 create mode 100644 drivers/net/wireless/silabs/wfx/hif_tx_mib.h

diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.c b/drivers/net/wireless/silabs/wfx/hif_tx.c
new file mode 100644
index 000000000000..40b9808eb511
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.c
@@ -0,0 +1,492 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Implementation of the host-to-chip commands (aka request/confirmation) of the
+ * hardware API.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ */
+#include <linux/etherdevice.h>
+
+#include "hif_tx.h"
+#include "wfx.h"
+#include "bh.h"
+#include "hwio.h"
+#include "debug.h"
+#include "sta.h"
+
+void wfx_init_hif_cmd(struct wfx_hif_cmd *hif_cmd)
+{
+	init_completion(&hif_cmd->ready);
+	init_completion(&hif_cmd->done);
+	mutex_init(&hif_cmd->lock);
+}
+
+static void wfx_fill_header(struct wfx_hif_msg *hif, int if_id, unsigned int cmd, size_t size)
+{
+	if (if_id == -1)
+		if_id = 2;
+
+	WARN(cmd > 0x3f, "invalid hardware command %#.2x", cmd);
+	WARN(size > 0xFFF, "requested buffer is too large: %zu bytes", size);
+	WARN(if_id > 0x3, "invalid interface ID %d", if_id);
+
+	hif->len = cpu_to_le16(size + 4);
+	hif->id = cmd;
+	hif->interface = if_id;
+}
+
+static void *wfx_alloc_hif(size_t body_len, struct wfx_hif_msg **hif)
+{
+	*hif = kzalloc(sizeof(*hif) + body_len, GFP_KERNEL);
+	if (*hif)
+		return (*hif)->body;
+	else
+		return NULL;
+}
+
+int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request,
+		 void *reply, size_t reply_len, bool no_reply)
+{
+	const char *mib_name = "";
+	const char *mib_sep = "";
+	int cmd = request->id;
+	int vif = request->interface;
+	int ret;
+
+	/* Do not wait for any reply if chip is frozen */
+	if (wdev->chip_frozen)
+		return -ETIMEDOUT;
+
+	mutex_lock(&wdev->hif_cmd.lock);
+	WARN(wdev->hif_cmd.buf_send, "data locking error");
+
+	/* Note: call to complete() below has an implicit memory barrier that hopefully protect
+	 * buf_send
+	 */
+	wdev->hif_cmd.buf_send = request;
+	wdev->hif_cmd.buf_recv = reply;
+	wdev->hif_cmd.len_recv = reply_len;
+	complete(&wdev->hif_cmd.ready);
+
+	wfx_bh_request_tx(wdev);
+
+	if (no_reply) {
+		/* Chip won't reply. Give enough time to the wq to send the buffer. */
+		msleep(100);
+		wdev->hif_cmd.buf_send = NULL;
+		mutex_unlock(&wdev->hif_cmd.lock);
+		return 0;
+	}
+
+	if (wdev->poll_irq)
+		wfx_bh_poll_irq(wdev);
+
+	ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 1 * HZ);
+	if (!ret) {
+		dev_err(wdev->dev, "chip is abnormally long to answer\n");
+		reinit_completion(&wdev->hif_cmd.ready);
+		ret = wait_for_completion_timeout(&wdev->hif_cmd.done, 3 * HZ);
+	}
+	if (!ret) {
+		dev_err(wdev->dev, "chip did not answer\n");
+		wfx_pending_dump_old_frames(wdev, 3000);
+		wdev->chip_frozen = true;
+		reinit_completion(&wdev->hif_cmd.done);
+		ret = -ETIMEDOUT;
+	} else {
+		ret = wdev->hif_cmd.ret;
+	}
+
+	wdev->hif_cmd.buf_send = NULL;
+	mutex_unlock(&wdev->hif_cmd.lock);
+
+	if (ret &&
+	    (cmd == HIF_REQ_ID_READ_MIB || cmd == HIF_REQ_ID_WRITE_MIB)) {
+		mib_name = wfx_get_mib_name(((u16 *)request)[2]);
+		mib_sep = "/";
+	}
+	if (ret < 0)
+		dev_err(wdev->dev, "hardware request %s%s%s (%#.2x) on vif %d returned error %d\n",
+			wfx_get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret);
+	if (ret > 0)
+		dev_warn(wdev->dev, "hardware request %s%s%s (%#.2x) on vif %d returned status %d\n",
+			 wfx_get_hif_name(cmd), mib_sep, mib_name, cmd, vif, ret);
+
+	return ret;
+}
+
+/* This function is special. After HIF_REQ_ID_SHUT_DOWN, chip won't reply to any request anymore.
+ * Obviously, only call this function during device unregister.
+ */
+int wfx_hif_shutdown(struct wfx_dev *wdev)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+
+	wfx_alloc_hif(0, &hif);
+	if (!hif)
+		return -ENOMEM;
+	wfx_fill_header(hif, -1, HIF_REQ_ID_SHUT_DOWN, 0);
+	ret = wfx_cmd_send(wdev, hif, NULL, 0, true);
+	if (wdev->pdata.gpio_wakeup)
+		gpiod_set_value(wdev->pdata.gpio_wakeup, 0);
+	else
+		wfx_control_reg_write(wdev, 0);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len)
+{
+	int ret;
+	size_t buf_len = sizeof(struct wfx_hif_req_configuration) + len;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_configuration *body = wfx_alloc_hif(buf_len, &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->length = cpu_to_le16(len);
+	memcpy(body->pds_data, conf, len);
+	wfx_fill_header(hif, -1, HIF_REQ_ID_CONFIGURATION, buf_len);
+	ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_reset(struct wfx_vif *wvif, bool reset_stat)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_reset *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->reset_stat = reset_stat;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_RESET, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id,
+		     void *val, size_t val_len)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	int buf_len = sizeof(struct wfx_hif_cnf_read_mib) + val_len;
+	struct wfx_hif_req_read_mib *body = wfx_alloc_hif(sizeof(*body), &hif);
+	struct wfx_hif_cnf_read_mib *reply = kmalloc(buf_len, GFP_KERNEL);
+
+	if (!body || !reply) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	body->mib_id = cpu_to_le16(mib_id);
+	wfx_fill_header(hif, vif_id, HIF_REQ_ID_READ_MIB, sizeof(*body));
+	ret = wfx_cmd_send(wdev, hif, reply, buf_len, false);
+
+	if (!ret && mib_id != le16_to_cpu(reply->mib_id)) {
+		dev_warn(wdev->dev, "%s: confirmation mismatch request\n", __func__);
+		ret = -EIO;
+	}
+	if (ret == -ENOMEM)
+		dev_err(wdev->dev, "buffer is too small to receive %s (%zu < %d)\n",
+			wfx_get_mib_name(mib_id), val_len, le16_to_cpu(reply->length));
+	if (!ret)
+		memcpy(val, &reply->mib_data, le16_to_cpu(reply->length));
+	else
+		memset(val, 0xFF, val_len);
+out:
+	kfree(hif);
+	kfree(reply);
+	return ret;
+}
+
+int wfx_hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, size_t val_len)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	int buf_len = sizeof(struct wfx_hif_req_write_mib) + val_len;
+	struct wfx_hif_req_write_mib *body = wfx_alloc_hif(buf_len, &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->mib_id = cpu_to_le16(mib_id);
+	body->length = cpu_to_le16(val_len);
+	memcpy(&body->mib_data, val, val_len);
+	wfx_fill_header(hif, vif_id, HIF_REQ_ID_WRITE_MIB, buf_len);
+	ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req,
+		 int chan_start_idx, int chan_num)
+{
+	int ret, i;
+	struct wfx_hif_msg *hif;
+	size_t buf_len = sizeof(struct wfx_hif_req_start_scan_alt) + chan_num * sizeof(u8);
+	struct wfx_hif_req_start_scan_alt *body = wfx_alloc_hif(buf_len, &hif);
+
+	WARN(chan_num > HIF_API_MAX_NB_CHANNELS, "invalid params");
+	WARN(req->n_ssids > HIF_API_MAX_NB_SSIDS, "invalid params");
+
+	if (!hif)
+		return -ENOMEM;
+	for (i = 0; i < req->n_ssids; i++) {
+		memcpy(body->ssid_def[i].ssid, req->ssids[i].ssid, IEEE80211_MAX_SSID_LEN);
+		body->ssid_def[i].ssid_length = cpu_to_le32(req->ssids[i].ssid_len);
+	}
+	body->num_of_ssids = HIF_API_MAX_NB_SSIDS;
+	body->maintain_current_bss = 1;
+	body->disallow_ps = 1;
+	body->tx_power_level = cpu_to_le32(req->channels[chan_start_idx]->max_power);
+	body->num_of_channels = chan_num;
+	for (i = 0; i < chan_num; i++)
+		body->channel_list[i] = req->channels[i + chan_start_idx]->hw_value;
+	if (req->no_cck)
+		body->max_transmit_rate = API_RATE_INDEX_G_6MBPS;
+	else
+		body->max_transmit_rate = API_RATE_INDEX_B_1MBPS;
+	if (req->channels[chan_start_idx]->flags & IEEE80211_CHAN_NO_IR) {
+		body->min_channel_time = cpu_to_le32(50);
+		body->max_channel_time = cpu_to_le32(150);
+	} else {
+		body->min_channel_time = cpu_to_le32(10);
+		body->max_channel_time = cpu_to_le32(50);
+		body->num_of_probe_requests = 2;
+		body->probe_delay = 100;
+	}
+
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START_SCAN, buf_len);
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_stop_scan(struct wfx_vif *wvif)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	/* body associated to HIF_REQ_ID_STOP_SCAN is empty */
+	wfx_alloc_hif(0, &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_STOP_SCAN, 0);
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
+		 struct ieee80211_channel *channel, const u8 *ssid, int ssidlen)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_join *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	WARN_ON(!conf->beacon_int);
+	WARN_ON(!conf->basic_rates);
+	WARN_ON(!channel);
+	WARN_ON(sizeof(body->ssid) < ssidlen);
+	WARN(!conf->ibss_joined && !ssidlen, "joining an unknown BSS");
+	if (!hif)
+		return -ENOMEM;
+	body->infrastructure_bss_mode = !conf->ibss_joined;
+	body->short_preamble = conf->use_short_preamble;
+	body->probe_for_join = !(channel->flags & IEEE80211_CHAN_NO_IR);
+	body->channel_number = channel->hw_value;
+	body->beacon_interval = cpu_to_le32(conf->beacon_int);
+	body->basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates));
+	memcpy(body->bssid, conf->bssid, sizeof(body->bssid));
+	if (ssid) {
+		body->ssid_length = cpu_to_le32(ssidlen);
+		memcpy(body->ssid, ssid, ssidlen);
+	}
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_JOIN, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_set_bss_params(struct wfx_vif *wvif, int aid, int beacon_lost_count)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_set_bss_params *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->aid = cpu_to_le16(aid);
+	body->beacon_lost_count = beacon_lost_count;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_BSS_PARAMS, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_add_key(struct wfx_dev *wdev, const struct wfx_hif_req_add_key *arg)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	/* FIXME: only send necessary bits */
+	struct wfx_hif_req_add_key *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	/* FIXME: swap bytes as necessary in body */
+	memcpy(body, arg, sizeof(*body));
+	if (wfx_api_older_than(wdev, 1, 5))
+		/* Legacy firmwares expect that add_key to be sent on right interface. */
+		wfx_fill_header(hif, arg->int_id, HIF_REQ_ID_ADD_KEY, sizeof(*body));
+	else
+		wfx_fill_header(hif, -1, HIF_REQ_ID_ADD_KEY, sizeof(*body));
+	ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_remove_key(struct wfx_dev *wdev, int idx)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_remove_key *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->entry_index = idx;
+	wfx_fill_header(hif, -1, HIF_REQ_ID_REMOVE_KEY, sizeof(*body));
+	ret = wfx_cmd_send(wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue,
+				  const struct ieee80211_tx_queue_params *arg)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_edca_queue_params *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!body)
+		return -ENOMEM;
+
+	WARN_ON(arg->aifs > 255);
+	if (!hif)
+		return -ENOMEM;
+	body->aifsn = arg->aifs;
+	body->cw_min = cpu_to_le16(arg->cw_min);
+	body->cw_max = cpu_to_le16(arg->cw_max);
+	body->tx_op_limit = cpu_to_le16(arg->txop * USEC_PER_TXOP);
+	body->queue_id = 3 - queue;
+	/* API 2.0 has changed queue IDs values */
+	if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BE)
+		body->queue_id = HIF_QUEUE_ID_BACKGROUND;
+	if (wfx_api_older_than(wvif->wdev, 2, 0) && queue == IEEE80211_AC_BK)
+		body->queue_id = HIF_QUEUE_ID_BESTEFFORT;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_EDCA_QUEUE_PARAMS, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_set_pm_mode *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!body)
+		return -ENOMEM;
+
+	if (!hif)
+		return -ENOMEM;
+	if (ps) {
+		body->enter_psm = 1;
+		/* Firmware does not support more than 128ms */
+		body->fast_psm_idle_period = min(dynamic_ps_timeout * 2, 255);
+		if (body->fast_psm_idle_period)
+			body->fast_psm = 1;
+	}
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_SET_PM_MODE, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
+		  const struct ieee80211_channel *channel)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_start *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	WARN_ON(!conf->beacon_int);
+	if (!hif)
+		return -ENOMEM;
+	body->dtim_period = conf->dtim_period;
+	body->short_preamble = conf->use_short_preamble;
+	body->channel_number = channel->hw_value;
+	body->beacon_interval = cpu_to_le32(conf->beacon_int);
+	body->basic_rate_set = cpu_to_le32(wfx_rate_mask_to_hw(wvif->wdev, conf->basic_rates));
+	body->ssid_length = conf->ssid_len;
+	memcpy(body->ssid, conf->ssid, conf->ssid_len);
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_START, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_beacon_transmit(struct wfx_vif *wvif, bool enable)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_beacon_transmit *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->enable_beaconing = enable ? 1 : 0;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_BEACON_TRANSMIT, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_map_link(struct wfx_vif *wvif, bool unmap, u8 *mac_addr, int sta_id, bool mfp)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	struct wfx_hif_req_map_link *body = wfx_alloc_hif(sizeof(*body), &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	if (mac_addr)
+		ether_addr_copy(body->mac_addr, mac_addr);
+	body->mfpc = mfp ? 1 : 0;
+	body->unmap = unmap ? 1 : 0;
+	body->peer_sta_id = sta_id;
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_MAP_LINK, sizeof(*body));
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
+
+int wfx_hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len)
+{
+	int ret;
+	struct wfx_hif_msg *hif;
+	int buf_len = sizeof(struct wfx_hif_req_update_ie) + ies_len;
+	struct wfx_hif_req_update_ie *body = wfx_alloc_hif(buf_len, &hif);
+
+	if (!hif)
+		return -ENOMEM;
+	body->beacon = 1;
+	body->num_ies = cpu_to_le16(1);
+	memcpy(body->ie, ies, ies_len);
+	wfx_fill_header(hif, wvif->id, HIF_REQ_ID_UPDATE_IE, buf_len);
+	ret = wfx_cmd_send(wvif->wdev, hif, NULL, 0, false);
+	kfree(hif);
+	return ret;
+}
diff --git a/drivers/net/wireless/silabs/wfx/hif_tx.h b/drivers/net/wireless/silabs/wfx/hif_tx.h
new file mode 100644
index 000000000000..71817a6571f0
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/hif_tx.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of the host-to-chip commands (aka request/confirmation) of the
+ * hardware API.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+#ifndef WFX_HIF_TX_H
+#define WFX_HIF_TX_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+
+struct ieee80211_channel;
+struct ieee80211_bss_conf;
+struct ieee80211_tx_queue_params;
+struct cfg80211_scan_request;
+struct wfx_hif_req_add_key;
+struct wfx_dev;
+struct wfx_vif;
+
+struct wfx_hif_cmd {
+	struct mutex       lock;
+	struct completion  ready;
+	struct completion  done;
+	struct wfx_hif_msg *buf_send;
+	void               *buf_recv;
+	size_t             len_recv;
+	int                ret;
+};
+
+void wfx_init_hif_cmd(struct wfx_hif_cmd *wfx_hif_cmd);
+int wfx_cmd_send(struct wfx_dev *wdev, struct wfx_hif_msg *request,
+		 void *reply, size_t reply_len, bool async);
+
+int wfx_hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *buf, size_t buf_size);
+int wfx_hif_write_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *buf, size_t buf_size);
+int wfx_hif_start(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
+		  const struct ieee80211_channel *channel);
+int wfx_hif_reset(struct wfx_vif *wvif, bool reset_stat);
+int wfx_hif_join(struct wfx_vif *wvif, const struct ieee80211_bss_conf *conf,
+		 struct ieee80211_channel *channel, const u8 *ssid, int ssidlen);
+int wfx_hif_map_link(struct wfx_vif *wvif, bool unmap, u8 *mac_addr, int sta_id, bool mfp);
+int wfx_hif_add_key(struct wfx_dev *wdev, const struct wfx_hif_req_add_key *arg);
+int wfx_hif_remove_key(struct wfx_dev *wdev, int idx);
+int wfx_hif_set_pm(struct wfx_vif *wvif, bool ps, int dynamic_ps_timeout);
+int wfx_hif_set_bss_params(struct wfx_vif *wvif, int aid, int beacon_lost_count);
+int wfx_hif_set_edca_queue_params(struct wfx_vif *wvif, u16 queue,
+				  const struct ieee80211_tx_queue_params *arg);
+int wfx_hif_beacon_transmit(struct wfx_vif *wvif, bool enable);
+int wfx_hif_update_ie_beacon(struct wfx_vif *wvif, const u8 *ies, size_t ies_len);
+int wfx_hif_scan(struct wfx_vif *wvif, struct cfg80211_scan_request *req80211,
+		 int chan_start, int chan_num);
+int wfx_hif_stop_scan(struct wfx_vif *wvif);
+int wfx_hif_configuration(struct wfx_dev *wdev, const u8 *conf, size_t len);
+int wfx_hif_shutdown(struct wfx_dev *wdev);
+
+#endif
diff --git a/drivers/net/wireless/silabs/wfx/hif_tx_mib.c b/drivers/net/wireless/silabs/wfx/hif_tx_mib.c
new file mode 100644
index 000000000000..1c57dd2b697c
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/hif_tx_mib.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Implementation of the host-to-chip MIBs of the hardware API.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+
+#include <linux/etherdevice.h>
+
+#include "wfx.h"
+#include "hif_tx.h"
+#include "hif_tx_mib.h"
+#include "hif_api_mib.h"
+
+int wfx_hif_set_output_power(struct wfx_vif *wvif, int val)
+{
+	struct wfx_hif_mib_current_tx_power_level arg = {
+		.power_level = cpu_to_le32(val * 10),
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_CURRENT_TX_POWER_LEVEL,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_beacon_wakeup_period(struct wfx_vif *wvif,
+				     unsigned int dtim_interval, unsigned int listen_interval)
+{
+	struct wfx_hif_mib_beacon_wake_up_period arg = {
+		.wakeup_period_min = dtim_interval,
+		.receive_dtim = 0,
+		.wakeup_period_max = listen_interval,
+	};
+
+	if (dtim_interval > 0xFF || listen_interval > 0xFFFF)
+		return -EINVAL;
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BEACON_WAKEUP_PERIOD,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif, int rssi_thold, int rssi_hyst)
+{
+	struct wfx_hif_mib_rcpi_rssi_threshold arg = {
+		.rolling_average_count = 8,
+		.detection = 1,
+	};
+
+	if (!rssi_thold && !rssi_hyst) {
+		arg.upperthresh = 1;
+		arg.lowerthresh = 1;
+	} else {
+		arg.upper_threshold = rssi_thold + rssi_hyst;
+		arg.upper_threshold = (arg.upper_threshold + 110) * 2;
+		arg.lower_threshold = rssi_thold;
+		arg.lower_threshold = (arg.lower_threshold + 110) * 2;
+	}
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_RCPI_RSSI_THRESHOLD,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_get_counters_table(struct wfx_dev *wdev, int vif_id,
+			       struct wfx_hif_mib_extended_count_table *arg)
+{
+	if (wfx_api_older_than(wdev, 1, 3)) {
+		/* extended_count_table is wider than count_table */
+		memset(arg, 0xFF, sizeof(*arg));
+		return wfx_hif_read_mib(wdev, vif_id, HIF_MIB_ID_COUNTERS_TABLE,
+				    arg, sizeof(struct wfx_hif_mib_count_table));
+	} else {
+		return wfx_hif_read_mib(wdev, vif_id, HIF_MIB_ID_EXTENDED_COUNTERS_TABLE,
+					arg, sizeof(struct wfx_hif_mib_extended_count_table));
+	}
+}
+
+int wfx_hif_set_macaddr(struct wfx_vif *wvif, u8 *mac)
+{
+	struct wfx_hif_mib_mac_address arg = { };
+
+	if (mac)
+		ether_addr_copy(arg.mac_addr, mac);
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_MAC_ADDRESS,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_rx_filter(struct wfx_vif *wvif,
+			  bool filter_bssid, bool filter_prbreq)
+{
+	struct wfx_hif_mib_rx_filter arg = { };
+
+	if (filter_bssid)
+		arg.bssid_filter = 1;
+	if (!filter_prbreq)
+		arg.fwd_probe_req = 1;
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_RX_FILTER, &arg, sizeof(arg));
+}
+
+int wfx_hif_set_beacon_filter_table(struct wfx_vif *wvif, int tbl_len,
+				    const struct wfx_hif_ie_table_entry *tbl)
+{
+	int ret;
+	struct wfx_hif_mib_bcn_filter_table *arg;
+	int buf_len = struct_size(arg, ie_table, tbl_len);
+
+	arg = kzalloc(buf_len, GFP_KERNEL);
+	if (!arg)
+		return -ENOMEM;
+	arg->num_of_info_elmts = cpu_to_le32(tbl_len);
+	memcpy(arg->ie_table, tbl, flex_array_size(arg, ie_table, tbl_len));
+	ret = wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BEACON_FILTER_TABLE,
+				arg, buf_len);
+	kfree(arg);
+	return ret;
+}
+
+int wfx_hif_beacon_filter_control(struct wfx_vif *wvif, int enable, int beacon_count)
+{
+	struct wfx_hif_mib_bcn_filter_enable arg = {
+		.enable = cpu_to_le32(enable),
+		.bcn_count = cpu_to_le32(beacon_count),
+	};
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BEACON_FILTER_ENABLE,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_operational_mode(struct wfx_dev *wdev, enum wfx_hif_op_power_mode mode)
+{
+	struct wfx_hif_mib_gl_operational_power_mode arg = {
+		.power_mode = mode,
+		.wup_ind_activation = 1,
+	};
+
+	return wfx_hif_write_mib(wdev, -1, HIF_MIB_ID_GL_OPERATIONAL_POWER_MODE,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_template_frame(struct wfx_vif *wvif, struct sk_buff *skb,
+			       u8 frame_type, int init_rate)
+{
+	struct wfx_hif_mib_template_frame *arg;
+
+	WARN(skb->len > HIF_API_MAX_TEMPLATE_FRAME_SIZE, "frame is too big");
+	skb_push(skb, 4);
+	arg = (struct wfx_hif_mib_template_frame *)skb->data;
+	skb_pull(skb, 4);
+	arg->init_rate = init_rate;
+	arg->frame_type = frame_type;
+	arg->frame_length = cpu_to_le16(skb->len);
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_TEMPLATE_FRAME,
+				 arg, sizeof(*arg) + skb->len);
+}
+
+int wfx_hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required)
+{
+	struct wfx_hif_mib_protected_mgmt_policy arg = { };
+
+	WARN(required && !capable, "incoherent arguments");
+	if (capable) {
+		arg.pmf_enable = 1;
+		arg.host_enc_auth_frames = 1;
+	}
+	if (!required)
+		arg.unpmf_allowed = 1;
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_PROTECTED_MGMT_POLICY,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_block_ack_policy(struct wfx_vif *wvif, u8 tx_tid_policy, u8 rx_tid_policy)
+{
+	struct wfx_hif_mib_block_ack_policy arg = {
+		.block_ack_tx_tid_policy = tx_tid_policy,
+		.block_ack_rx_tid_policy = rx_tid_policy,
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_BLOCK_ACK_POLICY,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_association_mode(struct wfx_vif *wvif, int ampdu_density,
+				 bool greenfield, bool short_preamble)
+{
+	struct wfx_hif_mib_set_association_mode arg = {
+		.preambtype_use = 1,
+		.mode = 1,
+		.spacing = 1,
+		.short_preamble = short_preamble,
+		.greenfield = greenfield,
+		.mpdu_start_spacing = ampdu_density,
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_ASSOCIATION_MODE,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, int policy_index, u8 *rates)
+{
+	struct wfx_hif_mib_set_tx_rate_retry_policy *arg;
+	size_t size = struct_size(arg, tx_rate_retry_policy, 1);
+	int ret;
+
+	arg = kzalloc(size, GFP_KERNEL);
+	if (!arg)
+		return -ENOMEM;
+	arg->num_tx_rate_policies = 1;
+	arg->tx_rate_retry_policy[0].policy_index = policy_index;
+	arg->tx_rate_retry_policy[0].short_retry_count = 255;
+	arg->tx_rate_retry_policy[0].long_retry_count = 255;
+	arg->tx_rate_retry_policy[0].first_rate_sel = 1;
+	arg->tx_rate_retry_policy[0].terminate = 1;
+	arg->tx_rate_retry_policy[0].count_init = 1;
+	memcpy(&arg->tx_rate_retry_policy[0].rates, rates,
+	       sizeof(arg->tx_rate_retry_policy[0].rates));
+	ret = wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_TX_RATE_RETRY_POLICY,
+				arg, size);
+	kfree(arg);
+	return ret;
+}
+
+int wfx_hif_keep_alive_period(struct wfx_vif *wvif, int period)
+{
+	struct wfx_hif_mib_keep_alive_period arg = {
+		.keep_alive_period = cpu_to_le16(period),
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_KEEP_ALIVE_PERIOD,
+				 &arg, sizeof(arg));
+};
+
+int wfx_hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, __be32 *addr)
+{
+	struct wfx_hif_mib_arp_ip_addr_table arg = {
+		.condition_idx = idx,
+		.arp_enable = HIF_ARP_NS_FILTERING_DISABLE,
+	};
+
+	if (addr) {
+		/* Caution: type of addr is __be32 */
+		memcpy(arg.ipv4_address, addr, sizeof(arg.ipv4_address));
+		arg.arp_enable = HIF_ARP_NS_FILTERING_ENABLE;
+	}
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_ARP_IP_ADDRESSES_TABLE,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_use_multi_tx_conf(struct wfx_dev *wdev, bool enable)
+{
+	struct wfx_hif_mib_gl_set_multi_msg arg = {
+		.enable_multi_tx_conf = enable,
+	};
+
+	return wfx_hif_write_mib(wdev, -1, HIF_MIB_ID_GL_SET_MULTI_MSG, &arg, sizeof(arg));
+}
+
+int wfx_hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val)
+{
+	struct wfx_hif_mib_set_uapsd_information arg = { };
+
+	if (val & BIT(IEEE80211_AC_VO))
+		arg.trig_voice = 1;
+	if (val & BIT(IEEE80211_AC_VI))
+		arg.trig_video = 1;
+	if (val & BIT(IEEE80211_AC_BE))
+		arg.trig_be = 1;
+	if (val & BIT(IEEE80211_AC_BK))
+		arg.trig_bckgrnd = 1;
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SET_UAPSD_INFORMATION,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_erp_use_protection(struct wfx_vif *wvif, bool enable)
+{
+	struct wfx_hif_mib_non_erp_protection arg = {
+		.use_cts_to_self = enable,
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_NON_ERP_PROTECTION,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_slot_time(struct wfx_vif *wvif, int val)
+{
+	struct wfx_hif_mib_slot_time arg = {
+		.slot_time = cpu_to_le32(val),
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_SLOT_TIME, &arg, sizeof(arg));
+}
+
+int wfx_hif_wep_default_key_id(struct wfx_vif *wvif, int val)
+{
+	struct wfx_hif_mib_wep_default_key_id arg = {
+		.wep_default_key_id = val,
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_WEP_DEFAULT_KEY_ID,
+				 &arg, sizeof(arg));
+}
+
+int wfx_hif_rts_threshold(struct wfx_vif *wvif, int val)
+{
+	struct wfx_hif_mib_dot11_rts_threshold arg = {
+		.threshold = cpu_to_le32(val >= 0 ? val : 0xFFFF),
+	};
+
+	return wfx_hif_write_mib(wvif->wdev, wvif->id, HIF_MIB_ID_DOT11_RTS_THRESHOLD,
+				 &arg, sizeof(arg));
+}
diff --git a/drivers/net/wireless/silabs/wfx/hif_tx_mib.h b/drivers/net/wireless/silabs/wfx/hif_tx_mib.h
new file mode 100644
index 000000000000..bcd4ef6a8497
--- /dev/null
+++ b/drivers/net/wireless/silabs/wfx/hif_tx_mib.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Implementation of the host-to-chip MIBs of the hardware API.
+ *
+ * Copyright (c) 2017-2020, Silicon Laboratories, Inc.
+ * Copyright (c) 2010, ST-Ericsson
+ * Copyright (C) 2010, ST-Ericsson SA
+ */
+#ifndef WFX_HIF_TX_MIB_H
+#define WFX_HIF_TX_MIB_H
+
+#include <linux/types.h>
+
+struct sk_buff;
+struct wfx_vif;
+struct wfx_dev;
+struct wfx_hif_ie_table_entry;
+struct wfx_hif_mib_extended_count_table;
+
+int wfx_hif_set_output_power(struct wfx_vif *wvif, int val);
+int wfx_hif_set_beacon_wakeup_period(struct wfx_vif *wvif,
+				     unsigned int dtim_interval, unsigned int listen_interval);
+int wfx_hif_set_rcpi_rssi_threshold(struct wfx_vif *wvif, int rssi_thold, int rssi_hyst);
+int wfx_hif_get_counters_table(struct wfx_dev *wdev, int vif_id,
+			       struct wfx_hif_mib_extended_count_table *arg);
+int wfx_hif_set_macaddr(struct wfx_vif *wvif, u8 *mac);
+int wfx_hif_set_rx_filter(struct wfx_vif *wvif, bool filter_bssid, bool fwd_probe_req);
+int wfx_hif_set_beacon_filter_table(struct wfx_vif *wvif, int tbl_len,
+				    const struct wfx_hif_ie_table_entry *tbl);
+int wfx_hif_beacon_filter_control(struct wfx_vif *wvif, int enable, int beacon_count);
+int wfx_hif_set_operational_mode(struct wfx_dev *wdev, enum wfx_hif_op_power_mode mode);
+int wfx_hif_set_template_frame(struct wfx_vif *wvif, struct sk_buff *skb,
+			       u8 frame_type, int init_rate);
+int wfx_hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required);
+int wfx_hif_set_block_ack_policy(struct wfx_vif *wvif, u8 tx_tid_policy, u8 rx_tid_policy);
+int wfx_hif_set_association_mode(struct wfx_vif *wvif, int ampdu_density,
+				 bool greenfield, bool short_preamble);
+int wfx_hif_set_tx_rate_retry_policy(struct wfx_vif *wvif, int policy_index, u8 *rates);
+int wfx_hif_keep_alive_period(struct wfx_vif *wvif, int period);
+int wfx_hif_set_arp_ipv4_filter(struct wfx_vif *wvif, int idx, __be32 *addr);
+int wfx_hif_use_multi_tx_conf(struct wfx_dev *wdev, bool enable);
+int wfx_hif_set_uapsd_info(struct wfx_vif *wvif, unsigned long val);
+int wfx_hif_erp_use_protection(struct wfx_vif *wvif, bool enable);
+int wfx_hif_slot_time(struct wfx_vif *wvif, int val);
+int wfx_hif_wep_default_key_id(struct wfx_vif *wvif, int val);
+int wfx_hif_rts_threshold(struct wfx_vif *wvif, int val);
+
+#endif
-- 
2.34.1


  parent reply	other threads:[~2022-01-11 17:16 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-11 17:14 [PATCH v9 00/24] wfx: get out from the staging area Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 01/24] mmc: sdio: add SDIO IDs for Silabs WF200 chip Jerome Pouiller
2022-01-12 10:58   ` Ulf Hansson
2022-01-12 12:45     ` Kalle Valo
2022-01-11 17:14 ` [PATCH v9 02/24] dt-bindings: introduce silabs,wfx.yaml Jerome Pouiller
2022-01-11 20:49   ` Rob Herring
2022-01-11 22:19   ` Rob Herring
2022-01-12  9:51     ` Jérôme Pouiller
2022-01-11 17:14 ` [PATCH v9 03/24] wfx: add Makefile/Kconfig Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 04/24] wfx: add wfx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 05/24] wfx: add main.c/main.h Jerome Pouiller
2022-01-26  8:20   ` Jérôme Pouiller
2022-02-10 14:20     ` Kalle Valo
2022-02-10 14:41       ` Jérôme Pouiller
2022-02-10 14:51         ` Kalle Valo
2022-02-10 15:13           ` Jérôme Pouiller
2022-02-10 16:25             ` Kalle Valo
2022-02-10 16:37               ` Jérôme Pouiller
2022-02-11  7:08                 ` Kalle Valo
2022-02-10 14:23   ` Pali Rohár
2022-01-11 17:14 ` [PATCH v9 06/24] wfx: add bus.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 07/24] wfx: add bus_spi.c Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 08/24] wfx: add bus_sdio.c Jerome Pouiller
2022-01-12 10:51   ` Ulf Hansson
2022-01-12 10:58   ` Pali Rohár
2022-01-12 11:18     ` Jérôme Pouiller
2022-01-12 11:43       ` Pali Rohár
2022-01-12 12:06         ` Greg Kroah-Hartman
2022-01-12 12:14           ` Pali Rohár
2022-01-12 15:03         ` Ulf Hansson
2022-01-12 16:45         ` Jérôme Pouiller
2022-01-12 17:48           ` Pali Rohár
2022-01-12 18:23             ` Jérôme Pouiller
2022-01-13 12:07               ` Ulf Hansson
2022-01-11 17:14 ` [PATCH v9 09/24] wfx: add hwio.c/hwio.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 10/24] wfx: add fwio.c/fwio.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 11/24] wfx: add bh.c/bh.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 12/24] wfx: add hif_api_*.h Jerome Pouiller
2022-01-11 17:14 ` Jerome Pouiller [this message]
2022-01-11 17:14 ` [PATCH v9 14/24] wfx: add key.c/key.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 15/24] wfx: add hif_rx.c/hif_rx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 16/24] wfx: add data_rx.c/data_rx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 17/24] wfx: add queue.c/queue.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 18/24] wfx: add data_tx.c/data_tx.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 19/24] wfx: add sta.c/sta.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 20/24] wfx: add scan.c/scan.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 21/24] wfx: add debug.c/debug.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 22/24] wfx: add traces.h Jerome Pouiller
2022-01-11 17:14 ` [PATCH v9 23/24] wfx: remove from the staging area Jerome Pouiller
2022-01-12  7:49   ` Kalle Valo
2022-01-12  9:32     ` Jérôme Pouiller
2022-01-12 12:46       ` Kalle Valo
2022-01-11 17:14 ` [PATCH v9 24/24] wfx: get out " Jerome Pouiller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220111171424.862764-14-Jerome.Pouiller@silabs.com \
    --to=jerome.pouiller@silabs.com \
    --cc=davem@davemloft.net \
    --cc=devel@driverdev.osuosl.org \
    --cc=devicetree@vger.kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=kvalo@codeaurora.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mmc@vger.kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pali@kernel.org \
    --cc=robh+dt@kernel.org \
    --cc=ulf.hansson@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.