Commit eb0208ec authored by Preethi Banala's avatar Preethi Banala Committed by Jeff Kirsher

ice: Split irq_tracker into sw_irq_tracker and hw_irq_tracker

For the PF driver, when mapping interrupts to queues, we need to request
IRQs from the kernel and we also have to allocate interrupts from
the device.

Similarly, when the VF driver (iavf.ko) initializes, it requests the kernel
IRQs that it needs but it can't directly allocate interrupts in the device.
Instead, it sends a mailbox message to the ice driver, which then allocates
interrupts in the device on the VF driver's behalf.

Currently both these cases end up having to reserve entries in
pf->irq_tracker but irq_tracker itself is sized based on how many vectors
the PF driver needs. Under the right circumstances, the VF driver can fail
to get entries in irq_tracker, which will result in the VF driver failing
probe.

To fix this, sw_irq_tracker and hw_irq_tracker are introduced. The
sw_irq_tracker tracks only the PF's IRQ request and doesn't play any
role in VF init. hw_irq_tracker represents the device's interrupt space.
When interrupts have to be allocated in the device for either PF or VF,
hw_irq_tracker will be looked up to see if the device has run out of
interrupts.
Signed-off-by: default avatarPreethi Banala <preethi.banala@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 5755143d
...@@ -172,7 +172,8 @@ struct ice_vsi { ...@@ -172,7 +172,8 @@ struct ice_vsi {
u32 rx_buf_failed; u32 rx_buf_failed;
u32 rx_page_failed; u32 rx_page_failed;
int num_q_vectors; int num_q_vectors;
int base_vector; int sw_base_vector; /* Irq base for OS reserved vectors */
int hw_base_vector; /* HW (absolute) index of a vector */
enum ice_vsi_type type; enum ice_vsi_type type;
u16 vsi_num; /* HW (absolute) index of this VSI */ u16 vsi_num; /* HW (absolute) index of this VSI */
u16 idx; /* software index in pf->vsi[] */ u16 idx; /* software index in pf->vsi[] */
...@@ -240,8 +241,14 @@ enum ice_pf_flags { ...@@ -240,8 +241,14 @@ enum ice_pf_flags {
struct ice_pf { struct ice_pf {
struct pci_dev *pdev; struct pci_dev *pdev;
/* OS reserved IRQ details */
struct msix_entry *msix_entries; struct msix_entry *msix_entries;
struct ice_res_tracker *irq_tracker; struct ice_res_tracker *sw_irq_tracker;
/* HW reserved Interrupts for this PF */
struct ice_res_tracker *hw_irq_tracker;
struct ice_vsi **vsi; /* VSIs created by the driver */ struct ice_vsi **vsi; /* VSIs created by the driver */
struct ice_sw *first_sw; /* first switch created by firmware */ struct ice_sw *first_sw; /* first switch created by firmware */
DECLARE_BITMAP(state, __ICE_STATE_NBITS); DECLARE_BITMAP(state, __ICE_STATE_NBITS);
...@@ -256,9 +263,11 @@ struct ice_pf { ...@@ -256,9 +263,11 @@ struct ice_pf {
struct mutex sw_mutex; /* lock for protecting VSI alloc flow */ struct mutex sw_mutex; /* lock for protecting VSI alloc flow */
u32 msg_enable; u32 msg_enable;
u32 hw_csum_rx_error; u32 hw_csum_rx_error;
u32 oicr_idx; /* Other interrupt cause vector index */ u32 sw_oicr_idx; /* Other interrupt cause SW 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 */ u32 num_lan_msix; /* Total MSIX vectors for base driver */
u32 num_avail_msix; /* remaining MSIX vectors left unclaimed */
u16 num_lan_tx; /* num lan tx queues setup */ u16 num_lan_tx; /* num lan tx queues setup */
u16 num_lan_rx; /* num lan rx queues setup */ u16 num_lan_rx; /* num lan rx queues setup */
u16 q_left_tx; /* remaining num tx queues left unclaimed */ u16 q_left_tx; /* remaining num tx queues left unclaimed */
...@@ -293,8 +302,8 @@ struct ice_netdev_priv { ...@@ -293,8 +302,8 @@ struct ice_netdev_priv {
static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi, static inline void ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,
struct ice_q_vector *q_vector) struct ice_q_vector *q_vector)
{ {
u32 vector = (vsi && q_vector) ? vsi->base_vector + q_vector->v_idx : u32 vector = (vsi && q_vector) ? vsi->hw_base_vector + q_vector->v_idx :
((struct ice_pf *)hw->back)->oicr_idx; ((struct ice_pf *)hw->back)->hw_oicr_idx;
int itr = ICE_ITR_NONE; int itr = ICE_ITR_NONE;
u32 val; u32 val;
......
...@@ -1039,9 +1039,9 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) ...@@ -1039,9 +1039,9 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
int num_q_vectors = 0; int num_q_vectors = 0;
if (vsi->base_vector) { if (vsi->sw_base_vector || vsi->hw_base_vector) {
dev_dbg(&pf->pdev->dev, "VSI %d has non-zero base vector %d\n", dev_dbg(&pf->pdev->dev, "VSI %d has non-zero HW base vector %d or SW base vector %d\n",
vsi->vsi_num, vsi->base_vector); vsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector);
return -EEXIST; return -EEXIST;
} }
...@@ -1051,6 +1051,21 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) ...@@ -1051,6 +1051,21 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
switch (vsi->type) { switch (vsi->type) {
case ICE_VSI_PF: case ICE_VSI_PF:
num_q_vectors = vsi->num_q_vectors; 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) {
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);
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; break;
default: default:
dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n", dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n",
...@@ -1058,17 +1073,18 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) ...@@ -1058,17 +1073,18 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)
break; break;
} }
if (num_q_vectors) if (vsi->hw_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, dev_err(&pf->pdev->dev,
"Failed to get tracking for %d vectors for VSI %d, err=%d\n", "Failed to get tracking for %d HW vectors for VSI %d, err=%d\n",
num_q_vectors, vsi->vsi_num, vsi->base_vector); num_q_vectors, vsi->vsi_num, vsi->hw_base_vector);
ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector,
vsi->idx);
pf->num_avail_sw_msix += num_q_vectors;
return -ENOENT; return -ENOENT;
} }
pf->num_avail_hw_msix -= num_q_vectors;
return 0; return 0;
} }
...@@ -1554,7 +1570,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi) ...@@ -1554,7 +1570,7 @@ int ice_vsi_cfg_txqs(struct ice_vsi *vsi)
void ice_vsi_cfg_msix(struct ice_vsi *vsi) void ice_vsi_cfg_msix(struct ice_vsi *vsi)
{ {
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
u16 vector = vsi->base_vector; u16 vector = vsi->hw_base_vector;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
u32 txq = 0, rxq = 0; u32 txq = 0, rxq = 0;
int i, q, itr; int i, q, itr;
...@@ -1762,7 +1778,7 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi) ...@@ -1762,7 +1778,7 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi)
* the queue to schedule NAPI handler * the queue to schedule NAPI handler
*/ */
v_idx = vsi->tx_rings[i]->q_vector->v_idx; v_idx = vsi->tx_rings[i]->q_vector->v_idx;
wr32(hw, GLINT_DYN_CTL(vsi->base_vector + v_idx), wr32(hw, GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),
GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M); GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M);
} }
status = ice_dis_vsi_txq(vsi->port_info, vsi->num_txq, q_ids, q_teids, status = ice_dis_vsi_txq(vsi->port_info, vsi->num_txq, q_ids, q_teids,
...@@ -1939,7 +1955,12 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, ...@@ -1939,7 +1955,12 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
return vsi; return vsi;
unroll_vector_base: unroll_vector_base:
ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); /* reclaim SW interrupts back to the common pool */
ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
pf->num_avail_sw_msix += vsi->num_q_vectors;
/* reclaim HW interrupt back to the common pool */
ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);
pf->num_avail_hw_msix += vsi->num_q_vectors;
unroll_alloc_q_vector: unroll_alloc_q_vector:
ice_vsi_free_q_vectors(vsi); ice_vsi_free_q_vectors(vsi);
unroll_vsi_init: unroll_vsi_init:
...@@ -1960,7 +1981,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, ...@@ -1960,7 +1981,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
static void ice_vsi_release_msix(struct ice_vsi *vsi) static void ice_vsi_release_msix(struct ice_vsi *vsi)
{ {
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
u16 vector = vsi->base_vector; u16 vector = vsi->hw_base_vector;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
u32 txq = 0; u32 txq = 0;
u32 rxq = 0; u32 rxq = 0;
...@@ -1992,7 +2013,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi) ...@@ -1992,7 +2013,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)
void ice_vsi_free_irq(struct ice_vsi *vsi) void ice_vsi_free_irq(struct ice_vsi *vsi)
{ {
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
int base = vsi->base_vector; int base = vsi->sw_base_vector;
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
int i; int i;
...@@ -2000,6 +2021,8 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) ...@@ -2000,6 +2021,8 @@ void ice_vsi_free_irq(struct ice_vsi *vsi)
if (!vsi->q_vectors || !vsi->irqs_ready) if (!vsi->q_vectors || !vsi->irqs_ready)
return; return;
ice_vsi_release_msix(vsi);
vsi->irqs_ready = false; vsi->irqs_ready = false;
for (i = 0; i < vsi->num_q_vectors; i++) { for (i = 0; i < vsi->num_q_vectors; i++) {
u16 vector = i + base; u16 vector = i + base;
...@@ -2022,7 +2045,6 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) ...@@ -2022,7 +2045,6 @@ void ice_vsi_free_irq(struct ice_vsi *vsi)
devm_free_irq(&pf->pdev->dev, irq_num, devm_free_irq(&pf->pdev->dev, irq_num,
vsi->q_vectors[i]); vsi->q_vectors[i]);
} }
ice_vsi_release_msix(vsi);
} }
} }
...@@ -2110,6 +2132,9 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) ...@@ -2110,6 +2132,9 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)
int start = res->search_hint; int start = res->search_hint;
int end = start; int end = start;
if ((start + needed) > res->num_entries)
return -ENOMEM;
id |= ICE_RES_VALID_BIT; id |= ICE_RES_VALID_BIT;
do { do {
...@@ -2183,9 +2208,9 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) ...@@ -2183,9 +2208,9 @@ 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) void ice_vsi_dis_irq(struct ice_vsi *vsi)
{ {
int base = vsi->sw_base_vector;
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
struct ice_hw *hw = &pf->hw; struct ice_hw *hw = &pf->hw;
int base = vsi->base_vector;
u32 val; u32 val;
int i; int i;
...@@ -2218,8 +2243,8 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) ...@@ -2218,8 +2243,8 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)
/* disable each interrupt */ /* disable each interrupt */
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {
for (i = vsi->base_vector; for (i = vsi->hw_base_vector;
i < (vsi->num_q_vectors + vsi->base_vector); i++) i < (vsi->num_q_vectors + vsi->hw_base_vector); i++)
wr32(hw, GLINT_DYN_CTL(i), 0); wr32(hw, GLINT_DYN_CTL(i), 0);
ice_flush(hw); ice_flush(hw);
...@@ -2262,8 +2287,10 @@ int ice_vsi_release(struct ice_vsi *vsi) ...@@ -2262,8 +2287,10 @@ int ice_vsi_release(struct ice_vsi *vsi)
ice_vsi_close(vsi); ice_vsi_close(vsi);
/* reclaim interrupt vectors back to PF */ /* reclaim interrupt vectors back to PF */
ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
pf->num_avail_msix += vsi->num_q_vectors; pf->num_avail_sw_msix += vsi->num_q_vectors;
ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);
pf->num_avail_hw_msix += vsi->num_q_vectors;
ice_remove_vsi_fltr(&pf->hw, vsi->idx); ice_remove_vsi_fltr(&pf->hw, vsi->idx);
ice_vsi_delete(vsi); ice_vsi_delete(vsi);
...@@ -2299,8 +2326,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) ...@@ -2299,8 +2326,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)
return -EINVAL; return -EINVAL;
ice_vsi_free_q_vectors(vsi); ice_vsi_free_q_vectors(vsi);
ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);
vsi->base_vector = 0; ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);
vsi->sw_base_vector = 0;
vsi->hw_base_vector = 0;
ice_vsi_clear_rings(vsi); ice_vsi_clear_rings(vsi);
ice_vsi_free_arrays(vsi, false); ice_vsi_free_arrays(vsi, false);
ice_vsi_set_num_qs(vsi); ice_vsi_set_num_qs(vsi);
......
...@@ -95,7 +95,7 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf) ...@@ -95,7 +95,7 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)
/* Trigger sw interrupt to revive the queue */ /* Trigger sw interrupt to revive the queue */
v_idx = tx_ring->q_vector->v_idx; v_idx = tx_ring->q_vector->v_idx;
wr32(&vsi->back->hw, wr32(&vsi->back->hw,
GLINT_DYN_CTL(vsi->base_vector + v_idx), GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),
(itr << GLINT_DYN_CTL_ITR_INDX_S) | (itr << GLINT_DYN_CTL_ITR_INDX_S) |
GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_SWINT_TRIG_M |
GLINT_DYN_CTL_INTENA_MSK_M); GLINT_DYN_CTL_INTENA_MSK_M);
...@@ -1122,7 +1122,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename) ...@@ -1122,7 +1122,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)
{ {
int q_vectors = vsi->num_q_vectors; int q_vectors = vsi->num_q_vectors;
struct ice_pf *pf = vsi->back; struct ice_pf *pf = vsi->back;
int base = vsi->base_vector; int base = vsi->sw_base_vector;
int rx_int_idx = 0; int rx_int_idx = 0;
int tx_int_idx = 0; int tx_int_idx = 0;
int vector, err; int vector, err;
...@@ -1203,7 +1203,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf) ...@@ -1203,7 +1203,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)
wr32(hw, PFINT_OICR_ENA, val); wr32(hw, PFINT_OICR_ENA, val);
/* SW_ITR_IDX = 0, but don't change INTENA */ /* SW_ITR_IDX = 0, but don't change INTENA */
wr32(hw, GLINT_DYN_CTL(pf->oicr_idx), wr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx),
GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M); GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);
} }
...@@ -1321,12 +1321,15 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf) ...@@ -1321,12 +1321,15 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)
ice_flush(&pf->hw); ice_flush(&pf->hw);
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) { if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {
synchronize_irq(pf->msix_entries[pf->oicr_idx].vector); synchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector);
devm_free_irq(&pf->pdev->dev, devm_free_irq(&pf->pdev->dev,
pf->msix_entries[pf->oicr_idx].vector, pf); pf->msix_entries[pf->sw_oicr_idx].vector, pf);
} }
ice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID); 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);
} }
/** /**
...@@ -1356,39 +1359,53 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf) ...@@ -1356,39 +1359,53 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)
if (ice_is_reset_in_progress(pf->state)) if (ice_is_reset_in_progress(pf->state))
goto skip_req_irq; goto skip_req_irq;
/* reserve one vector in irq_tracker for misc interrupts */ /* reserve one vector in sw_irq_tracker for misc interrupts */
oicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); oicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);
if (oicr_idx < 0) if (oicr_idx < 0)
return oicr_idx; return oicr_idx;
pf->oicr_idx = 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;
err = devm_request_irq(&pf->pdev->dev, err = devm_request_irq(&pf->pdev->dev,
pf->msix_entries[pf->oicr_idx].vector, pf->msix_entries[pf->sw_oicr_idx].vector,
ice_misc_intr, 0, pf->int_name, pf); ice_misc_intr, 0, pf->int_name, pf);
if (err) { if (err) {
dev_err(&pf->pdev->dev, dev_err(&pf->pdev->dev,
"devm_request_irq for %s failed: %d\n", "devm_request_irq for %s failed: %d\n",
pf->int_name, err); pf->int_name, err);
ice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID); ice_free_res(pf->sw_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; return err;
} }
skip_req_irq: skip_req_irq:
ice_ena_misc_vector(pf); ice_ena_misc_vector(pf);
val = ((pf->oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) | val = ((pf->hw_oicr_idx & PFINT_OICR_CTL_MSIX_INDX_M) |
PFINT_OICR_CTL_CAUSE_ENA_M); PFINT_OICR_CTL_CAUSE_ENA_M);
wr32(hw, PFINT_OICR_CTL, val); wr32(hw, PFINT_OICR_CTL, val);
/* This enables Admin queue Interrupt causes */ /* This enables Admin queue Interrupt causes */
val = ((pf->oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) | val = ((pf->hw_oicr_idx & PFINT_FW_CTL_MSIX_INDX_M) |
PFINT_FW_CTL_CAUSE_ENA_M); PFINT_FW_CTL_CAUSE_ENA_M);
wr32(hw, PFINT_FW_CTL, val); wr32(hw, PFINT_FW_CTL, val);
itr_gran = hw->itr_gran_200; itr_gran = hw->itr_gran_200;
wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx), wr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),
ITR_TO_REG(ICE_ITR_8K, itr_gran)); ITR_TO_REG(ICE_ITR_8K, itr_gran));
ice_flush(hw); ice_flush(hw);
...@@ -1797,6 +1814,7 @@ static int ice_ena_msix_range(struct ice_pf *pf) ...@@ -1797,6 +1814,7 @@ static int ice_ena_msix_range(struct ice_pf *pf)
/* reserve vectors for LAN traffic */ /* reserve vectors for LAN traffic */
pf->num_lan_msix = min_t(int, num_online_cpus(), v_left); pf->num_lan_msix = min_t(int, num_online_cpus(), v_left);
v_budget += pf->num_lan_msix; v_budget += pf->num_lan_msix;
v_left -= pf->num_lan_msix;
pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget, pf->msix_entries = devm_kcalloc(&pf->pdev->dev, v_budget,
sizeof(struct msix_entry), GFP_KERNEL); sizeof(struct msix_entry), GFP_KERNEL);
...@@ -1824,10 +1842,11 @@ static int ice_ena_msix_range(struct ice_pf *pf) ...@@ -1824,10 +1842,11 @@ static int ice_ena_msix_range(struct ice_pf *pf)
"not enough vectors. requested = %d, obtained = %d\n", "not enough vectors. requested = %d, obtained = %d\n",
v_budget, v_actual); v_budget, v_actual);
if (v_actual >= (pf->num_lan_msix + 1)) { if (v_actual >= (pf->num_lan_msix + 1)) {
pf->num_avail_msix = v_actual - (pf->num_lan_msix + 1); pf->num_avail_sw_msix = v_actual -
(pf->num_lan_msix + 1);
} else if (v_actual >= 2) { } else if (v_actual >= 2) {
pf->num_lan_msix = 1; pf->num_lan_msix = 1;
pf->num_avail_msix = v_actual - 2; pf->num_avail_sw_msix = v_actual - 2;
} else { } else {
pci_disable_msix(pf->pdev); pci_disable_msix(pf->pdev);
err = -ERANGE; err = -ERANGE;
...@@ -1859,13 +1878,33 @@ static void ice_dis_msix(struct ice_pf *pf) ...@@ -1859,13 +1878,33 @@ static void ice_dis_msix(struct ice_pf *pf)
clear_bit(ICE_FLAG_MSIX_ENA, pf->flags); clear_bit(ICE_FLAG_MSIX_ENA, pf->flags);
} }
/**
* 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)
{
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;
}
}
/** /**
* ice_init_interrupt_scheme - Determine proper interrupt scheme * ice_init_interrupt_scheme - Determine proper interrupt scheme
* @pf: board private structure to initialize * @pf: board private structure to initialize
*/ */
static int ice_init_interrupt_scheme(struct ice_pf *pf) static int ice_init_interrupt_scheme(struct ice_pf *pf)
{ {
int vectors = 0; int vectors = 0, hw_vectors = 0;
ssize_t size; ssize_t size;
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
...@@ -1879,30 +1918,31 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) ...@@ -1879,30 +1918,31 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)
/* set up vector assignment tracking */ /* set up vector assignment tracking */
size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors); size = sizeof(struct ice_res_tracker) + (sizeof(u16) * vectors);
pf->irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL); pf->sw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
if (!pf->irq_tracker) { if (!pf->sw_irq_tracker) {
ice_dis_msix(pf); ice_dis_msix(pf);
return -ENOMEM; return -ENOMEM;
} }
pf->irq_tracker->num_entries = vectors; /* populate SW interrupts pool with number of OS granted IRQs. */
pf->num_avail_sw_msix = vectors;
pf->sw_irq_tracker->num_entries = vectors;
return 0; /* set up HW vector assignment tracking */
} hw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;
size = sizeof(struct ice_res_tracker) + (sizeof(u16) * hw_vectors);
/** pf->hw_irq_tracker = devm_kzalloc(&pf->pdev->dev, size, GFP_KERNEL);
* ice_clear_interrupt_scheme - Undo things done by ice_init_interrupt_scheme if (!pf->hw_irq_tracker) {
* @pf: board private structure ice_clear_interrupt_scheme(pf);
*/ return -ENOMEM;
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->irq_tracker) {
devm_kfree(&pf->pdev->dev, pf->irq_tracker);
pf->irq_tracker = NULL;
} }
/* 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;
return 0;
} }
/** /**
...@@ -3213,6 +3253,12 @@ static void ice_rebuild(struct ice_pf *pf) ...@@ -3213,6 +3253,12 @@ static void ice_rebuild(struct ice_pf *pf)
if (err) if (err)
goto err_sched_init_port; goto err_sched_init_port;
/* 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); err = ice_vsi_rebuild_all(pf);
if (err) { if (err) {
dev_err(dev, "ice_vsi_rebuild_all failed\n"); dev_err(dev, "ice_vsi_rebuild_all failed\n");
...@@ -3610,7 +3656,7 @@ static void ice_tx_timeout(struct net_device *netdev) ...@@ -3610,7 +3656,7 @@ static void ice_tx_timeout(struct net_device *netdev)
if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
val = rd32(&pf->hw, val = rd32(&pf->hw,
GLINT_DYN_CTL(tx_ring->q_vector->v_idx + GLINT_DYN_CTL(tx_ring->q_vector->v_idx +
tx_ring->vsi->base_vector - 1)); tx_ring->vsi->hw_base_vector));
netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n", netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %d, NTC: 0x%x, HWB: 0x%x, NTU: 0x%x, TAIL: 0x%x, INT: 0x%x\n",
vsi->vsi_num, hung_queue, tx_ring->next_to_clean, vsi->vsi_num, hung_queue, tx_ring->next_to_clean,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment