Browse Source

Merge branch 'be2net'

Sathya Perla says:

====================
be2net: patch set

Patch 1/2 is a v2 of a patch that was submitted earlier (as a part of a
different patch-set). v2 incorporates a suggestion given by David Laight
for how long to poll for pending TX completions while disabling a device.

Patch 2/2 fixes a crash in be_remove()->be_close()
path after be2net has aborted an EEH error recovery
due to a permanant failure.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
David S. Miller 11 years ago
parent
commit
677df2f4ae

+ 1 - 0
drivers/net/ethernet/emulex/benet/be.h

@@ -374,6 +374,7 @@ enum vf_state {
 #define BE_FLAGS_NAPI_ENABLED			(1 << 9)
 #define BE_FLAGS_NAPI_ENABLED			(1 << 9)
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		(1 << 11)
 #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD		(1 << 11)
 #define BE_FLAGS_VXLAN_OFFLOADS			(1 << 12)
 #define BE_FLAGS_VXLAN_OFFLOADS			(1 << 12)
+#define BE_FLAGS_SETUP_DONE			(1 << 13)
 
 
 #define BE_UC_PMAC_COUNT			30
 #define BE_UC_PMAC_COUNT			30
 #define BE_VF_UC_PMAC_COUNT			2
 #define BE_VF_UC_PMAC_COUNT			2

+ 13 - 4
drivers/net/ethernet/emulex/benet/be_main.c

@@ -2033,11 +2033,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 	bool dummy_wrb;
 	bool dummy_wrb;
 	int i, pending_txqs;
 	int i, pending_txqs;
 
 
-	/* Wait for a max of 200ms for all the tx-completions to arrive. */
+	/* Stop polling for compls when HW has been silent for 10ms */
 	do {
 	do {
 		pending_txqs = adapter->num_tx_qs;
 		pending_txqs = adapter->num_tx_qs;
 
 
 		for_all_tx_queues(adapter, txo, i) {
 		for_all_tx_queues(adapter, txo, i) {
+			cmpl = 0;
+			num_wrbs = 0;
 			txq = &txo->q;
 			txq = &txo->q;
 			while ((txcp = be_tx_compl_get(&txo->cq))) {
 			while ((txcp = be_tx_compl_get(&txo->cq))) {
 				end_idx =
 				end_idx =
@@ -2050,14 +2052,13 @@ static void be_tx_compl_clean(struct be_adapter *adapter)
 			if (cmpl) {
 			if (cmpl) {
 				be_cq_notify(adapter, txo->cq.id, false, cmpl);
 				be_cq_notify(adapter, txo->cq.id, false, cmpl);
 				atomic_sub(num_wrbs, &txq->used);
 				atomic_sub(num_wrbs, &txq->used);
-				cmpl = 0;
-				num_wrbs = 0;
+				timeo = 0;
 			}
 			}
 			if (atomic_read(&txq->used) == 0)
 			if (atomic_read(&txq->used) == 0)
 				pending_txqs--;
 				pending_txqs--;
 		}
 		}
 
 
-		if (pending_txqs == 0 || ++timeo > 200)
+		if (pending_txqs == 0 || ++timeo > 10 || be_hw_error(adapter))
 			break;
 			break;
 
 
 		mdelay(1);
 		mdelay(1);
@@ -2725,6 +2726,12 @@ static int be_close(struct net_device *netdev)
 	struct be_eq_obj *eqo;
 	struct be_eq_obj *eqo;
 	int i;
 	int i;
 
 
+	/* This protection is needed as be_close() may be called even when the
+	 * adapter is in cleared state (after eeh perm failure)
+	 */
+	if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
+		return 0;
+
 	be_roce_dev_close(adapter);
 	be_roce_dev_close(adapter);
 
 
 	if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
 	if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3055,6 +3062,7 @@ static int be_clear(struct be_adapter *adapter)
 	be_clear_queues(adapter);
 	be_clear_queues(adapter);
 
 
 	be_msix_disable(adapter);
 	be_msix_disable(adapter);
+	adapter->flags &= ~BE_FLAGS_SETUP_DONE;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3559,6 +3567,7 @@ static int be_setup(struct be_adapter *adapter)
 		adapter->phy.fc_autoneg = 1;
 		adapter->phy.fc_autoneg = 1;
 
 
 	be_schedule_worker(adapter);
 	be_schedule_worker(adapter);
+	adapter->flags |= BE_FLAGS_SETUP_DONE;
 	return 0;
 	return 0;
 err:
 err:
 	be_clear(adapter);
 	be_clear(adapter);