linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, Joerg Roedel <joro@8bytes.org>,
	Will Deacon <will@kernel.org>,
	linux-pci@vger.kernel.org, Bjorn Helgaas <bhelgaas@google.com>,
	Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
	Marc Zyngier <maz@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jason Gunthorpe <jgg@mellanox.com>,
	Dave Jiang <dave.jiang@intel.com>,
	Alex Williamson <alex.williamson@redhat.com>,
	Kevin Tian <kevin.tian@intel.com>,
	Dan Williams <dan.j.williams@intel.com>,
	Logan Gunthorpe <logang@deltatee.com>,
	Ashok Raj <ashok.raj@intel.com>, Jon Mason <jdmason@kudzu.us>,
	Allen Hubbe <allenbh@gmail.com>
Subject: [patch V2 33/33] irqchip: Add IDXD Interrupt Message Store driver
Date: Mon, 21 Nov 2022 15:38:27 +0100 (CET)	[thread overview]
Message-ID: <20221121091328.288703733@linutronix.de> (raw)
In-Reply-To: 20221121083657.157152924@linutronix.de

Provide a driver for the Intel IDXD IMS implementation. The implementation
uses a large message store array in device memory.

The IMS domain implementation is minimal and just provides the required
irq_chip callbacks and one domain callback which prepares the MSI
descriptor for easy usage in the irq_chip callbacks.

The necessary iobase is stored in the irqdomain and the PASID which is
required for operation is handed in via msi_instance_cookie in the
allocation function.

Not much to see here. A few lines of code and a filled in template is all
what's needed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 drivers/irqchip/Kconfig                    |    7 +
 drivers/irqchip/Makefile                   |    1 
 drivers/irqchip/irq-pci-intel-idxd.c       |  143 +++++++++++++++++++++++++++++
 include/linux/irqchip/irq-pci-intel-idxd.h |   22 ++++
 4 files changed, 173 insertions(+)

--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -695,4 +695,11 @@ config SUNPLUS_SP7021_INTC
 	  chained controller, routing all interrupt source in P-Chip to
 	  the primary controller on C-Chip.
 
+config PCI_INTEL_IDXD_IMS
+	tristate "Intel IDXD Interrupt Message Store controller"
+	depends on PCI_MSI
+	help
+	  Support for Intel IDXD IMS Interrupt Message Store controller
+	  with IMS slot storage in a slot array in device memory
+
 endmenu
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -121,3 +121,4 @@ obj-$(CONFIG_IRQ_IDT3243X)		+= irq-idt32
 obj-$(CONFIG_APPLE_AIC)			+= irq-apple-aic.o
 obj-$(CONFIG_MCHP_EIC)			+= irq-mchp-eic.o
 obj-$(CONFIG_SUNPLUS_SP7021_INTC)	+= irq-sp7021-intc.o
