diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_main.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 603 |
1 files changed, 401 insertions, 202 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 6607fa6fe556..5d7660bc8846 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -14,6 +14,7 @@ #include "ice_dcb_lib.h" #include "ice_dcb_nl.h" #include "ice_devlink.h" +#include "ice_hwmon.h" /* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the * ice tracepoint functions. This must be done exactly once across the * ice driver. @@ -612,7 +613,7 @@ skip: ice_pf_dis_all_vsi(pf, false); if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) - ice_ptp_prepare_for_reset(pf); + ice_ptp_prepare_for_reset(pf, reset_type); if (ice_is_feature_supported(pf, ICE_F_GNSS)) ice_gnss_exit(pf); @@ -979,7 +980,7 @@ static void ice_set_dflt_mib(struct ice_pf *pf) * Octets 13 - 20 are TSA values - leave as zeros */ buf[5] = 0x64; - len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S; + len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); offset += len + 2; tlv = (struct ice_lldp_org_tlv *) ((char *)tlv + sizeof(tlv->typelen) + len); @@ -1013,7 +1014,7 @@ static void ice_set_dflt_mib(struct ice_pf *pf) /* Octet 1 left as all zeros - PFC disabled */ buf[0] = 0x08; - len = (typelen & ICE_LLDP_TLV_LEN_M) >> ICE_LLDP_TLV_LEN_S; + len = FIELD_GET(ICE_LLDP_TLV_LEN_M, typelen); offset += len + 2; if (ice_aq_set_lldp_mib(hw, mib_type, (void *)lldpmib, offset, NULL)) @@ -1252,6 +1253,32 @@ ice_handle_link_event(struct ice_pf *pf, struct ice_rq_event_info *event) } /** + * ice_get_fwlog_data - copy the FW log data from ARQ event + * @pf: PF that the FW log event is associated with + * @event: event structure containing FW log data + */ +static void +ice_get_fwlog_data(struct ice_pf *pf, struct ice_rq_event_info *event) +{ + struct ice_fwlog_data *fwlog; + struct ice_hw *hw = &pf->hw; + + fwlog = &hw->fwlog_ring.rings[hw->fwlog_ring.tail]; + + memset(fwlog->data, 0, PAGE_SIZE); + fwlog->data_size = le16_to_cpu(event->desc.datalen); + + memcpy(fwlog->data, event->msg_buf, fwlog->data_size); + ice_fwlog_ring_increment(&hw->fwlog_ring.tail, hw->fwlog_ring.size); + + if (ice_fwlog_ring_full(&hw->fwlog_ring)) { + /* the rings are full so bump the head to create room */ + ice_fwlog_ring_increment(&hw->fwlog_ring.head, + hw->fwlog_ring.size); + } +} + +/** * ice_aq_prep_for_event - Prepare to wait for an AdminQ event from firmware * @pf: pointer to the PF private structure * @task: intermediate helper storage and identifier for waiting @@ -1532,8 +1559,8 @@ static int __ice_clean_ctrlq(struct ice_pf *pf, enum ice_ctl_q q_type) ice_vc_process_vf_msg(pf, &event, &data); break; - case ice_aqc_opc_fw_logging: - ice_output_fw_log(hw, &event.desc, event.msg_buf); + case ice_aqc_opc_fw_logs_event: + ice_get_fwlog_data(pf, &event); break; case ice_aqc_opc_lldp_set_mib_change: ice_dcb_process_lldp_set_mib_change(pf, &event); @@ -1622,8 +1649,10 @@ static void ice_clean_sbq_subtask(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; - /* Nothing to do here if sideband queue is not supported */ - if (!ice_is_sbq_supported(hw)) { + /* if mac_type is not generic, sideband is not supported + * and there's nothing to do here + */ + if (!ice_is_generic_mac(hw)) { clear_bit(ICE_SIDEBANDQ_EVENT_PENDING, pf->state); return; } @@ -1744,14 +1773,10 @@ static void ice_handle_mdd_event(struct ice_pf *pf) /* find what triggered an MDD event */ reg = rd32(hw, GL_MDET_TX_PQM); if (reg & GL_MDET_TX_PQM_VALID_M) { - u8 pf_num = (reg & GL_MDET_TX_PQM_PF_NUM_M) >> - GL_MDET_TX_PQM_PF_NUM_S; - u16 vf_num = (reg & GL_MDET_TX_PQM_VF_NUM_M) >> - GL_MDET_TX_PQM_VF_NUM_S; - u8 event = (reg & GL_MDET_TX_PQM_MAL_TYPE_M) >> - GL_MDET_TX_PQM_MAL_TYPE_S; - u16 queue = ((reg & GL_MDET_TX_PQM_QNUM_M) >> - GL_MDET_TX_PQM_QNUM_S); + u8 pf_num = FIELD_GET(GL_MDET_TX_PQM_PF_NUM_M, reg); + u16 vf_num = FIELD_GET(GL_MDET_TX_PQM_VF_NUM_M, reg); + u8 event = FIELD_GET(GL_MDET_TX_PQM_MAL_TYPE_M, reg); + u16 queue = FIELD_GET(GL_MDET_TX_PQM_QNUM_M, reg); if (netif_msg_tx_err(pf)) dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", @@ -1761,14 +1786,10 @@ static void ice_handle_mdd_event(struct ice_pf *pf) reg = rd32(hw, GL_MDET_TX_TCLAN_BY_MAC(hw)); if (reg & GL_MDET_TX_TCLAN_VALID_M) { - u8 pf_num = (reg & GL_MDET_TX_TCLAN_PF_NUM_M) >> - GL_MDET_TX_TCLAN_PF_NUM_S; - u16 vf_num = (reg & GL_MDET_TX_TCLAN_VF_NUM_M) >> - GL_MDET_TX_TCLAN_VF_NUM_S; - u8 event = (reg & GL_MDET_TX_TCLAN_MAL_TYPE_M) >> - GL_MDET_TX_TCLAN_MAL_TYPE_S; - u16 queue = ((reg & GL_MDET_TX_TCLAN_QNUM_M) >> - GL_MDET_TX_TCLAN_QNUM_S); + u8 pf_num = FIELD_GET(GL_MDET_TX_TCLAN_PF_NUM_M, reg); + u16 vf_num = FIELD_GET(GL_MDET_TX_TCLAN_VF_NUM_M, reg); + u8 event = FIELD_GET(GL_MDET_TX_TCLAN_MAL_TYPE_M, reg); + u16 queue = FIELD_GET(GL_MDET_TX_TCLAN_QNUM_M, reg); if (netif_msg_tx_err(pf)) dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n", @@ -1778,14 +1799,10 @@ static void ice_handle_mdd_event(struct ice_pf *pf) reg = rd32(hw, GL_MDET_RX); if (reg & GL_MDET_RX_VALID_M) { - u8 pf_num = (reg & GL_MDET_RX_PF_NUM_M) >> - GL_MDET_RX_PF_NUM_S; - u16 vf_num = (reg & GL_MDET_RX_VF_NUM_M) >> - GL_MDET_RX_VF_NUM_S; - u8 event = (reg & GL_MDET_RX_MAL_TYPE_M) >> - GL_MDET_RX_MAL_TYPE_S; - u16 queue = ((reg & GL_MDET_RX_QNUM_M) >> - GL_MDET_RX_QNUM_S); + u8 pf_num = FIELD_GET(GL_MDET_RX_PF_NUM_M, reg); + u16 vf_num = FIELD_GET(GL_MDET_RX_VF_NUM_M, reg); + u8 event = FIELD_GET(GL_MDET_RX_MAL_TYPE_M, reg); + u16 queue = FIELD_GET(GL_MDET_RX_QNUM_M, reg); if (netif_msg_rx_err(pf)) dev_info(dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n", @@ -2146,7 +2163,7 @@ static int ice_configure_phy(struct ice_vsi *vsi) /* Ensure we have media as we cannot configure a medialess port */ if (!(phy->link_info.link_info & ICE_AQ_MEDIA_AVAILABLE)) - return -EPERM; + return -ENOMEDIUM; ice_print_topo_conflict(vsi); @@ -3031,6 +3048,7 @@ static int ice_xdp(struct net_device *dev, struct netdev_bpf *xdp) static void ice_ena_misc_vector(struct ice_pf *pf) { struct ice_hw *hw = &pf->hw; + u32 pf_intr_start_offset; u32 val; /* Disable anti-spoof detection interrupt to prevent spurious event @@ -3059,6 +3077,47 @@ static void ice_ena_misc_vector(struct ice_pf *pf) /* SW_ITR_IDX = 0, but don't change INTENA */ wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index), GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); + + if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) + return; + pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; + wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), + GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); +} + +/** + * ice_ll_ts_intr - ll_ts interrupt handler + * @irq: interrupt number + * @data: pointer to a q_vector + */ +static irqreturn_t ice_ll_ts_intr(int __always_unused irq, void *data) +{ + struct ice_pf *pf = data; + u32 pf_intr_start_offset; + struct ice_ptp_tx *tx; + unsigned long flags; + struct ice_hw *hw; + u32 val; + u8 idx; + + hw = &pf->hw; + tx = &pf->ptp.port.tx; + spin_lock_irqsave(&tx->lock, flags); + ice_ptp_complete_tx_single_tstamp(tx); + + idx = find_next_bit_wrap(tx->in_use, tx->len, + tx->last_ll_ts_idx_read + 1); + if (idx != tx->len) + ice_ptp_req_tx_single_tstamp(tx, idx); + spin_unlock_irqrestore(&tx->lock, flags); + + val = GLINT_DYN_CTL_INTENA_M | GLINT_DYN_CTL_CLEARPBA_M | + (ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S); + pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; + wr32(hw, GLINT_DYN_CTL(pf->ll_ts_irq.index + pf_intr_start_offset), + val); + + return IRQ_HANDLED; } /** @@ -3069,6 +3128,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf) static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) { struct ice_pf *pf = (struct ice_pf *)data; + irqreturn_t ret = IRQ_HANDLED; struct ice_hw *hw = &pf->hw; struct device *dev; u32 oicr, ena_mask; @@ -3108,8 +3168,8 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) /* we have a reset warning */ ena_mask &= ~PFINT_OICR_GRST_M; - reset = (rd32(hw, GLGEN_RSTAT) & GLGEN_RSTAT_RESET_TYPE_M) >> - GLGEN_RSTAT_RESET_TYPE_S; + reset = FIELD_GET(GLGEN_RSTAT_RESET_TYPE_M, + rd32(hw, GLGEN_RSTAT)); if (reset == ICE_RESET_CORER) pf->corer_count++; @@ -3150,8 +3210,22 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) if (oicr & PFINT_OICR_TSYN_TX_M) { ena_mask &= ~PFINT_OICR_TSYN_TX_M; - if (!hw->reset_ongoing && ice_ptp_pf_handles_tx_interrupt(pf)) + if (ice_pf_state_is_nominal(pf) && + pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) { + struct ice_ptp_tx *tx = &pf->ptp.port.tx; + unsigned long flags; + u8 idx; + + spin_lock_irqsave(&tx->lock, flags); + idx = find_next_bit_wrap(tx->in_use, tx->len, + tx->last_ll_ts_idx_read + 1); + if (idx != tx->len) + ice_ptp_req_tx_single_tstamp(tx, idx); + spin_unlock_irqrestore(&tx->lock, flags); + } else if (ice_ptp_pf_handles_tx_interrupt(pf)) { set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); + ret = IRQ_WAKE_THREAD; + } } if (oicr & PFINT_OICR_TSYN_EVNT_M) { @@ -3167,7 +3241,7 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) GLTSYN_STAT_EVENT1_M | GLTSYN_STAT_EVENT2_M); - set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); + ice_ptp_extts_event(pf); } } @@ -3190,8 +3264,11 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) set_bit(ICE_PFR_REQ, pf->state); } } + ice_service_task_schedule(pf); + if (ret == IRQ_HANDLED) + ice_irq_dynamic_ena(hw, NULL, NULL); - return IRQ_WAKE_THREAD; + return ret; } /** @@ -3207,12 +3284,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) hw = &pf->hw; if (ice_is_reset_in_progress(pf->state)) - return IRQ_HANDLED; - - ice_service_task_schedule(pf); - - if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) - ice_ptp_extts_event(pf); + goto skip_irq; if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { /* Process outstanding Tx timestamps. If there is more work, @@ -3224,6 +3296,7 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) } } +skip_irq: ice_irq_dynamic_ena(hw, NULL, NULL); return IRQ_HANDLED; @@ -3254,6 +3327,20 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw) } /** + * ice_free_irq_msix_ll_ts- Unroll ll_ts vector setup + * @pf: board private structure + */ +static void ice_free_irq_msix_ll_ts(struct ice_pf *pf) +{ + int irq_num = pf->ll_ts_irq.virq; + + synchronize_irq(irq_num); + devm_free_irq(ice_pf_to_dev(pf), irq_num, pf); + + ice_free_irq(pf, pf->ll_ts_irq); +} + +/** * ice_free_irq_msix_misc - Unroll misc vector setup * @pf: board private structure */ @@ -3272,6 +3359,8 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf); ice_free_irq(pf, pf->oicr_irq); + if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) + ice_free_irq_msix_ll_ts(pf); } /** @@ -3297,10 +3386,12 @@ static void ice_ena_ctrlq_interrupts(struct ice_hw *hw, u16 reg_idx) PFINT_MBX_CTL_CAUSE_ENA_M); wr32(hw, PFINT_MBX_CTL, val); - /* This enables Sideband queue Interrupt causes */ - val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | - PFINT_SB_CTL_CAUSE_ENA_M); - wr32(hw, PFINT_SB_CTL, val); + if (!hw->dev_caps.ts_dev_info.ts_ll_int_read) { + /* enable Sideband queue Interrupt causes */ + val = ((reg_idx & PFINT_SB_CTL_MSIX_INDX_M) | + PFINT_SB_CTL_CAUSE_ENA_M); + wr32(hw, PFINT_SB_CTL, val); + } ice_flush(hw); } @@ -3317,13 +3408,17 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); struct ice_hw *hw = &pf->hw; - struct msi_map oicr_irq; + u32 pf_intr_start_offset; + struct msi_map irq; int err = 0; if (!pf->int_name[0]) snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", dev_driver_string(dev), dev_name(dev)); + if (!pf->int_name_ll_ts[0]) + snprintf(pf->int_name_ll_ts, sizeof(pf->int_name_ll_ts) - 1, + "%s-%s:ll_ts", dev_driver_string(dev), dev_name(dev)); /* Do not request IRQ but do enable OICR interrupt since settings are * lost during reset. Note that this function is called only during * rebuild path and not while reset is in progress. @@ -3332,11 +3427,11 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) goto skip_req_irq; /* reserve one vector in irq_tracker for misc interrupts */ - oicr_irq = ice_alloc_irq(pf, false); - if (oicr_irq.index < 0) - return oicr_irq.index; + irq = ice_alloc_irq(pf, false); + if (irq.index < 0) + return irq.index; - pf->oicr_irq = oicr_irq; + pf->oicr_irq = irq; err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr, ice_misc_intr_thread_fn, 0, pf->int_name, pf); @@ -3347,10 +3442,34 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) return err; } + /* reserve one vector in irq_tracker for ll_ts interrupt */ + if (!pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) + goto skip_req_irq; + + irq = ice_alloc_irq(pf, false); + if (irq.index < 0) + return irq.index; + + pf->ll_ts_irq = irq; + err = devm_request_irq(dev, pf->ll_ts_irq.virq, ice_ll_ts_intr, 0, + pf->int_name_ll_ts, pf); + if (err) { + dev_err(dev, "devm_request_irq for %s failed: %d\n", + pf->int_name_ll_ts, err); + ice_free_irq(pf, pf->ll_ts_irq); + return err; + } + skip_req_irq: ice_ena_misc_vector(pf); ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index); + /* This enables LL TS interrupt */ + pf_intr_start_offset = rd32(hw, PFINT_ALLOC) & PFINT_ALLOC_FIRST; + if (pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) + wr32(hw, PFINT_SB_CTL, + ((pf->ll_ts_irq.index + pf_intr_start_offset) & + PFINT_SB_CTL_MSIX_INDX_M) | PFINT_SB_CTL_CAUSE_ENA_M); wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index), ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S); @@ -3375,9 +3494,11 @@ static void ice_napi_add(struct ice_vsi *vsi) if (!vsi->netdev) return; - ice_for_each_q_vector(vsi, v_idx) + ice_for_each_q_vector(vsi, v_idx) { netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx]->napi, ice_napi_poll); + __ice_q_vector_set_napi_queues(vsi->q_vectors[v_idx], false); + } } /** @@ -3397,6 +3518,7 @@ static void ice_set_ops(struct ice_vsi *vsi) netdev->netdev_ops = &ice_netdev_ops; netdev->udp_tunnel_nic_info = &pf->hw.udp_tunnel_nic; + netdev->xdp_metadata_ops = &ice_xdp_md_ops; ice_set_ethtool_ops(netdev); if (vsi->type != ICE_VSI_PF) @@ -4361,6 +4483,19 @@ static void ice_print_wake_reason(struct ice_pf *pf) } /** + * ice_pf_fwlog_update_module - update 1 module + * @pf: pointer to the PF struct + * @log_level: log_level to use for the @module + * @module: module to update + */ +void ice_pf_fwlog_update_module(struct ice_pf *pf, int log_level, int module) +{ + struct ice_hw *hw = &pf->hw; + + hw->fwlog_cfg.module_entries[module].log_level = log_level; +} + +/** * ice_register_netdev - register netdev * @vsi: pointer to the VSI struct */ @@ -4439,90 +4574,6 @@ static void ice_decfg_netdev(struct ice_vsi *vsi) vsi->netdev = NULL; } -static int ice_start_eth(struct ice_vsi *vsi) -{ - int err; - - err = ice_init_mac_fltr(vsi->back); - if (err) - return err; - - err = ice_vsi_open(vsi); - if (err) - ice_fltr_remove_all(vsi); - - return err; -} - -static void ice_stop_eth(struct ice_vsi *vsi) -{ - ice_fltr_remove_all(vsi); - ice_vsi_close(vsi); -} - -static int ice_init_eth(struct ice_pf *pf) -{ - struct ice_vsi *vsi = ice_get_main_vsi(pf); - int err; - - if (!vsi) - return -EINVAL; - - /* init channel list */ - INIT_LIST_HEAD(&vsi->ch_list); - - err = ice_cfg_netdev(vsi); - if (err) - return err; - /* Setup DCB netlink interface */ - ice_dcbnl_setup(vsi); - - err = ice_init_mac_fltr(pf); - if (err) - goto err_init_mac_fltr; - - err = ice_devlink_create_pf_port(pf); - if (err) - goto err_devlink_create_pf_port; - - SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); - - err = ice_register_netdev(vsi); - if (err) - goto err_register_netdev; - - err = ice_tc_indir_block_register(vsi); - if (err) - goto err_tc_indir_block_register; - - ice_napi_add(vsi); - - return 0; - -err_tc_indir_block_register: - ice_unregister_netdev(vsi); -err_register_netdev: - ice_devlink_destroy_pf_port(pf); -err_devlink_create_pf_port: -err_init_mac_fltr: - ice_decfg_netdev(vsi); - return err; -} - -static void ice_deinit_eth(struct ice_pf *pf) -{ - struct ice_vsi *vsi = ice_get_main_vsi(pf); - - if (!vsi) - return; - - ice_vsi_close(vsi); - ice_unregister_netdev(vsi); - ice_devlink_destroy_pf_port(pf); - ice_tc_indir_block_unregister(vsi); - ice_decfg_netdev(vsi); -} - /** * ice_wait_for_fw - wait for full FW readiness * @hw: pointer to the hardware structure @@ -4548,7 +4599,7 @@ static int ice_wait_for_fw(struct ice_hw *hw, u32 timeout) return -ETIMEDOUT; } -static int ice_init_dev(struct ice_pf *pf) +int ice_init_dev(struct ice_pf *pf) { struct device *dev = ice_pf_to_dev(pf); struct ice_hw *hw = &pf->hw; @@ -4641,7 +4692,7 @@ err_init_pf: return err; } -static void ice_deinit_dev(struct ice_pf *pf) +void ice_deinit_dev(struct ice_pf *pf) { ice_free_irq_msix_misc(pf); ice_deinit_pf(pf); @@ -4685,6 +4736,8 @@ static void ice_init_features(struct ice_pf *pf) if (ice_init_lag(pf)) dev_warn(dev, "Failed to init link aggregation support\n"); + + ice_hwmon_init(pf); } static void ice_deinit_features(struct ice_pf *pf) @@ -4702,6 +4755,8 @@ static void ice_deinit_features(struct ice_pf *pf) ice_ptp_release(pf); if (test_bit(ICE_FLAG_DPLL, pf->flags)) ice_dpll_deinit(pf); + if (pf->eswitch_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) + xa_destroy(&pf->eswitch.reprs); } static void ice_init_wakeup(struct ice_pf *pf) @@ -4942,31 +4997,47 @@ static void ice_deinit(struct ice_pf *pf) /** * ice_load - load pf by init hw and starting VSI * @pf: pointer to the pf instance + * + * This function has to be called under devl_lock. */ int ice_load(struct ice_pf *pf) { - struct ice_vsi_cfg_params params = {}; struct ice_vsi *vsi; int err; - err = ice_init_dev(pf); + devl_assert_locked(priv_to_devlink(pf)); + + vsi = ice_get_main_vsi(pf); + + /* init channel list */ + INIT_LIST_HEAD(&vsi->ch_list); + + err = ice_cfg_netdev(vsi); if (err) return err; - vsi = ice_get_main_vsi(pf); + /* Setup DCB netlink interface */ + ice_dcbnl_setup(vsi); - params = ice_vsi_to_params(vsi); - params.flags = ICE_VSI_FLAG_INIT; + err = ice_init_mac_fltr(pf); + if (err) + goto err_init_mac_fltr; - rtnl_lock(); - err = ice_vsi_cfg(vsi, ¶ms); + err = ice_devlink_create_pf_port(pf); if (err) - goto err_vsi_cfg; + goto err_devlink_create_pf_port; - err = ice_start_eth(ice_get_main_vsi(pf)); + SET_NETDEV_DEVLINK_PORT(vsi->netdev, &pf->devlink_port); + + err = ice_register_netdev(vsi); + if (err) + goto err_register_netdev; + + err = ice_tc_indir_block_register(vsi); if (err) - goto err_start_eth; - rtnl_unlock(); + goto err_tc_indir_block_register; + + ice_napi_add(vsi); err = ice_init_rdma(pf); if (err) @@ -4980,29 +5051,35 @@ int ice_load(struct ice_pf *pf) return 0; err_init_rdma: - ice_vsi_close(ice_get_main_vsi(pf)); - rtnl_lock(); -err_start_eth: - ice_vsi_decfg(ice_get_main_vsi(pf)); -err_vsi_cfg: - rtnl_unlock(); - ice_deinit_dev(pf); + ice_tc_indir_block_unregister(vsi); +err_tc_indir_block_register: + ice_unregister_netdev(vsi); +err_register_netdev: + ice_devlink_destroy_pf_port(pf); +err_devlink_create_pf_port: +err_init_mac_fltr: + ice_decfg_netdev(vsi); return err; } /** * ice_unload - unload pf by stopping VSI and deinit hw * @pf: pointer to the pf instance + * + * This function has to be called under devl_lock. */ void ice_unload(struct ice_pf *pf) { + struct ice_vsi *vsi = ice_get_main_vsi(pf); + + devl_assert_locked(priv_to_devlink(pf)); + ice_deinit_features(pf); ice_deinit_rdma(pf); - rtnl_lock(); - ice_stop_eth(ice_get_main_vsi(pf)); - ice_vsi_decfg(ice_get_main_vsi(pf)); - rtnl_unlock(); - ice_deinit_dev(pf); + ice_tc_indir_block_unregister(vsi); + ice_unregister_netdev(vsi); + ice_devlink_destroy_pf_port(pf); + ice_decfg_netdev(vsi); } /** @@ -5100,27 +5177,23 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) if (err) goto err_init; - err = ice_init_eth(pf); + devl_lock(priv_to_devlink(pf)); + err = ice_load(pf); + devl_unlock(priv_to_devlink(pf)); if (err) - goto err_init_eth; - - err = ice_init_rdma(pf); - if (err) - goto err_init_rdma; + goto err_load; err = ice_init_devlink(pf); if (err) goto err_init_devlink; - ice_init_features(pf); - return 0; err_init_devlink: - ice_deinit_rdma(pf); -err_init_rdma: - ice_deinit_eth(pf); -err_init_eth: + devl_lock(priv_to_devlink(pf)); + ice_unload(pf); + devl_unlock(priv_to_devlink(pf)); +err_load: ice_deinit(pf); err_init: pci_disable_device(pdev); @@ -5208,18 +5281,22 @@ static void ice_remove(struct pci_dev *pdev) ice_free_vfs(pf); } + ice_hwmon_exit(pf); + ice_service_task_stop(pf); ice_aq_cancel_waiting_tasks(pf); set_bit(ICE_DOWN, pf->state); if (!ice_is_safe_mode(pf)) ice_remove_arfs(pf); - ice_deinit_features(pf); + ice_deinit_devlink(pf); - ice_deinit_rdma(pf); - ice_deinit_eth(pf); - ice_deinit(pf); + devl_lock(priv_to_devlink(pf)); + ice_unload(pf); + devl_unlock(priv_to_devlink(pf)); + + ice_deinit(pf); ice_vsi_release_all(pf); ice_setup_mc_magic_wake(pf); @@ -5306,6 +5383,7 @@ static int ice_reinit_interrupt_scheme(struct ice_pf *pf) if (ret) goto err_reinit; ice_vsi_map_rings_to_vectors(pf->vsi[v]); + ice_vsi_set_napi_queues(pf->vsi[v]); } ret = ice_req_irq_msix_misc(pf); @@ -5611,6 +5689,10 @@ static const struct pci_device_id ice_pci_tbl[] = { { PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_1GBE) }, { PCI_VDEVICE(INTEL, ICE_DEV_ID_E823L_QSFP) }, { PCI_VDEVICE(INTEL, ICE_DEV_ID_E822_SI_DFLT) }, + { PCI_VDEVICE(INTEL, ICE_DEV_ID_E825C_BACKPLANE), }, + { PCI_VDEVICE(INTEL, ICE_DEV_ID_E825C_QSFP), }, + { PCI_VDEVICE(INTEL, ICE_DEV_ID_E825C_SFP), }, + { PCI_VDEVICE(INTEL, ICE_DEV_ID_E825C_SGMII), }, { PCI_VDEVICE(INTEL, ICE_DEV_ID_E830_BACKPLANE) }, { PCI_VDEVICE(INTEL, ICE_DEV_ID_E830_QSFP56) }, { PCI_VDEVICE(INTEL, ICE_DEV_ID_E830_SFP) }, @@ -5672,6 +5754,8 @@ static int __init ice_module_init(void) goto err_dest_wq; } + ice_debugfs_init(); + status = pci_register_driver(&ice_driver); if (status) { pr_err("failed to register PCI driver, err %d\n", status); @@ -5682,6 +5766,7 @@ static int __init ice_module_init(void) err_dest_lag_wq: destroy_workqueue(ice_lag_wq); + ice_debugfs_exit(); err_dest_wq: destroy_workqueue(ice_wq); return status; @@ -5697,6 +5782,7 @@ module_init(ice_module_init); static void __exit ice_module_exit(void) { pci_unregister_driver(&ice_driver); + ice_debugfs_exit(); destroy_workqueue(ice_wq); destroy_workqueue(ice_lag_wq); pr_info("module unloaded\n"); @@ -6041,6 +6127,23 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features) } /** + * ice_set_rx_rings_vlan_proto - update rings with new stripped VLAN proto + * @vsi: PF's VSI + * @vlan_ethertype: VLAN ethertype (802.1Q or 802.1ad) in network byte order + * + * Store current stripped VLAN proto in ring packet context, + * so it can be accessed more efficiently by packet processing code. + */ +static void +ice_set_rx_rings_vlan_proto(struct ice_vsi *vsi, __be16 vlan_ethertype) +{ + u16 i; + + ice_for_each_alloc_rxq(vsi, i) + vsi->rx_rings[i]->pkt_ctx.vlan_proto = vlan_ethertype; +} + +/** * ice_set_vlan_offload_features - set VLAN offload features for the PF VSI * @vsi: PF's VSI * @features: features used to determine VLAN offload settings @@ -6082,6 +6185,9 @@ ice_set_vlan_offload_features(struct ice_vsi *vsi, netdev_features_t features) if (strip_err || insert_err) return -EIO; + ice_set_rx_rings_vlan_proto(vsi, enable_stripping ? + htons(vlan_ethertype) : 0); + return 0; } @@ -6670,13 +6776,11 @@ void ice_update_vsi_stats(struct ice_vsi *vsi) cur_ns->rx_crc_errors = pf->stats.crc_errors; cur_ns->rx_errors = pf->stats.crc_errors + pf->stats.illegal_bytes + - pf->stats.rx_len_errors + pf->stats.rx_undersize + pf->hw_csum_rx_error + pf->stats.rx_jabber + pf->stats.rx_fragments + pf->stats.rx_oversize; - cur_ns->rx_length_errors = pf->stats.rx_len_errors; /* record drops from the port level */ cur_ns->rx_missed_errors = pf->stats.eth.rx_discards; } @@ -6816,9 +6920,6 @@ void ice_update_pf_stats(struct ice_pf *pf) &prev_ps->mac_remote_faults, &cur_ps->mac_remote_faults); - ice_stat_update32(hw, GLPRT_RLEC(port), pf->stat_prev_loaded, - &prev_ps->rx_len_errors, &cur_ps->rx_len_errors); - ice_stat_update32(hw, GLPRT_RUC(port), pf->stat_prev_loaded, &prev_ps->rx_undersize, &cur_ps->rx_undersize); @@ -6901,6 +7002,50 @@ static void ice_napi_disable_all(struct ice_vsi *vsi) } /** + * ice_vsi_dis_irq - Mask off queue interrupt generation on the VSI + * @vsi: the VSI being un-configured + */ +static void ice_vsi_dis_irq(struct ice_vsi *vsi) +{ + struct ice_pf *pf = vsi->back; + struct ice_hw *hw = &pf->hw; + u32 val; + int i; + + /* disable interrupt causation from each Rx queue; Tx queues are + * handled in ice_vsi_stop_tx_ring() + */ + if (vsi->rx_rings) { + ice_for_each_rxq(vsi, i) { + if (vsi->rx_rings[i]) { + u16 reg; + + reg = vsi->rx_rings[i]->reg_idx; + val = rd32(hw, QINT_RQCTL(reg)); + val &= ~QINT_RQCTL_CAUSE_ENA_M; + wr32(hw, QINT_RQCTL(reg), val); + } + } + } + + /* disable each interrupt */ + ice_for_each_q_vector(vsi, i) { + if (!vsi->q_vectors[i]) + continue; + wr32(hw, GLINT_DYN_CTL(vsi->q_vectors[i]->reg_idx), 0); + } + + ice_flush(hw); + + /* don't call synchronize_irq() for VF's from the host */ + if (vsi->type == ICE_VSI_VF) + return; + + ice_for_each_q_vector(vsi, i) + synchronize_irq(vsi->q_vectors[i]->irq.virq); +} + +/** * ice_down - Shutdown the connection * @vsi: The VSI being stopped * @@ -7389,7 +7534,7 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) * fail. */ if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) - ice_ptp_reset(pf); + ice_ptp_rebuild(pf, reset_type); if (ice_is_feature_supported(pf, ICE_F_GNSS)) ice_gnss_init(pf); @@ -7401,18 +7546,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) goto err_vsi_rebuild; } - /* configure PTP timestamping after VSI rebuild */ - if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags)) { - if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_SELF) - ice_ptp_cfg_timestamp(pf, false); - else if (pf->ptp.tx_interrupt_mode == ICE_PTP_TX_INTERRUPT_ALL) - /* for E82x PHC owner always need to have interrupts */ - ice_ptp_cfg_timestamp(pf, true); - } - - err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL); + err = ice_eswitch_rebuild(pf); if (err) { - dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err); + dev_err(dev, "Switchdev rebuild failed: %d\n", err); goto err_vsi_rebuild; } @@ -7461,6 +7597,9 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type) ice_plug_aux_dev(pf); if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG)) ice_lag_rebuild(pf); + + /* Restore timestamp mode settings after VSI rebuild */ + ice_ptp_restore_timestamp_mode(pf); return; err_vsi_rebuild: @@ -7710,6 +7849,59 @@ int ice_get_rss_key(struct ice_vsi *vsi, u8 *seed) } /** + * ice_set_rss_hfunc - Set RSS HASH function + * @vsi: Pointer to VSI structure + * @hfunc: hash function (ICE_AQ_VSI_Q_OPT_RSS_*) + * + * Returns 0 on success, negative on failure + */ +int ice_set_rss_hfunc(struct ice_vsi *vsi, u8 hfunc) +{ + struct ice_hw *hw = &vsi->back->hw; + struct ice_vsi_ctx *ctx; + bool symm; + int err; + + if (hfunc == vsi->rss_hfunc) + return 0; + + if (hfunc != ICE_AQ_VSI_Q_OPT_RSS_HASH_TPLZ && + hfunc != ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ) + return -EOPNOTSUPP; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + ctx->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_Q_OPT_VALID); + ctx->info.q_opt_rss = vsi->info.q_opt_rss; + ctx->info.q_opt_rss &= ~ICE_AQ_VSI_Q_OPT_RSS_HASH_M; + ctx->info.q_opt_rss |= + FIELD_PREP(ICE_AQ_VSI_Q_OPT_RSS_HASH_M, hfunc); + ctx->info.q_opt_tc = vsi->info.q_opt_tc; + ctx->info.q_opt_flags = vsi->info.q_opt_rss; + + err = ice_update_vsi(hw, vsi->idx, ctx, NULL); + if (err) { + dev_err(ice_pf_to_dev(vsi->back), "Failed to configure RSS hash for VSI %d, error %d\n", + vsi->vsi_num, err); + } else { + vsi->info.q_opt_rss = ctx->info.q_opt_rss; + vsi->rss_hfunc = hfunc; + netdev_info(vsi->netdev, "Hash function set to: %sToeplitz\n", + hfunc == ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ ? + "Symmetric " : ""); + } + kfree(ctx); + if (err) + return err; + + /* Fix the symmetry setting for all existing RSS configurations */ + symm = !!(hfunc == ICE_AQ_VSI_Q_OPT_RSS_HASH_SYM_TPLZ); + return ice_set_rss_cfg_symm(hw, vsi, symm); +} + +/** * ice_bridge_getlink - Get the hardware bridge mode * @skb: skb buff * @pid: process ID @@ -7806,6 +7998,8 @@ ice_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, pf_sw = pf->first_sw; /* find the attribute in the netlink message */ br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC); + if (!br_spec) + return -EINVAL; nla_for_each_nested(attr, br_spec, rem) { __u16 mode; @@ -7895,8 +8089,8 @@ static void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue) struct ice_hw *hw = &pf->hw; u32 head, val = 0; - head = (rd32(hw, QTX_COMM_HEAD(vsi->txq_map[txqueue])) & - QTX_COMM_HEAD_HEAD_M) >> QTX_COMM_HEAD_HEAD_S; + head = FIELD_GET(QTX_COMM_HEAD_HEAD_M, + rd32(hw, QTX_COMM_HEAD(vsi->txq_map[txqueue]))); /* Read interrupt register */ val = rd32(hw, GLINT_DYN_CTL(tx_ring->q_vector->reg_idx)); @@ -8144,13 +8338,12 @@ static int ice_add_vsi_to_fdir(struct ice_pf *pf, struct ice_vsi *vsi) for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) { enum ice_flow_priority prio; - u64 prof_id; /* add this VSI to FDir profile for this flow */ prio = ICE_FLOW_PRIO_NORMAL; prof = hw->fdir_prof[flow]; - prof_id = flow + tun * ICE_FLTR_PTYPE_MAX; - status = ice_flow_add_entry(hw, ICE_BLK_FD, prof_id, + status = ice_flow_add_entry(hw, ICE_BLK_FD, + prof->prof_id[tun], prof->vsi_h[0], vsi->idx, prio, prof->fdir_seg[tun], &entry_h); @@ -9193,8 +9386,14 @@ int ice_stop(struct net_device *netdev) int link_err = ice_force_phys_link_state(vsi, false); if (link_err) { - netdev_err(vsi->netdev, "Failed to set physical link down, VSI %d error %d\n", - vsi->vsi_num, link_err); + if (link_err == -ENOMEDIUM) + netdev_info(vsi->netdev, "Skipping link reconfig - no media attached, VSI %d\n", + vsi->vsi_num); + else + netdev_err(vsi->netdev, "Failed to set physical link down, VSI %d error %d\n", + vsi->vsi_num, link_err); + + ice_vsi_close(vsi); return -EIO; } } |