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.
This commit is contained in:
Jack F Vogel 2010-02-01 19:28:43 +00:00
parent 7432531341
commit 29e1e1a3a7
2 changed files with 116 additions and 3 deletions

View File

@ -35,6 +35,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS #ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h" #include "opt_device_polling.h"
#include "opt_inet.h" #include "opt_inet.h"
#include "opt_altq.h"
#endif #endif
#include <sys/param.h> #include <sys/param.h>
@ -1545,13 +1546,13 @@ em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
if (cmd == POLL_AND_CHECK_STATUS) { if (cmd == POLL_AND_CHECK_STATUS) {
reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR); reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
callout_stop(&adapter->timer);
adapter->hw.mac.get_link_status = 1; adapter->hw.mac.get_link_status = 1;
em_update_link_status(adapter); 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); EM_CORE_UNLOCK(adapter);

View File

@ -36,6 +36,7 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS #ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h" #include "opt_device_polling.h"
#include "opt_inet.h" #include "opt_inet.h"
#include "opt_altq.h"
#endif #endif
#include <sys/param.h> #include <sys/param.h>
@ -250,6 +251,10 @@ static void igb_handle_link(void *context, int pending);
static void igb_msix_que(void *); static void igb_msix_que(void *);
static void igb_msix_link(void *); static void igb_msix_link(void *);
#ifdef DEVICE_POLLING
static poll_handler_t igb_poll;
#endif /* POLLING */
/********************************************************************* /*********************************************************************
* FreeBSD Device Interface Entry Points * FreeBSD Device Interface Entry Points
*********************************************************************/ *********************************************************************/
@ -624,6 +629,11 @@ igb_detach(device_t dev)
return (EBUSY); return (EBUSY);
} }
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
ether_poll_deregister(ifp);
#endif
IGB_CORE_LOCK(adapter); IGB_CORE_LOCK(adapter);
adapter->in_detach = 1; adapter->in_detach = 1;
igb_stop(adapter); igb_stop(adapter);
@ -974,6 +984,9 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
IGB_CORE_LOCK(adapter); IGB_CORE_LOCK(adapter);
igb_disable_intr(adapter); igb_disable_intr(adapter);
igb_set_multi(adapter); igb_set_multi(adapter);
#ifdef DEVICE_POLLING
if (!(ifp->if_capenable & IFCAP_POLLING))
#endif
igb_enable_intr(adapter); igb_enable_intr(adapter);
IGB_CORE_UNLOCK(adapter); IGB_CORE_UNLOCK(adapter);
} }
@ -1000,6 +1013,26 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)"); IOCTL_DEBUGOUT("ioctl rcv'd: SIOCSIFCAP (Set Capabilities)");
reinit = 0; reinit = 0;
mask = ifr->ifr_reqcap ^ ifp->if_capenable; 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) { if (mask & IFCAP_HWCSUM) {
ifp->if_capenable ^= IFCAP_HWCSUM; ifp->if_capenable ^= IFCAP_HWCSUM;
reinit = 1; reinit = 1;
@ -1123,8 +1156,19 @@ igb_init_locked(struct adapter *adapter)
/* this clears any pending interrupts */ /* this clears any pending interrupts */
E1000_READ_REG(&adapter->hw, E1000_ICR); 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); igb_enable_intr(adapter);
E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC); E1000_WRITE_REG(&adapter->hw, E1000_ICS, E1000_ICS_LSC);
}
/* Don't reset the phy next time init gets called */ /* Don't reset the phy next time init gets called */
adapter->hw.phy.reset_disable = TRUE; adapter->hw.phy.reset_disable = TRUE;
@ -1201,6 +1245,9 @@ igb_handle_que(void *context, int pending)
} }
/* Reenable this interrupt */ /* Reenable this interrupt */
#ifdef DEVICE_POLLING
if (!(ifp->if_capenable & IFCAP_POLLING))
#endif
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims); E1000_WRITE_REG(&adapter->hw, E1000_EIMS, que->eims);
} }
@ -1257,6 +1304,63 @@ igb_irq_fast(void *arg)
return FILTER_HANDLED; 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 */ /* 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); E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->rx_mask);
callout_reset(&adapter->timer, hz, igb_local_timer, adapter); callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
return; return;
@ -2544,6 +2651,9 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities |= IFCAP_LRO; ifp->if_capabilities |= IFCAP_LRO;
ifp->if_capenable = ifp->if_capabilities; ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
/* /*
* Tell the upper layer(s) we support long frames. * Tell the upper layer(s) we support long frames.
@ -2808,7 +2918,9 @@ err_tx_desc:
igb_dma_free(adapter, &txr->txdma); igb_dma_free(adapter, &txr->txdma);
free(adapter->rx_rings, M_DEVBUF); free(adapter->rx_rings, M_DEVBUF);
rx_fail: rx_fail:
#if __FreeBSD_version >= 800000
buf_ring_free(txr->br, M_DEVBUF); buf_ring_free(txr->br, M_DEVBUF);
#endif
free(adapter->tx_rings, M_DEVBUF); free(adapter->tx_rings, M_DEVBUF);
tx_fail: tx_fail:
free(adapter->queues, M_DEVBUF); free(adapter->queues, M_DEVBUF);