Blob Blame History Raw
From: Alexander Duyck <alexander.h.duyck@intel.com>
Date: Mon, 19 Mar 2018 09:28:03 -0700
Subject: i40evf: Reorder configure_clsflower to avoid deadlock on error
Patch-mainline: v4.17-rc1
Git-commit: 640a8af5841fd66a26e26f5b9fb5476a3755852a
References: bsc#1111981 FATE#326312 FATE#326313

While doing some code review I noticed that we can get into a state where
we exit with the "IN_CRITICAL_TASK" bit set while notifying the PF of
flower filters. This patch is meant to address that plus tweak the ordering
of the while loop waiting on it slightly so that we don't wait an extra
period after we have failed for the last time.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/net/ethernet/intel/i40evf/i40evf_main.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -2790,14 +2790,7 @@ static int i40evf_configure_clsflower(st
 {
 	int tc = tc_classid_to_hwtc(adapter->netdev, cls_flower->classid);
 	struct i40evf_cloud_filter *filter = NULL;
-	int err = 0, count = 50;
-
-	while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
-				&adapter->crit_section)) {
-		udelay(1);
-		if (--count == 0)
-			return -EINVAL;
-	}
+	int err = -EINVAL, count = 50;
 
 	if (tc < 0) {
 		dev_err(&adapter->pdev->dev, "Invalid traffic class\n");
@@ -2805,10 +2798,16 @@ static int i40evf_configure_clsflower(st
 	}
 
 	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
-	if (!filter) {
-		err = -ENOMEM;
-		goto clearout;
+	if (!filter)
+		return -ENOMEM;
+
+	while (test_and_set_bit(__I40EVF_IN_CRITICAL_TASK,
+				&adapter->crit_section)) {
+		if (--count == 0)
+			goto err;
+		udelay(1);
 	}
+
 	filter->cookie = cls_flower->cookie;
 
 	/* set the mask to all zeroes to begin with */
@@ -2833,7 +2832,7 @@ static int i40evf_configure_clsflower(st
 err:
 	if (err)
 		kfree(filter);
-clearout:
+
 	clear_bit(__I40EVF_IN_CRITICAL_TASK, &adapter->crit_section);
 	return err;
 }