All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wenbo Cao <caowenbo@mucse.com>
To: Wenbo Cao <caowenbo@mucse.com>
Cc: dev@dpdk.org, ferruh.yigit@amd.com, thomas@monjalon.net,
	andrew.rybchenko@oktetlabs.ru, yaojun@mucse.com
Subject: [PATCH v6 5/8] net/rnp add reset code for Chip Init process
Date: Fri,  1 Sep 2023 02:30:47 +0000	[thread overview]
Message-ID: <20230901023050.40893-6-caowenbo@mucse.com> (raw)
In-Reply-To: <20230901023050.40893-1-caowenbo@mucse.com>

we must get the shape info of nic from Firmware for
reset. so the related codes is first get firmware info
and then reset the chip

Signed-off-by: Wenbo Cao <caowenbo@mucse.com>
---
 drivers/net/rnp/base/rnp_hw.h |  56 +++++++++++-
 drivers/net/rnp/meson.build   |   3 +
 drivers/net/rnp/rnp.h         |  27 ++++++
 drivers/net/rnp/rnp_ethdev.c  |  93 ++++++++++++++++++-
 drivers/net/rnp/rnp_mbx_fw.h  | 163 +++++++++++++++++++++++++++++++++-
 5 files changed, 339 insertions(+), 3 deletions(-)

diff --git a/drivers/net/rnp/base/rnp_hw.h b/drivers/net/rnp/base/rnp_hw.h
index 1db966cf21..57b7dc75a0 100644
--- a/drivers/net/rnp/base/rnp_hw.h
+++ b/drivers/net/rnp/base/rnp_hw.h
@@ -8,6 +8,9 @@
 #include <ethdev_driver.h>
 
 #include "rnp_osdep.h"
