Commit cfebc0a3 authored by Piotr Raczynski's avatar Piotr Raczynski Committed by Tony Nguyen
Browse files

ice: track interrupt vectors with xarray



Replace custom interrupt tracker with generic xarray data structure.
Remove all code responsible for searching for a new entry with xa_alloc,
which always tries to allocate at the lowes possible index. As a result
driver is always using a contiguous region of the MSIX vector table.

New tracker keeps ice_irq_entry entries in xarray as opaque for the rest
of the driver hiding the entry details from the caller.

Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Reviewed-by: default avatarMichal Swiatkowski <michal.swiatkowski@linux.intel.com>
Reviewed-by: default avatarSimon Horman <simon.horman@corigine.com>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: default avatarPiotr Raczynski <piotr.raczynski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 4aad5335
Loading
Loading
Loading
Loading
+1 −8
Original line number Diff line number Diff line
@@ -104,7 +104,6 @@
#define ICE_Q_WAIT_RETRY_LIMIT	10
#define ICE_Q_WAIT_MAX_RETRY	(5 * ICE_Q_WAIT_RETRY_LIMIT)
#define ICE_MAX_LG_RSS_QS	256
#define ICE_RES_VALID_BIT	0x8000
#define ICE_INVAL_Q_INDEX	0xffff

#define ICE_MAX_RXQS_PER_TC		256	/* Used when setting VSI context per TC Rx queues */
@@ -242,12 +241,6 @@ struct ice_tc_cfg {
	struct ice_tc_info tc_info[ICE_MAX_TRAFFIC_CLASS];
};

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

struct ice_qs_cfg {
	struct mutex *qs_mutex;  /* will be assigned to &pf->avail_q_mutex */
	unsigned long *pf_map;
@@ -536,7 +529,7 @@ struct ice_pf {

	/* OS reserved IRQ details */
	struct msix_entry *msix_entries;
	struct ice_res_tracker *irq_tracker;
	struct ice_irq_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.
+77 −24
Original line number Diff line number Diff line
@@ -5,6 +5,75 @@
#include "ice_lib.h"
#include "ice_irq.h"

/**
 * ice_init_irq_tracker - initialize interrupt tracker
 * @pf: board private structure
 * @max_vectors: maximum number of vectors that tracker can hold
 */
static void
ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors)
{
	pf->irq_tracker.num_entries = max_vectors;
	xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC);
}

/**
 * ice_deinit_irq_tracker - free xarray tracker
 * @pf: board private structure
 */
static void ice_deinit_irq_tracker(struct ice_pf *pf)
{
	xa_destroy(&pf->irq_tracker.entries);
}

/**
 * ice_free_irq_res - free a block of resources
 * @pf: board private structure
 * @index: starting index previously returned by ice_get_res
 */
static void ice_free_irq_res(struct ice_pf *pf, u16 index)
{
	struct ice_irq_entry *entry;

	entry = xa_erase(&pf->irq_tracker.entries, index);
	kfree(entry);
}

/**
 * ice_get_irq_res - get an interrupt resource
 * @pf: board private structure
 *
 * Allocate new irq entry in the free slot of the tracker. Since xarray
 * is used, always allocate new entry at the lowest possible index. Set
 * proper allocation limit for maximum tracker entries.
 *
 * Returns allocated irq entry or NULL on failure.
 */
static struct ice_irq_entry *ice_get_irq_res(struct ice_pf *pf)
{
	struct xa_limit limit = { .max = pf->irq_tracker.num_entries,
				  .min = 0 };
	struct ice_irq_entry *entry;
	unsigned int index;
	int ret;

	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
	if (!entry)
		return NULL;

	ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit,
		       GFP_KERNEL);

	if (ret) {
		kfree(entry);
		entry = NULL;
	} else {
		entry->index = index;
	}

	return entry;
}

