linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Miquel Raynal <miquel.raynal@bootlin.com>
To: Alexander Aring <alex.aring@gmail.com>,
	Stefan Schmidt <stefan@datenfreihafen.org>,
	linux-wpan@vger.kernel.org
Cc: netdev@vger.kernel.org, linux-wireless@vger.kernel.org,
	David Girault <david.girault@qorvo.com>,
	Romuald Despres <romuald.despres@qorvo.com>,
	Frederic Blain <frederic.blain@qorvo.com>,
	Nicolas Schodet <nico@ni.fr.eu.org>,
	Michael Hennerich <michael.hennerich@analog.com>,
	Jakub Kicinski <kuba@kernel.org>,
	Varka Bhadram <varkabhadram@gmail.com>,
	Xue Liu <liuxuenetmail@gmail.com>, Alan Ott <alan@signal11.us>,
	Thomas Petazzoni <thomas.petazzoni@bootlin.com>,
	Miquel Raynal <miquel.raynal@bootlin.com>
Subject: [PATCH v3 36/41] net: mac802154: Handle beacons requests
Date: Mon, 17 Jan 2022 12:54:35 +0100	[thread overview]
Message-ID: <20220117115440.60296-37-miquel.raynal@bootlin.com> (raw)
In-Reply-To: <20220117115440.60296-1-miquel.raynal@bootlin.com>

Implement the core hooks in order to provide the softMAC layer support
for sending beacons. Besides being able to test the full passive
scanning procedure, this will also be used when defining PAN coordinator
status, in order to give a device the right to answer received
BEACON_REQ.

Changing the channels is prohibited while a beacon operation is
ongoing.

The implementation uses a workqueue triggered at a certain interval
depending on the symbol duration for the current channel and the
interval order provided.

Sending beacons in response to an active scan request is not
yet supported.

Co-developed-by: David Girault <david.girault@qorvo.com>
Signed-off-by: David Girault <david.girault@qorvo.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 include/net/ieee802154_netdev.h |  24 ++++++
 net/ieee802154/header_ops.c     |  29 ++++++++
 net/mac802154/cfg.c             |  41 ++++++++++-
 net/mac802154/ieee802154_i.h    |  13 ++++
 net/mac802154/main.c            |   2 +
 net/mac802154/scan.c            | 126 ++++++++++++++++++++++++++++++++
 6 files changed, 233 insertions(+), 2 deletions(-)

diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 45dff5d11bc8..f7716aeec93b 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -116,6 +116,21 @@ enum ieee802154_frame_type {
 	IEEE802154_EXTENDED_FRAME,
 };
 
+enum ieee802154_frame_version {
+	IEEE802154_2003_STD,
+	IEEE802154_2006_STD,
+	IEEE802154_STD,
+	IEEE802154_RESERVED_STD,
+	IEEE802154_MULTIPURPOSE_STD = IEEE802154_2003_STD,
+};
+
+enum ieee802154_addressing_mode {
+	IEEE802154_NO_ADDRESSING,
+	IEEE802154_RESERVED,
+	IEEE802154_SHORT_ADDRESSING,
+	IEEE802154_EXTENDED_ADDRESSING,
+};
+
 struct ieee802154_hdr {
 	struct ieee802154_hdr_fc fc;
 	u8 seq;
@@ -124,6 +139,11 @@ struct ieee802154_hdr {
 	struct ieee802154_sechdr sec;
 };
 
+struct ieee802154_beacon_frame {
+	struct ieee802154_hdr mhr;
+	struct ieee802154_beacon_hdr mac_pl;
+};
+
 /* pushes hdr onto the skb. fields of hdr->fc that can be calculated from
  * the contents of hdr will be, and the actual value of those bits in
  * hdr->fc will be ignored. this includes the INTRA_PAN bit and the frame
@@ -149,6 +169,10 @@ int ieee802154_hdr_peek_addrs(const struct sk_buff *skb,
  */
 int ieee802154_hdr_peek(const struct sk_buff *skb, struct ieee802154_hdr *hdr);
 
+/* pushes a beacon frame into an skb */
+int ieee802154_beacon_push(struct sk_buff *skb,
+			   struct ieee802154_beacon_frame *beacon);
+
 int ieee802154_max_payload(const struct ieee802154_hdr *hdr);
 
 static inline int
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index af337cf62764..bab710aa36f9 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -6,6 +6,7 @@
  * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
  */
 
+#include <linux/crc-ccitt.h>
 #include <linux/ieee802154.h>
 
 #include <net/mac802154.h>
@@ -120,6 +121,34 @@ ieee802154_hdr_push(struct sk_buff *skb, struct ieee802154_hdr *hdr)
 }
 EXPORT_SYMBOL_GPL(ieee802154_hdr_push);
 
