Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Jun 2015 22:05:34 +0000 (UTC)
From:      Sean Bruno <sbruno@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r283932 - projects/em_mq/sys/dev/e1000
Message-ID:  <201506022205.t52M5YGt082391@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sbruno
Date: Tue Jun  2 22:05:33 2015
New Revision: 283932
URL: https://svnweb.freebsd.org/changeset/base/283932

Log:
  MFH @283923

Modified:
  projects/em_mq/sys/dev/e1000/if_em.c
  projects/em_mq/sys/dev/e1000/if_em.h
Directory Properties:
  projects/em_mq/   (props changed)
  projects/em_mq/sys/   (props changed)

Modified: projects/em_mq/sys/dev/e1000/if_em.c
==============================================================================
--- projects/em_mq/sys/dev/e1000/if_em.c	Tue Jun  2 21:36:45 2015	(r283931)
+++ projects/em_mq/sys/dev/e1000/if_em.c	Tue Jun  2 22:05:33 2015	(r283932)
@@ -1,6 +1,6 @@
 /******************************************************************************
 
-  Copyright (c) 2001-2014, Intel Corporation 
+  Copyright (c) 2001-2015, Intel Corporation 
   All rights reserved.
   
   Redistribution and use in source and binary forms, with or without 
@@ -961,12 +961,13 @@ em_start_locked(if_t ifp, struct tx_ring
 			break;
 		}
 
+		/* Mark the queue as having work */
+		if (txr->busy == EM_TX_IDLE)
+			txr->busy = EM_TX_BUSY;
+
 		/* Send a copy of the frame to the BPF listener */
 		ETHER_BPF_MTAP(ifp, m_head);
 
-		/* Set timeout in case hardware has problems transmitting. */
-		txr->watchdog_time = ticks;
-                txr->queue_status = EM_QUEUE_WORKING;
 	}
 
 	return;
@@ -1064,11 +1065,9 @@ em_mq_start_locked(if_t ifp, struct tx_r
                         break;
 	}
 
-	if (enq > 0) {
-                /* Set the watchdog */
-                txr->queue_status = EM_QUEUE_WORKING;
-		txr->watchdog_time = ticks;
-	}
+	/* Mark the queue as having work */
+	if ((enq > 0) && (txr->busy == EM_TX_IDLE))
+		txr->busy = EM_TX_BUSY;
 
 	if (txr->tx_avail < EM_MAX_SCATTER)
 		em_txeof(txr);
@@ -2155,8 +2154,6 @@ retry:
 	 */
 	tx_buffer = &txr->tx_buffers[first];
 	tx_buffer->next_eop = last;
-	/* Update the watchdog time early and often */
-	txr->watchdog_time = ticks;
 
 	/*
 	 * Advance the Transmit Descriptor Tail (TDT), this tells the E1000
@@ -2302,16 +2299,15 @@ em_local_timer(void *arg)
 	** and the HUNG state will be static if set.
 	*/
 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
-		if ((txr->queue_status == EM_QUEUE_HUNG) &&
-		    (adapter->pause_frames == 0)) {
+		if (txr->busy == EM_TX_HUNG)
 			goto hung;
-		}
+		if (txr->busy >= EM_TX_MAXTRIES)
+			txr->busy = EM_TX_HUNG;
 		/* Schedule a TX tasklet if needed */
 		if (txr->tx_avail <= EM_MAX_SCATTER)
 			taskqueue_enqueue(txr->tq, &txr->tx_task);
 	}
 	
-	adapter->pause_frames = 0;
 	callout_reset(&adapter->timer, hz, em_local_timer, adapter);
 #ifndef DEVICE_POLLING
 	/* Trigger an RX interrupt to guarantee mbuf refresh */
@@ -2325,7 +2321,6 @@ hung:
 	em_print_debug_info(adapter);
 	if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING);
 	adapter->watchdog_events++;
-	adapter->pause_frames = 0;
 	em_init_locked(adapter);
 }
 
