svn commit: r203354 - head/sys/dev/e1000

Jack F Vogel jfv at FreeBSD.org
Mon Feb 1 19:28:44 UTC 2010


Author: jfv
Date: Mon Feb  1 19:28:43 2010
New Revision: 203354
URL: http://svn.freebsd.org/changeset/base/203354

Log:
  A few minor changes:  add altq option header, add missing conditional
  around a buf_ring call that will break 7.3, and thanks to Fabien Thomas
  add POLLING support for igb and a minor related fix in the em driver.

Modified:
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_igb.c

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c	Mon Feb  1 18:27:19 2010	(r203353)
+++ head/sys/dev/e1000/if_em.c	Mon Feb  1 19:28:43 2010	(r203354)
@@ -35,6 +35,7 @@
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_device_polling.h"
 #include "opt_inet.h"
+#include "opt_altq.h"
 #endif
 
 #include <sys/param.h>
@@ -1545,13 +1546,13 @@ em_poll(struct ifnet *ifp, enum poll_cmd
 
 	if (cmd == POLL_AND_CHECK_STATUS) {
 		reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+		/* Link status change */
 		if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
-			callout_stop(&adapter->timer);
 			adapter->hw.mac.get_link_status = 1;
 			em_update_link_status(adapter);
-			callout_reset(&adapter->timer, hz,
-			    em_local_timer, adapter);
 		}
+		if (reg_icr & E1000_ICR_RXO)
+			adapter->rx_overruns++;
 	}
 	EM_CORE_UNLOCK(adapter);
 

Modified: head/sys/dev/e1000/if_igb.c
==============================================================================
--- head/sys/dev/e1000/if_igb.c	Mon Feb  1 18:27:19 2010	(r203353)
+++ head/sys/dev/e1000/if_igb.c	Mon Feb  1 19:28:43 2010	(r203354)
@@ -36,6 +36,7 @@
 #ifdef HAVE_KERNEL_OPTION_HEADERS
 #include "opt_device_polling.h"
 #include "opt_inet.h"
+#include "opt_altq.h"
 #endif
 
 #include <sys/param.h>
@@ -250,6 +251,10 @@ static void	igb_handle_link(void *contex
 static void	igb_msix_que(void *);
 static void	igb_msix_link(void *);
 
+#ifdef DEVICE_POLLING
+static poll_handler_t igb_poll;
+#endif /* POLLING */
+
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
  *********************************************************************/
@@ -624,6 +629,11 @@ igb_detach(device_t dev)
 		return (EBUSY);
 	}
 
+#ifdef DEVICE_POLLING
+	if (ifp->if_capenable & IFCAP_POLLING)
+		ether_poll_deregister(ifp);
+#endif
+
 	IGB_CORE_LOCK(adapter);
 	adapter->in_detach = 1;
 	igb_stop(adapter);
@@ -974,6 +984,9 @@ igb_ioctl(struct ifnet *ifp, u_long comm
 			IGB_CORE_LOCK(adapter);
 			igb_disable_intr(adapter);
 			igb_set_multi(adapter);
+#ifdef DEVICE_POLLING
+			if (!(ifp->if_capenable & IFCAP_POLLING))
+#endif
 				igb_enable_intr(adapter);
 			IGB_CORE_UNLOCK(adapter);
 		}
