- 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.
This commit is contained in:
jhb 2009-11-19 18:37:55 +00:00
parent 4ba3c79b59
commit 00a2480413
2 changed files with 22 additions and 33 deletions

View File

@ -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 @@ ixgb_ioctl(struct ifnet * ifp, IOCTL_CMD_TYPE command, caddr_t data)
**********************************************************************/
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;

View File

@ -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 */