Re: [kvm-unit-tests PATCH v5 09/12] pci: Add generic ECAM host support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 21, 2016 at 11:26:55AM +0200, Andrew Jones wrote:
> On Tue, Jul 19, 2016 at 02:53:06PM +0200, Alexander Gordeev wrote:
> > Unlike x86, other architectures using generic ECAM PCI host
> > do not have a luxury of PCI bus initialized by a BIOS and
> > ready to use at start. Thus, we need allocate and assign
> > resources to all devices, much like an architecture's
> > firmware would do.
> > 
> > There is no any sort of resource management for memory and
> > io spaces, since only ones-per-BAR allocations are expected
> > and no deallocations at all.
> > 
> > Cc: Thomas Huth <thuth@xxxxxxxxxx>
> > Cc: Andrew Jones <drjones@xxxxxxxxxx>
> > Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx>
> > Signed-off-by: Alexander Gordeev <agordeev@xxxxxxxxxx>
> > ---
> >  lib/asm-generic/pci-host-bridge.h |  26 ++++
> >  lib/pci-host-generic.c            | 295 ++++++++++++++++++++++++++++++++++++++
> >  lib/pci-host-generic.h            |  46 ++++++
> >  lib/pci.c                         |   4 +-
> >  lib/pci.h                         |   3 +
> >  5 files changed, 372 insertions(+), 2 deletions(-)
> >  create mode 100644 lib/asm-generic/pci-host-bridge.h
> >  create mode 100644 lib/pci-host-generic.c
> >  create mode 100644 lib/pci-host-generic.h
> > 
> > diff --git a/lib/asm-generic/pci-host-bridge.h b/lib/asm-generic/pci-host-bridge.h
> > new file mode 100644
> > index 000000000000..872df3a81310
> > --- /dev/null
> > +++ b/lib/asm-generic/pci-host-bridge.h
> > @@ -0,0 +1,26 @@
> > +#ifndef _ASM_PCI_HOST_BRIDGE_H_
> > +#define _ASM_PCI_HOST_BRIDGE_H_
> > +/*
> > + * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev <agordeev@xxxxxxxxxx>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +
> > +phys_addr_t pci_host_bridge_get_paddr(uint64_t addr);
> > +
> > +static inline
> > +phys_addr_t pci_translate_addr(pcidevaddr_t __unused dev, uint64_t addr)
> > +{
> > +	/*
> > +	 * Assume we only have single PCI host bridge in a system.
> > +	 */
> > +	return pci_host_bridge_get_paddr(addr);
> > +}
> > +
> > +uint8_t pci_config_readb(pcidevaddr_t dev, uint8_t reg);
> > +uint16_t pci_config_readw(pcidevaddr_t dev, uint8_t reg);
> > +uint32_t pci_config_readl(pcidevaddr_t dev, uint8_t reg);
> > +void pci_config_writel(pcidevaddr_t dev, uint8_t reg, uint32_t val);
> > +
> > +#endif
> > diff --git a/lib/pci-host-generic.c b/lib/pci-host-generic.c
> > new file mode 100644
> > index 000000000000..4a2716a33150
> > --- /dev/null
> > +++ b/lib/pci-host-generic.c
> > @@ -0,0 +1,295 @@
> > +/*
> > + * Generic PCI host controller as described in PCI Bus Binding to Open Firmware
> > + *
> > + * Copyright (C) 2016, Red Hat Inc, Alexander Gordeev <agordeev@xxxxxxxxxx>
> > + *
> > + * This work is licensed under the terms of the GNU LGPL, version 2.
> > + */
> > +#include "libcflat.h"
> > +#include "devicetree.h"
> > +#include "alloc.h"
> > +#include "pci.h"
> > +#include "asm/pci.h"
> > +#include "asm/io.h"
> > +#include "pci-host-generic.h"
> > +#include <linux/pci_regs.h>
> > +
> > +static struct pci_host_bridge *pci_host_bridge;
> > +
> > +static int of_flags_to_pci_type(u32 of_flags)
> > +{
> > +	static int type_map[] = {
> > +		[1] = PCI_BASE_ADDRESS_SPACE_IO,
> > +		[2] = PCI_BASE_ADDRESS_MEM_TYPE_32,
> > +		[3] = PCI_BASE_ADDRESS_MEM_TYPE_64
> > +	};
> > +	int idx = (of_flags >> 24) & 0x03;
> > +	int res;
> > +
> > +	assert(idx > 0);
> > +	res = type_map[idx];
> > +
> > +	if (of_flags & 0x40000000)
> > +		res |= PCI_BASE_ADDRESS_MEM_PREFETCH;
> > +
> > +	return res;
> > +}
> > +
> > +static int pci_bar_type(u32 bar)
> > +{
> > +	if (bar & PCI_BASE_ADDRESS_SPACE)
> > +		return PCI_BASE_ADDRESS_SPACE_IO;
> > +	else
> > +		return bar & (PCI_BASE_ADDRESS_MEM_TYPE_MASK |
> > +			      PCI_BASE_ADDRESS_MEM_PREFETCH);
> > +}
> > +
> > +/*
> > + * Probe DT for a generic PCI host controller
> > + * See kernel Documentation/devicetree/bindings/pci/host-generic-pci.txt
> > + * and function gen_pci_probe() in drivers/pci/host/pci-host-generic.c
> > + */
> > +static struct pci_host_bridge *pci_dt_probe(void)
> > +{
> > +	struct pci_host_bridge *host;
> > +	const void *fdt = dt_fdt();
> > +	const struct fdt_property *prop;
> > +	struct dt_pbus_reg base;
> > +	struct dt_device dt_dev;
> > +	struct dt_bus dt_bus;
> > +	struct pci_addr_space *as;
> > +	fdt32_t *data;
> > +	u32 bus, bus_max;
> > +	u32 nac, nsc, nac_root, nsc_root;
> > +	int nr_range_cells, nr_addr_spaces;
> > +	int ret, node, len, i;
> > +
> > +	if (!dt_available()) {
> > +		printf("No device tree found\n");
> > +		return NULL;
> > +	}
> > +
> > +	dt_bus_init_defaults(&dt_bus);
> > +	dt_device_init(&dt_dev, &dt_bus, NULL);
> > +
> > +	node = fdt_path_offset(fdt, "/");
> > +	assert(node >= 0);
> > +
> > +	ret = dt_get_nr_cells(node, &nac_root, &nsc_root);
> > +	assert(ret == 0);
> > +	assert(nac_root == 1 || nac_root == 2);
> > +
> > +	node = fdt_node_offset_by_compatible(fdt, node,
> > +					     "pci-host-ecam-generic");
> > +	if (node == -FDT_ERR_NOTFOUND) {
> > +		printf("No PCIe ECAM compatible controller found\n");
> > +		return NULL;
> > +	}
> > +	assert(node >= 0);
> > +
> > +	prop = fdt_get_property(fdt, node, "device_type", &len);
> > +	assert(prop && len == 4 && !strcmp((char *)prop->data, "pci"));
> > +
> > +	dt_device_bind_node(&dt_dev, node);
> > +	ret = dt_pbus_get_base(&dt_dev, &base);
> > +	assert(ret == 0);
> > +
> > +	prop = fdt_get_property(fdt, node, "bus-range", &len);
> > +	if (prop == NULL) {
> > +		assert(len == -FDT_ERR_NOTFOUND);
> > +		bus		= 0x00;
> > +		bus_max		= 0xff;
> > +	} else {
> > +		data		= (fdt32_t *)prop->data;
> > +		bus		= fdt32_to_cpu(data[0]);
> > +		bus_max		= fdt32_to_cpu(data[1]);
> > +		assert(bus <= bus_max);
> > +	}
> > +	assert(bus_max < base.size / (1 << PCI_ECAM_BUS_SHIFT));
> 
> I see you kept the inequality, rather than my suggestion to change it to
> assert(bus_max + 1 == base.size / (1 << PCI_ECAM_BUS_SHIFT)) Any reason
> why?

Because I do not read "bus-range" property description as it should
match the host address space size. IOW, number of implemented busses
which is less than host address space does not appear as a failure.

> I'm not too worried about it though...
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux