Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Jun 2002 10:48:38 +0900
From:      Kyunghwan Kim <redjade@atropos.snu.ac.kr>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/39977: Device polling support for em(4) driver
Message-ID:  <20020629104838.A6435@atropos.snu.ac.kr>

next in thread | raw e-mail | index | archive | help

>Number:         39977
>Category:       kern
>Synopsis:       Device polling support for em(4) driver
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jun 28 18:50:06 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Kyunghwan Kim
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
Web Data Bank, Inc.
>Environment:
System: FreeBSD genomy.wdb.co.kr 5.0-CURRENT FreeBSD 5.0-CURRENT #0: Tue Apr 9 15:40:58 KST 2002 root@genomy.wdb.co.kr:/usr/src/sys/i386/compile/GENOMY i386


>Description:
	Device polling support for em(4) driver.

>How-To-Repeat:
	nothing

>Fix:
	Don't mind the revision numbers, these are in local cvs.
	patch against -CURRENT today(20020629):

Index: if_em.c
===================================================================
RCS file: /data/cvs/em/if_em.c,v
retrieving revision 1.11
retrieving revision 1.11.2.1
diff -u -r1.11 -r1.11.2.1
--- if_em.c	2002/06/21 09:13:34	1.11
+++ if_em.c	2002/06/28 09:49:27	1.11.2.1
@@ -143,6 +143,9 @@
 static int  em_get_buf(struct em_rx_buffer *, struct adapter *,
 		       struct mbuf *);
 static void em_enable_vlans(struct adapter *adapter);
+#ifdef DEVICE_POLLING
+static poll_handler_t em_poll;
+#endif /* DEVICE_POLLING */
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points                    
@@ -631,6 +634,11 @@
 			em_set_multi(adapter);
 			if (adapter->hw.mac_type == em_82542_rev2_0)
 				em_initialize_receive_unit(adapter);
+#ifdef DEVICE_POLLING
+			if (ifp->if_ipending & IFF_POLLING)
+				break;
+			else
+#endif /* DEVICE_POLLING */
 			em_enable_intr(adapter);
 		}
 		break;
@@ -919,6 +927,11 @@
 
 	adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz);
 	em_clear_hw_cntrs(&adapter->hw);
+#ifdef DEVICE_POLLING
+	if (ifp->if_ipending & IFF_POLLING)
+		em_disable_intr(adapter);
+	else
+#endif /* DEVICE_POLLING */
 	em_enable_intr(adapter);
 
 	splx(s);
@@ -951,6 +964,9 @@
 	/* Tell the stack that the interface is no longer active */
 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 
+#ifdef DEVICE_POLLING
+	ether_poll_deregister(ifp);
+#endif /* DEVICE_POLLING */
 	return;
 }
 
@@ -970,6 +986,17 @@
 
 	ifp = &adapter->interface_data.ac_if;
 
+#ifdef DEVICE_POLLING
+	if (ifp->if_ipending & IFF_POLLING)
+		return;
+
+	if (ether_poll_register(em_poll, ifp)) {
+		em_disable_intr(adapter);
+		em_poll(ifp, 0, 1);
+		return;
+	}
+#endif /* DEVICE_POLLING */
+
 	em_disable_intr(adapter);
 	while (loop_cnt > 0 && 
 	       (reg_icr = E1000_READ_REG(&adapter->hw, ICR)) != 0) {
@@ -1892,6 +1919,13 @@
 	}
 
 	while (current_desc->status & E1000_RXD_STAT_DD) {
+#ifdef DEVICE_POLLING
+		if (ifp->if_ipending & IFF_POLLING) {
+			if (adapter->rxcycles <= 0)
+				break;
+			adapter->rxcycles--;
+		}
+#endif /* DEVICE_POLLING */
 
 		/* Get a pointer to the actual receive buffer */
 		rx_buffer = STAILQ_FIRST(&adapter->rx_buffer_list);
@@ -2366,3 +2400,45 @@
 	return;
 }
 
+#ifdef DEVICE_POLLING
+static void
+em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct adapter  *adapter = ifp->if_softc;
+	u_int32_t       loop_cnt = EM_MAX_INTR;
+	u_int32_t       reg_icr;
+
+	if (cmd == POLL_DEREGISTER) {
+		em_enable_intr(adapter);
+		return;
+	}
+
+	adapter->rxcycles = count;
+	em_process_receive_interrupts(adapter);
+	em_clean_transmit_interrupts(adapter);
+	if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
+		em_start(ifp);
+
+	if (cmd == POLL_AND_CHECK_STATUS) {
+		while (loop_cnt > 0 && (reg_icr = E1000_READ_REG(&adapter->hw,
+		    ICR)) != 0) {
+			/* Link status change */
+			if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+				untimeout(em_local_timer, adapter,
+				    adapter->timer_handle);
+				adapter->hw.get_link_status = 1;
+				em_check_for_link(&adapter->hw);
+				em_print_link_status(adapter);
+				adapter->timer_handle = timeout(em_local_timer,
+				    adapter, 2*hz);
+			}
+
+			if (ifp->if_flags & IFF_RUNNING) {
+				em_process_receive_interrupts(adapter);
+				em_clean_transmit_interrupts(adapter);
+			}
+			loop_cnt--;
+		}
+	}
+}
+#endif /* DEVICE_POLLING */
Index: if_em.h
===================================================================
RCS file: /data/cvs/em/if_em.h,v
retrieving revision 1.3
retrieving revision 1.3.2.1
diff -u -r1.3 -r1.3.2.1
--- if_em.h	2002/06/21 09:13:35	1.3
+++ if_em.h	2002/06/28 09:49:28	1.3.2.1
@@ -245,6 +245,9 @@
 #endif
 
 	struct em_hw_stats stats;
