Commit cbe66bfe authored by Brett Creeley's avatar Brett Creeley Committed by Jeff Kirsher
Browse files

ice: Refactor interrupt tracking



Currently we have two MSI-x (IRQ) trackers, one for OS requested MSI-x
entries (sw_irq_tracker) and one for hardware MSI-x vectors
(hw_irq_tracker). Generally the sw_irq_tracker has less entries than the
hw_irq_tracker because the hw_irq_tracker has entries equal to the max
allowed MSI-x per PF and the sw_irq_tracker is mainly the minimum (non
SR-IOV portion of the vectors, kernel granted IRQs). All of the non
SR-IOV portions of the driver (i.e. LAN queues, RDMA queues, OICR, etc.)
take at least one of each type of tracker resource. SR-IOV only grabs
entries from the hw_irq_tracker. There are a few issues with this approach
that can be seen when doing any kind of device reconfiguration (i.e.
ethtool -L, SR-IOV, etc.). One of them being, any time the driver creates
an ice_q_vector and associates it to a LAN queue pair it will grab and
use one entry from the hw_irq_tracker and one from the sw_irq_tracker.
If the indices on these does not match it will cause a Tx timeout, which
will cause a reset and then the indices will match up again and traffic
will resume. The mismatched indices come from the trackers not being the
same size and/or the search_hint in the two trackers not being equal.
Another reason for the refactor is the co-existence of features with
SR-IOV. If SR-IOV is enabled and the interrupts are taken from the end
of the sw_irq_tracker then other features can no longer use this space
because the hardware has now given the remaining interrupts to SR-IOV.

This patch reworks how we track MSI-x vectors by removing the
hw_irq_tracker completely and instead MSI-x resources needed for SR-IOV
are determined all at once instead of per VF. This can be done because
when creating VFs we know how many are wanted and how many MSI-x vectors
each VF needs. This also allows us to start using MSI-x resources from
the end of the PF's allowed MSI-x vectors so we are less likely to use
entries needed for other features (i.e. RDMA, L2 Offload, etc).

This patch also reworks the ice_res_tracker structure by removing the
search_hint and adding a new member - "end". Instead of having a
search_hint we will always search from 0. The new member, "end", will be
used to manipulate the end of the ice_res_tracker (specifically
sw_irq_tracker) during runtime based on MSI-x vectors needed by SR-IOV.
In the normal case, the end of ice_res_tracker will be equal to the
ice_res_tracker's num_entries.

The sriov_base_vector member was added to the PF structure. It is used
to represent the starting MSI-x index of all the needed MSI-x vectors
for all SR-IOV VFs. Depending on how many MSI-x are needed, SR-IOV may
have to take resources from the sw_irq_tracker. This is done by setting
the sw_irq_tracker->end equal to the pf->sriov_base_vector. When all
SR-IOV VFs are removed then the sw_irq_tracker->end is reset back to
sw_irq_tracker->num_entries. The sriov_base_vector, along with the VF's
number of MSI-x (pf->num_vf_msix), vf_id, and the base MSI-x index on
the PF (pf->hw.func_caps.common_cap.msix_vector_first_id), is used to
calculate the first HW absolute MSI-x index for each VF, which is used
to write to the VPINT_ALLOC[_PCI] and GLINT_VECT2FUNC registers to
program the VFs MSI-x PCI configuration bits. Also, the sriov_base_vector
is used along with VF's num_vf_msix, vf_id, and q_vector->v_idx to
determine the MSI-x register index (used for writing to GLINT_DYN_CTL)
within the PF's space.

Interrupt changes removed any references to hw_base_vector, hw_oicr_idx,
and hw_irq_tracker. Only sw_base_vector, sw_oicr_idx, and sw_irq_tracker
variables remain. Change all of these by removing the "sw_" prefix to
help avoid confusion with these variables and their use.

