Index: sys/dev/ixl/if_ixl.c =================================================================== --- sys/dev/ixl/if_ixl.c +++ sys/dev/ixl/if_ixl.c @@ -113,6 +113,7 @@ static void ixl_configure_legacy(struct ixl_pf *); static void ixl_free_pci_resources(struct ixl_pf *); static void ixl_local_timer(void *); +static void ixl_queues_timer(struct ixl_pf *pf); static int ixl_setup_interface(device_t, struct ixl_vsi *); static void ixl_link_event(struct ixl_pf *, struct i40e_arq_event_info *); static void ixl_config_rss(struct ixl_vsi *); @@ -1748,13 +1749,9 @@ ixl_local_timer(void *arg) { struct ixl_pf *pf = arg; - struct i40e_hw *hw = &pf->hw; - struct ixl_vsi *vsi = &pf->vsi; - struct ixl_queue *que = vsi->queues; - device_t dev = pf->dev; - int hung = 0; - u32 mask; + struct ifnet *ifp; + ifp = pf->vsi.ifp; mtx_assert(&pf->pf_mtx, MA_OWNED); /* Fire off the adminq task */ @@ -1763,6 +1760,22 @@ /* Update stats */ ixl_update_stats_counters(pf); + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + ixl_queues_timer(pf); + + callout_reset(&pf->timer, hz, ixl_local_timer, pf); +} + +static void +ixl_queues_timer(struct ixl_pf *pf) +{ + struct i40e_hw *hw = &pf->hw; + struct ixl_vsi *vsi = &pf->vsi; + struct ixl_queue *que = vsi->queues; + device_t dev = pf->dev; + int hung = 0; + u32 mask; + /* ** Check status of the queues */ @@ -1798,15 +1811,10 @@ } } /* Only reinit if all queues show hung */ - if (hung == vsi->num_queues) - goto hung; - - callout_reset(&pf->timer, hz, ixl_local_timer, pf); - return; - -hung: - device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n"); - ixl_init_locked(pf); + if (hung == vsi->num_queues) { + device_printf(dev, "Local Timer: HANG DETECT - Resetting!!\n"); + ixl_init_locked(pf); + } } /* @@ -1883,8 +1891,9 @@ /* Tell the stack that the interface is no longer active */ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); - /* Stop the local timer */ - callout_stop(&pf->timer); + /* Stop the local timer if SR-IOV not in use. */ + if (pf->num_vfs == 0) + callout_stop(&pf->timer); return; } @@ -6322,6 +6331,10 @@ msg = event->msg_buf; msg_size = event->msg_len; + /* This must be a stray msg from a previously destroyed VF. */ + if (!(vf->vf_flags & VF_FLAG_ENABLED)) + return; + I40E_VC_DEBUG(pf, ixl_vc_opcode_level(opcode), "Got msg %s(%d) from VF-%d of size %d\n", ixl_vc_opcode_str(opcode), opcode, vf_num, msg_size); @@ -6381,6 +6394,7 @@ ixl_handle_vflr(void *arg, int pending) { struct ixl_pf *pf; + struct ixl_vf *vf; struct i40e_hw *hw; uint16_t global_vf_num; uint32_t vflrstat_index, vflrstat_mask, vflrstat, icr0; @@ -6393,6 +6407,10 @@ for (i = 0; i < pf->num_vfs; i++) { global_vf_num = hw->func_caps.vf_base_id + i; + vf = &pf->vfs[i]; + if (!(vf->vf_flags & VF_FLAG_ENABLED)) + continue; + vflrstat_index = IXL_GLGEN_VFLRSTAT_INDEX(global_vf_num); vflrstat_mask = IXL_GLGEN_VFLRSTAT_MASK(global_vf_num); vflrstat = rd32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index)); @@ -6400,7 +6418,7 @@ wr32(hw, I40E_GLGEN_VFLRSTAT(vflrstat_index), vflrstat_mask); - ixl_reinit_vf(pf, &pf->vfs[i]); + ixl_reinit_vf(pf, vf); } } @@ -6502,6 +6520,9 @@ ixl_configure_msix(pf); ixl_enable_adminq(hw); + ixl_flush(hw); + + callout_reset(&pf->timer, hz, ixl_local_timer, pf); pf->num_vfs = num_vfs; IXL_PF_UNLOCK(pf); @@ -6540,8 +6561,12 @@ pf->veb_seid = 0; } - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) { ixl_disable_intr(vsi); + ixl_flush(hw); + + callout_stop(&pf->timer); + } vfs = pf->vfs; num_vfs = pf->num_vfs;