Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 17 Apr 2006 10:28:03 +0400
From:      Andrew Belashov <bel@orel.ru>
To:        sparc64@freebsd.org
Subject:   Call for testers, hme(4) device polling patch
Message-ID:  <44433573.70702@orel.ru>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------070306050507010000060006
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

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.

--------------070306050507010000060006
Content-Type: text/plain;
 name="hme_polling.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="hme_polling.patch"

--- 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)

--------------070306050507010000060006--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?44433573.70702>