Signed-off-by: default avatarBrett Creeley <brett.creeley@intel.com>
Signed-off-by: default avatarAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 0e674aeb
Loading
Loading
Loading
Loading
+10 −11
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ struct ice_tc_cfg {

struct ice_res_tracker {
	u16 num_entries;
	u16 search_hint;
	u16 end;
	u16 list[1];
};

@@ -252,8 +252,7 @@ struct ice_vsi {
	u32 rx_buf_failed;
	u32 rx_page_failed;
	int num_q_vectors;
	int sw_base_vector;		/* Irq base for OS reserved vectors */
	int hw_base_vector;		/* HW (absolute) index of a vector */
	int base_vector;		/* IRQ base for OS reserved vectors */
	enum ice_vsi_type type;
	u16 vsi_num;			/* HW (absolute) index of this VSI */
	u16 idx;			/* software index in pf->vsi[] */
@@ -348,10 +347,12 @@ struct ice_pf {

	/* OS reserved IRQ details */
	struct msix_entry *msix_entries;
	struct ice_res_tracker *sw_irq_tracker;

	/* HW reserved Interrupts for this PF */
	struct ice_res_tracker *hw_irq_tracker;
	struct ice_res_tracker *irq_tracker;
	/* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the
	 * number of MSIX vectors needed for all SR-IOV VFs from the number of
	 * MSIX vectors allowed on this PF.
	 */
	u16 sriov_base_vector;

	struct ice_vsi **vsi;		/* VSIs created by the driver */
	struct ice_sw *first_sw;	/* first switch created by firmware */
@@ -373,10 +374,8 @@ struct ice_pf {
	struct mutex sw_mutex;		/* lock for protecting VSI alloc flow */
	u32 msg_enable;
	u32 hw_csum_rx_error;
	u32 sw_oicr_idx;	/* Other interrupt cause SW vector index */
	u32 oicr_idx;		/* Other interrupt cause MSIX vector index */
	u32 num_avail_sw_msix;	/* remaining MSIX SW vectors left unclaimed */
	u32 hw_oicr_idx;	/* Other interrupt cause vector HW index */
	u32 num_avail_hw_msix;	/* remaining HW MSIX vectors left unclaimed */
	u32 num_lan_msix;	/* Total MSIX vectors for base driver */
	u16 num_lan_tx;		/* num LAN Tx queues setup */
	u16 num_lan_rx;		/* num LAN Rx queues setup */
@@ -418,7 +417,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
		    struct ice_q_vector *q_vector)
{
	u32 vector = (vsi && q_vector) ? q_vector->reg_idx :
				((struct ice_pf *)hw->back)->hw_oicr_idx;
				((struct ice_pf *)hw->back)->oicr_idx;
	int itr = ICE_ITR_NONE;
	u32 val;

+2 −3
Original line number Diff line number Diff line
@@ -772,7 +772,7 @@ static u64 ice_intr_test(struct net_device *netdev)

	netdev_info(netdev, "interrupt test\n");

	wr32(&pf->hw, GLINT_DYN_CTL(pf->sw_oicr_idx),
	wr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx),
	     GLINT_DYN_CTL_SW_ITR_INDX_M |
	     GLINT_DYN_CTL_INTENA_MSK_M |
	     GLINT_DYN_CTL_SWINT_TRIG_M);
@@ -2987,8 +2987,7 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,

		if (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) {
			rc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high;
			wr32(&pf->hw, GLINT_RATE(vsi->hw_base_vector +
						 rc->ring->q_vector->v_idx),
			wr32(&pf->hw, GLINT_RATE(rc->ring->q_vector->reg_idx),
			     ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high,
						   pf->hw.intrl_gran));
		}
+52 −127
Original line number Diff line number Diff line
@@ -1168,62 +1168,33 @@ err_out:
static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
{
	struct ice_pf *pf = vsi->back;
	int num_q_vectors = 0;
	u16 num_q_vectors;

	if (vsi->sw_base_vector || vsi->hw_base_vector) {
		dev_dbg(&pf->pdev->dev, "VSI %d has non-zero HW base vector %d or SW base vector %d\n",
			vsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector);
	/* SRIOV doesn't grab irq_tracker entries for each VSI */
	if (vsi->type == ICE_VSI_VF)
		return 0;

	if (vsi->base_vector) {
		dev_dbg(&pf->pdev->dev, "VSI %d has non-zero base vector %d\n",
			vsi->vsi_num, vsi->base_vector);
		return -EEXIST;
	}

	if (!test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
		return -ENOENT;

	switch (vsi->type) {
	case ICE_VSI_PF:
	num_q_vectors = vsi->num_q_vectors;
	/* reserve slots from OS requested IRQs */
		vsi->sw_base_vector = ice_get_res(pf, pf->sw_irq_tracker,
						  num_q_vectors, vsi->idx);
		if (vsi->sw_base_vector < 0) {
	vsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors,
				       vsi->idx);
	if (vsi->base_vector < 0) {
		dev_err(&pf->pdev->dev,
				"Failed to get tracking for %d SW vectors for VSI %d, err=%d\n",
				num_q_vectors, vsi->vsi_num,
				vsi->sw_base_vector);
			"Failed to get tracking for %d vectors for VSI %d, err=%d\n",
			num_q_vectors, vsi->vsi_num, vsi->base_vector);
		return -ENOENT;
	}
	pf->num_avail_sw_msix -= num_q_vectors;

		/* reserve slots from HW interrupts */
		vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker,
						  num_q_vectors, vsi->idx);
		break;
	case ICE_VSI_VF:
		/* take VF misc vector and data vectors into account */
		num_q_vectors = pf->num_vf_msix;
		/* For VF VSI, reserve slots only from HW interrupts */
		vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker,
						  num_q_vectors, vsi->idx);
		break;
	default:
		dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type);
		break;
	}

	if (vsi->hw_base_vector < 0) {
		dev_err(&pf->pdev->dev,
			"Failed to get tracking for %d HW vectors for VSI %d, err=%d\n",
			num_q_vectors, vsi->vsi_num, vsi->hw_base_vector);
		if (vsi->type != ICE_VSI_VF) {
			ice_free_res(pf->sw_irq_tracker,
				     vsi->sw_base_vector, vsi->idx);
			pf->num_avail_sw_msix += num_q_vectors;
		}
		return -ENOENT;
	}

	pf->num_avail_hw_msix -= num_q_vectors;

	return 0;
}

@@ -2261,7 +2232,14 @@ ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)
			goto clear_reg_idx;
		}

		q_vector->reg_idx = q_vector->v_idx + vsi->hw_base_vector;
		if (vsi->type == ICE_VSI_VF) {
			struct ice_vf *vf = &vsi->back->vf[vsi->vf_id];

			q_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);
		} else {
			q_vector->reg_idx =
				q_vector->v_idx + vsi->base_vector;
		}
	}

	return 0;