+int ieee802154_beacon_push(struct sk_buff *skb,
+			   struct ieee802154_beacon_frame *beacon)
+{
+	struct ieee802154_beacon_hdr *mac_pl = &beacon->mac_pl;
+	struct ieee802154_hdr *mhr = &beacon->mhr;
+	u16 crc;
+	int ret;
+
+	skb_reserve(skb, sizeof(*mhr));
+	ret = ieee802154_hdr_push(skb, mhr);
+	if (ret < 0)
+		return ret;
+
+	skb_reset_mac_header(skb);
+	skb->mac_len = ret;
+
+	skb_put_data(skb, mac_pl, sizeof(*mac_pl));
+
+	if (mac_pl->pend_short_addr_count || mac_pl->pend_ext_addr_count)
+		return -EOPNOTSUPP;
+
+	crc = crc_ccitt(0, skb->data, skb->len);
+	put_unaligned_le16(crc, skb_put(skb, 2));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ieee802154_beacon_push);
+
 static int
 ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan,
 			struct ieee802154_addr *addr)
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
index 958b609b8c1b..5a22297708ec 100644
--- a/net/mac802154/cfg.c
+++ b/net/mac802154/cfg.c
@@ -117,8 +117,10 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
 	    wpan_phy->current_channel == channel)
 		return 0;
 
-	/* Refuse to change channels during a scanning operation */
-	if (mac802154_scan_is_ongoing(local))
+	/* Refuse to change channels during a scanning operation or when a
+	 * beacons request is ongoing.
+	 */
+	if (mac802154_scan_is_ongoing(local) || local->ongoing_beacons_request)
 		return -EBUSY;
 
 	ret = drv_set_channel(local, page, channel);
@@ -301,6 +303,39 @@ static int mac802154_abort_scan(struct wpan_phy *wpan_phy,
 	return ret;
 }
 
