MFC polling(4) for bge(4).

This commit is contained in:
glebius 2005-11-09 11:42:01 +00:00
parent 88bf054121
commit a01df0dc97
3 changed files with 115 additions and 3 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd October 1, 2005
.Dd October 22, 2005
.Dt POLLING 4
.Os
.Sh NAME
@ -177,6 +177,7 @@ Debugging variables.
.Sh SUPPORTED DEVICES
Device polling requires explicit modifications to the device drivers.
As of this writing, the
.Xr bge 4 ,
.Xr dc 4 ,
.Xr em 4 ,
.Xr fwe 4 ,

View File

@ -66,6 +66,10 @@ __FBSDID("$FreeBSD$");
* ring.
*/
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h"
#endif
#include <sys/param.h>
#include <sys/endian.h>
#include <sys/systm.h>
@ -263,6 +267,12 @@ static void bge_writereg_ind (struct bge_softc *, int, int);
static int bge_miibus_readreg (device_t, int, int);
static int bge_miibus_writereg (device_t, int, int, int);
static void bge_miibus_statchg (device_t);
#ifdef DEVICE_POLLING
static void bge_poll (struct ifnet *ifp, enum poll_cmd cmd,
int count);
static void bge_poll_locked (struct ifnet *ifp, enum poll_cmd cmd,
int count);
#endif
static void bge_reset (struct bge_softc *);
@ -2417,6 +2427,9 @@ bge_attach(dev)
ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING |
IFCAP_VLAN_MTU;
ifp->if_capenable = ifp->if_capabilities;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
/*
* Figure out what sort of media we have by checking the
@ -2517,6 +2530,11 @@ bge_detach(dev)
sc = device_get_softc(dev);
ifp = sc->bge_ifp;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING)
ether_poll_deregister(ifp);
#endif
BGE_LOCK(sc);
bge_stop(sc);
bge_reset(sc);
@ -2744,6 +2762,14 @@ bge_rxeof(sc)
u_int16_t vlan_tag = 0;
int have_tag = 0;
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
if (sc->rxcycles <= 0)
break;
sc->rxcycles--;
}
#endif
cur_rx =
&sc->bge_ldata.bge_rx_return_ring[sc->bge_rx_saved_considx];
@ -2901,6 +2927,41 @@ bge_txeof(sc)
return;
}
#ifdef DEVICE_POLLING
static void
bge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct bge_softc *sc = ifp->if_softc;
BGE_LOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
bge_poll_locked(ifp, cmd, count);
BGE_UNLOCK(sc);
}
static void
bge_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
{
struct bge_softc *sc = ifp->if_softc;
BGE_LOCK_ASSERT(sc);
sc->rxcycles = count;
bge_rxeof(sc);
bge_txeof(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
bge_start_locked(ifp);
if (cmd == POLL_AND_CHECK_STATUS) {
u_int32_t status;
status = CSR_READ_4(sc, BGE_MAC_STS);
if (status)
CSR_WRITE_4(sc, BGE_MAC_STS, status);
}
}
#endif /* DEVICE_POLLING */
static void
bge_intr(xsc)
void *xsc;
@ -2915,6 +2976,13 @@ bge_intr(xsc)
BGE_LOCK(sc);
#ifdef DEVICE_POLLING
if (ifp->if_capenable & IFCAP_POLLING) {
BGE_UNLOCK(sc);
return;
}
#endif
bus_dmamap_sync(sc->bge_cdata.bge_status_tag,
sc->bge_cdata.bge_status_map, BUS_DMASYNC_POSTWRITE);
@ -3412,11 +3480,24 @@ bge_init_locked(sc)
/* Tell firmware we're alive. */
BGE_SETBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
#ifdef DEVICE_POLLING
/* Disable interrupts if we are polling. */
if (ifp->if_capenable & IFCAP_POLLING) {
BGE_SETBIT(sc, BGE_PCI_MISC_CTL,
BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 1);
CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 1);
} else
#endif
/* Enable host interrupts. */
{
BGE_SETBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_CLEAR_INTA);
BGE_CLRBIT(sc, BGE_PCI_MISC_CTL, BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
}
bge_ifmedia_upd(ifp);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@ -3621,6 +3702,34 @@ bge_ioctl(ifp, command, data)
break;
case SIOCSIFCAP:
mask = ifr->ifr_reqcap ^ ifp->if_capenable;
#ifdef DEVICE_POLLING
if (mask & IFCAP_POLLING) {
if (ifr->ifr_reqcap & IFCAP_POLLING) {
error = ether_poll_register(bge_poll, ifp);
if (error)
return(error);
BGE_LOCK(sc);
BGE_SETBIT(sc, BGE_PCI_MISC_CTL,
BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 1);
CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 1);
CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 1);
ifp->if_capenable |= IFCAP_POLLING;
BGE_UNLOCK(sc);
} else {
error = ether_poll_deregister(ifp);
/* Enable interrupt even in error case */
BGE_LOCK(sc);
CSR_WRITE_4(sc, BGE_HCC_RX_MAX_COAL_BDS_INT, 0);
CSR_WRITE_4(sc, BGE_HCC_TX_MAX_COAL_BDS_INT, 0);
BGE_CLRBIT(sc, BGE_PCI_MISC_CTL,
BGE_PCIMISCCTL_MASK_PCI_INTR);
CSR_WRITE_4(sc, BGE_MBX_IRQ0_LO, 0);
ifp->if_capenable &= ~IFCAP_POLLING;
BGE_UNLOCK(sc);
}
}
#endif
/* NB: the code for RX csum offload is disabled for now */
if (mask & IFCAP_TXCSUM) {
ifp->if_capenable ^= IFCAP_TXCSUM;
@ -3629,7 +3738,6 @@ bge_ioctl(ifp, command, data)
else
ifp->if_hwassist = 0;
}
error = 0;
break;
default:
error = ether_ioctl(ifp, command, data);

View File

@ -2355,6 +2355,9 @@ struct bge_softc {
struct callout bge_stat_ch;
char *bge_vpd_prodname;
char *bge_vpd_readonly;
#ifdef DEVICE_POLLING
int rxcycles;
#endif /* DEVICE_POLLING */
};
#define BGE_LOCK_INIT(_sc, _name) \