/**
 * ice_reduce_msix_usage - Reduce usage of MSI-X vectors
 * @pf: board private structure
@@ -163,11 +232,7 @@ static int ice_ena_msix_range(struct ice_pf *pf)
void ice_clear_interrupt_scheme(struct ice_pf *pf)
{
	pci_free_irq_vectors(pf->pdev);

	if (pf->irq_tracker) {
		devm_kfree(ice_pf_to_dev(pf), pf->irq_tracker);
		pf->irq_tracker = NULL;
	}
	ice_deinit_irq_tracker(pf);
}

/**
@@ -183,19 +248,7 @@ int ice_init_interrupt_scheme(struct ice_pf *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) {
		pci_free_irq_vectors(pf->pdev);
		return -ENOMEM;
	}

	/* populate SW interrupts pool with number of OS granted IRQs. */
	pf->irq_tracker->num_entries = (u16)vectors;
	pf->irq_tracker->end = pf->irq_tracker->num_entries;
	ice_init_irq_tracker(pf, vectors);

	return 0;
}
@@ -221,13 +274,13 @@ int ice_init_interrupt_scheme(struct ice_pf *pf)
struct msi_map ice_alloc_irq(struct ice_pf *pf)
{
	struct msi_map map = { .index = -ENOENT };
	int entry;
	struct ice_irq_entry *entry;

	entry = ice_get_res(pf, pf->irq_tracker);
	if (entry < 0)
	entry = ice_get_irq_res(pf);
	if (!entry)
		return map;

	map.index = entry;
	map.index = entry->index;
	map.virq = pci_irq_vector(pf->pdev, map.index);

	return map;
@@ -238,9 +291,9 @@ struct msi_map ice_alloc_irq(struct ice_pf *pf)
 * @pf: board private structure
 * @map: map with interrupt details
 *
 * Remove allocated interrupt from the interrupt tracker
 * Remove allocated interrupt from the interrupt tracker.
 */
void ice_free_irq(struct ice_pf *pf, struct msi_map map)
{
	ice_free_res(pf->irq_tracker, map.index);
	ice_free_irq_res(pf, map.index);
}
+9 −0
Original line number Diff line number Diff line
@@ -4,6 +4,15 @@
#ifndef _ICE_IRQ_H_
#define _ICE_IRQ_H_

struct ice_irq_entry {
	unsigned int index;
};

struct ice_irq_tracker {
	struct xarray entries;
	u16 num_entries;	/* total vectors available */
};

int ice_init_interrupt_scheme(struct ice_pf *pf);
void ice_clear_interrupt_scheme(struct ice_pf *pf);

+0 −45
Original line number Diff line number Diff line
@@ -1370,51 +1370,6 @@ static int ice_vsi_init(struct ice_vsi *vsi, u32 vsi_flags)
	return ret;
}

/**
 * ice_free_res - free a block of resources
 * @res: pointer to the resource
 * @index: starting index previously returned by ice_get_res
 *
 * Returns number of resources freed
 */
int ice_free_res(struct ice_res_tracker *res, u16 index)
{
	if (!res || index >= res->end)
		return -EINVAL;

	res->list[index] = 0;

	return 0;
}

/**
 * ice_get_res - get a resource from the tracker
 * @pf: board private structure
 * @res: pointer to the resource
 *
 * Returns the item index, or negative for error
 */
int
ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res)
{
	u16 i;

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

	/* skip already allocated entries */
	for (i = 0; i < res->end; i++)
		if (!(res->list[i] & ICE_RES_VALID_BIT))
			break;

	if (i < res->end) {
		res->list[i] = ICE_RES_VALID_BIT;
		return i;
	} else {
		return -ENOMEM;
	}
}

/**
 * ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
 * @vsi: the VSI having rings deallocated
+0 −5
Original line number Diff line number Diff line
@@ -104,11 +104,6 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked);
void ice_vsi_decfg(struct ice_vsi *vsi);
void ice_dis_vsi(struct ice_vsi *vsi, bool locked);

int ice_free_res(struct ice_res_tracker *res, u16 index);

int
ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res);

int ice_vsi_rebuild(struct ice_vsi *vsi, u32 vsi_flags);
int ice_vsi_cfg(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params);

Loading