+static int mac802154_send_beacons(struct wpan_phy *wpan_phy,
+				  struct cfg802154_beacons_request *request)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	struct ieee802154_sub_if_data *sdata;
+	int ret;
+
+	sdata = IEEE802154_WPAN_DEV_TO_SUB_IF(request->wpan_dev);
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->beacons_lock);
+	ret = mac802154_send_beacons_locked(sdata, request);
+	mutex_unlock(&local->beacons_lock);
+
+	return ret;
+}
+
+static int mac802154_stop_beacons(struct wpan_phy *wpan_phy,
+				  struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
+	int ret;
+
+	ASSERT_RTNL();
+
+	mutex_lock(&local->beacons_lock);
+	ret = mac802154_stop_beacons_locked(local);
+	mutex_unlock(&local->beacons_lock);
+
+	return ret;
+}
+
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 static void
 ieee802154_get_llsec_table(struct wpan_phy *wpan_phy,
@@ -510,6 +545,8 @@ const struct cfg802154_ops mac802154_config_ops = {
 	.set_ackreq_default = ieee802154_set_ackreq_default,
 	.trigger_scan = mac802154_trigger_scan,
 	.abort_scan = mac802154_abort_scan,
+	.send_beacons = mac802154_send_beacons,
+	.stop_beacons = mac802154_stop_beacons,
 #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
 	.get_llsec_table = ieee802154_get_llsec_table,
 	.lock_llsec_table = ieee802154_lock_llsec_table,
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index f7562f4cacdf..514446c1f815 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -57,6 +57,14 @@ struct ieee802154_local {
 	struct ieee802154_sub_if_data __rcu *scan_sdata;
 	struct delayed_work scan_work;
 
+	/* Beacons handling */
+	bool ongoing_beacons_request;
+	struct mutex beacons_lock;
+	unsigned int beacons_interval;
+	struct delayed_work beacons_work;
+	struct ieee802154_sub_if_data __rcu *beacons_sdata;
+	struct ieee802154_beacon_frame beacon;
+
 	bool started;
 	bool suspended;
 
@@ -219,6 +227,11 @@ static inline bool mac802154_scan_is_ongoing(struct ieee802154_local *local)
 	return atomic_read(&local->scanning);
 }
 
+void mac802154_beacons_work(struct work_struct *work);
+int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_beacons_request *request);
+int mac802154_stop_beacons_locked(struct ieee802154_local *local);
+
 /* interface handling */
 int ieee802154_iface_init(void);
 void ieee802154_iface_exit(void);
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
index bd453b1c0223..8992bcc3eca9 100644
--- a/net/mac802154/main.c
+++ b/net/mac802154/main.c
@@ -91,6 +91,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 	INIT_LIST_HEAD(&local->interfaces);
 	mutex_init(&local->iflist_mtx);
 	mutex_init(&local->scan_lock);
+	mutex_init(&local->beacons_lock);
 
 	tasklet_setup(&local->tasklet, ieee802154_tasklet_handler);
 
@@ -98,6 +99,7 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
 
 	INIT_WORK(&local->sync_tx_work, ieee802154_xmit_sync_worker);
 	INIT_DELAYED_WORK(&local->scan_work, mac802154_scan_work);
+	INIT_DELAYED_WORK(&local->beacons_work, mac802154_beacons_work);
 
 	/* init supported flags with 802.15.4 default ranges */
 	phy->supported.max_minbe = 8;
diff --git a/net/mac802154/scan.c b/net/mac802154/scan.c
index 3129cc95157a..d9b54b35660a 100644
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -17,6 +17,13 @@
 #include "driver-ops.h"
 #include "../ieee802154/nl802154.h"
 
+#define IEEE802154_BEACON_MHR_SZ 13
+#define IEEE802154_BEACON_PL_SZ 4
+#define IEEE802154_CRC_SZ 2
+#define IEEE802154_BEACON_SKB_SZ (IEEE802154_BEACON_MHR_SZ + \
+				  IEEE802154_BEACON_PL_SZ + \
+				  IEEE802154_CRC_SZ)
+
 static bool mac802154_check_promiscuous(struct ieee802154_local *local)
 {
 	struct ieee802154_sub_if_data *sdata;
@@ -257,3 +264,122 @@ int mac802154_scan_process_beacon(struct ieee802154_local *local,
 
 	return 0;
 }
+
+static int mac802154_transmit_beacon_locked(struct ieee802154_local *local,
+					    struct wpan_dev *wpan_dev)
+{
+	struct ieee802154_sub_if_data *sdata;
+	struct sk_buff *skb;
+	int ret;
+
+	lockdep_assert_held(&local->beacons_lock);
+
+	/* Update the sequence number */
+	local->beacon.mhr.seq = atomic_inc_return(&wpan_dev->bsn);
+
+	skb = alloc_skb(IEEE802154_BEACON_SKB_SZ, GFP_KERNEL);
+	if (!skb)
+		return -ENOBUFS;
+
+	sdata = rcu_dereference_protected(local->beacons_sdata,
+					  lockdep_is_held(&local->beacons_lock));
+	skb->dev = sdata->dev;
+
+	ret = ieee802154_beacon_push(skb, &local->beacon);
+	if (ret) {
+		kfree_skb(skb);
+		return ret;
+	}
+
+	ieee802154_mlme_tx(local, skb);
+
+	return 0;
+}
+
+void mac802154_beacons_work(struct work_struct *work)
+{
+	struct ieee802154_local *local =
+		container_of(work, struct ieee802154_local, beacons_work.work);
+	struct ieee802154_sub_if_data *sdata;
+	struct wpan_dev *wpan_dev;
+	int ret;
+
+	mutex_lock(&local->beacons_lock);
+
+	if (!local->ongoing_beacons_request)
+		goto unlock_mutex;
+
+	if (local->suspended)
+		goto queue_work;
+
+	sdata = rcu_dereference_protected(local->beacons_sdata,
+					  lockdep_is_held(&local->beacons_lock));
+	wpan_dev = &sdata->wpan_dev;
+
+	ret = mac802154_transmit_beacon_locked(local, wpan_dev);
+	if (ret)
+		pr_err("Error when transmitting beacon (%d)\n", ret);
+
+queue_work:
+	ieee802154_queue_delayed_work(&local->hw, &local->beacons_work,
+				      local->beacons_interval);
+
+unlock_mutex:
+	mutex_unlock(&local->beacons_lock);
+}
+
+int mac802154_send_beacons_locked(struct ieee802154_sub_if_data *sdata,
+				  struct cfg802154_beacons_request *request)
+{
+	struct ieee802154_local *local = sdata->local;
+
+	lockdep_assert_held(&local->beacons_lock);
+
+	if (local->ongoing_beacons_request)
+		return -EBUSY;
+
+	local->ongoing_beacons_request = true;
+
+	memset(&local->beacon, 0, sizeof(local->beacon));
+	local->beacon.mhr.fc.type = IEEE802154_BEACON_FRAME;
+	local->beacon.mhr.fc.security_enabled = 0;
+	local->beacon.mhr.fc.frame_pending = 0;
+	local->beacon.mhr.fc.ack_request = 0;
+	local->beacon.mhr.fc.intra_pan = 0;
+	local->beacon.mhr.fc.dest_addr_mode = IEEE802154_NO_ADDRESSING;
+	local->beacon.mhr.fc.version = IEEE802154_2003_STD;
+	local->beacon.mhr.fc.source_addr_mode = IEEE802154_EXTENDED_ADDRESSING;
+	atomic_set(&request->wpan_dev->bsn, -1);
+	local->beacon.mhr.source.mode = IEEE802154_ADDR_LONG;
+	local->beacon.mhr.source.pan_id = cpu_to_le16(request->wpan_dev->pan_id);
+	local->beacon.mhr.source.extended_addr = cpu_to_le64(request->wpan_dev->extended_addr);
+	local->beacon.mac_pl.beacon_order = request->interval;
+	local->beacon.mac_pl.superframe_order = request->interval;
+	local->beacon.mac_pl.final_cap_slot = 0xf;
+	local->beacon.mac_pl.battery_life_ext = 0;
+	local->beacon.mac_pl.pan_coordinator = 1;
+	local->beacon.mac_pl.assoc_permit = 1;
+
+	rcu_assign_pointer(local->beacons_sdata, sdata);
+
+	/* Start the beacon work */
+	local->beacons_interval =
+		mac802154_scan_get_channel_time(request->interval,
+						request->wpan_phy->symbol_duration);
+	ieee802154_queue_delayed_work(&local->hw, &local->beacons_work, 0);
+
+	return 0;
+}
+
+int mac802154_stop_beacons_locked(struct ieee802154_local *local)
+{
+	lockdep_assert_held(&local->beacons_lock);
+
+	if (!local->ongoing_beacons_request)
+		return -ESRCH;
+
+	local->ongoing_beacons_request = false;
+	cancel_delayed_work(&local->beacons_work);
+
+	return 0;
+}
-- 
2.27.0


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

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-17 11:53 [PATCH v3 00/41] IEEE 802.15.4 scan support Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 01/41] MAINTAINERS: Remove Harry Morris bouncing address Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 02/41] net: ieee802154: hwsim: Ensure proper channel selection at probe time Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 03/41] net: ieee802154: hwsim: Ensure frame checksum are valid Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 04/41] net: ieee802154: Use the IEEE802154_MAX_PAGE define when relevant Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 05/41] net: ieee802154: Improve the way supported channels are declared Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 06/41] net: ieee802154: Give more details to the core about the channel configurations Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 07/41] net: ieee802154: mcr20a: Fix lifs/sifs periods Miquel Raynal
2022-01-17 22:52   ` Alexander Aring
2022-01-18 18:20     ` Miquel Raynal
2022-01-18 22:53       ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 08/41] net: mac802154: Convert the symbol duration into nanoseconds Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 09/41] net: mac802154: Set the symbol duration automatically Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 10/41] net: ieee802154: Drop duration settings when the core does it already Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 11/41] net: ieee802154: Move IEEE 802.15.4 Kconfig main entry Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 12/41] net: mac802154: Include the softMAC stack inside the IEEE 802.15.4 menu Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 13/41] net: ieee802154: Move the address structure earlier Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 14/41] net: ieee802154: Add a kernel doc header to the ieee802154_addr structure Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 15/41] net: ieee802154: Return meaningful error codes from the netlink helpers Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 16/41] net: mac802154: Explain the use of ieee802154_wake/stop_queue() Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 17/41] net: ieee802154: at86rf230: Call the complete helper when a transmission is over Miquel Raynal
2022-01-17 22:58   ` Alexander Aring
2022-01-18  0:34   ` Alexander Aring
2022-01-18  0:36     ` Alexander Aring
2022-01-18 18:22       ` Miquel Raynal
2022-01-19 22:45       ` Miquel Raynal
2022-01-19 22:56       ` Miquel Raynal
2022-01-19 23:34         ` Alexander Aring
2022-01-20  0:19           ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 18/41] net: ieee802154: atusb: " Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 19/41] net: ieee802154: ca8210: " Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 20/41] net: mac802154: Stop exporting ieee802154_wake/stop_queue() Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 21/41] net: mac802154: Rename the synchronous xmit worker Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 22/41] net: mac802154: Rename the main tx_work struct Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 23/41] net: mac802154: Follow the count of ongoing transmissions Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 24/41] net: mac802154: Hold the transmit queue when relevant Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 25/41] net: mac802154: Create a hot tx path Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 26/41] net: mac802154: Add a warning in the hot path Miquel Raynal
2022-01-17 23:14   ` Alexander Aring
2022-01-18 18:20     ` Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 27/41] net: mac802154: Introduce a tx queue flushing mechanism Miquel Raynal
2022-01-17 22:43   ` Alexander Aring
2022-01-18 18:14     ` Miquel Raynal
2022-01-18 23:16       ` Alexander Aring
2022-01-17 11:54 ` [PATCH v3 28/41] net: mac802154: Introduce a synchronous API for MLME commands Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 29/41] net: ieee802154: Add support for internal PAN management Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 30/41] net: ieee802154: Define a beacon frame header Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 31/41] net: ieee802154: Define frame types Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 32/41] net: ieee802154: Add support for scanning requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 33/41] net: mac802154: Handle scan requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 34/41] net: ieee802154: Full PAN management Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 35/41] net: ieee802154: Add beacons support Miquel Raynal
2022-01-17 11:54 ` Miquel Raynal [this message]
2022-01-17 11:54 ` [PATCH v3 37/41] net: ieee802154: Trace the registration of new PANs Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 38/41] net: mac802154: Add support for active scans Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 39/41] net: mac802154: Add support for processing beacon requests Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 40/41] net: ieee802154: Handle limited devices with only datagram support Miquel Raynal
2022-01-17 11:54 ` [PATCH v3 41/41] net: ieee802154: ca8210: Flag the driver as being limited Miquel Raynal
2022-01-17 23:02 ` [PATCH v3 00/41] IEEE 802.15.4 scan support Alexander Aring
2022-01-18 10:40   ` Miquel Raynal
2022-01-18 23:12     ` Alexander Aring
2022-01-20  0:24       ` Miquel Raynal

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=20220117115440.60296-37-miquel.raynal@bootlin.com \
    --to=miquel.raynal@bootlin.com \
    --cc=alan@signal11.us \
    --cc=alex.aring@gmail.com \
    --cc=david.girault@qorvo.com \
    --cc=frederic.blain@qorvo.com \
    --cc=kuba@kernel.org \
    --cc=linux-wireless@vger.kernel.org \
    --cc=linux-wpan@vger.kernel.org \
    --cc=liuxuenetmail@gmail.com \
    --cc=michael.hennerich@analog.com \
    --cc=netdev@vger.kernel.org \
    --cc=nico@ni.fr.eu.org \
    --cc=romuald.despres@qorvo.com \
    --cc=stefan@datenfreihafen.org \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=varkabhadram@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).