All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tetsuya Mukawa <mukawa@igel.co.jp>
To: dev@dpdk.org
Subject: [PATCH v3 4/8] eal: Consolidate rte_eal_pci_probe/close_one_driver() of linuxapp and bsdapp
Date: Mon, 29 Jun 2015 11:56:46 +0900	[thread overview]
Message-ID: <1435546610-4533-5-git-send-email-mukawa@igel.co.jp> (raw)
In-Reply-To: <1435546610-4533-1-git-send-email-mukawa@igel.co.jp>

From: "Tetsuya.Mukawa" <mukawa@igel.co.jp>

This patch consolidates below functions, and implements these in common
eal code.
 - rte_eal_pci_probe_one_driver()
 - rte_eal_pci_close_one_driver()

Because pci_map_device() is only implemented in linuxapp, the patch
implements it in bsdapp too. This implemented function will be merged to
linuxapp one with later patch.

Signed-off-by: Tetsuya Mukawa <mukawa@igel.co.jp>
---
 lib/librte_eal/bsdapp/eal/eal_pci.c    |  74 ++---------------
 lib/librte_eal/common/eal_common_pci.c | 129 ++++++++++++++++++++++++++++
 lib/librte_eal/common/eal_private.h    |  21 ++---
 lib/librte_eal/linuxapp/eal/eal_pci.c  | 148 ++-------------------------------
 4 files changed, 153 insertions(+), 219 deletions(-)

diff --git a/lib/librte_eal/bsdapp/eal/eal_pci.c b/lib/librte_eal/bsdapp/eal/eal_pci.c
index c7017eb..2a623e3 100644
--- a/lib/librte_eal/bsdapp/eal/eal_pci.c
+++ b/lib/librte_eal/bsdapp/eal/eal_pci.c
@@ -88,7 +88,7 @@ static struct rte_tailq_elem rte_uio_tailq = {
 EAL_REGISTER_TAILQ(rte_uio_tailq)
 
 /* unbind kernel driver for this device */
-static int
+int
 pci_unbind_kernel_driver(struct rte_pci_device *dev __rte_unused)
 {
 	RTE_LOG(ERR, EAL, "RTE_PCI_DRV_FORCE_UNBIND flag is not implemented "
@@ -430,6 +430,13 @@ skipdev:
 	return 0;
 }
 
+/* Map pci device */
+int
+pci_map_device(struct rte_pci_device *dev)
+{
+	return pci_uio_map_resource(dev);
+}
+
 /*
  * Scan the content of the PCI bus, and add the devices in the devices
  * list. Call pci_scan_one() for each pci entry found.
@@ -480,71 +487,6 @@ error:
 	return -1;
 }
 
-/*
- * If vendor/device ID match, call the devinit() function of the
- * driver.
- */
-int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
-{
-	const struct rte_pci_id *id_table;
-	int ret;
-
-	for (id_table = dr->id_table ; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->numa_node);
-
-		RTE_LOG(DEBUG, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->name);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->devargs != NULL &&
-			dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
-
-			RTE_LOG(DEBUG, EAL, "  Device is blacklisted, not initializing\n");
-			return 0;
-		}
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-			/* map resources for devices that use igb_uio */
-			ret = pci_uio_map_resource(dev);
-			if (ret != 0)
-				return ret;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-		           rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver devinit() function */
-		return dr->devinit(dr, dev);
-	}
-	/* return positive value if driver is not found */
-	return 1;
-}
-
 /* Init the PCI EAL subsystem */
 int
 rte_eal_pci_init(void)
