diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_main.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_main.c | 357 | 
1 files changed, 64 insertions, 293 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 42c318ceff61..93979ab18bc1 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -2490,7 +2490,6 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)  {  	int q_vectors = vsi->num_q_vectors;  	struct ice_pf *pf = vsi->back; -	int base = vsi->base_vector;  	struct device *dev;  	int rx_int_idx = 0;  	int tx_int_idx = 0; @@ -2501,7 +2500,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)  	for (vector = 0; vector < q_vectors; vector++) {  		struct ice_q_vector *q_vector = vsi->q_vectors[vector]; -		irq_num = pf->msix_entries[base + vector].vector; +		irq_num = q_vector->irq.virq;  		if (q_vector->tx.tx_ring && q_vector->rx.rx_ring) {  			snprintf(q_vector->name, sizeof(q_vector->name) - 1, @@ -2555,9 +2554,8 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)  	return 0;  free_q_irqs: -	while (vector) { -		vector--; -		irq_num = pf->msix_entries[base + vector].vector; +	while (vector--) { +		irq_num = vsi->q_vectors[vector]->irq.virq;  		if (!IS_ENABLED(CONFIG_RFS_ACCEL))  			irq_set_affinity_notifier(irq_num, NULL);  		irq_set_affinity_hint(irq_num, NULL); @@ -2635,11 +2633,11 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)  	int i;  	old_prog = xchg(&vsi->xdp_prog, prog); -	if (old_prog) -		bpf_prog_put(old_prog); -  	ice_for_each_rxq(vsi, i)  		WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog); + +	if (old_prog) +		bpf_prog_put(old_prog);  }  /** @@ -2924,6 +2922,12 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,  		}  	} +	/* hot swap progs and avoid toggling link */ +	if (ice_is_xdp_ena_vsi(vsi) == !!prog) { +		ice_vsi_assign_bpf_prog(vsi, prog); +		return 0; +	} +  	/* need to stop netdev while setting up the program for Rx rings */  	if (if_running && !test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {  		ret = ice_down(vsi); @@ -2956,13 +2960,6 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,  		xdp_ring_err = ice_realloc_zc_buf(vsi, false);  		if (xdp_ring_err)  			NL_SET_ERR_MSG_MOD(extack, "Freeing XDP Rx resources failed"); -	} else { -		/* safe to call even when prog == vsi->xdp_prog as -		 * dev_xdp_install in net/core/dev.c incremented prog's -		 * refcount so corresponding bpf_prog_put won't cause -		 * underflow -		 */ -		ice_vsi_assign_bpf_prog(vsi, prog);  	}  	if (if_running) @@ -3047,7 +3044,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)  	wr32(hw, PFINT_OICR_ENA, val);  	/* SW_ITR_IDX = 0, but don't change INTENA */ -	wr32(hw, GLINT_DYN_CTL(pf->oicr_idx), +	wr32(hw, GLINT_DYN_CTL(pf->oicr_irq.index),  	     GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);  } @@ -3060,7 +3057,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)  {  	struct ice_pf *pf = (struct ice_pf *)data;  	struct ice_hw *hw = &pf->hw; -	irqreturn_t ret = IRQ_NONE;  	struct device *dev;  	u32 oicr, ena_mask; @@ -3142,19 +3138,24 @@ 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) -			ret = IRQ_WAKE_THREAD; +			set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);  	}  	if (oicr & PFINT_OICR_TSYN_EVNT_M) {  		u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;  		u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx)); -		/* Save EVENTs from GTSYN register */ -		pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M | -						     GLTSYN_STAT_EVENT1_M | -						     GLTSYN_STAT_EVENT2_M);  		ena_mask &= ~PFINT_OICR_TSYN_EVNT_M; -		kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work); + +		if (hw->func_caps.ts_func_info.src_tmr_owned) { +			/* Save EVENTs from GLTSYN register */ +			pf->ptp.ext_ts_irq |= gltsyn_stat & +					      (GLTSYN_STAT_EVENT0_M | +					       GLTSYN_STAT_EVENT1_M | +					       GLTSYN_STAT_EVENT2_M); + +			set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); +		}  	}  #define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M) @@ -3174,16 +3175,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)  		if (oicr & (PFINT_OICR_PCI_EXCEPTION_M |  			    PFINT_OICR_ECC_ERR_M)) {  			set_bit(ICE_PFR_REQ, pf->state); -			ice_service_task_schedule(pf);  		}  	} -	if (!ret) -		ret = IRQ_HANDLED; -	ice_service_task_schedule(pf); -	ice_irq_dynamic_ena(hw, NULL, NULL); - -	return ret; +	return IRQ_WAKE_THREAD;  }  /** @@ -3194,12 +3189,29 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data)  static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data)  {  	struct ice_pf *pf = data; +	struct ice_hw *hw; + +	hw = &pf->hw;  	if (ice_is_reset_in_progress(pf->state))  		return IRQ_HANDLED; -	while (!ice_ptp_process_ts(pf)) -		usleep_range(50, 100); +	ice_service_task_schedule(pf); + +	if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) +		ice_ptp_extts_event(pf); + +	if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { +		/* Process outstanding Tx timestamps. If there is more work, +		 * re-arm the interrupt to trigger again. +		 */ +		if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) { +			wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); +			ice_flush(hw); +		} +	} + +	ice_irq_dynamic_ena(hw, NULL, NULL);  	return IRQ_HANDLED;  } @@ -3234,6 +3246,7 @@ static void ice_dis_ctrlq_interrupts(struct ice_hw *hw)   */  static void ice_free_irq_msix_misc(struct ice_pf *pf)  { +	int misc_irq_num = pf->oicr_irq.virq;  	struct ice_hw *hw = &pf->hw;  	ice_dis_ctrlq_interrupts(hw); @@ -3242,14 +3255,10 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)  	wr32(hw, PFINT_OICR_ENA, 0);  	ice_flush(hw); -	if (pf->msix_entries) { -		synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); -		devm_free_irq(ice_pf_to_dev(pf), -			      pf->msix_entries[pf->oicr_idx].vector, pf); -	} +	synchronize_irq(misc_irq_num); +	devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf); -	pf->num_avail_sw_msix += 1; -	ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID); +	ice_free_irq(pf, pf->oicr_irq);  }  /** @@ -3295,7 +3304,8 @@ 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; -	int oicr_idx, err = 0; +	struct msi_map oicr_irq; +	int err = 0;  	if (!pf->int_name[0])  		snprintf(pf->int_name, sizeof(pf->int_name) - 1, "%s-%s:misc", @@ -3309,30 +3319,26 @@ 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_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); -	if (oicr_idx < 0) -		return oicr_idx; - -	pf->num_avail_sw_msix -= 1; -	pf->oicr_idx = (u16)oicr_idx; - -	err = devm_request_threaded_irq(dev, -					pf->msix_entries[pf->oicr_idx].vector, -					ice_misc_intr, ice_misc_intr_thread_fn, -					0, pf->int_name, pf); +	oicr_irq = ice_alloc_irq(pf, false); +	if (oicr_irq.index < 0) +		return oicr_irq.index; + +	pf->oicr_irq = oicr_irq; +	err = devm_request_threaded_irq(dev, pf->oicr_irq.virq, ice_misc_intr, +					ice_misc_intr_thread_fn, 0, +					pf->int_name, pf);  	if (err) {  		dev_err(dev, "devm_request_threaded_irq for %s failed: %d\n",  			pf->int_name, err); -		ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); -		pf->num_avail_sw_msix += 1; +		ice_free_irq(pf, pf->oicr_irq);  		return err;  	}  skip_req_irq:  	ice_ena_misc_vector(pf); -	ice_ena_ctrlq_interrupts(hw, pf->oicr_idx); -	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx), +	ice_ena_ctrlq_interrupts(hw, pf->oicr_irq.index); +	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_irq.index),  	     ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);  	ice_flush(hw); @@ -3901,224 +3907,6 @@ static int ice_init_pf(struct ice_pf *pf)  }  /** - * ice_reduce_msix_usage - Reduce usage of MSI-X vectors - * @pf: board private structure - * @v_remain: number of remaining MSI-X vectors to be distributed - * - * Reduce the usage of MSI-X vectors when entire request cannot be fulfilled. - * pf->num_lan_msix and pf->num_rdma_msix values are set based on number of - * remaining vectors. - */ -static void ice_reduce_msix_usage(struct ice_pf *pf, int v_remain) -{ -	int v_rdma; - -	if (!ice_is_rdma_ena(pf)) { -		pf->num_lan_msix = v_remain; -		return; -	} - -	/* RDMA needs at least 1 interrupt in addition to AEQ MSIX */ -	v_rdma = ICE_RDMA_NUM_AEQ_MSIX + 1; - -	if (v_remain < ICE_MIN_LAN_TXRX_MSIX + ICE_MIN_RDMA_MSIX) { -		dev_warn(ice_pf_to_dev(pf), "Not enough MSI-X vectors to support RDMA.\n"); -		clear_bit(ICE_FLAG_RDMA_ENA, pf->flags); - -		pf->num_rdma_msix = 0; -		pf->num_lan_msix = ICE_MIN_LAN_TXRX_MSIX; -	} else if ((v_remain < ICE_MIN_LAN_TXRX_MSIX + v_rdma) || -		   (v_remain - v_rdma < v_rdma)) { -		/* Support minimum RDMA and give remaining vectors to LAN MSIX */ -		pf->num_rdma_msix = ICE_MIN_RDMA_MSIX; -		pf->num_lan_msix = v_remain - ICE_MIN_RDMA_MSIX; -	} else { -		/* Split remaining MSIX with RDMA after accounting for AEQ MSIX -		 */ -		pf->num_rdma_msix = (v_remain - ICE_RDMA_NUM_AEQ_MSIX) / 2 + -				    ICE_RDMA_NUM_AEQ_MSIX; -		pf->num_lan_msix = v_remain - pf->num_rdma_msix; -	} -} - -/** - * ice_ena_msix_range - Request a range of MSIX vectors from the OS - * @pf: board private structure - * - * Compute the number of MSIX vectors wanted and request from the OS. Adjust - * device usage if there are not enough vectors. Return the number of vectors - * reserved or negative on failure. - */ -static int ice_ena_msix_range(struct ice_pf *pf) -{ -	int num_cpus, hw_num_msix, v_other, v_wanted, v_actual; -	struct device *dev = ice_pf_to_dev(pf); -	int err, i; - -	hw_num_msix = pf->hw.func_caps.common_cap.num_msix_vectors; -	num_cpus = num_online_cpus(); - -	/* LAN miscellaneous handler */ -	v_other = ICE_MIN_LAN_OICR_MSIX; - -	/* Flow Director */ -	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) -		v_other += ICE_FDIR_MSIX; - -	/* switchdev */ -	v_other += ICE_ESWITCH_MSIX; - -	v_wanted = v_other; - -	/* LAN traffic */ -	pf->num_lan_msix = num_cpus; -	v_wanted += pf->num_lan_msix; - -	/* RDMA auxiliary driver */ -	if (ice_is_rdma_ena(pf)) { -		pf->num_rdma_msix = num_cpus + ICE_RDMA_NUM_AEQ_MSIX; -		v_wanted += pf->num_rdma_msix; -	} - -	if (v_wanted > hw_num_msix) { -		int v_remain; - -		dev_warn(dev, "not enough device MSI-X vectors. wanted = %d, available = %d\n", -			 v_wanted, hw_num_msix); - -		if (hw_num_msix < ICE_MIN_MSIX) { -			err = -ERANGE; -			goto exit_err; -		} - -		v_remain = hw_num_msix - v_other; -		if (v_remain < ICE_MIN_LAN_TXRX_MSIX) { -			v_other = ICE_MIN_MSIX - ICE_MIN_LAN_TXRX_MSIX; -			v_remain = ICE_MIN_LAN_TXRX_MSIX; -		} - -		ice_reduce_msix_usage(pf, v_remain); -		v_wanted = pf->num_lan_msix + pf->num_rdma_msix + v_other; - -		dev_notice(dev, "Reducing request to %d MSI-X vectors for LAN traffic.\n", -			   pf->num_lan_msix); -		if (ice_is_rdma_ena(pf)) -			dev_notice(dev, "Reducing request to %d MSI-X vectors for RDMA.\n", -				   pf->num_rdma_msix); -	} - -	pf->msix_entries = devm_kcalloc(dev, v_wanted, -					sizeof(*pf->msix_entries), GFP_KERNEL); -	if (!pf->msix_entries) { -		err = -ENOMEM; -		goto exit_err; -	} - -	for (i = 0; i < v_wanted; i++) -		pf->msix_entries[i].entry = i; - -	/* actually reserve the vectors */ -	v_actual = pci_enable_msix_range(pf->pdev, pf->msix_entries, -					 ICE_MIN_MSIX, v_wanted); -	if (v_actual < 0) { -		dev_err(dev, "unable to reserve MSI-X vectors\n"); -		err = v_actual; -		goto msix_err; -	} - -	if (v_actual < v_wanted) { -		dev_warn(dev, "not enough OS MSI-X vectors. requested = %d, obtained = %d\n", -			 v_wanted, v_actual); - -		if (v_actual < ICE_MIN_MSIX) { -			/* error if we can't get minimum vectors */ -			pci_disable_msix(pf->pdev); -			err = -ERANGE; -			goto msix_err; -		} else { -			int v_remain = v_actual - v_other; - -			if (v_remain < ICE_MIN_LAN_TXRX_MSIX) -				v_remain = ICE_MIN_LAN_TXRX_MSIX; - -			ice_reduce_msix_usage(pf, v_remain); - -			dev_notice(dev, "Enabled %d MSI-X vectors for LAN traffic.\n", -				   pf->num_lan_msix); - -			if (ice_is_rdma_ena(pf)) -				dev_notice(dev, "Enabled %d MSI-X vectors for RDMA.\n", -					   pf->num_rdma_msix); -		} -	} - -	return v_actual; - -msix_err: -	devm_kfree(dev, pf->msix_entries); - -exit_err: -	pf->num_rdma_msix = 0; -	pf->num_lan_msix = 0; -	return err; -} - -/** - * ice_dis_msix - Disable MSI-X interrupt setup in OS - * @pf: board private structure - */ -static void ice_dis_msix(struct ice_pf *pf) -{ -	pci_disable_msix(pf->pdev); -	devm_kfree(ice_pf_to_dev(pf), pf->msix_entries); -	pf->msix_entries = NULL; -} - -/** - * ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme - * @pf: board private structure - */ -static void ice_clear_interrupt_scheme(struct ice_pf *pf) -{ -	ice_dis_msix(pf); - -	if (pf->irq_tracker) { -		devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker); -		pf->irq_tracker = NULL; -	} -} - -/** - * ice_init_interrupt_scheme - Determine proper interrupt scheme - * @pf: board private structure to initialize - */ -static int ice_init_interrupt_scheme(struct ice_pf *pf) -{ -	int vectors; - -	vectors = ice_ena_msix_range(pf); - -	if (vectors < 0) -		return vectors; - -	/* set up vector assignment tracking */ -	pf->irq_tracker = devm_kzalloc(ice_pf_to_dev(pf), -				       struct_size(pf->irq_tracker, list, vectors), -				       GFP_KERNEL); -	if (!pf->irq_tracker) { -		ice_dis_msix(pf); -		return -ENOMEM; -	} - -	/* populate SW interrupts pool with number of OS granted IRQs. */ -	pf->num_avail_sw_msix = (u16)vectors; -	pf->irq_tracker->num_entries = (u16)vectors; -	pf->irq_tracker->end = pf->irq_tracker->num_entries; - -	return 0; -} - -/**   * ice_is_wol_supported - check if WoL is supported   * @hw: pointer to hardware info   * @@ -5835,11 +5623,6 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)  	if (!is_valid_ether_addr(mac))  		return -EADDRNOTAVAIL; -	if (ether_addr_equal(netdev->dev_addr, mac)) { -		netdev_dbg(netdev, "already using mac %pM\n", mac); -		return 0; -	} -  	if (test_bit(ICE_DOWN, pf->state) ||  	    ice_is_reset_in_progress(pf->state)) {  		netdev_err(netdev, "can't set mac %pM. device not ready\n", @@ -7629,21 +7412,9 @@ static int ice_change_mtu(struct net_device *netdev, int new_mtu)  	}  	netdev->mtu = (unsigned int)new_mtu; - -	/* if VSI is up, bring it down and then back up */ -	if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) { -		err = ice_down(vsi); -		if (err) { -			netdev_err(netdev, "change MTU if_down err %d\n", err); -			return err; -		} - -		err = ice_up(vsi); -		if (err) { -			netdev_err(netdev, "change MTU if_up err %d\n", err); -			return err; -		} -	} +	err = ice_down_up(vsi); +	if (err) +		return err;  	netdev_dbg(netdev, "changed MTU to %d\n", new_mtu);  	set_bit(ICE_FLAG_MTU_CHANGED, pf->flags);  |