+obj-$(CONFIG_PCI_INTEL_IDXD_IMS)	+= irq-pci-intel-idxd.o
--- /dev/null
+++ b/drivers/irqchip/irq-pci-intel-idxd.c
@@ -0,0 +1,143 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Interrupt chip and domain for Intel IDXD with hardware array based
+ * interrupt message store (IMS).
+ */
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/msi.h>
+#include <linux/pci.h>
+
+#include <linux/irqchip/irq-pci-intel-idxd.h>
+
+MODULE_LICENSE("GPL");
+
+/**
+ * struct ims_slot - The hardware layout of a slot in the memory table
+ * @address_lo:	Lower 32bit address
+ * @address_hi:	Upper 32bit address
+ * @data:	Message data
+ * @ctrl:	Control word
+ */
+struct ims_slot {
+	u32	address_lo;
+	u32	address_hi;
+	u32	data;
+	u32	ctrl;
+} __packed;
+
+/* Bit to mask the interrupt in the control word */
+#define CTRL_VECTOR_MASKBIT	BIT(0)
+/* Bit to enable PASID in the control word */
+#define CTRL_PASID_ENABLE	BIT(3)
+/* Position of PASID.LSB in the control word */
+#define CTRL_PASID_SHIFT	12
+
+static inline void iowrite32_and_flush(u32 value, void __iomem *addr)
+{
+	iowrite32(value, addr);
+	ioread32(addr);
+}
+
+static void idxd_mask(struct irq_data *data)
+{
+	struct msi_desc *desc = irq_data_get_msi_desc(data);
+	struct ims_slot __iomem *slot = desc->data.dcookie.iobase;
+	u32 cval = (u32)desc->data.icookie.value;
+
+	iowrite32_and_flush(cval | CTRL_VECTOR_MASKBIT, &slot->ctrl);
+}
+
+static void idxd_unmask(struct irq_data *data)
+{
+	struct msi_desc *desc = irq_data_get_msi_desc(data);
+	struct ims_slot __iomem *slot = desc->data.dcookie.iobase;
+	u32 cval = (u32)desc->data.icookie.value;
+
+	iowrite32_and_flush(cval, &slot->ctrl);
+}
+
+static void idxd_write_msi_msg(struct irq_data *data, struct msi_msg *msg)
+{
+	struct msi_desc *desc = irq_data_get_msi_desc(data);
+	struct ims_slot __iomem *slot = desc->data.dcookie.iobase;
+
+	iowrite32(msg->address_lo, &slot->address_lo);
+	iowrite32(msg->address_hi, &slot->address_hi);
+	iowrite32_and_flush(msg->data, &slot->data);
+}
+
+static void idxd_shutdown(struct irq_data *data)
+{
+	struct msi_desc *desc = irq_data_get_msi_desc(data);
+	struct ims_slot __iomem *slot = desc->data.dcookie.iobase;
+
+	iowrite32(0, &slot->address_lo);
+	iowrite32(0, &slot->address_hi);
+	iowrite32(0, &slot->data);
+	iowrite32_and_flush(CTRL_VECTOR_MASKBIT, &slot->ctrl);
+}
+
+static void idxd_prepare_desc(struct irq_domain *domain, msi_alloc_info_t *arg,
+			      struct msi_desc *desc)
+{
+	struct msi_domain_info *info = domain->host_data;
+	struct ims_slot __iomem *slot;
+
+	/* Set up the slot address for the irq_chip callbacks */
+	slot = (__force struct ims_slot __iomem *) info->data;
+	slot += desc->msi_index;
+	desc->data.dcookie.iobase = slot;
+
+	/* Mask the interrupt for paranoia sake */
+	iowrite32_and_flush(CTRL_VECTOR_MASKBIT, &slot->ctrl);
+
+	/*
+	 * The caller provided PASID. Shift it to the proper position
+	 * and set the PASID enable bit.
+	 */
+	desc->data.icookie.value <<= CTRL_PASID_SHIFT;
+	desc->data.icookie.value |= CTRL_PASID_ENABLE;
+
+	arg->hwirq = desc->msi_index;
+}
+
+static const struct msi_domain_template idxd_ims_template = {
+	.chip = {
+		.name			= "PCI-IDXD",
+		.irq_mask		= idxd_mask,
+		.irq_unmask		= idxd_unmask,
+		.irq_write_msi_msg	= idxd_write_msi_msg,
+		.irq_shutdown		= idxd_shutdown,
+		.flags			= IRQCHIP_ONESHOT_SAFE,
+	},
+
+	.ops = {
+		.prepare_desc		= idxd_prepare_desc,
+	},
+
+	.info = {
+		.flags			= MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS |
+					  MSI_FLAG_FREE_MSI_DESCS |
+					  MSI_FLAG_PCI_IMS,
+		.bus_token		= DOMAIN_BUS_PCI_DEVICE_IMS,
+	},
+};
+
+/**
+ * pci_intel_idxd_create_ims_domain - Create a IDXD IMS domain
+ * @pdev:	IDXD PCI device to operate on
+ * @slots:	Pointer to the mapped slot memory arrray
+ * @nr_slots:	The number of slots in the array
+ *
+ * Returns: True on success, false otherwise
+ *
+ * The domain is automatically destroyed when the @pdev is destroyed
+ */
+bool pci_intel_idxd_create_ims_domain(struct pci_dev *pdev, void __iomem *slots,
+				      unsigned int nr_slots)
+{
+	return pci_create_ims_domain(pdev, &idxd_ims_template, nr_slots, (__force void *)slots);
+}
+EXPORT_SYMBOL_GPL(pci_intel_idxd_create_ims_domain);
--- /dev/null
+++ b/include/linux/irqchip/irq-pci-intel-idxd.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* (C) Copyright 2022 Thomas Gleixner <tglx@linutronix.de> */
+
+#ifndef _LINUX_IRQCHIP_IRQ_PCI_INTEL_IDXD_H
+#define _LINUX_IRQCHIP_IRQ_PCI_INTEL_IDXD_H
+
+#include <linux/msi_api.h>
+#include <linux/bits.h>
+#include <linux/types.h>
+
+/*
+ * Conveniance macro to wrap the PASID for interrupt allocation
+ * via pci_ims_alloc_irq(pdev, INTEL_IDXD_DEV_COOKIE(pasid))
+ */
+#define INTEL_IDXD_DEV_COOKIE(pasid)	(union msi_instance_cookie) { .value = (pasid), }
+
+struct pci_dev;
+
+bool pci_intel_idxd_create_ims_domain(struct pci_dev *pdev, void __iomem *slots,
+				      unsigned int nr_slots);
+
+#endif


  parent reply	other threads:[~2022-11-21 14:42 UTC|newest]