diff --git a/lib/librte_eal/common/eal_common_pci.c b/lib/librte_eal/common/eal_common_pci.c
index 4229aaf..6eb6257 100644
--- a/lib/librte_eal/common/eal_common_pci.c
+++ b/lib/librte_eal/common/eal_common_pci.c
@@ -99,6 +99,135 @@ static struct rte_devargs *pci_devargs_lookup(struct rte_pci_device *dev)
 }
 
 /*
+ * If vendor/device ID match, call the devinit() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
+{
+	int ret;
+	const struct rte_pci_id *id_table;
+
+	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+
+		/* check if device's identifiers match the driver's ones */
+		if (id_table->vendor_id != dev->id.vendor_id &&
+				id_table->vendor_id != PCI_ANY_ID)
+			continue;
+		if (id_table->device_id != dev->id.device_id &&
+				id_table->device_id != PCI_ANY_ID)
+			continue;
+		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
+				id_table->subsystem_vendor_id != PCI_ANY_ID)
+			continue;
+		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
+				id_table->subsystem_device_id != PCI_ANY_ID)
+			continue;
+
+		struct rte_pci_addr *loc = &dev->addr;
+
+		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+				loc->domain, loc->bus, loc->devid, loc->function,
+				dev->numa_node);
+
+		RTE_LOG(DEBUG, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
+				dev->id.device_id, dr->name);
+
+		/* no initialization when blacklisted, return without error */
+		if (dev->devargs != NULL &&
+			dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
+			RTE_LOG(DEBUG, EAL, "  Device is blacklisted, not initializing\n");
+			return 1;
+		}
+
+		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
+#ifdef RTE_PCI_CONFIG
+			/*
+			 * Set PCIe config space for high performance.
+			 * Return value can be ignored.
+			 */
+			pci_config_space_set(dev);
+#endif
+			/* map resources for devices that use igb_uio */
+			ret = pci_map_device(dev);
+			if (ret != 0)
+				return ret;
+		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
+				rte_eal_process_type() == RTE_PROC_PRIMARY) {
+			/* unbind current driver */
+			if (pci_unbind_kernel_driver(dev) < 0)
+				return -1;
+		}
+
+		/* reference driver structure */
+		dev->driver = dr;
+
+		/* call the driver devinit() function */
+		return dr->devinit(dr, dev);
+	}
+	/* return positive value if driver is not found */
+	return 1;
+}
+
+#ifdef RTE_LIBRTE_EAL_HOTPLUG
+/*
+ * If vendor/device ID match, call the devuninit() function of the
+ * driver.
+ */
+static int
+rte_eal_pci_close_one_driver(struct rte_pci_driver *dr,
+		struct rte_pci_device *dev)
+{
+	const struct rte_pci_id *id_table;
+
+	if ((dr == NULL) || (dev == NULL))
+		return -EINVAL;
+
+	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
+
+		/* check if device's identifiers match the driver's ones */
+		if (id_table->vendor_id != dev->id.vendor_id &&
+				id_table->vendor_id != PCI_ANY_ID)
+			continue;
+		if (id_table->device_id != dev->id.device_id &&
+				id_table->device_id != PCI_ANY_ID)
+			continue;
+		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
+				id_table->subsystem_vendor_id != PCI_ANY_ID)
+			continue;
+		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
+				id_table->subsystem_device_id != PCI_ANY_ID)
+			continue;
+
+		struct rte_pci_addr *loc = &dev->addr;
+
+		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
+				loc->domain, loc->bus, loc->devid,
+				loc->function, dev->numa_node);
+
+		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n", dev->id.vendor_id,
+				dev->id.device_id, dr->name);
+
+		/* call the driver devuninit() function */
+		if (dr->devuninit && (dr->devuninit(dev) < 0))
+			return -1;	/* negative value is an error */
+
+		/* clear driver structure */
+		dev->driver = NULL;
+
+		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
+			/* unmap resources for devices that use igb_uio */
+			pci_unmap_device(dev);
+
+		return 0;
+	}
+
+	/* return positive value if driver is not found */
+	return 1;
+}
+#endif /* RTE_LIBRTE_EAL_HOTPLUG */
+
+/*
  * If vendor/device ID match, call the devinit() function of all
  * registered driver for the given device. Return -1 if initialization
  * failed, return 1 if no driver is found for this device.
diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h
index 4acf5a0..fe2c596 100644
--- a/lib/librte_eal/common/eal_private.h
+++ b/lib/librte_eal/common/eal_private.h
@@ -154,30 +154,31 @@ struct rte_pci_driver;
 struct rte_pci_device;
 
 /**
- * Mmap memory for single PCI device
+ * Unbind kernel driver for this device
  *
  * This function is private to EAL.
  *
  * @return
  *   0 on success, negative on error
  */
-int rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev);
+int pci_unbind_kernel_driver(struct rte_pci_device *dev);
 
 /**
- * Munmap memory for single PCI device
+ * Map this device
  *
  * This function is private to EAL.
  *
- * @param	dr
- *  The pointer to the pci driver structure
- * @param	dev
- *  The pointer to the pci device structure
  * @return
  *   0 on success, negative on error
  */
-int rte_eal_pci_close_one_driver(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev);
+int pci_map_device(struct rte_pci_device *dev);
+
+/**
+ * Unmap this device
+ *
+ * This function is private to EAL.
+ */
+void pci_unmap_device(struct rte_pci_device *dev);
 
 /**
  * Init tail queues for non-EAL library structures. This is to allow
diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c
index d2adc66..91e958e 100644
--- a/lib/librte_eal/linuxapp/eal/eal_pci.c
+++ b/lib/librte_eal/linuxapp/eal/eal_pci.c
@@ -57,7 +57,7 @@
  */
 
 /* unbind kernel driver for this device */
