2.5.18 early printk, PCI segment, multi-IOMMU support
Subsystems (2)
PATCH 1/1 2.5.18 early printk, PCI segment, multi-IOMMU support
The attached patches are for 2.5.18-ia64-020530. They add support for early printk on a UART, multiple PCI segments, PCI root bridge translation offsets, and multiple HP ZX1 IOMMUs.
These have the same content as the ones I just posted for 2.4.18, except that 2.5.18 has slightly older ACPI, has a different ZX1 "fake device" strategy (doesn't use sysdata) and doesn't have a working ZX1 IOMMU yet.
The early printk diff includes a diff to hcdp_serial.c, which was not in the 020530 patch. If you have since pulled hcdp_serial.c into 2.5, that hunk will be useful, otherwise you can just ignore it. (Without HCDP, you have to specify the UART address with CONFIG_IA64_EARLY_PRINTK_UART_BASE.)
Tested on HP ZX1 and i2000.
10_early_printk.diff
Early printk for MMIO UARTs. UART address from HCDP or specified in config.
30_sci.diff
Add acpi_irq_to_vector() to handle both legacy ISA and new GSI interrupt numbers. Add support for SCI on GSI interrupt.
40_pcibios_segment.diff
Add struct pci_controller for IA64 sysdata. Stash the PCI segment there and add support in config accessors.
50_iosapic_segment.diff
Add segment support for PCI interrupts.
60_pci_tra.diff
Add support for PCI root bridges with non-zero translation offsets.
70_enable_device.diff
Add a platform vector for pci_enable_device(). ZX1 needs this to associate a device with the correct IOMMU.
Signature · 3 lines
Bjorn Helgaas - bjorn_helgaas at hp.com Linux Systems Operation R&D Hewlett-Packard Company
arch/ia64/Config.help +18 -4
@@ -502,10 +502,24 @@ problems, but slow! If you're unsure, select N. CONFIG_IA64_EARLY_PRINTK - Selecting this option uses the VGA screen for printk() output before - the consoles are initialised. It is useful for debugging problems - early in the boot process, but only if you have a VGA screen - attached. If you're unsure, select N. + Selecting this option uses a UART or VGA screen (or both) for + printk() output before the consoles are initialised. It is useful + for debugging problems early in the boot process, but only if you + have a serial terminal or a VGA screen attached. If you're unsure, + select N. + +CONFIG_IA64_EARLY_PRINTK_UART + Select this option to use a serial port for early printk() output. + You must either select CONFIG_SERIAL_HCDP (to locate the UART + using the EFI HCDP table) or set the UART address explicitly + with CONFIG_IA64_EARLY_PRINTK_UART_BASE. + +CONFIG_IA64_EARLY_PRINTK_UART_BASE + The physical MMIO address of the UART to use for early printk(). + This overrides any UART located using the EFI HCDP table. + +CONFIG_IA64_EARLY_PRINTK_VGA + Select this option to use VGA for early printk() output. CONFIG_IA64_PRINT_HAZARDS Selecting this option prints more information for Illegal Dependency
arch/ia64/config.in +8 -1
@@ -255,7 +255,14 @@ bool ' Disable VHPT' CONFIG_DISABLE_VHPT bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ - bool ' Early printk support (requires VGA!)' CONFIG_IA64_EARLY_PRINTK + bool ' Early printk support' CONFIG_IA64_EARLY_PRINTK + if [ "$CONFIG_IA64_EARLY_PRINTK" != "n" ]; then + bool ' Early printk on MMIO serial port' CONFIG_IA64_EARLY_PRINTK_UART + if [ "$CONFIG_IA64_EARLY_PRINTK_UART" != "n" ]; then + hex ' UART MMIO base address' CONFIG_IA64_EARLY_PRINTK_UART_BASE 0 + fi + bool ' Early printk on VGA' CONFIG_IA64_EARLY_PRINTK_VGA + fi bool ' Debug memory allocations' CONFIG_DEBUG_SLAB bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK bool ' Turn on compare-and-exchange bug checking (slow!)' CONFIG_IA64_DEBUG_CMPXCHG
kernel/printk.c +53 -2
73 lines not on this page · raw message
drivers/char/hcdp_serial.c +38 -0
@@ -219,3 +219,41 @@printk ("Leaving setup_serial_hcdp()\n" );#endif } + +#ifdef CONFIG_IA64_EARLY_PRINTK_UART +unsigned long hcdp_early_uart (void ) +{ +efi_system_table_t *systab; +efi_config_table_t *config_tables; +hcdp_t *hcdp =0 ; +hcdp_dev_t *dev; +int i; + + systab = (efi_system_table_t *) ia64_boot_param->efi_systab; +if (!systab) +return 0 ; + systab =__va (systab); + + config_tables = (efi_config_table_t *) systab->tables; +if (!config_tables) +return 0 ; + config_tables =__va (config_tables); + +for (i =0 ; i < systab->nr_tables; i++) { +if (efi_guidcmp (config_tables[i].guid,HCDP_TABLE_GUID ) ==0 ) { + hcdp = (hcdp_t *) config_tables[i].table; +break ; + } + } +if (!hcdp) +return 0 ; + hcdp =__va (hcdp); + +for (i =0 , dev = hcdp->hcdp_dev; i < hcdp->num_entries; i++, dev++) { +if (dev->type ==HCDP_DEV_CONSOLE ) +return (u64 ) dev->base_addr.addrhi <<32 + | dev->base_addr.addrlo; + } +return 0 ; +} +#endif
arch/ia64/kernel/acpi.c +53 -2
92 lines not on this page · raw message
arch/ia64/kernel/iosapic.c +2 -2
@@ -125,8 +125,8 @@* Translate IOSAPIC irq number to the corresponding IA-64 interrupt vector. If no * entry exists, return -1. */ -static int -iosapic_irq_to_vector (int irq) +int +iosapic_irq_to_vector (unsigned int irq) {int vector;
drivers/acpi/acpi_osl.c +12 -9
@@ -33,6 +33,7 @@#include <linux/interrupt.h> #include <linux/kmod.h> #include <linux/delay.h> +#include <linux/acpi.h> #include <asm/io.h> #include "acpi.h"
@@ -40,11 +41,6 @@#include <asm/efi.h> #endif -#ifdef _IA64 -#include <asm/hw_irq.h> -#include <asm/delay.h> -#endif -#define _COMPONENT ACPI_OS_SERVICESACPI_MODULE_NAME ("osl" )
@@ -225,8 +221,15 @@ acpi_os_install_interrupt_handler(u32 irq, OSD_HANDLER handler, void *context) { #ifdef _IA64 - irq =isa_irq_to_vector (irq); -#endif /*_IA64*/ + int vector; + + vector =acpi_irq_to_vector (irq); +if (vector <0 ) { + printk(KERN_ERR PREFIX "SCI (IRQ%d) not registered\n", irq); +return AE_OK ; + } + irq = vector; +#endif acpi_irq_irq = irq; acpi_irq_handler = handler; acpi_irq_context = context;
@@ -243,8 +246,8 @@ {if (acpi_irq_handler) {#ifdef _IA64 - irq =isa_irq_to_vector (irq); -#endif /*_IA64*/ + irq =acpi_irq_to_vector (irq); +#endif free_irq (irq, acpi_irq); acpi_irq_handler =NULL ; }
include/asm-ia64/iosapic.h +1 -0
@@ -53,6 +53,7 @@extern void __init iosapic_init (unsigned long address,unsigned int base_irq,int pcat_compat); +extern int iosapic_irq_to_vector (unsigned int irq);extern int iosapic_register_irq (u32 global_vector,unsigned long polarity,unsigned long edge_triggered,u32 base_irq,char *iosapic_address);
include/linux/acpi.h +1 -0
@@ -389,6 +389,7 @@#ifdef CONFIG_ACPI_INTERPRETER int acpi_init (void ); +int acpi_irq_to_vector (u32 irq);#endif /*CONFIG_ACPI_INTERPRETER*/
arch/ia64/kernel/pci.c +72 -28
183 lines not on this page · raw message
drivers/acpi/acpi_pci_root.c +1 -1
@@ -653,7 +653,7 @@* PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->data.bus =pcibios_scan_root (root->data.id.segment, root->data.id.bus); + root->data.bus =pcibios_scan_root (root->handle, root->data.id.segment, root->data.id.bus);if (!root->data.bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n",
include/asm-ia64/pci.h +9 -1
@@ -21,7 +21,7 @@#define PCIBIOS_MIN_MEM 0x10000000void pcibios_config_init (void ); -struct pci_bus *pcibios_scan_root (int seg,int bus); +struct pci_bus *pcibios_scan_root (void *acpi_handle,int segment,int bus);extern int (*pci_config_read)(int seg,int bus,int dev,int fn,int reg,int len,u32 *value);extern int (*pci_config_write)(int seg,int bus,int dev,int fn,int reg,int len,u32 value);
@@ -95,5 +95,13 @@#define HAVE_PCI_MMAP extern int pci_mmap_page_range (struct pci_dev *dev,struct vm_area_struct *vma,enum pci_mmap_state mmap_state,int write_combine); + +struct pci_controller { +void *acpi_handle; +int segment; +}; + +#define PCI_CONTROLLER (dev) ((struct pci_controller *) dev->sysdata) +#define PCI_SEGMENT (dev) (PCI_CONTROLLER(dev)->segment)#endif /* _ASM_IA64_PCI_H */
arch/ia64/kernel/acpi.c +1 -0
@@ -695,6 +695,7 @@list_for_each (node, &acpi_prts.entries) { entry = (struct acpi_prt_entry *)node; + vector[i].segment = entry->id.seg; vector[i].bus = entry->id.bus; vector[i].pci_id = ((u32 ) entry->id.dev <<16 ) |0xffff ; vector[i].pin = entry->id.pin;
arch/ia64/kernel/iosapic.c +9 -5
@@ -26,12 +26,13 @@* 02/04/18 J.I. Lee bug fix in iosapic_init_pci_irq * 02/04/30 J.I. Lee bug fix in find_iosapic to fix ACPI PCI IRQ to IOSAPIC mapping * error +* 02/07/11 B. Helgaas Support PCI segments */ /* * Here is what the interrupt logic between a PCI device and the CPU looks like: * * (1) A PCI device raises one of the four interrupt pins (INTA, INTB, INTC, INTD). The -* device is uniquely identified by its bus--, and slot-number (the function +* device is uniquely identified by its segment--, bus--, and slot-number (the function * number does not matter here because all functions share the same interrupt * lines). *
@@ -141,12 +142,13 @@* return -1. */ int -pci_pin_to_vector (int bus,int slot,int pci_pin) +pci_pin_to_vector (int segment,int bus,int slot,int pci_pin) {struct pci_vector_struct *r;for (r = pci_irq.route; r < pci_irq.route + pci_irq.num_routes; ++r) -if (r->bus == bus && (r->pci_id >>16 ) == slot && r->pin == pci_pin) +if (r->segment == segment && r->bus == bus && + (r->pci_id >>16 ) == slot && r->pin == pci_pin)return iosapic_irq_to_vector (r->irq);return -1 ; }
@@ -691,6 +693,7 @@ iosapic_pci_fixup (int phase) {struct pci_dev *dev; +int segment;unsigned char pin;int vector;struct hw_interrupt_type *irq_type;
@@ -708,7 +711,8 @@pci_read_config_byte (dev,PCI_INTERRUPT_PIN , &pin);if (pin) { pin--;/* interrupt pins are numbered starting from 1 */ - vector =pci_pin_to_vector (dev->bus->number,PCI_SLOT (dev->devfn), pin); + segment =PCI_SEGMENT (dev); + vector =pci_pin_to_vector (segment, dev->bus->number,PCI_SLOT (dev->devfn), pin);if (vector <0 && dev->bus->parent) {/* go back to the bridge */ struct pci_dev *bridge = dev->bus->self;
@@ -718,7 +722,7 @@do {/* do the bridge swizzle... */ pin = (pin +PCI_SLOT (dev->devfn)) %4 ; - vector =pci_pin_to_vector (bridge->bus->number, + vector =pci_pin_to_vector (segment, bridge->bus->number,PCI_SLOT (bridge->devfn), pin); }while (vector <0 && (bridge = bridge->bus->self));
include/asm-ia64/system.h +1 -0
@@ -29,6 +29,7 @@#include <linux/types.h> struct pci_vector_struct { +__u16 segment;/* PCI Segment number */ __u16 bus;/* PCI Bus number */ __u32 pci_id;/* ACPI split 16 bits device, 16 bits function (see section 6.1.1) */ __u8 pin;/* PCI PIN (0 = A, 1 = B, 2 = C, 3 = D) */
arch/ia64/kernel/acpi.c +67 -0
73 lines not on this page · raw message
arch/ia64/kernel/pci.c +31 -1
@@ -13,6 +13,7 @@#include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/spinlock.h> +#include <linux/acpi.h> #include <asm/machvec.h> #include <asm/page.h>
@@ -214,6 +215,7 @@ pcibios_scan_root(void *handle, int seg, int bus) {struct pci_controller *controller; +u64 base, size, offset;printk ("PCI: Probing PCI hardware on bus (%02x:%02x)\n" , seg, bus);
@@ -222,6 +224,10 @@return NULL ; controller->acpi_handle = handle; + +acpi_get_addr_space (handle,ACPI_MEMORY_RANGE , &base, &size, &offset); + controller->mem_offset = offset; +return scan_root_bus (bus, pci_root_ops, controller); }
@@ -267,6 +273,27 @@subsys_initcall (pcibios_init); +static void __init +pcibios_fixup_resource (struct resource *res,u64 offset) +{ + res->start += offset; + res->end += offset; +} + +void __init +pcibios_fixup_device_resources (struct pci_dev *dev,struct pci_bus *bus) +{ +int i; + +for (i =0 ; i <PCI_NUM_RESOURCES ; i++) { +if (!dev->resource[i].start) +continue ; +if (dev->resource[i].flags &IORESOURCE_MEM ) +pcibios_fixup_resource (&dev->resource[i], +PCI_CONTROLLER (dev)->mem_offset); + } +} +/* * Called after each bus is probed, but before its children * are examined.
@@ -274,7 +301,10 @@void __init pcibios_fixup_bus (struct pci_bus *b) { -return ; +struct list_head *ln; + +for (ln = b->devices.next; ln != &b->devices; ln = ln->next) +pcibios_fixup_device_resources (pci_dev_b (ln), b); }void __init
include/asm-ia64/pci.h +2 -0
@@ -99,6 +99,8 @@struct pci_controller {void *acpi_handle;int segment; + +u64 mem_offset; };#define PCI_CONTROLLER (dev) ((struct pci_controller *) dev->sysdata)
include/linux/acpi.h +1 -0
@@ -390,6 +390,7 @@int acpi_init (void );int acpi_irq_to_vector (u32 irq); +acpi_status acpi_get_addr_space (acpi_handle ,u8 type,u64 *base,u64 *length,u64 *tra);#endif /*CONFIG_ACPI_INTERPRETER*/
arch/ia64/kernel/pci.c +1 -2
@@ -342,8 +342,7 @@if (!dev)return -EINVAL ; -/* Not needed, since we enable all devices at startup. */ - +platform_pci_enable_device (dev);printk (KERN_INFO "PCI: Found IRQ %d for device %s\n" , dev->irq, dev->slot_name);return 0 ; }
include/asm-ia64/machvec.h +8 -1
@@ -24,6 +24,7 @@typedef void ia64_mv_cpu_init_t (void );typedef void ia64_mv_irq_init_t (void );typedef void ia64_mv_pci_fixup_t (int ); +typedef void ia64_mv_pci_enable_device_t (struct pci_dev *);typedef unsigned long ia64_mv_map_nr_t (unsigned long );typedef void ia64_mv_mca_init_t (void );typedef void ia64_mv_mca_handler_t (void );
@@ -92,7 +93,8 @@# define platform_cmci_handler ia64_mv.cmci_handler# define platform_log_print ia64_mv.log_print# define platform_pci_fixup ia64_mv.pci_fixup -# define platform_send_ipi ia64_mv.send_ipi +# define platform_pci_enable_device ia64_mv.pci_enable_device +# define platform_send_ipi ia64_mv.send_ipi# define platform_global_tlb_purge ia64_mv.global_tlb_purge# define platform_pci_dma_init ia64_mv.dma_init# define platform_pci_alloc_consistent ia64_mv.alloc_consistent
@@ -123,6 +125,7 @@ia64_mv_cpu_init_t *cpu_init;ia64_mv_irq_init_t *irq_init;ia64_mv_pci_fixup_t *pci_fixup; +ia64_mv_pci_enable_device_t *pci_enable_device;ia64_mv_map_nr_t *map_nr;ia64_mv_mca_init_t *mca_init;ia64_mv_mca_handler_t *mca_handler;
@@ -160,6 +163,7 @@ platform_cpu_init, \ platform_irq_init, \ platform_pci_fixup, \ + platform_pci_enable_device, \ platform_map_nr, \ platform_mca_init, \ platform_mca_handler, \
@@ -238,6 +242,9 @@#endif #ifndef platform_pci_fixup# define platform_pci_fixup ((ia64_mv_pci_fixup_t *) machvec_noop) +#endif +#ifndef platform_pci_enable_device +# define platform_pci_enable_device ((ia64_mv_pci_enable_device_t *) machvec_noop)#endif #ifndef platform_send_ipi# define platform_send_ipi ia64_send_ipi/* default to architected version */
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Bjorn Helgaas
Bjorn> Tested on HP ZX1 and i2000.
Bjorn> 10_early_printk.diff Early printk for MMIO UARTs. UART Bjorn> address from HCDP or specified in config.
Bjorn> 30_sci.diff Add acpi_irq_to_vector() to handle both legacy Bjorn> ISA and new GSI interrupt numbers. Add support for SCI on Bjorn> GSI interrupt.
Bjorn> 40_pcibios_segment.diff Add struct pci_controller for IA64 Bjorn> sysdata. Stash the PCI segment there and add support in Bjorn> config accessors.
Bjorn> 50_iosapic_segment.diff Add segment support for PCI Bjorn> interrupts.
The above look fine to me. I'm not really an ACPI expert so if anybody has an issue with these (particularly the latter three), speak up.
Bjorn> 60_pci_tra.diff Add support for PCI root bridges with Bjorn> non-zero translation offsets.
This one handles only memory offsets. Any particular reason for this? Perhaps there should be at least a check which will warn/panic if a non-zero I/O offset is found?
Bjorn> 70_enable_device.diff Add a platform vector for Bjorn> pci_enable_device(). ZX1 needs this to associate a device Bjorn> with the correct IOMMU.
Hmmh, are you expecting other platform-specific work will have to be done in pci_enable_device() in the future? If all we really need here is a platform-specific PCI-device -> IOMMU mapping, perhaps we should call it just that. OTOH, I can see that this is a natural callback point. Any comments by folks doing the hw support for other (hotplug-capable) machines?
--david
Quoted 6 lines
Bjorn> 60_pci_tra.diff Add support for PCI root bridges with Bjorn> non-zero translation offsets.
This one handles only memory offsets. Any particular reason for this? Perhaps there should be at least a check which will warn/panic if a non-zero I/O offset is found?
Yup, there's a reason, but it's kind of lame: I haven't figured out how to deal with I/O offsets yet :-) That gets into how I/O spaces other than the legacy 64Kb space are described in ACPI, and how the kernel accesses them. So handling I/O offsets will (I think) involve more extensive changes to I/O port addressing.
Signature · 3 lines
Bjorn Helgaas - bjorn_helgaas at hp.com Linux Systems Operation R&D Hewlett-Packard Company