Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a04bee82 authored by Bjorn Helgaas's avatar Bjorn Helgaas
Browse files

Merge branches 'pci/host-aardvark', 'pci/host-altera', 'pci/host-dra7xx',...

Merge branches 'pci/host-aardvark', 'pci/host-altera', 'pci/host-dra7xx', 'pci/host-hv', 'pci/host-vmd' and 'pci/host-xilinx' into next

* pci/host-aardvark:
  arm64: dts: marvell: Add Aardvark PCIe support for Armada 3700
  PCI: aardvark: Add Aardvark PCI host controller driver
  dt-bindings: add DT binding for the Aardvark PCIe controller

* pci/host-altera:
  PCI: altera: Poll for link up status after retraining the link
  PCI: altera: Check link status before retrain link
  PCI: altera: Reorder read/write functions

* pci/host-dra7xx:
  PCI: dra7xx: Fix return value in case of error

* pci/host-hv:
  PCI: hv: Fix interrupt cleanup path
  PCI: hv: Handle all pending messages in hv_pci_onchannelcallback()
  PCI: hv: Don't leak buffer in hv_pci_onchannelcallback()

* pci/host-vmd:
  x86/PCI: VMD: Separate MSI and MSI-X vector sharing
  x86/PCI: VMD: Use x86_vector_domain as parent domain
  x86/PCI: VMD: Use lock save/restore in interrupt enable path
  x86/PCI: VMD: Initialize list item in IRQ disable
  x86/PCI: VMD: Select device dma ops to override

* pci/host-xilinx:
  PCI: xilinx: Fix return value in case of error

Manually apply changes from pci/demodularize-hosts and
pci/host-request-windows to drivers/pci/host/pci-aardvark.c
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
Aardvark PCIe controller

This PCIe controller is used on the Marvell Armada 3700 ARM64 SoC.

The Device Tree node describing an Aardvark PCIe controller must
contain the following properties:

 - compatible: Should be "marvell,armada-3700-pcie"
 - reg: range of registers for the PCIe controller
 - interrupts: the interrupt line of the PCIe controller
 - #address-cells: set to <3>
 - #size-cells: set to <2>
 - device_type: set to "pci"
 - ranges: ranges for the PCI memory and I/O regions
 - #interrupt-cells: set to <1>
 - msi-controller: indicates that the PCIe controller can itself
   handle MSI interrupts
 - msi-parent: pointer to the MSI controller to be used
 - interrupt-map-mask and interrupt-map: standard PCI properties to
   define the mapping of the PCIe interface to interrupt numbers.
 - bus-range: PCI bus numbers covered

In addition, the Device Tree describing an Aardvark PCIe controller
must include a sub-node that describes the legacy interrupt controller
built into the PCIe controller. This sub-node must have the following
properties:

 - interrupt-controller
 - #interrupt-cells: set to <1>

Example:

	pcie0: pcie@d0070000 {
		compatible = "marvell,armada-3700-pcie";
		device_type = "pci";
		status = "disabled";
		reg = <0 0xd0070000 0 0x20000>;
		#address-cells = <3>;
		#size-cells = <2>;
		bus-range = <0x00 0xff>;
		interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
		#interrupt-cells = <1>;
		msi-controller;
		msi-parent = <&pcie0>;
		ranges = <0x82000000 0 0xe8000000   0 0xe8000000 0 0x1000000 /* Port 0 MEM */
			  0x81000000 0 0xe9000000   0 0xe9000000 0 0x10000>; /* Port 0 IO*/
		interrupt-map-mask = <0 0 0 7>;
		interrupt-map = <0 0 0 1 &pcie_intc 0>,
				<0 0 0 2 &pcie_intc 1>,
				<0 0 0 3 &pcie_intc 2>,
				<0 0 0 4 &pcie_intc 3>;
		pcie_intc: interrupt-controller {
			interrupt-controller;
			#interrupt-cells = <1>;
		};
	};
+7 −0
Original line number Diff line number Diff line
@@ -8742,6 +8742,13 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S:	Maintained
F:	drivers/pci/host/*mvebu*

PCI DRIVER FOR AARDVARK (Marvell Armada 3700)
M:	Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
L:	linux-pci@vger.kernel.org
L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S:	Maintained
F:	drivers/pci/host/pci-aardvark.c

PCI DRIVER FOR NVIDIA TEGRA
M:	Thierry Reding <thierry.reding@gmail.com>
L:	linux-tegra@vger.kernel.org
+5 −0
Original line number Diff line number Diff line
@@ -76,3 +76,8 @@
&usb3 {
	status = "okay";
};

/* CON17 (PCIe) / CON12 (mini-PCIe) */
&pcie0 {
	status = "okay";
};
+25 −0
Original line number Diff line number Diff line
@@ -141,5 +141,30 @@
				      <0x1d40000 0x40000>; /* GICR */
			};
		};

		pcie0: pcie@d0070000 {
			compatible = "marvell,armada-3700-pcie";
			device_type = "pci";
			status = "disabled";
			reg = <0 0xd0070000 0 0x20000>;
			#address-cells = <3>;
			#size-cells = <2>;
			bus-range = <0x00 0xff>;
			interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
			#interrupt-cells = <1>;
			msi-parent = <&pcie0>;
			msi-controller;
			ranges = <0x82000000 0 0xe8000000   0 0xe8000000 0 0x1000000 /* Port 0 MEM */
				  0x81000000 0 0xe9000000   0 0xe9000000 0 0x10000>; /* Port 0 IO*/
			interrupt-map-mask = <0 0 0 7>;
			interrupt-map = <0 0 0 1 &pcie_intc 0>,
					<0 0 0 2 &pcie_intc 1>,
					<0 0 0 3 &pcie_intc 2>,
					<0 0 0 4 &pcie_intc 3>;
			pcie_intc: interrupt-controller {
				interrupt-controller;
				#interrupt-cells = <1>;
			};
		};
	};
};
+25 −16
Original line number Diff line number Diff line
@@ -119,10 +119,11 @@ static void vmd_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
static void vmd_irq_enable(struct irq_data *data)
{
	struct vmd_irq *vmdirq = data->chip_data;
	unsigned long flags;

	raw_spin_lock(&list_lock);
	raw_spin_lock_irqsave(&list_lock, flags);
	list_add_tail_rcu(&vmdirq->node, &vmdirq->irq->irq_list);
	raw_spin_unlock(&list_lock);
	raw_spin_unlock_irqrestore(&list_lock, flags);

	data->chip->irq_unmask(data);
}
@@ -130,12 +131,14 @@ static void vmd_irq_enable(struct irq_data *data)
static void vmd_irq_disable(struct irq_data *data)
{
	struct vmd_irq *vmdirq = data->chip_data;
	unsigned long flags;

	data->chip->irq_mask(data);

	raw_spin_lock(&list_lock);
	raw_spin_lock_irqsave(&list_lock, flags);
	list_del_rcu(&vmdirq->node);
	raw_spin_unlock(&list_lock);
	INIT_LIST_HEAD_RCU(&vmdirq->node);
	raw_spin_unlock_irqrestore(&list_lock, flags);
}

