x86: Convert PCI init to x86_init to simplify Moorestown support
cover x86: Convert PCI init to x86_init to simplify Moorestown support
While reviewing the Moorestown patches I noticed weird modifications to the PCI code. The main point seems to be to use pcibios_irq_init but override pci_enable_irq. This is currently not possible by overriding pci_enable_irq before that function is called as pcibios_irq_init returns when pci_enable_irq is set. Jacop proposed a function pointer in x86_init to transport that information into pcibios_irq_init but its just a another hack. I looked at the init code in pci_subsys_init which calls various platform specific setup functions which may or may not override pci_enable_irq. The most confusing thing in that series of calls is the global variable pcibios_scanned which is used to signal the functions in that call chain that the should return. The visws pci quirk does not touch pcibios_scanned so that pci_legacy_init is called to scan the bus. Pretty non obvious. :)
In order to allow a cleaner override of pci_enable_irq while still being able to call pcibios_irq_init I converted the code to use the new x86_init infrastructure.
Aside of this MRST needs another hook close to the existing #ifdef'ed OLPC pci arch init call according to the moorestown support patch in pci-2.6.git. I added a x86_init function for this as well.
The series applies on top of the x86/platform branch ingit://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git
It's a bit painful to puzzle the bits and pieces for MRST together. Is there some big patch which contains all of the evil hacks which are necessary to get this puppies up and running. I don't care if they are ugly but I'd really like to get the full picture of it.
Thanks,
tglx
RFC PATCH 1/4 x86: Move pci init function to x86_init
The PCI initialization in pci_subsys_init() is weird. pci_numaq_init, pci_acpi_init, pci_visws_init and pci_legacy_init are called and each implementation checks and eventually modifies the global variable pcibios_scanned.
x86_init functions allow us to do this more elegant. The pci.init function pointer is preset to pci_legacy_init. numaq, acpi and visws can modify the pointer in their early setup functions. The functions return 0 when they did the full initialization including bus scan. A non zero return value indicates that pci_legacy_init needs to be called either because the selected function failed or wants the generic bus scan in pci_legacy_init to happen (e.g. visws).
--- arch/x86/include/asm/numaq.h | 1 + arch/x86/include/asm/pci.h | 7 +++++++ arch/x86/include/asm/pci_x86.h | 14 +++++++++++--- arch/x86/include/asm/setup.h | 2 -- arch/x86/include/asm/visws/cobalt.h | 2 ++ arch/x86/include/asm/x86_init.h | 9 +++++++++ arch/x86/kernel/acpi/boot.c | 4 ++++ arch/x86/kernel/apic/numaq_32.c | 1 + arch/x86/kernel/visws_quirks.c | 6 +----- arch/x86/kernel/x86_init.c | 5 +++++ arch/x86/pci/acpi.c | 6 +----- arch/x86/pci/common.c | 6 ------ arch/x86/pci/legacy.c | 22 ++++++++-------------- arch/x86/pci/numaq_32.c | 6 ------ arch/x86/pci/visws.c | 6 ++---- 15 files changed, 52 insertions(+), 45 deletions(-)
arch/x86/include/asm/numaq.h +1 -0
@@ -30,6 +30,7 @@extern int found_numaq;extern int get_memcfg_numaq (void ); +extern int pci_numaq_init (void );extern void *xquad_portio;
arch/x86/include/asm/pci.h +7 -0
@@ -45,8 +45,15 @@ static inline int pci_proc_domain(struct#ifdef CONFIG_PCI extern unsigned int pcibios_assign_all_busses (void ); +extern int pci_legacy_init (void ); +# ifdef CONFIG_ACPI +# define x86_default_pci_init pci_acpi_init +# else +# define x86_default_pci_init pci_legacy_init +# endif #else #define pcibios_assign_all_busses () 0 +#define x86_default_pci_init NULL#endif #define pcibios_scan_all_fns (a, b) 0
arch/x86/include/asm/pci_x86.h +11 -3
@@ -82,7 +82,6 @@ struct irq_routing_table {extern unsigned int pcibios_irq_mask; -extern int pcibios_scanned;extern spinlock_t pci_config_lock;extern int (*pcibios_enable_irq)(struct pci_dev *dev);
@@ -112,9 +111,8 @@ extern void __init dmi_check_skip_isa_al/* some common used subsys_initcalls */ extern int __init pci_acpi_init (void );extern int __init pcibios_irq_init (void ); -extern int __init pci_visws_init (void ); -extern int __init pci_numaq_init (void );extern int __init pcibios_init (void ); +extern int pci_legacy_init (void );/* pci-mmconfig.c */
@@ -166,3 +164,13 @@ static inline void mmio_config_writel(vo { asmvolatile ("movl %%eax,(%1)" : :"a" (val),"r" (pos) :"memory" ); } + +#ifdef CONFIG_PCI +# ifdef CONFIG_ACPI +# define x86_default_pci_init pci_acpi_init +# else +# define x86_default_pci_init pci_legacy_init +# endif +#else +# define x86_default_pci_init NULL +#endif
arch/x86/include/asm/setup.h +0 -2
@@ -37,10 +37,8 @@ void setup_bios_corruption_check(void);#ifdef CONFIG_X86_VISWS extern void visws_early_detect (void ); -extern int is_visws_box (void );#else static inline void visws_early_detect (void ) { } -static inline int is_visws_box (void ) {return 0 ; }#endif extern unsigned long saved_video_mode;
arch/x86/include/asm/visws/cobalt.h +2 -0
@@ -122,4 +122,6 @@ extern char visws_board_type;extern char visws_board_rev; +extern int pci_visws_init (void ); +#endif /* _ASM_X86_VISWS_COBALT_H */
arch/x86/include/asm/x86_init.h +9 -0
@@ -92,6 +92,14 @@ struct x86_init_timers { };/** +* struct x86_init_pci - platform specific pci init functions +* @init: platform specific pci init +*/ +struct x86_init_pci { +int (*init)(void ); +}; + +/** * struct x86_init_ops - functions for platform specific setup * */
@@ -102,6 +110,7 @@ struct x86_init_ops {struct x86_init_oem oem;struct x86_init_paging paging;struct x86_init_timers timers; +struct x86_init_pci pci; };/**
arch/x86/kernel/acpi/boot.c +4 -0
@@ -35,6 +35,7 @@#include <linux/ioport.h> #include <linux/pci.h> +#include <asm/pci_x86.h> #include <asm/pgtable.h> #include <asm/io_apic.h> #include <asm/apic.h>
@@ -1719,6 +1720,9 @@ int __init acpi_boot_init(void)acpi_table_parse (ACPI_SIG_HPET , acpi_parse_hpet); +if (!acpi_noirq) + x86_init.pci.init = pci_acpi_init; +return 0 ; }
arch/x86/kernel/apic/numaq_32.c +1 -0
@@ -282,6 +282,7 @@ static __init void early_check_numaq(voi x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus; x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info; x86_init.timers.tsc_pre_init = numaq_tsc_init; + x86_init.pci.init = pci_numaq_init; } }
arch/x86/kernel/visws_quirks.c +1 -5
@@ -49,11 +49,6 @@ extern int no_broadcast;char visws_board_type =-1 ;char visws_board_rev =-1 ; -int is_visws_box (void ) -{ -return visws_board_type >=0 ; -} -static void __init visws_time_init (void ) {printk (KERN_INFO "Starting Cobalt Timer system clock\n" );
@@ -242,6 +237,7 @@ void __init visws_early_detect(void) x86_init.irqs.pre_vector_init = visws_pre_intr_init; x86_init.irqs.trap_init = visws_trap_init; x86_init.timers.timer_init = visws_time_init; + x86_init.pci.init = pci_visws_init;/* * Install reboot quirks:
arch/x86/kernel/x86_init.c +5 -0
@@ -7,6 +7,7 @@#include <asm/bios_ebda.h> #include <asm/paravirt.h> +#include <asm/pci_x86.h> #include <asm/mpspec.h> #include <asm/setup.h> #include <asm/apic.h>
@@ -63,6 +64,10 @@ struct __initdata x86_init_ops x86_init .tsc_pre_init = x86_init_noop, .timer_init = hpet_time_init, }, + + .pci = { + .init = x86_default_pci_init, + }, };__cpuinitdata struct x86_cpuinit_ops x86_cpuinit = {
arch/x86/pci/acpi.c +1 -5
@@ -236,15 +236,11 @@ int __init pci_acpi_init(void) {struct pci_dev *dev =NULL ; -if (pcibios_scanned) -return 0 ; -if (acpi_noirq) -return 0 ; +return -ENODEV ;printk (KERN_INFO "PCI: Using ACPI for IRQ routing\n" );acpi_irq_penalty_init (); - pcibios_scanned++; pcibios_enable_irq = acpi_pci_irq_enable; pcibios_disable_irq = acpi_pci_irq_disable;
arch/x86/pci/common.c +0 -6
@@ -72,12 +72,6 @@ struct pci_ops pci_root_ops = { };/* -* legacy, numa, and acpi all want to call pcibios_scan_root -* from their initcalls. This flag prevents that. -*/ -int pcibios_scanned; - -/* * This interrupt-safe spinlock protects all accesses to PCI * configuration space. */
arch/x86/pci/legacy.c +8 -14
@@ -35,16 +35,13 @@ static void __devinit pcibios_fixup_peer } } -static int __init pci_legacy_init (void ) +int __init pci_legacy_init (void ) {if (!raw_pci_ops) {printk ("PCI: System does not support PCI\n" );return 0 ; } -if (pcibios_scanned++) -return 0 ; -printk ("PCI: Probing PCI hardware\n" ); pci_root_bus =pcibios_scan_root (0 );if (pci_root_bus)
@@ -55,16 +52,13 @@ static int __init pci_legacy_init(void)int __init pci_subsys_init (void ) { -#ifdef CONFIG_X86_NUMAQ -pci_numaq_init (); -#endif -#ifdef CONFIG_ACPI -pci_acpi_init (); -#endif -#ifdef CONFIG_X86_VISWS -pci_visws_init (); -#endif -pci_legacy_init (); +/* +* The init function returns an non zero value when +* pci_legacy_init should be invoked. +*/ +if (x86_init.pci.init ()) +pci_legacy_init (); +pcibios_fixup_peer_bridges ();pcibios_irq_init ();pcibios_init ();
arch/x86/pci/numaq_32.c +0 -6
@@ -152,14 +152,8 @@ int __init pci_numaq_init(void) {int quad; -if (!found_numaq) -return 0 ; - raw_pci_ops = &pci_direct_conf1_mq; -if (pcibios_scanned++) -return 0 ; - pci_root_bus =pcibios_scan_root (0 );if (pci_root_bus)pci_bus_add_devices (pci_root_bus);
arch/x86/pci/visws.c +2 -4
@@ -69,9 +69,6 @@ void __init pcibios_update_irq(struct pcint __init pci_visws_init (void ) { -if (!is_visws_box ()) -return -1 ; - pcibios_enable_irq = &pci_visws_enable_irq; pcibios_disable_irq = &pci_visws_disable_irq;
@@ -90,5 +87,6 @@ int __init pci_visws_init(void)pci_scan_bus_with_sysdata (pci_bus1);pci_fixup_irqs (pci_common_swizzle, visws_map_irq);pcibios_resource_survey (); -return 0 ; +/* Request bus scan */ +return 1 ; }
RFC PATCH 2/4 x86: Add pci_init_irq to x86_init
In reply to Thomas GleixnerMoorestown wants to reuse pcibios_init_irq but needs to provide its own implementation of pci_enable_irq. After we distangled the init we can move the init_irq call to x86_init and remove the pci_enable_irq != NULL check in pcibios_init_irq. pci_enable_irq is compile time initialized to pirq_enable_irq and the special cases which override it (visws and acpi) set the x86_init function pointer to noop. That allows MSRT to override pci_enable_irq and otherwise run pcibios_init_irq unmodified.
--- arch/x86/include/asm/pci_x86.h | 4 +++- arch/x86/include/asm/x86_init.h | 2 ++ arch/x86/kernel/visws_quirks.c | 1 + arch/x86/kernel/x86_init.c | 1 + arch/x86/pci/acpi.c | 1 + arch/x86/pci/irq.c | 12 ++++-------- arch/x86/pci/legacy.c | 2 +- 7 files changed, 13 insertions(+), 10 deletions(-)
arch/x86/include/asm/pci_x86.h +3 -1
@@ -110,7 +110,7 @@ extern void __init dmi_check_skip_isa_al/* some common used subsys_initcalls */ extern int __init pci_acpi_init (void ); -extern int __init pcibios_irq_init (void ); +extern void __init pcibios_irq_init (void );extern int __init pcibios_init (void );extern int pci_legacy_init (void );
@@ -171,6 +171,8 @@ static inline void mmio_config_writel(vo# else # define x86_default_pci_init pci_legacy_init# endif +# define x86_default_pci_init_irq pcibios_irq_init#else # define x86_default_pci_init NULL +# define x86_default_pci_init_irq NULL#endif
arch/x86/include/asm/x86_init.h +2 -0
@@ -94,9 +94,11 @@ struct x86_init_timers {/** * struct x86_init_pci - platform specific pci init functions * @init: platform specific pci init +* @init_irq: platform specific pci irq init */ struct x86_init_pci {int (*init)(void ); +void (*init_irq)(void ); };/**
arch/x86/kernel/visws_quirks.c +1 -0
@@ -238,6 +238,7 @@ void __init visws_early_detect(void) x86_init.irqs.trap_init = visws_trap_init; x86_init.timers.timer_init = visws_time_init; x86_init.pci.init = pci_visws_init; + x86_init.pci.init_irq = x86_init_noop;/* * Install reboot quirks:
arch/x86/kernel/x86_init.c +1 -0
@@ -67,6 +67,7 @@ struct __initdata x86_init_ops x86_init .pci = { .init = x86_default_pci_init, + .init_irq = x86_default_pci_init_irq, }, };
arch/x86/pci/acpi.c +1 -0
@@ -243,6 +243,7 @@ int __init pci_acpi_init(void)acpi_irq_penalty_init (); pcibios_enable_irq = acpi_pci_irq_enable; pcibios_disable_irq = acpi_pci_irq_disable; + x86_init.pci.init_irq = x86_init_noop;if (pci_routeirq) {/*
arch/x86/pci/irq.c +4 -8
@@ -53,7 +53,7 @@ struct irq_router_handler {int (*probe)(struct irq_router *r,struct pci_dev *router,u16 device); }; -int (*pcibios_enable_irq)(struct pci_dev *dev) =NULL ; +int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;void (*pcibios_disable_irq)(struct pci_dev *dev) =NULL ;/*
@@ -1110,12 +1110,12 @@ static struct dmi_system_id __initdata p { } }; -int __init pcibios_irq_init (void ) +void __init pcibios_irq_init (void ) {DBG (KERN_DEBUG "PCI: IRQ init\n" ); -if (pcibios_enable_irq || raw_pci_ops ==NULL ) -return 0 ; +if (raw_pci_ops ==NULL ) +return ;dmi_check_system (pciirq_dmi_table);
@@ -1142,8 +1142,6 @@ int __init pcibios_irq_init(void) pirq_table =NULL ; } - pcibios_enable_irq = pirq_enable_irq; -pcibios_fixup_irqs ();if (io_apic_assign_pci_irqs && pci_routeirq) {
@@ -1157,8 +1155,6 @@ int __init pcibios_irq_init(void)for_each_pci_dev (dev)pirq_enable_irq (dev); } - -return 0 ; }static void pirq_penalize_isa_irq (int irq,int active)
arch/x86/pci/legacy.c +1 -1
@@ -60,7 +60,7 @@ int __init pci_subsys_init(void)pci_legacy_init ();pcibios_fixup_peer_bridges (); -pcibios_irq_init (); + x86_init.pci.init_irq ();pcibios_init ();return 0 ;
RFC PATCH 3/4 x86: Add pcibios_fixup_irqs to x86_init
In reply to Thomas GleixnerPlatforms like Moorestown want to override the pcibios_fixup_irqs default function. Add it to x86_init.pci
--- arch/x86/include/asm/pci_x86.h | 3 +++ arch/x86/include/asm/x86_init.h | 2 ++ arch/x86/kernel/x86_init.c | 1 + arch/x86/pci/irq.c | 4 ++-- 4 files changed, 8 insertions(+), 2 deletions(-)
arch/x86/include/asm/pci_x86.h +3 -0
@@ -113,6 +113,7 @@ extern int __init pci_acpi_init(void);extern void __init pcibios_irq_init (void );extern int __init pcibios_init (void );extern int pci_legacy_init (void ); +extern void pcibios_fixup_irqs (void );/* pci-mmconfig.c */
@@ -172,7 +173,9 @@ static inline void mmio_config_writel(vo# define x86_default_pci_init pci_legacy_init# endif # define x86_default_pci_init_irq pcibios_irq_init +# define x86_default_pci_fixup_irqs pcibios_fixup_irqs#else # define x86_default_pci_init NULL# define x86_default_pci_init_irq NULL +# define x86_default_pci_fixup_irqs NULL#endif
arch/x86/include/asm/x86_init.h +2 -0
@@ -95,10 +95,12 @@ struct x86_init_timers {* struct x86_init_pci - platform specific pci init functions * @init: platform specific pci init * @init_irq: platform specific pci irq init +* @fixup_irqs: platform specific pci irq fixup */ struct x86_init_pci {int (*init)(void );void (*init_irq)(void ); +void (*fixup_irqs)(void ); };/**
arch/x86/kernel/x86_init.c +1 -0
@@ -68,6 +68,7 @@ struct __initdata x86_init_ops x86_init .pci = { .init = x86_default_pci_init, .init_irq = x86_default_pci_init_irq, + .fixup_irqs = x86_default_pci_fixup_irqs, }, };
arch/x86/pci/irq.c +2 -2
@@ -1016,7 +1016,7 @@ static int pcibios_lookup_irq(struct pcireturn 1 ; } -static void __init pcibios_fixup_irqs (void ) +void __init pcibios_fixup_irqs (void ) {struct pci_dev *dev =NULL ;u8 pin;
@@ -1142,7 +1142,7 @@ void __init pcibios_irq_init(void) pirq_table =NULL ; } -pcibios_fixup_irqs (); + x86_init.pci.fixup_irqs ();if (io_apic_assign_pci_irqs && pci_routeirq) {struct pci_dev *dev =NULL ;
RFC PATCH 4/4 x86: Add pci subarch init to x86_init
In reply to Thomas GleixnerReplace the #ifdef'ed olpc specific init function by a conditional x86_init function. This hook is also helpful for the upcoming Moorestown support.
--- arch/x86/include/asm/olpc.h | 20 ++------------------ arch/x86/include/asm/pci_x86.h | 1 - arch/x86/include/asm/x86_init.h | 4 +++- arch/x86/kernel/olpc.c | 8 +++++--- arch/x86/pci/init.c | 7 +++---- arch/x86/pci/olpc.c | 3 --- 6 files changed, 13 insertions(+), 30 deletions(-)
arch/x86/include/asm/olpc.h +2 -18
@@ -13,7 +13,6 @@ struct olpc_platform_t {#define OLPC_F_PRESENT 0x01#define OLPC_F_DCON 0x02 -#define OLPC_F_VSA 0x04#ifdef CONFIG_OLPC
@@ -51,18 +50,6 @@ static inline int olpc_has_dcon(void) }/* -* The VSA is software from AMD that typical Geode bioses will include. -* It is used to emulate the PCI bus, VGA, etc. OLPC's Open Firmware does -* not include the VSA; instead, PCI is emulated by the kernel. -* -* The VSA is described further in arch/x86/pci/olpc.c. -*/ -static inline int olpc_has_vsa (void ) -{ -return (olpc_platform_info.flags &OLPC_F_VSA ) ?1 :0 ; -} - -/* * The "Mass Production" version of OLPC's XO is identified as being model * C2. During the prototype phase, the following models (in chronological * order) were created: A1, B1, B2, B3, B4, C1. The A1 through B2 models
@@ -87,13 +74,10 @@ static inline int olpc_has_dcon(void)return 0 ; } -static inline int olpc_has_vsa (void ) -{ -return 0 ; -} -#endif +extern int pci_olpc_init (void ); +/* EC related functions */ extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
arch/x86/include/asm/pci_x86.h +0 -1
@@ -104,7 +104,6 @@ extern bool port_cf9_safe;extern int pci_direct_probe (void );extern void pci_direct_init (int type);extern void pci_pcbios_init (void ); -extern int pci_olpc_init (void );extern void __init dmi_check_pciprobe (void );extern void __init dmi_check_skip_isa_align (void );
arch/x86/include/asm/x86_init.h +3 -1
@@ -93,11 +93,13 @@ struct x86_init_timers {/** * struct x86_init_pci - platform specific pci init functions -* @init: platform specific pci init +* @arch_init: platform specific pci arch init call +* @init: platform specific pci subsystem init * @init_irq: platform specific pci irq init * @fixup_irqs: platform specific pci irq fixup */ struct x86_init_pci { +int (*arch_init)(void );int (*init)(void );void (*init_irq)(void );void (*fixup_irqs)(void );
arch/x86/kernel/olpc.c +5 -3
@@ -17,6 +17,8 @@#include <linux/spinlock.h> #include <linux/io.h> #include <linux/string.h> + +#include <asm/setup.h> #include <asm/geode.h> #include <asm/olpc.h>
@@ -243,9 +245,9 @@ static int __init olpc_init(void)olpc_ec_cmd (EC_FIRMWARE_REV ,NULL ,0 , (unsigned char *) &olpc_platform_info.ecver,1 ); -/* check to see if the VSA exists */ -if (geode_has_vsa2 ()) - olpc_platform_info.flags |=OLPC_F_VSA ; +/* If the VSA exists let it emulate PCI, if not emulate in kernel */ +if (!geode_has_vsa2 ()) + x86_init.pci.arch_init = pci_olpc_init; printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
arch/x86/pci/init.c +3 -4
@@ -15,10 +15,9 @@ static __init int pci_arch_init(void)if (!(pci_probe &PCI_PROBE_NOEARLY ))pci_mmcfg_early_init (); -#ifdef CONFIG_PCI_OLPC -if (!pci_olpc_init ()) -return 0 ;/* skip additional checks if it's an XO */ -#endif +if (x86_init.pci.arch_init && !x86_init.pci.arch_init ()) +return 0 ; +#ifdef CONFIG_PCI_BIOS pci_pcbios_init ();#endif
arch/x86/pci/olpc.c +0 -3
@@ -304,9 +304,6 @@ static struct pci_raw_ops pci_olpc_confint __init pci_olpc_init (void ) { -if (!machine_is_olpc () ||olpc_has_vsa ()) -return -ENODEV ; -printk (KERN_INFO "PCI: Using configuration type OLPC\n" ); raw_pci_ops = &pci_olpc_conf; is_lx =is_geode_lx ();
Re: [RFC patch 4/4] x86: Add pci subarch init to x86_init
Quoted 5 lines · On Sun, 30 Aug 2009 13:05:42 -0000 Thomas Gleixner <[email protected]> wrote:
Replace the #ifdef'ed olpc specific init function by a conditional
x86_initfunction. This hook is also helpful for the upcoming Moorestown support.Signed-off-by Thomas Gleixner <[email protected]>
Quoted 8 lines
--- arch/x86/include/asm/olpc.h | 20 ++------------------ arch/x86/include/asm/pci_x86.h | 1 - arch/x86/include/asm/x86_init.h | 4 +++- arch/x86/kernel/olpc.c | 8 +++++--- arch/x86/pci/init.c | 7 +++---- arch/x86/pci/olpc.c | 3 --- 6 files changed, 13 insertions(+), 30 deletions(-)
This is definitely nicer than what we have today... There's one other PCI patch for MRST in my pci tree:
http://git.kernel.org/?p=linux/kernel/git/jbarnes/pci-2.6.git;a=shortlog;h=mrst-support
it might also need updating in light of these changes.
Signature · 1 line
Jesse Barnes, Intel Open Source Technology Center