Introduce polling(4) capability for bge(4).

Submitted by:	Oleg Bulyzhin <oleg rinet.ru>
This commit is contained in:
Gleb Smirnoff 2005-10-22 14:31:01 +00:00
parent bf148c3eaf
commit 7571918432
2 changed files with 113 additions and 2 deletions

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>
@ -265,6 +269,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 *);
@ -2421,6 +2431,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
@ -2521,6 +2534,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);
@ -2748,6 +2766,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];
@ -2905,6 +2931,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;
@ -2919,6 +2980,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);
@ -3416,11 +3484,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;
@ -3625,6 +3706,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;
@ -3633,7 +3742,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) \