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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to