/*
@@ -166,16 +169,20 @@ static irq_hw_number_t vmd_get_hwirq(struct msi_domain_info *info,
 * XXX: We can be even smarter selecting the best IRQ once we solve the
 * affinity problem.
 */
static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd)
static struct vmd_irq_list *vmd_next_irq(struct vmd_dev *vmd, struct msi_desc *desc)
{
	int i, best = 0;
	int i, best = 1;
	unsigned long flags;

	raw_spin_lock(&list_lock);
	if (!desc->msi_attrib.is_msix || vmd->msix_count == 1)
		return &vmd->irqs[0];

	raw_spin_lock_irqsave(&list_lock, flags);
	for (i = 1; i < vmd->msix_count; i++)
		if (vmd->irqs[i].count < vmd->irqs[best].count)
			best = i;
	vmd->irqs[best].count++;
	raw_spin_unlock(&list_lock);
	raw_spin_unlock_irqrestore(&list_lock, flags);

	return &vmd->irqs[best];
}
@@ -184,14 +191,15 @@ static int vmd_msi_init(struct irq_domain *domain, struct msi_domain_info *info,
			unsigned int virq, irq_hw_number_t hwirq,
			msi_alloc_info_t *arg)
{
	struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(arg->desc)->bus);
	struct msi_desc *desc = arg->desc;
	struct vmd_dev *vmd = vmd_from_bus(msi_desc_to_pci_dev(desc)->bus);
	struct vmd_irq *vmdirq = kzalloc(sizeof(*vmdirq), GFP_KERNEL);

	if (!vmdirq)
		return -ENOMEM;

	INIT_LIST_HEAD(&vmdirq->node);
	vmdirq->irq = vmd_next_irq(vmd);
	vmdirq->irq = vmd_next_irq(vmd, desc);
	vmdirq->virq = virq;

	irq_domain_set_info(domain, virq, vmdirq->irq->vmd_vector, info->chip,
@@ -203,11 +211,12 @@ static void vmd_msi_free(struct irq_domain *domain,
			struct msi_domain_info *info, unsigned int virq)
{
	struct vmd_irq *vmdirq = irq_get_chip_data(virq);
	unsigned long flags;

	/* XXX: Potential optimization to rebalance */
	raw_spin_lock(&list_lock);
	raw_spin_lock_irqsave(&list_lock, flags);
	vmdirq->irq->count--;
	raw_spin_unlock(&list_lock);
	raw_spin_unlock_irqrestore(&list_lock, flags);

	kfree_rcu(vmdirq, rcu);
}
@@ -261,7 +270,7 @@ static struct device *to_vmd_dev(struct device *dev)

static struct dma_map_ops *vmd_dma_ops(struct device *dev)
{
	return to_vmd_dev(dev)->archdata.dma_ops;
	return get_dma_ops(to_vmd_dev(dev));
}

static void *vmd_alloc(struct device *dev, size_t size, dma_addr_t *addr,
@@ -367,7 +376,7 @@ static void vmd_teardown_dma_ops(struct vmd_dev *vmd)
{
	struct dma_domain *domain = &vmd->dma_domain;

	if (vmd->dev->dev.archdata.dma_ops)
	if (get_dma_ops(&vmd->dev->dev))
		del_dma_domain(domain);
}

@@ -379,7 +388,7 @@ static void vmd_teardown_dma_ops(struct vmd_dev *vmd)

static void vmd_setup_dma_ops(struct vmd_dev *vmd)
{
	const struct dma_map_ops *source = vmd->dev->dev.archdata.dma_ops;
	const struct dma_map_ops *source = get_dma_ops(&vmd->dev->dev);
	struct dma_map_ops *dest = &vmd->dma_ops;
	struct dma_domain *domain = &vmd->dma_domain;

@@ -594,7 +603,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd)
	sd->node = pcibus_to_node(vmd->dev->bus);

	vmd->irq_domain = pci_msi_create_irq_domain(NULL, &vmd_msi_domain_info,
						    NULL);
						    x86_vector_domain);
	if (!vmd->irq_domain)
		return -ENODEV;

Loading