-static int
+int
 pci_unbind_kernel_driver(struct rte_pci_device *dev)
 {
 	int n;
@@ -563,7 +563,8 @@ pci_config_space_set(struct rte_pci_device *dev)
 }
 #endif
 
-static int
+/* Map pci device */
+int
 pci_map_device(struct rte_pci_device *dev)
 {
 	int ret = -1;
@@ -592,7 +593,8 @@ pci_map_device(struct rte_pci_device *dev)
 }
 
 #ifdef RTE_LIBRTE_EAL_HOTPLUG
-static void
+/* Unmap pci device */
+void
 pci_unmap_device(struct rte_pci_device *dev)
 {
 	if (dev == NULL)
@@ -616,146 +618,6 @@ pci_unmap_device(struct rte_pci_device *dev)
 }
 #endif /* RTE_LIBRTE_EAL_HOTPLUG */
 
-/*
- * If vendor/device ID match, call the devinit() function of the
- * driver.
- */
-int
-rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *dev)
-{
-	int ret;
-	const struct rte_pci_id *id_table;
-
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-				id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-				id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id != dev->id.subsystem_vendor_id &&
-				id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id != dev->id.subsystem_device_id &&
-				id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(DEBUG, EAL, "PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid, loc->function,
-				dev->numa_node);
-
-		RTE_LOG(DEBUG, EAL, "  probe driver: %x:%x %s\n", dev->id.vendor_id,
-				dev->id.device_id, dr->name);
-
-		/* no initialization when blacklisted, return without error */
-		if (dev->devargs != NULL &&
-			dev->devargs->type == RTE_DEVTYPE_BLACKLISTED_PCI) {
-			RTE_LOG(DEBUG, EAL, "  Device is blacklisted, not initializing\n");
-			return 1;
-		}
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING) {
-#ifdef RTE_PCI_CONFIG
-			/*
-			 * Set PCIe config space for high performance.
-			 * Return value can be ignored.
-			 */
-			pci_config_space_set(dev);
-#endif
-			/* map resources for devices that use igb_uio */
-			ret = pci_map_device(dev);
-			if (ret != 0)
-				return ret;
-		} else if (dr->drv_flags & RTE_PCI_DRV_FORCE_UNBIND &&
-		           rte_eal_process_type() == RTE_PROC_PRIMARY) {
-			/* unbind current driver */
-			if (pci_unbind_kernel_driver(dev) < 0)
-				return -1;
-		}
-
-		/* reference driver structure */
-		dev->driver = dr;
-
-		/* call the driver devinit() function */
-		return dr->devinit(dr, dev);
-	}
-	/* return positive value if driver is not found */
-	return 1;
-}
-
-#ifdef RTE_LIBRTE_EAL_HOTPLUG
-/*
- * If vendor/device ID match, call the devuninit() function of the
- * driver.
- */
-int
-rte_eal_pci_close_one_driver(struct rte_pci_driver *dr,
-		struct rte_pci_device *dev)
-{
-	const struct rte_pci_id *id_table;
-
-	if ((dr == NULL) || (dev == NULL))
-		return -EINVAL;
-
-	for (id_table = dr->id_table; id_table->vendor_id != 0; id_table++) {
-
-		/* check if device's identifiers match the driver's ones */
-		if (id_table->vendor_id != dev->id.vendor_id &&
-		    id_table->vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->device_id != dev->id.device_id &&
-		    id_table->device_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_vendor_id !=
-		    dev->id.subsystem_vendor_id &&
-		    id_table->subsystem_vendor_id != PCI_ANY_ID)
-			continue;
-		if (id_table->subsystem_device_id !=
-		    dev->id.subsystem_device_id &&
-		    id_table->subsystem_device_id != PCI_ANY_ID)
-			continue;
-
-		struct rte_pci_addr *loc = &dev->addr;
-
-		RTE_LOG(DEBUG, EAL,
-				"PCI device "PCI_PRI_FMT" on NUMA socket %i\n",
-				loc->domain, loc->bus, loc->devid,
-				loc->function, dev->numa_node);
-
-		RTE_LOG(DEBUG, EAL, "  remove driver: %x:%x %s\n",
-				dev->id.vendor_id, dev->id.device_id,
-				dr->name);
-
-		/* call the driver devuninit() function */
-		if (dr->devuninit && (dr->devuninit(dev) < 0))
-			return -1;	/* negative value is an error */
-
-		/* clear driver structure */
-		dev->driver = NULL;
-
-		if (dr->drv_flags & RTE_PCI_DRV_NEED_MAPPING)
-			/* unmap resources for devices that use igb_uio */
-			pci_unmap_device(dev);
-
-		return 0;
-	}
-	/* return positive value if driver is not found */
-	return 1;
-}
-#else /* RTE_LIBRTE_EAL_HOTPLUG */
-int
-rte_eal_pci_close_one_driver(struct rte_pci_driver *dr __rte_unused,
-		struct rte_pci_device *dev __rte_unused)
-{
-	RTE_LOG(ERR, EAL, "Hotplug support isn't enabled\n");
-	return -1;
-}
-#endif /* RTE_LIBRTE_EAL_HOTPLUG */
-
 /* Init the PCI EAL subsystem */
 int
 rte_eal_pci_init(void)