@@ -2416,17 +2394,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
		if (ret)
			goto unroll_alloc_q_vector;

		/* Setup Vector base only during VF init phase or when VF asks
		 * for more vectors than assigned number. In all other cases,
		 * assign hw_base_vector to the value given earlier.
		 */
		if (test_bit(ICE_VF_STATE_CFG_INTR, pf->vf[vf_id].vf_states)) {
			ret = ice_vsi_setup_vector_base(vsi);
			if (ret)
				goto unroll_vector_base;
		} else {
			vsi->hw_base_vector = pf->vf[vf_id].first_vector_idx;
		}
		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
		if (ret)
			goto unroll_vector_base;
@@ -2470,11 +2437,8 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,

unroll_vector_base:
	/* reclaim SW interrupts back to the common pool */
	ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
	ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
	pf->num_avail_sw_msix += vsi->num_q_vectors;
	/* reclaim HW interrupt back to the common pool */
	ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);
	pf->num_avail_hw_msix += vsi->num_q_vectors;
unroll_alloc_q_vector:
	ice_vsi_free_q_vectors(vsi);
unroll_vsi_init:
@@ -2495,17 +2459,17 @@ unroll_get_qs:
static void ice_vsi_release_msix(struct ice_vsi *vsi)
{
	struct ice_pf *pf = vsi->back;
	u16 vector = vsi->hw_base_vector;
	struct ice_hw *hw = &pf->hw;
	u32 txq = 0;
	u32 rxq = 0;
	int i, q;

	for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
	for (i = 0; i < vsi->num_q_vectors; i++) {
		struct ice_q_vector *q_vector = vsi->q_vectors[i];
		u16 reg_idx = q_vector->reg_idx;

		wr32(hw, GLINT_ITR(ICE_IDX_ITR0, vector), 0);
		wr32(hw, GLINT_ITR(ICE_IDX_ITR1, vector), 0);
		wr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0);
		wr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0);
		for (q = 0; q < q_vector->num_ring_tx; q++) {
			wr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);
			txq++;
