Skip to contentSkip to conversation

ARM: PCI: implement generic PCI host controller

PATCH New Will Deacon 5 participants 30 messages Feb 18, 2014 – Feb 21, 2014

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

v3 cover ARM: PCI: implement generic PCI host controller

Hi,

This is version 3 of the patches previously posted here:

v1: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/229679.html
v2: http://lists.infradead.org/pipermail/linux-arm-kernel/2014-February/232213.html

Changes since v2 include:

- Tightening up of the DT requirements:
* Must have at least a non-prefetchable memory region
* "reg" property now defines a base and size for config space
* bus-range property supported and used in conjunction with "reg"
* device_type must be "pci"

- Fixed bus mapping so we don't sleep in atomic

- Updated compatible strings and file names to get rid of "arm"

- Added a really dumb I/O space allocator

- Moved a bunch of ->probe() into ->setup(). Note that I've not included Arnd's patch to propagate ->setup() failures back to ->probe(), so despite the use of devm_* to manage resource allocations, I still have explicit cleanup code on the failure paths.

All feedback welcome.

Will

Will Deacon (3):
ARM: mach-virt: allow PCI support to be selected
ARM: bios32: use pci_enable_resource to enable PCI resources
PCI: ARM: add support for generic PCI host controller

 .../devicetree/bindings/pci/host-generic-pci.txt   |  88 +++++
 arch/arm/kernel/bios32.c                           |  37 +-
 arch/arm/mach-virt/Kconfig                         |   1 +
 drivers/pci/host/Kconfig                           |   7 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-host-generic.c                | 381 +++++++++++++++++++++
 6 files changed, 481 insertions(+), 34 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt
 create mode 100644 drivers/pci/host/pci-host-generic.c
Signature · 1 line
1.8.2.2
#1 lore raw

PATCH v3 1/3 ARM: mach-virt: allow PCI support to be selected

mach-virt can make use of virtio-pci devices, which requires the guest kernel to have PCI support selected.

This patch selects CONFIG_MIGHT_HAVE_PCI when CONFIG_ARCH_VIRT=y.

---
 arch/arm/mach-virt/Kconfig | 1 +
 1 file changed, 1 insertion(+)
arch/arm/mach-virt/Kconfig +1 -0
index 081d46929436..f40fb55574cb 100644
@@ -8,3 +8,4 @@ config ARCH_VIRT
 	select CPU_V7
 	select SPARSE_IRQ
 	select USE_OF
+	select MIGHT_HAVE_PCI
Signature · 1 line
1.8.2.2
#2 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

In reply to Will Deacon

This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code.

A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents).

---
 arch/arm/kernel/bios32.c | 37 +++----------------------------------
 1 file changed, 3 insertions(+), 34 deletions(-)
arch/arm/kernel/bios32.c +3 -34
index 317da88ae65b..91f48804e3bb 100644
@@ -608,41 +608,10 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		/* Only set up the requested stuff */
-		if (!(mask & (1 << idx)))
-			continue;
-
-		r = dev->resource + idx;
-		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because"
-			       " of resource collisions\n", pci_name(dev));
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
+	if (pci_has_flag(PCI_PROBE_ONLY))
+		return 0;
 
-	/*
-	 * Bridges (eg, cardbus bridges) need to be fully enabled
-	 */
-	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
-		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
-	if (cmd != old_cmd) {
-		printk("PCI: enabling device %s (%04x -> %04x)\n",
-		       pci_name(dev), old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
+	return pci_enable_resources(dev, mask);
 }
 
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
Signature · 1 line
1.8.2.2
#3 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

Quoted 11 lines · Will Deacon

This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code.

A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents).

Quoted 3 lines

Tested acceptably fine here with crudbus-from-hell.

Signature · 3 lines
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
#4 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

Quoted 12 lines · Russell King - ARM Linux
Quoted 11 lines · Will Deacon

This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code.

A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents).

Quoted 7 lines
Quoted 3 lines

Tested acceptably fine here with crudbus-from-hell.

Cheers Russell.

Will

#5 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

In reply to Russell King - ARM Linux
Quoted 12 lines · Russell King - ARM Linux
Quoted 11 lines · Will Deacon

This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code.

A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents).

Quoted 7 lines
Quoted 3 lines

Tested acceptably fine here with crudbus-from-hell.

Damn, I just found a problem with this patch when PCI_PROBE_ONLY is set.

The problem is that bios32.c won't create a resource hierarchy for the firmware-initialised resources, so we have a bunch of orphaned resources that we can't pass to pci_enable_resources (since it checks r->parent).

This means that, unless firmware *enables* all of the resources, Linux won't be able to enable them. I think this is stronger than simply not re-assigning devices like the PCI_PROBE_ONLY flag intends.

I can see two solutions:

(1) Just drop this patch and stick with the old code (which doesn't check r->parent). The downside is we still don't have any resource hierarchy, so /proc/iomem doesn't contain bus information.

(2) Walk over the bus claiming the resources that we find. Patch below.

Any thoughts?

Will

--->8

commit 802062290eee961362d3090a50cf851412a63314

Author: Will Deacon <[email protected]>
Date:   Wed Feb 19 23:29:30 2014 +0000

ARM: bios32: claim firmware-initialised resources when PCI_PROBE_ONLY

When initialising a PCI bus with the PCI_PROBE_ONLY flag set, we don't (re-)assign any firmware-initialised resources, leading to an incomplete resource hierarchy and devices with orphaned resources.

If we try to enable these orphaned resources using pci_enable_resources, we will get back -EINVAL since a valid ->parent pointer is required. Consequently, pcibios_enable_device doesn't attempt to enable devices when PCI_PROBE_ONLY is set. This has the unfortunate effect of requiring the firmware to *enable* all of the devices!

This patch fixes the problem by building up a resource hierarchy from the firmware-initialised resources when PCI_PROBE_ONLY is set.

arch/arm/kernel/bios32.c +31 -3
index 91f48804e3bb..d65c76a4d7ad 100644
@@ -514,6 +514,35 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
 	}
 }
 
