aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/ice/if_ice_iflib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ice/if_ice_iflib.c')
-rw-r--r--sys/dev/ice/if_ice_iflib.c267
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 */