@@ -2527,7 +2491,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)
void ice_vsi_free_irq(struct ice_vsi *vsi)
{
	struct ice_pf *pf = vsi->back;
	int base = vsi->sw_base_vector;
	int base = vsi->base_vector;

	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
		int i;
@@ -2623,11 +2587,11 @@ int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
	int count = 0;
	int i;

	if (!res || index >= res->num_entries)
	if (!res || index >= res->end)
		return -EINVAL;

	id |= ICE_RES_VALID_BIT;
	for (i = index; i < res->num_entries && res->list[i] == id; i++) {
	for (i = index; i < res->end && res->list[i] == id; i++) {
		res->list[i] = 0;
		count++;
	}
@@ -2645,10 +2609,9 @@ int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
 */
static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
{
	int start = res->search_hint;
	int end = start;
	int start = 0, end = 0;

	if ((start + needed) > res->num_entries)
	if (needed > res->end)
		return -ENOMEM;

	id |= ICE_RES_VALID_BIT;
@@ -2657,7 +2620,7 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
		/* skip already allocated entries */
		if (res->list[end++] & ICE_RES_VALID_BIT) {
			start = end;
			if ((start + needed) > res->num_entries)
			if ((start + needed) > res->end)
				break;
		}

@@ -2668,13 +2631,9 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
			while (i != end)
				res->list[i++] = id;

			if (end == res->num_entries)
				end = 0;

			res->search_hint = end;
			return start;
		}
	} while (1);
	} while (end < res->end);

	return -ENOMEM;
}
@@ -2686,16 +2645,11 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
 * @needed: size of the block needed
 * @id: identifier to track owner
 *
 * Returns the base item index of the block, or -ENOMEM for error
 * The search_hint trick and lack of advanced fit-finding only works
 * because we're highly likely to have all the same sized requests.
 * Linear search time and any fragmentation should be minimal.
 * Returns the base item index of the block, or negative for error
 */
int
ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
{
	int ret;

	if (!res || !pf)
		return -EINVAL;

@@ -2706,16 +2660,7 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
		return -EINVAL;
	}

	/* search based on search_hint */
	ret = ice_search_res(res, needed, id);

	if (ret < 0) {
		/* previous search failed. Reset search hint and try again */
		res->search_hint = 0;
		ret = ice_search_res(res, needed, id);
	}

	return ret;
	return ice_search_res(res, needed, id);
}

/**
@@ -2724,7 +2669,7 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)
 */
