Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1086487/?format=api
{ "id": 1086487, "url": "http://patchwork.ozlabs.org/api/patches/1086487/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190416173052.28928-8-anirudh.venkataramanan@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20190416173052.28928-8-anirudh.venkataramanan@intel.com>", "list_archive_url": null, "date": "2019-04-16T17:30:44", "name": "[S20,07/15] ice: Refactor interrupt tracking", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "8c926bd75c738958d5d992ac77bd73782cc5f0b5", "submitter": { "id": 73601, "url": "http://patchwork.ozlabs.org/api/people/73601/?format=api", "name": "Anirudh Venkataramanan", "email": "anirudh.venkataramanan@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20190416173052.28928-8-anirudh.venkataramanan@intel.com/mbox/", "series": [ { "id": 103108, "url": "http://patchwork.ozlabs.org/api/series/103108/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=103108", "date": "2019-04-16T17:30:37", "name": "Fixes and feature updates for ice", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/103108/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1086487/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1086487/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=osuosl.org\n\t(client-ip=140.211.166.136; helo=silver.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 44kC934935z9s3l\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 17 Apr 2019 03:31:51 +1000 (AEST)", "from localhost (localhost [127.0.0.1])\n\tby silver.osuosl.org (Postfix) with ESMTP id 18904241AE;\n\tTue, 16 Apr 2019 17:31:50 +0000 (UTC)", "from silver.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id JK6g98nQkuSR; Tue, 16 Apr 2019 17:31:31 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby silver.osuosl.org (Postfix) with ESMTP id 1909023223;\n\tTue, 16 Apr 2019 17:31:31 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 0988A1BF28D\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:29 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id 03D038796C\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:29 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id c041NjflBpx0 for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:27 +0000 (UTC)", "from mga09.intel.com (mga09.intel.com [134.134.136.24])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id C6A8387648\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 16 Apr 2019 17:31:26 +0000 (UTC)", "from orsmga002.jf.intel.com ([10.7.209.21])\n\tby orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t16 Apr 2019 10:31:25 -0700", "from shasta.jf.intel.com ([10.166.244.191])\n\tby orsmga002.jf.intel.com with ESMTP; 16 Apr 2019 10:31:25 -0700" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.60,358,1549958400\"; d=\"scan'208\";a=\"151390481\"", "From": "Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 16 Apr 2019 10:30:44 -0700", "Message-Id": "<20190416173052.28928-8-anirudh.venkataramanan@intel.com>", "X-Mailer": "git-send-email 2.20.1", "In-Reply-To": "<20190416173052.28928-1-anirudh.venkataramanan@intel.com>", "References": "<20190416173052.28928-1-anirudh.venkataramanan@intel.com>", "MIME-Version": "1.0", "Subject": "[Intel-wired-lan] [PATCH S20 07/15] ice: Refactor interrupt tracking", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "From: Brett Creeley <brett.creeley@intel.com>\n\nCurrently we have two MSI-x (IRQ) trackers, one for OS requested MSI-x\nentries (sw_irq_tracker) and one for hardware MSI-x vectors\n(hw_irq_tracker). Generally the sw_irq_tracker has less entries than the\nhw_irq_tracker because the hw_irq_tracker has entries equal to the max\nallowed MSI-x per PF and the sw_irq_tracker is mainly the minimum (non\nSR-IOV portion of the vectors, kernel granted IRQs). All of the non\nSR-IOV portions of the driver (i.e. LAN queues, RDMA queues, OICR, etc.)\ntake at least one of each type of tracker resource. SR-IOV only grabs\nentries from the hw_irq_tracker. There are a few issues with this approach\nthat can be seen when doing any kind of device reconfiguration (i.e.\nethtool -L, SR-IOV, etc.). One of them being, any time the driver creates\nan ice_q_vector and associates it to a LAN queue pair it will grab and\nuse one entry from the hw_irq_tracker and one from the sw_irq_tracker.\nIf the indices on these does not match it will cause a Tx timeout, which\nwill cause a reset and then the indices will match up again and traffic\nwill resume. The mismatched indices come from the trackers not being the\nsame size and/or the search_hint in the two trackers not being equal.\nAnother reason for the refactor is the co-existence of features with\nSR-IOV. If SR-IOV is enabled and the interrupts are taken from the end\nof the sw_irq_tracker then other features can no longer use this space\nbecause the hardware has now given the remaining interrupts to SR-IOV.\n\nThis patch reworks how we track MSI-x vectors by removing the\nhw_irq_tracker completely and instead MSI-x resources needed for SR-IOV\nare determined all at once instead of per VF. This can be done because\nwhen creating VFs we know how many are wanted and how many MSI-x vectors\neach VF needs. This also allows us to start using MSI-x resources from\nthe end of the PF's allowed MSI-x vectors so we are less likely to use\nentries needed for other features (i.e. RDMA, L2 Offload, etc).\n\nThis patch also reworks the ice_res_tracker structure by removing the\nsearch_hint and adding a new member - \"end\". Instead of having a\nsearch_hint we will always search from 0. The new member, \"end\", will be\nused to manipulate the end of the ice_res_tracker (specifically\nsw_irq_tracker) during runtime based on MSI-x vectors needed by SR-IOV.\nIn the normal case, the end of ice_res_tracker will be equal to the\nice_res_tracker's num_entries.\n\nThe sriov_base_vector member was added to the PF structure. It is used\nto represent the starting MSI-x index of all the needed MSI-x vectors\nfor all SR-IOV VFs. Depending on how many MSI-x are needed, SR-IOV may\nhave to take resources from the sw_irq_tracker. This is done by setting\nthe sw_irq_tracker->end equal to the pf->sriov_base_vector. When all\nSR-IOV VFs are removed then the sw_irq_tracker->end is reset back to\nsw_irq_tracker->num_entries. The sriov_base_vector, along with the VF's\nnumber of MSI-x (pf->num_vf_msix), vf_id, and the base MSI-x index on\nthe PF (pf->hw.func_caps.common_cap.msix_vector_first_id), is used to\ncalculate the first HW absolute MSI-x index for each VF, which is used\nto write to the VPINT_ALLOC[_PCI] and GLINT_VECT2FUNC registers to\nprogram the VFs MSI-x PCI configuration bits. Also, the sriov_base_vector\nis used along with VF's num_vf_msix, vf_id, and q_vector->v_idx to\ndetermine the MSI-x register index (used for writing to GLINT_DYN_CTL)\nwithin the PF's space.\n\nInterrupt changes removed any references to hw_base_vector, hw_oicr_idx,\nand hw_irq_tracker. Only sw_base_vector, sw_oicr_idx, and sw_irq_tracker\nvariables remain. Change all of these by removing the \"sw_\" prefix to\nhelp avoid confusion with these variables and their use.\n\nSigned-off-by: Brett Creeley <brett.creeley@intel.com>\nSigned-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com>\n---\n drivers/net/ethernet/intel/ice/ice.h | 21 +-\n drivers/net/ethernet/intel/ice/ice_ethtool.c | 5 +-\n drivers/net/ethernet/intel/ice/ice_lib.c | 179 +++++------------\n drivers/net/ethernet/intel/ice/ice_main.c | 82 +++-----\n .../net/ethernet/intel/ice/ice_virtchnl_pf.c | 186 ++++++++++++++++--\n .../net/ethernet/intel/ice/ice_virtchnl_pf.h | 8 +\n 6 files changed, 263 insertions(+), 218 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 5c5b9e3e9e5c..fe7241df8ee5 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -167,7 +167,7 @@ struct ice_tc_cfg {\n \n struct ice_res_tracker {\n \tu16 num_entries;\n-\tu16 search_hint;\n+\tu16 end;\n \tu16 list[1];\n };\n \n@@ -252,8 +252,7 @@ struct ice_vsi {\n \tu32 rx_buf_failed;\n \tu32 rx_page_failed;\n \tint num_q_vectors;\n-\tint sw_base_vector;\t\t/* Irq base for OS reserved vectors */\n-\tint hw_base_vector;\t\t/* HW (absolute) index of a vector */\n+\tint base_vector;\t\t/* Irq base for OS reserved vectors */\n \tenum ice_vsi_type type;\n \tu16 vsi_num;\t\t\t/* HW (absolute) index of this VSI */\n \tu16 idx;\t\t\t/* software index in pf->vsi[] */\n@@ -348,10 +347,12 @@ struct ice_pf {\n \n \t/* OS reserved IRQ details */\n \tstruct msix_entry *msix_entries;\n-\tstruct ice_res_tracker *sw_irq_tracker;\n-\n-\t/* HW reserved Interrupts for this PF */\n-\tstruct ice_res_tracker *hw_irq_tracker;\n+\tstruct ice_res_tracker *irq_tracker;\n+\t/* First MSIX vector used by SR-IOV VFs. Calculated by subtracting the\n+\t * number of MSIX vectors needed for all SR-IOV VFs from the number of\n+\t * MSIX vectors allowed on this PF.\n+\t */\n+\tu16 sriov_base_vector;\n \n \tstruct ice_vsi **vsi;\t\t/* VSIs created by the driver */\n \tstruct ice_sw *first_sw;\t/* first switch created by firmware */\n@@ -373,10 +374,8 @@ struct ice_pf {\n \tstruct mutex sw_mutex;\t\t/* lock for protecting VSI alloc flow */\n \tu32 msg_enable;\n \tu32 hw_csum_rx_error;\n-\tu32 sw_oicr_idx;\t/* Other interrupt cause SW vector index */\n+\tu32 oicr_idx;\t\t/* Other interrupt cause MSIX vector index */\n \tu32 num_avail_sw_msix;\t/* remaining MSIX SW vectors left unclaimed */\n-\tu32 hw_oicr_idx;\t/* Other interrupt cause vector HW index */\n-\tu32 num_avail_hw_msix;\t/* remaining HW MSIX vectors left unclaimed */\n \tu32 num_lan_msix;\t/* Total MSIX vectors for base driver */\n \tu16 num_lan_tx;\t\t/* num LAN Tx queues setup */\n \tu16 num_lan_rx;\t\t/* num LAN Rx queues setup */\n@@ -418,7 +417,7 @@ ice_irq_dynamic_ena(struct ice_hw *hw, struct ice_vsi *vsi,\n \t\t struct ice_q_vector *q_vector)\n {\n \tu32 vector = (vsi && q_vector) ? q_vector->reg_idx :\n-\t\t\t\t((struct ice_pf *)hw->back)->hw_oicr_idx;\n+\t\t\t\t((struct ice_pf *)hw->back)->oicr_idx;\n \tint itr = ICE_ITR_NONE;\n \tu32 val;\n \ndiff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c\nindex 9dd628e20091..77c98b121e62 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c\n@@ -772,7 +772,7 @@ static u64 ice_intr_test(struct net_device *netdev)\n \n \tnetdev_info(netdev, \"interrupt test\\n\");\n \n-\twr32(&pf->hw, GLINT_DYN_CTL(pf->sw_oicr_idx),\n+\twr32(&pf->hw, GLINT_DYN_CTL(pf->oicr_idx),\n \t GLINT_DYN_CTL_SW_ITR_INDX_M |\n \t GLINT_DYN_CTL_INTENA_MSK_M |\n \t GLINT_DYN_CTL_SWINT_TRIG_M);\n@@ -2987,8 +2987,7 @@ ice_set_rc_coalesce(enum ice_container_type c_type, struct ethtool_coalesce *ec,\n \n \t\tif (ec->rx_coalesce_usecs_high != rc->ring->q_vector->intrl) {\n \t\t\trc->ring->q_vector->intrl = ec->rx_coalesce_usecs_high;\n-\t\t\twr32(&pf->hw, GLINT_RATE(vsi->hw_base_vector +\n-\t\t\t\t\t\t rc->ring->q_vector->v_idx),\n+\t\t\twr32(&pf->hw, GLINT_RATE(rc->ring->q_vector->reg_idx),\n \t\t\t ice_intrl_usec_to_reg(ec->rx_coalesce_usecs_high,\n \t\t\t\t\t\t pf->hw.intrl_gran));\n \t\t}\ndiff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c\nindex 95323ee49e58..515b154547c5 100644\n--- a/drivers/net/ethernet/intel/ice/ice_lib.c\n+++ b/drivers/net/ethernet/intel/ice/ice_lib.c\n@@ -1168,61 +1168,32 @@ static int ice_vsi_alloc_q_vectors(struct ice_vsi *vsi)\n static int ice_vsi_setup_vector_base(struct ice_vsi *vsi)\n {\n \tstruct ice_pf *pf = vsi->back;\n-\tint num_q_vectors = 0;\n+\tu16 num_q_vectors;\n \n-\tif (vsi->sw_base_vector || vsi->hw_base_vector) {\n-\t\tdev_dbg(&pf->pdev->dev, \"VSI %d has non-zero HW base vector %d or SW base vector %d\\n\",\n-\t\t\tvsi->vsi_num, vsi->hw_base_vector, vsi->sw_base_vector);\n+\t/* SRIOV doesn't grab irq_tracker entries for each VSI */\n+\tif (vsi->type == ICE_VSI_VF)\n+\t\treturn 0;\n+\n+\tif (vsi->base_vector) {\n+\t\tdev_dbg(&pf->pdev->dev, \"VSI %d has non-zero base vector %d\\n\",\n+\t\t\tvsi->vsi_num, vsi->base_vector);\n \t\treturn -EEXIST;\n \t}\n \n \tif (!test_bit(ICE_FLAG_MSIX_ENA, pf->flags))\n \t\treturn -ENOENT;\n \n-\tswitch (vsi->type) {\n-\tcase ICE_VSI_PF:\n-\t\tnum_q_vectors = vsi->num_q_vectors;\n-\t\t/* reserve slots from OS requested IRQs */\n-\t\tvsi->sw_base_vector = ice_get_res(pf, pf->sw_irq_tracker,\n-\t\t\t\t\t\t num_q_vectors, vsi->idx);\n-\t\tif (vsi->sw_base_vector < 0) {\n-\t\t\tdev_err(&pf->pdev->dev,\n-\t\t\t\t\"Failed to get tracking for %d SW vectors for VSI %d, err=%d\\n\",\n-\t\t\t\tnum_q_vectors, vsi->vsi_num,\n-\t\t\t\tvsi->sw_base_vector);\n-\t\t\treturn -ENOENT;\n-\t\t}\n-\t\tpf->num_avail_sw_msix -= num_q_vectors;\n-\n-\t\t/* reserve slots from HW interrupts */\n-\t\tvsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker,\n-\t\t\t\t\t\t num_q_vectors, vsi->idx);\n-\t\tbreak;\n-\tcase ICE_VSI_VF:\n-\t\t/* take VF misc vector and data vectors into account */\n-\t\tnum_q_vectors = pf->num_vf_msix;\n-\t\t/* For VF VSI, reserve slots only from HW interrupts */\n-\t\tvsi->hw_base_vector = ice_get_res(pf, pf->hw_irq_tracker,\n-\t\t\t\t\t\t num_q_vectors, vsi->idx);\n-\t\tbreak;\n-\tdefault:\n-\t\tdev_warn(&pf->pdev->dev, \"Unknown VSI type %d\\n\", vsi->type);\n-\t\tbreak;\n-\t}\n-\n-\tif (vsi->hw_base_vector < 0) {\n+\tnum_q_vectors = vsi->num_q_vectors;\n+\t/* reserve slots from OS requested IRQs */\n+\tvsi->base_vector = ice_get_res(pf, pf->irq_tracker, num_q_vectors,\n+\t\t\t\t vsi->idx);\n+\tif (vsi->base_vector < 0) {\n \t\tdev_err(&pf->pdev->dev,\n-\t\t\t\"Failed to get tracking for %d HW vectors for VSI %d, err=%d\\n\",\n-\t\t\tnum_q_vectors, vsi->vsi_num, vsi->hw_base_vector);\n-\t\tif (vsi->type != ICE_VSI_VF) {\n-\t\t\tice_free_res(pf->sw_irq_tracker,\n-\t\t\t\t vsi->sw_base_vector, vsi->idx);\n-\t\t\tpf->num_avail_sw_msix += num_q_vectors;\n-\t\t}\n+\t\t\t\"Failed to get tracking for %d vectors for VSI %d, err=%d\\n\",\n+\t\t\tnum_q_vectors, vsi->vsi_num, vsi->base_vector);\n \t\treturn -ENOENT;\n \t}\n-\n-\tpf->num_avail_hw_msix -= num_q_vectors;\n+\tpf->num_avail_sw_msix -= num_q_vectors;\n \n \treturn 0;\n }\n@@ -2261,7 +2232,14 @@ ice_vsi_set_q_vectors_reg_idx(struct ice_vsi *vsi)\n \t\t\tgoto clear_reg_idx;\n \t\t}\n \n-\t\tq_vector->reg_idx = q_vector->v_idx + vsi->hw_base_vector;\n+\t\tif (vsi->type == ICE_VSI_VF) {\n+\t\t\tstruct ice_vf *vf = &vsi->back->vf[vsi->vf_id];\n+\n+\t\t\tq_vector->reg_idx = ice_calc_vf_reg_idx(vf, q_vector);\n+\t\t} else {\n+\t\t\tq_vector->reg_idx =\n+\t\t\t\tq_vector->v_idx + vsi->base_vector;\n+\t\t}\n \t}\n \n \treturn 0;\n@@ -2416,17 +2394,6 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,\n \t\tif (ret)\n \t\t\tgoto unroll_alloc_q_vector;\n \n-\t\t/* Setup Vector base only during VF init phase or when VF asks\n-\t\t * for more vectors than assigned number. In all other cases,\n-\t\t * assign hw_base_vector to the value given earlier.\n-\t\t */\n-\t\tif (test_bit(ICE_VF_STATE_CFG_INTR, pf->vf[vf_id].vf_states)) {\n-\t\t\tret = ice_vsi_setup_vector_base(vsi);\n-\t\t\tif (ret)\n-\t\t\t\tgoto unroll_vector_base;\n-\t\t} else {\n-\t\t\tvsi->hw_base_vector = pf->vf[vf_id].first_vector_idx;\n-\t\t}\n \t\tret = ice_vsi_set_q_vectors_reg_idx(vsi);\n \t\tif (ret)\n \t\t\tgoto unroll_vector_base;\n@@ -2470,11 +2437,8 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,\n \n unroll_vector_base:\n \t/* reclaim SW interrupts back to the common pool */\n-\tice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);\n+\tice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);\n \tpf->num_avail_sw_msix += vsi->num_q_vectors;\n-\t/* reclaim HW interrupt back to the common pool */\n-\tice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);\n-\tpf->num_avail_hw_msix += vsi->num_q_vectors;\n unroll_alloc_q_vector:\n \tice_vsi_free_q_vectors(vsi);\n unroll_vsi_init:\n@@ -2495,17 +2459,17 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,\n static void ice_vsi_release_msix(struct ice_vsi *vsi)\n {\n \tstruct ice_pf *pf = vsi->back;\n-\tu16 vector = vsi->hw_base_vector;\n \tstruct ice_hw *hw = &pf->hw;\n \tu32 txq = 0;\n \tu32 rxq = 0;\n \tint i, q;\n \n-\tfor (i = 0; i < vsi->num_q_vectors; i++, vector++) {\n+\tfor (i = 0; i < vsi->num_q_vectors; i++) {\n \t\tstruct ice_q_vector *q_vector = vsi->q_vectors[i];\n+\t\tu16 reg_idx = q_vector->reg_idx;\n \n-\t\twr32(hw, GLINT_ITR(ICE_IDX_ITR0, vector), 0);\n-\t\twr32(hw, GLINT_ITR(ICE_IDX_ITR1, vector), 0);\n+\t\twr32(hw, GLINT_ITR(ICE_IDX_ITR0, reg_idx), 0);\n+\t\twr32(hw, GLINT_ITR(ICE_IDX_ITR1, reg_idx), 0);\n \t\tfor (q = 0; q < q_vector->num_ring_tx; q++) {\n \t\t\twr32(hw, QINT_TQCTL(vsi->txq_map[txq]), 0);\n \t\t\ttxq++;\n@@ -2527,7 +2491,7 @@ static void ice_vsi_release_msix(struct ice_vsi *vsi)\n void ice_vsi_free_irq(struct ice_vsi *vsi)\n {\n \tstruct ice_pf *pf = vsi->back;\n-\tint base = vsi->sw_base_vector;\n+\tint base = vsi->base_vector;\n \n \tif (test_bit(ICE_FLAG_MSIX_ENA, pf->flags)) {\n \t\tint i;\n@@ -2623,11 +2587,11 @@ int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)\n \tint count = 0;\n \tint i;\n \n-\tif (!res || index >= res->num_entries)\n+\tif (!res || index >= res->end)\n \t\treturn -EINVAL;\n \n \tid |= ICE_RES_VALID_BIT;\n-\tfor (i = index; i < res->num_entries && res->list[i] == id; i++) {\n+\tfor (i = index; i < res->end && res->list[i] == id; i++) {\n \t\tres->list[i] = 0;\n \t\tcount++;\n \t}\n@@ -2645,10 +2609,9 @@ int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)\n */\n static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)\n {\n-\tint start = res->search_hint;\n-\tint end = start;\n+\tint start = 0, end = 0;\n \n-\tif ((start + needed) > res->num_entries)\n+\tif (needed > res->end)\n \t\treturn -ENOMEM;\n \n \tid |= ICE_RES_VALID_BIT;\n@@ -2657,7 +2620,7 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)\n \t\t/* skip already allocated entries */\n \t\tif (res->list[end++] & ICE_RES_VALID_BIT) {\n \t\t\tstart = end;\n-\t\t\tif ((start + needed) > res->num_entries)\n+\t\t\tif ((start + needed) > res->end)\n \t\t\t\tbreak;\n \t\t}\n \n@@ -2668,13 +2631,9 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)\n \t\t\twhile (i != end)\n \t\t\t\tres->list[i++] = id;\n \n-\t\t\tif (end == res->num_entries)\n-\t\t\t\tend = 0;\n-\n-\t\t\tres->search_hint = end;\n \t\t\treturn start;\n \t\t}\n-\t} while (1);\n+\t} while (end < res->end);\n \n \treturn -ENOMEM;\n }\n@@ -2686,16 +2645,11 @@ static int ice_search_res(struct ice_res_tracker *res, u16 needed, u16 id)\n * @needed: size of the block needed\n * @id: identifier to track owner\n *\n- * Returns the base item index of the block, or -ENOMEM for error\n- * The search_hint trick and lack of advanced fit-finding only works\n- * because we're highly likely to have all the same sized requests.\n- * Linear search time and any fragmentation should be minimal.\n+ * Returns the base item index of the block, or negative for error\n */\n int\n ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)\n {\n-\tint ret;\n-\n \tif (!res || !pf)\n \t\treturn -EINVAL;\n \n@@ -2706,16 +2660,7 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)\n \t\treturn -EINVAL;\n \t}\n \n-\t/* search based on search_hint */\n-\tret = ice_search_res(res, needed, id);\n-\n-\tif (ret < 0) {\n-\t\t/* previous search failed. Reset search hint and try again */\n-\t\tres->search_hint = 0;\n-\t\tret = ice_search_res(res, needed, id);\n-\t}\n-\n-\treturn ret;\n+\treturn ice_search_res(res, needed, id);\n }\n \n /**\n@@ -2724,7 +2669,7 @@ ice_get_res(struct ice_pf *pf, struct ice_res_tracker *res, u16 needed, u16 id)\n */\n void ice_vsi_dis_irq(struct ice_vsi *vsi)\n {\n-\tint base = vsi->sw_base_vector;\n+\tint base = vsi->base_vector;\n \tstruct ice_pf *pf = vsi->back;\n \tstruct ice_hw *hw = &pf->hw;\n \tu32 val;\n@@ -2777,15 +2722,12 @@ void ice_vsi_dis_irq(struct ice_vsi *vsi)\n */\n int ice_vsi_release(struct ice_vsi *vsi)\n {\n-\tstruct ice_vf *vf = NULL;\n \tstruct ice_pf *pf;\n \n \tif (!vsi->back)\n \t\treturn -ENODEV;\n \tpf = vsi->back;\n \n-\tif (vsi->type == ICE_VSI_VF)\n-\t\tvf = &pf->vf[vsi->vf_id];\n \t/* do not unregister while driver is in the reset recovery pending\n \t * state. Since reset/rebuild happens through PF service task workqueue,\n \t * it's not a good idea to unregister netdev that is associated to the\n@@ -2803,21 +2745,15 @@ int ice_vsi_release(struct ice_vsi *vsi)\n \t\tice_vsi_dis_irq(vsi);\n \tice_vsi_close(vsi);\n \n-\t/* reclaim interrupt vectors back to PF */\n+\t/* SR-IOV determines needed MSIX resources all at once instead of per\n+\t * VSI since when VFs are spawned we know how many VFs there are and how\n+\t * many interrupts each VF needs. SR-IOV MSIX resources are also\n+\t * cleared in the same manner.\n+\t */\n \tif (vsi->type != ICE_VSI_VF) {\n \t\t/* reclaim SW interrupts back to the common pool */\n-\t\tice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);\n+\t\tice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);\n \t\tpf->num_avail_sw_msix += vsi->num_q_vectors;\n-\t\t/* reclaim HW interrupts back to the common pool */\n-\t\tice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector, vsi->idx);\n-\t\tpf->num_avail_hw_msix += vsi->num_q_vectors;\n-\t} else if (test_bit(ICE_VF_STATE_CFG_INTR, vf->vf_states)) {\n-\t\t/* Reclaim VF resources back only while freeing all VFs or\n-\t\t * vector reassignment is requested\n-\t\t */\n-\t\tice_free_res(pf->hw_irq_tracker, vf->first_vector_idx,\n-\t\t\t vsi->idx);\n-\t\tpf->num_avail_hw_msix += pf->num_vf_msix;\n \t}\n \n \tif (vsi->type == ICE_VSI_PF)\n@@ -2873,24 +2809,17 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)\n \tice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);\n \tice_vsi_free_q_vectors(vsi);\n \n+\t/* SR-IOV determines needed MSIX resources all at once instead of per\n+\t * VSI since when VFs are spawned we know how many VFs there are and how\n+\t * many interrupts each VF needs. SR-IOV MSIX resources are also\n+\t * cleared in the same manner.\n+\t */\n \tif (vsi->type != ICE_VSI_VF) {\n \t\t/* reclaim SW interrupts back to the common pool */\n-\t\tice_free_res(pf->sw_irq_tracker, vsi->sw_base_vector, vsi->idx);\n+\t\tice_free_res(pf->irq_tracker, vsi->base_vector, vsi->idx);\n \t\tpf->num_avail_sw_msix += vsi->num_q_vectors;\n-\t\tvsi->sw_base_vector = 0;\n-\t\t/* reclaim HW interrupts back to the common pool */\n-\t\tice_free_res(pf->hw_irq_tracker, vsi->hw_base_vector,\n-\t\t\t vsi->idx);\n-\t\tpf->num_avail_hw_msix += vsi->num_q_vectors;\n-\t} else {\n-\t\t/* Reclaim VF resources back to the common pool for reset and\n-\t\t * and rebuild, with vector reassignment\n-\t\t */\n-\t\tice_free_res(pf->hw_irq_tracker, vf->first_vector_idx,\n-\t\t\t vsi->idx);\n-\t\tpf->num_avail_hw_msix += pf->num_vf_msix;\n+\t\tvsi->base_vector = 0;\n \t}\n-\tvsi->hw_base_vector = 0;\n \n \tice_vsi_clear_rings(vsi);\n \tice_vsi_free_arrays(vsi);\n@@ -2916,10 +2845,6 @@ int ice_vsi_rebuild(struct ice_vsi *vsi)\n \t\tif (ret)\n \t\t\tgoto err_rings;\n \n-\t\tret = ice_vsi_setup_vector_base(vsi);\n-\t\tif (ret)\n-\t\t\tgoto err_vectors;\n-\n \t\tret = ice_vsi_set_q_vectors_reg_idx(vsi);\n \t\tif (ret)\n \t\t\tgoto err_vectors;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c\nindex 4ca2d7a8d172..6fc4d8176d14 100644\n--- a/drivers/net/ethernet/intel/ice/ice_main.c\n+++ b/drivers/net/ethernet/intel/ice/ice_main.c\n@@ -95,7 +95,7 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)\n \t\t\t\t/* Trigger sw interrupt to revive the queue */\n \t\t\t\tv_idx = tx_ring->q_vector->v_idx;\n \t\t\t\twr32(&vsi->back->hw,\n-\t\t\t\t GLINT_DYN_CTL(vsi->hw_base_vector + v_idx),\n+\t\t\t\t GLINT_DYN_CTL(vsi->base_vector + v_idx),\n \t\t\t\t (itr << GLINT_DYN_CTL_ITR_INDX_S) |\n \t\t\t\t GLINT_DYN_CTL_SWINT_TRIG_M |\n \t\t\t\t GLINT_DYN_CTL_INTENA_MSK_M);\n@@ -1327,7 +1327,7 @@ static int ice_vsi_req_irq_msix(struct ice_vsi *vsi, char *basename)\n {\n \tint q_vectors = vsi->num_q_vectors;\n \tstruct ice_pf *pf = vsi->back;\n-\tint base = vsi->sw_base_vector;\n+\tint base = vsi->base_vector;\n \tint rx_int_idx = 0;\n \tint tx_int_idx = 0;\n \tint vector, err;\n@@ -1408,7 +1408,7 @@ static void ice_ena_misc_vector(struct ice_pf *pf)\n \twr32(hw, PFINT_OICR_ENA, val);\n \n \t/* SW_ITR_IDX = 0, but don't change INTENA */\n-\twr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx),\n+\twr32(hw, GLINT_DYN_CTL(pf->oicr_idx),\n \t GLINT_DYN_CTL_SW_ITR_INDX_M | GLINT_DYN_CTL_INTENA_MSK_M);\n }\n \n@@ -1561,15 +1561,13 @@ static void ice_free_irq_msix_misc(struct ice_pf *pf)\n \tice_flush(hw);\n \n \tif (test_bit(ICE_FLAG_MSIX_ENA, pf->flags) && pf->msix_entries) {\n-\t\tsynchronize_irq(pf->msix_entries[pf->sw_oicr_idx].vector);\n+\t\tsynchronize_irq(pf->msix_entries[pf->oicr_idx].vector);\n \t\tdevm_free_irq(&pf->pdev->dev,\n-\t\t\t pf->msix_entries[pf->sw_oicr_idx].vector, pf);\n+\t\t\t pf->msix_entries[pf->oicr_idx].vector, pf);\n \t}\n \n \tpf->num_avail_sw_msix += 1;\n-\tice_free_res(pf->sw_irq_tracker, pf->sw_oicr_idx, ICE_RES_MISC_VEC_ID);\n-\tpf->num_avail_hw_msix += 1;\n-\tice_free_res(pf->hw_irq_tracker, pf->hw_oicr_idx, ICE_RES_MISC_VEC_ID);\n+\tice_free_res(pf->irq_tracker, pf->oicr_idx, ICE_RES_MISC_VEC_ID);\n }\n \n /**\n@@ -1623,43 +1621,31 @@ static int ice_req_irq_msix_misc(struct ice_pf *pf)\n \tif (ice_is_reset_in_progress(pf->state))\n \t\tgoto skip_req_irq;\n \n-\t/* reserve one vector in sw_irq_tracker for misc interrupts */\n-\toicr_idx = ice_get_res(pf, pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n+\t/* reserve one vector in irq_tracker for misc interrupts */\n+\toicr_idx = ice_get_res(pf, pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n \tif (oicr_idx < 0)\n \t\treturn oicr_idx;\n \n \tpf->num_avail_sw_msix -= 1;\n-\tpf->sw_oicr_idx = oicr_idx;\n-\n-\t/* reserve one vector in hw_irq_tracker for misc interrupts */\n-\toicr_idx = ice_get_res(pf, pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n-\tif (oicr_idx < 0) {\n-\t\tice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n-\t\tpf->num_avail_sw_msix += 1;\n-\t\treturn oicr_idx;\n-\t}\n-\tpf->num_avail_hw_msix -= 1;\n-\tpf->hw_oicr_idx = oicr_idx;\n+\tpf->oicr_idx = oicr_idx;\n \n \terr = devm_request_irq(&pf->pdev->dev,\n-\t\t\t pf->msix_entries[pf->sw_oicr_idx].vector,\n+\t\t\t pf->msix_entries[pf->oicr_idx].vector,\n \t\t\t ice_misc_intr, 0, pf->int_name, pf);\n \tif (err) {\n \t\tdev_err(&pf->pdev->dev,\n \t\t\t\"devm_request_irq for %s failed: %d\\n\",\n \t\t\tpf->int_name, err);\n-\t\tice_free_res(pf->sw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n+\t\tice_free_res(pf->irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n \t\tpf->num_avail_sw_msix += 1;\n-\t\tice_free_res(pf->hw_irq_tracker, 1, ICE_RES_MISC_VEC_ID);\n-\t\tpf->num_avail_hw_msix += 1;\n \t\treturn err;\n \t}\n \n skip_req_irq:\n \tice_ena_misc_vector(pf);\n \n-\tice_ena_ctrlq_interrupts(hw, pf->hw_oicr_idx);\n-\twr32(hw, GLINT_ITR(ICE_RX_ITR, pf->hw_oicr_idx),\n+\tice_ena_ctrlq_interrupts(hw, pf->oicr_idx);\n+\twr32(hw, GLINT_ITR(ICE_RX_ITR, pf->oicr_idx),\n \t ITR_REG_ALIGN(ICE_ITR_8K) >> ICE_ITR_GRAN_S);\n \n \tice_flush(hw);\n@@ -2168,14 +2154,9 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf)\n \tif (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))\n \t\tice_dis_msix(pf);\n \n-\tif (pf->sw_irq_tracker) {\n-\t\tdevm_kfree(&pf->pdev->dev, pf->sw_irq_tracker);\n-\t\tpf->sw_irq_tracker = NULL;\n-\t}\n-\n-\tif (pf->hw_irq_tracker) {\n-\t\tdevm_kfree(&pf->pdev->dev, pf->hw_irq_tracker);\n-\t\tpf->hw_irq_tracker = NULL;\n+\tif (pf->irq_tracker) {\n+\t\tdevm_kfree(&pf->pdev->dev, pf->irq_tracker);\n+\t\tpf->irq_tracker = NULL;\n \t}\n }\n \n@@ -2185,7 +2166,7 @@ static void ice_clear_interrupt_scheme(struct ice_pf *pf)\n */\n static int ice_init_interrupt_scheme(struct ice_pf *pf)\n {\n-\tint vectors = 0, hw_vectors = 0;\n+\tint vectors;\n \n \tif (test_bit(ICE_FLAG_MSIX_ENA, pf->flags))\n \t\tvectors = ice_ena_msix_range(pf);\n@@ -2196,31 +2177,18 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)\n \t\treturn vectors;\n \n \t/* set up vector assignment tracking */\n-\tpf->sw_irq_tracker =\n-\t\tdevm_kzalloc(&pf->pdev->dev, sizeof(*pf->sw_irq_tracker) +\n+\tpf->irq_tracker =\n+\t\tdevm_kzalloc(&pf->pdev->dev, sizeof(*pf->irq_tracker) +\n \t\t\t (sizeof(u16) * vectors), GFP_KERNEL);\n-\tif (!pf->sw_irq_tracker) {\n+\tif (!pf->irq_tracker) {\n \t\tice_dis_msix(pf);\n \t\treturn -ENOMEM;\n \t}\n \n \t/* populate SW interrupts pool with number of OS granted IRQs. */\n \tpf->num_avail_sw_msix = vectors;\n-\tpf->sw_irq_tracker->num_entries = vectors;\n-\n-\t/* set up HW vector assignment tracking */\n-\thw_vectors = pf->hw.func_caps.common_cap.num_msix_vectors;\n-\tpf->hw_irq_tracker =\n-\t\tdevm_kzalloc(&pf->pdev->dev, sizeof(*pf->hw_irq_tracker) +\n-\t\t\t (sizeof(u16) * hw_vectors), GFP_KERNEL);\n-\tif (!pf->hw_irq_tracker) {\n-\t\tice_clear_interrupt_scheme(pf);\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\t/* populate HW interrupts pool with number of HW supported irqs. */\n-\tpf->num_avail_hw_msix = hw_vectors;\n-\tpf->hw_irq_tracker->num_entries = hw_vectors;\n+\tpf->irq_tracker->num_entries = vectors;\n+\tpf->irq_tracker->end = pf->irq_tracker->num_entries;\n \n \treturn 0;\n }\n@@ -3794,12 +3762,6 @@ static void ice_rebuild(struct ice_pf *pf)\n \n \tice_dcb_rebuild(pf);\n \n-\t/* reset search_hint of irq_trackers to 0 since interrupts are\n-\t * reclaimed and could be allocated from beginning during VSI rebuild\n-\t */\n-\tpf->sw_irq_tracker->search_hint = 0;\n-\tpf->hw_irq_tracker->search_hint = 0;\n-\n \terr = ice_vsi_rebuild_all(pf);\n \tif (err) {\n \t\tdev_err(dev, \"ice_vsi_rebuild_all failed\\n\");\ndiff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\nindex fd19ab53653d..0f79cf0e4ee8 100644\n--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c\n@@ -205,8 +205,7 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)\n \twr32(hw, VPINT_ALLOC(vf->vf_id), 0);\n \twr32(hw, VPINT_ALLOC_PCI(vf->vf_id), 0);\n \n-\tfirst = vf->first_vector_idx +\n-\t\thw->func_caps.common_cap.msix_vector_first_id;\n+\tfirst = vf->first_vector_idx;\n \tlast = first + pf->num_vf_msix - 1;\n \tfor (v = first; v <= last; v++) {\n \t\tu32 reg;\n@@ -231,6 +230,42 @@ static void ice_dis_vf_mappings(struct ice_vf *vf)\n \t\t\t\"Scattered mode for VF Rx queues is not yet implemented\\n\");\n }\n \n+/**\n+ * ice_sriov_free_msix_res - Reset/free any used MSIX resources\n+ * @pf: pointer to the PF structure\n+ *\n+ * If MSIX entries from the pf->irq_tracker were needed then we need to\n+ * reset the irq_tracker->end and give back the entries we needed to\n+ * num_avail_sw_msix.\n+ *\n+ * If no MSIX entries were taken from the pf->irq_tracker then just clear\n+ * the pf->sriov_base_vector.\n+ *\n+ * Returns 0 on success, and -EINVAL on error.\n+ */\n+static int ice_sriov_free_msix_res(struct ice_pf *pf)\n+{\n+\tstruct ice_res_tracker *res;\n+\n+\tif (!pf)\n+\t\treturn -EINVAL;\n+\n+\tres = pf->irq_tracker;\n+\tif (!res)\n+\t\treturn -EINVAL;\n+\n+\t/* give back irq_tracker resources used */\n+\tif (pf->sriov_base_vector < res->num_entries) {\n+\t\tres->end = res->num_entries;\n+\t\tpf->num_avail_sw_msix +=\n+\t\t\tres->num_entries - pf->sriov_base_vector;\n+\t}\n+\n+\tpf->sriov_base_vector = 0;\n+\n+\treturn 0;\n+}\n+\n /**\n * ice_free_vfs - Free all VFs\n * @pf: pointer to the PF structure\n@@ -288,6 +323,10 @@ void ice_free_vfs(struct ice_pf *pf)\n \t\t}\n \t}\n \n+\tif (ice_sriov_free_msix_res(pf))\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"Failed to free MSIX resources used by SR-IOV\\n\");\n+\n \tdevm_kfree(&pf->pdev->dev, pf->vf);\n \tpf->vf = NULL;\n \n@@ -456,6 +495,22 @@ ice_vf_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi, u16 vf_id)\n \treturn ice_vsi_setup(pf, pi, ICE_VSI_VF, vf_id);\n }\n \n+/**\n+ * ice_calc_vf_first_vector_idx - Calculate absolute MSIX vector index in HW\n+ * @pf: pointer to PF structure\n+ * @vf: pointer to VF that the first MSIX vector index is being calculated for\n+ *\n+ * This returns the first MSIX vector index in HW that is used by this VF and\n+ * this will always be the OICR index in the AVF driver so any functionality\n+ * using vf->first_vector_idx for queue configuration will have to increment by\n+ * 1 to avoid meddling with the OICR index.\n+ */\n+static int ice_calc_vf_first_vector_idx(struct ice_pf *pf, struct ice_vf *vf)\n+{\n+\treturn pf->hw.func_caps.common_cap.msix_vector_first_id +\n+\t\tpf->sriov_base_vector + vf->vf_id * pf->num_vf_msix;\n+}\n+\n /**\n * ice_alloc_vsi_res - Setup VF VSI and its resources\n * @vf: pointer to the VF structure\n@@ -470,6 +525,9 @@ static int ice_alloc_vsi_res(struct ice_vf *vf)\n \tstruct ice_vsi *vsi;\n \tint status = 0;\n \n+\t/* first vector index is the VFs OICR index */\n+\tvf->first_vector_idx = ice_calc_vf_first_vector_idx(pf, vf);\n+\n \tvsi = ice_vf_vsi_setup(pf, pf->hw.port_info, vf->vf_id);\n \n \tif (!vsi) {\n@@ -480,14 +538,6 @@ static int ice_alloc_vsi_res(struct ice_vf *vf)\n \tvf->lan_vsi_idx = vsi->idx;\n \tvf->lan_vsi_num = vsi->vsi_num;\n \n-\t/* first vector index is the VFs OICR index */\n-\tvf->first_vector_idx = vsi->hw_base_vector;\n-\t/* Since hw_base_vector holds the vector where data queue interrupts\n-\t * starts, increment by 1 since VFs allocated vectors include OICR intr\n-\t * as well.\n-\t */\n-\tvsi->hw_base_vector += 1;\n-\n \t/* Check if port VLAN exist before, and restore it accordingly */\n \tif (vf->port_vlan_id) {\n \t\tice_vsi_manage_pvid(vsi, vf->port_vlan_id, true);\n@@ -580,8 +630,7 @@ static void ice_ena_vf_mappings(struct ice_vf *vf)\n \n \thw = &pf->hw;\n \tvsi = pf->vsi[vf->lan_vsi_idx];\n-\tfirst = vf->first_vector_idx +\n-\t\thw->func_caps.common_cap.msix_vector_first_id;\n+\tfirst = vf->first_vector_idx;\n \tlast = (first + pf->num_vf_msix) - 1;\n \tabs_vf_id = vf->vf_id + hw->func_caps.vf_base_id;\n \n@@ -686,6 +735,97 @@ ice_determine_res(struct ice_pf *pf, u16 avail_res, u16 max_res, u16 min_res)\n \treturn 0;\n }\n \n+/**\n+ * ice_calc_vf_reg_idx - Calculate the VF's register index in the PF space\n+ * @vf: VF to calculate the register index for\n+ * @q_vector: a q_vector associated to the VF\n+ */\n+int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector)\n+{\n+\tstruct ice_pf *pf;\n+\n+\tif (!vf || !q_vector)\n+\t\treturn -EINVAL;\n+\n+\tpf = vf->pf;\n+\n+\t/* always add one to account for the OICR being the first MSIX */\n+\treturn pf->sriov_base_vector + pf->num_vf_msix * vf->vf_id +\n+\t\tq_vector->v_idx + 1;\n+}\n+\n+/**\n+ * ice_get_max_valid_res_idx - Get the max valid resource index\n+ * @res: pointer to the resource to find the max valid index for\n+ *\n+ * Start from the end of the ice_res_tracker and return right when we find the\n+ * first res->list entry with the ICE_RES_VALID_BIT set. This function is only\n+ * valid for SR-IOV because it is the only consumer that manipulates the\n+ * res->end and this is always called when res->end is set to res->num_entries.\n+ */\n+static int ice_get_max_valid_res_idx(struct ice_res_tracker *res)\n+{\n+\tint i;\n+\n+\tif (!res)\n+\t\treturn -EINVAL;\n+\n+\tfor (i = res->num_entries - 1; i >= 0; i--)\n+\t\tif (res->list[i] & ICE_RES_VALID_BIT)\n+\t\t\treturn i;\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_sriov_set_msix_res - Set any used MSIX resources\n+ * @pf: pointer to PF structure\n+ * @num_msix_needed: number of MSIX vectors needed for all SR-IOV VFs\n+ *\n+ * This function allows SR-IOV resources to be taken from the end of the PF's\n+ * allowed HW MSIX vectors so in many cases the irq_tracker will not\n+ * be needed. In these cases we just set the pf->sriov_base_vector and return\n+ * success.\n+ *\n+ * If SR-IOV needs to use any pf->irq_tracker entries it updates the\n+ * irq_tracker->end based on the first entry needed for SR-IOV. This makes it\n+ * so any calls to ice_get_res() using the irq_tracker will not try to use\n+ * resources at or beyond the newly set value.\n+ *\n+ * Return 0 on success, and -EINVAL when there are not enough MSIX vectors in\n+ * in the PF's space available for SR-IOV.\n+ */\n+static int ice_sriov_set_msix_res(struct ice_pf *pf, u16 num_msix_needed)\n+{\n+\tint max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);\n+\tu16 pf_total_msix_vectors =\n+\t\tpf->hw.func_caps.common_cap.num_msix_vectors;\n+\tstruct ice_res_tracker *res = pf->irq_tracker;\n+\tint sriov_base_vector;\n+\n+\tif (max_valid_res_idx < 0)\n+\t\treturn max_valid_res_idx;\n+\n+\tsriov_base_vector = pf_total_msix_vectors - num_msix_needed;\n+\n+\t/* make sure we only grab irq_tracker entries from the list end and\n+\t * that we have enough available MSIX vectors\n+\t */\n+\tif (sriov_base_vector <= max_valid_res_idx)\n+\t\treturn -EINVAL;\n+\n+\tpf->sriov_base_vector = sriov_base_vector;\n+\n+\t/* dip into irq_tracker entries and update used resources */\n+\tif (num_msix_needed > (pf_total_msix_vectors - res->num_entries)) {\n+\t\tpf->num_avail_sw_msix -=\n+\t\t\tres->num_entries - pf->sriov_base_vector;\n+\t\tres->end = pf->sriov_base_vector;\n+\t}\n+\n+\treturn 0;\n+}\n+\n /**\n * ice_check_avail_res - check if vectors and queues are available\n * @pf: pointer to the PF structure\n@@ -696,11 +836,16 @@ ice_determine_res(struct ice_pf *pf, u16 avail_res, u16 max_res, u16 min_res)\n */\n static int ice_check_avail_res(struct ice_pf *pf)\n {\n-\tu16 num_msix, num_txq, num_rxq;\n+\tint max_valid_res_idx = ice_get_max_valid_res_idx(pf->irq_tracker);\n+\tu16 num_msix, num_txq, num_rxq, num_avail_msix;\n \n-\tif (!pf->num_alloc_vfs)\n+\tif (!pf->num_alloc_vfs || max_valid_res_idx < 0)\n \t\treturn -EINVAL;\n \n+\t/* add 1 to max_valid_res_idx to account for it being 0-based */\n+\tnum_avail_msix = pf->hw.func_caps.common_cap.num_msix_vectors -\n+\t\t(max_valid_res_idx + 1);\n+\n \t/* Grab from HW interrupts common pool\n \t * Note: By the time the user decides it needs more vectors in a VF\n \t * its already too late since one must decide this prior to creating the\n@@ -717,11 +862,11 @@ static int ice_check_avail_res(struct ice_pf *pf)\n \t * grab default interrupt vectors (5 as supported by AVF driver).\n \t */\n \tif (pf->num_alloc_vfs <= 16) {\n-\t\tnum_msix = ice_determine_res(pf, pf->num_avail_hw_msix,\n+\t\tnum_msix = ice_determine_res(pf, num_avail_msix,\n \t\t\t\t\t ICE_MAX_INTR_PER_VF,\n \t\t\t\t\t ICE_MIN_INTR_PER_VF);\n \t} else if (pf->num_alloc_vfs <= ICE_MAX_VF_COUNT) {\n-\t\tnum_msix = ice_determine_res(pf, pf->num_avail_hw_msix,\n+\t\tnum_msix = ice_determine_res(pf, num_avail_msix,\n \t\t\t\t\t ICE_DFLT_INTR_PER_VF,\n \t\t\t\t\t ICE_MIN_INTR_PER_VF);\n \t} else {\n@@ -750,6 +895,9 @@ static int ice_check_avail_res(struct ice_pf *pf)\n \tif (!num_txq || !num_rxq)\n \t\treturn -EIO;\n \n+\tif (ice_sriov_set_msix_res(pf, num_msix * pf->num_alloc_vfs))\n+\t\treturn -EINVAL;\n+\n \t/* since AVF driver works with only queue pairs which means, it expects\n \t * to have equal number of Rx and Tx queues, so take the minimum of\n \t * available Tx or Rx queues\n@@ -938,6 +1086,10 @@ bool ice_reset_all_vfs(struct ice_pf *pf, bool is_vflr)\n \t\tvf->num_vf_qs = 0;\n \t}\n \n+\tif (ice_sriov_free_msix_res(pf))\n+\t\tdev_err(&pf->pdev->dev,\n+\t\t\t\"Failed to free MSIX resources used by SR-IOV\\n\");\n+\n \tif (ice_check_avail_res(pf)) {\n \t\tdev_err(&pf->pdev->dev,\n \t\t\t\"Cannot allocate VF resources, try with fewer number of VFs\\n\");\n@@ -1119,7 +1271,7 @@ static int ice_alloc_vfs(struct ice_pf *pf, u16 num_alloc_vfs)\n \tint i, ret;\n \n \t/* Disable global interrupt 0 so we don't try to handle the VFLR. */\n-\twr32(hw, GLINT_DYN_CTL(pf->hw_oicr_idx),\n+\twr32(hw, GLINT_DYN_CTL(pf->oicr_idx),\n \t ICE_ITR_NONE << GLINT_DYN_CTL_ITR_INDX_S);\n \n \tice_flush(hw);\ndiff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h\nindex 9583ad3f6fb6..c3ca522c245a 100644\n--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h\n+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.h\n@@ -101,6 +101,8 @@ int ice_set_vf_trust(struct net_device *netdev, int vf_id, bool trusted);\n int ice_set_vf_link_state(struct net_device *netdev, int vf_id, int link_state);\n \n int ice_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool ena);\n+\n+int ice_calc_vf_reg_idx(struct ice_vf *vf, struct ice_q_vector *q_vector);\n #else /* CONFIG_PCI_IOV */\n #define ice_process_vflr_event(pf) do {} while (0)\n #define ice_free_vfs(pf) do {} while (0)\n@@ -166,5 +168,11 @@ ice_set_vf_link_state(struct net_device __always_unused *netdev,\n \treturn -EOPNOTSUPP;\n }\n \n+static inline int\n+ice_calc_vf_reg_idx(struct ice_vf __always_unused *vf,\n+\t\t struct ice_q_vector __always_unused *q_vector)\n+{\n+\treturn 0;\n+}\n #endif /* CONFIG_PCI_IOV */\n #endif /* _ICE_VIRTCHNL_PF_H_ */\n", "prefixes": [ "S20", "07/15" ] }