@@ -2394,9 +2389,9 @@ em_update_link_status(struct adapter *ad
 		if (bootverbose)
 			device_printf(dev, "Link is Down\n");
 		adapter->link_active = 0;
-		/* Link down, disable watchdog */
+		/* Link down, disable hang detection */
 		for (int i = 0; i < adapter->num_queues; i++, txr++)
-			txr->queue_status = EM_QUEUE_IDLE;
+			txr->busy = EM_TX_IDLE;
 		if_link_state_change(ifp, LINK_STATE_DOWN);
 	}
 }
@@ -2427,10 +2422,10 @@ em_stop(void *arg)
 	/* Tell the stack that the interface is no longer active */
 	if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, IFF_DRV_RUNNING);
 
-        /* Unarm watchdog timer. */
+        /* Disarm Hang Detection. */
 	for (int i = 0; i < adapter->num_queues; i++, txr++) {
 		EM_TX_LOCK(txr);
-		txr->queue_status = EM_QUEUE_IDLE;
+		txr->busy = EM_TX_IDLE;
 		EM_TX_UNLOCK(txr);
 	}
 
@@ -3449,7 +3444,7 @@ em_setup_transmit_ring(struct tx_ring *t
 
 	/* Set number of descriptors available */
 	txr->tx_avail = adapter->num_tx_desc;
-	txr->queue_status = EM_QUEUE_IDLE;
+	txr->busy = EM_TX_IDLE;
 
 	/* Clear checksum offload context. */
 	txr->last_hw_offload = 0;
@@ -3510,7 +3505,7 @@ em_initialize_transmit_unit(struct adapt
 		    E1000_READ_REG(&adapter->hw, E1000_TDBAL(i)),
 		    E1000_READ_REG(&adapter->hw, E1000_TDLEN(i)));
 
-		txr->queue_status = EM_QUEUE_IDLE;
+		txr->busy = EM_TX_IDLE;
 		txdctl = 0; /* clear txdctl */
                 txdctl |= 0x1f; /* PTHRESH */
                 txdctl |= 1 << 8; /* HTHRESH */
@@ -3912,9 +3907,9 @@ em_txeof(struct tx_ring *txr)
 		return;
 #endif /* DEV_NETMAP */
 
-	/* No work, make sure watchdog is off */
+	/* No work, make sure hang detection is disabled */
         if (txr->tx_avail == adapter->num_tx_desc) {
-		txr->queue_status = EM_QUEUE_IDLE;
+		txr->busy = EM_TX_IDLE;
                 return;
 	}
 
@@ -3957,7 +3952,6 @@ em_txeof(struct tx_ring *txr)
                         	tx_buffer->m_head = NULL;
                 	}
 			tx_buffer->next_eop = -1;
-			txr->watchdog_time = ticks;
 
 	                if (++first == adapter->num_tx_desc)
 				first = 0;
@@ -3982,14 +3976,16 @@ em_txeof(struct tx_ring *txr)
         txr->next_to_clean = first;
 
 	/*
-	** Watchdog calculation, we know there's
-	** work outstanding or the first return
-	** would have been taken, so none processed
-	** for too long indicates a hang. local timer
-	** will examine this and do a reset if needed.
+	** Hang detection: we know there's work outstanding
+	** or the entry return would have been taken, so no
+	** descriptor processed here indicates a potential hang.
+	** The local timer will examine this and do a reset if needed.
 	*/
-	if ((!processed) && ((ticks - txr->watchdog_time) > EM_WATCHDOG))
-		txr->queue_status = EM_QUEUE_HUNG;
+	if (processed == 0) {
+		if (txr->busy != EM_TX_HUNG)
+			++txr->busy;
+	} else /* At least one descriptor was cleaned */
+		txr->busy = EM_TX_BUSY; /* note this clears HUNG */
 
         /*
          * If we have a minimum free, clear IFF_DRV_OACTIVE
@@ -4002,10 +3998,9 @@ em_txeof(struct tx_ring *txr)
 		if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
 	}
 
-	/* Disable watchdog if all clean */
-	if (txr->tx_avail == adapter->num_tx_desc) {
-		txr->queue_status = EM_QUEUE_IDLE;
-	} 
+	/* Disable hang detection if all clean */
+	if (txr->tx_avail == adapter->num_tx_desc)
+		txr->busy = EM_TX_IDLE;
 }
 
 
