diff options
Diffstat (limited to 'sys/dev/ice/if_ice_iflib.c')
-rw-r--r-- | sys/dev/ice/if_ice_iflib.c | 267 |
1 files changed, 232 insertions, 35 deletions
diff --git a/sys/dev/ice/if_ice_iflib.c b/sys/dev/ice/if_ice_iflib.c index 4e451bf3fb55..1469d2916465 100644 --- a/sys/dev/ice/if_ice_iflib.c +++ b/sys/dev/ice/if_ice_iflib.c @@ -42,6 +42,9 @@ #include "ice_drv_info.h" #include "ice_switch.h" #include "ice_sched.h" +#ifdef PCI_IOV +#include "ice_iov.h" +#endif #include <sys/module.h> #include <sys/sockio.h> @@ -84,6 +87,13 @@ static int ice_if_i2c_req(if_ctx_t ctx, struct ifi2creq *req); static int ice_if_suspend(if_ctx_t ctx); static int ice_if_resume(if_ctx_t ctx); static bool ice_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event); +static void ice_init_link(struct ice_softc *sc); +#ifdef PCI_IOV +static int ice_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params); +static void ice_if_iov_uninit(if_ctx_t ctx); +static int ice_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params); +static void ice_if_vflr_handle(if_ctx_t ctx); +#endif static int ice_setup_mirror_vsi(struct ice_mirr_if *mif); static int ice_wire_mirror_intrs(struct ice_mirr_if *mif); static void ice_free_irqvs_subif(struct ice_mirr_if *mif); @@ -157,6 +167,11 @@ static device_method_t ice_methods[] = { DEVMETHOD(device_shutdown, iflib_device_shutdown), DEVMETHOD(device_suspend, iflib_device_suspend), DEVMETHOD(device_resume, iflib_device_resume), +#ifdef PCI_IOV + DEVMETHOD(pci_iov_init, iflib_device_iov_init), + DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), + DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), +#endif DEVMETHOD_END }; @@ -197,6 +212,12 @@ static device_method_t ice_iflib_methods[] = { DEVMETHOD(ifdi_suspend, ice_if_suspend), DEVMETHOD(ifdi_resume, ice_if_resume), DEVMETHOD(ifdi_needs_restart, ice_if_needs_restart), +#ifdef PCI_IOV + DEVMETHOD(ifdi_iov_vf_add, ice_if_iov_vf_add), + DEVMETHOD(ifdi_iov_init, ice_if_iov_init), + DEVMETHOD(ifdi_iov_uninit, ice_if_iov_uninit), + DEVMETHOD(ifdi_vflr_handle, ice_if_vflr_handle), +#endif DEVMETHOD_END }; @@ -458,7 +479,7 @@ ice_if_attach_pre(if_ctx_t ctx) { struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); enum ice_fw_modes fw_mode; - enum ice_status status; + int status; if_softc_ctx_t scctx; struct ice_hw *hw; device_t dev; @@ -472,6 +493,7 @@ ice_if_attach_pre(if_ctx_t ctx) sc->media = iflib_get_media(ctx); sc->sctx = iflib_get_sctx(ctx); sc->iflib_ctx_lock = iflib_ctx_lock_get(ctx); + sc->ifp = iflib_get_ifp(ctx); dev = sc->dev = iflib_get_dev(ctx); scctx = sc->scctx = iflib_get_softc_ctx(ctx); @@ -551,7 +573,7 @@ reinit_hw: * of the hardware */ err = ice_load_pkg_file(sc); - if (err == ICE_SUCCESS) { + if (!err) { ice_deinit_hw(hw); goto reinit_hw; } @@ -631,12 +653,8 @@ reinit_hw: */ ice_setup_pf_vsi(sc); - err = ice_alloc_vsi_qmap(&sc->pf_vsi, scctx->isc_ntxqsets_max, + ice_alloc_vsi_qmap(&sc->pf_vsi, scctx->isc_ntxqsets_max, scctx->isc_nrxqsets_max); - if (err) { - device_printf(dev, "Unable to allocate VSI Queue maps\n"); - goto free_main_vsi; - } /* Allocate MSI-X vectors (due to isc_flags IFLIB_SKIP_MSIX) */ err = ice_allocate_msix(sc); @@ -713,7 +731,7 @@ static void ice_update_link_status(struct ice_softc *sc, bool update_media) { struct ice_hw *hw = &sc->hw; - enum ice_status status; + int status; /* Never report link up when in recovery mode */ if (ice_test_state(&sc->state, ICE_STATE_RECOVERY_MODE)) @@ -735,6 +753,9 @@ ice_update_link_status(struct ice_softc *sc, bool update_media) iflib_link_state_change(sc->ctx, LINK_STATE_DOWN, 0); ice_rdma_link_change(sc, LINK_STATE_DOWN, 0); } +#ifdef PCI_IOV + ice_vc_notify_all_vfs_link_state(sc); +#endif update_media = true; } @@ -761,7 +782,7 @@ ice_if_attach_post(if_ctx_t ctx) { struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); if_t ifp = iflib_get_ifp(ctx); - enum ice_status status; + int status; int err; ASSERT_CTX_LOCKED(sc); @@ -776,8 +797,6 @@ ice_if_attach_post(if_ctx_t ctx) * handler is called, so wait until attach_post to setup the * isc_max_frame_size. */ - - sc->ifp = ifp; sc->scctx->isc_max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN; @@ -830,17 +849,24 @@ ice_if_attach_post(if_ctx_t ctx) * was previously in DSCP PFC mode. */ status = ice_aq_set_pfc_mode(&sc->hw, ICE_AQC_PFC_VLAN_BASED_PFC, NULL); - if (status != ICE_SUCCESS) + if (status) device_printf(sc->dev, "Setting pfc mode failed, status %s\n", ice_status_str(status)); ice_add_device_sysctls(sc); +#ifdef PCI_IOV + if (ice_is_bit_set(sc->feat_cap, ICE_FEATURE_SRIOV)) { + err = ice_iov_attach(sc); + if (err == ENOMEM) + return (err); + } +#endif /* PCI_IOV */ + /* Get DCBX/LLDP state and start DCBX agent */ ice_init_dcb_setup(sc); - /* Setup link configuration parameters */ - ice_init_link_configuration(sc); - ice_update_link_status(sc, true); + /* Setup link, if PHY FW is ready */ + ice_init_link(sc); /* Configure interrupt causes for the administrative interrupt */ ice_configure_misc_interrupts(sc); @@ -939,7 +965,7 @@ ice_if_detach(if_ctx_t ctx) { struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); struct ice_vsi *vsi = &sc->pf_vsi; - enum ice_status status; + int status; int i; ASSERT_CTX_LOCKED(sc); @@ -958,6 +984,11 @@ ice_if_detach(if_ctx_t ctx) ice_destroy_mirror_interface(sc); ice_rdma_pf_detach(sc); +#ifdef PCI_IOV + if (ice_is_bit_set(sc->feat_cap, ICE_FEATURE_SRIOV)) + ice_iov_detach(sc); +#endif /* PCI_IOV */ + /* Free allocated media types */ ifmedia_removeall(sc->media); @@ -1681,6 +1712,11 @@ ice_if_msix_intr_assign(if_ctx_t ctx, int msix) /* For future interrupt assignments */ sc->last_rid = rid + sc->irdma_vectors; +#ifdef PCI_IOV + /* Create soft IRQ for handling VF resets */ + iflib_softirq_alloc_generic(ctx, NULL, IFLIB_INTR_IOV, sc, 0, "iov"); +#endif + return (0); fail: for (; i >= 0; i--, vector--) @@ -1860,7 +1896,7 @@ ice_if_promisc_set(if_ctx_t ctx, int flags) struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); struct ice_hw *hw = &sc->hw; device_t dev = sc->dev; - enum ice_status status; + int status; bool promisc_enable = flags & IFF_PROMISC; bool multi_enable = flags & IFF_ALLMULTI; ice_declare_bitmap(promisc_mask, ICE_PROMISC_MAX); @@ -2141,12 +2177,24 @@ ice_poll_for_media_avail(struct ice_softc *sc) struct ice_hw *hw = &sc->hw; struct ice_port_info *pi = hw->port_info; + /* E830 only: There's no interrupt for when the PHY FW has finished loading, + * so poll for the status in the media task here if it's previously + * been detected that it's still loading. + */ + if (ice_is_e830(hw) && + ice_test_state(&sc->state, ICE_STATE_PHY_FW_INIT_PENDING)) { + if (rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_LOADING_M) + ice_clear_state(&sc->state, ICE_STATE_PHY_FW_INIT_PENDING); + else + return; + } + if (ice_test_state(&sc->state, ICE_STATE_NO_MEDIA)) { pi->phy.get_link_info = true; ice_get_link_status(pi, &sc->link_up); if (pi->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) { - enum ice_status status; + int status; /* Re-enable link and re-apply user link settings */ if (ice_test_state(&sc->state, ICE_STATE_LINK_ACTIVE_ON_DOWN) || @@ -2270,7 +2318,12 @@ ice_transition_recovery_mode(struct ice_softc *sc) ice_rdma_pf_detach(sc); ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_cap); +#ifdef PCI_IOV + if (ice_test_and_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en)) + ice_iov_detach(sc); +#else ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en); +#endif /* PCI_IOV */ ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_cap); ice_vsi_del_txqs_ctx(vsi); @@ -2318,7 +2371,12 @@ ice_transition_safe_mode(struct ice_softc *sc) ice_rdma_pf_detach(sc); ice_clear_bit(ICE_FEATURE_RDMA, sc->feat_cap); +#ifdef PCI_IOV + if (ice_test_and_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en)) + ice_iov_detach(sc); +#else ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_en); +#endif /* PCI_IOV */ ice_clear_bit(ICE_FEATURE_SRIOV, sc->feat_cap); ice_clear_bit(ICE_FEATURE_RSS, sc->feat_cap); @@ -2386,6 +2444,12 @@ ice_if_update_admin_status(if_ctx_t ctx) if (pending > 0) reschedule = true; + if (ice_is_generic_mac(&sc->hw)) { + ice_process_ctrlq(sc, ICE_CTL_Q_SB, &pending); + if (pending > 0) + reschedule = true; + } + ice_process_ctrlq(sc, ICE_CTL_Q_MAILBOX, &pending); if (pending > 0) reschedule = true; @@ -2397,6 +2461,15 @@ ice_if_update_admin_status(if_ctx_t ctx) /* Check and update link status */ ice_update_link_status(sc, false); +#ifdef PCI_IOV + /* + * Schedule VFs' reset handler after global resets + * and other events were processed. + */ + if (ice_testandclear_state(&sc->state, ICE_STATE_VFLR_PENDING)) + iflib_iov_intr_deferred(ctx); +#endif + /* * If there are still messages to process, we need to reschedule * ourselves. Otherwise, we can just re-enable the interrupt. We'll be @@ -2564,7 +2637,7 @@ ice_rebuild(struct ice_softc *sc) struct ice_hw *hw = &sc->hw; device_t dev = sc->dev; enum ice_ddp_state pkg_state; - enum ice_status status; + int status; int err; sc->rebuild_ticks = ticks; @@ -2602,7 +2675,9 @@ ice_rebuild(struct ice_softc *sc) } /* Re-enable FW logging. Keep going even if this fails */ - status = ice_fwlog_set(hw, &hw->fwlog_cfg); + status = ICE_SUCCESS; + if (hw->pf_id == 0) + status = ice_fwlog_set(hw, &hw->fwlog_cfg); if (!status) { /* * We should have the most updated cached copy of the @@ -2702,11 +2777,11 @@ ice_rebuild(struct ice_softc *sc) if (hw->port_info->qos_cfg.is_sw_lldp) ice_add_rx_lldp_filter(sc); - /* Refresh link status */ + /* Apply previous link settings and refresh link status, if PHY + * FW is ready. + */ ice_clear_state(&sc->state, ICE_STATE_LINK_STATUS_REPORTED); - sc->hw.port_info->phy.get_link_info = true; - ice_get_link_status(sc->hw.port_info, &sc->link_up); - ice_update_link_status(sc, true); + ice_init_link(sc); /* RDMA interface will be restarted by the stack re-init */ @@ -2726,7 +2801,7 @@ ice_rebuild(struct ice_softc *sc) goto err_deinit_pf_vsi; } - log(LOG_INFO, "%s: device rebuild successful\n", sc->ifp->if_xname); + log(LOG_INFO, "%s: device rebuild successful\n", if_name(sc->ifp)); /* In order to completely restore device functionality, the iflib core * needs to be reset. We need to request an iflib reset. Additionally, @@ -2774,7 +2849,7 @@ static void ice_handle_reset_event(struct ice_softc *sc) { struct ice_hw *hw = &sc->hw; - enum ice_status status; + int status; device_t dev = sc->dev; /* When a CORER, GLOBR, or EMPR is about to happen, the hardware will @@ -2792,12 +2867,23 @@ ice_handle_reset_event(struct ice_softc *sc) * resetting. */ IFLIB_CTX_UNLOCK(sc); + +#define ICE_EMPR_ADDL_WAIT_MSEC_SLOW 20000 + if ((ice_is_e830(hw) || ice_is_e825c(hw)) && + (((rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >> + GLGEN_RSTAT_RESET_TYPE_S) == ICE_RESET_EMPR)) + ice_msec_pause(ICE_EMPR_ADDL_WAIT_MSEC_SLOW); + status = ice_check_reset(hw); IFLIB_CTX_LOCK(sc); if (status) { device_printf(dev, "Device never came out of reset, err %s\n", ice_status_str(status)); + ice_set_state(&sc->state, ICE_STATE_RESET_FAILED); + ice_clear_state(&sc->state, ICE_STATE_RESET_PFR_REQ); + ice_clear_state(&sc->state, ICE_STATE_PREPARED_FOR_RESET); + device_printf(dev, "Reset failed; please reload the device driver\n"); return; } @@ -2829,7 +2915,7 @@ static void ice_handle_pf_reset_request(struct ice_softc *sc) { struct ice_hw *hw = &sc->hw; - enum ice_status status; + int status; /* Check for PF reset requests */ if (!ice_testandclear_state(&sc->state, ICE_STATE_RESET_PFR_REQ)) @@ -2880,7 +2966,13 @@ ice_init_device_features(struct ice_softc *sc) ice_set_bit(ICE_FEATURE_HAS_PBA, sc->feat_cap); ice_set_bit(ICE_FEATURE_DCB, sc->feat_cap); ice_set_bit(ICE_FEATURE_TX_BALANCE, sc->feat_cap); + ice_set_bit(ICE_FEATURE_PHY_STATISTICS, sc->feat_cap); + if (ice_is_e810(hw)) + ice_set_bit(ICE_FEATURE_PHY_STATISTICS, sc->feat_en); + + if (ice_is_e825c(hw)) + ice_set_bit(ICE_FEATURE_DUAL_NAC, sc->feat_cap); /* Disable features due to hardware limitations... */ if (!hw->func_caps.common_cap.rss_table_size) ice_clear_bit(ICE_FEATURE_RSS, sc->feat_cap); @@ -2915,6 +3007,12 @@ ice_init_device_features(struct ice_softc *sc) ice_set_bit(ICE_FEATURE_TEMP_SENSOR, sc->feat_cap); ice_set_bit(ICE_FEATURE_TEMP_SENSOR, sc->feat_en); } + + if (hw->func_caps.common_cap.next_cluster_id_support || + hw->dev_caps.common_cap.next_cluster_id_support) { + ice_set_bit(ICE_FEATURE_NEXT_CLUSTER_ID, sc->feat_cap); + ice_set_bit(ICE_FEATURE_NEXT_CLUSTER_ID, sc->feat_en); + } } /** @@ -2961,7 +3059,7 @@ static void ice_if_vlan_register(if_ctx_t ctx, u16 vtag) { struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); - enum ice_status status; + int status; ASSERT_CTX_LOCKED(sc); @@ -2991,7 +3089,7 @@ static void ice_if_vlan_unregister(if_ctx_t ctx, u16 vtag) { struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); - enum ice_status status; + int status; ASSERT_CTX_LOCKED(sc); @@ -3279,6 +3377,110 @@ ice_if_needs_restart(if_ctx_t ctx, enum iflib_restart_event event) } } +/** + * ice_init_link - Do link configuration and link status reporting + * @sc: driver private structure + * + * Contains an extra check that skips link config when an E830 device + * does not have the "FW_LOADING"/"PHYBUSY" bit set in GL_MNG_FWSM set. + */ +static void +ice_init_link(struct ice_softc *sc) +{ + struct ice_hw *hw = &sc->hw; + device_t dev = sc->dev; + + /* Check if FW is ready before setting up link; defer setup to the + * admin task if it isn't. + */ + if (ice_is_e830(hw) && + (rd32(hw, GL_MNG_FWSM) & GL_MNG_FWSM_FW_LOADING_M)) { + ice_set_state(&sc->state, ICE_STATE_PHY_FW_INIT_PENDING); + device_printf(dev, + "Link initialization is blocked by PHY FW initialization.\n"); + device_printf(dev, + "Link initialization will continue after PHY FW initialization completes.\n"); + /* Do not access PHY config while PHY FW is busy initializing */ + } else { + ice_clear_state(&sc->state, ICE_STATE_PHY_FW_INIT_PENDING); + ice_init_link_configuration(sc); + ice_update_link_status(sc, true); + } + +} + +#ifdef PCI_IOV +/** + * ice_if_iov_init - iov init handler for iflib + * @ctx: iflib context pointer + * @num_vfs: number of VFs to create + * @params: configuration parameters for the PF + * + * Configure the driver for SR-IOV mode. Used to setup things like memory + * before any VFs are created. + * + * @remark This is a wrapper for ice_iov_init + */ +static int +ice_if_iov_init(if_ctx_t ctx, uint16_t num_vfs, const nvlist_t *params) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + return ice_iov_init(sc, num_vfs, params); +} + +/** + * ice_if_iov_uninit - iov uninit handler for iflib + * @ctx: iflib context pointer + * + * Destroys VFs and frees their memory and resources. + * + * @remark This is a wrapper for ice_iov_uninit + */ +static void +ice_if_iov_uninit(if_ctx_t ctx) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + ice_iov_uninit(sc); +} + +/** + * ice_if_iov_vf_add - iov add vf handler for iflib + * @ctx: iflib context pointer + * @vfnum: index of VF to configure + * @params: configuration parameters for the VF + * + * Sets up the VF given by the vfnum index. This is called by the OS + * for each VF created by the PF driver after it is spawned. + * + * @remark This is a wrapper for ice_iov_vf_add + */ +static int +ice_if_iov_vf_add(if_ctx_t ctx, uint16_t vfnum, const nvlist_t *params) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + + return ice_iov_add_vf(sc, vfnum, params); +} + +/** + * ice_if_vflr_handle - iov VFLR handler + * @ctx: iflib context pointer + * + * Performs the necessar teardown or setup required for a VF after + * a VFLR is initiated. + * + * @remark This is a wrapper for ice_iov_handle_vflr + */ +static void +ice_if_vflr_handle(if_ctx_t ctx) +{ + struct ice_softc *sc = (struct ice_softc *)iflib_get_softc(ctx); + ice_iov_handle_vflr(sc); +} +#endif /* PCI_IOV */ + extern struct if_txrx ice_subif_txrx; /** @@ -3518,12 +3720,7 @@ ice_setup_mirror_vsi(struct ice_mirr_if *mif) mif->vsi = vsi; /* Reserve VSI queue allocation from PF queues */ - ret = ice_alloc_vsi_qmap(vsi, ICE_DEFAULT_VF_QUEUES, ICE_DEFAULT_VF_QUEUES); - if (ret) { - device_printf(dev, "%s: Unable to allocate mirror VSI queue maps (%d queues): %s\n", - __func__, ICE_DEFAULT_VF_QUEUES, ice_err_str(ret)); - goto release_vsi; - } + ice_alloc_vsi_qmap(vsi, ICE_DEFAULT_VF_QUEUES, ICE_DEFAULT_VF_QUEUES); vsi->num_tx_queues = vsi->num_rx_queues = ICE_DEFAULT_VF_QUEUES; /* Assign Tx queues from PF space */ |