summaryrefslogtreecommitdiffstats
path: root/sys/dev/ixgb
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2009-11-19 18:37:55 +0000
committerjhb <jhb@FreeBSD.org>2009-11-19 18:37:55 +0000
commit00a2480413843cb1a2e42dbbcfdf0353a3e8c144 (patch)
tree7e7a57abe694b590735dd900170a9b74407c5192 /sys/dev/ixgb
parent4ba3c79b59a632c50b603118ca52aa1141c73e20 (diff)
downloadFreeBSD-src-00a2480413843cb1a2e42dbbcfdf0353a3e8c144.zip
FreeBSD-src-00a2480413843cb1a2e42dbbcfdf0353a3e8c144.tar.gz
- Use callout_init_mtx() instead of callout_init(..., CALLOUT_MPSAFE).
- Add a missing callout_drain() to detach. - Hook into the stats timer and use that to drive the transmit watchdog instead of using if_watchdog. - Run the stats timer every second to match other drivers instead of every other second. - Remove dubious callout handling that stopped the timer only to start it again while holding the driver lock without dropping it in between the stop and the start.
Diffstat (limited to 'sys/dev/ixgb')
-rw-r--r--sys/dev/ixgb/if_ixgb.c54
-rw-r--r--sys/dev/ixgb/if_ixgb.h1
2 files changed, 22 insertions, 33 deletions
diff --git a/sys/dev/ixgb/if_ixgb.c b/sys/dev/ixgb/if_ixgb.c
index 21d0bf0..990f791 100644
--- a/sys/dev/ixgb/if_ixgb.c
+++ b/sys/dev/ixgb/if_ixgb.c
@@ -97,7 +97,7 @@ static void ixgb_intr(void *);
static void ixgb_start(struct ifnet *);
static void ixgb_start_locked(struct ifnet *);
static int ixgb_ioctl(struct ifnet *, IOCTL_CMD_TYPE, caddr_t);
-static void ixgb_watchdog(struct ifnet *);
+static void ixgb_watchdog(struct adapter *);
static void ixgb_init(void *);
static void ixgb_init_locked(struct adapter *);
static void ixgb_stop(void *);
@@ -274,7 +274,7 @@ ixgb_attach(device_t dev)
(void *)adapter, 0,
ixgb_sysctl_stats, "I", "Statistics");
- callout_init(&adapter->timer, CALLOUT_MPSAFE);
+ callout_init_mtx(&adapter->timer, &adapter->mtx, 0);
/* Determine hardware revision */
ixgb_identify_hardware(adapter);
@@ -382,13 +382,14 @@ ixgb_detach(device_t dev)
IXGB_UNLOCK(adapter);
#if __FreeBSD_version < 500000
- ether_ifdetach(adapter->ifp, ETHER_BPF_SUPPORTED);
+ ether_ifdetach(ifp, ETHER_BPF_SUPPORTED);
#else
- ether_ifdetach(adapter->ifp);
+ ether_ifdetach(ifp);
#endif
+ callout_drain(&adapter->timer);
ixgb_free_pci_resources(adapter);
#if __FreeBSD_version >= 500000
- if_free(adapter->ifp);
+ if_free(ifp);
#endif
/* Free Transmit Descriptor ring */
@@ -409,9 +410,6 @@ ixgb_detach(device_t dev)
if (adapter->prev != NULL)
adapter->prev->next = adapter->next;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- ifp->if_timer = 0;
-
IXGB_LOCK_DESTROY(adapter);
return (0);
}
@@ -473,7 +471,7 @@ ixgb_start_locked(struct ifnet * ifp)
ETHER_BPF_MTAP(ifp, m_head);
#endif
/* Set timeout in case hardware has problems transmitting */
- ifp->if_timer = IXGB_TX_TIMEOUT;
+ adapter->tx_timer = IXGB_TX_TIMEOUT;
}
return;
@@ -610,26 +608,24 @@ out:
**********************************************************************/
static void
-ixgb_watchdog(struct ifnet * ifp)
+ixgb_watchdog(struct adapter *adapter)
{
- struct adapter *adapter;
- adapter = ifp->if_softc;
+ struct ifnet *ifp;
+
+ ifp = adapter->ifp;
/*
* If we are in this routine because of pause frames, then don't
* reset the hardware.
*/
if (IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF) {
- ifp->if_timer = IXGB_TX_TIMEOUT;
+ adapter->tx_timer = IXGB_TX_TIMEOUT;
return;
}
if_printf(ifp, "watchdog timeout -- resetting\n");
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-
-
ixgb_stop(adapter);
- ixgb_init(adapter);
+ ixgb_init_locked(adapter);
ifp->if_oerrors++;
@@ -713,7 +709,7 @@ ixgb_init_locked(struct adapter *adapter)
temp_reg |= IXGB_CTRL0_JFE;
IXGB_WRITE_REG(&adapter->hw, CTRL0, temp_reg);
}
- callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
+ callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
ixgb_clear_hw_cntrs(&adapter->hw);
#ifdef DEVICE_POLLING
/*
@@ -753,11 +749,8 @@ ixgb_poll_locked(struct ifnet * ifp, enum poll_cmd cmd, int count)
if (cmd == POLL_AND_CHECK_STATUS) {
reg_icr = IXGB_READ_REG(&adapter->hw, ICR);
if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
- callout_stop(&adapter->timer);
ixgb_check_for_link(&adapter->hw);
ixgb_print_link_status(adapter);
- callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
- adapter);
}
}
rx_npkts = ixgb_process_receive_interrupts(adapter, count);
@@ -830,11 +823,8 @@ ixgb_intr(void *arg)
/* Link status change */
if (reg_icr & (IXGB_INT_RXSEQ | IXGB_INT_LSC)) {
- callout_stop(&adapter->timer);
ixgb_check_for_link(&adapter->hw);
ixgb_print_link_status(adapter);
- callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer,
- adapter);
}
while (loop_cnt > 0) {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
@@ -1123,7 +1113,7 @@ ixgb_local_timer(void *arg)
struct adapter *adapter = arg;
ifp = adapter->ifp;
- IXGB_LOCK(adapter);
+ IXGB_LOCK_ASSERT(adapter);
ixgb_check_for_link(&adapter->hw);
ixgb_print_link_status(adapter);
@@ -1131,10 +1121,9 @@ ixgb_local_timer(void *arg)
if (ixgb_display_debug_stats && ifp->if_drv_flags & IFF_DRV_RUNNING) {
ixgb_print_hw_stats(adapter);
}
- callout_reset(&adapter->timer, 2 * hz, ixgb_local_timer, adapter);
-
- IXGB_UNLOCK(adapter);
- return;
+ if (adapter->tx_timer != 0 && --adapter->tx_timer == 0)
+ ixgb_watchdog(adapter);
+ callout_reset(&adapter->timer, hz, ixgb_local_timer, adapter);
}
static void
@@ -1183,9 +1172,9 @@ ixgb_stop(void *arg)
ixgb_free_transmit_structures(adapter);
ixgb_free_receive_structures(adapter);
-
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ adapter->tx_timer = 0;
return;
}
@@ -1352,7 +1341,6 @@ ixgb_setup_interface(device_t dev, struct adapter * adapter)
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
ifp->if_ioctl = ixgb_ioctl;
ifp->if_start = ixgb_start;
- ifp->if_watchdog = ixgb_watchdog;
ifp->if_snd.ifq_maxlen = adapter->num_tx_desc - 1;
#if __FreeBSD_version < 500000
@@ -1755,9 +1743,9 @@ ixgb_clean_transmit_interrupts(struct adapter * adapter)
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
if (num_avail == adapter->num_tx_desc)
- ifp->if_timer = 0;
+ adapter->tx_timer = 0;
else if (num_avail == adapter->num_tx_desc_avail)
- ifp->if_timer = IXGB_TX_TIMEOUT;
+ adapter->tx_timer = IXGB_TX_TIMEOUT;
}
adapter->num_tx_desc_avail = num_avail;
return;
diff --git a/sys/dev/ixgb/if_ixgb.h b/sys/dev/ixgb/if_ixgb.h
index cef9b55..9e5355a 100644
--- a/sys/dev/ixgb/if_ixgb.h
+++ b/sys/dev/ixgb/if_ixgb.h
@@ -284,6 +284,7 @@ struct adapter {
struct ifmedia media;
struct callout timer;
int io_rid;
+ int tx_timer;
struct mtx mtx;
/* Info about the board itself */
OpenPOWER on IntegriCloud