+static void pcibios_claim_one_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *child_bus;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		int i;
+
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *r = &dev->resource[i];
+
+			if (r->parent || !r->start || !r->flags)
+				continue;
+
+			pr_debug("PCI: Claiming %s: "
+				 "Resource %d: %016llx..%016llx [%x]\n",
+				 pci_name(dev), i,
+				 (unsigned long long)r->start,
+				 (unsigned long long)r->end,
+				 (unsigned int)r->flags);
+
+			pci_claim_resource(dev, i);
+		}
+	}
+
+	list_for_each_entry(child_bus, &bus->children, node)
+		pcibios_claim_one_bus(child_bus);
+}
+
 void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
 {
 	struct pci_sys_data *sys;
@@ -541,6 +570,8 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
 			 * Assign resources.
 			 */
 			pci_bus_assign_resources(bus);
+		} else {
+			pcibios_claim_one_bus(bus);
 		}
 
 		/*
@@ -608,9 +639,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-	if (pci_has_flag(PCI_PROBE_ONLY))
-		return 0;
-
 	return pci_enable_resources(dev, mask);
 }
 
maintainer
#6 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

Quoted 23 lines · Will Deacon
Quoted 12 lines · Russell King - ARM Linux
Quoted 11 lines · Will Deacon

This patch moves bios32 over to using the generic code for enabling PCI resources. Since the core code takes care of bridge resources too, we can also drop the explicit IO and MEMORY enabling for them in the arch code.

A side-effect of this change is that we no longer explicitly enable devices when running in PCI_PROBE_ONLY mode. This stays closer to the meaning of the option and prevents us from trying to enable devices without any assigned resources (the core code refuses to enable resources without parents).

Quoted 7 lines
Quoted 3 lines

Tested acceptably fine here with crudbus-from-hell.

Damn, I just found a problem with this patch when PCI_PROBE_ONLY is set.

Quoted 7 lines

The problem is that bios32.c won't create a resource hierarchy for the firmware-initialised resources, so we have a bunch of orphaned resources that we can't pass to pci_enable_resources (since it checks r->parent).

This means that, unless firmware *enables* all of the resources, Linux won't be able to enable them. I think this is stronger than simply not re-assigning devices like the PCI_PROBE_ONLY flag intends.

By "firmware enabling resources," do you mean firmware assigning addresses in the BARs and turning on the PCI_COMMAND_MEMORY (or _IO) bits?

I'd like to make the generic code ignore BAR values if PCI_COMMAND_MEMORY (or _IO) is cleared. When those bits are cleared, I don't think there's a good way to determine whether the address in a BAR is valid.

It sounds like you want PCI_PROBE_ONLY to mean that we should try to use the existing BAR contents even if PCI_COMMAND_MEMORY is cleared. Is that right? Maybe we could try to use the existing BAR address if we can actually claim it, i.e., if it is inside one of the upstream bridge windows.

Quoted 9 lines

I can see two solutions:

(1) Just drop this patch and stick with the old code (which doesn't check r->parent). The downside is we still don't have any resource hierarchy, so /proc/iomem doesn't contain bus information.

(2) Walk over the bus claiming the resources that we find. Patch below.

Any thoughts?

I really want to nuke all the arch-specific "claim resource" code because it isn't arch-dependent.

Quoted 80 lines

commit 802062290eee961362d3090a50cf851412a63314

Author: Will Deacon <[email protected]>
Date:   Wed Feb 19 23:29:30 2014 +0000

ARM: bios32: claim firmware-initialised resources when PCI_PROBE_ONLY

When initialising a PCI bus with the PCI_PROBE_ONLY flag set, we don't (re-)assign any firmware-initialised resources, leading to an incomplete resource hierarchy and devices with orphaned resources.

If we try to enable these orphaned resources using pci_enable_resources, we will get back -EINVAL since a valid ->parent pointer is required. Consequently, pcibios_enable_device doesn't attempt to enable devices when PCI_PROBE_ONLY is set. This has the unfortunate effect of requiring the firmware to *enable* all of the devices!

This patch fixes the problem by building up a resource hierarchy from the firmware-initialised resources when PCI_PROBE_ONLY is set.

arch/arm/kernel/bios32.c +31 -3
index 91f48804e3bb..d65c76a4d7ad 100644
@@ -514,6 +514,35 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
        }
 }
 
+static void pcibios_claim_one_bus(struct pci_bus *bus)
+{
+       struct pci_dev *dev;
+       struct pci_bus *child_bus;
+
+       list_for_each_entry(dev, &bus->devices, bus_list) {
+               int i;
+
+               for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+                       struct resource *r = &dev->resource[i];
+
+                       if (r->parent || !r->start || !r->flags)
+                               continue;
+
+                       pr_debug("PCI: Claiming %s: "
+                                "Resource %d: %016llx..%016llx [%x]\n",
+                                pci_name(dev), i,
+                                (unsigned long long)r->start,
+                                (unsigned long long)r->end,
+                                (unsigned int)r->flags);
+
+                       pci_claim_resource(dev, i);
+               }
+       }
+
+       list_for_each_entry(child_bus, &bus->children, node)
+               pcibios_claim_one_bus(child_bus);
+}
+
 void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
 {
        struct pci_sys_data *sys;
@@ -541,6 +570,8 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
                         * Assign resources.
                         */
                        pci_bus_assign_resources(bus);
