diff options
author | Preethi Banala <preethi.banala@intel.com> | 2018-09-19 20:23:16 -0400 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2018-10-02 10:16:19 -0400 |
commit | eb0208ec42d319bc09fead0e1afe2bc0c28aeca0 (patch) | |
tree | 0af2e51b50e4ab0f45e35fa4fcb090386f071267 /drivers/net/ethernet/intel/ice/ice_lib.c | |
parent | 5755143dd18d3b7fa97b419d18d9bb4764b7b46f (diff) |
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: Preethi Banala <preethi.banala@intel.com>
Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_lib.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_lib.c | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index a4dfdf35ceab..8f7ee77cb70b 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c | |||
@@ -1039,9 +1039,9 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) | |||
1039 | struct ice_pf *pf = vsi->back; | 1039 | struct ice_pf *pf = vsi->back; |
1040 | int num_q_vectors = 0; | 1040 | int num_q_vectors = 0; |
1041 | 1041 | ||
1042 | if (vsi->base_vector) { | 1042 | if (vsi->sw_base_vector || vsi->hw_base_vector) { |
1043 | dev_dbg(&pf->pdev->dev, "VSI %d has non-zero base vector %d\n", | 1043 | dev_dbg(&pf->pdev->dev, "VSI %d has non-zero HW base vector %d or SW base vector %d\n", |
1044 | vsi->vsi_num, vsi->base_vector); | 1044 | vsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector); |
1045 | return -EEXIST; | 1045 | return -EEXIST; |
1046 | } | 1046 | } |
1047 | 1047 | ||
@@ -1051,6 +1051,21 @@ static int ice_vsi_setup_vector_base(struct ice_vsi *vsi) | |||
1051 | switch (vsi->type) { | 1051 | switch (vsi->type) { |
1052 | case ICE_VSI_PF: | 1052 | case ICE_VSI_PF: |
1053 | num_q_vectors = vsi->num_q_vectors; | 1053 | num_q_vectors = vsi->num_q_vectors; |
1054 | /* reserve slots from OS requested IRQs */ | ||
1055 | vsi->sw_base_vector = ice_get_res(pf, pf->sw_irq_tracker, | ||
1056 | num_q_vectors, vsi->idx); | ||
1057 | if (vsi->sw_base_vector < 0) { | ||
1058 | dev_err(&pf->pdev->dev, | ||
1059 | "Failed to get tracking for %d SW vectors for VSI %d, err=%d\n", | ||
1060 | num_q_vectors, vsi->vsi_num, | ||
1061 | vsi->sw_base_vector); | ||
1062 | return -ENOENT; | ||
1063 | } | ||
1064 | pf->num_avail_sw_msix -= num_q_vectors; | ||
1065 | |||
1066 | /* reserve slots from HW interrupts */ | ||
1067 | vsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker, | ||
1068 | num_q_vectors, vsi->idx); | ||
1054 | break; | 1069 | break; |
1055 | default: | 1070 | default: |
1056 | dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n", | 1071 | 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 | break; | 1073 | break; |
1059 | } | 1074 | } |
1060 | 1075 | ||
1061 | if (num_q_vectors) | 1076 | if (vsi->hw_base_vector < 0) { |
1062 | vsi->base_vector = ice_get_res(pf, pf->irq_tracker, | ||
1063 | num_q_vectors, vsi->idx); | ||
1064 | |||
1065 | if (vsi->base_vector < 0) { | ||
1066 | dev_err(&pf->pdev->dev, | 1077 | dev_err(&pf->pdev->dev, |
1067 | "Failed to get tracking for %d vectors for VSI %d, err=%d\n", | 1078 | "Failed to get tracking for %d HW vectors for VSI %d, err=%d\n", |
1068 | num_q_vectors, vsi->vsi_num, vsi->base_vector); | 1079 | num_q_vectors, vsi->vsi_num, vsi->hw_base_vector); |
1080 | ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, | ||
1081 | vsi->idx); | ||
1082 | pf->num_avail_sw_msix += num_q_vectors; | ||
1069 | return -ENOENT; | 1083 | return -ENOENT; |
1070 | } | 1084 | } |
1071 | 1085 | ||
1086 | pf->num_avail_hw_msix -= num_q_vectors; | ||
1087 | |||
1072 | return 0; | 1088 | return 0; |
1073 | } | 1089 | } |
1074 | 1090 | ||
@@ -1554,7 +1570,7 @@ err_cfg_txqs: | |||
1554 | void ice_vsi_cfg_msix(struct ice_vsi *vsi) | 1570 | void ice_vsi_cfg_msix(struct ice_vsi *vsi) |
1555 | { | 1571 | { |
1556 | struct ice_pf *pf = vsi->back; | 1572 | struct ice_pf *pf = vsi->back; |
1557 | u16 vector = vsi->base_vector; | 1573 | u16 vector = vsi->hw_base_vector; |
1558 | struct ice_hw *hw = &pf->hw; | 1574 | struct ice_hw *hw = &pf->hw; |
1559 | u32 txq = 0, rxq = 0; | 1575 | u32 txq = 0, rxq = 0; |
1560 | int i, q, itr; | 1576 | int i, q, itr; |
@@ -1762,7 +1778,7 @@ int ice_vsi_stop_tx_rings(struct ice_vsi *vsi) | |||
1762 | * the queue to schedule NAPI handler | 1778 | * the queue to schedule NAPI handler |
1763 | */ | 1779 | */ |
1764 | v_idx = vsi->tx_rings[i]->q_vector->v_idx; | 1780 | v_idx = vsi->tx_rings[i]->q_vector->v_idx; |
1765 | wr32(hw, GLINT_DYN_CTL(vsi->base_vector + v_idx), | 1781 | wr32(hw, GLINT_DYN_CTL(vsi->hw_base_vector + v_idx), |
1766 | GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M); | 1782 | GLINT_DYN_CTL_SWINT_TRIG_M | GLINT_DYN_CTL_INTENA_MSK_M); |
1767 | } | 1783 | } |
1768 | status = ice_dis_vsi_txq(vsi->port_info, vsi->num_txq, q_ids, q_teids, | 1784 | 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 | return vsi; | 1955 | return vsi; |
1940 | 1956 | ||
1941 | unroll_vector_base: | 1957 | unroll_vector_base: |
1942 | ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); | 1958 | /* reclaim SW interrupts back to the common pool */ |
1959 | ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); | ||
1960 | pf->num_avail_sw_msix += vsi->num_q_vectors; | ||
1961 | /* reclaim HW interrupt back to the common pool */ | ||
1962 | ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); | ||
1963 | pf->num_avail_hw_msix += vsi->num_q_vectors; | ||
1943 | unroll_alloc_q_vector: | 1964 | unroll_alloc_q_vector: |
1944 | ice_vsi_free_q_vectors(vsi); | 1965 | ice_vsi_free_q_vectors(vsi); |
1945 | unroll_vsi_init: | 1966 | unroll_vsi_init: |
@@ -1960,7 +1981,7 @@ unroll_get_qs: | |||
1960 | static void ice_vsi_release_msix(struct ice_vsi *vsi) | 1981 | static void ice_vsi_release_msix(struct ice_vsi *vsi) |
1961 | { | 1982 | { |
1962 | struct ice_pf *pf = vsi->back; | 1983 | struct ice_pf *pf = vsi->back; |
1963 | u16 vector = vsi->base_vector; | 1984 | u16 vector = vsi->hw_base_vector; |
1964 | struct ice_hw *hw = &pf->hw; | 1985 | struct ice_hw *hw = &pf->hw; |
1965 | u32 txq = 0; | 1986 | u32 txq = 0; |
1966 | u32 rxq = 0; | 1987 | u32 rxq = 0; |
@@ -1992,7 +2013,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi) | |||
1992 | void ice_vsi_free_irq(struct ice_vsi *vsi) | 2013 | void ice_vsi_free_irq(struct ice_vsi *vsi) |
1993 | { | 2014 | { |
1994 | struct ice_pf *pf = vsi->back; | 2015 | struct ice_pf *pf = vsi->back; |
1995 | int base = vsi->base_vector; | 2016 | int base = vsi->sw_base_vector; |
1996 | 2017 | ||
1997 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { | 2018 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { |
1998 | int i; | 2019 | int i; |
@@ -2000,6 +2021,8 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) | |||
2000 | if (!vsi->q_vectors || !vsi->irqs_ready) | 2021 | if (!vsi->q_vectors || !vsi->irqs_ready) |
2001 | return; | 2022 | return; |
2002 | 2023 | ||
2024 | ice_vsi_release_msix(vsi); | ||
2025 | |||
2003 | vsi->irqs_ready = false; | 2026 | vsi->irqs_ready = false; |
2004 | for (i = 0; i < vsi->num_q_vectors; i++) { | 2027 | for (i = 0; i < vsi->num_q_vectors; i++) { |
2005 | u16 vector = i + base; | 2028 | u16 vector = i + base; |
@@ -2022,7 +2045,6 @@ void ice_vsi_free_irq(struct ice_vsi *vsi) | |||
2022 | devm_free_irq(&pf->pdev->dev, irq_num, | 2045 | devm_free_irq(&pf->pdev->dev, irq_num, |
2023 | vsi->q_vectors[i]); | 2046 | vsi->q_vectors[i]); |
2024 | } | 2047 | } |
2025 | ice_vsi_release_msix(vsi); | ||
2026 | } | 2048 | } |
2027 | } | 2049 | } |
2028 | 2050 | ||
@@ -2110,6 +2132,9 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id) | |||
2110 | int start = res->search_hint; | 2132 | int start = res->search_hint; |
2111 | int end = start; | 2133 | int end = start; |
2112 | 2134 | ||
2135 | if ((start + needed) > res->num_entries) | ||
2136 | return -ENOMEM; | ||
2137 | |||
2113 | id |= ICE_RES_VALID_BIT; | 2138 | id |= ICE_RES_VALID_BIT; |
2114 | 2139 | ||
2115 | do { | 2140 | do { |
@@ -2183,9 +2208,9 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id) | |||
2183 | */ | 2208 | */ |
2184 | void ice_vsi_dis_irq(struct ice_vsi *vsi) | 2209 | void ice_vsi_dis_irq(struct ice_vsi *vsi) |
2185 | { | 2210 | { |
2211 | int base = vsi->sw_base_vector; | ||
2186 | struct ice_pf *pf = vsi->back; | 2212 | struct ice_pf *pf = vsi->back; |
2187 | struct ice_hw *hw = &pf->hw; | 2213 | struct ice_hw *hw = &pf->hw; |
2188 | int base = vsi->base_vector; | ||
2189 | u32 val; | 2214 | u32 val; |
2190 | int i; | 2215 | int i; |
2191 | 2216 | ||
@@ -2218,8 +2243,8 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi) | |||
2218 | 2243 | ||
2219 | /* disable each interrupt */ | 2244 | /* disable each interrupt */ |
2220 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { | 2245 | if (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) { |
2221 | for (i = vsi->base_vector; | 2246 | for (i = vsi->hw_base_vector; |
2222 | i < (vsi->num_q_vectors + vsi->base_vector); i++) | 2247 | i < (vsi->num_q_vectors + vsi->hw_base_vector); i++) |
2223 | wr32(hw, GLINT_DYN_CTL(i), 0); | 2248 | wr32(hw, GLINT_DYN_CTL(i), 0); |
2224 | 2249 | ||
2225 | ice_flush(hw); | 2250 | ice_flush(hw); |
@@ -2262,8 +2287,10 @@ int ice_vsi_release(struct ice_vsi *vsi) | |||
2262 | ice_vsi_close(vsi); | 2287 | ice_vsi_close(vsi); |
2263 | 2288 | ||
2264 | /* reclaim interrupt vectors back to PF */ | 2289 | /* reclaim interrupt vectors back to PF */ |
2265 | ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); | 2290 | ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); |
2266 | pf->num_avail_msix += vsi->num_q_vectors; | 2291 | pf->num_avail_sw_msix += vsi->num_q_vectors; |
2292 | ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); | ||
2293 | pf->num_avail_hw_msix += vsi->num_q_vectors; | ||
2267 | 2294 | ||
2268 | ice_remove_vsi_fltr(&pf->hw, vsi->idx); | 2295 | ice_remove_vsi_fltr(&pf->hw, vsi->idx); |
2269 | ice_vsi_delete(vsi); | 2296 | ice_vsi_delete(vsi); |
@@ -2299,8 +2326,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi) | |||
2299 | return -EINVAL; | 2326 | return -EINVAL; |
2300 | 2327 | ||
2301 | ice_vsi_free_q_vectors(vsi); | 2328 | ice_vsi_free_q_vectors(vsi); |
2302 | ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); | 2329 | ice_free_res(vsi->back->sw_irq_tracker, vsi->sw_base_vector, vsi->idx); |
2303 | vsi->base_vector = 0; | 2330 | ice_free_res(vsi->back->hw_irq_tracker, vsi->hw_base_vector, vsi->idx); |
2331 | vsi->sw_base_vector = 0; | ||
2332 | vsi->hw_base_vector = 0; | ||
2304 | ice_vsi_clear_rings(vsi); | 2333 | ice_vsi_clear_rings(vsi); |
2305 | ice_vsi_free_arrays(vsi, false); | 2334 | ice_vsi_free_arrays(vsi, false); |
2306 | ice_vsi_set_num_qs(vsi); | 2335 | ice_vsi_set_num_qs(vsi); |