void ice_vsi_dis_irq(struct ice_vsi *vsi)
{
	int base = vsi->sw_base_vector;
	int base = vsi->base_vector;
	struct ice_pf *pf = vsi->back;
	struct ice_hw *hw = &pf->hw;
	u32 val;
@@ -2777,15 +2722,12 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
 */
int ice_vsi_release(struct ice_vsi *vsi)
{
	struct ice_vf *vf = NULL;
	struct ice_pf *pf;

	if (!vsi->back)
		return -ENODEV;
	pf = vsi->back;

	if (vsi->type == ICE_VSI_VF)
		vf = &pf->vf[vsi->vf_id];
	/* do not unregister while driver is in the reset recovery pending
	 * state. Since reset/rebuild happens through PF service task workqueue,
	 * it's not a good idea to unregister netdev that is associated to the
@@ -2803,21 +2745,15 @@ int ice_vsi_release(struct ice_vsi *vsi)
		ice_vsi_dis_irq(vsi);
	ice_vsi_close(vsi);

	/* reclaim interrupt vectors back to PF */
	/* SR-IOV determines needed MSIX resources all at once instead of per
	 * VSI since when VFs are spawned we know how many VFs there are and how
	 * many interrupts each VF needs. SR-IOV MSIX resources are also
	 * cleared in the same manner.
	 */
	if (vsi->type != ICE_VSI_VF) {
		/* reclaim SW interrupts back to the common pool */
		ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
		pf->num_avail_sw_msix += vsi->num_q_vectors;
		/* reclaim HW interrupts back to the common pool */
		ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);
		pf->num_avail_hw_msix += vsi->num_q_vectors;
	} else if (test_bit(ICE_VF_STATE_CFG_INTR, vf->vf_states)) {
		/* Reclaim VF resources back only while freeing all VFs or
		 * vector reassignment is requested
		 */
		ice_free_res(pf->hw_irq_tracker, vf->first_vector_idx,
			     vsi->idx);
		pf->num_avail_hw_msix += pf->num_vf_msix;
	}

	if (vsi->type == ICE_VSI_PF)
@@ -2873,24 +2809,17 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)
	ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
	ice_vsi_free_q_vectors(vsi);

	/* SR-IOV determines needed MSIX resources all at once instead of per
	 * VSI since when VFs are spawned we know how many VFs there are and how
	 * many interrupts each VF needs. SR-IOV MSIX resources are also
	 * cleared in the same manner.
	 */
	if (vsi->type != ICE_VSI_VF) {
		/* reclaim SW interrupts back to the common pool */
		ice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
		ice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);
		pf->num_avail_sw_msix += vsi->num_q_vectors;
		vsi->sw_base_vector = 0;
		/* reclaim HW interrupts back to the common pool */
		ice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector,
			     vsi->idx);
		pf->num_avail_hw_msix += vsi->num_q_vectors;
	} else {
		/* Reclaim VF resources back to the common pool for reset and
		 * and rebuild, with vector reassignment
		 */
		ice_free_res(pf->hw_irq_tracker, vf->first_vector_idx,
			     vsi->idx);
		pf->num_avail_hw_msix += pf->num_vf_msix;
		vsi->base_vector = 0;
	}
	vsi->hw_base_vector = 0;

	ice_vsi_clear_rings(vsi);
	ice_vsi_free_arrays(vsi);
@@ -2916,10 +2845,6 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)
		if (ret)
			goto err_rings;

		ret = ice_vsi_setup_vector_base(vsi);
		if (ret)
			goto err_vectors;

		ret = ice_vsi_set_q_vectors_reg_idx(vsi);
		if (ret)
			goto err_vectors;
+22 −60
Original line number Diff line number Diff line
@@ -95,7 +95,7 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)
				/* Trigger sw interrupt to revive the queue */
				v_idx = tx_ring->q_vector->v_idx;
				wr32(&vsi->back->hw,
				     GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),
				     GLINT_DYN_CTL(vsi->base_vector + v_idx),
				     (itr << GLINT_DYN_CTL_ITR_INDX_S) |
				     GLINT_DYN_CTL_SWINT_TRIG_M |
				     GLINT_DYN_CTL_INTENA_MSK_M);
@@ -1327,7 +1327,7 @@ 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->sw_base_vector;
	int base = vsi->base_vector;
	int rx_int_idx = 0;
	int tx_int_idx = 0;
	int vector, err;
@@ -1408,7 +1408,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->hw_oicr_idx),
	wr32(hw, GLINT_DYN_CTL(pf->oicr_idx),
	     GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
}

@@ -1561,15 +1561,13 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
	ice_flush(hw);

	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {
		synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector);
		synchronize_irq(pf->msix_entries[pf->oicr_idx].vector);
		devm_free_irq(&pf->pdev->dev,
			      pf->msix_entries[pf->sw_oicr_idx].vector, pf);
			      pf->msix_entries[pf->oicr_idx].vector, pf);
	}

	pf->num_avail_sw_msix += 1;
	ice_free_res(pf->sw_irq_tracker, pf->sw_oicr_idx, ICE_RES_MISC_VEC_ID);
	pf->num_avail_hw_msix += 1;
	ice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID);
	ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);
}