Thread overview: 71+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-21 14:37 [patch V2 00/33] genirq, PCI/MSI: Support for per device MSI and PCI/IMS - Part 3 implementation Thomas Gleixner
2022-11-21 14:37 ` [patch V2 01/33] genirq/msi: Rearrange MSI domain flags Thomas Gleixner
2022-11-21 14:37 ` [patch V2 02/33] genirq/msi: Provide struct msi_parent_ops Thomas Gleixner
2022-11-23  7:57   ` Tian, Kevin
2022-11-23 11:28     ` Thomas Gleixner
2022-11-24  0:53       ` Tian, Kevin
2022-11-21 14:37 ` [patch V2 03/33] genirq/msi: Provide data structs for per device domains Thomas Gleixner
2022-11-23  7:57   ` Tian, Kevin
2022-11-23 11:29     ` Thomas Gleixner
2022-11-21 14:37 ` [patch V2 04/33] genirq/msi: Add size info to struct msi_domain_info Thomas Gleixner
2022-11-21 14:37 ` [patch V2 05/33] genirq/msi: Split msi_create_irq_domain() Thomas Gleixner
2022-11-21 14:37 ` [patch V2 06/33] genirq/irqdomain: Add irq_domain::dev for per device MSI domains Thomas Gleixner
2022-11-21 14:37 ` [patch V2 07/33] genirq/msi: Provide msi_create/free_device_irq_domain() Thomas Gleixner
2022-11-23  8:02   ` Tian, Kevin
2022-11-23 11:38     ` Thomas Gleixner
2022-11-23 21:01       ` Thomas Gleixner
2022-11-24  1:07       ` Tian, Kevin
2022-11-24  8:36         ` Thomas Gleixner
2022-11-28  1:47           ` Tian, Kevin
2022-11-21 14:37 ` [patch V2 08/33] genirq/msi: Provide msi_match_device_domain() Thomas Gleixner
2022-11-21 14:37 ` [patch V2 09/33] genirq/msi: Add range checking to msi_insert_desc() Thomas Gleixner
2022-11-21 14:37 ` [patch V2 10/33] PCI/MSI: Split __pci_write_msi_msg() Thomas Gleixner
2022-11-21 14:37 ` [patch V2 11/33] genirq/msi: Provide BUS_DEVICE_PCI_MSI[X] Thomas Gleixner
2022-11-21 14:38 ` [patch V2 12/33] PCI/MSI: Add support for per device MSI[X] domains Thomas Gleixner
2022-11-23  8:08   ` Tian, Kevin
2022-11-23 11:41     ` Thomas Gleixner
2022-11-23 21:50       ` Thomas Gleixner
2022-11-24  1:08         ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 13/33] x86/apic/vector: Provide MSI parent domain Thomas Gleixner
2022-11-23  8:16   ` Tian, Kevin
2022-11-23 13:42     ` Thomas Gleixner
2022-11-24  1:10       ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 14/33] PCI/MSI: Remove unused pci_dev_has_special_msi_domain() Thomas Gleixner
2022-11-21 14:38 ` [patch V2 15/33] iommu/vt-d: Switch to MSI parent domains Thomas Gleixner
2022-11-21 14:38 ` [patch V2 16/33] iommu/amd: Switch to MSI base domains Thomas Gleixner
2022-11-21 14:38 ` [patch V2 17/33] x86/apic/msi: Remove arch_create_remap_msi_irq_domain() Thomas Gleixner
2022-11-21 14:38 ` [patch V2 18/33] genirq/msi: Provide struct msi_map Thomas Gleixner
2022-11-21 14:38 ` [patch V2 19/33] genirq/msi: Provide msi_desc::msi_data Thomas Gleixner
2022-11-23  8:27   ` Tian, Kevin
2022-11-23 11:41     ` Thomas Gleixner
2022-11-21 14:38 ` [patch V2 20/33] genirq/msi: Provide msi_domain_ops::prepare_desc() Thomas Gleixner
2022-11-21 14:38 ` [patch V2 21/33] genirq/msi: Provide msi_domain_alloc_irq_at() Thomas Gleixner
2022-11-24  2:54   ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 22/33] genirq/msi: Provide MSI_FLAG_MSIX_ALLOC_DYN Thomas Gleixner
2022-11-21 14:38 ` [patch V2 23/33] PCI/MSI: Split MSI-X descriptor setup Thomas Gleixner
2022-11-21 14:38 ` [patch V2 24/33] PCI/MSI: Provide prepare_desc() MSI domain op Thomas Gleixner
2022-11-21 14:38 ` [patch V2 25/33] PCI/MSI: Provide post-enable dynamic allocation interfaces for MSI-X Thomas Gleixner
2022-11-24  2:58   ` Tian, Kevin
2022-11-24  9:08     ` Thomas Gleixner
2022-11-28  1:49       ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 26/33] x86/apic/msi: Enable MSI_FLAG_PCI_MSIX_ALLOC_DYN Thomas Gleixner
2022-11-21 14:38 ` [patch V2 27/33] genirq/msi: Provide constants for PCI/IMS support Thomas Gleixner
2022-11-24  3:01   ` Tian, Kevin
2022-11-24  9:10     ` Thomas Gleixner
2022-11-24 13:09       ` Jason Gunthorpe
2022-11-24 13:28         ` Thomas Gleixner
2022-11-21 14:38 ` [patch V2 28/33] PCI/MSI: Provide IMS (Interrupt Message Store) support Thomas Gleixner
2022-11-24  3:10   ` Tian, Kevin
2022-11-24  9:10     ` Thomas Gleixner
2022-11-21 14:38 ` [patch V2 29/33] PCI/MSI: Provide pci_ims_alloc/free_irq() Thomas Gleixner
2022-11-24  3:11   ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 30/33] x86/apic/msi: Enable PCI/IMS Thomas Gleixner
2022-11-21 14:38 ` [patch V2 31/33] iommu/vt-d: " Thomas Gleixner
2022-11-24  3:17   ` Tian, Kevin
2022-11-24  9:37     ` Thomas Gleixner
2022-11-24 13:14       ` Jason Gunthorpe
2022-11-24 13:21         ` Thomas Gleixner
2022-11-28  1:54           ` Tian, Kevin
2022-11-21 14:38 ` [patch V2 32/33] iommu/amd: " Thomas Gleixner
2022-11-21 14:38 ` Thomas Gleixner [this message]
2022-11-24  3:19   ` [patch V2 33/33] irqchip: Add IDXD Interrupt Message Store driver Tian, Kevin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221121091328.288703733@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=alex.williamson@redhat.com \
    --cc=allenbh@gmail.com \
    --cc=ashok.raj@intel.com \
    --cc=bhelgaas@google.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.jiang@intel.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jdmason@kudzu.us \
    --cc=jgg@mellanox.com \
    --cc=joro@8bytes.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=logang@deltatee.com \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=maz@kernel.org \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).