+#ifdef DEVICE_POLLING
+	int		rxcycles;
+#endif /* DEVICE_POLLING */
 };
 
 #endif                                                  /* _EM_H_DEFINED_ */

	and patch against -STABLE today(20020629):

Index: if_em.c
===================================================================
RCS file: /data/cvs/em/if_em.c,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.2.1.2.1
diff -u -r1.1.1.1.2.1 -r1.1.1.1.2.1.2.1
--- if_em.c	2002/06/19 08:28:59	1.1.1.1.2.1
+++ if_em.c	2002/06/28 09:16:36	1.1.1.1.2.1.2.1
@@ -143,6 +143,9 @@
 static int em_get_buf __P((struct em_rx_buffer *, struct adapter *,
 			   struct mbuf *));
 static void em_enable_vlans __P((struct adapter *adapter));
+#ifdef DEVICE_POLLING
+static poll_handler_t em_poll;
+#endif /* DEVICE_POLLING */
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points                    
@@ -631,6 +634,11 @@
 			em_set_multi(adapter);
 			if (adapter->hw.mac_type == em_82542_rev2_0)
 				em_initialize_receive_unit(adapter);
+#ifdef DEVICE_POLLING
+			if (ifp->if_ipending & IFF_POLLING)
+				break;
+			else
+#endif /* DEVICE_POLLING */
 			em_enable_intr(adapter);
 		}
 		break;
@@ -919,6 +927,11 @@
 
 	adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz);
 	em_clear_hw_cntrs(&adapter->hw);
+#ifdef DEVICE_POLLING
+	if (ifp->if_ipending & IFF_POLLING)
+		em_disable_intr(adapter);
+	else
+#endif /* DEVICE_POLLING */
 	em_enable_intr(adapter);
 
 	splx(s);
@@ -951,6 +964,10 @@
 	/* Tell the stack that the interface is no longer active */
 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
 
+#ifdef DEVICE_POLLING
+	ether_poll_deregister(ifp);
+#endif /* DEVICE_POLLING */
+
 	return;
 }
 
@@ -970,6 +987,17 @@
 
 	ifp = &adapter->interface_data.ac_if;
 
+#ifdef DEVICE_POLLING
+	if (ifp->if_ipending & IFF_POLLING)
+		return;
+
+	if (ether_poll_register(em_poll, ifp)) {
+		em_disable_intr(adapter);
+		em_poll(ifp, 0, 1);
+		return;
+	}
+#endif /* DEVICE_POLLING */
+
 	em_disable_intr(adapter);
 	while (loop_cnt > 0 && 
 	       (reg_icr = E1000_READ_REG(&adapter->hw, ICR)) != 0) {
@@ -1892,6 +1920,13 @@
 	}
 
 	while (current_desc->status & E1000_RXD_STAT_DD) {
+#ifdef DEVICE_POLLING
+		if (ifp->if_ipending & IFF_POLLING) {
+			if (adapter->rxcycles <= 0)
+				break;
+			adapter->rxcycles--;
+		}
+#endif /* DEVICE_POLLING */
 
 		/* Get a pointer to the actual receive buffer */
 		rx_buffer = STAILQ_FIRST(&adapter->rx_buffer_list);
@@ -2366,3 +2401,45 @@
 	return;
 }
 
+#ifdef DEVICE_POLLING
+static void
+em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct adapter	*adapter = ifp->if_softc;
+	u_int32_t	loop_cnt = EM_MAX_INTR;
+	u_int32_t	reg_icr;
+
+	if (cmd == POLL_DEREGISTER) {
+		em_enable_intr(adapter);
+		return;
+	}
+
+	adapter->rxcycles = count;
+	em_process_receive_interrupts(adapter);
+	em_clean_transmit_interrupts(adapter);
+	if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL)
+		em_start(ifp);
+
+	if (cmd == POLL_AND_CHECK_STATUS) {
+		while (loop_cnt > 0 && (reg_icr = E1000_READ_REG(&adapter->hw,
+		    ICR)) != 0) {
+			/* Link status change */
+			if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+				untimeout(em_local_timer, adapter,
+				    adapter->timer_handle);
+				adapter->hw.get_link_status = 1;
+				em_check_for_link(&adapter->hw);
+				em_print_link_status(adapter);
+				adapter->timer_handle = timeout(em_local_timer,
+				    adapter, 2*hz);
+			}
+
+			if (ifp->if_flags & IFF_RUNNING) {
+				em_process_receive_interrupts(adapter);
+				em_clean_transmit_interrupts(adapter);
+			}
+			loop_cnt--;
+		}
+	}
+}
+#endif /* DEVICE_POLLING */
Index: if_em.h
===================================================================
RCS file: /data/cvs/em/if_em.h,v
retrieving revision 1.1.1.1.2.1
retrieving revision 1.1.1.1.2.1.2.1
diff -u -r1.1.1.1.2.1 -r1.1.1.1.2.1.2.1
--- if_em.h	2002/06/19 08:29:00	1.1.1.1.2.1
+++ if_em.h	2002/06/28 09:16:37	1.1.1.1.2.1.2.1
@@ -245,6 +245,10 @@
 #endif
 
 	struct em_hw_stats stats;
+
+#ifdef DEVICE_POLLING
+	int		rxcycles;
+#endif /* DEVICE_POLLING */
 };
 
 #endif                                                  /* _EM_H_DEFINED_ */
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




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