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

powerpc/fsl_msi: add support for "msi-address-64" property

Add support for the msi-address-64 property of a PCI node. This property
specifies the PCI address of MSIIR (message signaled interrupt index
register).

In commit 3da34aae ("powerpc/fsl: Support unique MSI addresses per PCIe Root
Complex"), the msi_addr_hi/msi_addr_lo fields of struct fsl_msi were redefined
from an actual address to just an offset, but the fields were not renamed
accordingly. These fields are replace with a single field, msiir_offset,
to reflect the new meaning.

Signed-off-by: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

authored by

Timur Tabi and committed by
Kumar Gala
2bcd1c0c 45116806

+57 -8
+42
Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
··· 25 25 are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed 26 26 to MPIC. 27 27 28 + Optional properties: 29 + - msi-address-64: 64-bit PCI address of the MSIIR register. The MSIIR register 30 + is used for MSI messaging. The address of MSIIR in PCI address space is 31 + the MSI message address. 32 + 33 + This property may be used in virtualized environments where the hypervisor 34 + has created an alternate mapping for the MSIR block. See below for an 35 + explanation. 36 + 37 + 28 38 Example: 29 39 msi@41600 { 30 40 compatible = "fsl,mpc8610-msi", "fsl,mpic-msi"; ··· 51 41 0xe7 0>; 52 42 interrupt-parent = <&mpic>; 53 43 }; 44 + 45 + The Freescale hypervisor and msi-address-64 46 + ------------------------------------------- 47 + Normally, PCI devices have access to all of CCSR via an ATMU mapping. The 48 + Freescale MSI driver calculates the address of MSIIR (in the MSI register 49 + block) and sets that address as the MSI message address. 50 + 51 + In a virtualized environment, the hypervisor may need to create an IOMMU 52 + mapping for MSIIR. The Freescale ePAPR hypervisor has this requirement 53 + because of hardware limitations of the Peripheral Access Management Unit 54 + (PAMU), which is currently the only IOMMU that the hypervisor supports. 55 + The ATMU is programmed with the guest physical address, and the PAMU 56 + intercepts transactions and reroutes them to the true physical address. 57 + 58 + In the PAMU, each PCI controller is given only one primary window. The 59 + PAMU restricts DMA operations so that they can only occur within a window. 60 + Because PCI devices must be able to DMA to memory, the primary window must 61 + be used to cover all of the guest's memory space. 62 + 63 + PAMU primary windows can be divided into 256 subwindows, and each 64 + subwindow can have its own address mapping ("guest physical" to "true 65 + physical"). However, each subwindow has to have the same alignment, which 66 + means they cannot be located at just any address. Because of these 67 + restrictions, it is usually impossible to create a 4KB subwindow that 68 + covers MSIIR where it's normally located. 69 + 70 + Therefore, the hypervisor has to create a subwindow inside the same 71 + primary window used for memory, but mapped to the MSIR block (where MSIIR 72 + lives). The first subwindow after the end of guest memory is used for 73 + this. The address specified in the msi-address-64 property is the PCI 74 + address of MSIIR. The hypervisor configures the PAMU to map that address to 75 + the true physical address of MSIIR.
+14 -6
arch/powerpc/sysdev/fsl_msi.c
··· 30 30 31 31 struct fsl_msi_feature { 32 32 u32 fsl_pic_ip; 33 - u32 msiir_offset; 33 + u32 msiir_offset; /* Offset of MSIIR, relative to start of MSIR bank */ 34 34 }; 35 35 36 36 struct fsl_msi_cascade_data { ··· 126 126 { 127 127 struct fsl_msi *msi_data = fsl_msi_data; 128 128 struct pci_controller *hose = pci_bus_to_host(pdev->bus); 129 - u64 base = fsl_pci_immrbar_base(hose); 129 + u64 address; /* Physical address of the MSIIR */ 130 + int len; 131 + const u64 *reg; 130 132 131 - msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); 132 - msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); 133 + /* If the msi-address-64 property exists, then use it */ 134 + reg = of_get_property(hose->dn, "msi-address-64", &len); 135 + if (reg && (len == sizeof(u64))) 136 + address = be64_to_cpup(reg); 137 + else 138 + address = fsl_pci_immrbar_base(hose) + msi_data->msiir_offset; 139 + 140 + msg->address_lo = lower_32_bits(address); 141 + msg->address_hi = upper_32_bits(address); 133 142 134 143 msg->data = hwirq; 135 144 ··· 368 359 369 360 msi->irqhost->host_data = msi; 370 361 371 - msi->msi_addr_hi = 0x0; 372 - msi->msi_addr_lo = features->msiir_offset + (res.start & 0xfffff); 362 + msi->msiir_offset = features->msiir_offset + (res.start & 0xfffff); 373 363 374 364 rc = fsl_msi_init_allocator(msi); 375 365 if (rc) {
+1 -2
arch/powerpc/sysdev/fsl_msi.h
··· 28 28 29 29 unsigned long cascade_irq; 30 30 31 - u32 msi_addr_lo; 32 - u32 msi_addr_hi; 31 + u32 msiir_offset; /* Offset of MSIIR, relative to start of CCSR */ 33 32 void __iomem *msi_regs; 34 33 u32 feature; 35 34 int msi_virqs[NR_MSI_REG];