@@ -1000,6 +1013,26 @@ igb_ioctl(struct ifnet *ifp, u_long comm
 		IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
 		reinit = 0;
 		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
+#ifdef DEVICE_POLLING
+		if (mask & IFCAP_POLLING) {
+			if (ifr->ifr_reqcap & IFCAP_POLLING) {
+				error = ether_poll_register(igb_poll, ifp);
+				if (error)
+					return (error);
+				IGB_CORE_LOCK(adapter);
+				igb_disable_intr(adapter);
+				ifp->if_capenable |= IFCAP_POLLING;
+				IGB_CORE_UNLOCK(adapter);
+			} else {
+				error = ether_poll_deregister(ifp);
+				/* Enable interrupt even in error case */
+				IGB_CORE_LOCK(adapter);
+				igb_enable_intr(adapter);
+				ifp->if_capenable &= ~IFCAP_POLLING;
+				IGB_CORE_UNLOCK(adapter);
+			}
+		}
+#endif
 		if (mask & IFCAP_HWCSUM) {
 			ifp->if_capenable ^= IFCAP_HWCSUM;
 			reinit = 1;
@@ -1123,8 +1156,19 @@ igb_init_locked(struct adapter *adapter)
 
 	/* this clears any pending interrupts */
 	E1000_READ_REG(&adapter->hw, E1000_ICR);
+#ifdef DEVICE_POLLING
+	/*
+	 * Only enable interrupts if we are not polling, make sure
+	 * they are off otherwise.
+	 */
+	if (ifp->if_capenable & IFCAP_POLLING)
+		igb_disable_intr(adapter);
+	else
+#endif /* DEVICE_POLLING */
+	{
 	igb_enable_intr(adapter);
 	E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
+	}
 
 	/* Don't reset the phy next time init gets called */
 	adapter->hw.phy.reset_disable = TRUE;
@@ -1201,6 +1245,9 @@ igb_handle_que(void *context, int pendin
 	}
 
 	/* Reenable this interrupt */
+#ifdef DEVICE_POLLING
+	if (!(ifp->if_capenable & IFCAP_POLLING))
+#endif
 	E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
 }
 
@@ -1257,6 +1304,63 @@ igb_irq_fast(void *arg)
 	return FILTER_HANDLED;
 }
 
+#ifdef DEVICE_POLLING
+/*********************************************************************
+ *
+ *  Legacy polling routine  
+ *
+ *********************************************************************/
+#if __FreeBSD_version >= 800000
+#define POLL_RETURN_COUNT(a) (a)
+static int
+#else
+#define POLL_RETURN_COUNT(a)
+static void
+#endif
+igb_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct adapter *adapter = ifp->if_softc;
+	struct rx_ring	*rxr = adapter->rx_rings;
+	struct tx_ring	*txr = adapter->tx_rings;
+	u32		reg_icr, rx_done = 0;
+	u32		loop = IGB_MAX_LOOP;
+	bool		more;
+
+	IGB_CORE_LOCK(adapter);
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+		IGB_CORE_UNLOCK(adapter);
+		return POLL_RETURN_COUNT(rx_done);
+	}
+
+	if (cmd == POLL_AND_CHECK_STATUS) {
+		reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+		/* Link status change */
+		if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))
+			taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+		if (reg_icr & E1000_ICR_RXO)
+			adapter->rx_overruns++;
+	}
+	IGB_CORE_UNLOCK(adapter);
+
+	/* TODO: rx_count */
+	rx_done = igb_rxeof(rxr, count) ? 1 : 0;
+
+	IGB_TX_LOCK(txr);
+	do {
+		more = igb_txeof(txr);
+	} while (loop-- && more);
+#if __FreeBSD_version >= 800000
+	if (!drbr_empty(ifp, txr->br))
+		igb_mq_start_locked(ifp, txr, NULL);
+#else
+	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+		igb_start_locked(txr, ifp);
+#endif
+	IGB_TX_UNLOCK(txr);
+	return POLL_RETURN_COUNT(rx_done);
+}
+#endif /* DEVICE_POLLING */
 
 /*********************************************************************
  *
@@ -1783,6 +1887,9 @@ igb_local_timer(void *arg)
 	}
 
 	/* Trigger an RX interrupt on all queues */
+#ifdef DEVICE_POLLING
+	if (!(ifp->if_capenable & IFCAP_POLLING))
+#endif
 	E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->rx_mask);
 	callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
 	return;
@@ -2544,6 +2651,9 @@ igb_setup_interface(device_t dev, struct
 		ifp->if_capabilities |= IFCAP_LRO;
 
 	ifp->if_capenable = ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+	ifp->if_capabilities |= IFCAP_POLLING;
+#endif
 
 	/*
 	 * Tell the upper layer(s) we support long frames.
@@ -2808,7 +2918,9 @@ err_tx_desc:
 		igb_dma_free(adapter, &txr->txdma);
 	free(adapter->rx_rings, M_DEVBUF);
 rx_fail:
+#if __FreeBSD_version >= 800000
 	buf_ring_free(txr->br, M_DEVBUF);
+#endif
 	free(adapter->tx_rings, M_DEVBUF);
 tx_fail:
 	free(adapter->queues, M_DEVBUF);


More information about the svn-src-head mailing list