+               } else {
+                       pcibios_claim_one_bus(bus);
                }
 
                /*
@@ -608,9 +639,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
  */
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-       if (pci_has_flag(PCI_PROBE_ONLY))
-               return 0;
-
        return pci_enable_resources(dev, mask);
 }
 
#7 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

Quoted 10 lines · Bjorn Helgaas
Quoted 9 lines

Damn, I just found a problem with this patch when PCI_PROBE_ONLY is set.

The problem is that bios32.c won't create a resource hierarchy for the firmware-initialised resources, so we have a bunch of orphaned resources that we can't pass to pci_enable_resources (since it checks r->parent).

This means that, unless firmware *enables* all of the resources, Linux won't be able to enable them. I think this is stronger than simply not re-assigning devices like the PCI_PROBE_ONLY flag intends.

Quoted 8 lines

By "firmware enabling resources," do you mean firmware assigning addresses in the BARs and turning on the PCI_COMMAND_MEMORY (or _IO) bits?

I'd like to make the generic code ignore BAR values if PCI_COMMAND_MEMORY (or _IO) is cleared. When those bits are cleared, I don't think there's a good way to determine whether the address in a BAR is valid.

I think this is pretty smart, PROBE_ONLY really should mean 'everything is perfect, do not touch it' and if the device isn't enabled, well.. It isn't enabled, the firmware should have done it.

Will, this if for kvmtool right? Keeping the patch as is and instead changing kvmtool to enable the devices seems like a good option?

Alternatively, there are OF ways to communicate the BAR assignment through the DT. I actually have no idea how this information is used by the core code, but it might let you avoid the probe_only by specifying the desired BAR value through the DT.

Regards,
Jason

#8 lore raw

PATCH v3 2/3 ARM: bios32: use pci_enable_resource to enable PCI resources

Hi Jason, Bjorn,

Thanks for the comments.

Quoted 15 lines · Jason Gunthorpe
Quoted 14 lines · Bjorn Helgaas
Quoted 9 lines

Damn, I just found a problem with this patch when PCI_PROBE_ONLY is set.

The problem is that bios32.c won't create a resource hierarchy for the firmware-initialised resources, so we have a bunch of orphaned resources that we can't pass to pci_enable_resources (since it checks r->parent).

This means that, unless firmware *enables* all of the resources, Linux won't be able to enable them. I think this is stronger than simply not re-assigning devices like the PCI_PROBE_ONLY flag intends.

By "firmware enabling resources," do you mean firmware assigning addresses in the BARs and turning on the PCI_COMMAND_MEMORY (or _IO) bits?

Quoted 8 lines
Quoted 4 lines

I'd like to make the generic code ignore BAR values if PCI_COMMAND_MEMORY (or _IO) is cleared. When those bits are cleared, I don't think there's a good way to determine whether the address in a BAR is valid.

I think this is pretty smart, PROBE_ONLY really should mean 'everything is perfect, do not touch it' and if the device isn't enabled, well.. It isn't enabled, the firmware should have done it.

Yes, that's one (sane) interpretation of the PROBE_ONLY flag and I'm happy to run with it if we all agree. We'll need some extra code paths to assign disabled resources when PROBE_ONLY is passed, but that can come later.

Quoted 2 lines

Will, this if for kvmtool right? Keeping the patch as is and instead changing kvmtool to enable the devices seems like a good option?

Sure, I can do that easily enough. I just wanted to make sure that we agree on PROBE_ONLY before I start hacking kvmtool. I'll drop this additional patch.

Cheers,

Will

#9 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

In reply to Will Deacon

This patch adds support for a generic PCI host controller, such as a firmware-initialised device with static windows or an emulation by something such as kvmtool.

The controller itself has no configuration registers and has its address spaces described entirely by the device-tree (using the bindings from ePAPR). Both CAM and ECAM are supported for Config Space accesses.

Corresponding documentation is added for the DT binding.

