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>