-- 
2.1.4

  parent reply	other threads:[~2015-06-29  2:57 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-19  6:21 [PATCH 0/8] Add Port Hotplug support to BSD Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 1/8] eal: Add pci_uio_alloc_uio_resource() Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 2/8] eal: Add pci_uio_map_uio_resource_by_index() Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 3/8] eal: Consolidate pci_map and mapped_pci_resource of linuxapp and bsdapp Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 4/8] eal: Consolidate rte_eal_pci_probe/close_one_driver() " Tetsuya Mukawa
2015-06-26  8:21   ` [PATCH v2 0/8] Add Port Hotplug support to BSD Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 1/8] eal: Add pci_uio_alloc_uio_resource() Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 2/8] eal: Add pci_uio_map_uio_resource_by_index() Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 3/8] eal: Consolidate pci_map and mapped_pci_resource of linuxapp and bsdapp Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 4/8] eal: Consolidate rte_eal_pci_probe/close_one_driver() " Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 5/8] eal: Consolidate pci_map/unmap_device() " Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 6/8] eal: Consolidate pci_map/unmap_resource() " Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 7/8] eal: Consolidate pci uio functions " Tetsuya Mukawa
2015-06-26  8:21     ` [PATCH v2 8/8] eal: Enable Port Hotplug as default in Linux and BSD Tetsuya Mukawa
2015-06-29  2:56   ` [PATCH v3 0/8] Add Port Hotplug support to BSD Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 1/8] eal: Add pci_uio_alloc_uio_resource() Tetsuya Mukawa
2015-06-29 13:24       ` Iremonger, Bernard
2015-06-30  2:31         ` Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 2/8] eal: Add pci_uio_map_uio_resource_by_index() Tetsuya Mukawa
2015-06-29 13:36       ` Iremonger, Bernard
2015-06-30  2:34         ` Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 3/8] eal: Consolidate pci_map and mapped_pci_resource of linuxapp and bsdapp Tetsuya Mukawa
2015-06-29  2:56     ` Tetsuya Mukawa [this message]
2015-06-29 15:28       ` [PATCH v3 4/8] eal: Consolidate rte_eal_pci_probe/close_one_driver() " Bruce Richardson
2015-06-30  8:08         ` Tetsuya Mukawa
2015-06-30 12:50           ` Bruce Richardson
2015-06-29  2:56     ` [PATCH v3 5/8] eal: Consolidate pci_map/unmap_device() " Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 6/8] eal: Consolidate pci_map/unmap_resource() " Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 7/8] eal: Consolidate pci uio functions " Tetsuya Mukawa
2015-06-29 14:03       ` Iremonger, Bernard
2015-06-30  2:43         ` Tetsuya Mukawa
2015-06-30  8:28           ` Tetsuya Mukawa
2015-06-29  2:56     ` [PATCH v3 8/8] eal: Enable Port Hotplug as default in Linux and BSD Tetsuya Mukawa
2015-06-30  8:26       ` [PATCH v4] Add Port Hotplug support to BSD Tetsuya Mukawa
2015-06-30  8:26         ` [PATCH v4] eal: Enable Port Hotplug as default in Linux and BSD Tetsuya Mukawa
2015-06-30 15:08           ` Iremonger, Bernard
2015-06-30 15:40             ` Bruce Richardson
2015-07-01  6:37               ` Tetsuya Mukawa
2015-07-08 22:15           ` Thomas Monjalon
2015-06-29 15:30     ` [PATCH v3 0/8] Add Port Hotplug support to BSD Bruce Richardson
2015-06-30  8:08       ` Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 5/8] eal: Consolidate pci_map/unmap_device() of linuxapp and bsdapp Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 6/8] eal: Consolidate pci_map/unmap_resource() " Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 7/8] eal: Consolidate pci uio functions " Tetsuya Mukawa
2015-05-19  6:21 ` [PATCH 8/8] eal: Enable Port Hotplug as default in Linux and BSD Tetsuya Mukawa
2015-05-19 16:03 ` [PATCH 0/8] Add Port Hotplug support to BSD Stephen Hemminger

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=1435546610-4533-5-git-send-email-mukawa@igel.co.jp \
    --to=mukawa@igel.co.jp \
    --cc=dev@dpdk.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.