@@ -301,6 +301,7 @@ config ICE
select LIBIE
select LIBIE_ADMINQ
select LIBIE_FWLOG if DEBUG_FS
+ select LIBIE_IRQ
select NET_DEVLINK
select PACKING
select PLDMFW
@@ -36,6 +36,7 @@
#include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/auxiliary_bus.h>
+#include <linux/net/intel/libie/irq.h>
#include <linux/net/intel/virtchnl.h>
#include <linux/cpu_rmap.h>
#include <linux/dim.h>
@@ -351,8 +352,6 @@ struct ice_vsi {
u32 rx_buf_failed;
u32 rx_page_failed;
u16 num_q_vectors;
- /* tell if only dynamic irq allocation is allowed */
- bool irq_dyn_alloc;
bool hsplit:1;
u16 vsi_num; /* HW (absolute) index of this VSI */
@@ -565,7 +564,7 @@ struct ice_pf {
struct devlink_port devlink_port;
/* OS reserved IRQ details */
- struct ice_irq_tracker irq_tracker;
+ struct libie_irq irq;
struct ice_virt_irq_tracker virt_irq_tracker;
u16 ctrl_vsi_idx; /* control VSI index in pf->vsi array */
@@ -140,7 +140,7 @@ static int ice_vsi_alloc_q_vector(struct ice_vsi *vsi, u16 v_idx)
}
}
- q_vector->irq = ice_alloc_irq(pf, vsi->irq_dyn_alloc);
+ q_vector->irq = libie_irq_alloc(&pf->irq, LIBIE_IRQ_ANY);
if (q_vector->irq.index < 0) {
err = -ENOMEM;
goto err_free_q_vector;
@@ -209,7 +209,7 @@ static void ice_free_q_vector(struct ice_vsi *vsi, int v_idx)
ice_get_vf_ctrl_vsi(pf, vsi))
goto free_q_vector;
- ice_free_irq(pf, q_vector->irq);
+ libie_irq_free(&pf->irq, q_vector->irq);
free_q_vector:
kfree(q_vector);
@@ -239,7 +239,7 @@ int ice_alloc_rdma_qvector(struct iidc_rdma_core_dev_info *cdev,
return -EINVAL;
pf = pci_get_drvdata(cdev->pdev);
- map = ice_alloc_irq(pf, true);
+ map = libie_irq_alloc(&pf->irq, LIBIE_IRQ_ANY);
if (map.index < 0)
return -ENOMEM;
@@ -268,7 +268,7 @@ void ice_free_rdma_qvector(struct iidc_rdma_core_dev_info *cdev,
map.index = entry->entry;
map.virq = entry->vector;
- ice_free_irq(pf, map);
+ libie_irq_free(&pf->irq, map);
}
EXPORT_SYMBOL_GPL(ice_free_rdma_qvector);
@@ -5,21 +5,6 @@
#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
- * @num_static: number of preallocated interrupts
- */
-static void
-ice_init_irq_tracker(struct ice_pf *pf, unsigned int max_vectors,
- unsigned int num_static)
-{
- pf->irq_tracker.num_entries = max_vectors;
- pf->irq_tracker.num_static = num_static;
- xa_init_flags(&pf->irq_tracker.entries, XA_FLAGS_ALLOC);
-}
-
static int
ice_init_virt_irq_tracker(struct ice_pf *pf, u32 base, u32 num_entries)
{
@@ -33,76 +18,11 @@ ice_init_virt_irq_tracker(struct ice_pf *pf, u32 base, u32 num_entries)
return 0;
}
-/**
- * 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);
-}
-
static void ice_deinit_virt_irq_tracker(struct ice_pf *pf)
{
bitmap_free(pf->virt_irq_tracker.bm);
}
-/**
- * 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
- * @dyn_allowed: allow entry to be dynamically allocated
- *
- * 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,
- bool dyn_allowed)
-{
- struct xa_limit limit = { .max = pf->irq_tracker.num_entries - 1,
- .min = 0 };
- unsigned int num_static = pf->irq_tracker.num_static - 1;
- struct ice_irq_entry *entry;
- unsigned int index;
- int ret;
-
- entry = kzalloc_obj(*entry);
- if (!entry)
- return NULL;
-
- /* only already allocated if the caller says so */
- if (!dyn_allowed)
- limit.max = num_static;
-
- ret = xa_alloc(&pf->irq_tracker.entries, &index, entry, limit,
- GFP_KERNEL);
-
- if (ret) {
- kfree(entry);
- entry = NULL;
- } else {
- entry->index = index;
- entry->dynamic = index > num_static;
- }
-
- return entry;
-}
-
#define ICE_RDMA_AEQ_MSIX 1
static int ice_get_default_msix_amount(struct ice_pf *pf)
{
@@ -118,8 +38,7 @@ static int ice_get_default_msix_amount(struct ice_pf *pf)
*/
void ice_clear_interrupt_scheme(struct ice_pf *pf)
{
- pci_free_irq_vectors(pf->pdev);
- ice_deinit_irq_tracker(pf);
+ libie_irq_deinit(&pf->irq);
ice_deinit_virt_irq_tracker(pf);
}
@@ -130,7 +49,7 @@ void ice_clear_interrupt_scheme(struct ice_pf *pf)
int ice_init_interrupt_scheme(struct ice_pf *pf)
{
int total_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
- int vectors;
+ int err;
/* load default PF MSI-X range */
if (!pf->msix.min)
@@ -143,97 +62,15 @@ int ice_init_interrupt_scheme(struct ice_pf *pf)
pf->msix.total = total_vectors;
pf->msix.rest = total_vectors - pf->msix.max;
- if (pci_msix_can_alloc_dyn(pf->pdev))
- vectors = pf->msix.min;
- else
- vectors = pf->msix.max;
-
- vectors = pci_alloc_irq_vectors(pf->pdev, pf->msix.min, vectors,
- PCI_IRQ_MSIX);
- if (vectors < 0)
- return vectors;
-
- ice_init_irq_tracker(pf, pf->msix.max, vectors);
-
- return ice_init_virt_irq_tracker(pf, pf->msix.max, pf->msix.rest);
-}
-
-/**
- * ice_alloc_irq - Allocate new interrupt vector
- * @pf: board private structure
- * @dyn_allowed: allow dynamic allocation of the interrupt
- *
- * Allocate new interrupt vector for a given owner id.
- * return struct msi_map with interrupt details and track
- * allocated interrupt appropriately.
- *
- * This function reserves new irq entry from the irq_tracker.
- * if according to the tracker information all interrupts that
- * were allocated with ice_pci_alloc_irq_vectors are already used
- * and dynamically allocated interrupts are supported then new
- * interrupt will be allocated with pci_msix_alloc_irq_at.
- *
- * Some callers may only support dynamically allocated interrupts.
- * This is indicated with dyn_allowed flag.
- *
- * On failure, return map with negative .index. The caller
- * is expected to check returned map index.
- *
- */
-struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_allowed)
-{
- struct msi_map map = { .index = -ENOENT };
- struct device *dev = ice_pf_to_dev(pf);
- struct ice_irq_entry *entry;
-
- entry = ice_get_irq_res(pf, dyn_allowed);
- if (!entry)
- return map;
-
- if (pci_msix_can_alloc_dyn(pf->pdev) && entry->dynamic) {
- map = pci_msix_alloc_irq_at(pf->pdev, entry->index, NULL);
- if (map.index < 0)
- goto exit_free_res;
- dev_dbg(dev, "allocated new irq at index %d\n", map.index);
- } else {
- map.index = entry->index;
- map.virq = pci_irq_vector(pf->pdev, map.index);
- }
-
- return map;
-
-exit_free_res:
- dev_err(dev, "Could not allocate irq at idx %d\n", entry->index);
- ice_free_irq_res(pf, entry->index);
- return map;
-}
-
-/**
- * ice_free_irq - Free interrupt vector
- * @pf: board private structure
- * @map: map with interrupt details
- *
- * Remove allocated interrupt from the interrupt tracker. If interrupt was
- * allocated dynamically, free respective interrupt vector.
- */
-void ice_free_irq(struct ice_pf *pf, struct msi_map map)
-{
- struct ice_irq_entry *entry;
-
- entry = xa_load(&pf->irq_tracker.entries, map.index);
-
- if (!entry) {
- dev_err(ice_pf_to_dev(pf), "Failed to get MSIX interrupt entry at index %d",
- map.index);
- return;
- }
-
- dev_dbg(ice_pf_to_dev(pf), "Free irq at index %d\n", map.index);
+ err = libie_irq_init(&pf->irq, pf->pdev, pf->msix.min, pf->msix.max);
+ if (err)
+ return err;
- if (entry->dynamic)
- pci_msix_free_irq(pf->pdev, map);
+ err = ice_init_virt_irq_tracker(pf, pf->msix.max, pf->msix.rest);
+ if (err)
+ libie_irq_deinit(&pf->irq);
- ice_free_irq_res(pf, map.index);
+ return err;
}
/**
@@ -4,17 +4,6 @@
#ifndef _ICE_IRQ_H_
#define _ICE_IRQ_H_
-struct ice_irq_entry {
- unsigned int index;
- bool dynamic; /* allocation type flag */
-};
-
-struct ice_irq_tracker {
- struct xarray entries;
- u16 num_entries; /* total vectors available */
- u16 num_static; /* preallocated entries */
-};
-
struct ice_virt_irq_tracker {
unsigned long *bm; /* bitmap to track irq usage */
u32 num_entries;
@@ -28,9 +17,6 @@ struct ice_virt_irq_tracker {
int ice_init_interrupt_scheme(struct ice_pf *pf);
void ice_clear_interrupt_scheme(struct ice_pf *pf);
-struct msi_map ice_alloc_irq(struct ice_pf *pf, bool dyn_only);
-void ice_free_irq(struct ice_pf *pf, struct msi_map map);
-
int ice_virt_get_irqs(struct ice_pf *pf, u32 needed);
void ice_virt_free_irqs(struct ice_pf *pf, u32 index, u32 irqs);
#endif
@@ -211,7 +211,6 @@ static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
vsi->alloc_txq = 1;
vsi->alloc_rxq = 1;
vsi->num_q_vectors = 1;
- vsi->irq_dyn_alloc = true;
break;
case ICE_VSI_VF:
if (vf->num_req_qs)
@@ -572,8 +571,6 @@ ice_vsi_alloc_def(struct ice_vsi *vsi, struct ice_channel *ch)
return -ENOMEM;
}
- vsi->irq_dyn_alloc = pci_msix_can_alloc_dyn(vsi->back->pdev);
-
switch (vsi->type) {
case ICE_VSI_PF:
case ICE_VSI_SF:
@@ -44,6 +44,7 @@ MODULE_IMPORT_NS("LIBETH_XDP");
MODULE_IMPORT_NS("LIBIE");
MODULE_IMPORT_NS("LIBIE_ADMINQ");
MODULE_IMPORT_NS("LIBIE_FWLOG");
+MODULE_IMPORT_NS("LIBIE_IRQ");
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(ICE_DDP_PKG_FILE);
@@ -3357,7 +3358,7 @@ static void ice_free_irq_msix_ll_ts(struct ice_pf *pf)
synchronize_irq(irq_num);
devm_free_irq(ice_pf_to_dev(pf), irq_num, pf);
- ice_free_irq(pf, pf->ll_ts_irq);
+ libie_irq_free(&pf->irq, pf->ll_ts_irq);
}
/**
@@ -3378,7 +3379,7 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
synchronize_irq(misc_irq_num);
devm_free_irq(ice_pf_to_dev(pf), misc_irq_num, pf);
- ice_free_irq(pf, pf->oicr_irq);
+ libie_irq_free(&pf->irq, pf->oicr_irq);
if (pf->ll_ts_irq.index >= 0)
ice_free_irq_msix_ll_ts(pf);
}
@@ -3447,7 +3448,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
goto skip_req_irq;
/* reserve one vector in irq_tracker for misc interrupts */
- irq = ice_alloc_irq(pf, false);
+ irq = libie_irq_alloc(&pf->irq, LIBIE_IRQ_STATIC);
if (irq.index < 0)
return irq.index;
@@ -3458,7 +3459,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
if (err) {
dev_err(dev, "devm_request_threaded_irq for %s failed: %d\n",
pf->int_name, err);
- ice_free_irq(pf, pf->oicr_irq);
+ libie_irq_free(&pf->irq, pf->oicr_irq);
return err;
}
@@ -3468,7 +3469,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
goto skip_req_irq;
}
- irq = ice_alloc_irq(pf, false);
+ irq = libie_irq_alloc(&pf->irq, LIBIE_IRQ_STATIC);
if (irq.index < 0)
return irq.index;
@@ -3478,7 +3479,7 @@ static int ice_req_irq_msix_misc(struct ice_pf *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);
+ libie_irq_free(&pf->irq, pf->ll_ts_irq);
pf->ll_ts_irq.index = -ENOENT;
return err;
}
@@ -3963,7 +3964,7 @@ void ice_deinit_pf(struct ice_pf *pf)
if (pf->ptp.clock)
ptp_clock_unregister(pf->ptp.clock);
- if (!xa_empty(&pf->irq_tracker.entries))
+ if (!xa_empty(&pf->irq.entries))
ice_free_irq_msix_misc(pf);
xa_destroy(&pf->dyn_ports);
@@ -98,6 +98,7 @@ static struct libie_irq_entry *libie_get_irq(struct libie_irq *irq,
enum libie_irq_type type)
{
struct libie_irq_entry *entry;
+ struct xa_limit limit;
unsigned int index;
if (!irq->pdev)
@@ -113,9 +114,26 @@ static struct libie_irq_entry *libie_get_irq(struct libie_irq *irq,
if (!entry)
return NULL;
- if (xa_alloc(&irq->entries, &index, entry, irq->limits[type],
- GFP_KERNEL))
- goto free_entry;
+ /* If any, first try dynamic */
+ if (type == LIBIE_IRQ_ANY)
+ limit = irq->limits[LIBIE_IRQ_DYNAMIC];
+ else
+ limit = irq->limits[type];
+
+ if (xa_alloc(&irq->entries, &index, entry, limit, GFP_KERNEL)) {
+ if (type != LIBIE_IRQ_ANY)
+ goto free_entry;
+ /* Dynamic for any type failed, try static */
+ if (xa_alloc(&irq->entries, &index, entry,
+ irq->limits[LIBIE_IRQ_STATIC], GFP_KERNEL))
+ goto free_entry;
+
+ type = LIBIE_IRQ_STATIC;
+ }
+
+ /* If still any it is dynamic */
+ if (type == LIBIE_IRQ_ANY)
+ type = LIBIE_IRQ_DYNAMIC;
entry->index = index;
entry->type = type;
@@ -149,6 +167,7 @@ EXPORT_SYMBOL_NS_GPL(libie_put_irq, "LIBIE_IRQ");
*
* For LIBIE_IRQ_DYNAMIC function allocs new interrupt and return it.
* For LIBIE_IRQ_STATIC function returns already allocated one.
+ * For LIBIE_IRQ_ANY first try DYNAMIC, if it failed try STATIC
*
* The function should be called for getting irq information (index and virq)
* for specific irq type. Returned information should be stored to use index for
@@ -202,8 +221,9 @@ EXPORT_SYMBOL_NS_GPL(libie_irq_alloc, "LIBIE_IRQ");
* @irq: libie_irq structure
* @map: msi_map structure returned from libie_alloc_irq()
*
- * In case of dynamic allocation and LIBIE_IRQ_DYNAMIC type pci_msix_free_irq()
- * is called. Otherwise only free driver irq entry related resources.
+ * In case of dynamic allocation and LIBIE_IRQ_DYNAMIC (or LIBIE_IRQ_ANY)
+ * type pci_msix_free_irq() is called. Otherwise only free driver irq entry
+ * related resources.
*
* It is safe to call this function with map that doesn't exist in xarray
* as long as the map.virq is 0 or negative. It is true when libie_irq_alloc()
@@ -17,6 +17,7 @@
* enum libie_irq_type - enum representing types of irq entries
* @LIBIE_IRQ_STATIC: irq static allocated from kernel at driver probe
* @LIBIE_IRQ_DYNAMIC: irq dynamic allocated during normal driver operation
+ * @LIBIE_IRQ_ANY: use when STATIC or DYNAMIC can be allocated
* @LIBIE_IRQ_NUM_TYPES: must be the last one, used to define the array size
*
* Enum is used to get software irq indexes from some kind of pool. The pool is
@@ -31,6 +32,7 @@
enum libie_irq_type {
LIBIE_IRQ_STATIC,
LIBIE_IRQ_DYNAMIC,
+ LIBIE_IRQ_ANY,
LIBIE_IRQ_NUM_TYPES,
};