Blame SOURCES/0001-net-enic-allocate-stats-DMA-buffer-upfront-during-pr.patch

c7ffa4
From 8d782f3f89e1dcd0c8af1c3c93501d7a06159d66 Mon Sep 17 00:00:00 2001
c7ffa4
From: Hyong Youb Kim <hyonkim@cisco.com>
c7ffa4
Date: Wed, 7 Mar 2018 18:46:58 -0800
c7ffa4
Subject: [PATCH] net/enic: allocate stats DMA buffer upfront during probe
c7ffa4
c7ffa4
The driver provides a DMA buffer to the firmware when it requests port
c7ffa4
stats. The NIC then fills that buffer with latest stats. Currently,
c7ffa4
the driver allocates the DMA buffer the first time it requests stats
c7ffa4
and saves it for later use. This can lead to crashes when
c7ffa4
primary/secondary processes are involved. For example, the following
c7ffa4
sequence crashes the secondary process.
c7ffa4
c7ffa4
1. Start a primary app that does not call rte_eth_stats_get()
c7ffa4
2. dpdk-procinfo -- --stats
c7ffa4
c7ffa4
dpdk-procinfo crashes while trying to allocate the stats DMA buffer
c7ffa4
because the alloc function pointer (vdev.alloc_consistent) is valid
c7ffa4
only in the primary process, not in the secondary process.
c7ffa4
c7ffa4
Overwriting the alloc function pointer in the secondary process is not
c7ffa4
an option, as it will simply make the pointer invalid in the primary
c7ffa4
process. Instead, allocate the DMA buffer during probe so that only
c7ffa4
the primary process does both allocate and free. This allows the
c7ffa4
secondary process to dump stats as well.
c7ffa4
c7ffa4
Fixes: 9913fbb91df0 ("enic/base: common code")
c7ffa4
Cc: stable@dpdk.org
c7ffa4
c7ffa4
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
c7ffa4
Reviewed-by: John Daley <johndale@cisco.com>
c7ffa4
---
c7ffa4
 drivers/net/enic/base/vnic_dev.c | 24 ++++++++++++++----------
c7ffa4
 drivers/net/enic/base/vnic_dev.h |  1 +
c7ffa4
 drivers/net/enic/enic_main.c     |  9 +++++++++
c7ffa4
 3 files changed, 24 insertions(+), 10 deletions(-)
c7ffa4
c7ffa4
diff --git a/drivers/net/enic/base/vnic_dev.c b/drivers/net/enic/base/vnic_dev.c
c7ffa4
index 05b595eb8..1f8d222fc 100644
c7ffa4
--- a/drivers/net/enic/base/vnic_dev.c
c7ffa4
+++ b/drivers/net/enic/base/vnic_dev.c
c7ffa4
@@ -587,17 +587,9 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats)
c7ffa4
 {
c7ffa4
 	u64 a0, a1;
c7ffa4
 	int wait = 1000;
c7ffa4
-	static u32 instance;
c7ffa4
-	char name[NAME_MAX];
c7ffa4
 
c7ffa4
-	if (!vdev->stats) {
c7ffa4
-		snprintf((char *)name, sizeof(name),
c7ffa4
-			"vnic_stats-%u", instance++);
c7ffa4
-		vdev->stats = vdev->alloc_consistent(vdev->priv,
c7ffa4
-			sizeof(struct vnic_stats), &vdev->stats_pa, (u8 *)name);
c7ffa4
-		if (!vdev->stats)
c7ffa4
-			return -ENOMEM;
c7ffa4
-	}
c7ffa4
+	if (!vdev->stats)
c7ffa4
+		return -ENOMEM;
c7ffa4
 
c7ffa4
 	*stats = vdev->stats;
c7ffa4
 	a0 = vdev->stats_pa;
c7ffa4
@@ -922,6 +914,18 @@ u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev)
c7ffa4
 	return vdev->intr_coal_timer_info.max_usec;
c7ffa4
 }
c7ffa4
 
c7ffa4
+int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev)
c7ffa4
+{
c7ffa4
+	char name[NAME_MAX];
c7ffa4
+	static u32 instance;
c7ffa4
+
c7ffa4
+	snprintf((char *)name, sizeof(name), "vnic_stats-%u", instance++);
c7ffa4
+	vdev->stats = vdev->alloc_consistent(vdev->priv,
c7ffa4
+					     sizeof(struct vnic_stats),
c7ffa4
+					     &vdev->stats_pa, (u8 *)name);
c7ffa4
+	return vdev->stats == NULL ? -ENOMEM : 0;
c7ffa4
+}
c7ffa4
+
c7ffa4
 void vnic_dev_unregister(struct vnic_dev *vdev)
c7ffa4
 {
c7ffa4
 	if (vdev) {
c7ffa4
diff --git a/drivers/net/enic/base/vnic_dev.h b/drivers/net/enic/base/vnic_dev.h
c7ffa4
index 8c0992063..7e5736b4d 100644
c7ffa4
--- a/drivers/net/enic/base/vnic_dev.h
c7ffa4
+++ b/drivers/net/enic/base/vnic_dev.h
c7ffa4
@@ -165,6 +165,7 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
c7ffa4
 	void *priv, struct rte_pci_device *pdev, struct vnic_dev_bar *bar,
c7ffa4
 	unsigned int num_bars);
c7ffa4
 struct rte_pci_device *vnic_dev_get_pdev(struct vnic_dev *vdev);
c7ffa4
+int vnic_dev_alloc_stats_mem(struct vnic_dev *vdev);
c7ffa4
 int vnic_dev_cmd_init(struct vnic_dev *vdev, int fallback);
c7ffa4
 int vnic_dev_get_size(void);
c7ffa4
 int vnic_dev_int13(struct vnic_dev *vdev, u64 arg, u32 op);
c7ffa4
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
c7ffa4
index c3796c543..235ef5940 100644
c7ffa4
--- a/drivers/net/enic/enic_main.c
c7ffa4
+++ b/drivers/net/enic/enic_main.c
c7ffa4
@@ -1478,6 +1478,15 @@ int enic_probe(struct enic *enic)
c7ffa4
 		enic_alloc_consistent,
c7ffa4
 		enic_free_consistent);
c7ffa4
 
c7ffa4
+	/*
c7ffa4
+	 * Allocate the consistent memory for stats upfront so both primary and
c7ffa4
+	 * secondary processes can dump stats.
c7ffa4
+	 */
c7ffa4
+	err = vnic_dev_alloc_stats_mem(enic->vdev);
c7ffa4
+	if (err) {
c7ffa4
+		dev_err(enic, "Failed to allocate cmd memory, aborting\n");
c7ffa4
+		goto err_out_unregister;
c7ffa4
+	}
c7ffa4
 	/* Issue device open to get device in known state */
c7ffa4
 	err = enic_dev_open(enic);
c7ffa4
 	if (err) {
c7ffa4
-- 
c7ffa4
2.14.3
c7ffa4