Whilst debugging some SPARC64 issues relating to PCI bridges, it became apparent that the logic for generating the ranges property for the PCI host bridge isn't flexible enough to allow generation of the correct values across all architectures.
In order to allow per-architecture customisation of PCI host bridge properties, split them out into a separate struct within pci_arch_t and migrate all PCI architectures over to use them. As a side effect we can now remove the rbase and rlen members from pci_arch_t since they are no longer required.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (5): pci: define pci_range_t typedef and add it to pci_arch_t struct pci: move memory type enum from drivers/pci.c to include/drivers/pci.h arch: update pci_host_t host_ranges with values for each architecture pci: update pci_set_host_ranges() to use the new pci_arch_t host_ranges arch: remove rbase and rlen from pci_arch_t for all PCI architectures
arch/ppc/qemu/init.c | 29 +++++++++++++++++------- arch/sparc64/openbios.c | 6 +++++ arch/x86/openbios.c | 4 ++++ drivers/pci.c | 56 ++++++++++++++--------------------------------- include/drivers/pci.h | 19 ++++++++++++++-- 5 files changed, 64 insertions(+), 50 deletions(-)
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- include/drivers/pci.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 5772b79..5a7480b 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -3,6 +3,15 @@
typedef uint32_t pci_addr;
+typedef struct pci_range_t pci_range_t; + +struct pci_range_t { + unsigned int type; + unsigned long childaddr; + unsigned long parentaddr; + unsigned long len; +}; + typedef struct pci_arch_t pci_arch_t;
struct pci_arch_t { @@ -20,6 +29,7 @@ struct pci_arch_t { unsigned long io_len; unsigned long rbase; unsigned long rlen; + pci_range_t host_ranges[4]; uint8_t irqs[4]; };
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/pci.c | 7 ------- include/drivers/pci.h | 7 +++++++ 2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/drivers/pci.c b/drivers/pci.c index d506a50..432ef71 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -59,13 +59,6 @@ const pci_arch_t *arch; #define IS_PREFETCHABLE 0x40000000 #define IS_ALIASED 0x20000000
-enum { - CONFIGURATION_SPACE = 0, - IO_SPACE = 1, - MEMORY_SPACE_32 = 2, - MEMORY_SPACE_64 = 3, -}; - static int encode_int32_cells(int num_cells, u32 *prop, ucell val) { int i = 0; diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 5a7480b..02599c1 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -1,6 +1,13 @@ #ifndef _H_PCI #define _H_PCI
+enum { + CONFIGURATION_SPACE = 0, + IO_SPACE = 1, + MEMORY_SPACE_32 = 2, + MEMORY_SPACE_64 = 3, +}; + typedef uint32_t pci_addr;
typedef struct pci_range_t pci_range_t;
As derived from the current logic in pci_host_set_ranges().
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/ppc/qemu/init.c | 21 +++++++++++++++++++++ arch/sparc64/openbios.c | 6 ++++++ arch/x86/openbios.c | 4 ++++ 3 files changed, 31 insertions(+)
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index ffbf08d..6984e91 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -108,6 +108,11 @@ static const pci_arch_t known_arch[] = { .io_len = 0x00010000, .rbase = 0x00000000, .rlen = 0x00400000, + .host_ranges = { + { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0x80000000, .len = 0x00010000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xc0100000, .len = 0x10000000 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + }, .irqs = { 9, 11, 9, 11 } }, [ARCH_MAC99] = { @@ -125,6 +130,11 @@ static const pci_arch_t known_arch[] = { .io_len = 0x00800000, .rbase = 0x00000000, .rlen = 0x01000000, + .host_ranges = { + { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + }, .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } }, [ARCH_MAC99_U3] = { @@ -142,6 +152,11 @@ static const pci_arch_t known_arch[] = { .io_len = 0x00800000, .rbase = 0x00000000, .rlen = 0x01000000, + .host_ranges = { + { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + }, .irqs = { 0x1b, 0x1c, 0x1d, 0x1e } }, [ARCH_HEATHROW] = { @@ -159,6 +174,12 @@ static const pci_arch_t known_arch[] = { .io_len = 0x00800000, .rbase = 0xfd000000, .rlen = 0x01000000, + .host_ranges = { + { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xfe000000, .len = 0x00800000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xfd000000, .len = 0x01000000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + }, .irqs = { 21, 22, 23, 24 } }, }; diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index d624eb2..20673bc 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -64,6 +64,12 @@ static const struct hwdef hwdefs[] = { .mem_len = 0x10000000, .io_base = APB_SPECIAL_BASE + 0x2000000ULL, // PCI Bus I/O space .io_len = 0x10000, + .host_ranges = { + { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, + { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x10000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0x10000000 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + }, .irqs = { 0, 1, 2, 3 }, }, .machine_id_low = 0, diff --git a/arch/x86/openbios.c b/arch/x86/openbios.c index d8a0f9e..8a48a95 100644 --- a/arch/x86/openbios.c +++ b/arch/x86/openbios.c @@ -30,6 +30,10 @@ static const pci_arch_t default_pci_host = { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = PCI_DEVICE_ID_INTEL_82441, .io_base = 0x1000, + .host_ranges = { + { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0x1000, .len = 0 }, + { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } + } }; #endif
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/sparc64/openbios.c | 2 +- drivers/pci.c | 49 ++++++++++++++++------------------------------- 2 files changed, 17 insertions(+), 34 deletions(-)
diff --git a/arch/sparc64/openbios.c b/arch/sparc64/openbios.c index 20673bc..ef1fdae 100644 --- a/arch/sparc64/openbios.c +++ b/arch/sparc64/openbios.c @@ -67,7 +67,7 @@ static const struct hwdef hwdefs[] = { .host_ranges = { { .type = CONFIGURATION_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x1000000ULL, .len = 0x2000000 }, { .type = IO_SPACE, .parentaddr = 0, .childaddr = APB_SPECIAL_BASE + 0x2000000ULL, .len = 0x10000 }, - { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0x10000000 }, + { .type = MEMORY_SPACE_32, .parentaddr = 0x100000, .childaddr = APB_MEM_BASE + 0x100000ULL, .len = 0x10000000 }, { .type = 0, .parentaddr = 0, .childaddr = 0, .len = 0 } }, .irqs = { 0, 1, 2, 3 }, diff --git a/drivers/pci.c b/drivers/pci.c index 432ef71..27fb5f0 100644 --- a/drivers/pci.c +++ b/drivers/pci.c @@ -470,41 +470,24 @@ static void pci_host_set_ranges(const pci_config_t *config) { phandle_t dev = get_cur_dev(); u32 props[32]; - int ncells; - - ncells = 0; + int ncells = 0; + pci_range_t range; + int i; -#ifdef CONFIG_SPARC64 - /* While configuration space isn't mentioned in the IEEE-1275 PCI - bindings, it appears in the PCI host bridge ranges property in - real device trees. Hence we disable this range for all host - bridges except for SPARC, particularly as it causes Darwin/OS X - to incorrectly calculated PCI memory space ranges on PPC. */ - ncells += pci_encode_phys_addr(props + ncells, 0, CONFIGURATION_SPACE, - 0, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->cfg_addr); - ncells += pci_encode_size(props + ncells, arch->cfg_len); -#endif - - if (arch->io_base) { - ncells += pci_encode_phys_addr(props + ncells, 0, IO_SPACE, - 0, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->io_base); - ncells += pci_encode_size(props + ncells, arch->io_len); - } - if (arch->rbase) { - ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, - 0, 0, 0); - ncells += host_encode_phys_addr(props + ncells, arch->rbase); - ncells += pci_encode_size(props + ncells, arch->rlen); - } - if (arch->pci_mem_base) { - ncells += pci_encode_phys_addr(props + ncells, 0, MEMORY_SPACE_32, - 0, 0, arch->pci_mem_base); - ncells += host_encode_phys_addr(props + ncells, arch->host_pci_base + - arch->pci_mem_base); - ncells += pci_encode_size(props + ncells, arch->mem_len); + for (i = 0; i < 4; i++) { + range = arch->host_ranges[i]; + + /* End of range list reached */ + if (range.type == 0x0 && range.len == 0x0) { + break; + } + + ncells += pci_encode_phys_addr(props + ncells, 0, range.type, + 0, 0, range.parentaddr); + ncells += host_encode_phys_addr(props + ncells, range.childaddr); + ncells += pci_encode_size(props + ncells, range.len); } + set_property(dev, "ranges", (char *)props, ncells * sizeof(props[0])); }
This is now handled by the host_ranges property so remove all remaining references.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- arch/ppc/qemu/init.c | 8 -------- include/drivers/pci.h | 2 -- 2 files changed, 10 deletions(-)
diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index 6984e91..5ce080c 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -106,8 +106,6 @@ static const pci_arch_t known_arch[] = { .mem_len = 0x10000000, .io_base = 0x80000000, .io_len = 0x00010000, - .rbase = 0x00000000, - .rlen = 0x00400000, .host_ranges = { { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0x80000000, .len = 0x00010000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xc0100000, .len = 0x10000000 }, @@ -128,8 +126,6 @@ static const pci_arch_t known_arch[] = { .mem_len = 0x10000000, .io_base = 0xf2000000, .io_len = 0x00800000, - .rbase = 0x00000000, - .rlen = 0x01000000, .host_ranges = { { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 }, @@ -150,8 +146,6 @@ static const pci_arch_t known_arch[] = { .mem_len = 0x10000000, .io_base = 0xf2000000, .io_len = 0x00800000, - .rbase = 0x00000000, - .rlen = 0x01000000, .host_ranges = { { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xf2000000, .len = 0x00800000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0x80000000, .childaddr = 0x80000000, .len = 0x10000000 }, @@ -172,8 +166,6 @@ static const pci_arch_t known_arch[] = { .mem_len = 0x10000000, .io_base = 0xfe000000, .io_len = 0x00800000, - .rbase = 0xfd000000, - .rlen = 0x01000000, .host_ranges = { { .type = IO_SPACE, .parentaddr = 0, .childaddr = 0xfe000000, .len = 0x00800000 }, { .type = MEMORY_SPACE_32, .parentaddr = 0, .childaddr = 0xfd000000, .len = 0x01000000 }, diff --git a/include/drivers/pci.h b/include/drivers/pci.h index 02599c1..e9f20a1 100644 --- a/include/drivers/pci.h +++ b/include/drivers/pci.h @@ -34,8 +34,6 @@ struct pci_arch_t { unsigned long mem_len; unsigned long io_base; unsigned long io_len; - unsigned long rbase; - unsigned long rlen; pci_range_t host_ranges[4]; uint8_t irqs[4]; };
On 08/07/17 20:36, Mark Cave-Ayland wrote:
Whilst debugging some SPARC64 issues relating to PCI bridges, it became apparent that the logic for generating the ranges property for the PCI host bridge isn't flexible enough to allow generation of the correct values across all architectures.
In order to allow per-architecture customisation of PCI host bridge properties, split them out into a separate struct within pci_arch_t and migrate all PCI architectures over to use them. As a side effect we can now remove the rbase and rlen members from pci_arch_t since they are no longer required.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk
Mark Cave-Ayland (5): pci: define pci_range_t typedef and add it to pci_arch_t struct pci: move memory type enum from drivers/pci.c to include/drivers/pci.h arch: update pci_host_t host_ranges with values for each architecture pci: update pci_set_host_ranges() to use the new pci_arch_t host_ranges arch: remove rbase and rlen from pci_arch_t for all PCI architectures
arch/ppc/qemu/init.c | 29 +++++++++++++++++------- arch/sparc64/openbios.c | 6 +++++ arch/x86/openbios.c | 4 ++++ drivers/pci.c | 56 ++++++++++++++--------------------------------- include/drivers/pci.h | 19 ++++++++++++++-- 5 files changed, 64 insertions(+), 50 deletions(-)
Applied to master.
ATB,
Mark.