+#include "rnp_dma_regs.h"
+#include "rnp_eth_regs.h"
+#include "rnp_cfg.h"
 
 static inline unsigned int rnp_rd_reg(volatile void *addr)
 {
@@ -29,7 +32,18 @@ static inline void rnp_wr_reg(volatile void *reg, int val)
 	rnp_rd_reg((uint8_t *)(_base) + (_off))
 #define rnp_io_wr(_base, _off, _val)	\
 	rnp_wr_reg((uint8_t *)(_base) + (_off), (_val))
-
+#define rnp_eth_rd(_hw, _off)		\
+	rnp_rd_reg((uint8_t *)((_hw)->eth_base) + (_off))
+#define rnp_eth_wr(_hw, _off, _val)	\
+	rnp_wr_reg((uint8_t *)((_hw)->eth_base) + (_off), (_val))
+#define rnp_dma_rd(_hw, _off)		\
+	rnp_rd_reg((uint8_t *)((_hw)->dma_base) + (_off))
+#define rnp_dma_wr(_hw, _off, _val)	\
+	rnp_wr_reg((uint8_t *)((_hw)->dma_base) + (_off), (_val))
+#define rnp_top_rd(_hw, _off)		\
+	rnp_rd_reg((uint8_t *)((_hw)->comm_reg_base) + (_off))
+#define rnp_top_wr(_hw, _off, _val)	\
+	rnp_wr_reg((uint8_t *)((_hw)->comm_reg_base) + (_off), (_val))
 struct rnp_hw;
 /* Mbx Operate info */
 enum MBX_ID {
@@ -98,6 +112,17 @@ struct rnp_mbx_info {
 	rte_atomic16_t state;
 } __rte_cache_aligned;
 
+struct rnp_mac_api {
+	int32_t (*init_hw)(struct rnp_hw *hw);
+	int32_t (*reset_hw)(struct rnp_hw *hw);
+};
+
+struct rnp_mac_info {
+	uint8_t assign_addr[RTE_ETHER_ADDR_LEN];
+	uint8_t set_addr[RTE_ETHER_ADDR_LEN];
+	struct rnp_mac_api ops;
+} __rte_cache_aligned;
+
 struct rnp_eth_adapter;
 #define RNP_MAX_HW_PORT_PERR_PF (4)
 struct rnp_hw {
@@ -111,8 +136,10 @@ struct rnp_hw {
 	void *eth_base;
 	void *veb_base;
 	void *mac_base[RNP_MAX_HW_PORT_PERR_PF];
+	void *comm_reg_base;
 	void *msix_base;
 	/* === dma == */
+	void *dev_version;
 	void *dma_axi_en;
 	void *dma_axi_st;
 
@@ -120,10 +147,37 @@ struct rnp_hw {
 	uint16_t vendor_id;
 	uint16_t function;
 	uint16_t pf_vf_num;
+	int pfvfnum;
 	uint16_t max_vfs;
+
+	bool ncsi_en;
+	uint8_t ncsi_rar_entries;
+
+	int sgmii_phy_id;
+	int is_sgmii;
+	u16 phy_type;
+	uint8_t force_10g_1g_speed_ablity;
+	uint8_t force_speed_stat;
+#define FORCE_SPEED_STAT_DISABLED       (0)
+#define FORCE_SPEED_STAT_1G             (1)
+#define FORCE_SPEED_STAT_10G            (2)
+	uint32_t speed;
+	unsigned int axi_mhz;
+
+	int fw_version;  /* Primary FW Version */
+	uint32_t fw_uid; /* Subclass Fw Version */
+
+	int nic_mode;
+	unsigned char lane_mask;
+	int lane_of_port[4];
+	char phy_port_ids[4]; /* port id: for lane0~3: value: 0 ~ 7 */
+	uint8_t max_port_num; /* Max Port Num This PF Have */
+
 	void *cookie_pool;
 	char cookie_p_name[RTE_MEMZONE_NAMESIZE];
 
+	struct rnp_mac_info mac;
 	struct rnp_mbx_info mbx;
+	rte_spinlock_t fw_lock;
 } __rte_cache_aligned;
 #endif /* __RNP_H__*/
diff --git a/drivers/net/rnp/meson.build b/drivers/net/rnp/meson.build
index 60bba486fc..855c894032 100644
--- a/drivers/net/rnp/meson.build
+++ b/drivers/net/rnp/meson.build
@@ -9,5 +9,8 @@ endif
 sources = files(
 		'rnp_ethdev.c',
 		'rnp_mbx.c',
+		'rnp_mbx_fw.c',
+		'base/rnp_api.c',
 )
+
 includes += include_directories('base')
diff --git a/drivers/net/rnp/rnp.h b/drivers/net/rnp/rnp.h
index 6e12885877..45638aae5b 100644
--- a/drivers/net/rnp/rnp.h
+++ b/drivers/net/rnp/rnp.h
@@ -13,6 +13,20 @@
 #define RNP_CFG_BAR		(4)
 #define RNP_PF_INFO_BAR		(0)
 
+enum rnp_resource_share_m {
+	RNP_SHARE_CORPORATE = 0,
+	RNP_SHARE_INDEPENDENT,
+};
+/*
+ * Structure to store private data for each driver instance (for each port).
+ */
+enum rnp_work_mode {
+	RNP_SINGLE_40G = 0,
+	RNP_SINGLE_10G = 1,
+	RNP_DUAL_10G = 2,
+	RNP_QUAD_10G = 3,
+};
+
 struct rnp_eth_port {
 	struct rnp_eth_adapter *adapt;
 	struct rnp_hw *hw;
@@ -21,9 +35,12 @@ struct rnp_eth_port {
 
 struct rnp_share_ops {
 	const struct rnp_mbx_api *mbx_api;
+	const struct rnp_mac_api *mac_api;
 } __rte_cache_aligned;
 
 struct rnp_eth_adapter {
+	enum rnp_work_mode mode;
+	enum rnp_resource_share_m s_mode; /* Port Resource Share Policy */
 	struct rnp_hw hw;
 	uint16_t max_vfs;
 	struct rte_pci_device *pdev;
@@ -31,7 +48,9 @@ struct rnp_eth_adapter {
 	struct rnp_eth_port *ports[RNP_MAX_PORT_OF_PF];
 	struct rnp_share_ops *share_priv;
 
+	int max_link_speed;
 	uint8_t num_ports; /* Cur Pf Has physical Port Num */
+	uint8_t lane_mask;
 } __rte_cache_aligned;
 
 #define RNP_DEV_TO_PORT(eth_dev) \
@@ -40,9 +59,14 @@ struct rnp_eth_adapter {
 	((struct rnp_eth_adapter *)(RNP_DEV_TO_PORT(eth_dev)->adapt))
 #define RNP_DEV_TO_HW(eth_dev) \
 	(&((struct rnp_eth_adapter *)(RNP_DEV_TO_PORT((eth_dev))->adapt))->hw)
+#define RNP_HW_TO_ADAPTER(hw) \
+	((struct rnp_eth_adapter *)((hw)->back))
 #define RNP_DEV_PP_PRIV_TO_MBX_OPS(dev) \
 	(((struct rnp_share_ops *)(dev)->process_private)->mbx_api)
 #define RNP_DEV_TO_MBX_OPS(dev)	RNP_DEV_PP_PRIV_TO_MBX_OPS(dev)
+#define RNP_DEV_PP_PRIV_TO_MAC_OPS(dev) \
+	(((struct rnp_share_ops *)(dev)->process_private)->mac_api)
+#define RNP_DEV_TO_MAC_OPS(dev) RNP_DEV_PP_PRIV_TO_MAC_OPS(dev)
 
 static inline void rnp_reg_offset_init(struct rnp_hw *hw)
 {
@@ -56,6 +80,7 @@ static inline void rnp_reg_offset_init(struct rnp_hw *hw)
 		hw->msix_base = (void *)((uint8_t *)hw->iobar4 + 0xa4000);
 	}
 	/* === dma status/config====== */
+	hw->dev_version = (void *)((uint8_t *)hw->iobar4 + 0x0000);
 	hw->link_sync = (void *)((uint8_t *)hw->iobar4 + 0x000c);
 	hw->dma_axi_en = (void *)((uint8_t *)hw->iobar4 + 0x0010);
 	hw->dma_axi_st = (void *)((uint8_t *)hw->iobar4 + 0x0014);
@@ -69,5 +94,7 @@ static inline void rnp_reg_offset_init(struct rnp_hw *hw)
 	/* mac */
 	for (i = 0; i < RNP_MAX_HW_PORT_PERR_PF; i++)
 		hw->mac_base[i] = (void *)((uint8_t *)hw->iobar4 + 0x60000 + 0x10000 * i);
+	/* ===  top reg === */
+	hw->comm_reg_base = (void *)((uint8_t *)hw->iobar4 + 0x30000);
 }
 #endif /* __RNP_H__ */
diff --git a/drivers/net/rnp/rnp_ethdev.c b/drivers/net/rnp/rnp_ethdev.c
index a2dc27548a..8bb4fd5963 100644
--- a/drivers/net/rnp/rnp_ethdev.c
+++ b/drivers/net/rnp/rnp_ethdev.c
@@ -8,7 +8,9 @@
 #include <ethdev_driver.h>
 
 #include "rnp.h"
+#include "rnp_api.h"
 #include "rnp_mbx.h"
+#include "rnp_mbx_fw.h"
 #include "rnp_logs.h"
 
 static int
@@ -92,7 +94,30 @@ rnp_alloc_eth_port(struct rte_pci_device *primary_pci, char *name)
 
 static void rnp_get_nic_attr(struct rnp_eth_adapter *adapter)
 {
-	RTE_SET_USED(adapter);
+	struct rnp_hw *hw = &adapter->hw;
+	int lane_mask = 0, err, mode = 0;
+
+	rnp_mbx_link_event_enable(adapter->eth_dev, false);
+
+	err = rnp_mbx_get_capability(adapter->eth_dev, &lane_mask, &mode);
+	if (err < 0 || !lane_mask) {
+		PMD_DRV_LOG(ERR, "%s: mbx_get_capability error! errcode=%d\n",
+				__func__, hw->speed);
+		return;
+	}
+
+	adapter->num_ports = __builtin_popcount(lane_mask);
+	adapter->max_link_speed = hw->speed;
+	adapter->lane_mask = lane_mask;
+	adapter->mode = hw->nic_mode;
+
+	PMD_DRV_LOG(INFO, "max link speed:%d lane_mask:0x%x nic-mode:0x%x\n",
+			(int)adapter->max_link_speed,
+			(int)adapter->num_ports, adapter->mode);
+	if (adapter->num_ports && adapter->num_ports == 1)
+		adapter->s_mode = RNP_SHARE_CORPORATE;
+	else
+		adapter->s_mode = RNP_SHARE_INDEPENDENT;
 }
 
 static int
@@ -125,6 +150,72 @@ rnp_process_resource_init(struct rte_eth_dev *eth_dev)
 	return 0;
 }
 
+static int32_t rnp_init_hw_pf(struct rnp_hw *hw)
+{
+	struct rnp_eth_adapter *adapter = RNP_HW_TO_ADAPTER(hw);
+	uint32_t version;
+	uint32_t reg;
+
+	PMD_INIT_FUNC_TRACE();
+	version = rnp_rd_reg(hw->dev_version);
+	PMD_DRV_LOG(INFO, "NIC HW Version:0x%.2x\n", version);
+
+	/* Disable Rx/Tx Dma */
+	rnp_wr_reg(hw->dma_axi_en, false);
+	/* Check Dma Chanle Status */
+	while (rnp_rd_reg(hw->dma_axi_st) == 0)
+		;
+
+	/* Reset Nic All Hardware */
+	if (rnp_reset_hw(adapter->eth_dev, hw))
+		return -EPERM;
+
+	/* Rx Proto Offload No-BYPASS */
+	rnp_eth_wr(hw, RNP_ETH_ENGINE_BYPASS, false);
+	/* Enable Flow Filter Engine */
+	rnp_eth_wr(hw, RNP_HOST_FILTER_EN, true);
+	/* Enable VXLAN Parse */
+	rnp_eth_wr(hw, RNP_EN_TUNNEL_VXLAN_PARSE, true);
+	/* Enabled REDIR ACTION */
+	rnp_eth_wr(hw, RNP_REDIR_CTRL, true);
+
+	/* Setup Scatter DMA Mem Size */
+	reg = ((RTE_ETHER_MAX_LEN / 16) << RNP_DMA_SCATTER_MEM_SHIFT);
+	rnp_dma_wr(hw,  RNP_DMA_CTRL, reg);
+#ifdef PHYTIUM_SUPPORT
+#define RNP_DMA_PADDING      (1 << 8)
+	reg = rnp_dma_rd(hw, RNP_DMA_CTRL);
+	reg |= RNP_DMA_PADDING;
+	rnp_dma_wr(hw, RNP_DMA_CTRL, reg);
+#endif
+	/* Enable Rx/Tx Dma */
+	rnp_wr_reg(hw->dma_axi_en, 0b1111);
+
+	rnp_top_wr(hw, RNP_TX_QINQ_WORKAROUND, 1);
+
+	return 0;
+}
+
+static int32_t rnp_reset_hw_pf(struct rnp_hw *hw)
+{
+	struct rnp_eth_adapter *adapter = hw->back;
+
+	rnp_top_wr(hw, RNP_NIC_RESET, 0);
+	rte_wmb();
+	rnp_top_wr(hw, RNP_NIC_RESET, 1);
+
+	rnp_mbx_fw_reset_phy(adapter->eth_dev);
+
+	PMD_DRV_LOG(INFO, "PF[%d] reset nic finish\n",
+			hw->function);
+	return 0;
+}
+
+const struct rnp_mac_api rnp_mac_ops = {
+	.reset_hw	= rnp_reset_hw_pf,
+	.init_hw	= rnp_init_hw_pf
+};
+
 static void
 rnp_common_ops_init(struct rnp_eth_adapter *adapter)
 {
diff --git a/drivers/net/rnp/rnp_mbx_fw.h b/drivers/net/rnp/rnp_mbx_fw.h
index 439090b5a3..f842639c86 100644
--- a/drivers/net/rnp/rnp_mbx_fw.h
+++ b/drivers/net/rnp/rnp_mbx_fw.h
@@ -16,7 +16,168 @@ struct mbx_req_cookie {
 	int priv_len;
 	char priv[RNP_MAX_SHARE_MEM];
 };
+enum GENERIC_CMD {
+	/* link configuration admin commands */
+	GET_PHY_ABALITY = 0x0601,
+	RESET_PHY = 0x0603,
+	SET_EVENT_MASK = 0x0613,
+};
+
+enum link_event_mask {
+	EVT_LINK_UP = 1,
+	EVT_NO_MEDIA = 2,
+	EVT_LINK_FAULT = 3,
+	EVT_PHY_TEMP_ALARM = 4,
+	EVT_EXCESSIVE_ERRORS = 5,
+	EVT_SIGNAL_DETECT = 6,
+	EVT_AUTO_NEGOTIATION_DONE = 7,
+	EVT_MODULE_QUALIFICATION_FAILED = 8,
+	EVT_PORT_TX_SUSPEND = 9,
+};
+
+enum pma_type {
+	PHY_TYPE_NONE = 0,
+	PHY_TYPE_1G_BASE_KX,
+	PHY_TYPE_SGMII,
+	PHY_TYPE_10G_BASE_KR,
+	PHY_TYPE_25G_BASE_KR,
+	PHY_TYPE_40G_BASE_KR4,
+	PHY_TYPE_10G_BASE_SR,
+	PHY_TYPE_40G_BASE_SR4,
+	PHY_TYPE_40G_BASE_CR4,
+	PHY_TYPE_40G_BASE_LR4,
+	PHY_TYPE_10G_BASE_LR,
+	PHY_TYPE_10G_BASE_ER,
+};
+
+struct phy_abilities {
+	unsigned char link_stat;
+	unsigned char lane_mask;
+
+	int speed;
+	short phy_type;
+	short nic_mode;
+	short pfnum;
+	unsigned int fw_version;
+	unsigned int axi_mhz;
+	uint8_t port_ids[4];
+	uint32_t fw_uid;
+	uint32_t phy_id;
+
+	int wol_status;
+
+	union {
+		unsigned int ext_ablity;
+		struct {
+			unsigned int valid                 : 1;
+			unsigned int wol_en                : 1;
+			unsigned int pci_preset_runtime_en : 1;
+			unsigned int smbus_en              : 1;
+			unsigned int ncsi_en               : 1;
+			unsigned int rpu_en                : 1;
+			unsigned int v2                    : 1;
+			unsigned int pxe_en                : 1;
+			unsigned int mctp_en               : 1;
+		} e;
+	};
+} __rte_packed __rte_aligned(4);
+
+/* firmware -> driver */
 struct mbx_fw_cmd_reply {
-} __rte_cache_aligned;
+	/* fw must set: DD, CMP, Error(if error), copy value */
+	unsigned short flags;
+	/* from command: LB,RD,VFC,BUF,SI,EI,FE */
+	unsigned short opcode;     /* 2-3: copy from req */
+	unsigned short error_code; /* 4-5: 0 if no error */
+	unsigned short datalen;    /* 6-7: */
+	union {
+		struct {
+			unsigned int cookie_lo; /* 8-11: */
+			unsigned int cookie_hi; /* 12-15: */
+		};
+		void *cookie;
+	};
+	/* ===== data ==== [16-64] */
+	union {
+		struct phy_abilities phy_abilities;
+	};
+} __rte_packed __rte_aligned(4);
+
+#define MBX_REQ_HDR_LEN            24
+/* driver -> firmware */
+struct mbx_fw_cmd_req {
+	unsigned short flags;     /* 0-1 */
+	unsigned short opcode;    /* 2-3 enum LINK_ADM_CMD */
+	unsigned short datalen;   /* 4-5 */
+	unsigned short ret_value; /* 6-7 */
+	union {
+		struct {
+			unsigned int cookie_lo; /* 8-11 */
+			unsigned int cookie_hi; /* 12-15 */
+		};
+		void *cookie;
+	};
+	unsigned int reply_lo; /* 16-19 5dw */
+	unsigned int reply_hi; /* 20-23 */
+	/* === data === [24-64] 7dw */
+	union {
+		struct {
+			int requester;
+#define REQUEST_BY_DPDK 0xa1
+#define REQUEST_BY_DRV  0xa2
+#define REQUEST_BY_PXE  0xa3
+		} get_phy_ablity;
+
+		struct {
+			unsigned short enable_stat;
+			unsigned short event_mask; /* enum link_event_mask */
+		} stat_event_mask;
+	};
+} __rte_packed __rte_aligned(4);
+
+static inline void
+build_phy_abalities_req(struct mbx_fw_cmd_req *req, void *cookie)
+{
+	req->flags   = 0;
+	req->opcode  = GET_PHY_ABALITY;
+	req->datalen = 0;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->cookie = cookie;
+}
+
+/* enum link_event_mask or */
+static inline void
+build_link_set_event_mask(struct mbx_fw_cmd_req *req,
+			  unsigned short event_mask,
+			  unsigned short enable,
+			  void *cookie)
+{
+	req->flags = 0;
+	req->opcode = SET_EVENT_MASK;
+	req->datalen = sizeof(req->stat_event_mask);
+	req->cookie = cookie;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->stat_event_mask.event_mask = event_mask;
+	req->stat_event_mask.enable_stat = enable;
+}
+
+static inline void
+build_reset_phy_req(struct mbx_fw_cmd_req *req,
+		    void *cookie)
+{
+	req->flags = 0;
+	req->opcode = RESET_PHY;
+	req->datalen = 0;
+	req->reply_lo = 0;
+	req->reply_hi = 0;
+	req->cookie = cookie;
+}
 
+int rnp_mbx_get_capability(struct rte_eth_dev *dev,
+			   int *lane_mask,
+			   int *nic_mode);
+int rnp_mbx_link_event_enable(struct rte_eth_dev *dev, int enable);
+int rnp_mbx_fw_reset_phy(struct rte_eth_dev *dev);
 #endif /* __RNP_MBX_FW_H__*/
-- 
2.27.0


  parent reply	other threads:[~2023-09-01  2:32 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-01  2:30 [PATCH v6 0/8] [v6]drivers/net Add Support mucse N10 Pmd Driver Wenbo Cao
2023-09-01  2:30 ` [PATCH v6 1/8] net/rnp: add skeleton Wenbo Cao
2023-09-05 15:35   ` Ferruh Yigit
2023-09-06  8:15     ` 11
2024-03-29 11:28   ` Ferruh Yigit
2024-03-29 14:45     ` 11
2024-04-02 10:15       ` Ferruh Yigit
2023-09-01  2:30 ` [PATCH v6 2/8] net/rnp: add ethdev probe and remove Wenbo Cao
2023-09-05 15:36   ` Ferruh Yigit
2023-09-06 10:42     ` 11
2023-09-01  2:30 ` [PATCH v6 3/8] net/rnp: add device init and uninit Wenbo Cao
2023-09-05 15:44   ` Ferruh Yigit
2023-09-06 11:03     ` 11
2023-09-01  2:30 ` [PATCH v6 4/8] net/rnp: add mbx basic api feature Wenbo Cao
2023-09-05 15:45   ` Ferruh Yigit
2023-09-06 10:32     ` 11
2023-09-01  2:30 ` Wenbo Cao [this message]
2023-09-05 15:46   ` [PATCH v6 5/8] net/rnp add reset code for Chip Init process Ferruh Yigit
2023-09-06  9:23     ` 11
2023-09-01  2:30 ` [PATCH v6 6/8] net/rnp add port info resource init Wenbo Cao
2023-09-05 16:56   ` Ferruh Yigit
2023-09-06  9:07     ` 11
2023-09-01  2:30 ` [PATCH v6 7/8] net/rnp add devargs runtime parsing functions Wenbo Cao
2023-09-05 15:46   ` Ferruh Yigit
2023-09-06  9:13     ` 11
2023-09-01  2:30 ` [PATCH v6 8/8] net/rnp handle device interrupts Wenbo Cao
2023-09-05 15:34 ` [PATCH v6 0/8] [v6]drivers/net Add Support mucse N10 Pmd Driver Ferruh Yigit

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=20230901023050.40893-6-caowenbo@mucse.com \
    --to=caowenbo@mucse.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=thomas@monjalon.net \
    --cc=yaojun@mucse.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 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.