diff options
author | luigi <luigi@FreeBSD.org> | 2002-11-25 19:56:16 +0000 |
---|---|---|
committer | luigi <luigi@FreeBSD.org> | 2002-11-25 19:56:16 +0000 |
commit | a7a6eb6da6c7003000f09cf3bd4c91023aef8154 (patch) | |
tree | 26f0bcfb8a1f1a78677a6141c89fe6f2bb51e22c /sys/dev/em/if_em.c | |
parent | c8bb4761073b63c552907a7725638fa86a221a27 (diff) | |
download | FreeBSD-src-a7a6eb6da6c7003000f09cf3bd4c91023aef8154.zip FreeBSD-src-a7a6eb6da6c7003000f09cf3bd4c91023aef8154.tar.gz |
Add polling support to the "em" driver.
Reviewed by: pdeuskar (maintainer)
Approved by: re
Diffstat (limited to 'sys/dev/em/if_em.c')
-rw-r--r-- | sys/dev/em/if_em.c | 63 |
1 files changed, 59 insertions, 4 deletions
diff --git a/sys/dev/em/if_em.c b/sys/dev/em/if_em.c index ecbea9a..146d44f 100644 --- a/sys/dev/em/if_em.c +++ b/sys/dev/em/if_em.c @@ -127,7 +127,7 @@ static void em_update_stats_counters(struct adapter *); static void em_clean_transmit_interrupts(struct adapter *); static int em_allocate_receive_structures(struct adapter *); static int em_allocate_transmit_structures(struct adapter *); -static void em_process_receive_interrupts(struct adapter *); +static void em_process_receive_interrupts(struct adapter *, int); static void em_receive_checksum(struct adapter *, struct em_rx_desc * rx_desc, struct mbuf *); @@ -682,12 +682,55 @@ em_init(void *arg) adapter->timer_handle = timeout(em_local_timer, adapter, 2*hz); em_clear_hw_cntrs(&adapter->hw); +#ifdef DEVICE_POLLING + /* + * Only enable interrupts if we are not polling, make sure + * they are off otherwise. + */ + if (ifp->if_ipending & IFF_POLLING) + em_disable_intr(adapter); + else +#endif /* DEVICE_POLLING */ em_enable_intr(adapter); splx(s); return; } +#ifdef DEVICE_POLLING +static poll_handler_t em_poll; + +static void +em_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) +{ + struct adapter *adapter = ifp->if_softc; + + if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */ + em_enable_intr(adapter); + return; + } + if (cmd == POLL_AND_CHECK_STATUS) { + u_int32_t reg_icr = E1000_READ_REG(&adapter->hw, ICR); + + 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, count); + em_clean_transmit_interrupts(adapter); + } + if (ifp->if_flags & IFF_RUNNING && ifp->if_snd.ifq_head != NULL) + em_start(ifp); +} +#endif /* DEVICE_POLLING */ + /********************************************************************* * * Interrupt Service routine @@ -704,6 +747,17 @@ em_intr(void *arg) 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) { @@ -720,7 +774,7 @@ em_intr(void *arg) } if (ifp->if_flags & IFF_RUNNING) { - em_process_receive_interrupts(adapter); + em_process_receive_interrupts(adapter, -1); em_clean_transmit_interrupts(adapter); } loop_cnt--; @@ -1993,7 +2047,7 @@ em_free_receive_structures(struct adapter * adapter) * *********************************************************************/ static void -em_process_receive_interrupts(struct adapter * adapter) +em_process_receive_interrupts(struct adapter * adapter, int count) { struct mbuf *mp; struct ifnet *ifp; @@ -2018,7 +2072,7 @@ em_process_receive_interrupts(struct adapter * adapter) return; } - while (current_desc->status & E1000_RXD_STAT_DD) { + while ((current_desc->status & E1000_RXD_STAT_DD) && (count != 0)) { /* Get a pointer to the actual receive buffer */ rx_buffer = STAILQ_FIRST(&adapter->rx_buffer_list); @@ -2032,6 +2086,7 @@ em_process_receive_interrupts(struct adapter * adapter) accept_frame = 1; if (current_desc->status & E1000_RXD_STAT_EOP) { + count--; eop = 1; len = current_desc->length - ETHER_CRC_LEN; } else { |