/**
@@ -1623,43 +1621,31 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
	if (ice_is_reset_in_progress(pf->state))
		goto skip_req_irq;

	/* reserve one vector in sw_irq_tracker for misc interrupts */
	oicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
	/* 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->sw_oicr_idx = oicr_idx;

	/* reserve one vector in hw_irq_tracker for misc interrupts */
	oicr_idx = ice_get_res(pf, pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
	if (oicr_idx < 0) {
		ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
		pf->num_avail_sw_msix += 1;
		return oicr_idx;
	}
	pf->num_avail_hw_msix -= 1;
	pf->hw_oicr_idx = oicr_idx;
	pf->oicr_idx = oicr_idx;

	err = devm_request_irq(&pf->pdev->dev,
			       pf->msix_entries[pf->sw_oicr_idx].vector,
			       pf->msix_entries[pf->oicr_idx].vector,
			       ice_misc_intr, 0, pf->int_name, pf);
	if (err) {
		dev_err(&pf->pdev->dev,
			"devm_request_irq for %s failed: %d\n",
			pf->int_name, err);
		ice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
		ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);
		pf->num_avail_sw_msix += 1;
		ice_free_res(pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
		pf->num_avail_hw_msix += 1;
		return err;
	}

skip_req_irq:
	ice_ena_misc_vector(pf);

	ice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx);
	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),
	ice_ena_ctrlq_interrupts(hw, pf->oicr_idx);
	wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),
	     ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);

	ice_flush(hw);
@@ -2168,14 +2154,9 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf)
	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
		ice_dis_msix(pf);

	if (pf->sw_irq_tracker) {
		devm_kfree(&pf->pdev->dev, pf->sw_irq_tracker);
		pf->sw_irq_tracker = NULL;
	}

	if (pf->hw_irq_tracker) {
		devm_kfree(&pf->pdev->dev, pf->hw_irq_tracker);
		pf->hw_irq_tracker = NULL;
	if (pf->irq_tracker) {
		devm_kfree(&pf->pdev->dev, pf->irq_tracker);
		pf->irq_tracker = NULL;
	}
}

@@ -2185,7 +2166,7 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf)
 */
static int ice_init_interrupt_scheme(struct ice_pf *pf)
{
	int vectors = 0, hw_vectors = 0;
	int vectors;

	if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
		vectors = ice_ena_msix_range(pf);
@@ -2196,31 +2177,18 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
		return vectors;

	/* set up vector assignment tracking */
	pf->sw_irq_tracker =
		devm_kzalloc(&pf->pdev->dev, sizeof(*pf->sw_irq_tracker) +
	pf->irq_tracker =
		devm_kzalloc(&pf->pdev->dev, sizeof(*pf->irq_tracker) +
			     (sizeof(u16) * vectors), GFP_KERNEL);
	if (!pf->sw_irq_tracker) {
	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 = vectors;
	pf->sw_irq_tracker->num_entries = vectors;

	/* set up HW vector assignment tracking */
	hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
	pf->hw_irq_tracker =
		devm_kzalloc(&pf->pdev->dev, sizeof(*pf->hw_irq_tracker) +
			     (sizeof(u16) * hw_vectors), GFP_KERNEL);
	if (!pf->hw_irq_tracker) {
		ice_clear_interrupt_scheme(pf);
		return -ENOMEM;
	}

	/* populate HW interrupts pool with number of HW supported irqs. */
	pf->num_avail_hw_msix = hw_vectors;
	pf->hw_irq_tracker->num_entries = hw_vectors;
	pf->irq_tracker->num_entries = vectors;
	pf->irq_tracker->end = pf->irq_tracker->num_entries;

	return 0;
}
@@ -3794,12 +3762,6 @@ static void ice_rebuild(struct ice_pf *pf)

	ice_dcb_rebuild(pf);

	/* reset search_hint of irq_trackers to 0 since interrupts are
	 * reclaimed and could be allocated from beginning during VSI rebuild
	 */
	pf->sw_irq_tracker->search_hint = 0;
	pf->hw_irq_tracker->search_hint = 0;

	err = ice_vsi_rebuild_all(pf);
	if (err) {
		dev_err(dev, "ice_vsi_rebuild_all failed\n");
+169 −17

File changed.

Preview size limit exceeded, changes collapsed.

Loading