Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1035066/?format=api
{ "id": 1035066, "url": "http://patchwork.ozlabs.org/api/patches/1035066/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1549048453-3584-3-git-send-email-megha.dey@linux.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": "<1549048453-3584-3-git-send-email-megha.dey@linux.intel.com>", "list_archive_url": null, "date": "2019-02-01T19:14:09", "name": "[RFC,v4,2/6] PCI/MSI: Dynamic allocation of MSI-X vectors by group", "commit_ref": null, "pull_url": null, "state": "rfc", "archived": false, "hash": "793ceff48a69bf9f03bbafbbc808482820e61bbc", "submitter": { "id": 75876, "url": "http://patchwork.ozlabs.org/api/people/75876/?format=api", "name": "Dey, Megha", "email": "megha.dey@linux.intel.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/1549048453-3584-3-git-send-email-megha.dey@linux.intel.com/mbox/", "series": [ { "id": 89594, "url": "http://patchwork.ozlabs.org/api/series/89594/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=89594", "date": "2019-02-01T19:14:07", "name": "Introduce dynamic allocation/freeing of MSI-X vectors", "version": 4, "mbox": "http://patchwork.ozlabs.org/series/89594/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1035066/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1035066/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.137; helo=fraxinus.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dmarc=none (p=none dis=none)\n\theader.from=linux.intel.com" ], "Received": [ "from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137])\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 43rmzq13sHz9s4V\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat, 2 Feb 2019 06:16:23 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id A667386C37;\n\tFri, 1 Feb 2019 19:16:21 +0000 (UTC)", "from fraxinus.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id ZgSYCS4p2fPh; Fri, 1 Feb 2019 19:16:19 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby fraxinus.osuosl.org (Postfix) with ESMTP id E9D4686C35;\n\tFri, 1 Feb 2019 19:16:17 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id 31AFB1BF369\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 1 Feb 2019 18:52:35 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id A7F8D82033\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 1 Feb 2019 18:52:34 +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 iX0xpa9IaJfi for <intel-wired-lan@lists.osuosl.org>;\n\tFri, 1 Feb 2019 18:52:24 +0000 (UTC)", "from mga03.intel.com (mga03.intel.com [134.134.136.65])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 521B186187\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tFri, 1 Feb 2019 18:52:23 +0000 (UTC)", "from orsmga003.jf.intel.com ([10.7.209.27])\n\tby orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t01 Feb 2019 10:50:53 -0800", "from megha-z97x-ud7-th.sc.intel.com ([143.183.85.162])\n\tby orsmga003.jf.intel.com with ESMTP; 01 Feb 2019 10:50:52 -0800" ], "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.56,549,1539673200\"; d=\"scan'208\";a=\"123233687\"", "From": "Megha Dey <megha.dey@linux.intel.com>", "To": "linux-drivers-review@linux.intel.com,\n\tintel-wired-lan@lists.osuosl.org", "Date": "Fri, 1 Feb 2019 11:14:09 -0800", "Message-Id": "<1549048453-3584-3-git-send-email-megha.dey@linux.intel.com>", "X-Mailer": "git-send-email 2.7.4", "In-Reply-To": "<1549048453-3584-1-git-send-email-megha.dey@linux.intel.com>", "References": "<1549048453-3584-1-git-send-email-megha.dey@linux.intel.com>", "X-Mailman-Approved-At": "Fri, 01 Feb 2019 19:16:15 +0000", "Subject": "[Intel-wired-lan] [RFC v4 2/6] PCI/MSI: Dynamic allocation of MSI-X\n\tvectors by group", "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>", "Cc": "ravi.v.shankar@intel.com, ashok.raj@intel.com, kyung.min.park@intel.com, \n\tjacob.jun.pan@intel.com, Megha Dey <megha.dey@linux.intel.com>,\n\tmegha.dey@intel.com", "MIME-Version": "1.0", "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": "Currently, MSI-X vector enabling and allocation for a PCIe device is\nstatic i.e. a device driver gets only one chance to enable a specific\nnumber of MSI-X vectors, usually during device probe. Also, in many\ncases, drivers usually reserve more than required number of vectors\nanticipating their use, which unnecessarily blocks resources that\ncould have been made available to other devices. Lastly, there is no\nway for drivers to reserve more vectors, if the MSI-x has already been\nenabled for that device.\n\nHence, a dynamic MSI-X kernel infrastructure can benefit drivers by\ndeferring MSI-X allocation to post probe phase, where actual demand\ninformation is available.\n\nThis patch enables the dynamic allocation of MSI-X vectors even after\nMSI-X is enabled for a PCIe device by introducing a new API:\npci_alloc_irq_vectors_dyn().\n\nThis API can be called multiple times by the driver. The MSI-X vectors\nallocated each time this API is called are associated with a group ID.\n\nIn order to obtain the Linux IRQ number associated with each vector in\na group, a new api, pci_irq_vector_group() has been introduced.\n\nSigned-off-by: Megha Dey <megha.dey@linux.intel.com>\n---\n drivers/pci/msi.c | 186 +++++++++++++++++++++++++++++++++++++++++++++-------\n drivers/pci/probe.c | 19 ++++++\n include/linux/pci.h | 36 ++++++++++\n kernel/irq/msi.c | 8 +--\n 4 files changed, 222 insertions(+), 27 deletions(-)", "diff": "diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c\nindex 4c0b478..a0cf3d3 100644\n--- a/drivers/pci/msi.c\n+++ b/drivers/pci/msi.c\n@@ -102,7 +102,7 @@ int __weak arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)\n \tif (type == PCI_CAP_ID_MSI && nvec > 1)\n \t\treturn 1;\n \n-\tfor_each_pci_msi_entry(entry, dev) {\n+\tfor_each_pci_msi_entry_from(entry, dev) {\n \t\tret = arch_setup_msi_irq(dev, entry);\n \t\tif (ret < 0)\n \t\t\treturn ret;\n@@ -468,7 +468,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)\n \tint i;\n \n \t/* Determine how many msi entries we have */\n-\tfor_each_pci_msi_entry(entry, pdev)\n+\tfor_each_pci_msi_entry_from(entry, pdev)\n \t\tnum_msi += entry->nvec_used;\n \tif (!num_msi)\n \t\treturn 0;\n@@ -477,7 +477,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)\n \tmsi_attrs = kcalloc(num_msi + 1, sizeof(void *), GFP_KERNEL);\n \tif (!msi_attrs)\n \t\treturn -ENOMEM;\n-\tfor_each_pci_msi_entry(entry, pdev) {\n+\tfor_each_pci_msi_entry_from(entry, pdev) {\n \t\tfor (i = 0; i < entry->nvec_used; i++) {\n \t\t\tmsi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);\n \t\t\tif (!msi_dev_attr)\n@@ -506,7 +506,11 @@ static int populate_msi_sysfs(struct pci_dev *pdev)\n \t\tgoto error_irq_group;\n \tmsi_irq_groups[0] = msi_irq_group;\n \n-\tret = sysfs_create_groups(&pdev->dev.kobj, msi_irq_groups);\n+\tif (!pdev->msix_enabled)\n+\t\tret = sysfs_create_group(&pdev->dev.kobj, msi_irq_group);\n+\telse\n+\t\tret = sysfs_merge_group(&pdev->dev.kobj, msi_irq_group);\n+\n \tif (ret)\n \t\tgoto error_irq_groups;\n \tpdev->msi_irq_groups = msi_irq_groups;\n@@ -574,7 +578,7 @@ static int msi_verify_entries(struct pci_dev *dev)\n {\n \tstruct msi_desc *entry;\n \n-\tfor_each_pci_msi_entry(entry, dev) {\n+\tfor_each_pci_msi_entry_from(entry, dev) {\n \t\tif (!dev->no_64bit_msi || !entry->msg.address_hi)\n \t\t\tcontinue;\n \t\tpci_err(dev, \"Device has broken 64-bit MSI but arch\"\n@@ -615,6 +619,9 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,\n \n \tlist_add_tail(&entry->list, dev_to_msi_list(&dev->dev));\n \n+\t dev->dev.first_desc = list_last_entry\n+ (dev_to_msi_list(&dev->dev), struct msi_desc, list);\n+\n \t/* Configure MSI capability structure */\n \tret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);\n \tif (ret) {\n@@ -700,6 +707,17 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,\n \t\tentry->mask_base\t\t= base;\n \n \t\tlist_add_tail(&entry->list, dev_to_msi_list(&dev->dev));\n+\n+\t\t/*\n+\t\t * Save the pointer to the first msi_desc entry of every\n+\t\t * MSI-X group. This pointer is used by other functions\n+\t\t * as the starting point to iterate through each of the\n+\t\t * entries in that particular group.\n+\t\t */\n+\t\tif (!i)\n+\t\t\tdev->dev.first_desc = list_last_entry\n+\t\t\t(dev_to_msi_list(&dev->dev), struct msi_desc, list);\n+\n \t\tif (masks)\n \t\t\tcurmsk++;\n \t}\n@@ -715,7 +733,7 @@ static void msix_program_entries(struct pci_dev *dev,\n \tstruct msi_desc *entry;\n \tint i = 0;\n \n-\tfor_each_pci_msi_entry(entry, dev) {\n+\tfor_each_pci_msi_entry_from(entry, dev) {\n \t\tif (entries)\n \t\t\tentries[i++].vector = entry->irq;\n \t\tentry->masked = readl(pci_msix_desc_addr(entry) +\n@@ -740,18 +758,20 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,\n {\n \tint ret;\n \tu16 control;\n-\tvoid __iomem *base;\n \n \t/* Ensure MSI-X is disabled while it is set up */\n \tpci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);\n \n \tpci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);\n+\n \t/* Request & Map MSI-X table region */\n-\tbase = msix_map_region(dev, msix_table_size(control));\n-\tif (!base)\n-\t\treturn -ENOMEM;\n+\tif (!dev->msix_enabled) {\n+\t\tdev->base = msix_map_region(dev, msix_table_size(control));\n+\t\tif (!dev->base)\n+\t\t\treturn -ENOMEM;\n+\t}\n \n-\tret = msix_setup_entries(dev, base, entries, nvec, affd);\n+\tret = msix_setup_entries(dev, dev->base, entries, nvec, affd);\n \tif (ret)\n \t\treturn ret;\n \n@@ -784,6 +804,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,\n \tpci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);\n \n \tpcibios_free_irq(dev);\n+\n \treturn 0;\n \n out_avail:\n@@ -795,7 +816,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,\n \t\tstruct msi_desc *entry;\n \t\tint avail = 0;\n \n-\t\tfor_each_pci_msi_entry(entry, dev) {\n+\t\tfor_each_pci_msi_entry_from(entry, dev) {\n \t\t\tif (entry->irq != 0)\n \t\t\t\tavail++;\n \t\t}\n@@ -932,7 +953,8 @@ int pci_msix_vec_count(struct pci_dev *dev)\n EXPORT_SYMBOL(pci_msix_vec_count);\n \n static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,\n-\t\t\t int nvec, const struct irq_affinity *affd)\n+\t\t\t int nvec, const struct irq_affinity *affd,\n+\t\t\t bool one_shot)\n {\n \tint nr_entries;\n \tint i, j;\n@@ -1086,7 +1108,8 @@ EXPORT_SYMBOL(pci_enable_msi);\n \n static int __pci_enable_msix_range(struct pci_dev *dev,\n \t\t\t\t struct msix_entry *entries, int minvec,\n-\t\t\t\t int maxvec, const struct irq_affinity *affd)\n+\t\t\t\t int maxvec, const struct irq_affinity *affd,\n+\t\t\t\t bool one_shot)\n {\n \tint rc, nvec = maxvec;\n \n@@ -1100,7 +1123,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev,\n \tif (affd && affd->nr_sets && minvec != maxvec)\n \t\treturn -EINVAL;\n \n-\tif (WARN_ON_ONCE(dev->msix_enabled))\n+\tif (one_shot && WARN_ON_ONCE(dev->msix_enabled))\n \t\treturn -EINVAL;\n \n \tfor (;;) {\n@@ -1110,7 +1133,7 @@ static int __pci_enable_msix_range(struct pci_dev *dev,\n \t\t\t\treturn -ENOSPC;\n \t\t}\n \n-\t\trc = __pci_enable_msix(dev, entries, nvec, affd);\n+\t\trc = __pci_enable_msix(dev, entries, nvec, affd, one_shot);\n \t\tif (rc == 0)\n \t\t\treturn nvec;\n \n@@ -1141,7 +1164,8 @@ static int __pci_enable_msix_range(struct pci_dev *dev,\n int pci_enable_msix_range(struct pci_dev *dev, struct msix_entry *entries,\n \t\tint minvec, int maxvec)\n {\n-\treturn __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL);\n+\treturn __pci_enable_msix_range(dev, entries, minvec, maxvec, NULL,\n+\t\t\t\t\t\t\t\t\tfalse);\n }\n EXPORT_SYMBOL(pci_enable_msix_range);\n \n@@ -1167,9 +1191,45 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,\n \t\t\t\t unsigned int max_vecs, unsigned int flags,\n \t\t\t\t const struct irq_affinity *affd)\n {\n+\tint *group = NULL;\n+\n+\tdev->dev.one_shot = true;\n+\n+\treturn pci_alloc_irq_vectors_affinity_dyn(dev, min_vecs, max_vecs,\n+\t\t\t\t\tflags, NULL, group, dev->dev.one_shot);\n+}\n+EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);\n+\n+/**\n+ * pci_alloc_irq_vectors_affinity_dyn - allocate multiple IRQs for a device\n+ * dynamically. Can be called multiple times.\n+ * @dev:\t\tPCI device to operate on\n+ * @min_vecs:\t\tminimum number of vectors required (must be >= 1)\n+ * @max_vecs:\t\tmaximum (desired) number of vectors\n+ * @flags:\t\tflags or quirks for the allocation\n+ * @affd:\t\toptional description of the affinity requirements\n+ * @group_id:\t\tgroup ID assigned to vectors allocated\n+ *\n+ * Allocate up to @max_vecs interrupt vectors for @dev, using MSI-X. Return\n+ * the number of vectors allocated (which might be smaller than @max_vecs)\n+ * if successful, or a negative error code on error. If less than @min_vecs\n+ * interrupt vectors are available for @dev the function will fail with -ENOSPC.\n+ * Assign a unique group ID to the set of vectors being allocated.\n+ *\n+ * To get the Linux IRQ number used for a vector that can be passed to\n+ * request_irq() use the pci_irq_vector() helper.\n+ */\n+int pci_alloc_irq_vectors_affinity_dyn(struct pci_dev *dev,\n+\t\t\t\t unsigned int min_vecs,\n+\t\t\t\t unsigned int max_vecs,\n+\t\t\t\t unsigned int flags,\n+\t\t\t\t const struct irq_affinity *affd,\n+\t\t\t\t int *group_id, bool one_shot)\n+{\n \tstatic const struct irq_affinity msi_default_affd;\n-\tint msix_vecs = -ENOSPC;\n+\tint msix_vecs = -ENOSPC, i, *group = NULL;\n \tint msi_vecs = -ENOSPC;\n+\tstruct msix_entry *entries = NULL;\n \n \tif (flags & PCI_IRQ_AFFINITY) {\n \t\tif (!affd)\n@@ -1180,15 +1240,53 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,\n \t}\n \n \tif (flags & PCI_IRQ_MSIX) {\n-\t\tmsix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs,\n-\t\t\t\t\t\t max_vecs, affd);\n+\t\tif (!one_shot) {\n+\t\t\tentries = kcalloc(max_vecs, sizeof(struct msix_entry),\n+\t\t\t\t\t\t\t\tGFP_KERNEL);\n+\t\t\tif (entries == NULL)\n+\t\t\t\treturn -ENOMEM;\n+\n+\t\t\tgroup = kcalloc(max_vecs, sizeof(int), GFP_KERNEL);\n+\t\t\tif (group == NULL)\n+\t\t\t\treturn -ENOMEM;\n+\n+\t\t\tif (!dev->msix_enabled)\n+\t\t\t\tdev->num_msix = pci_msix_vec_count(dev);\n+\n+\t\t\t/* Assign a unique group ID */\n+\t\t\t*group = idr_alloc(dev->dev.msix_dev_idr->grp_idr, NULL,\n+\t\t\t\t\t\t0, dev->num_msix, GFP_KERNEL);\n+\t\t\tif (*group < 0) {\n+\t\t\t\tif (*group == -ENOSPC)\n+\t\t\t\t\tpci_err(dev, \"No free group IDs\\n\");\n+\t\t\t\treturn *group;\n+\t\t\t}\n+\t\t\t*group_id = *group;\n+\n+\t\t\tfor (i = 0; i < max_vecs; i++) {\n+\t\t\t\t/* tag every entry with a group ID */\n+\t\t\t\tentries[i].entry = idr_alloc(\n+\t\t\t\t\tdev->dev.msix_dev_idr->entry_idr,\n+\t\t\t\t\tgroup, 0, dev->num_msix, GFP_KERNEL);\n+\t\t\t\tif (entries[i].entry < 0) {\n+\t\t\t\t\tif (entries[i].entry == -ENOSPC)\n+\t\t\t\t\t\tpci_err(dev, \"No free IDs\\n\");\n+\t\t\t\t\treturn entries[i].entry;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n+\t\tmsix_vecs = __pci_enable_msix_range(dev, entries, min_vecs, max_vecs,\n+\t\t\t\t\t\t\t\taffd, one_shot);\n+\n+\t\tkfree(entries);\n+\n \t\tif (msix_vecs > 0)\n \t\t\treturn msix_vecs;\n \t}\n \n \tif (flags & PCI_IRQ_MSI) {\n-\t\tmsi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs,\n-\t\t\t\t\t\t affd);\n+\t\tmsi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);\n \t\tif (msi_vecs > 0)\n \t\t\treturn msi_vecs;\n \t}\n@@ -1201,11 +1299,14 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,\n \t\t}\n \t}\n \n+\tif (flags & (PCI_IRQ_MSI | PCI_IRQ_LEGACY))\n+\t\treturn -EINVAL;\n+\n \tif (msix_vecs == -ENOSPC)\n \t\treturn -ENOSPC;\n \treturn msi_vecs;\n }\n-EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);\n+EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity_dyn);\n \n /**\n * pci_free_irq_vectors - free previously allocated IRQs for a device\n@@ -1255,6 +1356,45 @@ int pci_irq_vector(struct pci_dev *dev, unsigned int nr)\n EXPORT_SYMBOL(pci_irq_vector);\n \n /**\n+ * pci_irq_vector_group - return the IRQ number of a device vector associated\n+ * with a group\n+ * @dev: PCI device to operate on\n+ * @nr: device-relative interrupt vector index (0-based).\n+ * @group: group from which IRQ number should be returned\n+ */\n+int pci_irq_vector_group(struct pci_dev *dev, unsigned int nr,\n+\t\t\t\t\t\tunsigned int group_id)\n+{\n+\tif (dev->msix_enabled) {\n+\t\tstruct msi_desc *entry;\n+\t\tint *group, i = 0, grp_present = 0;\n+\n+\t\tfor_each_pci_msi_entry(entry, dev) {\n+\t\t\tgroup = idr_find(dev->dev.msix_dev_idr->entry_idr,\n+\t\t\t\t\t\tentry->msi_attrib.entry_nr);\n+\t\t\tif (*group == group_id) {\n+\t\t\t\tgrp_present = 1;\n+\t\t\t\tif (i == nr)\n+\t\t\t\t\treturn entry->irq;\n+\t\t\t\ti++;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!grp_present) {\n+\t\t\tpci_err(dev, \"Group %d not present\\n\", group_id);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tpci_err(dev, \"Interrupt vector index %d does not exist in \"\n+\t\t\t\t\t\t\"group %d\\n\", nr, group_id);\n+\t}\n+\n+\tpci_err(dev, \"MSI-X not enabled\\n\");\n+\treturn -EINVAL;\n+}\n+EXPORT_SYMBOL(pci_irq_vector_group);\n+\n+/**\n * pci_irq_get_affinity - return the affinity of a particular msi vector\n * @dev:\tPCI device to operate on\n * @nr:\t\tdevice-relative interrupt vector index (0-based).\ndiff --git a/drivers/pci/probe.c b/drivers/pci/probe.c\nindex 257b9f6..dd4a6ef 100644\n--- a/drivers/pci/probe.c\n+++ b/drivers/pci/probe.c\n@@ -2188,6 +2188,25 @@ struct pci_dev *pci_alloc_dev(struct pci_bus *bus)\n \tif (!dev)\n \t\treturn NULL;\n \n+\t/* For dynamic MSI-x */\n+\tdev->dev.msix_dev_idr = kzalloc(sizeof(struct dev_idr), GFP_KERNEL);\n+\tif (!dev->dev.msix_dev_idr)\n+\t\treturn NULL;\n+\n+\tdev->dev.msix_dev_idr->grp_idr = kzalloc(sizeof(struct idr),\n+\t\t\t\t\t\t\t\tGFP_KERNEL);\n+\tif (!dev->dev.msix_dev_idr->grp_idr)\n+\t\treturn NULL;\n+\n+\tdev->dev.msix_dev_idr->entry_idr = kzalloc(sizeof(struct idr),\n+\t\t\t\t\t\t\t\tGFP_KERNEL);\n+\tif (!dev->dev.msix_dev_idr->entry_idr)\n+\t\treturn NULL;\n+\n+\t/* Initialise the IDR structures */\n+\tidr_init(dev->dev.msix_dev_idr->grp_idr);\n+\tidr_init(dev->dev.msix_dev_idr->entry_idr);\n+\n \tINIT_LIST_HEAD(&dev->bus_list);\n \tdev->dev.type = &pci_dev_type;\n \tdev->bus = pci_bus_get(bus);\ndiff --git a/include/linux/pci.h b/include/linux/pci.h\nindex 177305f..28eab4a 100644\n--- a/include/linux/pci.h\n+++ b/include/linux/pci.h\n@@ -1396,9 +1396,16 @@ static inline int pci_enable_msix_exact(struct pci_dev *dev,\n int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,\n \t\t\t\t unsigned int max_vecs, unsigned int flags,\n \t\t\t\t const struct irq_affinity *affd);\n+int pci_alloc_irq_vectors_affinity_dyn(struct pci_dev *dev,\n+\t\t\t\t unsigned int min_vecs, unsigned int max_vecs,\n+\t\t\t\t unsigned int flags,\n+\t\t\t\t const struct irq_affinity *affd,\n+\t\t\t\t int *group_id, bool one_shot);\n \n void pci_free_irq_vectors(struct pci_dev *dev);\n int pci_irq_vector(struct pci_dev *dev, unsigned int nr);\n+int pci_irq_vector_group(struct pci_dev *dev, unsigned int nr,\n+\t\t\t\t\t\tunsigned int group_id);\n const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev, int vec);\n int pci_irq_get_node(struct pci_dev *pdev, int vec);\n \n@@ -1428,6 +1435,17 @@ pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,\n \treturn -ENOSPC;\n }\n \n+static inline int\n+pci_alloc_irq_vectors_affinity_dyn(struct pci_dev *dev, unsigned int min_vecs,\n+\t\t\t\t unsigned int max_vecs, unsigned int flags,\n+\t\t\t\t const struct irq_affinity *aff_desc,\n+\t\t\t\t int *group_id, bool one_shot)\n+{\n+\tif ((flags & PCI_IRQ_LEGACY) && min_vecs == 1 && dev->irq)\n+\t\treturn 1;\n+\treturn -ENOSPC;\n+}\n+\n static inline void pci_free_irq_vectors(struct pci_dev *dev)\n {\n }\n@@ -1438,6 +1456,15 @@ static inline int pci_irq_vector(struct pci_dev *dev, unsigned int nr)\n \t\treturn -EINVAL;\n \treturn dev->irq;\n }\n+\n+static inline int pci_irq_vector_group(struct pci_dev *dev, unsigned int nr,\n+\t\t\t\t\t\t\tunsigned int group)\n+{\n+\tif (WARN_ON_ONCE(nr > 0))\n+\t\treturn -EINVAL;\n+\treturn dev->irq;\n+}\n+\n static inline const struct cpumask *pci_irq_get_affinity(struct pci_dev *pdev,\n \t\tint vec)\n {\n@@ -1458,6 +1485,15 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,\n \t\t\t\t\t NULL);\n }\n \n+static inline int\n+pci_alloc_irq_vectors_dyn(struct pci_dev *dev, unsigned int min_vecs,\n+\t\t\t unsigned int max_vecs, unsigned int flags,\n+\t\t\t int *group_id)\n+{\n+\treturn pci_alloc_irq_vectors_affinity_dyn(dev, min_vecs, max_vecs,\n+\t\t\t\t\t flags, NULL, group_id, false);\n+}\n+\n /**\n * pci_irqd_intx_xlate() - Translate PCI INTx value to an IRQ domain hwirq\n * @d: the INTx IRQ domain\ndiff --git a/kernel/irq/msi.c b/kernel/irq/msi.c\nindex ad26fbc..5cfa931 100644\n--- a/kernel/irq/msi.c\n+++ b/kernel/irq/msi.c\n@@ -411,7 +411,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,\n \tif (ret)\n \t\treturn ret;\n \n-\tfor_each_msi_entry(desc, dev) {\n+\tfor_each_msi_entry_from(desc, dev) {\n \t\tops->set_desc(&arg, desc);\n \n \t\tvirq = __irq_domain_alloc_irqs(domain, -1, desc->nvec_used,\n@@ -437,7 +437,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,\n \n \tcan_reserve = msi_check_reservation_mode(domain, info, dev);\n \n-\tfor_each_msi_entry(desc, dev) {\n+\tfor_each_msi_entry_from(desc, dev) {\n \t\tvirq = desc->irq;\n \t\tif (desc->nvec_used == 1)\n \t\t\tdev_dbg(dev, \"irq %d for MSI\\n\", virq);\n@@ -465,7 +465,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,\n \t * so request_irq() will assign the final vector.\n \t */\n \tif (can_reserve) {\n-\t\tfor_each_msi_entry(desc, dev) {\n+\t\tfor_each_msi_entry_from(desc, dev) {\n \t\t\tirq_data = irq_domain_get_irq_data(domain, desc->irq);\n \t\t\tirqd_clr_activated(irq_data);\n \t\t}\n@@ -473,7 +473,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,\n \treturn 0;\n \n cleanup:\n-\tfor_each_msi_entry(desc, dev) {\n+\tfor_each_msi_entry_from(desc, dev) {\n \t\tstruct irq_data *irqd;\n \n \t\tif (desc->irq == virq)\n", "prefixes": [ "RFC", "v4", "2/6" ] }