---
 .../devicetree/bindings/pci/host-generic-pci.txt   |  88 +++++
 drivers/pci/host/Kconfig                           |   7 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pci-host-generic.c                | 381 +++++++++++++++++++++
 4 files changed, 477 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/host-generic-pci.txt
 create mode 100644 drivers/pci/host/pci-host-generic.c
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +88 -0
new file mode 100644
index 000000000000..03e1640a7602
@@ -0,0 +1,88 @@
+* Generic PCI host controller
+
+Firmware-initialised PCI host controllers and PCI emulations, such as the
+virtio-pci implementations found in kvmtool and other para-virtualised
+systems, do not require driver support for complexities such as regulator
+and clock management. In fact, the controller may not even require the
+configuration of a control interface by the operating system, instead
+presenting a set of fixed windows describing a subset of IO, Memory and
+Configuration Spaces.
+
+Such a controller can be described purely in terms of the standardized device
+tree bindings communicated in pci.txt:
+
+- compatible     : Must be "pci-host-cam-generic" or "pci-host-ecam-generic"
+                   depending on the layout of configuration space (CAM vs
+                   ECAM respectively).
+
+- device_type    : Must be "pci".
+
+- ranges         : As described in IEEE Std 1275-1994, but must provide
+                   at least a definition of non-prefetchable memory. One
+                   or both of prefetchable Memory and IO Space may also
+                   be provided.
+
+- bus-range      : Optional property (also described in IEEE Std 1275-1994)
+                   to indicate the range of bus numbers for this controller.
+                   If absent, defaults to <0 255> (i.e. all buses).
+
+- #address-cells : Must be 3.
+
+- #size-cells    : Must be 2.
+
+- reg            : The Configuration Space base address and size, as accessed
+                   from the parent bus.
+
+Configuration Space is assumed to be memory-mapped (as opposed to being
+accessed via an ioport) and laid out with a direct correspondence to the
+geography of a PCI bus address by concatenating the various components to
+form an offset.
+
+For CAM, this 24-bit offset is:
+
+        cfg_offset(bus, device, function, register) =
+                   bus << 16 | device << 11 | function << 8 | register
+
+Whilst ECAM extends this by 4 bits to accomodate 4k of function space:
+
+        cfg_offset(bus, device, function, register) =
+                   bus << 20 | device << 15 | function << 12 | register
+
+Interrupt mapping is exactly as described in `Open Firmware Recommended
+Practice: Interrupt Mapping' and requires the following properties:
+
+- #interrupt-cells   : Must be 1
+
+- interrupt-map      : <see aforementioned specification>
+
+- interrupt-map-mask : <see aforementioned specification>
+
+
+Example:
+
+pci {
+    compatible = "pci-host-cam-generic"
+    device_type = "pci";
+    #address-cells = <3>;
+    #size-cells = <2>;
+    bus-range = <0x0 0x1>;
+
+    // CPU_PHYSICAL(2)  SIZE(2)
+    reg = <0x0 0x40000000  0x0 0x1000000>;
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
+             <0x2000000 0x0 0x41000000  0x0 0x41000000  0x0 0x3f000000>;
+
+
+    #interrupt-cells = <0x1>;
+
+    // PCI_DEVICE(3)  INT#(1)  CONTROLLER(PHANDLE)  CONTROLLER_DATA(3)
+    interrupt-map = <  0x0 0x0 0x0  0x1  &gic  0x0 0x4 0x1
+                     0x800 0x0 0x0  0x1  &gic  0x0 0x5 0x1
+                    0x1000 0x0 0x0  0x1  &gic  0x0 0x6 0x1
+                    0x1800 0x0 0x0  0x1  &gic  0x0 0x7 0x1>;
+
+    // PCI_DEVICE(3)  INT#(1)
+    interrupt-map-mask = <0xf800 0x0 0x0  0x7>;
+}
drivers/pci/host/Kconfig +7 -0
index 47d46c6d8468..f91637d47065 100644
@@ -33,4 +33,11 @@ config PCI_RCAR_GEN2
 	  There are 3 internal PCI controllers available with a single
 	  built-in EHCI/OHCI host controller present on each one.
 
+config PCI_HOST_GENERIC
+	bool "Generic PCI host controller"
+	depends on ARM && OF
+	help
+	  Say Y here if you want to support a simple generic PCI host
+	  controller, such as the one emulated by kvmtool.
+
 endmenu
drivers/pci/host/Makefile +1 -0
index 13fb3333aa05..bd1bf1ab4ac8 100644
@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o
 obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
+obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
drivers/pci/host/pci-host-generic.c new file +381 -0

381 lines not on this page · raw message

Signature · 1 line
1.8.2.2
#10 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 9 lines · On Tuesday 18 February 2014 12:20:43 Will Deacon wrote:
drivers/pci/host/pci-host-generic.c new file +9 -0
+static int gen_pci_alloc_io_offset(u32 sz, resource_size_t *offset)
+{
+	static DECLARE_BITMAP(io_map, (IO_SPACE_LIMIT + 1) / SZ_64K);
+	int idx, num_wins;
+
+	if (sz > SZ_64K)
+		return -ENOSPC;
+
+	num_wins = (IO_SPACE_LIMIT + 1) / SZ_64K;

drivers/pci/host/pci-host-generic.c line 177

Quoted 10 lines
drivers/pci/host/pci-host-generic.c new file +10 -0
+	idx = 0;
+	do {
+		idx = find_next_zero_bit(io_map, num_wins, idx);
+		if (idx == num_wins)
+			return -ENOSPC;
+	} while (test_and_set_bit(idx, io_map));
+
+	*offset = idx * SZ_64K;
+	return 0;
+}

Sicne you're always starting the search at 0 and you never free the map, this is essentially the same as remembering the last number that was used and using the next one, right?

You should also pass the rang->pci_addr here to calculate the offset in case the pci_addr is not zero.

drivers/pci/host/pci-host-generic.c line 304

Quoted 8 lines
drivers/pci/host/pci-host-generic.c new file +8 -0
+	/* Register our I/O and Memory resources */
+	res_valid = 0;
+	list_for_each_entry(win, &pci->host.windows, list) {
+		struct resource *parent;
+
+		if (resource_type(win->res) == IORESOURCE_IO) {
+			parent = &ioport_resource;
+			err = pci_ioremap_io(win->offset, win->res->start);

and consequently pass the pci_addr rather than the offset here. How about moving the pci_ioremap_io() call into gen_pci_alloc_io_offset()?

Arnd

#11 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 17 lines · Arnd Bergmann
Quoted 15 lines · On Tuesday 18 February 2014 12:20:43 Will Deacon wrote:
drivers/pci/host/pci-host-generic.c new file +15 -0
+static int gen_pci_alloc_io_offset(u32 sz, resource_size_t *offset)
+{
+	static DECLARE_BITMAP(io_map, (IO_SPACE_LIMIT + 1) / SZ_64K);
+	int idx, num_wins;
+
+	if (sz > SZ_64K)
+		return -ENOSPC;
+
+	num_wins = (IO_SPACE_LIMIT + 1) / SZ_64K;
+	idx = 0;
+	do {
+		idx = find_next_zero_bit(io_map, num_wins, idx);
+		if (idx == num_wins)
+			return -ENOSPC;
+	} while (test_and_set_bit(idx, io_map));
Quoted 8 lines

drivers/pci/host/pci-host-generic.c line 177

Quoted 4 lines
drivers/pci/host/pci-host-generic.c new file +4 -0
+
+	*offset = idx * SZ_64K;
+	return 0;
+}

Sicne you're always starting the search at 0 and you never free the map, this is essentially the same as remembering the last number that was used and using the next one, right?

Yes, I can implement that easily enough. I was wondering if there was a case for allowing windows to be freed, but it doesn't feel especially compelling.

Quoted 14 lines

You should also pass the rang->pci_addr here to calculate the offset in case the pci_addr is not zero.

drivers/pci/host/pci-host-generic.c line 304

Quoted 8 lines
drivers/pci/host/pci-host-generic.c new file +8 -0
+	/* Register our I/O and Memory resources */
+	res_valid = 0;
+	list_for_each_entry(win, &pci->host.windows, list) {
+		struct resource *parent;
+
+		if (resource_type(win->res) == IORESOURCE_IO) {
+			parent = &ioport_resource;
+			err = pci_ioremap_io(win->offset, win->res->start);

and consequently pass the pci_addr rather than the offset here. How about moving the pci_ioremap_io() call into gen_pci_alloc_io_offset()?

Can do.

Thanks for the feedback.

Will

#12 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 13 lines · Will Deacon
Quoted 12 lines · Arnd Bergmann

drivers/pci/host/pci-host-generic.c line 304

Quoted 8 lines · On Tuesday 18 February 2014 12:20:43 Will Deacon wrote:
drivers/pci/host/pci-host-generic.c new file +8 -0
+	/* Register our I/O and Memory resources */
+	res_valid = 0;
+	list_for_each_entry(win, &pci->host.windows, list) {
+		struct resource *parent;
+
+		if (resource_type(win->res) == IORESOURCE_IO) {
+			parent = &ioport_resource;
+			err = pci_ioremap_io(win->offset, win->res->start);

and consequently pass the pci_addr rather than the offset here. How about moving the pci_ioremap_io() call into gen_pci_alloc_io_offset()?

I've probably just confused myself, but passing the pci_addr to pci_ioremap_io doesn't make sense to me. My understanding is that:

cpu = bus + offset

In the case of I/O, the offset is really:

offset = (PCI_IO_VIRT_BASE - bus) + window

where window is determined by the simple allocator I wrote.

Now, the __io macro takes care of PCI_IO_VIRT_BASE so we don't actually care about that when adding the PCI I/O resources, instead we'll just pass:

offset = window - bus

and then pci_ioremap_io will just want the window offset, since that's added directly on to PCI_IO_VIRT_BASE for the ioremap_page_range.

If I call pci_ioremap_io(range->pci_addr, ...) then I'm going to trip a BUG_ON unless the pci_addr is within IO_SPACE_LIMIT.

Will

#13 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 12 lines · On Wednesday 19 February 2014 11:07:19 Will Deacon wrote:
Quoted 11 lines · Will Deacon
Quoted 10 lines · Arnd Bergmann
Quoted 8 lines · On Tuesday 18 February 2014 12:20:43 Will Deacon wrote:

+ /* Register our I/O and Memory resources */
+ res_valid = 0;
+ list_for_each_entry(win, &pci->host.windows, list) {

drivers/pci/host/pci-host-generic.c new file +5 -0
+         struct resource *parent;
+
+         if (resource_type(win->res) == IORESOURCE_IO) {
+                 parent = &ioport_resource;
+                 err = pci_ioremap_io(win->offset, win->res->start);
Quoted 5 lines
Quoted 2 lines
Quoted 2 lines

and consequently pass the pci_addr rather than the offset here. How about moving the pci_ioremap_io() call into gen_pci_alloc_io_offset()?

I've probably just confused myself, but passing the pci_addr to pci_ioremap_io doesn't make sense to me.

I think the confusion is that there are two different things we call offset here. The calculation of the offset you pass into pci_ioremap_io() is correct AFAICT now, but it's not what you are supposed to pass into pci_add_resource_offset() or what we normally put into pci_host_bridge_window->offset.

Quoted 3 lines

My understanding is that:

cpu = bus + offset

Right. This would be the case for mem_offset.

Quoted 3 lines

In the case of I/O, the offset is really:

offset = (PCI_IO_VIRT_BASE - bus) + window

I can't seem to make sense of this calculation. PCI_IO_VIRT_BASE is a pointer to the start of the virtual window. You can add offsets to the pointer, but subtracting a number from it is not a well-defined operation.

Quoted 1 line

where window is determined by the simple allocator I wrote.

And your allocator calls it offset, which is what confused me.

Quoted 4 lines

Now, the __io macro takes care of PCI_IO_VIRT_BASE so we don't actually care about that when adding the PCI I/O resources, instead we'll just pass:

offset = window - bus

Yes, this would be the io_offset that you pass into pci_add_resource_offset().

Quoted 2 lines

and then pci_ioremap_io will just want the window offset, since that's added directly on to PCI_IO_VIRT_BASE for the ioremap_page_range.

Yes.

Quoted 2 lines

If I call pci_ioremap_io(range->pci_addr, ...) then I'm going to trip a BUG_ON unless the pci_addr is within IO_SPACE_LIMIT.

range->pci_addr is what you call 'bus' above. Since you want 'window', you have to pass 'bus'+'offset', or 'range->pci_addr + io_offset'. Normally, one of the two would be zero, while the other is equal to 'window'.

Arnd

#14 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Hi Arnd,

Quoted 39 lines · Arnd Bergmann
Quoted 2 lines · On Wednesday 19 February 2014 11:07:19 Will Deacon wrote:

I've probably just confused myself, but passing the pci_addr to pci_ioremap_io doesn't make sense to me.

I think the confusion is that there are two different things we call offset here. The calculation of the offset you pass into pci_ioremap_io() is correct AFAICT now, but it's not what you are supposed to pass into pci_add_resource_offset() or what we normally put into pci_host_bridge_window->offset.

Quoted 3 lines

My understanding is that:

cpu = bus + offset

Right. This would be the case for mem_offset.

Quoted 3 lines

In the case of I/O, the offset is really:

offset = (PCI_IO_VIRT_BASE - bus) + window

I can't seem to make sense of this calculation. PCI_IO_VIRT_BASE is a pointer to the start of the virtual window. You can add offsets to the pointer, but subtracting a number from it is not a well-defined operation.

Quoted 1 line

where window is determined by the simple allocator I wrote.

And your allocator calls it offset, which is what confused me.

Quoted 4 lines

Now, the __io macro takes care of PCI_IO_VIRT_BASE so we don't actually care about that when adding the PCI I/O resources, instead we'll just pass:

offset = window - bus

Yes, this would be the io_offset that you pass into pci_add_resource_offset().

Quoted 2 lines

and then pci_ioremap_io will just want the window offset, since that's added directly on to PCI_IO_VIRT_BASE for the ioremap_page_range.

Quoted 8 lines

Yes.

Quoted 2 lines

If I call pci_ioremap_io(range->pci_addr, ...) then I'm going to trip a BUG_ON unless the pci_addr is within IO_SPACE_LIMIT.

range->pci_addr is what you call 'bus' above. Since you want 'window', you have to pass 'bus'+'offset', or 'range->pci_addr + io_offset'. Normally, one of the two would be zero, while the other is equal to 'window'.

Good, so we're in agreement! The issue indeed seems to be that there are multiple names for the same things :)

Will

#15 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

In reply to Will Deacon

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Regards,
Jason

#16 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 8 lines · Jason Gunthorpe

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Will

#17 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 10 lines · On Tuesday 18 February 2014 18:44:20 Will Deacon wrote:
Quoted 8 lines · Jason Gunthorpe

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Quoted 7 lines

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Do you have a list of the stuff in there?

If that is actually port I/O, leaving it in there may be best, but I agree the example should be changed.

Arnd

#18 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 14 lines · Arnd Bergmann
Quoted 13 lines · On Tuesday 18 February 2014 18:44:20 Will Deacon wrote:
Quoted 8 lines · Jason Gunthorpe

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

Quoted 6 lines
Quoted 4 lines

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Do you have a list of the stuff in there?

kvmtool provides an i8042, pci-shmem, an rtc, 8250 and vesa at the usual PC offsets. On ARM, I regularly use the 8250 (there are even DT bindings for it) and MarcZ got the rtc working for fun. Not tried the others though.

Quoted 2 lines

If that is actually port I/O, leaving it in there may be best, but I agree the example should be changed.

Yup, it is port I/O. I'll make something up for the example.

Will

#19 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 4 lines · On Tuesday 18 February 2014 18:51:50 Will Deacon wrote:

kvmtool provides an i8042, pci-shmem, an rtc, 8250 and vesa at the usual PC offsets. On ARM, I regularly use the 8250 (there are even DT bindings for it) and MarcZ got the rtc working for fun. Not tried the others though.

Ah, interesting. But which ones are between 0x1000-0x6200? The ones you list should all be in the ISA range between 0x0-0xfff as far as I can tell, which we keep clear of by setting PCIBIOS_MIN_IO to 0x1000.

Arnd

#20 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 10 lines · Arnd Bergmann
Quoted 4 lines · On Tuesday 18 February 2014 18:51:50 Will Deacon wrote:

kvmtool provides an i8042, pci-shmem, an rtc, 8250 and vesa at the usual PC offsets. On ARM, I regularly use the 8250 (there are even DT bindings for it) and MarcZ got the rtc working for fun. Not tried the others though.

Ah, interesting. But which ones are between 0x1000-0x6200? The ones you list should all be in the ISA range between 0x0-0xfff as far as I can tell, which we keep clear of by setting PCIBIOS_MIN_IO to 0x1000.

I think there's just a hole between 0x1000 - 0x6200.

Will

#21 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

In reply to Will Deacon
Quoted 10 lines · Will Deacon
Quoted 8 lines · Jason Gunthorpe

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Quoted 7 lines

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Just to be clear, kvm has reserved the first 64k of physical address space for this IO window? The 0 is fine then, but it isn't typical of real hardware.

Regarding the 0x6200.. There are two conflicting issues there :(
- You really don't want to let the PCI core assign resources to that range, it probably won't work.
- You probably need that range mapped into the ARM IO window, and the PCI driver is the thing doing that

The PCI core already has a black out for low IO ports, I think it already covers the usual PC suspects so you are probably fine with what you have for KVM.

Jason

#22 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 14 lines · Jason Gunthorpe
Quoted 13 lines · Will Deacon
Quoted 8 lines · Jason Gunthorpe

Documentation/devicetree/bindings/pci/host-generic-pci.txt line 74

Quoted 3 lines · Will Deacon
Documentation/devicetree/bindings/pci/host-generic-pci.txt new file +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

Quoted 8 lines
Quoted 4 lines

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Just to be clear, kvm has reserved the first 64k of physical address space for this IO window? The 0 is fine then, but it isn't typical of real hardware.

Yup, that's spot on.

Quoted 3 lines

Regarding the 0x6200.. There are two conflicting issues there :(
- You really don't want to let the PCI core assign resources to that range, it probably won't work.

Right, with kvmtool we don't support resource assignment (the BARs are fixed) so everything is PCI_PROBE_ONLY.

Quoted 6 lines

- You probably need that range mapped into the ARM IO window, and the PCI driver is the thing doing that

The PCI core already has a black out for low IO ports, I think it already covers the usual PC suspects so you are probably fine with what you have for KVM.

Great, so I'll just update the example then. Thanks!

Will

#23 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 7 lines · On Tuesday 18 February 2014 19:09:29 Will Deacon wrote:
Quoted 4 lines

Regarding the 0x6200.. There are two conflicting issues there
- You really don't want to let the PCI core assign resources to that range, it probably won't work.

Right, with kvmtool we don't support resource assignment (the BARs are fixed) so everything is PCI_PROBE_ONLY.

Ok, I looked at the source now and can confirm:

* 0x0-0x1000 are used for lots of legacy ISA devices.
* PCI devices get assigned IO addresses in 0x400 steps starting at 0x6200.
* There are three PCI drivers doing this: VESA, PCI-SHMEM and virtio-pci.

Regarding the PCI_PROBE_ONLY flag, how do you set that? Should we have a standard DT property for that? On PowerPC we already specified "linux,pci-probe-only" and "linux,pci-assign-all-buses", which seems reasonable to use in architecture independent code as well.

Arnd

#24 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 11 lines · Arnd Bergmann
Quoted 7 lines · On Tuesday 18 February 2014 19:09:29 Will Deacon wrote:
Quoted 4 lines

Regarding the 0x6200.. There are two conflicting issues there
- You really don't want to let the PCI core assign resources to that range, it probably won't work.

Right, with kvmtool we don't support resource assignment (the BARs are fixed) so everything is PCI_PROBE_ONLY.

Ok, I looked at the source now and can confirm:

Quoted 8 lines

* 0x0-0x1000 are used for lots of legacy ISA devices.
* PCI devices get assigned IO addresses in 0x400 steps starting at 0x6200.
* There are three PCI drivers doing this: VESA, PCI-SHMEM and virtio-pci.

Regarding the PCI_PROBE_ONLY flag, how do you set that? Should we have a standard DT property for that? On PowerPC we already specified "linux,pci-probe-only" and "linux,pci-assign-all-buses", which seems reasonable to use in architecture independent code as well.

For arch/arm/ it's done on the command line (pci=firmware) but yes, for the generic driver it sounds like a good idea to put this in the device-tree. I'll look at adding the ppc properties in the next version.

Cheers,

Will

#25 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 16 lines · Will Deacon
Quoted 15 lines · Arnd Bergmann
Quoted 7 lines · On Tuesday 18 February 2014 19:09:29 Will Deacon wrote:
Quoted 4 lines

Regarding the 0x6200.. There are two conflicting issues there
- You really don't want to let the PCI core assign resources to that range, it probably won't work.

Right, with kvmtool we don't support resource assignment (the BARs are fixed) so everything is PCI_PROBE_ONLY.

Ok, I looked at the source now and can confirm:

* 0x0-0x1000 are used for lots of legacy ISA devices.
* PCI devices get assigned IO addresses in 0x400 steps starting at 0x6200.
* There are three PCI drivers doing this: VESA, PCI-SHMEM and virtio-pci.

Quoted 8 lines
Quoted 4 lines

Regarding the PCI_PROBE_ONLY flag, how do you set that? Should we have a standard DT property for that? On PowerPC we already specified "linux,pci-probe-only" and "linux,pci-assign-all-buses", which seems reasonable to use in architecture independent code as well.

For arch/arm/ it's done on the command line (pci=firmware) but yes, for the generic driver it sounds like a good idea to put this in the device-tree. I'll look at adding the ppc properties in the next version.

Damn, I spoke too soon. PowerPC puts this information in the /chosen node, so it applies to all PCI host controllers in the system. That then maps nicely to pci_{add,clear}_flags which are global properties in Linux.

It sounds like this should really be per-controller. What do you think?

Will

#26 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 12 lines · On Tuesday 18 February 2014 19:57:32 Will Deacon wrote:
Quoted 10 lines · Will Deacon
Quoted 5 lines · Arnd Bergmann

On Tuesday 18 February 2014 19:09:29 Will Deacon wrote:
Regarding the PCI_PROBE_ONLY flag, how do you set that? Should we have a standard DT property for that? On PowerPC we already specified "linux,pci-probe-only" and "linux,pci-assign-all-buses", which seems reasonable to use in architecture independent code as well.

For arch/arm/ it's done on the command line (pci=firmware) but yes, for the generic driver it sounds like a good idea to put this in the device-tree. I'll look at adding the ppc properties in the next version.

Quoted 5 lines

Damn, I spoke too soon. PowerPC puts this information in the /chosen node, so it applies to all PCI host controllers in the system. That then maps nicely to pci_{add,clear}_flags which are global properties in Linux.

It sounds like this should really be per-controller. What do you think?

I don't have a strong opinion either way. I think the reason for having it in the /chosen node is so that a second-stage boot loader can easily override it, which is not a concern for us. In particular, the properties are only used on rtas-pci, which means we access the config space to firmware runtime abstraction services rather than hardware registers.

Apparently the embedded powerpc platforms don't support these flags at all, which I also didn't notice at first.

Arnd

#27 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 19 lines · Arnd Bergmann
Quoted 12 lines · On Tuesday 18 February 2014 19:57:32 Will Deacon wrote:
Quoted 10 lines · Will Deacon
Quoted 5 lines · Arnd Bergmann

On Tuesday 18 February 2014 19:09:29 Will Deacon wrote:
Regarding the PCI_PROBE_ONLY flag, how do you set that? Should we have a standard DT property for that? On PowerPC we already specified "linux,pci-probe-only" and "linux,pci-assign-all-buses", which seems reasonable to use in architecture independent code as well.

For arch/arm/ it's done on the command line (pci=firmware) but yes, for the generic driver it sounds like a good idea to put this in the device-tree. I'll look at adding the ppc properties in the next version.

Quoted 5 lines

Damn, I spoke too soon. PowerPC puts this information in the /chosen node, so it applies to all PCI host controllers in the system. That then maps nicely to pci_{add,clear}_flags which are global properties in Linux.

It sounds like this should really be per-controller. What do you think?

Quoted 8 lines

I don't have a strong opinion either way. I think the reason for having it in the /chosen node is so that a second-stage boot loader can easily override it, which is not a concern for us. In particular, the properties are only used on rtas-pci, which means we access the config space to firmware runtime abstraction services rather than hardware registers.

Apparently the embedded powerpc platforms don't support these flags at all, which I also didn't notice at first.

Even in the rtas case there's a:

	#ifdef CONFIG_PPC32 /* Will be made generic soon */

for linux,pci-assign-all-buses. I think I'll just go for linux,pci-probe-only initially, especially as PCI_REASSIGN_ALL_BUS isn't actually used anywhere outside of arch/powerpc/.

Will

#28 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

In reply to Will Deacon
Quoted 10 lines · On Tuesday 18 February 2014 18:44:20 Will Deacon wrote:
Quoted 8 lines · Jason Gunthorpe

Review

Quoted 3 lines · Will Deacon
(quoted diff) +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Quoted 7 lines

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Some more comments about this:

* After I looked at the kvmtool code some more, I think it would be nice to actually move the I/O space window to a nonzero location, e.g. between the PCI space and the AXI space. It's really confusing the way it is, and easy to introduce bugs if you have any code that accidentally relies on the numbers matching up. For all I can tell, kvmtool should just work fine with any definition of ARM_IOPORT_AREA, as long as you apply the trivial patch below.

* pci_get_io_space_block() is a very confusing name for a function that allocates a memory space block in kvmtool. It seems that KVM_IOPORT_AREA is a misnomer for the same reason. Note that PowerPC sets KVM_IOPORT_AREA to zero, but has the I/O space window at SPAPR_PCI_IO_WIN_ADDR, which is non-zero.

* It's interesting that you also support I/O space access to the PCI config space through PC-Style ports 0cf8-0cff. Not sure if that helps at all, but it is another standard way to probe the bus that could easily be implemented as an alternative to CAM and ECAM, in a generic PCI host driver.

Arnd

tools/kvm/arm/kvm-cpu.c +1 -1
index b017994..caf9a57 100644
@@ -105,7 +105,7 @@ bool kvm_cpu__emulate_mmio(struct kvm *kvm, u64 phys_addr, u8 *data, u32 len,
 		return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write);
 	} else if (arm_addr_in_ioport_region(phys_addr)) {
 		int direction = is_write ? KVM_EXIT_IO_OUT : KVM_EXIT_IO_IN;
-		u16 port = phys_addr & USHRT_MAX;
+		u16 port = (phys_addr - ARM_IOPORT_AREA) & USHRT_MAX;
 		return kvm__emulate_io(kvm, port, data, direction, len, 1);
 	} else if (arm_addr_in_pci_region(phys_addr)) {
 		return kvm__emulate_mmio(kvm, phys_addr, data, len, is_write);
#29 lore raw

PATCH v3 3/3 PCI: ARM: add support for generic PCI host controller

Quoted 21 lines · Arnd Bergmann
Quoted 10 lines · On Tuesday 18 February 2014 18:44:20 Will Deacon wrote:
Quoted 8 lines · Jason Gunthorpe

Review

Quoted 3 lines · Will Deacon
(quoted diff) +3 -0
+
+    // BUS_ADDRESS(3)  CPU_PHYSICAL(2)  SIZE(2)
+    ranges = <0x1000000 0x0 0x00000000  0x0 0x00000000  0x0 0x00010000>,
                                           ^^^^^^^^^^^^^^

This probably shouldn't be 0 in the example, nor in your kvm tool output. For example purposes any value will do.

Quoted 7 lines

Hmm, so kvmtool actually provides a PC ioport at 0x0, which is handy since there's an 8250 down there. That means we have:

0x0 - 0x6200 : Weird PC stuff
0x6200 - 0x10000 : PCI IO space

Should I just change everything to be offset by 0x6200?

Some more comments about this:

Quoted 7 lines

* After I looked at the kvmtool code some more, I think it would be nice to actually move the I/O space window to a nonzero location, e.g. between the PCI space and the AXI space. It's really confusing the way it is, and easy to introduce bugs if you have any code that accidentally relies on the numbers matching up. For all I can tell, kvmtool should just work fine with any definition of ARM_IOPORT_AREA, as long as you apply the trivial patch below.

Well, I think we need a bit more than that otherwise our I/O BARs won't be initialised correctly.

Quoted 5 lines

* pci_get_io_space_block() is a very confusing name for a function that allocates a memory space block in kvmtool. It seems that KVM_IOPORT_AREA is a misnomer for the same reason. Note that PowerPC sets KVM_IOPORT_AREA to zero, but has the I/O space window at SPAPR_PCI_IO_WIN_ADDR, which is non-zero.

Agreed about pci_get_io_space_block being a misnomer, that's probably due some cleanup. I don't think KVM_IOPORT_AREA is too bad though (it's zero for PowerPC because I added it and don't have a platform to test on).

Quoted 5 lines

* It's interesting that you also support I/O space access to the PCI config space through PC-Style ports 0cf8-0cff. Not sure if that helps at all, but it is another standard way to probe the bus that could easily be implemented as an alternative to CAM and ECAM, in a generic PCI host driver.

I won't add that initially, but if somebody needs it then it's easy to extend what we currently have.

Will