Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'hv-msi-parent-domain' into main

Nam Cao says:

====================
Subject: [PATCH for-netdev v2 0/2] PCI: hv: MSI parent domain conversion

This series originally belongs to a bigger series sent to PCI tree:
https://lore.kernel.org/linux-pci/024f0122314198fe0a42fef01af53e8953a687ec.1750858083.git.namcao@linutronix.de/

However, during review, we noticed that the patch conflicts with another
patch in netdev tree:
https://lore.kernel.org/netdev/1749651015-9668-1-git-send-email-shradhagupta@linux.microsoft.com/

As this series has no dependency with the rest of the series, we think it
is best to split out this one and send it to netdev, to avoid conflict
resolution headache later on.

Can netdev maintainers please pick it up?
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+85 -28
+1
drivers/pci/Kconfig
··· 223 223 tristate "Hyper-V PCI Frontend" 224 224 depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI && SYSFS 225 225 select PCI_HYPERV_INTERFACE 226 + select IRQ_MSI_LIB 226 227 help 227 228 The PCI device frontend driver allows the kernel to import arbitrary 228 229 PCI devices from a PCI backend to support PCI driver domains.
+83 -28
drivers/pci/controller/pci-hyperv.c
··· 44 44 #include <linux/delay.h> 45 45 #include <linux/semaphore.h> 46 46 #include <linux/irq.h> 47 + #include <linux/irqchip/irq-msi-lib.h> 47 48 #include <linux/msi.h> 48 49 #include <linux/hyperv.h> 49 50 #include <linux/refcount.h> ··· 509 508 struct list_head children; 510 509 struct list_head dr_list; 511 510 512 - struct msi_domain_info msi_info; 513 511 struct irq_domain *irq_domain; 514 512 515 513 struct workqueue_struct *wq; ··· 576 576 static void hv_pci_onchannelcallback(void *context); 577 577 578 578 #ifdef CONFIG_X86 579 - #define DELIVERY_MODE APIC_DELIVERY_MODE_FIXED 580 - #define FLOW_HANDLER handle_edge_irq 581 - #define FLOW_NAME "edge" 579 + #define DELIVERY_MODE APIC_DELIVERY_MODE_FIXED 580 + #define HV_MSI_CHIP_FLAGS MSI_CHIP_FLAG_SET_ACK 582 581 583 582 static int hv_pci_irqchip_init(void) 584 583 { ··· 722 723 #define HV_PCI_MSI_SPI_START 64 723 724 #define HV_PCI_MSI_SPI_NR (1020 - HV_PCI_MSI_SPI_START) 724 725 #define DELIVERY_MODE 0 725 - #define FLOW_HANDLER NULL 726 - #define FLOW_NAME NULL 726 + #define HV_MSI_CHIP_FLAGS MSI_CHIP_FLAG_SET_EOI 727 727 #define hv_msi_prepare NULL 728 728 729 729 struct hv_pci_chip_data { ··· 1685 1687 struct msi_desc *msi = irq_data_get_msi_desc(irq_data); 1686 1688 1687 1689 pdev = msi_desc_to_pci_dev(msi); 1688 - hbus = info->data; 1690 + hbus = domain->host_data; 1689 1691 int_desc = irq_data_get_irq_chip_data(irq_data); 1690 1692 if (!int_desc) 1691 1693 return; ··· 1703 1705 1704 1706 static void hv_irq_mask(struct irq_data *data) 1705 1707 { 1706 - pci_msi_mask_irq(data); 1707 1708 if (data->parent_data->chip->irq_mask) 1708 1709 irq_chip_mask_parent(data); 1709 1710 } ··· 1713 1716 1714 1717 if (data->parent_data->chip->irq_unmask) 1715 1718 irq_chip_unmask_parent(data); 1716 - pci_msi_unmask_irq(data); 1717 1719 } 1718 1720 1719 1721 struct compose_comp_ctxt { ··· 2097 2101 msg->data = 0; 2098 2102 } 2099 2103 2104 + static bool hv_pcie_init_dev_msi_info(struct device *dev, struct irq_domain *domain, 2105 + struct irq_domain *real_parent, struct msi_domain_info *info) 2106 + { 2107 + struct irq_chip *chip = info->chip; 2108 + 2109 + if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info)) 2110 + return false; 2111 + 2112 + info->ops->msi_prepare = hv_msi_prepare; 2113 + 2114 + chip->irq_set_affinity = irq_chip_set_affinity_parent; 2115 + 2116 + if (IS_ENABLED(CONFIG_X86)) 2117 + chip->flags |= IRQCHIP_MOVE_DEFERRED; 2118 + 2119 + return true; 2120 + } 2121 + 2122 + #define HV_PCIE_MSI_FLAGS_REQUIRED (MSI_FLAG_USE_DEF_DOM_OPS | \ 2123 + MSI_FLAG_USE_DEF_CHIP_OPS | \ 2124 + MSI_FLAG_PCI_MSI_MASK_PARENT) 2125 + #define HV_PCIE_MSI_FLAGS_SUPPORTED (MSI_FLAG_MULTI_PCI_MSI | \ 2126 + MSI_FLAG_PCI_MSIX | \ 2127 + MSI_FLAG_PCI_MSIX_ALLOC_DYN | \ 2128 + MSI_GENERIC_FLAGS_MASK) 2129 + 2130 + static const struct msi_parent_ops hv_pcie_msi_parent_ops = { 2131 + .required_flags = HV_PCIE_MSI_FLAGS_REQUIRED, 2132 + .supported_flags = HV_PCIE_MSI_FLAGS_SUPPORTED, 2133 + .bus_select_token = DOMAIN_BUS_PCI_MSI, 2134 + .chip_flags = HV_MSI_CHIP_FLAGS, 2135 + .prefix = "HV-", 2136 + .init_dev_msi_info = hv_pcie_init_dev_msi_info, 2137 + }; 2138 + 2100 2139 /* HW Interrupt Chip Descriptor */ 2101 2140 static struct irq_chip hv_msi_irq_chip = { 2102 2141 .name = "Hyper-V PCIe MSI", 2103 2142 .irq_compose_msi_msg = hv_compose_msi_msg, 2104 2143 .irq_set_affinity = irq_chip_set_affinity_parent, 2105 - #ifdef CONFIG_X86 2106 2144 .irq_ack = irq_chip_ack_parent, 2107 - .flags = IRQCHIP_MOVE_DEFERRED, 2108 - #elif defined(CONFIG_ARM64) 2109 2145 .irq_eoi = irq_chip_eoi_parent, 2110 - #endif 2111 2146 .irq_mask = hv_irq_mask, 2112 2147 .irq_unmask = hv_irq_unmask, 2113 2148 }; 2114 2149 2115 - static struct msi_domain_ops hv_msi_ops = { 2116 - .msi_prepare = hv_msi_prepare, 2117 - .msi_free = hv_msi_free, 2118 - .prepare_desc = pci_msix_prepare_desc, 2150 + static int hv_pcie_domain_alloc(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs, 2151 + void *arg) 2152 + { 2153 + /* 2154 + * TODO: Allocating and populating struct tran_int_desc in hv_compose_msi_msg() 2155 + * should be moved here. 2156 + */ 2157 + int ret; 2158 + 2159 + ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, arg); 2160 + if (ret < 0) 2161 + return ret; 2162 + 2163 + for (int i = 0; i < nr_irqs; i++) { 2164 + irq_domain_set_hwirq_and_chip(d, virq + i, 0, &hv_msi_irq_chip, NULL); 2165 + if (IS_ENABLED(CONFIG_X86)) 2166 + __irq_set_handler(virq + i, handle_edge_irq, 0, "edge"); 2167 + } 2168 + 2169 + return 0; 2170 + } 2171 + 2172 + static void hv_pcie_domain_free(struct irq_domain *d, unsigned int virq, unsigned int nr_irqs) 2173 + { 2174 + struct msi_domain_info *info = d->host_data; 2175 + 2176 + for (int i = 0; i < nr_irqs; i++) 2177 + hv_msi_free(d, info, virq + i); 2178 + 2179 + irq_domain_free_irqs_top(d, virq, nr_irqs); 2180 + } 2181 + 2182 + static const struct irq_domain_ops hv_pcie_domain_ops = { 2183 + .alloc = hv_pcie_domain_alloc, 2184 + .free = hv_pcie_domain_free, 2119 2185 }; 2120 2186 2121 2187 /** ··· 2195 2137 */ 2196 2138 static int hv_pcie_init_irq_domain(struct hv_pcibus_device *hbus) 2197 2139 { 2198 - hbus->msi_info.chip = &hv_msi_irq_chip; 2199 - hbus->msi_info.ops = &hv_msi_ops; 2200 - hbus->msi_info.flags = (MSI_FLAG_USE_DEF_DOM_OPS | 2201 - MSI_FLAG_USE_DEF_CHIP_OPS | MSI_FLAG_MULTI_PCI_MSI | 2202 - MSI_FLAG_PCI_MSIX | MSI_FLAG_PCI_MSIX_ALLOC_DYN); 2203 - hbus->msi_info.handler = FLOW_HANDLER; 2204 - hbus->msi_info.handler_name = FLOW_NAME; 2205 - hbus->msi_info.data = hbus; 2206 - hbus->irq_domain = pci_msi_create_irq_domain(hbus->fwnode, 2207 - &hbus->msi_info, 2208 - hv_pci_get_root_domain()); 2140 + struct irq_domain_info info = { 2141 + .fwnode = hbus->fwnode, 2142 + .ops = &hv_pcie_domain_ops, 2143 + .host_data = hbus, 2144 + .parent = hv_pci_get_root_domain(), 2145 + }; 2146 + 2147 + hbus->irq_domain = msi_create_parent_irq_domain(&info, &hv_pcie_msi_parent_ops); 2209 2148 if (!hbus->irq_domain) { 2210 2149 dev_err(&hbus->hdev->device, 2211 2150 "Failed to build an MSI IRQ domain\n");
+1
kernel/irq/irqdomain.c
··· 1561 1561 } 1562 1562 irq_domain_free_irqs_common(domain, virq, nr_irqs); 1563 1563 } 1564 + EXPORT_SYMBOL_GPL(irq_domain_free_irqs_top); 1564 1565 1565 1566 static void irq_domain_free_irqs_hierarchy(struct irq_domain *domain, 1566 1567 unsigned int irq_base,