@@ -5312,12 +5307,7 @@ em_update_stats_counters(struct adapter 
 	adapter->stats.rlec += E1000_READ_REG(&adapter->hw, E1000_RLEC);
 	adapter->stats.xonrxc += E1000_READ_REG(&adapter->hw, E1000_XONRXC);
 	adapter->stats.xontxc += E1000_READ_REG(&adapter->hw, E1000_XONTXC);
-	/*
-	** For watchdog management we need to know if we have been
-	** paused during the last interval, so capture that here.
-	*/
-	adapter->pause_frames = E1000_READ_REG(&adapter->hw, E1000_XOFFRXC);
-	adapter->stats.xoffrxc += adapter->pause_frames;
+	adapter->stats.xoffrxc += E1000_READ_REG(&adapter->hw, E1000_XOFFRXC);
 	adapter->stats.xofftxc += E1000_READ_REG(&adapter->hw, E1000_XOFFTXC);
 	adapter->stats.fcruc += E1000_READ_REG(&adapter->hw, E1000_FCRUC);
 	adapter->stats.prc64 += E1000_READ_REG(&adapter->hw, E1000_PRC64);
@@ -5948,7 +5938,7 @@ em_print_debug_info(struct adapter *adap
 		device_printf(dev, "hw tdh = %d, hw tdt = %d\n",
 	    		E1000_READ_REG(&adapter->hw, E1000_TDH(i)),
 	    		E1000_READ_REG(&adapter->hw, E1000_TDT(i)));
-		device_printf(dev, "Tx Queue Status = %d\n", txr->queue_status);
+		device_printf(dev, "Tx Queue Status = %d\n", txr->busy);
 		device_printf(dev, "TX descriptors avail = %d\n",
 	    		txr->tx_avail);
 		device_printf(dev, "Tx Descriptors avail failure = %ld\n",

Modified: projects/em_mq/sys/dev/e1000/if_em.h
==============================================================================
--- projects/em_mq/sys/dev/e1000/if_em.h	Tue Jun  2 21:36:45 2015	(r283931)
+++ projects/em_mq/sys/dev/e1000/if_em.h	Tue Jun  2 22:05:33 2015	(r283932)
@@ -204,9 +204,19 @@
 #define EM_EEPROM_APME			0x400;
 #define EM_82544_APME			0x0004;
 
-#define EM_QUEUE_IDLE			0
-#define EM_QUEUE_WORKING		1
-#define EM_QUEUE_HUNG			2
+/*
+ * Driver state logic for the detection of a hung state
+ * in hardware.  Set TX_HUNG whenever a TX packet is used
+ * (data is sent) and clear it when txeof() is invoked if
+ * any descriptors from the ring are cleaned/reclaimed.
+ * Increment internal counter if no descriptors are cleaned
+ * and compare to TX_MAXTRIES.  When counter > TX_MAXTRIES,
+ * reset adapter.
+ */
+#define EM_TX_IDLE			0x00000000
+#define EM_TX_BUSY			0x00000001
+#define EM_TX_HUNG			0x80000000
+#define EM_TX_MAXTRIES			10
 
 /*
  * TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
@@ -313,8 +323,7 @@ struct tx_ring {
         u32                     me;
         u32                     msix;
 	u32			ims;
-        int			queue_status;
-        int                     watchdog_time;
+        int			busy;
 	struct em_dma_alloc	txdma;
 	struct e1000_tx_desc	*tx_base;
         struct task             tx_task;
@@ -400,7 +409,6 @@ struct adapter {
 	int		if_flags;
 	int		max_frame_size;
 	int		min_frame_size;
-	int		pause_frames;
 	struct mtx	core_mtx;
 	int		em_insert_vlan_header;
 	u32		ims;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506022205.t52M5YGt082391>