Call for testers, hme(4) device polling patch
Andrew Belashov
bel at orel.ru
Mon Apr 17 06:28:10 UTC 2006
There is a patch that needs extensive testing which adds device polling
support in hme(4) driver. The patch was tested on U60(two CPUs) and had
no problems. If you encounter a panic related with the patch, please
let me know.(Don't forget to send your 'backtrace' output.)
--
With Best Regards,
Andrew Belashov.
-------------- next part --------------
--- sys/dev/hme/if_hme.c.orig Wed Mar 29 21:09:12 2006
+++ sys/dev/hme/if_hme.c Fri Apr 14 08:36:49 2006
@@ -61,9 +61,21 @@ __FBSDID("$FreeBSD: src/sys/dev/hme/if_h
* can be reactivated by setting special link option link0 with ifconfig(8).
*/
#define HME_CSUM_FEATURES (CSUM_TCP)
+#define HME_SEB_STAT_IMASK ( \
+ ~(/*HME_SEB_STAT_GOTFRAME | HME_SEB_STAT_SENTFRAME |*/ \
+ HME_SEB_STAT_HOSTTOTX | \
+ HME_SEB_STAT_RXTOHOST | \
+ HME_SEB_STAT_TXALL | \
+ HME_SEB_STAT_TXPERR | \
+ HME_SEB_STAT_RCNTEXP | \
+ HME_SEB_STAT_ALL_ERRORS ))
#define HMEDEBUG
#define KTR_HME KTR_CT2 /* XXX */
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -113,6 +125,10 @@ static int hme_mac_bitflip(struct hme_so
u_int32_t, u_int32_t);
static void hme_mifinit(struct hme_softc *);
static void hme_setladrf(struct hme_softc *, int);
+#ifdef DEVICE_POLLING
+static void hme_poll(struct ifnet *ifp, enum poll_cmd cmd, int count);
+static void hme_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count);
+#endif
static int hme_mediachange(struct ifnet *);
static void hme_mediastatus(struct ifnet *, struct ifmediareq *);
@@ -341,8 +357,11 @@ hme_config(struct hme_softc *sc)
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM;
+ ifp->if_capenable |= ifp->if_capabilities;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif
ifp->if_hwassist |= sc->sc_csum_features;
- ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM;
return (0);
fail_txdesc:
@@ -378,6 +397,10 @@ hme_detach(struct hme_softc *sc)
struct ifnet *ifp = sc->sc_ifp;
int i;
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING)
+ ether_poll_deregister(ifp);
+#endif
HME_LOCK(sc);
hme_stop(sc);
HME_UNLOCK(sc);
@@ -756,14 +779,13 @@ hme_init_locked(struct hme_softc *sc)
HME_MAC_WRITE_4(sc, HME_MACI_RXSIZE, HME_MAX_FRAMESIZE);
/* step 8. Global Configuration & Interrupt Mask */
- HME_SEB_WRITE_4(sc, HME_SEBI_IMASK,
- ~(/*HME_SEB_STAT_GOTFRAME | HME_SEB_STAT_SENTFRAME |*/
- HME_SEB_STAT_HOSTTOTX |
- HME_SEB_STAT_RXTOHOST |
- HME_SEB_STAT_TXALL |
- HME_SEB_STAT_TXPERR |
- HME_SEB_STAT_RCNTEXP |
- HME_SEB_STAT_ALL_ERRORS ));
+#ifdef DEVICE_POLLING
+ /* Disable interrupts if we are polling. */
+ if (ifp->if_capenable & IFCAP_POLLING)
+ HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, 0xffffffff);
+ else
+#endif
+ HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, HME_SEB_STAT_IMASK);
switch (sc->sc_burst) {
default:
@@ -1267,6 +1289,14 @@ hme_rint(struct hme_softc *sc)
if ((flags & HME_XD_OWN) != 0)
break;
+#ifdef DEVICE_POLLING
+ if (ifp->if_capenable & IFCAP_POLLING) {
+ if (sc->rxcycles <= 0)
+ break;
+ sc->rxcycles--;
+ }
+#endif
+
progress++;
if ((flags & HME_XD_OFL) != 0) {
device_printf(sc->sc_dev, "buffer overflow, ri=%d; "
@@ -1301,6 +1331,46 @@ hme_eint(struct hme_softc *sc, u_int sta
}
}
+#ifdef DEVICE_POLLING
+static void
+hme_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct hme_softc *sc = ifp->if_softc;
+
+ HME_LOCK(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ hme_poll_locked(ifp, cmd, count);
+ HME_UNLOCK(sc);
+}
+
+static void
+hme_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct hme_softc *sc = ifp->if_softc;
+ u_int32_t status;
+
+ HME_LOCK_ASSERT(sc, MA_OWNED);
+
+ sc->rxcycles = count;
+
+ status = HME_SEB_READ_4(sc, HME_SEBI_STAT);
+ CTR1(KTR_HME, "hme_poll: status %#x", (u_int)status);
+
+ if (cmd == POLL_AND_CHECK_STATUS &&
+ (status & HME_SEB_STAT_ALL_ERRORS) != 0)
+ hme_eint(sc, status);
+
+ if ((status & HME_SEB_STAT_RXTOHOST) != 0)
+ hme_rint(sc);
+
+ if ((status & (HME_SEB_STAT_TXALL | HME_SEB_STAT_HOSTTOTX)) != 0)
+ hme_tint(sc);
+
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ hme_start_locked(ifp);
+}
+#endif /* DEVICE_POLLING */
+
void
hme_intr(void *v)
{
@@ -1308,6 +1378,12 @@ hme_intr(void *v)
u_int32_t status;
HME_LOCK(sc);
+
+#ifdef DEVICE_POLLING
+ if (sc->sc_ifp->if_capenable & IFCAP_POLLING)
+ goto done_locked;
+#endif
+
status = HME_SEB_READ_4(sc, HME_SEBI_STAT);
CTR1(KTR_HME, "hme_intr: status %#x", (u_int)status);
@@ -1319,6 +1395,10 @@ hme_intr(void *v)
if ((status & HME_SEB_STAT_RXTOHOST) != 0)
hme_rint(sc);
+
+#ifdef DEVICE_POLLING
+done_locked:
+#endif
HME_UNLOCK(sc);
}
@@ -1555,12 +1635,39 @@ hme_ioctl(struct ifnet *ifp, u_long cmd,
break;
case SIOCSIFCAP:
HME_LOCK(sc);
- ifp->if_capenable = ifr->ifr_reqcap;
- if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
+ if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) {
ifp->if_hwassist = sc->sc_csum_features;
- else
+ ifp->if_capenable |= IFCAP_TXCSUM;
+ } else {
ifp->if_hwassist = 0;
+ ifp->if_capenable &= ~IFCAP_TXCSUM;
+ }
HME_UNLOCK(sc);
+#ifdef DEVICE_POLLING
+ if (ifr->ifr_reqcap & IFCAP_POLLING &&
+ !(ifp->if_capenable & IFCAP_POLLING)) {
+ error = ether_poll_register(hme_poll, ifp);
+ if (error)
+ return(error);
+ HME_LOCK(sc);
+ /* Disable interrupts */
+ HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, 0xffffffff);
+ ifp->if_capenable |= IFCAP_POLLING;
+ HME_UNLOCK(sc);
+ return (error);
+
+ }
+ if (!(ifr->ifr_reqcap & IFCAP_POLLING) &&
+ ifp->if_capenable & IFCAP_POLLING) {
+ error = ether_poll_deregister(ifp);
+ /* Enable interrupts. */
+ HME_LOCK(sc);
+ HME_SEB_WRITE_4(sc, HME_SEBI_IMASK, HME_SEB_STAT_IMASK);
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ HME_UNLOCK(sc);
+ return (error);
+ }
+#endif /* DEVICE_POLLING */
break;
default:
error = ether_ioctl(ifp, cmd, data);
--- sys/dev/hme/if_hmevar.h.orig Wed Mar 29 21:09:12 2006
+++ sys/dev/hme/if_hmevar.h Thu Apr 13 08:46:19 2006
@@ -144,6 +144,9 @@ struct hme_softc {
int sc_debug;
struct mtx sc_lock;
+#ifdef DEVICE_POLLING
+ int rxcycles;
+#endif
};
#define HME_LOCK(_sc) mtx_lock(&(_sc)->sc_lock)
More information about the freebsd-sparc64
mailing list