diff options
147 files changed, 4995 insertions, 1692 deletions
diff --git a/Documentation/serial/driver b/Documentation/serial/driver index ac7eabbf662..87856d3cfb6 100644 --- a/Documentation/serial/driver +++ b/Documentation/serial/driver @@ -111,24 +111,17 @@ hardware. Interrupts: locally disabled. This call must not sleep - stop_tx(port,tty_stop) + stop_tx(port) Stop transmitting characters. This might be due to the CTS line becoming inactive or the tty layer indicating we want - to stop transmission. - - tty_stop: 1 if this call is due to the TTY layer issuing a - TTY stop to the driver (equiv to rs_stop). + to stop transmission due to an XOFF character. Locking: port->lock taken. Interrupts: locally disabled. This call must not sleep - start_tx(port,tty_start) - start transmitting characters. (incidentally, nonempty will - always be nonzero, and shouldn't be used - it will be dropped). - - tty_start: 1 if this call was due to the TTY layer issuing - a TTY start to the driver (equiv to rs_start) + start_tx(port) + start transmitting characters. Locking: port->lock taken. Interrupts: locally disabled. diff --git a/MAINTAINERS b/MAINTAINERS index 671e32905d2..5899ec1504f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2650,11 +2650,6 @@ S: Maintained UCLINUX (AND M68KNOMMU) P: Greg Ungerer M: gerg@uclinux.org -M: gerg@snapgear.com -P: David McCullough -M: davidm@snapgear.com -P: D. Jeff Dionne (created first uClinux port) -M: jeff@uclinux.org W: http://www.uclinux.org/ L: uclinux-dev@uclinux.org (subscribers-only) S: Maintained diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4bf0e8737e1..68dfdba71d7 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -365,8 +365,8 @@ config NO_IDLE_HZ Please note that dynamic tick may affect the accuracy of timekeeping on some platforms depending on the implementation. - Currently at least OMAP platform is known to have accurate - timekeeping with dynamic tick. + Currently at least OMAP, PXA2xx and SA11x0 platforms are known + to have accurate timekeeping with dynamic tick. config ARCH_DISCONTIGMEM_ENABLE bool diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 51dbf5489b6..d7499071755 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/list.h> #include <linux/smp.h> +#include <linux/cpumask.h> #include <asm/irq.h> #include <asm/io.h> diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index 2b6b4c786e6..db07ce42b3b 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S @@ -284,7 +284,7 @@ __syscall_start: .long sys_fstatfs64 .long sys_tgkill .long sys_utimes -/* 270 */ .long sys_fadvise64_64 +/* 270 */ .long sys_arm_fadvise64_64_wrapper .long sys_pciconfig_iobase .long sys_pciconfig_read .long sys_pciconfig_write diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 3f8d0e3aefa..6281d488ac9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -265,6 +265,10 @@ sys_futex_wrapper: str r5, [sp, #4] @ push sixth arg b sys_futex +sys_arm_fadvise64_64_wrapper: + str r5, [sp, #4] @ push r5 to stack + b sys_arm_fadvise64_64 + /* * Note: off_4k (r5) is always units of 4K. If we can't do the requested * offset, we return EINVAL. diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index f897ce2ccf0..42629ff84f5 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c @@ -311,3 +311,13 @@ long execve(const char *filename, char **argv, char **envp) return ret; } EXPORT_SYMBOL(execve); + +/* + * Since loff_t is a 64 bit type we avoid a lot of ABI hastle + * with a different argument ordering. + */ +asmlinkage long sys_arm_fadvise64_64(int fd, int advice, + loff_t offset, loff_t len) +{ + return sys_fadvise64_64(fd, offset, len, advice); +} diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c index 1b7fcd50c3e..8880482dcbf 100644 --- a/arch/arm/kernel/time.c +++ b/arch/arm/kernel/time.c @@ -433,10 +433,12 @@ void timer_dyn_reprogram(void) { struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick; - write_seqlock(&xtime_lock); - if (dyn_tick->state & DYN_TICK_ENABLED) - dyn_tick->reprogram(next_timer_interrupt() - jiffies); - write_sequnlock(&xtime_lock); + if (dyn_tick) { + write_seqlock(&xtime_lock); + if (dyn_tick->state & DYN_TICK_ENABLED) + dyn_tick->reprogram(next_timer_interrupt() - jiffies); + write_sequnlock(&xtime_lock); + } } static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf) diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 04490a9f8f6..0422e906cc9 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -38,90 +38,6 @@ #include <asm/mach/irq.h> #include <asm/mach/time.h> -enum ixp4xx_irq_type { - IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE -}; -static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); - -/************************************************************************* - * GPIO acces functions - *************************************************************************/ - -/* - * Configure GPIO line for input, interrupt, or output operation - * - * TODO: Enable/disable the irq_desc based on interrupt or output mode. - * TODO: Should these be named ixp4xx_gpio_? - */ -void gpio_line_config(u8 line, u32 style) -{ - static const int gpio2irq[] = { - 6, 7, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 - }; - u32 enable; - volatile u32 *int_reg; - u32 int_style; - enum ixp4xx_irq_type irq_type; - - enable = *IXP4XX_GPIO_GPOER; - - if (style & IXP4XX_GPIO_OUT) { - enable &= ~((1) << line); - } else if (style & IXP4XX_GPIO_IN) { - enable |= ((1) << line); - - switch (style & IXP4XX_GPIO_INTSTYLE_MASK) - { - case (IXP4XX_GPIO_ACTIVE_HIGH): - int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; - irq_type = IXP4XX_IRQ_LEVEL; - break; - case (IXP4XX_GPIO_ACTIVE_LOW): - int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; - irq_type = IXP4XX_IRQ_LEVEL; - break; - case (IXP4XX_GPIO_RISING_EDGE): - int_style = IXP4XX_GPIO_STYLE_RISING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case (IXP4XX_GPIO_FALLING_EDGE): - int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case (IXP4XX_GPIO_TRANSITIONAL): - int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL; - irq_type = IXP4XX_IRQ_EDGE; - break; - default: - int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; - irq_type = IXP4XX_IRQ_LEVEL; - break; - } - - if (style & IXP4XX_GPIO_INTSTYLE_MASK) - ixp4xx_config_irq(gpio2irq[line], irq_type); - - if (line >= 8) { /* pins 8-15 */ - line -= 8; - int_reg = IXP4XX_GPIO_GPIT2R; - } - else { /* pins 0-7 */ - int_reg = IXP4XX_GPIO_GPIT1R; - } - - /* Clear the style for the appropriate pin */ - *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR << - (line * IXP4XX_GPIO_STYLE_SIZE)); - - /* Set the new style */ - *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); - } - - *IXP4XX_GPIO_GPOER = enable; -} - -EXPORT_SYMBOL(gpio_line_config); - /************************************************************************* * IXP4xx chipset I/O mapping *************************************************************************/ @@ -165,6 +81,69 @@ void __init ixp4xx_map_io(void) * (be it PCI or something else) configures that GPIO line * as an IRQ. **************************************************************************/ +enum ixp4xx_irq_type { + IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE +}; + +static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type); + +/* + * IRQ -> GPIO mapping table + */ +static int irq2gpio[32] = { + -1, -1, -1, -1, -1, -1, 0, 1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, -1, -1, +}; + +static int ixp4xx_set_irq_type(unsigned int irq, unsigned int type) +{ + int line = irq2gpio[irq]; + u32 int_style; + enum ixp4xx_irq_type irq_type; + volatile u32 *int_reg; + + /* + * Only for GPIO IRQs + */ + if (line < 0) + return -EINVAL; + + if (type & IRQT_BOTHEDGE) { + int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_RISING) { + int_style = IXP4XX_GPIO_STYLE_RISING_EDGE; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_FALLING) { + int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE; + irq_type = IXP4XX_IRQ_EDGE; + } else if (type & IRQT_HIGH) { + int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; + irq_type = IXP4XX_IRQ_LEVEL; + } else if (type & IRQT_LOW) { + int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; + irq_type = IXP4XX_IRQ_LEVEL; + } + + ixp4xx_config_irq(irq, irq_type); + + if (line >= 8) { /* pins 8-15 */ + line -= 8; + int_reg = IXP4XX_GPIO_GPIT2R; + } else { /* pins 0-7 */ + int_reg = IXP4XX_GPIO_GPIT1R; + } + + /* Clear the style for the appropriate pin */ + *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR << + (line * IXP4XX_GPIO_STYLE_SIZE)); + + /* Set the new style */ + *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); +} + static void ixp4xx_irq_mask(unsigned int irq) { if (cpu_is_ixp46x() && irq >= 32) @@ -183,12 +162,6 @@ static void ixp4xx_irq_unmask(unsigned int irq) static void ixp4xx_irq_ack(unsigned int irq) { - static int irq2gpio[32] = { - -1, -1, -1, -1, -1, -1, 0, 1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, -1, - }; int line = (irq < 32) ? irq2gpio[irq] : -1; if (line >= 0) @@ -209,12 +182,14 @@ static struct irqchip ixp4xx_irq_level_chip = { .ack = ixp4xx_irq_mask, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_level_unmask, + .type = ixp4xx_set_irq_type }; static struct irqchip ixp4xx_irq_edge_chip = { .ack = ixp4xx_irq_ack, .mask = ixp4xx_irq_mask, .unmask = ixp4xx_irq_unmask, + .type = ixp4xx_set_irq_type }; static void ixp4xx_config_irq(unsigned irq, enum ixp4xx_irq_type type) diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index afafb42ae12..60de8a94cff 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -30,11 +30,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); void __init coyote_pci_preinit(void) { - gpio_line_config(COYOTE_PCI_SLOT0_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - - gpio_line_config(COYOTE_PCI_SLOT1_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_COYOTE_PCI_SLOT0, IRQT_LOW); + set_irq_type(IRQ_COYOTE_PCI_SLOT1, IRQT_LOW); gpio_line_isr_clear(COYOTE_PCI_SLOT0_PIN); gpio_line_isr_clear(COYOTE_PCI_SLOT1_PIN); diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 411ea999619..8b2f2532245 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -24,11 +24,6 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> -void __init coyote_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data coyote_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -107,7 +102,7 @@ MACHINE_START(ADI_COYOTE, "ADI Engineering Coyote") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = coyote_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -125,7 +120,7 @@ MACHINE_START(IXDPG425, "Intel IXDPG425") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = coyote_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index b18035824e3..a66484b63d3 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -35,26 +35,20 @@ extern void ixp4xx_pci_preinit(void); extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); - /* - * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h - * Slot 0 isn't actually populated with a card connector but - * we initialize it anyway in case a future version has the - * slot populated or someone with good soldering skills has - * some free time. - */ - - -static void gtwx5715_init_gpio(u8 pin, u32 style) -{ - gpio_line_config(pin, style | IXP4XX_GPIO_ACTIVE_LOW); - - if (style & IXP4XX_GPIO_IN) gpio_line_isr_clear(pin); -} +/* + * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h + * Slot 0 isn't actually populated with a card connector but + * we initialize it anyway in case a future version has the + * slot populated or someone with good soldering skills has + * some free time. + */ void __init gtwx5715_pci_preinit(void) { - gtwx5715_init_gpio(GTWX5715_PCI_SLOT0_INTA_GPIO, IXP4XX_GPIO_IN); - gtwx5715_init_gpio(GTWX5715_PCI_SLOT1_INTA_GPIO, IXP4XX_GPIO_IN); + set_irq_type(GTWX5715_PCI_SLOT0_INTA_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT0_INTB_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT1_INTA_IRQ, IRQT_LOW); + set_irq_type(GTWX5715_PCI_SLOT1_INTB_IRQ, IRQT_LOW); ixp4xx_pci_preinit(); } diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 333459d6aa4..3fd92c5cbaa 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -101,12 +101,6 @@ static struct platform_device gtwx5715_uart_device = { .resource = gtwx5715_uart_resources, }; - -void __init gtwx5715_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data gtwx5715_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -144,7 +138,7 @@ MACHINE_START(GTWX5715, "Gemtek GTWX5715 (Linksys WRV54G)") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_UART2_BASE_PHYS, .io_pg_offst = ((IXP4XX_UART2_BASE_VIRT) >> 18) & 0xfffc, - .map_io = gtwx5715_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index c2ab9ebb598..f9a1d3e7d69 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -27,14 +27,10 @@ void __init ixdp425_pci_preinit(void) { - gpio_line_config(IXDP425_PCI_INTA_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTB_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTC_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(IXDP425_PCI_INTD_PIN, - IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTA, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTB, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTC, IRQT_LOW); + set_irq_type(IRQ_IXDP425_PCI_INTD, IRQT_LOW); gpio_line_isr_clear(IXDP425_PCI_INTA_PIN); gpio_line_isr_clear(IXDP425_PCI_INTB_PIN); diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index fa0646c8693..6c14ff3c23a 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -24,11 +24,6 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> -void __init ixdp425_map_io(void) -{ - ixp4xx_map_io(); -} - static struct flash_platform_data ixdp425_flash_data = { .map_name = "cfi_probe", .width = 2, @@ -133,7 +128,7 @@ MACHINE_START(IXDP425, "Intel IXDP425 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -145,7 +140,7 @@ MACHINE_START(IXDP465, "Intel IXDP465 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -157,7 +152,7 @@ MACHINE_START(IXCDP1100, "Intel IXCDP1100 Development Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, @@ -176,7 +171,7 @@ MACHINE_START(AVILA, "Gateworks Avila Network Platform") .phys_ram = PHYS_OFFSET, .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, - .map_io = ixdp425_map_io, + .map_io = ixp4xx_map_io, .init_irq = ixp4xx_init_irq, .timer = &ixp4xx_timer, .boot_params = 0x0100, diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c index ce4563f0067..fe5e7660de1 100644 --- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c @@ -29,8 +29,8 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); void __init ixdpg425_pci_preinit(void) { - gpio_line_config(6, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); - gpio_line_config(7, IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW); + set_irq_type(IRQ_IXP4XX_GPIO6, IRQT_LOW); + set_irq_type(IRQ_IXP4XX_GPIO7, IRQT_LOW); gpio_line_isr_clear(6); gpio_line_isr_clear(7); diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 6e5202154f9..7dad3f1465e 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -70,6 +70,11 @@ static unsigned long pxa_gettimeoffset (void) return usec; } +#ifdef CONFIG_NO_IDLE_HZ +static unsigned long initial_match; +static int match_posponed; +#endif + static irqreturn_t pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -77,11 +82,19 @@ pxa_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); +#ifdef CONFIG_NO_IDLE_HZ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + } +#endif + /* Loop until we get ahead of the free running timer. * This ensures an exact clock tick count and time accuracy. - * IRQs are disabled inside the loop to ensure coherence between - * lost_ticks (updated in do_timer()) and the match reg value, so we - * can use do_gettimeofday() from interrupt handlers. + * Since IRQs are disabled at this point, coherence between + * lost_ticks(updated in do_timer()) and the match reg value is + * ensured, hence we can use do_gettimeofday() from interrupt + * handlers. * * HACK ALERT: it seems that the PXA timer regs aren't updated right * away in all cases when a write occurs. We therefore compare with @@ -126,6 +139,42 @@ static void __init pxa_timer_init(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_NO_IDLE_HZ +static int pxa_dyn_tick_enable_disable(void) +{ + /* nothing to do */ + return 0; +} + +static void pxa_dyn_tick_reprogram(unsigned long ticks) +{ + if (ticks > 1) { + initial_match = OSMR0; + OSMR0 = initial_match + ticks * LATCH; + match_posponed = 1; + } +} + +static irqreturn_t +pxa_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + if ( (signed long)(initial_match - OSCR) <= 8 ) + return pxa_timer_interrupt(irq, dev_id, regs); + } + return IRQ_NONE; +} + +static struct dyn_tick_timer pxa_dyn_tick = { + .enable = pxa_dyn_tick_enable_disable, + .disable = pxa_dyn_tick_enable_disable, + .reprogram = pxa_dyn_tick_reprogram, + .handler = pxa_dyn_tick_handler, +}; +#endif + #ifdef CONFIG_PM static unsigned long osmr[4], oier; @@ -161,4 +210,7 @@ struct sys_timer pxa_timer = { .suspend = pxa_timer_suspend, .resume = pxa_timer_resume, .offset = pxa_gettimeoffset, +#ifdef CONFIG_NO_IDLE_HZ + .dyn_tick = &pxa_dyn_tick, +#endif }; diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 9a66050e887..f5960826875 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c @@ -388,6 +388,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, unsigned long hclk, unsigned long pclk) { + unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); struct clk *clkp = init_clocks; int ptr; int ret; @@ -446,5 +447,13 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, } } + /* show the clock-slow value */ + + printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n", + print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))), + (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast", + (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on", + (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on"); + return 0; } diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c index b018a1f680c..c67e0979aec 100644 --- a/arch/arm/mach-s3c2410/s3c2440-clock.c +++ b/arch/arm/mach-s3c2410/s3c2440-clock.c @@ -68,6 +68,7 @@ static struct clk s3c2440_clk_ac97 = { static int s3c2440_clk_add(struct sys_device *sysdev) { unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); + unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); struct clk *clk_h; struct clk *clk_p; struct clk *clk_xtal; @@ -80,8 +81,9 @@ static int s3c2440_clk_add(struct sys_device *sysdev) s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate); - printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n", - print_mhz(s3c2440_clk_upll.rate)); + printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n", + print_mhz(s3c2440_clk_upll.rate), + (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); clk_p = clk_get(NULL, "pclk"); clk_h = clk_get(NULL, "hclk"); diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 0eeb3616ffe..47e0420623f 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -70,15 +70,11 @@ static unsigned long sa1100_gettimeoffset (void) return usec; } -/* - * We will be entered with IRQs enabled. - * - * Loop until we get ahead of the free running timer. - * This ensures an exact clock tick count and time accuracy. - * IRQs are disabled inside the loop to ensure coherence between - * lost_ticks (updated in do_timer()) and the match reg value, so we - * can use do_gettimeofday() from interrupt handlers. - */ +#ifdef CONFIG_NO_IDLE_HZ +static unsigned long initial_match; +static int match_posponed; +#endif + static irqreturn_t sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { @@ -86,6 +82,21 @@ sa1100_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) write_seqlock(&xtime_lock); +#ifdef CONFIG_NO_IDLE_HZ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + } +#endif + + /* + * Loop until we get ahead of the free running timer. + * This ensures an exact clock tick count and time accuracy. + * Since IRQs are disabled at this point, coherence between + * lost_ticks(updated in do_timer()) and the match reg value is + * ensured, hence we can use do_gettimeofday() from interrupt + * handlers. + */ do { timer_tick(regs); OSSR = OSSR_M0; /* Clear match on timer 0 */ @@ -120,6 +131,42 @@ static void __init sa1100_timer_init(void) OSCR = 0; /* initialize free-running timer, force first match */ } +#ifdef CONFIG_NO_IDLE_HZ +static int sa1100_dyn_tick_enable_disable(void) +{ + /* nothing to do */ + return 0; +} + +static void sa1100_dyn_tick_reprogram(unsigned long ticks) +{ + if (ticks > 1) { + initial_match = OSMR0; + OSMR0 = initial_match + ticks * LATCH; + match_posponed = 1; + } +} + +static irqreturn_t +sa1100_dyn_tick_handler(int irq, void *dev_id, struct pt_regs *regs) +{ + if (match_posponed) { + match_posponed = 0; + OSMR0 = initial_match; + if ((signed long)(initial_match - OSCR) <= 0) + return sa1100_timer_interrupt(irq, dev_id, regs); + } + return IRQ_NONE; +} + +static struct dyn_tick_timer sa1100_dyn_tick = { + .enable = sa1100_dyn_tick_enable_disable, + .disable = sa1100_dyn_tick_enable_disable, + .reprogram = sa1100_dyn_tick_reprogram, + .handler = sa1100_dyn_tick_handler, +}; +#endif + #ifdef CONFIG_PM unsigned long osmr[4], oier; @@ -156,4 +203,7 @@ struct sys_timer sa1100_timer = { .suspend = sa1100_timer_suspend, .resume = sa1100_timer_resume, .offset = sa1100_gettimeoffset, +#ifdef CONFIG_NO_IDLE_HZ + .dyn_tick = &sa1100_dyn_tick, +#endif }; diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 81f4a8a2d34..4b39d867ac1 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -45,7 +45,7 @@ #define LDST_P_EQ_U(i) ((((i) ^ ((i) >> 1)) & (1 << 23)) == 0) -#define LDSTH_I_BIT(i) (i & (1 << 22)) /* half-word immed */ +#define LDSTHD_I_BIT(i) (i & (1 << 22)) /* double/half-word immed */ #define LDM_S_BIT(i) (i & (1 << 22)) /* write CPSR from SPSR */ #define RN_BITS(i) ((i >> 16) & 15) /* Rn */ @@ -68,6 +68,7 @@ static unsigned long ai_sys; static unsigned long ai_skipped; static unsigned long ai_half; static unsigned long ai_word; +static unsigned long ai_dword; static unsigned long ai_multi; static int ai_usermode; @@ -93,6 +94,8 @@ proc_alignment_read(char *page, char **start, off_t off, int count, int *eof, p += sprintf(p, "Skipped:\t%lu\n", ai_skipped); p += sprintf(p, "Half:\t\t%lu\n", ai_half); p += sprintf(p, "Word:\t\t%lu\n", ai_word); + if (cpu_architecture() >= CPU_ARCH_ARMv5TE) + p += sprintf(p, "DWord:\t\t%lu\n", ai_dword); p += sprintf(p, "Multi:\t\t%lu\n", ai_multi); p += sprintf(p, "User faults:\t%i (%s)\n", ai_usermode, usermode_action[ai_usermode]); @@ -283,12 +286,6 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r { unsigned int rd = RD_BITS(instr); - if ((instr & 0x01f00ff0) == 0x01000090) - goto swp; - - if ((instr & 0x90) != 0x90 || (instr & 0x60) == 0) - goto bad; - ai_half += 1; if (user_mode(regs)) @@ -323,10 +320,47 @@ do_alignment_ldrhstrh(unsigned long addr, unsigned long instr, struct pt_regs *r return TYPE_LDST; - swp: - printk(KERN_ERR "Alignment trap: not handling swp instruction\n"); - bad: - return TYPE_ERROR; + fault: + return TYPE_FAULT; +} + +static int +do_alignment_ldrdstrd(unsigned long addr, unsigned long instr, + struct pt_regs *regs) +{ + unsigned int rd = RD_BITS(instr); + + ai_dword += 1; + + if (user_mode(regs)) + goto user; + + if ((instr & 0xf0) == 0xd0) { + unsigned long val; + get32_unaligned_check(val, addr); + regs->uregs[rd] = val; + get32_unaligned_check(val, addr+4); + regs->uregs[rd+1] = val; + } else { + put32_unaligned_check(regs->uregs[rd], addr); + put32_unaligned_check(regs->uregs[rd+1], addr+4); + } + + return TYPE_LDST; + + user: + if ((instr & 0xf0) == 0xd0) { + unsigned long val; + get32t_unaligned_check(val, addr); + regs->uregs[rd] = val; + get32t_unaligned_check(val, addr+4); + regs->uregs[rd+1] = val; + } else { + put32t_unaligned_check(regs->uregs[rd], addr); + put32t_unaligned_check(regs->uregs[rd+1], addr+4); + } + + return TYPE_LDST; fault: return TYPE_FAULT; @@ -617,12 +651,20 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) regs->ARM_pc += thumb_mode(regs) ? 2 : 4; switch (CODING_BITS(instr)) { - case 0x00000000: /* ldrh or strh */ - if (LDSTH_I_BIT(instr)) + case 0x00000000: /* 3.13.4 load/store instruction extensions */ + if (LDSTHD_I_BIT(instr)) offset.un = (instr & 0xf00) >> 4 | (instr & 15); else offset.un = regs->uregs[RM_BITS(instr)]; - handler = do_alignment_ldrhstrh; + + if ((instr & 0x000000f0) == 0x000000b0 || /* LDRH, STRH */ + (instr & 0x001000f0) == 0x001000f0) /* LDRSH */ + handler = do_alignment_ldrhstrh; + else if ((instr & 0x001000f0) == 0x000000d0 || /* LDRD */ + (instr & 0x001000f0) == 0x000000f0) /* STRD */ + handler = do_alignment_ldrdstrd; + else + goto bad; break; case 0x04000000: /* ldr or str immediate */ diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c index 3c655c54e23..d125a3dc061 100644 --- a/arch/arm/mm/mm-armv.c +++ b/arch/arm/mm/mm-armv.c @@ -275,11 +275,9 @@ alloc_init_supersection(unsigned long virt, unsigned long phys, int prot) int i; for (i = 0; i < 16; i += 1) { - alloc_init_section(virt, phys & SUPERSECTION_MASK, - prot | PMD_SECT_SUPER); + alloc_init_section(virt, phys, prot | PMD_SECT_SUPER); virt += (PGDIR_SIZE / 2); - phys += (PGDIR_SIZE / 2); } } @@ -297,14 +295,10 @@ alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1, pg pte_t *ptep; if (pmd_none(*pmdp)) { - unsigned long pmdval; ptep = alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)); - pmdval = __pa(ptep) | prot_l1; - pmdp[0] = __pmd(pmdval); - pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t)); - flush_pmd_entry(pmdp); + __pmd_populate(pmdp, __pa(ptep) | prot_l1); } ptep = pte_offset_kernel(pmdp, virt); @@ -459,7 +453,7 @@ static void __init build_mem_type_table(void) for (i = 0; i < 16; i++) { unsigned long v = pgprot_val(protection_map[i]); - v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; + v = (v & ~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot; protection_map[i] = __pgprot(v); } @@ -583,23 +577,23 @@ static void __init create_mapping(struct map_desc *md) */ void setup_mm_for_reboot(char mode) { - unsigned long pmdval; + unsigned long base_pmdval; pgd_t *pgd; - pmd_t *pmd; int i; - int cpu_arch = cpu_architecture(); if (current->mm && current->mm->pgd) pgd = current->mm->pgd; else pgd = init_mm.pgd; - for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++) { - pmdval = (i << PGDIR_SHIFT) | - PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | - PMD_TYPE_SECT; - if (cpu_arch <= CPU_ARCH_ARMv5TEJ) - pmdval |= PMD_BIT4; + base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT; + if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ) + base_pmdval |= PMD_BIT4; + + for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) { + unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval; + pmd_t *pmd; + pmd = pmd_off(pgd, i << PGDIR_SHIFT); pmd[0] = __pmd(pmdval); pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))); diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 80988136f26..3deced637f0 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -383,6 +383,12 @@ source "drivers/acpi/Kconfig" endif +if PM + +source "arch/ia64/kernel/cpufreq/Kconfig" + +endif + endmenu if !IA64_HP_SIM diff --git a/arch/ia64/hp/sim/boot/fw-emu.c b/arch/ia64/hp/sim/boot/fw-emu.c index 5c46928e3dc..30fdfb1d0a5 100644 --- a/arch/ia64/hp/sim/boot/fw-emu.c +++ b/arch/ia64/hp/sim/boot/fw-emu.c @@ -237,17 +237,6 @@ sal_emulator (long index, unsigned long in1, unsigned long in2, return ((struct sal_ret_values) {status, r9, r10, r11}); } - -/* - * This is here to work around a bug in egcs-1.1.1b that causes the - * compiler to crash (seems like a bug in the new alias analysis code. - */ -void * -id (long addr) -{ - return (void *) addr; -} - struct ia64_boot_param * sys_fw_init (const char *args, int arglen) { diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index ebb89be2aa2..aa891c9bc9b 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c @@ -29,7 +29,6 @@ #include <asm/uaccess.h> #include <asm/rse.h> #include <asm/sigcontext.h> -#include <asm/segment.h> #include "ia32priv.h" diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index e1fb68ddec2..b242594be55 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_SMP) += smp.o smpboot.o domain.o obj-$(CONFIG_NUMA) += numa.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o obj-$(CONFIG_IA64_CYCLONE) += cyclone.o +obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_IA64_MCA_RECOVERY) += mca_recovery.o obj-$(CONFIG_KPROBES) += kprobes.o jprobes.o obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR) += uncached.o diff --git a/arch/ia64/kernel/cpufreq/Kconfig b/arch/ia64/kernel/cpufreq/Kconfig new file mode 100644 index 00000000000..2d9d5279b98 --- /dev/null +++ b/arch/ia64/kernel/cpufreq/Kconfig @@ -0,0 +1,29 @@ + +# +# CPU Frequency scaling +# + +menu "CPU Frequency scaling" + +source "drivers/cpufreq/Kconfig" + +if CPU_FREQ + +comment "CPUFreq processor drivers" + +config IA64_ACPI_CPUFREQ + tristate "ACPI Processor P-States driver" + select CPU_FREQ_TABLE + depends on ACPI_PROCESSOR + help + This driver adds a CPUFreq driver which utilizes the ACPI + Processor Performance States. + + For details, take a look at <file:Documentation/cpu-freq/>. + + If in doubt, say N. + +endif # CPU_FREQ + +endmenu + diff --git a/arch/ia64/kernel/cpufreq/Makefile b/arch/ia64/kernel/cpufreq/Makefile new file mode 100644 index 00000000000..f748d34c02f --- /dev/null +++ b/arch/ia64/kernel/cpufreq/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_IA64_ACPI_CPUFREQ) += acpi-cpufreq.o diff --git a/arch/ia64/kernel/cpufreq/acpi-cpufreq.c b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c new file mode 100644 index 00000000000..da4d5cf80a4 --- /dev/null +++ b/arch/ia64/kernel/cpufreq/acpi-cpufreq.c @@ -0,0 +1,499 @@ +/* + * arch/ia64/kernel/cpufreq/acpi-cpufreq.c + * This file provides the ACPI based P-state support. This + * module works with generic cpufreq infrastructure. Most of + * the code is based on i386 version + * (arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c) + * + * Copyright (C) 2005 Intel Corp + * Venkatesh Pallipadi <venkatesh.pallipadi@intel.com> + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/cpufreq.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> +#include <asm/io.h> +#include <asm/uaccess.h> +#include <asm/pal.h> + +#include <linux/acpi.h> +#include <acpi/processor.h> + +#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "acpi-cpufreq", msg) + +MODULE_AUTHOR("Venkatesh Pallipadi"); +MODULE_DESCRIPTION("ACPI Processor P-States Driver"); +MODULE_LICENSE("GPL"); + + +struct cpufreq_acpi_io { + struct acpi_processor_performance acpi_data; + struct cpufreq_frequency_table *freq_table; + unsigned int resume; +}; + +static struct cpufreq_acpi_io *acpi_io_data[NR_CPUS]; + +static struct cpufreq_driver acpi_cpufreq_driver; + + +static int +processor_set_pstate ( + u32 value) +{ + s64 retval; + + dprintk("processor_set_pstate\n"); + + retval = ia64_pal_set_pstate((u64)value); + + if (retval) { + dprintk("Failed to set freq to 0x%x, with error 0x%x\n", + value, retval); + return -ENODEV; + } + return (int)retval; +} + + +static int +processor_get_pstate ( + u32 *value) +{ + u64 pstate_index = 0; + s64 retval; + + dprintk("processor_get_pstate\n"); + + retval = ia64_pal_get_pstate(&pstate_index); + *value = (u32) pstate_index; + + if (retval) + dprintk("Failed to get current freq with " + "error 0x%x, idx 0x%x\n", retval, *value); + + return (int)retval; +} + + +/* To be used only after data->acpi_data is initialized */ +static unsigned +extract_clock ( + struct cpufreq_acpi_io *data, + unsigned value, + unsigned int cpu) +{ + unsigned long i; + + dprintk("extract_clock\n"); + + for (i = 0; i < data->acpi_data.state_count; i++) { + if (value >= data->acpi_data.states[i].control) + return data->acpi_data.states[i].core_frequency; + } + return data->acpi_data.states[i-1].core_frequency; +} + + +static unsigned int +processor_get_freq ( + struct cpufreq_acpi_io *data, + unsigned int cpu) +{ + int ret = 0; + u32 value = 0; + cpumask_t saved_mask; + unsigned long clock_freq; + + dprintk("processor_get_freq\n"); + + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (smp_processor_id() != cpu) { + ret = -EAGAIN; + goto migrate_end; + } + + /* + * processor_get_pstate gets the average frequency since the + * last get. So, do two PAL_get_freq()... + */ + ret = processor_get_pstate(&value); + ret = processor_get_pstate(&value); + + if (ret) { + set_cpus_allowed(current, saved_mask); + printk(KERN_WARNING "get performance failed with error %d\n", + ret); + ret = -EAGAIN; + goto migrate_end; + } + clock_freq = extract_clock(data, value, cpu); + ret = (clock_freq*1000); + +migrate_end: + set_cpus_allowed(current, saved_mask); + return ret; +} + + +static int +processor_set_freq ( + struct cpufreq_acpi_io *data, + unsigned int cpu, + int state) +{ + int ret = 0; + u32 value = 0; + struct cpufreq_freqs cpufreq_freqs; + cpumask_t saved_mask; + int retval; + + dprintk("processor_set_freq\n"); + + saved_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(cpu)); + if (smp_processor_id() != cpu) { + retval = -EAGAIN; + goto migrate_end; + } + + if (state == data->acpi_data.state) { + if (unlikely(data->resume)) { + dprintk("Called after resume, resetting to P%d\n", state); + data->resume = 0; + } else { + dprintk("Already at target state (P%d)\n", state); + retval = 0; + goto migrate_end; + } + } + + dprintk("Transitioning from P%d to P%d\n", + data->acpi_data.state, state); + + /* cpufreq frequency struct */ + cpufreq_freqs.cpu = cpu; + cpufreq_freqs.old = data->freq_table[data->acpi_data.state].frequency; + cpufreq_freqs.new = data->freq_table[state].frequency; + + /* notify cpufreq */ + cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); + + /* + * First we write the target state's 'control' value to the + * control_register. + */ + + value = (u32) data->acpi_data.states[state].control; + + dprintk("Transitioning to state: 0x%08x\n", value); + + ret = processor_set_pstate(value); + if (ret) { + unsigned int tmp = cpufreq_freqs.new; + cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); + cpufreq_freqs.new = cpufreq_freqs.old; + cpufreq_freqs.old = tmp; + cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_PRECHANGE); + cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); + printk(KERN_WARNING "Transition failed with error %d\n", ret); + retval = -ENODEV; + goto migrate_end; + } + + cpufreq_notify_transition(&cpufreq_freqs, CPUFREQ_POSTCHANGE); + + data->acpi_data.state = state; + + retval = 0; + +migrate_end: + set_cpus_allowed(current, saved_mask); + return (retval); +} + + +static unsigned int +acpi_cpufreq_get ( + unsigned int cpu) +{ + struct cpufreq_acpi_io *data = acpi_io_data[cpu]; + + dprintk("acpi_cpufreq_get\n"); + + return processor_get_freq(data, cpu); +} + + +static int +acpi_cpufreq_target ( + struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + unsigned int next_state = 0; + unsigned int result = 0; + + dprintk("acpi_cpufreq_setpolicy\n"); + + result = cpufreq_frequency_table_target(policy, + data->freq_table, target_freq, relation, &next_state); + if (result) + return (result); + + result = processor_set_freq(data, policy->cpu, next_state); + + return (result); +} + + +static int +acpi_cpufreq_verify ( + struct cpufreq_policy *policy) +{ + unsigned int result = 0; + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + + dprintk("acpi_cpufreq_verify\n"); + + result = cpufreq_frequency_table_verify(policy, + data->freq_table); + + return (result); +} + + +/* + * processor_init_pdc - let BIOS know about the SMP capabilities + * of this driver + * @perf: processor-specific acpi_io_data struct + * @cpu: CPU being initialized + * + * To avoid issues with legacy OSes, some BIOSes require to be informed of + * the SMP capabilities of OS P-state driver. Here we set the bits in _PDC + * accordingly. Actual call to _PDC is done in driver/acpi/processor.c + */ +static void +processor_init_pdc ( + struct acpi_processor_performance *perf, + unsigned int cpu, + struct acpi_object_list *obj_list + ) +{ + union acpi_object *obj; + u32 *buf; + + dprintk("processor_init_pdc\n"); + + perf->pdc = NULL; + /* Initialize pdc. It will be used later. */ + if (!obj_list) + return; + + if (!(obj_list->count && obj_list->pointer)) + return; + + obj = obj_list->pointer; + if ((obj->buffer.length == 12) && obj->buffer.pointer) { + buf = (u32 *)obj->buffer.pointer; + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; + perf->pdc = obj_list; + } + return; +} + + +static int +acpi_cpufreq_cpu_init ( + struct cpufreq_policy *policy) +{ + unsigned int i; + unsigned int cpu = policy->cpu; + struct cpufreq_acpi_io *data; + unsigned int result = 0; + + union acpi_object arg0 = {ACPI_TYPE_BUFFER}; + u32 arg0_buf[3]; + struct acpi_object_list arg_list = {1, &arg0}; + + dprintk("acpi_cpufreq_cpu_init\n"); + /* setup arg_list for _PDC settings */ + arg0.buffer.length = 12; + arg0.buffer.pointer = (u8 *) arg0_buf; + + data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); + if (!data) + return (-ENOMEM); + + memset(data, 0, sizeof(struct cpufreq_acpi_io)); + + acpi_io_data[cpu] = data; + + processor_init_pdc(&data->acpi_data, cpu, &arg_list); + result = acpi_processor_register_performance(&data->acpi_data, cpu); + data->acpi_data.pdc = NULL; + + if (result) + goto err_free; + + /* capability check */ + if (data->acpi_data.state_count <= 1) { + dprintk("No P-States\n"); + result = -ENODEV; + goto err_unreg; + } + + if ((data->acpi_data.control_register.space_id != + ACPI_ADR_SPACE_FIXED_HARDWARE) || + (data->acpi_data.status_register.space_id != + ACPI_ADR_SPACE_FIXED_HARDWARE)) { + dprintk("Unsupported address space [%d, %d]\n", + (u32) (data->acpi_data.control_register.space_id), + (u32) (data->acpi_data.status_register.space_id)); + result = -ENODEV; + goto err_unreg; + } + + /* alloc freq_table */ + data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * + (data->acpi_data.state_count + 1), + GFP_KERNEL); + if (!data->freq_table) { + result = -ENOMEM; + goto err_unreg; + } + + /* detect transition latency */ + policy->cpuinfo.transition_latency = 0; + for (i=0; i<data->acpi_data.state_count; i++) { + if ((data->acpi_data.states[i].transition_latency * 1000) > + policy->cpuinfo.transition_latency) { + policy->cpuinfo.transition_latency = + data->acpi_data.states[i].transition_latency * 1000; + } + } + policy->governor = CPUFREQ_DEFAULT_GOVERNOR; + + policy->cur = processor_get_freq(data, policy->cpu); + + /* table init */ + for (i = 0; i <= data->acpi_data.state_count; i++) + { + data->freq_table[i].index = i; + if (i < data->acpi_data.state_count) { + data->freq_table[i].frequency = + data->acpi_data.states[i].core_frequency * 1000; + } else { + data->freq_table[i].frequency = CPUFREQ_TABLE_END; + } + } + + result = cpufreq_frequency_table_cpuinfo(policy, data->freq_table); + if (result) { + goto err_freqfree; + } + + /* notify BIOS that we exist */ + acpi_processor_notify_smm(THIS_MODULE); + + printk(KERN_INFO "acpi-cpufreq: CPU%u - ACPI performance management " + "activated.\n", cpu); + + for (i = 0; i < data->acpi_data.state_count; i++) + dprintk(" %cP%d: %d MHz, %d mW, %d uS, %d uS, 0x%x 0x%x\n", + (i == data->acpi_data.state?'*':' '), i, + (u32) data->acpi_data.states[i].core_frequency, + (u32) data->acpi_data.states[i].power, + (u32) data->acpi_data.states[i].transition_latency, + (u32) data->acpi_data.states[i].bus_master_latency, + (u32) data->acpi_data.states[i].status, + (u32) data->acpi_data.states[i].control); + + cpufreq_frequency_table_get_attr(data->freq_table, policy->cpu); + + /* the first call to ->target() should result in us actually + * writing something to the appropriate registers. */ + data->resume = 1; + + return (result); + + err_freqfree: + kfree(data->freq_table); + err_unreg: + acpi_processor_unregister_performance(&data->acpi_data, cpu); + err_free: + kfree(data); + acpi_io_data[cpu] = NULL; + + return (result); +} + + +static int +acpi_cpufreq_cpu_exit ( + struct cpufreq_policy *policy) +{ + struct cpufreq_acpi_io *data = acpi_io_data[policy->cpu]; + + dprintk("acpi_cpufreq_cpu_exit\n"); + + if (data) { + cpufreq_frequency_table_put_attr(policy->cpu); + acpi_io_data[policy->cpu] = NULL; + acpi_processor_unregister_performance(&data->acpi_data, + policy->cpu); + kfree(data); + } + + return (0); +} + + +static struct freq_attr* acpi_cpufreq_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; + + +static struct cpufreq_driver acpi_cpufreq_driver = { + .verify = acpi_cpufreq_verify, + .target = acpi_cpufreq_target, + .get = acpi_cpufreq_get, + .init = acpi_cpufreq_cpu_init, + .exit = acpi_cpufreq_cpu_exit, + .name = "acpi-cpufreq", + .owner = THIS_MODULE, + .attr = acpi_cpufreq_attr, +}; + + +static int __init +acpi_cpufreq_init (void) +{ + dprintk("acpi_cpufreq_init\n"); + + return cpufreq_register_driver(&acpi_cpufreq_driver); +} + + +static void __exit +acpi_cpufreq_exit (void) +{ + dprintk("acpi_cpufreq_exit\n"); + + cpufreq_unregister_driver(&acpi_cpufreq_driver); + return; +} + + +late_initcall(acpi_cpufreq_init); +module_exit(acpi_cpufreq_exit); + diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c index 770fab37928..f2dbcd1db0d 100644 --- a/arch/ia64/kernel/sys_ia64.c +++ b/arch/ia64/kernel/sys_ia64.c @@ -35,7 +35,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len return -ENOMEM; #ifdef CONFIG_HUGETLB_PAGE - if (REGION_NUMBER(addr) == REGION_HPAGE) + if (REGION_NUMBER(addr) == RGN_HPAGE) addr = 0; #endif if (!addr) diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c index 490dfc9ab47..4e9d06c48a8 100644 --- a/arch/ia64/kernel/uncached.c +++ b/arch/ia64/kernel/uncached.c @@ -184,7 +184,7 @@ uncached_free_page(unsigned long maddr) { int node; - node = nasid_to_cnodeid(NASID_GET(maddr)); + node = paddr_to_nid(maddr - __IA64_UNCACHED_OFFSET); dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node); @@ -217,7 +217,7 @@ uncached_build_memmap(unsigned long start, unsigned long end, void *arg) memset((char *)vstart, 0, length); - node = nasid_to_cnodeid(NASID_GET(start)); + node = paddr_to_nid(start); for (; vstart < vend ; vstart += PAGE_SIZE) { dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart); diff --git a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile index 1902c3c2ef9..799407e7726 100644 --- a/arch/ia64/lib/Makefile +++ b/arch/ia64/lib/Makefile @@ -6,7 +6,7 @@ obj-y := io.o lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ - bitop.o checksum.o clear_page.o csum_partial_copy.o copy_page.o \ + bitop.o checksum.o clear_page.o csum_partial_copy.o \ clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ flush.o ip_fast_csum.o do_csum.o \ memset.o strlen.o swiotlb.o diff --git a/arch/ia64/lib/swiotlb.c b/arch/ia64/lib/swiotlb.c index ab7b3ad99a7..dbc0b3e449c 100644 --- a/arch/ia64/lib/swiotlb.c +++ b/arch/ia64/lib/swiotlb.c @@ -93,8 +93,7 @@ static int __init setup_io_tlb_npages(char *str) { if (isdigit(*str)) { - io_tlb_nslabs = simple_strtoul(str, &str, 0) << - (PAGE_SHIFT - IO_TLB_SHIFT); + io_tlb_nslabs = simple_strtoul(str, &str, 0); /* avoid tail segment of size < IO_TLB_SEGSIZE */ io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); } @@ -117,7 +116,7 @@ swiotlb_init_with_default_size (size_t default_size) unsigned long i; if (!io_tlb_nslabs) { - io_tlb_nslabs = (default_size >> PAGE_SHIFT); + io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); } diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index e0a776a3044..2d13889d0a9 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -76,7 +76,7 @@ int is_aligned_hugepage_range(unsigned long addr, unsigned long len) return -EINVAL; if (addr & ~HPAGE_MASK) return -EINVAL; - if (REGION_NUMBER(addr) != REGION_HPAGE) + if (REGION_NUMBER(addr) != RGN_HPAGE) return -EINVAL; return 0; @@ -87,7 +87,7 @@ struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int writ struct page *page; pte_t *ptep; - if (REGION_NUMBER(addr) != REGION_HPAGE) + if (REGION_NUMBER(addr) != RGN_HPAGE) return ERR_PTR(-EINVAL); ptep = huge_pte_offset(mm, addr); @@ -142,8 +142,8 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, u return -ENOMEM; if (len & ~HPAGE_MASK) return -EINVAL; - /* This code assumes that REGION_HPAGE != 0. */ - if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) + /* This code assumes that RGN_HPAGE != 0. */ + if ((REGION_NUMBER(addr) != RGN_HPAGE) || (addr & (HPAGE_SIZE - 1))) addr = HPAGE_REGION_BASE; else addr = ALIGN(addr, HPAGE_SIZE); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index f9472c50ab4..9977c122e9f 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -24,7 +24,6 @@ #include <asm/machvec.h> #include <asm/page.h> -#include <asm/segment.h> #include <asm/system.h> #include <asm/io.h> #include <asm/sal.h> diff --git a/arch/ia64/sn/include/tio.h b/arch/ia64/sn/include/tio.h index 0139124dd54..6b2e7b75eb1 100644 --- a/arch/ia64/sn/include/tio.h +++ b/arch/ia64/sn/include/tio.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_TIO_H @@ -26,6 +26,10 @@ #define TIO_ITTE_VALID_MASK 0x1 #define TIO_ITTE_VALID_SHIFT 16 +#define TIO_ITTE_WIDGET(itte) \ + (((itte) >> TIO_ITTE_WIDGET_SHIFT) & TIO_ITTE_WIDGET_MASK) +#define TIO_ITTE_VALID(itte) \ + (((itte) >> TIO_ITTE_VALID_SHIFT) & TIO_ITTE_VALID_MASK) #define TIO_ITTE_PUT(nasid, bigwin, widget, addr, valid) \ REMOTE_HUB_S((nasid), TIO_ITTE(bigwin), \ diff --git a/arch/ia64/sn/include/xtalk/hubdev.h b/arch/ia64/sn/include/xtalk/hubdev.h index 580a1c0403a..71c2b271b4c 100644 --- a/arch/ia64/sn/include/xtalk/hubdev.h +++ b/arch/ia64/sn/include/xtalk/hubdev.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_XTALK_HUBDEV_H #define _ASM_IA64_SN_XTALK_HUBDEV_H @@ -16,6 +16,9 @@ #define IIO_ITTE_WIDGET_MASK ((1<<IIO_ITTE_WIDGET_BITS)-1) #define IIO_ITTE_WIDGET_SHIFT 8 +#define IIO_ITTE_WIDGET(itte) \ + (((itte) >> IIO_ITTE_WIDGET_SHIFT) & IIO_ITTE_WIDGET_MASK) + /* * Use the top big window as a surrogate for the first small window */ @@ -34,7 +37,8 @@ struct sn_flush_device_list { unsigned long sfdl_force_int_addr; unsigned long sfdl_flush_value; volatile unsigned long *sfdl_flush_addr; - uint64_t sfdl_persistent_busnum; + uint32_t sfdl_persistent_busnum; + uint32_t sfdl_persistent_segment; struct pcibus_info *sfdl_pcibus_info; spinlock_t sfdl_flush_lock; }; @@ -58,7 +62,8 @@ struct hubdev_info { void *hdi_nodepda; void *hdi_node_vertex; - void *hdi_xtalk_vertex; + uint32_t max_segment_number; + uint32_t max_pcibus_number; }; extern void hubdev_init_node(nodepda_t *, cnodeid_t); diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c index 647deae9bfc..45854c637e9 100644 --- a/arch/ia64/sn/kernel/bte.c +++ b/arch/ia64/sn/kernel/bte.c @@ -29,16 +29,30 @@ /* two interfaces on two btes */ #define MAX_INTERFACES_TO_TRY 4 +#define MAX_NODES_TO_TRY 2 static struct bteinfo_s *bte_if_on_node(nasid_t nasid, int interface) { nodepda_t *tmp_nodepda; + if (nasid_to_cnodeid(nasid) == -1) + return (struct bteinfo_s *)NULL;; + tmp_nodepda = NODEPDA(nasid_to_cnodeid(nasid)); return &tmp_nodepda->bte_if[interface]; } +static inline void bte_start_transfer(struct bteinfo_s *bte, u64 len, u64 mode) +{ + if (is_shub2()) { + BTE_CTRL_STORE(bte, (IBLS_BUSY | ((len) | (mode) << 24))); + } else { + BTE_LNSTAT_STORE(bte, len); + BTE_CTRL_STORE(bte, mode); + } +} + /************************************************************************ * Block Transfer Engine copy related functions. * @@ -67,13 +81,15 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) { u64 transfer_size; u64 transfer_stat; + u64 notif_phys_addr; struct bteinfo_s *bte; bte_result_t bte_status; unsigned long irq_flags; unsigned long itc_end = 0; - struct bteinfo_s *btes_to_try[MAX_INTERFACES_TO_TRY]; - int bte_if_index; - int bte_pri, bte_sec; + int nasid_to_try[MAX_NODES_TO_TRY]; + int my_nasid = get_nasid(); + int bte_if_index, nasid_index; + int bte_first, btes_per_node = BTES_PER_NODE; BTE_PRINTK(("bte_copy(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%p)\n", src, dest, len, mode, notification)); @@ -86,36 +102,26 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification) (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK)); BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT))); - /* CPU 0 (per node) tries bte0 first, CPU 1 try bte1 first */ - if (cpuid_to_subnode(smp_processor_id()) == 0) { - bte_pri = 0; - bte_sec = 1; - } else { - bte_pri = 1; - bte_sec = 0; - } + /* + * Start with interface corresponding to cpu number + */ + bte_first = raw_smp_processor_id() % btes_per_node; if (mode & BTE_USE_DEST) { /* try remote then local */ - btes_to_try[0] = bte_if_on_node(NASID_GET(dest), bte_pri); - btes_to_try[1] = bte_if_on_node(NASID_GET(dest), bte_sec); + nasid_to_try[0] = NASID_GET(dest); if (mode & BTE_USE_ANY) { - btes_to_try[2] = bte_if_on_node(get_nasid(), bte_pri); - btes_to_try[3] = bte_if_on_node(get_nasid(), bte_sec); + nasid_to_try[1] = my_nasid; } else { - btes_to_try[2] = NULL; - btes_to_try[3] = NULL; + nasid_to_try[1] = (int)NULL; } } else { /* try local then remote */ - btes_to_try[0] = bte_if_on_node(get_nasid(), bte_pri); - btes_to_try[1] = bte_if_on_node(get_nasid(), bte_sec); + nasid_to_try[0] = my_nasid; if (mode & BTE_USE_ANY) { - btes_to_try[2] = bte_if_on_node(NASID_GET(dest), bte_pri); - btes_to_try[3] = bte_if_on_node(NASID_GET(dest), bte_sec); + nasid_to_try[1] = NASID_GET(dest); } else { - btes_to_try[2] = NULL; - btes_to_try[3] = NULL; + nasid_to_try[1] = (int)NULL; } } @@ -123,11 +129,12 @@ retry_bteop: do { local_irq_save(irq_flags); - bte_if_index = 0; + bte_if_index = bte_first; + nasid_index = 0; /* Attempt to lock one of the BTE interfaces. */ - while (bte_if_index < MAX_INTERFACES_TO_TRY) { - bte = btes_to_try[bte_if_index++]; + while (nasid_index < MAX_NODES_TO_TRY) { + bte = bte_if_on_node(nasid_to_try[nasid_index],bte_if_index); if (bte == NULL) { continue; @@ -143,6 +150,15 @@ retry_bteop: break; } } + + bte_if_index = (bte_if_index + 1) % btes_per_node; /* Next interface */ + if (bte_if_index == bte_first) { + /* + * We've tried all interfaces on this node + */ + nasid_index++; + } + bte = NULL; } @@ -169,7 +185,13 @@ retry_bteop: /* Initialize the notification to a known value. */ *bte->most_rcnt_na = BTE_WORD_BUSY; + notif_phys_addr = TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)); + if (is_shub2()) { + src = SH2_TIO_PHYS_TO_DMA(src); + dest = SH2_TIO_PHYS_TO_DMA(dest); + notif_phys_addr = SH2_TIO_PHYS_TO_DMA(notif_phys_addr); + } /* Set the source and destination registers */ BTE_PRINTKV(("IBSA = 0x%lx)\n", (TO_PHYS(src)))); BTE_SRC_STORE(bte, TO_PHYS(src)); @@ -177,14 +199,12 @@ retry_bteop: BTE_DEST_STORE(bte, TO_PHYS(dest)); /* Set the notification register */ - BTE_PRINTKV(("IBNA = 0x%lx)\n", - TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na)))); - BTE_NOTIF_STORE(bte, - TO_PHYS(ia64_tpa((unsigned long)bte->most_rcnt_na))); + BTE_PRINTKV(("IBNA = 0x%lx)\n", notif_phys_addr)); + BTE_NOTIF_STORE(bte, notif_phys_addr); /* Initiate the transfer */ BTE_PRINTK(("IBCT = 0x%lx)\n", BTE_VALID_MODE(mode))); - BTE_START_TRANSFER(bte, transfer_size, BTE_VALID_MODE(mode)); + bte_start_transfer(bte, transfer_size, BTE_VALID_MODE(mode)); itc_end = ia64_get_itc() + (40000000 * local_cpu_data->cyc_per_usec); @@ -195,6 +215,7 @@ retry_bteop: } while ((transfer_stat = *bte->most_rcnt_na) == BTE_WORD_BUSY) { + cpu_relax(); if (ia64_get_itc() > itc_end) { BTE_PRINTK(("BTE timeout nasid 0x%x bte%d IBLS = 0x%lx na 0x%lx\n", NASID_GET(bte->bte_base_addr), bte->bte_num, diff --git a/arch/ia64/sn/kernel/huberror.c b/arch/ia64/sn/kernel/huberror.c index 5c39b43ba3c..5c5eb01c50f 100644 --- a/arch/ia64/sn/kernel/huberror.c +++ b/arch/ia64/sn/kernel/huberror.c @@ -76,7 +76,7 @@ void hubiio_crb_free(struct hubdev_info *hubdev_info, int crbnum) */ REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum)); while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND) - udelay(1); + cpu_relax(); } diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c index 414cdf2e3c9..4564ed0b5ff 100644 --- a/arch/ia64/sn/kernel/io_init.c +++ b/arch/ia64/sn/kernel/io_init.c @@ -18,6 +18,7 @@ #include <asm/sn/simulator.h> #include <asm/sn/sn_sal.h> #include <asm/sn/tioca_provider.h> +#include <asm/sn/tioce_provider.h> #include "xtalk/hubdev.h" #include "xtalk/xwidgetdev.h" @@ -44,6 +45,9 @@ int sn_ioif_inited = 0; /* SN I/O infrastructure initialized? */ struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ +static int max_segment_number = 0; /* Default highest segment number */ +static int max_pcibus_number = 255; /* Default highest pci bus number */ + /* * Hooks and struct for unsupported pci providers */ @@ -157,13 +161,28 @@ static void sn_fixup_ionodes(void) uint64_t nasid; int i, widget; + /* + * Get SGI Specific HUB chipset information. + * Inform Prom that this kernel can support domain bus numbering. + */ for (i = 0; i < numionodes; i++) { hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo); nasid = cnodeid_to_nasid(i); + hubdev->max_segment_number = 0xffffffff; + hubdev->max_pcibus_number = 0xff; status = sal_get_hubdev_info(nasid, (uint64_t) __pa(hubdev)); if (status) continue; + /* Save the largest Domain and pcibus numbers found. */ + if (hubdev->max_segment_number) { + /* + * Dealing with a Prom that supports segments. + */ + max_segment_number = hubdev->max_segment_number; + max_pcibus_number = hubdev->max_pcibus_number; + } + /* Attach the error interrupt handlers */ if (nasid & 1) ice_error_init(hubdev); @@ -230,7 +249,7 @@ void sn_pci_unfixup_slot(struct pci_dev *dev) void sn_pci_fixup_slot(struct pci_dev *dev) { int idx; - int segment = 0; + int segment = pci_domain_nr(dev->bus); int status = 0; struct pcibus_bussoft *bs; struct pci_bus *host_pci_bus; @@ -283,9 +302,9 @@ void sn_pci_fixup_slot(struct pci_dev *dev) * PCI host_pci_dev struct and set up host bus linkages */ - bus_no = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32; + bus_no = (SN_PCIDEV_INFO(dev)->pdi_slot_host_handle >> 32) & 0xff; devfn = SN_PCIDEV_INFO(dev)->pdi_slot_host_handle & 0xffffffff; - host_pci_bus = pci_find_bus(pci_domain_nr(dev->bus), bus_no); + host_pci_bus = pci_find_bus(segment, bus_no); host_pci_dev = pci_get_slot(host_pci_bus, devfn); SN_PCIDEV_INFO(dev)->host_pci_dev = host_pci_dev; @@ -333,6 +352,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) prom_bussoft_ptr = __va(prom_bussoft_ptr); controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL); + controller->segment = segment; if (!controller) BUG(); @@ -390,7 +410,7 @@ void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus) if (controller->node >= num_online_nodes()) { struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); - printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%lu" + printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u" "L_IO=%lx L_MEM=%lx BASE=%lx\n", b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); @@ -445,6 +465,7 @@ sn_sysdata_free_start: static int __init sn_pci_init(void) { int i = 0; + int j = 0; struct pci_dev *pci_dev = NULL; extern void sn_init_cpei_timer(void); #ifdef CONFIG_PROC_FS @@ -464,6 +485,7 @@ static int __init sn_pci_init(void) pcibr_init_provider(); tioca_init_provider(); + tioce_init_provider(); /* * This is needed to avoid bounce limit checks in the blk layer @@ -479,8 +501,9 @@ static int __init sn_pci_init(void) #endif /* busses are not known yet ... */ - for (i = 0; i < PCI_BUSES_TO_SCAN; i++) - sn_pci_controller_fixup(0, i, NULL); + for (i = 0; i <= max_segment_number; i++) + for (j = 0; j <= max_pcibus_number; j++) + sn_pci_controller_fixup(i, j, NULL); /* * Generic Linux PCI Layer has created the pci_bus and pci_dev diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c index 84d276a14ec..9fc74631ba8 100644 --- a/arch/ia64/sn/kernel/irq.c +++ b/arch/ia64/sn/kernel/irq.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved. */ #include <linux/irq.h> @@ -76,16 +76,14 @@ static void sn_enable_irq(unsigned int irq) static void sn_ack_irq(unsigned int irq) { - uint64_t event_occurred, mask = 0; - int nasid; + u64 event_occurred, mask = 0; irq = irq & 0xff; - nasid = get_nasid(); event_occurred = - HUB_L((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED)); + HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED)); mask = event_occurred & SH_ALL_INT_MASK; - HUB_S((uint64_t *) GLOBAL_MMR_ADDR(nasid, SH_EVENT_OCCURRED_ALIAS), - mask); + HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), + mask); __set_bit(irq, (volatile void *)pda->sn_in_service_ivecs); move_irq(irq); @@ -93,15 +91,12 @@ static void sn_ack_irq(unsigned int irq) static void sn_end_irq(unsigned int irq) { - int nasid; int ivec; - uint64_t event_occurred; + u64 event_occurred; ivec = irq & 0xff; if (ivec == SGI_UART_VECTOR) { - nasid = get_nasid(); - event_occurred = HUB_L((uint64_t *) GLOBAL_MMR_ADDR - (nasid, SH_EVENT_OCCURRED)); + event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED)); /* If the UART bit is set here, we may have received an * interrupt from the UART that the driver missed. To * make sure, we IPI ourselves to force us to look again. @@ -132,6 +127,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) int local_widget, status; nasid_t local_nasid; struct sn_irq_info *new_irq_info; + struct sn_pcibus_provider *pci_provider; new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); if (new_irq_info == NULL) @@ -171,8 +167,9 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask) new_irq_info->irq_cpuid = cpuid; register_intr_pda(new_irq_info); - if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type)) - pcibr_change_devices_irq(new_irq_info); + pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type]; + if (pci_provider && pci_provider->target_interrupt) + (pci_provider->target_interrupt)(new_irq_info); spin_lock(&sn_irq_info_lock); list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); @@ -317,6 +314,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev) pci_dev_put(pci_dev); } +static inline void +sn_call_force_intr_provider(struct sn_irq_info *sn_irq_info) +{ + struct sn_pcibus_provider *pci_provider; + + pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type]; + if (pci_provider && pci_provider->force_interrupt) + (*pci_provider->force_interrupt)(sn_irq_info); +} + static void force_interrupt(int irq) { struct sn_irq_info *sn_irq_info; @@ -325,11 +332,9 @@ static void force_interrupt(int irq) return; rcu_read_lock(); - list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) { - if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && - (sn_irq_info->irq_bridge != NULL)) - pcibr_force_interrupt(sn_irq_info); - } + list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list) + sn_call_force_intr_provider(sn_irq_info); + rcu_read_unlock(); } @@ -351,6 +356,14 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; + /* + * Bridge types attached to TIO (anything but PIC) do not need this WAR + * since they do not target Shub II interrupt registers. If that + * ever changes, this check needs to accomodate. + */ + if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC) + return; + pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (!pcidev_info) return; @@ -377,16 +390,12 @@ static void sn_check_intr(int irq, struct sn_irq_info *sn_irq_info) break; } if (!test_bit(irr_bit, &irr_reg)) { - if (!test_bit(irq, pda->sn_soft_irr)) { - if (!test_bit(irq, pda->sn_in_service_ivecs)) { - regval &= 0xff; - if (sn_irq_info->irq_int_bit & regval & - sn_irq_info->irq_last_intr) { - regval &= - ~(sn_irq_info-> - irq_int_bit & regval); - pcibr_force_interrupt(sn_irq_info); - } + if (!test_bit(irq, pda->sn_in_service_ivecs)) { + regval &= 0xff; + if (sn_irq_info->irq_int_bit & regval & + sn_irq_info->irq_last_intr) { + regval &= ~(sn_irq_info->irq_int_bit & regval); + sn_call_force_intr_provider(sn_irq_info); } } } @@ -404,13 +413,7 @@ void sn_lb_int_war_check(void) rcu_read_lock(); for (i = pda->sn_first_irq; i <= pda->sn_last_irq; i++) { list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[i], list) { - /* - * Only call for PCI bridges that are fully - * initialized. - */ - if (IS_PCI_BRIDGE_ASIC(sn_irq_info->irq_bridge_type) && - (sn_irq_info->irq_bridge != NULL)) - sn_check_intr(i, sn_irq_info); + sn_check_intr(i, sn_irq_info); } } rcu_read_unlock(); diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 7c7fe441d62..a594aca959e 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -80,8 +80,6 @@ EXPORT_PER_CPU_SYMBOL(__sn_cnodeid_to_nasid); DEFINE_PER_CPU(struct nodepda_s *, __sn_nodepda); EXPORT_PER_CPU_SYMBOL(__sn_nodepda); -partid_t sn_partid = -1; -EXPORT_SYMBOL(sn_partid); char sn_system_serial_number_string[128]; EXPORT_SYMBOL(sn_system_serial_number_string); u64 sn_partition_serial_number; @@ -403,6 +401,7 @@ static void __init sn_init_pdas(char **cmdline_p) memset(nodepdaindr[cnode], 0, sizeof(nodepda_t)); memset(nodepdaindr[cnode]->phys_cpuid, -1, sizeof(nodepdaindr[cnode]->phys_cpuid)); + spin_lock_init(&nodepdaindr[cnode]->ptc_lock); } /* @@ -532,8 +531,8 @@ void __init sn_cpu_init(void) */ { u64 pio1[] = {SH1_PIO_WRITE_STATUS_0, 0, SH1_PIO_WRITE_STATUS_1, 0}; - u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_1, - SH2_PIO_WRITE_STATUS_2, SH2_PIO_WRITE_STATUS_3}; + u64 pio2[] = {SH2_PIO_WRITE_STATUS_0, SH2_PIO_WRITE_STATUS_2, + SH2_PIO_WRITE_STATUS_1, SH2_PIO_WRITE_STATUS_3}; u64 *pio; pio = is_shub1() ? pio1 : pio2; pda->pio_write_status_addr = (volatile unsigned long *) LOCAL_MMR_ADDR(pio[slice]); diff --git a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S index 96cb71d1568..3fa95065a44 100644 --- a/arch/ia64/sn/kernel/sn2/ptc_deadlock.S +++ b/arch/ia64/sn/kernel/sn2/ptc_deadlock.S @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #include <asm/types.h> @@ -11,7 +11,7 @@ #define DEADLOCKBIT SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_SHFT #define WRITECOUNTMASK SH_PIO_WRITE_STATUS_PENDING_WRITE_COUNT_MASK -#define ALIAS_OFFSET (SH1_PIO_WRITE_STATUS_0_ALIAS-SH1_PIO_WRITE_STATUS_0) +#define ALIAS_OFFSET 8 .global sn2_ptc_deadlock_recovery_core @@ -36,13 +36,15 @@ sn2_ptc_deadlock_recovery_core: extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address dep piowcphy=-1,piowcphy,63,1 movl mask=WRITECOUNTMASK + mov r8=r0 1: add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register - mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR - st8.rel [scr2]=scr1;; + ;; + ld8.acq scr1=[scr2];; 5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. + hint @pause and scr2=scr1,mask;; // mask of writecount bits cmp.ne p6,p0=zeroval,scr2 (p6) br.cond.sptk 5b @@ -57,6 +59,7 @@ sn2_ptc_deadlock_recovery_core: st8.rel [ptc0]=data0 // Write PTC0 & wait for completion. 5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + hint @pause and scr2=scr1,mask;; // mask of writecount bits cmp.ne p6,p0=zeroval,scr2 (p6) br.cond.sptk 5b;; @@ -67,6 +70,7 @@ sn2_ptc_deadlock_recovery_core: (p7) st8.rel [ptc1]=data1;; // Now write PTC1. 5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + hint @pause and scr2=scr1,mask;; // mask of writecount bits cmp.ne p6,p0=zeroval,scr2 (p6) br.cond.sptk 5b @@ -77,6 +81,7 @@ sn2_ptc_deadlock_recovery_core: srlz.i;; ////////////// END PHYSICAL MODE //////////////////// +(p8) add r8=1,r8 (p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. br.ret.sptk rp diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index 7af05a7ac74..0a4ee50c302 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #include <linux/init.h> @@ -20,6 +20,8 @@ #include <linux/module.h> #include <linux/bitops.h> #include <linux/nodemask.h> +#include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <asm/processor.h> #include <asm/irq.h> @@ -39,12 +41,120 @@ #include <asm/sn/nodepda.h> #include <asm/sn/rw_mmr.h> -void sn2_ptc_deadlock_recovery(volatile unsigned long *, unsigned long data0, - volatile unsigned long *, unsigned long data1); +DEFINE_PER_CPU(struct ptc_stats, ptcstats); +DECLARE_PER_CPU(struct ptc_stats, ptcstats); static __cacheline_aligned DEFINE_SPINLOCK(sn2_global_ptc_lock); -static unsigned long sn2_ptc_deadlock_count; +void sn2_ptc_deadlock_recovery(short *, short, int, volatile unsigned long *, unsigned long data0, + volatile unsigned long *, unsigned long data1); + +#ifdef DEBUG_PTC +/* + * ptctest: + * + * xyz - 3 digit hex number: + * x - Force PTC purges to use shub: + * 0 - no force + * 1 - force + * y - interupt enable + * 0 - disable interrupts + * 1 - leave interuupts enabled + * z - type of lock: + * 0 - global lock + * 1 - node local lock + * 2 - no lock + * + * Note: on shub1, only ptctest == 0 is supported. Don't try other values! + */ + +static unsigned int sn2_ptctest = 0; + +static int __init ptc_test(char *str) +{ + get_option(&str, &sn2_ptctest); + return 1; +} +__setup("ptctest=", ptc_test); + +static inline int ptc_lock(unsigned long *flagp) +{ + unsigned long opt = sn2_ptctest & 255; + + switch (opt) { + case 0x00: + spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); + break; + case 0x01: + spin_lock_irqsave(&sn_nodepda->ptc_lock, *flagp); + break; + case 0x02: + local_irq_save(*flagp); + break; + case 0x10: + spin_lock(&sn2_global_ptc_lock); + break; + case 0x11: + spin_lock(&sn_nodepda->ptc_lock); + break; + case 0x12: + break; + default: + BUG(); + } + return opt; +} + +static inline void ptc_unlock(unsigned long flags, int opt) +{ + switch (opt) { + case 0x00: + spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); + break; + case 0x01: + spin_unlock_irqrestore(&sn_nodepda->ptc_lock, flags); + break; + case 0x02: + local_irq_restore(flags); + break; + case 0x10: + spin_unlock(&sn2_global_ptc_lock); + break; + case 0x11: + spin_unlock(&sn_nodepda->ptc_lock); + break; + case 0x12: + break; + default: + BUG(); + } +} +#else + +#define sn2_ptctest 0 + +static inline int ptc_lock(unsigned long *flagp) +{ + spin_lock_irqsave(&sn2_global_ptc_lock, *flagp); + return 0; +} + +static inline void ptc_unlock(unsigned long flags, int opt) +{ + spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); +} +#endif + +struct ptc_stats { + unsigned long ptc_l; + unsigned long change_rid; + unsigned long shub_ptc_flushes; + unsigned long nodes_flushed; + unsigned long deadlocks; + unsigned long lock_itc_clocks; + unsigned long shub_itc_clocks; + unsigned long shub_itc_clocks_max; +}; static inline unsigned long wait_piowc(void) { @@ -89,9 +199,9 @@ void sn2_global_tlb_purge(unsigned long start, unsigned long end, unsigned long nbits) { - int i, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; + int i, opt, shub1, cnode, mynasid, cpu, lcpu = 0, nasid, flushed = 0; volatile unsigned long *ptc0, *ptc1; - unsigned long flags = 0, data0 = 0, data1 = 0; + unsigned long itc, itc2, flags, data0 = 0, data1 = 0; struct mm_struct *mm = current->active_mm; short nasids[MAX_NUMNODES], nix; nodemask_t nodes_flushed; @@ -114,16 +224,19 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end, start += (1UL << nbits); } while (start < end); ia64_srlz_i(); + __get_cpu_var(ptcstats).ptc_l++; preempt_enable(); return; } if (atomic_read(&mm->mm_users) == 1) { flush_tlb_mm(mm); + __get_cpu_var(ptcstats).change_rid++; preempt_enable(); return; } + itc = ia64_get_itc(); nix = 0; for_each_node_mask(cnode, nodes_flushed) nasids[nix++] = cnodeid_to_nasid(cnode); @@ -148,7 +261,12 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end, mynasid = get_nasid(); - spin_lock_irqsave(&sn2_global_ptc_lock, flags); + itc = ia64_get_itc(); + opt = ptc_lock(&flags); + itc2 = ia64_get_itc(); + __get_cpu_var(ptcstats).lock_itc_clocks += itc2 - itc; + __get_cpu_var(ptcstats).shub_ptc_flushes++; + __get_cpu_var(ptcstats).nodes_flushed += nix; do { if (shub1) @@ -157,7 +275,7 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end, data0 = (data0 & ~SH2_PTC_ADDR_MASK) | (start & SH2_PTC_ADDR_MASK); for (i = 0; i < nix; i++) { nasid = nasids[i]; - if (unlikely(nasid == mynasid)) { + if ((!(sn2_ptctest & 3)) && unlikely(nasid == mynasid)) { ia64_ptcga(start, nbits << 2); ia64_srlz_i(); } else { @@ -169,18 +287,22 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end, flushed = 1; } } - if (flushed && (wait_piowc() & - SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK)) { - sn2_ptc_deadlock_recovery(ptc0, data0, ptc1, data1); + (SH_PIO_WRITE_STATUS_WRITE_DEADLOCK_MASK))) { + sn2_ptc_deadlock_recovery(nasids, nix, mynasid, ptc0, data0, ptc1, data1); } start += (1UL << nbits); } while (start < end); - spin_unlock_irqrestore(&sn2_global_ptc_lock, flags); + itc2 = ia64_get_itc() - itc2; + __get_cpu_var(ptcstats).shub_itc_clocks += itc2; + if (itc2 > __get_cpu_var(ptcstats).shub_itc_clocks_max) + __get_cpu_var(ptcstats).shub_itc_clocks_max = itc2; + + ptc_unlock(flags, opt); preempt_enable(); } @@ -192,31 +314,29 @@ sn2_global_tlb_purge(unsigned long start, unsigned long end, * TLB flush transaction. The recovery sequence is somewhat tricky & is * coded in assembly language. */ -void sn2_ptc_deadlock_recovery(volatile unsigned long *ptc0, unsigned long data0, +void sn2_ptc_deadlock_recovery(short *nasids, short nix, int mynasid, volatile unsigned long *ptc0, unsigned long data0, volatile unsigned long *ptc1, unsigned long data1) { extern void sn2_ptc_deadlock_recovery_core(volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long, volatile unsigned long *, unsigned long); - int cnode, mycnode, nasid; - volatile unsigned long *piows; - volatile unsigned long zeroval; + short nasid, i; + unsigned long *piows, zeroval; - sn2_ptc_deadlock_count++; + __get_cpu_var(ptcstats).deadlocks++; - piows = pda->pio_write_status_addr; + piows = (unsigned long *) pda->pio_write_status_addr; zeroval = pda->pio_write_status_val; - mycnode = numa_node_id(); - - for_each_online_node(cnode) { - if (is_headless_node(cnode) || cnode == mycnode) + for (i=0; i < nix; i++) { + nasid = nasids[i]; + if (!(sn2_ptctest & 3) && nasid == mynasid) continue; - nasid = cnodeid_to_nasid(cnode); ptc0 = CHANGE_NASID(nasid, ptc0); if (ptc1) ptc1 = CHANGE_NASID(nasid, ptc1); sn2_ptc_deadlock_recovery_core(ptc0, data0, ptc1, data1, piows, zeroval); } + } /** @@ -293,3 +413,93 @@ void sn2_send_IPI(int cpuid, int vector, int delivery_mode, int redirect) sn_send_IPI_phys(nasid, physid, vector, delivery_mode); } + +#ifdef CONFIG_PROC_FS + +#define PTC_BASENAME "sgi_sn/ptc_statistics" + +static void *sn2_ptc_seq_start(struct seq_file *file, loff_t * offset) +{ + if (*offset < NR_CPUS) + return offset; + return NULL; +} + +static void *sn2_ptc_seq_next(struct seq_file *file, void *data, loff_t * offset) +{ + (*offset)++; + if (*offset < NR_CPUS) + return offset; + return NULL; +} + +static void sn2_ptc_seq_stop(struct seq_file *file, void *data) +{ +} + +static int sn2_ptc_seq_show(struct seq_file *file, void *data) +{ + struct ptc_stats *stat; + int cpu; + + cpu = *(loff_t *) data; + + if (!cpu) { + seq_printf(file, "# ptc_l change_rid shub_ptc_flushes shub_nodes_flushed deadlocks lock_nsec shub_nsec shub_nsec_max\n"); + seq_printf(file, "# ptctest %d\n", sn2_ptctest); + } + + if (cpu < NR_CPUS && cpu_online(cpu)) { + stat = &per_cpu(ptcstats, cpu); + seq_printf(file, "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld\n", cpu, stat->ptc_l, + stat->change_rid, stat->shub_ptc_flushes, stat->nodes_flushed, + stat->deadlocks, + 1000 * stat->lock_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks / per_cpu(cpu_info, cpu).cyc_per_usec, + 1000 * stat->shub_itc_clocks_max / per_cpu(cpu_info, cpu).cyc_per_usec); + } + + return 0; +} + +static struct seq_operations sn2_ptc_seq_ops = { + .start = sn2_ptc_seq_start, + .next = sn2_ptc_seq_next, + .stop = sn2_ptc_seq_stop, + .show = sn2_ptc_seq_show +}; + +int sn2_ptc_proc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &sn2_ptc_seq_ops); +} + +static struct file_operations proc_sn2_ptc_operations = { + .open = sn2_ptc_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static struct proc_dir_entry *proc_sn2_ptc; + +static int __init sn2_ptc_init(void) +{ + if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { + printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); + return -EINVAL; + } + proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations; + spin_lock_init(&sn2_global_ptc_lock); + return 0; +} + +static void __exit sn2_ptc_exit(void) +{ + remove_proc_entry(PTC_BASENAME, NULL); +} + +module_init(sn2_ptc_init); +module_exit(sn2_ptc_exit); +#endif /* CONFIG_PROC_FS */ + diff --git a/arch/ia64/sn/kernel/sn2/sn_hwperf.c b/arch/ia64/sn/kernel/sn2/sn_hwperf.c index 833e700fdac..0513aacac8c 100644 --- a/arch/ia64/sn/kernel/sn2/sn_hwperf.c +++ b/arch/ia64/sn/kernel/sn2/sn_hwperf.c @@ -36,7 +36,6 @@ #include <asm/topology.h> #include <asm/smp.h> #include <asm/semaphore.h> -#include <asm/segment.h> #include <asm/uaccess.h> #include <asm/sal.h> #include <asm/sn/io.h> @@ -59,7 +58,7 @@ static int sn_hwperf_enum_objects(int *nobj, struct sn_hwperf_object_info **ret) struct sn_hwperf_object_info *objbuf = NULL; if ((e = sn_hwperf_init()) < 0) { - printk("sn_hwperf_init failed: err %d\n", e); + printk(KERN_ERR "sn_hwperf_init failed: err %d\n", e); goto out; } @@ -111,7 +110,7 @@ static int sn_hwperf_geoid_to_cnode(char *location) if (sn_hwperf_location_to_bpos(location, &rack, &bay, &slot, &slab)) return -1; - for (cnode = 0; cnode < numionodes; cnode++) { + for_each_node(cnode) { geoid = cnodeid_get_geoid(cnode); module_id = geo_module(geoid); this_rack = MODULE_GET_RACK(module_id); @@ -124,11 +123,13 @@ static int sn_hwperf_geoid_to_cnode(char *location) } } - return cnode < numionodes ? cnode : -1; + return node_possible(cnode) ? cnode : -1; } static int sn_hwperf_obj_to_cnode(struct sn_hwperf_object_info * obj) { + if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) + BUG(); if (!obj->sn_hwp_this_part) return -1; return sn_hwperf_geoid_to_cnode(obj->location); @@ -174,31 +175,199 @@ static const char *sn_hwperf_get_slabname(struct sn_hwperf_object_info *obj, return slabname; } -static void print_pci_topology(struct seq_file *s, - struct sn_hwperf_object_info *obj, int *ordinal, - u64 rack, u64 bay, u64 slot, u64 slab) +static void print_pci_topology(struct seq_file *s) +{ + char *p; + size_t sz; + int e; + + for (sz = PAGE_SIZE; sz < 16 * PAGE_SIZE; sz += PAGE_SIZE) { + if (!(p = (char *)kmalloc(sz, GFP_KERNEL))) + break; + e = ia64_sn_ioif_get_pci_topology(__pa(p), sz); + if (e == SALRET_OK) + seq_puts(s, p); + kfree(p); + if (e == SALRET_OK || e == SALRET_NOT_IMPLEMENTED) + break; + } +} + +static inline int sn_hwperf_has_cpus(cnodeid_t node) +{ + return node_online(node) && nr_cpus_node(node); +} + +static inline int sn_hwperf_has_mem(cnodeid_t node) +{ + return node_online(node) && NODE_DATA(node)->node_present_pages; +} + +static struct sn_hwperf_object_info * +sn_hwperf_findobj_id(struct sn_hwperf_object_info *objbuf, + int nobj, int id) { - char *p1; - char *p2; - char *pg; - - if (!(pg = (char *)get_zeroed_page(GFP_KERNEL))) - return; /* ignore */ - if (ia64_sn_ioif_get_pci_topology(rack, bay, slot, slab, - __pa(pg), PAGE_SIZE) == SN_HWPERF_OP_OK) { - for (p1=pg; *p1 && p1 < pg + PAGE_SIZE;) { - if (!(p2 = strchr(p1, '\n'))) + int i; + struct sn_hwperf_object_info *p = objbuf; + + for (i=0; i < nobj; i++, p++) { + if (p->id == id) + return p; + } + + return NULL; + +} + +static int sn_hwperf_get_nearest_node_objdata(struct sn_hwperf_object_info *objbuf, + int nobj, cnodeid_t node, cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node) +{ + int e; + struct sn_hwperf_object_info *nodeobj = NULL; + struct sn_hwperf_object_info *op; + struct sn_hwperf_object_info *dest; + struct sn_hwperf_object_info *router; + struct sn_hwperf_port_info ptdata[16]; + int sz, i, j; + cnodeid_t c; + int found_mem = 0; + int found_cpu = 0; + + if (!node_possible(node)) + return -EINVAL; + + if (sn_hwperf_has_cpus(node)) { + if (near_cpu_node) + *near_cpu_node = node; + found_cpu++; + } + + if (sn_hwperf_has_mem(node)) { + if (near_mem_node) + *near_mem_node = node; + found_mem++; + } + + if (found_cpu && found_mem) + return 0; /* trivially successful */ + + /* find the argument node object */ + for (i=0, op=objbuf; i < nobj; i++, op++) { + if (!SN_HWPERF_IS_NODE(op) && !SN_HWPERF_IS_IONODE(op)) + continue; + if (node == sn_hwperf_obj_to_cnode(op)) { + nodeobj = op; + break; + } + } + if (!nodeobj) { + e = -ENOENT; + goto err; + } + + /* get it's interconnect topology */ + sz = op->ports * sizeof(struct sn_hwperf_port_info); + if (sz > sizeof(ptdata)) + BUG(); + e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, + SN_HWPERF_ENUM_PORTS, nodeobj->id, sz, + (u64)&ptdata, 0, 0, NULL); + if (e != SN_HWPERF_OP_OK) { + e = -EINVAL; + goto err; + } + + /* find nearest node with cpus and nearest memory */ + for (router=NULL, j=0; j < op->ports; j++) { + dest = sn_hwperf_findobj_id(objbuf, nobj, ptdata[j].conn_id); + if (!dest || SN_HWPERF_FOREIGN(dest) || + !SN_HWPERF_IS_NODE(dest) || SN_HWPERF_IS_IONODE(dest)) { + continue; + } + c = sn_hwperf_obj_to_cnode(dest); + if (!found_cpu && sn_hwperf_has_cpus(c)) { + if (near_cpu_node) + *near_cpu_node = c; + found_cpu++; + } + if (!found_mem && sn_hwperf_has_mem(c)) { + if (near_mem_node) + *near_mem_node = c; + found_mem++; + } + if (SN_HWPERF_IS_ROUTER(dest)) + router = dest; + } + + if (router && (!found_cpu || !found_mem)) { + /* search for a node connected to the same router */ + sz = router->ports * sizeof(struct sn_hwperf_port_info); + if (sz > sizeof(ptdata)) + BUG(); + e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, + SN_HWPERF_ENUM_PORTS, router->id, sz, + (u64)&ptdata, 0, 0, NULL); + if (e != SN_HWPERF_OP_OK) { + e = -EINVAL; + goto err; + } + for (j=0; j < router->ports; j++) { + dest = sn_hwperf_findobj_id(objbuf, nobj, + ptdata[j].conn_id); + if (!dest || dest->id == node || + SN_HWPERF_FOREIGN(dest) || + !SN_HWPERF_IS_NODE(dest) || + SN_HWPERF_IS_IONODE(dest)) { + continue; + } + c = sn_hwperf_obj_to_cnode(dest); + if (!found_cpu && sn_hwperf_has_cpus(c)) { + if (near_cpu_node) + *near_cpu_node = c; + found_cpu++; + } + if (!found_mem && sn_hwperf_has_mem(c)) { + if (near_mem_node) + *near_mem_node = c; + found_mem++; + } + if (found_cpu && found_mem) + break; + } + } + + if (!found_cpu || !found_mem) { + /* resort to _any_ node with CPUs and memory */ + for (i=0, op=objbuf; i < nobj; i++, op++) { + if (SN_HWPERF_FOREIGN(op) || + SN_HWPERF_IS_IONODE(op) || + !SN_HWPERF_IS_NODE(op)) { + continue; + } + c = sn_hwperf_obj_to_cnode(op); + if (!found_cpu && sn_hwperf_has_cpus(c)) { + if (near_cpu_node) + *near_cpu_node = c; + found_cpu++; + } + if (!found_mem && sn_hwperf_has_mem(c)) { + if (near_mem_node) + *near_mem_node = c; + found_mem++; + } + if (found_cpu && found_mem) break; - *p2 = '\0'; - seq_printf(s, "pcibus %d %s-%s\n", - *ordinal, obj->location, p1); - (*ordinal)++; - p1 = p2 + 1; } } - free_page((unsigned long)pg); + + if (!found_cpu || !found_mem) + e = -ENODATA; + +err: + return e; } + static int sn_topology_show(struct seq_file *s, void *d) { int sz; @@ -215,7 +384,6 @@ static int sn_topology_show(struct seq_file *s, void *d) struct sn_hwperf_object_info *p; struct sn_hwperf_object_info *obj = d; /* this object */ struct sn_hwperf_object_info *objs = s->private; /* all objects */ - int rack, bay, slot, slab; u8 shubtype; u8 system_size; u8 sharing_size; @@ -225,7 +393,6 @@ static int sn_topology_show(struct seq_file *s, void *d) u8 region_size; u16 nasid_mask; int nasid_msb; - int pci_bus_ordinal = 0; if (obj == objs) { seq_printf(s, "# sn_topology version 2\n"); @@ -253,6 +420,8 @@ static int sn_topology_show(struct seq_file *s, void *d) shubtype ? "shub2" : "shub1", (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift, system_size, sharing_size, coher, region_size); + + print_pci_topology(s); } if (SN_HWPERF_FOREIGN(obj)) { @@ -272,11 +441,24 @@ static int sn_topology_show(struct seq_file *s, void *d) if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) seq_putc(s, '\n'); else { + cnodeid_t near_mem = -1; + cnodeid_t near_cpu = -1; + seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal)); - for (i=0; i < numionodes; i++) { - seq_printf(s, i ? ":%d" : ", dist %d", - node_distance(ordinal, i)); + + if (sn_hwperf_get_nearest_node_objdata(objs, sn_hwperf_obj_cnt, + ordinal, &near_mem, &near_cpu) == 0) { + seq_printf(s, ", near_mem_nodeid %d, near_cpu_nodeid %d", + near_mem, near_cpu); + } + + if (!SN_HWPERF_IS_IONODE(obj)) { + for_each_online_node(i) { + seq_printf(s, i ? ":%d" : ", dist %d", + node_distance(ordinal, i)); + } } + seq_putc(s, '\n'); /* @@ -300,17 +482,6 @@ static int sn_topology_show(struct seq_file *s, void *d) seq_putc(s, '\n'); } } - - /* - * PCI busses attached to this node, if any - */ - if (sn_hwperf_location_to_bpos(obj->location, - &rack, &bay, &slot, &slab)) { - /* export pci bus info */ - print_pci_topology(s, obj, &pci_bus_ordinal, - rack, bay, slot, slab); - - } } if (obj->ports) { @@ -572,6 +743,8 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) if ((r = sn_hwperf_enum_objects(&nobj, &objs)) == 0) { memset(p, 0, a.sz); for (i = 0; i < nobj; i++) { + if (!SN_HWPERF_IS_NODE(objs + i)) + continue; node = sn_hwperf_obj_to_cnode(objs + i); for_each_online_cpu(j) { if (node != cpu_to_node(j)) @@ -598,7 +771,7 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) case SN_HWPERF_GET_NODE_NASID: if (a.sz != sizeof(u64) || - (node = a.arg) < 0 || node >= numionodes) { + (node = a.arg) < 0 || !node_possible(node)) { r = -EINVAL; goto error; } @@ -627,6 +800,14 @@ sn_hwperf_ioctl(struct inode *in, struct file *fp, u32 op, u64 arg) vfree(objs); goto error; } + + if (!SN_HWPERF_IS_NODE(objs + i) && + !SN_HWPERF_IS_IONODE(objs + i)) { + r = -ENOENT; + vfree(objs); + goto error; + } + *(u64 *)p = (u64)sn_hwperf_obj_to_cnode(objs + i); vfree(objs); } @@ -692,6 +873,7 @@ static int sn_hwperf_init(void) /* single threaded, once-only initialization */ down(&sn_hwperf_init_mutex); + if (sn_hwperf_salheap) { up(&sn_hwperf_init_mutex); return e; @@ -742,19 +924,6 @@ out: sn_hwperf_salheap = NULL; sn_hwperf_obj_cnt = 0; } - - if (!e) { - /* - * Register a dynamic misc device for ioctl. Platforms - * supporting hotplug will create /dev/sn_hwperf, else - * user can to look up the minor number in /proc/misc. - */ - if ((e = misc_register(&sn_hwperf_dev)) != 0) { - printk(KERN_ERR "sn_hwperf_init: misc register " - "for \"sn_hwperf\" failed, err %d\n", e); - } - } - up(&sn_hwperf_init_mutex); return e; } @@ -782,3 +951,41 @@ int sn_topology_release(struct inode *inode, struct file *file) vfree(seq->private); return seq_release(inode, file); } + +int sn_hwperf_get_nearest_node(cnodeid_t node, + cnodeid_t *near_mem_node, cnodeid_t *near_cpu_node) +{ + int e; + int nobj; + struct sn_hwperf_object_info *objbuf; + + if ((e = sn_hwperf_enum_objects(&nobj, &objbuf)) == 0) { + e = sn_hwperf_get_nearest_node_objdata(objbuf, nobj, + node, near_mem_node, near_cpu_node); + vfree(objbuf); + } + + return e; +} + +static int __devinit sn_hwperf_misc_register_init(void) +{ + int e; + + sn_hwperf_init(); + + /* + * Register a dynamic misc device for hwperf ioctls. Platforms + * supporting hotplug will create /dev/sn_hwperf, else user + * can to look up the minor number in /proc/misc. + */ + if ((e = misc_register(&sn_hwperf_dev)) != 0) { + printk(KERN_ERR "sn_hwperf_misc_register_init: failed to " + "register misc device for \"%s\"\n", sn_hwperf_dev.name); + } + + return e; +} + +device_initcall(sn_hwperf_misc_register_init); /* after misc_init() */ +EXPORT_SYMBOL(sn_hwperf_get_nearest_node); diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index 6a80fca807b..51bf82720d9 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #include <linux/config.h> #include <asm/uaccess.h> @@ -15,7 +15,7 @@ static int partition_id_show(struct seq_file *s, void *p) { - seq_printf(s, "%d\n", sn_local_partid()); + seq_printf(s, "%d\n", sn_partition_id); return 0; } diff --git a/arch/ia64/sn/kernel/sn2/timer_interrupt.c b/arch/ia64/sn/kernel/sn2/timer_interrupt.c index cde7375390b..adf5db2e2af 100644 --- a/arch/ia64/sn/kernel/sn2/timer_interrupt.c +++ b/arch/ia64/sn/kernel/sn2/timer_interrupt.c @@ -1,7 +1,7 @@ /* * * - * Copyright (c) 2003 Silicon Graphics, Inc. All Rights Reserved. + * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License @@ -50,14 +50,16 @@ void sn_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) LED_CPU_HEARTBEAT, LED_CPU_HEARTBEAT); } - if (enable_shub_wars_1_1()) { - /* Bugfix code for SHUB 1.1 */ - if (pda->pio_shub_war_cam_addr) - *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; + if (is_shub1()) { + if (enable_shub_wars_1_1()) { + /* Bugfix code for SHUB 1.1 */ + if (pda->pio_shub_war_cam_addr) + *pda->pio_shub_war_cam_addr = 0x8000000000000010UL; + } + if (pda->sn_lb_int_war_ticks == 0) + sn_lb_int_war_check(); + pda->sn_lb_int_war_ticks++; + if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL) + pda->sn_lb_int_war_ticks = 0; } - if (pda->sn_lb_int_war_ticks == 0) - sn_lb_int_war_check(); - pda->sn_lb_int_war_ticks++; - if (pda->sn_lb_int_war_ticks >= SN_LB_INT_WAR_INTERVAL) - pda->sn_lb_int_war_ticks = 0; } diff --git a/arch/ia64/sn/pci/Makefile b/arch/ia64/sn/pci/Makefile index 2f915bce25f..321576b1b42 100644 --- a/arch/ia64/sn/pci/Makefile +++ b/arch/ia64/sn/pci/Makefile @@ -7,4 +7,4 @@ # # Makefile for the sn pci general routines. -obj-y := pci_dma.o tioca_provider.o pcibr/ +obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/ diff --git a/arch/ia64/sn/pci/pcibr/pcibr_dma.c b/arch/ia64/sn/pci/pcibr/pcibr_dma.c index b058dc2a0b9..34093476e96 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_dma.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_dma.c @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2001-2005 Silicon Graphics, Inc. All rights reserved. */ #include <linux/types.h> @@ -215,8 +215,8 @@ void sn_dma_flush(uint64_t addr) int is_tio; int wid_num; int i, j; - int bwin; uint64_t flags; + uint64_t itte; struct hubdev_info *hubinfo; volatile struct sn_flush_device_list *p; struct sn_flush_nasid_entry *flush_nasid_list; @@ -233,31 +233,36 @@ void sn_dma_flush(uint64_t addr) if (!hubinfo) { BUG(); } - is_tio = (nasid & 1); - if (is_tio) { - wid_num = TIO_SWIN_WIDGETNUM(addr); - bwin = TIO_BWIN_WINDOWNUM(addr); - } else { - wid_num = SWIN_WIDGETNUM(addr); - bwin = BWIN_WINDOWNUM(addr); - } flush_nasid_list = &hubinfo->hdi_flush_nasid_list; if (flush_nasid_list->widget_p == NULL) return; - if (bwin > 0) { - uint64_t itte = flush_nasid_list->iio_itte[bwin]; - if (is_tio) { - wid_num = (itte >> TIO_ITTE_WIDGET_SHIFT) & - TIO_ITTE_WIDGET_MASK; - } else { - wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & - IIO_ITTE_WIDGET_MASK; - } + is_tio = (nasid & 1); + if (is_tio) { + int itte_index; + + if (TIO_HWIN(addr)) + itte_index = 0; + else if (TIO_BWIN_WINDOWNUM(addr)) + itte_index = TIO_BWIN_WINDOWNUM(addr); + else + itte_index = -1; + + if (itte_index >= 0) { + itte = flush_nasid_list->iio_itte[itte_index]; + if (! TIO_ITTE_VALID(itte)) + return; + wid_num = TIO_ITTE_WIDGET(itte); + } else + wid_num = TIO_SWIN_WIDGETNUM(addr); + } else { + if (BWIN_WINDOWNUM(addr)) { + itte = flush_nasid_list->iio_itte[BWIN_WINDOWNUM(addr)]; + wid_num = IIO_ITTE_WIDGET(itte); + } else + wid_num = SWIN_WIDGETNUM(addr); } - if (flush_nasid_list->widget_p == NULL) - return; if (flush_nasid_list->widget_p[wid_num] == NULL) return; p = &flush_nasid_list->widget_p[wid_num][0]; @@ -283,10 +288,16 @@ void sn_dma_flush(uint64_t addr) /* * For TIOCP use the Device(x) Write Request Buffer Flush Bridge * register since it ensures the data has entered the coherence - * domain, unlike PIC + * domain, unlike PIC. */ if (is_tio) { - uint32_t tio_id = REMOTE_HUB_L(nasid, TIO_NODE_ID); + /* + * Note: devices behind TIOCE should never be matched in the + * above code, and so the following code is PIC/CP centric. + * If CE ever needs the sn_dma_flush mechanism, we will have + * to account for that here and in tioce_bus_fixup(). + */ + uint32_t tio_id = HUB_L(TIO_IOSPACE_ADDR(nasid, TIO_NODE_ID)); uint32_t revnum = XWIDGET_PART_REV_NUM(tio_id); /* TIOCP BRINGUP WAR (PV907516): Don't write buffer flush reg */ @@ -306,7 +317,8 @@ void sn_dma_flush(uint64_t addr) *(volatile uint32_t *)(p->sfdl_force_int_addr) = 1; /* wait for the interrupt to come back. */ - while (*(p->sfdl_flush_addr) != 0x10f) ; + while (*(p->sfdl_flush_addr) != 0x10f) + cpu_relax(); /* okay, everything is synched up. */ spin_unlock_irqrestore((spinlock_t *)&p->sfdl_flush_lock, flags); diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c index b95e928636a..7b03b8084ff 100644 --- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c +++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c @@ -15,6 +15,7 @@ #include <asm/sn/pcibus_provider_defs.h> #include <asm/sn/pcidev.h> #include <asm/sn/sn_sal.h> +#include <asm/sn/sn2/sn_hwperf.h> #include "xtalk/xwidgetdev.h" #include "xtalk/hubdev.h" @@ -60,7 +61,7 @@ static int sal_pcibr_error_interrupt(struct pcibus_info *soft) ret_stuff.status = 0; ret_stuff.v0 = 0; - segment = 0; + segment = soft->pbi_buscommon.bs_persist_segment; busnum = soft->pbi_buscommon.bs_persist_busnum; SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_ERROR_INTERRUPT, @@ -88,6 +89,7 @@ void * pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) { int nasid, cnode, j; + cnodeid_t near_cnode; struct hubdev_info *hubdev_info; struct pcibus_info *soft; struct sn_flush_device_list *sn_flush_device_list; @@ -115,7 +117,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont /* * register the bridge's error interrupt handler */ - if (request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, + if (request_irq(SGI_PCIASIC_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, "PCIBR error", (void *)(soft))) { printk(KERN_WARNING "pcibr cannot allocate interrupt for error handler\n"); @@ -142,9 +144,12 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont j++, sn_flush_device_list++) { if (sn_flush_device_list->sfdl_slot == -1) continue; - if (sn_flush_device_list-> - sfdl_persistent_busnum == - soft->pbi_buscommon.bs_persist_busnum) + if ((sn_flush_device_list-> + sfdl_persistent_segment == + soft->pbi_buscommon.bs_persist_segment) && + (sn_flush_device_list-> + sfdl_persistent_busnum == + soft->pbi_buscommon.bs_persist_busnum)) sn_flush_device_list->sfdl_pcibus_info = soft; } @@ -158,12 +163,18 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont memset(soft->pbi_int_ate_resource.ate, 0, (soft->pbi_int_ate_size * sizeof(uint64_t))); - if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) - /* - * TIO PCI Bridge with no closest node information. - * FIXME: Find another way to determine the closest node - */ - controller->node = -1; + if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) { + /* TIO PCI Bridge: find nearest node with CPUs */ + int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode); + + if (e < 0) { + near_cnode = (cnodeid_t)-1; /* use any node */ + printk(KERN_WARNING "pcibr_bus_fixup: failed to find " + "near node with CPUs to TIO node %d, err=%d\n", + cnode, e); + } + controller->node = near_cnode; + } else controller->node = cnode; return soft; @@ -175,6 +186,9 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info) struct pcibus_info *pcibus_info; int bit = sn_irq_info->irq_int_bit; + if (! sn_irq_info->irq_bridge) + return; + pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; if (pcidev_info) { pcibus_info = @@ -184,7 +198,7 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info) } } -void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info) +void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info) { struct pcidev_info *pcidev_info; struct pcibus_info *pcibus_info; @@ -219,6 +233,8 @@ struct sn_pcibus_provider pcibr_provider = { .dma_map_consistent = pcibr_dma_map_consistent, .dma_unmap = pcibr_dma_unmap, .bus_fixup = pcibr_bus_fixup, + .force_interrupt = pcibr_force_interrupt, + .target_interrupt = pcibr_target_interrupt }; int diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c index 5d76a758146..ea09c12f025 100644 --- a/arch/ia64/sn/pci/tioca_provider.c +++ b/arch/ia64/sn/pci/tioca_provider.c @@ -559,7 +559,7 @@ tioca_error_intr_handler(int irq, void *arg, struct pt_regs *pt) ret_stuff.status = 0; ret_stuff.v0 = 0; - segment = 0; + segment = soft->ca_common.bs_persist_segment; busnum = soft->ca_common.bs_persist_busnum; SAL_CALL_NOLOCK(ret_stuff, @@ -622,7 +622,8 @@ tioca_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont nasid_to_cnodeid(tioca_common->ca_closest_nasid); tioca_common->ca_kernel_private = (uint64_t) tioca_kern; - bus = pci_find_bus(0, tioca_common->ca_common.bs_persist_busnum); + bus = pci_find_bus(tioca_common->ca_common.bs_persist_segment, + tioca_common->ca_common.bs_persist_busnum); BUG_ON(!bus); tioca_kern->ca_devices = &bus->devices; @@ -656,6 +657,8 @@ static struct sn_pcibus_provider tioca_pci_interfaces = { .dma_map_consistent = tioca_dma_map, .dma_unmap = tioca_dma_unmap, .bus_fixup = tioca_bus_fixup, + .force_interrupt = NULL, + .target_interrupt = NULL }; /** diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c new file mode 100644 index 00000000000..8e75db2b825 --- /dev/null +++ b/arch/ia64/sn/pci/tioce_provider.c @@ -0,0 +1,771 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2003-2005 Silicon Graphics, Inc. All Rights Reserved. + */ + +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/pci.h> +#include <asm/sn/sn_sal.h> +#include <asm/sn/addrs.h> +#include <asm/sn/pcidev.h> +#include <asm/sn/pcibus_provider_defs.h> +#include <asm/sn/tioce_provider.h> + +/** + * Bus address ranges for the 5 flavors of TIOCE DMA + */ + +#define TIOCE_D64_MIN 0x8000000000000000UL +#define TIOCE_D64_MAX 0xffffffffffffffffUL +#define TIOCE_D64_ADDR(a) ((a) >= TIOCE_D64_MIN) + +#define TIOCE_D32_MIN 0x0000000080000000UL +#define TIOCE_D32_MAX 0x00000000ffffffffUL +#define TIOCE_D32_ADDR(a) ((a) >= TIOCE_D32_MIN && (a) <= TIOCE_D32_MAX) + +#define TIOCE_M32_MIN 0x0000000000000000UL +#define TIOCE_M32_MAX 0x000000007fffffffUL +#define TIOCE_M32_ADDR(a) ((a) >= TIOCE_M32_MIN && (a) <= TIOCE_M32_MAX) + +#define TIOCE_M40_MIN 0x0000004000000000UL +#define TIOCE_M40_MAX 0x0000007fffffffffUL +#define TIOCE_M40_ADDR(a) ((a) >= TIOCE_M40_MIN && (a) <= TIOCE_M40_MAX) + +#define TIOCE_M40S_MIN 0x0000008000000000UL +#define TIOCE_M40S_MAX 0x000000ffffffffffUL +#define TIOCE_M40S_ADDR(a) ((a) >= TIOCE_M40S_MIN && (a) <= TIOCE_M40S_MAX) + +/* + * ATE manipulation macros. + */ + +#define ATE_PAGESHIFT(ps) (__ffs(ps)) +#define ATE_PAGEMASK(ps) ((ps)-1) + +#define ATE_PAGE(x, ps) ((x) >> ATE_PAGESHIFT(ps)) +#define ATE_NPAGES(start, len, pagesize) \ + (ATE_PAGE((start)+(len)-1, pagesize) - ATE_PAGE(start, pagesize) + 1) + +#define ATE_VALID(ate) ((ate) & (1UL << 63)) +#define ATE_MAKE(addr, ps) (((addr) & ~ATE_PAGEMASK(ps)) | (1UL << 63)) + +/* + * Flavors of ate-based mapping supported by tioce_alloc_map() + */ + +#define TIOCE_ATE_M32 1 +#define TIOCE_ATE_M40 2 +#define TIOCE_ATE_M40S 3 + +#define KB(x) ((x) << 10) +#define MB(x) ((x) << 20) +#define GB(x) ((x) << 30) + +/** + * tioce_dma_d64 - create a DMA mapping using 64-bit direct mode + * @ct_addr: system coretalk address + * + * Map @ct_addr into 64-bit CE bus space. No device context is necessary + * and no CE mapping are consumed. + * + * Bits 53:0 come from the coretalk address. The remaining bits are set as + * follows: + * + * 63 - must be 1 to indicate d64 mode to CE hardware + * 62 - barrier bit ... controlled with tioce_dma_barrier() + * 61 - 0 since this is not an MSI transaction + * 60:54 - reserved, MBZ + */ +static uint64_t +tioce_dma_d64(unsigned long ct_addr) +{ + uint64_t bus_addr; + + bus_addr = ct_addr | (1UL << 63); + + return bus_addr; +} + +/** + * pcidev_to_tioce - return misc ce related pointers given a pci_dev + * @pci_dev: pci device context + * @base: ptr to store struct tioce_mmr * for the CE holding this device + * @kernel: ptr to store struct tioce_kernel * for the CE holding this device + * @port: ptr to store the CE port number that this device is on + * + * Return pointers to various CE-related structures for the CE upstream of + * @pci_dev. + */ +static inline void +pcidev_to_tioce(struct pci_dev *pdev, struct tioce **base, + struct tioce_kernel **kernel, int *port) +{ + struct pcidev_info *pcidev_info; + struct tioce_common *ce_common; + struct tioce_kernel *ce_kernel; + + pcidev_info = SN_PCIDEV_INFO(pdev); + ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; + ce_kernel = (struct tioce_kernel *)ce_common->ce_kernel_private; + + if (base) + *base = (struct tioce *)ce_common->ce_pcibus.bs_base; + if (kernel) + *kernel = ce_kernel; + + /* + * we use port as a zero-based value internally, even though the + * documentation is 1-based. + */ + if (port) + *port = + (pdev->bus->number < ce_kernel->ce_port1_secondary) ? 0 : 1; +} + +/** + * tioce_alloc_map - Given a coretalk address, map it to pcie bus address + * space using one of the various ATE-based address modes. + * @ce_kern: tioce context + * @type: map mode to use + * @port: 0-based port that the requesting device is downstream of + * @ct_addr: the coretalk address to map + * @len: number of bytes to map + * + * Given the addressing type, set up various paramaters that define the + * ATE pool to use. Search for a contiguous block of entries to cover the + * length, and if enough resources exist, fill in the ATE's and construct a + * tioce_dmamap struct to track the mapping. + */ +static uint64_t +tioce_alloc_map(struct tioce_kernel *ce_kern, int type, int port, + uint64_t ct_addr, int len) +{ + int i; + int j; + int first; + int last; + int entries; + int nates; + int pagesize; + uint64_t *ate_shadow; + uint64_t *ate_reg; + uint64_t addr; + struct tioce *ce_mmr; + uint64_t bus_base; + struct tioce_dmamap *map; + + ce_mmr = (struct tioce *)ce_kern->ce_common->ce_pcibus.bs_base; + + switch (type) { + case TIOCE_ATE_M32: + /* + * The first 64 entries of the ate3240 pool are dedicated to + * super-page (TIOCE_ATE_M40S) mode. + */ + first = 64; + entries = TIOCE_NUM_M3240_ATES - 64; + ate_shadow = ce_kern->ce_ate3240_shadow; + ate_reg = ce_mmr->ce_ure_ate3240; + pagesize = ce_kern->ce_ate3240_pagesize; + bus_base = TIOCE_M32_MIN; + break; + case TIOCE_ATE_M40: + first = 0; + entries = TIOCE_NUM_M40_ATES; + ate_shadow = ce_kern->ce_ate40_shadow; + ate_reg = ce_mmr->ce_ure_ate40; + pagesize = MB(64); + bus_base = TIOCE_M40_MIN; + break; + case TIOCE_ATE_M40S: + /* + * ate3240 entries 0-31 are dedicated to port1 super-page + * mappings. ate3240 entries 32-63 are dedicated to port2. + */ + first = port * 32; + entries = 32; + ate_shadow = ce_kern->ce_ate3240_shadow; + ate_reg = ce_mmr->ce_ure_ate3240; + pagesize = GB(16); + bus_base = TIOCE_M40S_MIN; + break; + default: + return 0; + } + + nates = ATE_NPAGES(ct_addr, len, pagesize); + if (nates > entries) + return 0; + + last = first + entries - nates; + for (i = first; i <= last; i++) { + if (ATE_VALID(ate_shadow[i])) + continue; + + for (j = i; j < i + nates; j++) + if (ATE_VALID(ate_shadow[j])) + break; + + if (j >= i + nates) + break; + } + + if (i > last) + return 0; + + map = kcalloc(1, sizeof(struct tioce_dmamap), GFP_ATOMIC); + if (!map) + return 0; + + addr = ct_addr; + for (j = 0; j < nates; j++) { + uint64_t ate; + + ate = ATE_MAKE(addr, pagesize); + ate_shadow[i + j] = ate; + ate_reg[i + j] = ate; + addr += pagesize; + } + + map->refcnt = 1; + map->nbytes = nates * pagesize; + map->ct_start = ct_addr & ~ATE_PAGEMASK(pagesize); + map->pci_start = bus_base + (i * pagesize); + map->ate_hw = &ate_reg[i]; + map->ate_shadow = &ate_shadow[i]; + map->ate_count = nates; + + list_add(&map->ce_dmamap_list, &ce_kern->ce_dmamap_list); + + return (map->pci_start + (ct_addr - map->ct_start)); +} + +/** + * tioce_dma_d32 - create a DMA mapping using 32-bit direct mode + * @pdev: linux pci_dev representing the function + * @paddr: system physical address + * + * Map @paddr into 32-bit bus space of the CE associated with @pcidev_info. + */ +static uint64_t +tioce_dma_d32(struct pci_dev *pdev, uint64_t ct_addr) +{ + int dma_ok; + int port; + struct tioce *ce_mmr; + struct tioce_kernel *ce_kern; + uint64_t ct_upper; + uint64_t ct_lower; + dma_addr_t bus_addr; + + ct_upper = ct_addr & ~0x3fffffffUL; + ct_lower = ct_addr & 0x3fffffffUL; + + pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); + + if (ce_kern->ce_port[port].dirmap_refcnt == 0) { + volatile uint64_t tmp; + + ce_kern->ce_port[port].dirmap_shadow = ct_upper; + ce_mmr->ce_ure_dir_map[port] = ct_upper; + tmp = ce_mmr->ce_ure_dir_map[port]; + dma_ok = 1; + } else + dma_ok = (ce_kern->ce_port[port].dirmap_shadow == ct_upper); + + if (dma_ok) { + ce_kern->ce_port[port].dirmap_refcnt++; + bus_addr = TIOCE_D32_MIN + ct_lower; + } else + bus_addr = 0; + + return bus_addr; +} + +/** + * tioce_dma_barrier - swizzle a TIOCE bus address to include or exclude + * the barrier bit. + * @bus_addr: bus address to swizzle + * + * Given a TIOCE bus address, set the appropriate bit to indicate barrier + * attributes. + */ +static uint64_t +tioce_dma_barrier(uint64_t bus_addr, int on) +{ + uint64_t barrier_bit; + + /* barrier not supported in M40/M40S mode */ + if (TIOCE_M40_ADDR(bus_addr) || TIOCE_M40S_ADDR(bus_addr)) + return bus_addr; + + if (TIOCE_D64_ADDR(bus_addr)) + barrier_bit = (1UL << 62); + else /* must be m32 or d32 */ + barrier_bit = (1UL << 30); + + return (on) ? (bus_addr | barrier_bit) : (bus_addr & ~barrier_bit); +} + +/** + * tioce_dma_unmap - release CE mapping resources + * @pdev: linux pci_dev representing the function + * @bus_addr: bus address returned by an earlier tioce_dma_map + * @dir: mapping direction (unused) + * + * Locate mapping resources associated with @bus_addr and release them. + * For mappings created using the direct modes there are no resources + * to release. + */ +void +tioce_dma_unmap(struct pci_dev *pdev, dma_addr_t bus_addr, int dir) +{ + int i; + int port; + struct tioce_kernel *ce_kern; + struct tioce *ce_mmr; + unsigned long flags; + + bus_addr = tioce_dma_barrier(bus_addr, 0); + pcidev_to_tioce(pdev, &ce_mmr, &ce_kern, &port); + + /* nothing to do for D64 */ + + if (TIOCE_D64_ADDR(bus_addr)) + return; + + spin_lock_irqsave(&ce_kern->ce_lock, flags); + + if (TIOCE_D32_ADDR(bus_addr)) { + if (--ce_kern->ce_port[port].dirmap_refcnt == 0) { + ce_kern->ce_port[port].dirmap_shadow = 0; + ce_mmr->ce_ure_dir_map[port] = 0; + } + } else { + struct tioce_dmamap *map; + + list_for_each_entry(map, &ce_kern->ce_dmamap_list, + ce_dmamap_list) { + uint64_t last; + + last = map->pci_start + map->nbytes - 1; + if (bus_addr >= map->pci_start && bus_addr <= last) + break; + } + + if (&map->ce_dmamap_list == &ce_kern->ce_dmamap_list) { + printk(KERN_WARNING + "%s: %s - no map found for bus_addr 0x%lx\n", + __FUNCTION__, pci_name(pdev), bus_addr); + } else if (--map->refcnt == 0) { + for (i = 0; i < map->ate_count; i++) { + map->ate_shadow[i] = 0; + map->ate_hw[i] = 0; + } + + list_del(&map->ce_dmamap_list); + kfree(map); + } + } + + spin_unlock_irqrestore(&ce_kern->ce_lock, flags); +} + +/** + * tioce_do_dma_map - map pages for PCI DMA + * @pdev: linux pci_dev representing the function + * @paddr: host physical address to map + * @byte_count: bytes to map + * + * This is the main wrapper for mapping host physical pages to CE PCI space. + * The mapping mode used is based on the device's dma_mask. + */ +static uint64_t +tioce_do_dma_map(struct pci_dev *pdev, uint64_t paddr, size_t byte_count, + int barrier) +{ + unsigned long flags; + uint64_t ct_addr; + uint64_t mapaddr = 0; + struct tioce_kernel *ce_kern; + struct tioce_dmamap *map; + int port; + uint64_t dma_mask; + + dma_mask = (barrier) ? pdev->dev.coherent_dma_mask : pdev->dma_mask; + + /* cards must be able to address at least 31 bits */ + if (dma_mask < 0x7fffffffUL) + return 0; + + ct_addr = PHYS_TO_TIODMA(paddr); + + /* + * If the device can generate 64 bit addresses, create a D64 map. + * Since this should never fail, bypass the rest of the checks. + */ + if (dma_mask == ~0UL) { + mapaddr = tioce_dma_d64(ct_addr); + goto dma_map_done; + } + + pcidev_to_tioce(pdev, NULL, &ce_kern, &port); + + spin_lock_irqsave(&ce_kern->ce_lock, flags); + + /* + * D64 didn't work ... See if we have an existing map that covers + * this address range. Must account for devices dma_mask here since + * an existing map might have been done in a mode using more pci + * address bits than this device can support. + */ + list_for_each_entry(map, &ce_kern->ce_dmamap_list, ce_dmamap_list) { + uint64_t last; + + last = map->ct_start + map->nbytes - 1; + if (ct_addr >= map->ct_start && + ct_addr + byte_count - 1 <= last && + map->pci_start <= dma_mask) { + map->refcnt++; + mapaddr = map->pci_start + (ct_addr - map->ct_start); + break; + } + } + + /* + * If we don't have a map yet, and the card can generate 40 + * bit addresses, try the M40/M40S modes. Note these modes do not + * support a barrier bit, so if we need a consistent map these + * won't work. + */ + if (!mapaddr && !barrier && dma_mask >= 0xffffffffffUL) { + /* + * We have two options for 40-bit mappings: 16GB "super" ATE's + * and 64MB "regular" ATE's. We'll try both if needed for a + * given mapping but which one we try first depends on the + * size. For requests >64MB, prefer to use a super page with + * regular as the fallback. Otherwise, try in the reverse order. + */ + + if (byte_count > MB(64)) { + mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, + port, ct_addr, byte_count); + if (!mapaddr) + mapaddr = + tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, + ct_addr, byte_count); + } else { + mapaddr = tioce_alloc_map(ce_kern, TIOCE_ATE_M40, -1, + ct_addr, byte_count); + if (!mapaddr) + mapaddr = + tioce_alloc_map(ce_kern, TIOCE_ATE_M40S, + port, ct_addr, byte_count); + } + } + + /* + * 32-bit direct is the next mode to try + */ + if (!mapaddr && dma_mask >= 0xffffffffUL) + mapaddr = tioce_dma_d32(pdev, ct_addr); + + /* + * Last resort, try 32-bit ATE-based map. + */ + if (!mapaddr) + mapaddr = + tioce_alloc_map(ce_kern, TIOCE_ATE_M32, -1, ct_addr, + byte_count); + + spin_unlock_irqrestore(&ce_kern->ce_lock, flags); + +dma_map_done: + if (mapaddr & barrier) + mapaddr = tioce_dma_barrier(mapaddr, 1); + + return mapaddr; +} + +/** + * tioce_dma - standard pci dma map interface + * @pdev: pci device requesting the map + * @paddr: system physical address to map into pci space + * @byte_count: # bytes to map + * + * Simply call tioce_do_dma_map() to create a map with the barrier bit clear + * in the address. + */ +static uint64_t +tioce_dma(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +{ + return tioce_do_dma_map(pdev, paddr, byte_count, 0); +} + +/** + * tioce_dma_consistent - consistent pci dma map interface + * @pdev: pci device requesting the map + * @paddr: system physical address to map into pci space + * @byte_count: # bytes to map + * + * Simply call tioce_do_dma_map() to create a map with the barrier bit set + * in the address. + */ static uint64_t +tioce_dma_consistent(struct pci_dev *pdev, uint64_t paddr, size_t byte_count) +{ + return tioce_do_dma_map(pdev, paddr, byte_count, 1); +} + +/** + * tioce_error_intr_handler - SGI TIO CE error interrupt handler + * @irq: unused + * @arg: pointer to tioce_common struct for the given CE + * @pt: unused + * + * Handle a CE error interrupt. Simply a wrapper around a SAL call which + * defers processing to the SGI prom. + */ static irqreturn_t +tioce_error_intr_handler(int irq, void *arg, struct pt_regs *pt) +{ + struct tioce_common *soft = arg; + struct ia64_sal_retval ret_stuff; + ret_stuff.status = 0; + ret_stuff.v0 = 0; + + SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_ERROR_INTERRUPT, + soft->ce_pcibus.bs_persist_segment, + soft->ce_pcibus.bs_persist_busnum, 0, 0, 0, 0, 0); + + return IRQ_HANDLED; +} + +/** + * tioce_kern_init - init kernel structures related to a given TIOCE + * @tioce_common: ptr to a cached tioce_common struct that originated in prom + */ static struct tioce_kernel * +tioce_kern_init(struct tioce_common *tioce_common) +{ + int i; + uint32_t tmp; + struct tioce *tioce_mmr; + struct tioce_kernel *tioce_kern; + + tioce_kern = kcalloc(1, sizeof(struct tioce_kernel), GFP_KERNEL); + if (!tioce_kern) { + return NULL; + } + + tioce_kern->ce_common = tioce_common; + spin_lock_init(&tioce_kern->ce_lock); + INIT_LIST_HEAD(&tioce_kern->ce_dmamap_list); + tioce_common->ce_kernel_private = (uint64_t) tioce_kern; + + /* + * Determine the secondary bus number of the port2 logical PPB. + * This is used to decide whether a given pci device resides on + * port1 or port2. Note: We don't have enough plumbing set up + * here to use pci_read_config_xxx() so use the raw_pci_ops vector. + */ + + raw_pci_ops->read(tioce_common->ce_pcibus.bs_persist_segment, + tioce_common->ce_pcibus.bs_persist_busnum, + PCI_DEVFN(2, 0), PCI_SECONDARY_BUS, 1, &tmp); + tioce_kern->ce_port1_secondary = (uint8_t) tmp; + + /* + * Set PMU pagesize to the largest size available, and zero out + * the ate's. + */ + + tioce_mmr = (struct tioce *)tioce_common->ce_pcibus.bs_base; + tioce_mmr->ce_ure_page_map &= ~CE_URE_PAGESIZE_MASK; + tioce_mmr->ce_ure_page_map |= CE_URE_256K_PAGESIZE; + tioce_kern->ce_ate3240_pagesize = KB(256); + + for (i = 0; i < TIOCE_NUM_M40_ATES; i++) { + tioce_kern->ce_ate40_shadow[i] = 0; + tioce_mmr->ce_ure_ate40[i] = 0; + } + + for (i = 0; i < TIOCE_NUM_M3240_ATES; i++) { + tioce_kern->ce_ate3240_shadow[i] = 0; + tioce_mmr->ce_ure_ate3240[i] = 0; + } + + return tioce_kern; +} + +/** + * tioce_force_interrupt - implement altix force_interrupt() backend for CE + * @sn_irq_info: sn asic irq that we need an interrupt generated for + * + * Given an sn_irq_info struct, set the proper bit in ce_adm_force_int to + * force a secondary interrupt to be generated. This is to work around an + * asic issue where there is a small window of opportunity for a legacy device + * interrupt to be lost. + */ +static void +tioce_force_interrupt(struct sn_irq_info *sn_irq_info) +{ + struct pcidev_info *pcidev_info; + struct tioce_common *ce_common; + struct tioce *ce_mmr; + uint64_t force_int_val; + + if (!sn_irq_info->irq_bridge) + return; + + if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_TIOCE) + return; + + pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + if (!pcidev_info) + return; + + ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; + ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; + + /* + * irq_int_bit is originally set up by prom, and holds the interrupt + * bit shift (not mask) as defined by the bit definitions in the + * ce_adm_int mmr. These shifts are not the same for the + * ce_adm_force_int register, so do an explicit mapping here to make + * things clearer. + */ + + switch (sn_irq_info->irq_int_bit) { + case CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT; + break; + case CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT; + break; + case CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT; + break; + case CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT; + break; + case CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT; + break; + case CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT; + break; + case CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT; + break; + case CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT: + force_int_val = 1UL << CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT; + break; + default: + return; + } + ce_mmr->ce_adm_force_int = force_int_val; +} + +/** + * tioce_target_interrupt - implement set_irq_affinity for tioce resident + * functions. Note: only applies to line interrupts, not MSI's. + * + * @sn_irq_info: SN IRQ context + * + * Given an sn_irq_info, set the associated CE device's interrupt destination + * register. Since the interrupt destination registers are on a per-ce-slot + * basis, this will retarget line interrupts for all functions downstream of + * the slot. + */ +static void +tioce_target_interrupt(struct sn_irq_info *sn_irq_info) +{ + struct pcidev_info *pcidev_info; + struct tioce_common *ce_common; + struct tioce *ce_mmr; + int bit; + + pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; + if (!pcidev_info) + return; + + ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info; + ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base; + + bit = sn_irq_info->irq_int_bit; + + ce_mmr->ce_adm_int_mask |= (1UL << bit); + ce_mmr->ce_adm_int_dest[bit] = + ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) | + sn_irq_info->irq_xtalkaddr; + ce_mmr->ce_adm_int_mask &= ~(1UL << bit); + + tioce_force_interrupt(sn_irq_info); +} + +/** + * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus + * @prom_bussoft: Common prom/kernel struct representing the bus + * + * Replicates the tioce_common pointed to by @prom_bussoft in kernel + * space. Allocates and initializes a kernel-only area for a given CE, + * and sets up an irq for handling CE error interrupts. + * + * On successful setup, returns the kernel version of tioce_common back to + * the caller. + */ +static void * +tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller) +{ + struct tioce_common *tioce_common; + + /* + * Allocate kernel bus soft and copy from prom. + */ + + tioce_common = kcalloc(1, sizeof(struct tioce_common), GFP_KERNEL); + if (!tioce_common) + return NULL; + + memcpy(tioce_common, prom_bussoft, sizeof(struct tioce_common)); + tioce_common->ce_pcibus.bs_base |= __IA64_UNCACHED_OFFSET; + + if (tioce_kern_init(tioce_common) == NULL) { + kfree(tioce_common); + return NULL; + } + + if (request_irq(SGI_PCIASIC_ERROR, + tioce_error_intr_handler, + SA_SHIRQ, "TIOCE error", (void *)tioce_common)) + printk(KERN_WARNING + "%s: Unable to get irq %d. " + "Error interrupts won't be routed for " + "TIOCE bus %04x:%02x\n", + __FUNCTION__, SGI_PCIASIC_ERROR, + tioce_common->ce_pcibus.bs_persist_segment, + tioce_common->ce_pcibus.bs_persist_busnum); + + return tioce_common; +} + +static struct sn_pcibus_provider tioce_pci_interfaces = { + .dma_map = tioce_dma, + .dma_map_consistent = tioce_dma_consistent, + .dma_unmap = tioce_dma_unmap, + .bus_fixup = tioce_bus_fixup, + .force_interrupt = tioce_force_interrupt, + .target_interrupt = tioce_target_interrupt +}; + +/** + * tioce_init_provider - init SN PCI provider ops for TIO CE + */ +int +tioce_init_provider(void) +{ + sn_pci_provider[PCIIO_ASIC_TYPE_TIOCE] = &tioce_pci_interfaces; + return 0; +} diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 117f183f0b4..8520df9cee6 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -71,21 +71,31 @@ config M5206e help Motorola ColdFire 5206e processor support. +config M523x + bool "MCF523x" + help + Freescale Coldfire 5230/1/2/4/5 processor support + config M5249 bool "MCF5249" help Motorola ColdFire 5249 processor support. -config M527x - bool "MCF527x" +config M5271 + bool "MCF5271" help - Freescale (Motorola) ColdFire 5270/5271/5274/5275 processor support. + Freescale (Motorola) ColdFire 5270/5271 processor support. config M5272 bool "MCF5272" help Motorola ColdFire 5272 processor support. +config M5275 + bool "MCF5275" + help + Freescale (Motorola) ColdFire 5274/5275 processor support. + config M528x bool "MCF528x" help @@ -103,9 +113,14 @@ config M5407 endchoice +config M527x + bool + depends on (M5271 || M5275) + default y + config COLDFIRE bool - depends on (M5206 || M5206e || M5249 || M527x || M5272 || M528x || M5307 || M5407) + depends on (M5206 || M5206e || M523x || M5249 || M527x || M5272 || M528x || M5307 || M5407) default y choice @@ -183,6 +198,11 @@ config CLOCK_60MHz help Select a 60MHz CPU clock frequency. +config CLOCK_62_5MHz + bool "62.5MHz" + help + Select a 62.5MHz CPU clock frequency. + config CLOCK_64MHz bool "64MHz" help @@ -302,6 +322,12 @@ config ELITE help Support for the Motorola M5206eLITE board. +config M5235EVB + bool "Freescale M5235EVB support" + depends on M523x + help + Support for the Freescale M5235EVB board. + config M5249C3 bool "Motorola M5249C3 board support" depends on M5249 @@ -310,13 +336,13 @@ config M5249C3 config M5271EVB bool "Freescale (Motorola) M5271EVB board support" - depends on M527x + depends on M5271 help Support for the Freescale (Motorola) M5271EVB board. config M5275EVB bool "Freescale (Motorola) M5275EVB board support" - depends on M527x + depends on M5275 help Support for the Freescale (Motorola) M5275EVB board. @@ -343,6 +369,12 @@ config COBRA5282 depends on M528x help Support for the senTec COBRA5282 board. + +config SOM5282EM + bool "EMAC.Inc SOM5282EM board support" + depends on M528x + help + Support for the EMAC.Inc SOM5282EM module. config ARN5307 bool "Arnewsh 5307 board support" @@ -410,6 +442,12 @@ config CPU16B help Support for the SNEHA CPU16B board. +config MOD5272 + bool "Netburner MOD-5272 board support" + depends on M5272 + help + Support for the Netburner MOD-5272 board. + config ROMFS_FROM_ROM bool " ROMFS image not RAM resident" depends on (NETtel || SNAPGEAR) @@ -430,7 +468,7 @@ config ARNEWSH config MOTOROLA bool default y - depends on (M5206eC3 || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) + depends on (M5206eC3 || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5407C3) config HW_FEITH bool @@ -441,6 +479,11 @@ config senTec bool default y depends on (COBRA5272 || COBRA5282) + +config EMAC_INC + bool + default y + depends on (SOM5282EM) config SNEHA bool @@ -455,6 +498,15 @@ config LARGE_ALLOCS a lot of RAM, and you need to able to allocate very large contiguous chunks. If unsure, say N. +config 4KSTACKS + bool "Use 4Kb for kernel stacks instead of 8Kb" + default y + help + If you say Y here the kernel will use a 4Kb stacksize for the + kernel stack attached to each process/thread. This facilitates + running more threads on a system and also reduces the pressure + on the VM subsystem for higher order allocations. + choice prompt "RAM size" default AUTO diff --git a/arch/m68knommu/Makefile b/arch/m68knommu/Makefile index a254aa9d499..97022ed0da3 100644 --- a/arch/m68knommu/Makefile +++ b/arch/m68knommu/Makefile @@ -14,6 +14,7 @@ platform-$(CONFIG_M68VZ328) := 68VZ328 platform-$(CONFIG_M68360) := 68360 platform-$(CONFIG_M5206) := 5206 platform-$(CONFIG_M5206e) := 5206e +platform-$(CONFIG_M523x) := 523x platform-$(CONFIG_M5249) := 5249 platform-$(CONFIG_M527x) := 527x platform-$(CONFIG_M5272) := 5272 @@ -29,6 +30,7 @@ board-$(CONFIG_UCQUICC) := uCquicc board-$(CONFIG_DRAGEN2) := de2 board-$(CONFIG_ARNEWSH) := ARNEWSH board-$(CONFIG_MOTOROLA) := MOTOROLA +board-$(CONFIG_M5235EVB) := M5235EVB board-$(CONFIG_M5271EVB) := M5271EVB board-$(CONFIG_M5275EVB) := M5275EVB board-$(CONFIG_M5282EVB) := M5282EVB @@ -39,6 +41,7 @@ board-$(CONFIG_SECUREEDGEMP3) := MP3 board-$(CONFIG_CLEOPATRA) := CLEOPATRA board-$(CONFIG_senTec) := senTec board-$(CONFIG_SNEHA) := SNEHA +board-$(CONFIG_MOD5272) := MOD5272 BOARD := $(board-y) model-$(CONFIG_RAMKERNEL) := ram @@ -53,6 +56,7 @@ MODEL := $(model-y) # cpuclass-$(CONFIG_M5206) := 5307 cpuclass-$(CONFIG_M5206e) := 5307 +cpuclass-$(CONFIG_M523x) := 5307 cpuclass-$(CONFIG_M5249) := 5307 cpuclass-$(CONFIG_M527x) := 5307 cpuclass-$(CONFIG_M5272) := 5307 @@ -76,6 +80,7 @@ export PLATFORM BOARD MODEL CPUCLASS # cflags-$(CONFIG_M5206) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M5206e) := -m5200 -Wa,-S -Wa,-m5200 +cflags-$(CONFIG_M523x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5249) := -m5200 -Wa,-S -Wa,-m5200 cflags-$(CONFIG_M527x) := -m5307 -Wa,-S -Wa,-m5307 cflags-$(CONFIG_M5272) := -m5307 -Wa,-S -Wa,-m5307 diff --git a/arch/m68knommu/defconfig b/arch/m68knommu/defconfig index e4bd31be966..87f2d6587c5 100644 --- a/arch/m68knommu/defconfig +++ b/arch/m68knommu/defconfig @@ -1,24 +1,48 @@ # # Automatically generated make config: don't edit +# Linux kernel version: 2.6.13-uc0 +# Wed Aug 31 15:03:26 2005 # +CONFIG_M68KNOMMU=y # CONFIG_MMU is not set # CONFIG_FPU is not set CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y # CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_GENERIC_CALIBRATE_DELAY=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # -# CONFIG_SYSVIPC is not set +CONFIG_LOCALVERSION="" +# CONFIG_POSIX_MQUEUE is not set # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_AUDIT is not set +# CONFIG_HOTPLUG is not set +# CONFIG_KOBJECT_UEVENT is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +# CONFIG_KALLSYMS is not set +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_BASE_FULL=y +# CONFIG_FUTEX is not set +# CONFIG_EPOLL is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_CC_ALIGN_FUNCTIONS=0 +CONFIG_CC_ALIGN_LABELS=0 +CONFIG_CC_ALIGN_LOOPS=0 +CONFIG_CC_ALIGN_JUMPS=0 +CONFIG_BASE_SMALL=0 # # Loadable module support @@ -34,9 +58,11 @@ CONFIG_LOG_BUF_SHIFT=14 # CONFIG_M68360 is not set # CONFIG_M5206 is not set # CONFIG_M5206e is not set +# CONFIG_M523x is not set # CONFIG_M5249 is not set -# CONFIG_M527x is not set +# CONFIG_M5271 is not set CONFIG_M5272=y +# CONFIG_M5275 is not set # CONFIG_M528x is not set # CONFIG_M5307 is not set # CONFIG_M5407 is not set @@ -54,6 +80,8 @@ CONFIG_COLDFIRE=y # CONFIG_CLOCK_50MHz is not set # CONFIG_CLOCK_54MHz is not set # CONFIG_CLOCK_60MHz is not set +# CONFIG_CLOCK_62_5MHz is not set +# CONFIG_CLOCK_64MHz is not set CONFIG_CLOCK_66MHz=y # CONFIG_CLOCK_70MHz is not set # CONFIG_CLOCK_100MHz is not set @@ -65,13 +93,19 @@ CONFIG_CLOCK_66MHz=y # Platform # CONFIG_M5272C3=y +# CONFIG_COBRA5272 is not set +# CONFIG_CANCam is not set +# CONFIG_SCALES is not set # CONFIG_NETtel is not set +# CONFIG_CPU16B is not set +# CONFIG_MOD5272 is not set CONFIG_MOTOROLA=y # CONFIG_LARGE_ALLOCS is not set -# CONFIG_RAMAUTO is not set +CONFIG_4KSTACKS=y +CONFIG_RAMAUTO=y # CONFIG_RAM4MB is not set # CONFIG_RAM8MB is not set -CONFIG_RAM16MB=y +# CONFIG_RAM16MB is not set # CONFIG_RAM32MB is not set CONFIG_RAMAUTOBIT=y # CONFIG_RAM8BIT is not set @@ -79,20 +113,34 @@ CONFIG_RAMAUTOBIT=y # CONFIG_RAM32BIT is not set CONFIG_RAMKERNEL=y # CONFIG_ROMKERNEL is not set -# CONFIG_HIMEMKERNEL is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y # # Bus options (PCI, PCMCIA, EISA, MCA, ISA) # # CONFIG_PCI is not set -# CONFIG_HOTPLUG is not set + +# +# PCCARD (PCMCIA/CardBus) support +# +# CONFIG_PCCARD is not set + +# +# PCI Hotplug Support +# # # Executable file formats # -CONFIG_KCORE_AOUT=y CONFIG_BINFMT_FLAT=y # CONFIG_BINFMT_ZFLAT is not set +# CONFIG_BINFMT_SHARED_FLAT is not set +# CONFIG_BINFMT_MISC is not set # # Power management options @@ -100,12 +148,82 @@ CONFIG_BINFMT_FLAT=y # CONFIG_PM is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set + +# # Memory Technology Devices (MTD) # CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set -CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set # CONFIG_MTD_CMDLINE_PARTS is not set @@ -116,35 +234,50 @@ CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set +# CONFIG_INFTL is not set # # RAM/ROM/Flash chip drivers # # CONFIG_MTD_CFI is not set # CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set CONFIG_MTD_RAM=y # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set -# CONFIG_MTD_OBSOLETE_CHIPS is not set # # Mapping drivers for chip access # +# CONFIG_MTD_COMPLEX_MAPPINGS is not set CONFIG_MTD_UCLINUX=y +# CONFIG_MTD_SNAPGEARuC is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers # # CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLKMTD is not set +# CONFIG_MTD_BLOCK2MTD is not set # # Disk-On-Chip Device Drivers # -# CONFIG_MTD_DOC1000 is not set # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set # # NAND Flash Device Drivers @@ -159,21 +292,32 @@ CONFIG_MTD_UCLINUX=y # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices # # CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_COW_COMMON is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set -# CONFIG_BLK_DEV_BLKMEM is not set +CONFIG_INITRAMFS_SOURCE="" +# CONFIG_CDROM_PKTCDVD is not set # -# ATA/IDE/MFM/RLL support +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_AS is not set +# CONFIG_IOSCHED_DEADLINE is not set +# CONFIG_IOSCHED_CFQ is not set +# CONFIG_ATA_OVER_ETH is not set + +# +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set @@ -190,249 +334,230 @@ CONFIG_BLK_DEV_RAM_SIZE=4096 # # Fusion MPT device support # +# CONFIG_FUSION is not set # -# I2O device support -# - -# -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_XFRM_USER is not set -# CONFIG_IPV6 is not set - -# -# SCTP Configuration (EXPERIMENTAL) +# IEEE 1394 (FireWire) support # -CONFIG_IPV6_SCTP__=y -# CONFIG_IP_SCTP is not set -# CONFIG_ATM is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_HW_FLOWCONTROL is not set # -# QoS and/or fair queueing +# I2O device support # -# CONFIG_NET_SCHED is not set # -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y # CONFIG_MII is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NE2000 is not set +# CONFIG_NET_PCI is not set CONFIG_FEC=y +# CONFIG_FEC2 is not set # # Ethernet (1000 Mbit) # + +# +# Ethernet (10000 Mbit) +# + +# +# Token Ring devices +# + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set CONFIG_PPP=y # CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set # CONFIG_PPP_ASYNC is not set # CONFIG_PPP_SYNC_TTY is not set # CONFIG_PPP_DEFLATE is not set # CONFIG_PPP_BSDCOMP is not set # CONFIG_PPPOE is not set # CONFIG_SLIP is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # -# Wireless LAN (non-hamradio) +# ISDN subsystem # -# CONFIG_NET_RADIO is not set +# CONFIG_ISDN is not set # -# Token Ring devices (depends on LLC=y) +# Telephony Support # -# CONFIG_SHAPER is not set +# CONFIG_PHONE is not set # -# Wan interfaces +# Input device support # -# CONFIG_WAN is not set +# CONFIG_INPUT is not set # -# Amateur Radio support +# Hardware I/O ports # -# CONFIG_HAMRADIO is not set +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set # -# IrDA (infrared) support +# Character devices # -# CONFIG_IRDA is not set +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_LEDMAN is not set +# CONFIG_RESETSWITCH is not set # -# ISDN subsystem +# Serial drivers # -# CONFIG_ISDN_BOOL is not set +# CONFIG_SERIAL_8250 is not set # -# Telephony Support +# Non-8250 serial port support # -# CONFIG_PHONE is not set +CONFIG_SERIAL_COLDFIRE=y +# CONFIG_UNIX98_PTYS is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 # -# Input device support +# IPMI # -CONFIG_INPUT=y +# CONFIG_IPMI_HANDLER is not set # -# Userland interfaces +# Watchdog Cards # -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_TSDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set +# CONFIG_WATCHDOG is not set +# CONFIG_MCFWATCHDOG is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set # -# Input I/O drivers +# Ftape, the floppy tape device driver # -# CONFIG_GAMEPORT is not set -CONFIG_SOUND_GAMEPORT=y -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set +# CONFIG_RAW_DRIVER is not set # -# Input Device Drivers +# TPM devices # -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set +# CONFIG_MCF_QSPI is not set +# CONFIG_M41T11M6 is not set # -# Character devices +# I2C support # -# CONFIG_VT is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_RESETSWITCH is not set +# CONFIG_I2C is not set +# CONFIG_I2C_SENSOR is not set # -# Serial drivers +# Dallas's 1-wire bus # -# CONFIG_SERIAL_8250 is not set +# CONFIG_W1 is not set # -# Non-8250 serial port support +# Hardware Monitoring support # -CONFIG_SERIAL_COLDFIRE=y -# CONFIG_UNIX98_PTYS is not set +# CONFIG_HWMON is not set # -# I2C support +# Misc devices # -# CONFIG_I2C is not set # -# I2C Hardware Sensors Mainboard support +# Multimedia devices # +# CONFIG_VIDEO_DEV is not set # -# I2C Hardware Sensors Chip support +# Digital Video Broadcasting Devices # +# CONFIG_DVB is not set # -# Mice +# Graphics support # -# CONFIG_BUSMOUSE is not set -# CONFIG_QIC02_TAPE is not set +# CONFIG_FB is not set # -# IPMI +# SPI support # -# CONFIG_IPMI_HANDLER is not set +# CONFIG_SPI is not set # -# Watchdog Cards +# Sound # -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_GEN_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set +# CONFIG_SOUND is not set # -# Ftape, the floppy tape device driver +# USB support # -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set +# CONFIG_USB_ARCH_HAS_HCD is not set +# CONFIG_USB_ARCH_HAS_OHCI is not set # -# Multimedia devices +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# MMC/SD Card support +# +# CONFIG_MMC is not set + +# +# InfiniBand support +# + +# +# SN Devices # -# CONFIG_VIDEO_DEV is not set # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set + +# +# XFS support +# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y +CONFIG_MAGIC_ROM_PTR=y +# CONFIG_INOTIFY is not set # CONFIG_QUOTA is not set +# CONFIG_DNOTIFY is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set @@ -445,15 +570,17 @@ CONFIG_ROMFS_FS=y # # DOS/FAT/NT Filesystems # -# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set +CONFIG_SYSFS=y # CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -462,6 +589,7 @@ CONFIG_RAMFS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set @@ -479,12 +607,10 @@ CONFIG_RAMFS=y # # CONFIG_NFS_FS is not set # CONFIG_NFSD is not set -# CONFIG_EXPORTFS is not set # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -494,30 +620,19 @@ CONFIG_RAMFS=y CONFIG_MSDOS_PARTITION=y # -# Graphics support -# -# CONFIG_FB is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# - -# -# Bluetooth support +# Native Language Support # -# CONFIG_BT is not set +# CONFIG_NLS is not set # # Kernel hacking # +# CONFIG_PRINTK_TIME is not set +# CONFIG_DEBUG_KERNEL is not set +CONFIG_LOG_BUF_SHIFT=14 # CONFIG_FULLDEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set # CONFIG_HIGHPROFILE is not set +# CONFIG_BOOTPARAM is not set # CONFIG_DUMPTOFLASH is not set # CONFIG_NO_KERNEL_MSG is not set # CONFIG_BDM_DISABLE is not set @@ -525,6 +640,7 @@ CONFIG_MSDOS_PARTITION=y # # Security options # +# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # @@ -533,6 +649,12 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_CRYPTO is not set # +# Hardware crypto devices +# + +# # Library routines # +# CONFIG_CRC_CCITT is not set # CONFIG_CRC32 is not set +# CONFIG_LIBCRC32C is not set diff --git a/arch/m68knommu/kernel/setup.c b/arch/m68knommu/kernel/setup.c index 557238596dc..a220345e974 100644 --- a/arch/m68knommu/kernel/setup.c +++ b/arch/m68knommu/kernel/setup.c @@ -6,7 +6,7 @@ * Copyleft ()) 2000 James D. Schettine {james@telos-systems.com} * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> * Copyright (C) 1995 Hamish Macdonald - * Copyright (C) 2000 Lineo Inc. (www.lineo.com) + * Copyright (C) 2000 Lineo Inc. (www.lineo.com) * Copyright (C) 2001 Lineo, Inc. <www.lineo.com> * * 68VZ328 Fixes/support Evan Stawnyczy <e@lineo.ca> @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/fs.h> #include <linux/fb.h> +#include <linux/module.h> #include <linux/console.h> #include <linux/genhd.h> #include <linux/errno.h> @@ -45,6 +46,9 @@ unsigned long rom_length; unsigned long memory_start; unsigned long memory_end; +EXPORT_SYMBOL(memory_start); +EXPORT_SYMBOL(memory_end); + char command_line[COMMAND_LINE_SIZE]; /* setup some dummy routines */ @@ -103,15 +107,21 @@ void (*mach_power_off)( void ) = NULL; #if defined(CONFIG_M5206e) #define CPU "COLDFIRE(m5206e)" #endif +#if defined(CONFIG_M523x) + #define CPU "COLDFIRE(m523x)" +#endif #if defined(CONFIG_M5249) #define CPU "COLDFIRE(m5249)" #endif -#if defined(CONFIG_M527x) - #define CPU "COLDFIRE(m5270/5271/5274/5275)" +#if defined(CONFIG_M5271) + #define CPU "COLDFIRE(m5270/5271)" #endif #if defined(CONFIG_M5272) #define CPU "COLDFIRE(m5272)" #endif +#if defined(CONFIG_M5275) + #define CPU "COLDFIRE(m5274/5275)" +#endif #if defined(CONFIG_M528x) #define CPU "COLDFIRE(m5280/5282)" #endif @@ -152,7 +162,7 @@ void setup_arch(char **cmdline_p) init_mm.start_code = (unsigned long) &_stext; init_mm.end_code = (unsigned long) &_etext; init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) 0; + init_mm.brk = (unsigned long) 0; config_BSP(&command_line[0], sizeof(command_line)); @@ -171,7 +181,7 @@ void setup_arch(char **cmdline_p) #endif #ifdef CONFIG_ELITE printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n"); -#endif +#endif #ifdef CONFIG_TELOS printk(KERN_INFO "Modified for Omnia ToolVox by James D. Schettine, james@telos-systems.com\n"); #endif @@ -200,6 +210,9 @@ void setup_arch(char **cmdline_p) #ifdef CONFIG_DRAGEN2 printk(KERN_INFO "DragonEngine II board support by Georges Menie\n"); #endif +#ifdef CONFIG_M5235EVB + printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)"); +#endif #ifdef DEBUG printk(KERN_DEBUG "KERNEL -> TEXT=0x%06x-0x%06x DATA=0x%06x-0x%06x " @@ -223,7 +236,7 @@ void setup_arch(char **cmdline_p) saved_command_line[COMMAND_LINE_SIZE-1] = 0; #ifdef DEBUG - if (strlen(*cmdline_p)) + if (strlen(*cmdline_p)) printk(KERN_DEBUG "Command line: '%s'\n", *cmdline_p); #endif diff --git a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c index ad7dc6347f1..5bc06846286 100644 --- a/arch/m68knommu/kernel/traps.c +++ b/arch/m68knommu/kernel/traps.c @@ -21,6 +21,7 @@ #include <linux/signal.h> #include <linux/kernel.h> #include <linux/mm.h> +#include <linux/module.h> #include <linux/types.h> #include <linux/a.out.h> #include <linux/user.h> @@ -38,7 +39,7 @@ #include <asm/machdep.h> #include <asm/siginfo.h> -static char *vec_names[] = { +static char const * const vec_names[] = { "RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR", "ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc", "PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111", @@ -106,17 +107,20 @@ asmlinkage void buserr_c(struct frame *fp) int kstack_depth_to_print = 48; -void show_stack(struct task_struct *task, unsigned long *esp) +void show_stack(struct task_struct *task, unsigned long *stack) { - unsigned long *stack, *endstack, addr; + unsigned long *endstack, addr; extern char _start, _etext; int i; - if (esp == NULL) - esp = (unsigned long *) &esp; + if (!stack) { + if (task) + stack = (unsigned long *)task->thread.ksp; + else + stack = (unsigned long *)&stack; + } - stack = esp; - addr = (unsigned long) esp; + addr = (unsigned long) stack; endstack = (unsigned long *) PAGE_ALIGN(addr); printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack); @@ -306,6 +310,8 @@ void dump_stack(void) show_stack(current, &stack); } +EXPORT_SYMBOL(dump_stack); + #ifdef CONFIG_M68KFPU_EMU asmlinkage void fpemu_signal(int signal, int code, void *addr) { diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 31cb12892da..47f06787190 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -107,7 +107,7 @@ */ #if defined(CONFIG_ELITE) #define RAM_START 0x30020000 -#define RAM_END 0xe0000 +#define RAM_LENGTH 0xe0000 #endif /* @@ -118,7 +118,8 @@ #if defined(CONFIG_M5206eC3) || defined(CONFIG_M5249C3) || \ defined(CONFIG_M5272C3) || defined(CONFIG_M5307C3) || \ defined(CONFIG_ARN5307) || defined(CONFIG_M5407C3) || \ - defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) + defined(CONFIG_M5271EVB) || defined(CONFIG_M5275EVB) || \ + defined(CONFIG_M5235EVB) #define RAM_START 0x20000 #define RAM_LENGTH 0x3e0000 #endif @@ -145,6 +146,16 @@ #define RAM_LENGTH 0x3f0000 #endif + +/* + * The EMAC SoM-5282EM module. + */ +#if defined(CONFIG_SOM5282EM) +#define RAM_START 0x10000 +#define RAM_LENGTH 0xff0000 +#endif + + /* * These flash boot boards use all of ram for operation. Again the * actual memory size is not important here, assume at least 4MiB. @@ -158,7 +169,7 @@ #endif /* - * Sneha Boards mimimun memmory + * Sneha Boards mimimun memory * The end of RAM will vary depending on how much ram is fitted, * but this isn't important here, we assume at least 4MiB. */ @@ -167,6 +178,12 @@ #define RAM_LENGTH 0x3e0000 #endif +#if defined(CONFIG_MOD5272) +#define RAM_START 0x02000000 +#define RAM_LENGTH 0x00800000 +#define RAMVEC_START 0x20000000 +#define RAMVEC_LENGTH 0x00000400 +#endif #if defined(CONFIG_RAMKERNEL) #define TEXT ram diff --git a/arch/m68knommu/platform/523x/config.c b/arch/m68knommu/platform/523x/config.c new file mode 100644 index 00000000000..22767ce506e --- /dev/null +++ b/arch/m68knommu/platform/523x/config.c @@ -0,0 +1,82 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/523x/config.c + * + * Sub-architcture dependant initialization code for the Freescale + * 523x CPUs. + * + * Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com) + * Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com) + */ + +/***************************************************************************/ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/param.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <asm/dma.h> +#include <asm/traps.h> +#include <asm/machdep.h> +#include <asm/coldfire.h> +#include <asm/mcfsim.h> +#include <asm/mcfdma.h> + +/***************************************************************************/ + +void coldfire_pit_tick(void); +void coldfire_pit_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_pit_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +/***************************************************************************/ + +/* + * DMA channel base address table. + */ +unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = { + MCF_MBAR + MCFDMA_BASE0, +}; + +unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; + +/***************************************************************************/ + +void mcf_disableall(void) +{ + *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRH)) = 0xffffffff; + *((volatile unsigned long *) (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL)) = 0xffffffff; +} + +/***************************************************************************/ + +void mcf_autovector(unsigned int vec) +{ + /* Everything is auto-vectored on the 5272 */ +} + +/***************************************************************************/ + +void config_BSP(char *commandp, int size) +{ + mcf_disableall(); + +#ifdef CONFIG_BOOTPARAM + strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); + commandp[size-1] = 0; +#else + memset(commandp, 0, size); +#endif + + mach_sched_init = coldfire_pit_init; + mach_tick = coldfire_pit_tick; + mach_gettimeoffset = coldfire_pit_offset; + mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; +} + +/***************************************************************************/ diff --git a/arch/m68knommu/platform/5307/head.S b/arch/m68knommu/platform/5307/head.S index c7d7a395c4c..7f4ba837901 100644 --- a/arch/m68knommu/platform/5307/head.S +++ b/arch/m68knommu/platform/5307/head.S @@ -39,14 +39,18 @@ * Memory size exceptions for special cases. Some boards may be set * for auto memory sizing, but we can't do it that way for some reason. * For example the 5206eLITE board has static RAM, and auto-detecting - * the SDRAM will do you no good at all. + * the SDRAM will do you no good at all. Same goes for the MOD5272. */ #ifdef CONFIG_RAMAUTO #if defined(CONFIG_M5206eLITE) -#define MEM_SIZE 0x00100000 /* 1MiB default memory */ +#define MEM_SIZE 0x00100000 /* 1MiB default memory */ +#endif +#if defined(CONFIG_MOD5272) +#define MEM_SIZE 0x00800000 /* 8MiB default memory */ #endif #endif /* CONFIG_RAMAUTO */ + /* * If we don't have a fixed memory size now, then lets build in code * to auto detect the DRAM size. Obviously this is the prefered @@ -100,11 +104,15 @@ /* * Most ColdFire boards have their DRAM starting at address 0. - * Notable exception is the 5206eLITE board. + * Notable exception is the 5206eLITE board, another is the MOD5272. */ #if defined(CONFIG_M5206eLITE) #define MEM_BASE 0x30000000 #endif +#if defined(CONFIG_MOD5272) +#define MEM_BASE 0x02000000 +#define VBR_BASE 0x20000000 /* vectors in SRAM */ +#endif #ifndef MEM_BASE #define MEM_BASE 0x00000000 /* memory base at address 0 */ @@ -188,6 +196,7 @@ _start: movel %a7,_rambase GET_MEM_SIZE /* macro code determines size */ + addl %a7,%d0 movel %d0,_ramend /* set end ram addr */ /* diff --git a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S index 0f5d1fe8eb5..7d8990d784a 100644 --- a/arch/m68knommu/platform/68328/entry.S +++ b/arch/m68knommu/platform/68328/entry.S @@ -79,7 +79,7 @@ ENTRY(system_call) movel %sp@(PT_ORIG_D0),%d0 movel %sp,%d1 /* get thread_info pointer */ - andl #0xffffe000,%d1 + andl #-THREAD_SIZE,%d1 movel %d1,%a2 btst #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS) jne do_trace @@ -105,7 +105,7 @@ Luser_return: andw #ALLOWINT,%sr movel %sp,%d1 /* get thread_info pointer */ - andl #0xffffe000,%d1 + andl #-THREAD_SIZE,%d1 movel %d1,%a2 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ andl #_TIF_WORK_MASK,%d1 diff --git a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S index f7bc80a60e0..8ff48adf24a 100644 --- a/arch/m68knommu/platform/68360/entry.S +++ b/arch/m68knommu/platform/68360/entry.S @@ -96,7 +96,7 @@ Luser_return: andw #ALLOWINT,%sr movel %sp,%d1 /* get thread_info pointer */ - andl #0xffffe000,%d1 + andl #-THREAD_SIZE,%d1 movel %d1,%a2 move %a2@(TI_FLAGS),%d1 /* thread_info->flags */ andl #_TIF_WORK_MASK,%d1 diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index 468721d9ebd..3fb1fb619d2 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S @@ -249,8 +249,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) sync isync - /* Enable L2 HW prefetch + /* Enable L2 HW prefetch, if L2 is enabled */ + mfspr r3,SPRN_L2CR + andis. r3,r3,L2CR_L2E@h + beqlr mfspr r3,SPRN_MSSCR0 ori r3,r3,3 sync diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S index c3944104826..861115249b3 100644 --- a/arch/ppc/kernel/l2cr.S +++ b/arch/ppc/kernel/l2cr.S @@ -156,6 +156,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) The bit moved on the 7450..... ****/ +BEGIN_FTR_SECTION + /* Disable L2 prefetch on some 745x and try to ensure + * L2 prefetch engines are idle. As explained by errata + * text, we can't be sure they are, we just hope very hard + * that well be enough (sic !). At least I noticed Apple + * doesn't even bother doing the dcbf's here... + */ + mfspr r4,SPRN_MSSCR0 + rlwinm r4,r4,0,0,29 + sync + mtspr SPRN_MSSCR0,r4 + sync + isync + lis r4,KERNELBASE@h + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) + /* TODO: use HW flush assist when available */ lis r4,0x0002 @@ -230,7 +250,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) oris r3,r3,0x8000 mtspr SPRN_L2CR,r3 sync - + + /* Enable L2 HW prefetch on 744x/745x */ +BEGIN_FTR_SECTION + mfspr r3,SPRN_MSSCR0 + ori r3,r3,3 + sync + mtspr SPRN_MSSCR0,r3 + sync + isync +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) 4: /* Restore HID0[DPM] to whatever it was before */ diff --git a/arch/ppc64/mm/slb_low.S b/arch/ppc64/mm/slb_low.S index bab255889c5..698d6b9ed6d 100644 --- a/arch/ppc64/mm/slb_low.S +++ b/arch/ppc64/mm/slb_low.S @@ -97,25 +97,21 @@ BEGIN_FTR_SECTION lhz r9,PACAHIGHHTLBAREAS(r13) srdi r11,r3,(HTLB_AREA_SHIFT-SID_SHIFT) srd r9,r9,r11 - andi. r9,r9,1 - bne 5f + lhz r11,PACALOWHTLBAREAS(r13) + srd r11,r11,r3 + or r9,r9,r11 +END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) +#endif /* CONFIG_HUGETLB_PAGE */ li r11,SLB_VSID_USER - cmpldi r3,16 - bge 6f - - lhz r9,PACALOWHTLBAREAS(r13) - srd r9,r9,r3 - andi. r9,r9,1 - - beq 6f - -5: li r11,SLB_VSID_USER|SLB_VSID_L +#ifdef CONFIG_HUGETLB_PAGE +BEGIN_FTR_SECTION + rldimi r11,r9,8,55 /* shift masked bit into SLB_VSID_L */ END_FTR_SECTION_IFSET(CPU_FTR_16M_PAGE) #endif /* CONFIG_HUGETLB_PAGE */ -6: ld r9,PACACONTEXTID(r13) + ld r9,PACACONTEXTID(r13) rldimi r3,r9,USER_ESID_BITS,0 9: /* r3 = protovsid, r11 = flags, r10 = esid_data, cr7 = <>KERNELBASE */ diff --git a/arch/v850/configs/rte-ma1-cb_defconfig b/arch/v850/configs/rte-ma1-cb_defconfig index 1b5ca3c3a65..1a5beda36e2 100644 --- a/arch/v850/configs/rte-ma1-cb_defconfig +++ b/arch/v850/configs/rte-ma1-cb_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-uc0 -# Thu Jul 21 11:08:27 2005 +# Linux kernel version: 2.6.13-uc0 +# Fri Sep 2 13:54:27 2005 # # CONFIG_MMU is not set # CONFIG_UID16 is not set @@ -44,6 +44,8 @@ CONFIG_ZERO_BSS=y # CONFIG_V850E_HIGHRES_TIMER is not set # CONFIG_RESET_GUARD is not set CONFIG_LARGE_ALLOCS=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y # # Code maturity level options @@ -111,6 +113,52 @@ CONFIG_BINFMT_FLAT=y # CONFIG_BINFMT_MISC is not set # +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_UNIX is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_IP_TCPDIAG is not set +# CONFIG_IP_TCPDIAG_IPV6 is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_BIC=y +# CONFIG_IPV6 is not set +# CONFIG_NETFILTER is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_NET_SCHED is not set +# CONFIG_NET_CLS_ROUTE is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set + +# # Generic Driver Options # CONFIG_STANDALONE=y @@ -158,6 +206,7 @@ CONFIG_MTD_CFI_I2=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -232,6 +281,7 @@ CONFIG_IOSCHED_NOOP=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -244,53 +294,8 @@ CONFIG_IOSCHED_NOOP=y # CONFIG_I2O is not set # -# Networking support -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_UNIX is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_TUNNEL is not set -# CONFIG_IP_TCPDIAG is not set -# CONFIG_IP_TCPDIAG_IPV6 is not set -# CONFIG_IPV6 is not set -# CONFIG_NETFILTER is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set -# CONFIG_NET_CLS_ROUTE is not set - -# -# Network testing +# Network device support # -# CONFIG_NET_PKTGEN is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set CONFIG_NETDEVICES=y # CONFIG_DUMMY is not set # CONFIG_BONDING is not set @@ -372,6 +377,8 @@ CONFIG_EEPRO100=y # CONFIG_FDDI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set # # ISDN subsystem @@ -472,6 +479,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set # # XFS support @@ -479,6 +487,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y +# CONFIG_MAGIC_ROM_PTR is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -524,9 +534,11 @@ CONFIG_RAMFS=y # CONFIG_NFS_FS=y CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set # CONFIG_NFSD is not set CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y CONFIG_SUNRPC=y # CONFIG_SMB_FS is not set # CONFIG_CIFS is not set diff --git a/arch/v850/configs/rte-me2-cb_defconfig b/arch/v850/configs/rte-me2-cb_defconfig index 44becc06540..15e66647806 100644 --- a/arch/v850/configs/rte-me2-cb_defconfig +++ b/arch/v850/configs/rte-me2-cb_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-uc0 -# Thu Jul 21 11:30:08 2005 +# Linux kernel version: 2.6.13-uc0 +# Fri Sep 2 13:47:50 2005 # # CONFIG_MMU is not set # CONFIG_UID16 is not set @@ -41,6 +41,8 @@ CONFIG_ZERO_BSS=y # CONFIG_V850E_HIGHRES_TIMER is not set # CONFIG_RESET_GUARD is not set CONFIG_LARGE_ALLOCS=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y # # Code maturity level options @@ -56,7 +58,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -# CONFIG_AUDIT is not set # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y @@ -104,6 +105,11 @@ CONFIG_BINFMT_FLAT=y # CONFIG_BINFMT_MISC is not set # +# Networking +# +# CONFIG_NET is not set + +# # Generic Driver Options # CONFIG_STANDALONE=y @@ -151,6 +157,7 @@ CONFIG_MTD_CFI_I2=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -218,6 +225,7 @@ CONFIG_IOSCHED_NOOP=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -228,9 +236,8 @@ CONFIG_IOSCHED_NOOP=y # # -# Networking support +# Network device support # -# CONFIG_NET is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -311,7 +318,6 @@ CONFIG_SERIAL_CORE_CONSOLE=y # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # @@ -335,6 +341,7 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set # # XFS support @@ -342,6 +349,8 @@ CONFIG_SERIAL_CORE_CONSOLE=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y +# CONFIG_MAGIC_ROM_PTR is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set diff --git a/arch/v850/configs/sim_defconfig b/arch/v850/configs/sim_defconfig index d73f5f9d838..f31ba7398ad 100644 --- a/arch/v850/configs/sim_defconfig +++ b/arch/v850/configs/sim_defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.12-uc0 -# Thu Jul 21 11:29:27 2005 +# Linux kernel version: 2.6.13-uc0 +# Fri Sep 2 13:36:43 2005 # # CONFIG_MMU is not set # CONFIG_UID16 is not set @@ -36,6 +36,8 @@ CONFIG_NO_CACHE=y CONFIG_ZERO_BSS=y # CONFIG_RESET_GUARD is not set CONFIG_LARGE_ALLOCS=y +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y # # Code maturity level options @@ -51,7 +53,6 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_SYSCTL is not set -# CONFIG_AUDIT is not set # CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set CONFIG_EMBEDDED=y @@ -99,6 +100,11 @@ CONFIG_BINFMT_FLAT=y # CONFIG_BINFMT_MISC is not set # +# Networking +# +# CONFIG_NET is not set + +# # Generic Driver Options # CONFIG_STANDALONE=y @@ -146,6 +152,7 @@ CONFIG_MTD_CFI_I2=y # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers @@ -213,6 +220,7 @@ CONFIG_IOSCHED_NOOP=y # # Fusion MPT device support # +# CONFIG_FUSION is not set # # IEEE 1394 (FireWire) support @@ -223,9 +231,8 @@ CONFIG_IOSCHED_NOOP=y # # -# Networking support +# Network device support # -# CONFIG_NET is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -300,7 +307,6 @@ CONFIG_SERIO=y # # Ftape, the floppy tape device driver # -# CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set # @@ -324,6 +330,7 @@ CONFIG_SERIO=y # CONFIG_JBD is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set # # XFS support @@ -331,6 +338,8 @@ CONFIG_SERIO=y # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=y +# CONFIG_MAGIC_ROM_PTR is not set +CONFIG_INOTIFY=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set diff --git a/arch/v850/kernel/setup.c b/arch/v850/kernel/setup.c index c41d72b01b8..abd48409dcc 100644 --- a/arch/v850/kernel/setup.c +++ b/arch/v850/kernel/setup.c @@ -1,8 +1,8 @@ /* * arch/v850/kernel/setup.c -- Arch-dependent initialization functions * - * Copyright (C) 2001,02,03 NEC Electronics Corporation - * Copyright (C) 2001,02,03 Miles Bader <miles@gnu.org> + * Copyright (C) 2001,02,03,05 NEC Electronics Corporation + * Copyright (C) 2001,02,03,05 Miles Bader <miles@gnu.org> * * This file is subject to the terms and conditions of the GNU General * Public License. See the file COPYING in the main directory of this @@ -98,10 +98,20 @@ void __init trap_init (void) } #ifdef CONFIG_MTD + +/* From drivers/mtd/devices/slram.c */ +#define SLRAM_BLK_SZ 0x4000 + /* Set the root filesystem to be the given memory region. Some parameter may be appended to CMD_LINE. */ void set_mem_root (void *addr, size_t len, char *cmd_line) { + /* Some sort of idiocy in MTD means we must supply a length that's + a multiple of SLRAM_BLK_SZ. We just round up the real length, + as the file system shouldn't attempt to access anything beyond + the end of the image anyway. */ + len = (((len - 1) + SLRAM_BLK_SZ) / SLRAM_BLK_SZ) * SLRAM_BLK_SZ; + /* The only way to pass info to the MTD slram driver is via the command line. */ if (*cmd_line) { @@ -284,3 +294,33 @@ init_mem_alloc (unsigned long ram_start, unsigned long ram_len) free_area_init_node (0, NODE_DATA(0), zones_size, ADDR_TO_PAGE (PAGE_OFFSET), 0); } + + + +/* Taken from m68knommu */ +void show_mem(void) +{ + unsigned long i; + int free = 0, total = 0, reserved = 0, shared = 0; + int cached = 0; + + printk(KERN_INFO "\nMem-info:\n"); + show_free_areas(); + i = max_mapnr; + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (!page_count(mem_map+i)) + free++; + else + shared += page_count(mem_map+i) - 1; + } + printk(KERN_INFO "%d pages of RAM\n",total); + printk(KERN_INFO "%d free pages\n",free); + printk(KERN_INFO "%d reserved pages\n",reserved); + printk(KERN_INFO "%d pages shared\n",shared); + printk(KERN_INFO "%d pages swap cached\n",cached); +} diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index d568991ac6b..8666171e187 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c @@ -57,6 +57,7 @@ #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/delay.h> +#include <linux/serial_8250.h> #include "smapi.h" #include "mwavedd.h" #include "3780i.h" @@ -410,8 +411,8 @@ static ssize_t mwave_write(struct file *file, const char __user *buf, static int register_serial_portandirq(unsigned int port, int irq) { - struct serial_struct serial; - + struct uart_port uart; + switch ( port ) { case 0x3f8: case 0x2f8: @@ -442,12 +443,14 @@ static int register_serial_portandirq(unsigned int port, int irq) } /* switch */ /* irq is okay */ - memset(&serial, 0, sizeof(serial)); - serial.port = port; - serial.irq = irq; - serial.flags = ASYNC_SHARE_IRQ; - - return register_serial(&serial); + memset(&uart, 0, sizeof(struct uart_port)); + + uart.uartclk = 1843200; + uart.iobase = port; + uart.irq = irq; + uart.iotype = UPIO_PORT; + uart.flags = UPF_SHARE_IRQ; + return serial8250_register_port(&uart); } @@ -523,7 +526,7 @@ static void mwave_exit(void) #endif if ( pDrvData->sLine >= 0 ) { - unregister_serial(pDrvData->sLine); + serial8250_unregister_port(pDrvData->sLine); } if (pDrvData->bMwaveDevRegistered) { misc_deregister(&mwave_misc_dev); diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index d692af57213..baaa365285f 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c @@ -19,6 +19,7 @@ #include <linux/sched.h> #include <linux/byteorder/generic.h> #include <asm/sn/sn_sal.h> +#include <asm/unaligned.h> #include "snsc.h" static struct subch_data_s *event_sd; @@ -62,13 +63,16 @@ static int scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc) { char *desc_end; + __be32 from_buf; /* record event source address */ - *src = be32_to_cpup((__be32 *)event); + from_buf = get_unaligned((__be32 *)event); + *src = be32_to_cpup(&from_buf); event += 4; /* move on to event code */ /* record the system controller's event code */ - *code = be32_to_cpup((__be32 *)event); + from_buf = get_unaligned((__be32 *)event); + *code = be32_to_cpup(&from_buf); event += 4; /* move on to event arguments */ /* how many arguments are in the packet? */ @@ -82,7 +86,8 @@ scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc) /* not an integer argument, so give up */ return -1; } - *esp_code = be32_to_cpup((__be32 *)event); + from_buf = get_unaligned((__be32 *)event); + *esp_code = be32_to_cpup(&from_buf); event += 4; /* parse out the event description */ diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index bf3c011d2cf..d8bf6587789 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -102,6 +102,9 @@ config DVB_BUDGET_AV select VIDEO_DEV select VIDEO_SAA7146_VV select DVB_STV0299 + select DVB_TDA1004X + select DVB_TDA10021 + select FW_LOADER help Support for simple SAA7146 based DVB cards (so called Budget- or Nova-PCI cards) without onboard diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 7fc692a8f5b..dea6589d153 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -6,7 +6,7 @@ menu "Misc devices" config IBM_ASM tristate "Device driver for IBM RSA service processor" - depends on X86 && PCI && EXPERIMENTAL + depends on X86 && PCI && EXPERIMENTAL && BROKEN ---help--- This option enables device driver support for in-band access to the IBM RSA (Condor) service processor in eServer xSeries systems. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index e0239a10d32..7d8bcb38797 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -447,7 +447,7 @@ config NET_SB1250_MAC config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" - depends on NET_ETHERNET && PCI && SGI_IP27 + depends on NET_ETHERNET && PCI && SGI_IP27 && BROKEN select CRC32 select MII help diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 183ba97785b..dc5d089bf18 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -79,12 +79,55 @@ #include <asm/iommu.h> #include <asm/vio.h> -#include "iseries_veth.h" +#undef DEBUG MODULE_AUTHOR("Kyle Lucke <klucke@us.ibm.com>"); MODULE_DESCRIPTION("iSeries Virtual ethernet driver"); MODULE_LICENSE("GPL"); +#define VETH_EVENT_CAP (0) +#define VETH_EVENT_FRAMES (1) +#define VETH_EVENT_MONITOR (2) +#define VETH_EVENT_FRAMES_ACK (3) + +#define VETH_MAX_ACKS_PER_MSG (20) +#define VETH_MAX_FRAMES_PER_MSG (6) + +struct veth_frames_data { + u32 addr[VETH_MAX_FRAMES_PER_MSG]; + u16 len[VETH_MAX_FRAMES_PER_MSG]; + u32 eofmask; +}; +#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) + +struct veth_frames_ack_data { + u16 token[VETH_MAX_ACKS_PER_MSG]; +}; + +struct veth_cap_data { + u8 caps_version; + u8 rsvd1; + u16 num_buffers; + u16 ack_threshold; + u16 rsvd2; + u32 ack_timeout; + u32 rsvd3; + u64 rsvd4[3]; +}; + +struct veth_lpevent { + struct HvLpEvent base_event; + union { + struct veth_cap_data caps_data; + struct veth_frames_data frames_data; + struct veth_frames_ack_data frames_ack_data; + } u; + +}; + +#define DRV_NAME "iseries_veth" +#define DRV_VERSION "2.0" + #define VETH_NUMBUFFERS (120) #define VETH_ACKTIMEOUT (1000000) /* microseconds */ #define VETH_MAX_MCAST (12) @@ -113,9 +156,9 @@ MODULE_LICENSE("GPL"); struct veth_msg { struct veth_msg *next; - struct VethFramesData data; + struct veth_frames_data data; int token; - unsigned long in_use; + int in_use; struct sk_buff *skb; struct device *dev; }; @@ -125,23 +168,28 @@ struct veth_lpar_connection { struct work_struct statemachine_wq; struct veth_msg *msgs; int num_events; - struct VethCapData local_caps; + struct veth_cap_data local_caps; + struct kobject kobject; struct timer_list ack_timer; + struct timer_list reset_timer; + unsigned int reset_timeout; + unsigned long last_contact; + int outstanding_tx; + spinlock_t lock; unsigned long state; HvLpInstanceId src_inst; HvLpInstanceId dst_inst; - struct VethLpEvent cap_event, cap_ack_event; + struct veth_lpevent cap_event, cap_ack_event; u16 pending_acks[VETH_MAX_ACKS_PER_MSG]; u32 num_pending_acks; int num_ack_events; - struct VethCapData remote_caps; + struct veth_cap_data remote_caps; u32 ack_timeout; - spinlock_t msg_stack_lock; struct veth_msg *msg_stack_head; }; @@ -151,15 +199,17 @@ struct veth_port { u64 mac_addr; HvLpIndexMap lpar_map; - spinlock_t pending_gate; - struct sk_buff *pending_skb; - HvLpIndexMap pending_lpmask; + /* queue_lock protects the stopped_map and dev's queue. */ + spinlock_t queue_lock; + HvLpIndexMap stopped_map; + /* mcast_gate protects promiscuous, num_mcast & mcast_addr. */ rwlock_t mcast_gate; int promiscuous; - int all_mcast; int num_mcast; u64 mcast_addr[VETH_MAX_MCAST]; + + struct kobject kobject; }; static HvLpIndex this_lp; @@ -168,44 +218,56 @@ static struct net_device *veth_dev[HVMAXARCHITECTEDVIRTUALLANS]; /* = 0 */ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev); static void veth_recycle_msg(struct veth_lpar_connection *, struct veth_msg *); -static void veth_flush_pending(struct veth_lpar_connection *cnx); -static void veth_receive(struct veth_lpar_connection *, struct VethLpEvent *); -static void veth_timed_ack(unsigned long connectionPtr); +static void veth_wake_queues(struct veth_lpar_connection *cnx); +static void veth_stop_queues(struct veth_lpar_connection *cnx); +static void veth_receive(struct veth_lpar_connection *, struct veth_lpevent *); +static void veth_release_connection(struct kobject *kobject); +static void veth_timed_ack(unsigned long ptr); +static void veth_timed_reset(unsigned long ptr); /* * Utility functions */ -#define veth_printk(prio, fmt, args...) \ - printk(prio "%s: " fmt, __FILE__, ## args) +#define veth_info(fmt, args...) \ + printk(KERN_INFO DRV_NAME ": " fmt, ## args) #define veth_error(fmt, args...) \ - printk(KERN_ERR "(%s:%3.3d) ERROR: " fmt, __FILE__, __LINE__ , ## args) + printk(KERN_ERR DRV_NAME ": Error: " fmt, ## args) + +#ifdef DEBUG +#define veth_debug(fmt, args...) \ + printk(KERN_DEBUG DRV_NAME ": " fmt, ## args) +#else +#define veth_debug(fmt, args...) do {} while (0) +#endif +/* You must hold the connection's lock when you call this function. */ static inline void veth_stack_push(struct veth_lpar_connection *cnx, struct veth_msg *msg) { - unsigned long flags; - - spin_lock_irqsave(&cnx->msg_stack_lock, flags); msg->next = cnx->msg_stack_head; cnx->msg_stack_head = msg; - spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); } +/* You must hold the connection's lock when you call this function. */ static inline struct veth_msg *veth_stack_pop(struct veth_lpar_connection *cnx) { - unsigned long flags; struct veth_msg *msg; - spin_lock_irqsave(&cnx->msg_stack_lock, flags); msg = cnx->msg_stack_head; if (msg) cnx->msg_stack_head = cnx->msg_stack_head->next; - spin_unlock_irqrestore(&cnx->msg_stack_lock, flags); + return msg; } +/* You must hold the connection's lock when you call this function. */ +static inline int veth_stack_is_empty(struct veth_lpar_connection *cnx) +{ + return cnx->msg_stack_head == NULL; +} + static inline HvLpEvent_Rc veth_signalevent(struct veth_lpar_connection *cnx, u16 subtype, HvLpEvent_AckInd ackind, HvLpEvent_AckType acktype, @@ -249,7 +311,7 @@ static int veth_allocate_events(HvLpIndex rlp, int number) struct veth_allocation vc = { COMPLETION_INITIALIZER(vc.c), 0 }; mf_allocate_lp_events(rlp, HvLpEvent_Type_VirtualLan, - sizeof(struct VethLpEvent), number, + sizeof(struct veth_lpevent), number, &veth_complete_allocation, &vc); wait_for_completion(&vc.c); @@ -257,6 +319,137 @@ static int veth_allocate_events(HvLpIndex rlp, int number) } /* + * sysfs support + */ + +struct veth_cnx_attribute { + struct attribute attr; + ssize_t (*show)(struct veth_lpar_connection *, char *buf); + ssize_t (*store)(struct veth_lpar_connection *, const char *buf); +}; + +static ssize_t veth_cnx_attribute_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct veth_cnx_attribute *cnx_attr; + struct veth_lpar_connection *cnx; + + cnx_attr = container_of(attr, struct veth_cnx_attribute, attr); + cnx = container_of(kobj, struct veth_lpar_connection, kobject); + + if (!cnx_attr->show) + return -EIO; + + return cnx_attr->show(cnx, buf); +} + +#define CUSTOM_CNX_ATTR(_name, _format, _expression) \ +static ssize_t _name##_show(struct veth_lpar_connection *cnx, char *buf)\ +{ \ + return sprintf(buf, _format, _expression); \ +} \ +struct veth_cnx_attribute veth_cnx_attr_##_name = __ATTR_RO(_name) + +#define SIMPLE_CNX_ATTR(_name) \ + CUSTOM_CNX_ATTR(_name, "%lu\n", (unsigned long)cnx->_name) + +SIMPLE_CNX_ATTR(outstanding_tx); +SIMPLE_CNX_ATTR(remote_lp); +SIMPLE_CNX_ATTR(num_events); +SIMPLE_CNX_ATTR(src_inst); +SIMPLE_CNX_ATTR(dst_inst); +SIMPLE_CNX_ATTR(num_pending_acks); +SIMPLE_CNX_ATTR(num_ack_events); +CUSTOM_CNX_ATTR(ack_timeout, "%d\n", jiffies_to_msecs(cnx->ack_timeout)); +CUSTOM_CNX_ATTR(reset_timeout, "%d\n", jiffies_to_msecs(cnx->reset_timeout)); +CUSTOM_CNX_ATTR(state, "0x%.4lX\n", cnx->state); +CUSTOM_CNX_ATTR(last_contact, "%d\n", cnx->last_contact ? + jiffies_to_msecs(jiffies - cnx->last_contact) : 0); + +#define GET_CNX_ATTR(_name) (&veth_cnx_attr_##_name.attr) + +static struct attribute *veth_cnx_default_attrs[] = { + GET_CNX_ATTR(outstanding_tx), + GET_CNX_ATTR(remote_lp), + GET_CNX_ATTR(num_events), + GET_CNX_ATTR(reset_timeout), + GET_CNX_ATTR(last_contact), + GET_CNX_ATTR(state), + GET_CNX_ATTR(src_inst), + GET_CNX_ATTR(dst_inst), + GET_CNX_ATTR(num_pending_acks), + GET_CNX_ATTR(num_ack_events), + GET_CNX_ATTR(ack_timeout), + NULL +}; + +static struct sysfs_ops veth_cnx_sysfs_ops = { + .show = veth_cnx_attribute_show +}; + +static struct kobj_type veth_lpar_connection_ktype = { + .release = veth_release_connection, + .sysfs_ops = &veth_cnx_sysfs_ops, + .default_attrs = veth_cnx_default_attrs +}; + +struct veth_port_attribute { + struct attribute attr; + ssize_t (*show)(struct veth_port *, char *buf); + ssize_t (*store)(struct veth_port *, const char *buf); +}; + +static ssize_t veth_port_attribute_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct veth_port_attribute *port_attr; + struct veth_port *port; + + port_attr = container_of(attr, struct veth_port_attribute, attr); + port = container_of(kobj, struct veth_port, kobject); + + if (!port_attr->show) + return -EIO; + + return port_attr->show(port, buf); +} + +#define CUSTOM_PORT_ATTR(_name, _format, _expression) \ +static ssize_t _name##_show(struct veth_port *port, char *buf) \ +{ \ + return sprintf(buf, _format, _expression); \ +} \ +struct veth_port_attribute veth_port_attr_##_name = __ATTR_RO(_name) + +#define SIMPLE_PORT_ATTR(_name) \ + CUSTOM_PORT_ATTR(_name, "%lu\n", (unsigned long)port->_name) + +SIMPLE_PORT_ATTR(promiscuous); +SIMPLE_PORT_ATTR(num_mcast); +CUSTOM_PORT_ATTR(lpar_map, "0x%X\n", port->lpar_map); +CUSTOM_PORT_ATTR(stopped_map, "0x%X\n", port->stopped_map); +CUSTOM_PORT_ATTR(mac_addr, "0x%lX\n", port->mac_addr); + +#define GET_PORT_ATTR(_name) (&veth_port_attr_##_name.attr) +static struct attribute *veth_port_default_attrs[] = { + GET_PORT_ATTR(mac_addr), + GET_PORT_ATTR(lpar_map), + GET_PORT_ATTR(stopped_map), + GET_PORT_ATTR(promiscuous), + GET_PORT_ATTR(num_mcast), + NULL +}; + +static struct sysfs_ops veth_port_sysfs_ops = { + .show = veth_port_attribute_show +}; + +static struct kobj_type veth_port_ktype = { + .sysfs_ops = &veth_port_sysfs_ops, + .default_attrs = veth_port_default_attrs +}; + +/* * LPAR connection code */ @@ -266,7 +459,7 @@ static inline void veth_kick_statemachine(struct veth_lpar_connection *cnx) } static void veth_take_cap(struct veth_lpar_connection *cnx, - struct VethLpEvent *event) + struct veth_lpevent *event) { unsigned long flags; @@ -278,7 +471,7 @@ static void veth_take_cap(struct veth_lpar_connection *cnx, HvLpEvent_Type_VirtualLan); if (cnx->state & VETH_STATE_GOTCAPS) { - veth_error("Received a second capabilities from lpar %d\n", + veth_error("Received a second capabilities from LPAR %d.\n", cnx->remote_lp); event->base_event.xRc = HvLpEvent_Rc_BufferNotAvailable; HvCallEvent_ackLpEvent((struct HvLpEvent *) event); @@ -291,13 +484,13 @@ static void veth_take_cap(struct veth_lpar_connection *cnx, } static void veth_take_cap_ack(struct veth_lpar_connection *cnx, - struct VethLpEvent *event) + struct veth_lpevent *event) { unsigned long flags; spin_lock_irqsave(&cnx->lock, flags); if (cnx->state & VETH_STATE_GOTCAPACK) { - veth_error("Received a second capabilities ack from lpar %d\n", + veth_error("Received a second capabilities ack from LPAR %d.\n", cnx->remote_lp); } else { memcpy(&cnx->cap_ack_event, event, @@ -309,19 +502,24 @@ static void veth_take_cap_ack(struct veth_lpar_connection *cnx, } static void veth_take_monitor_ack(struct veth_lpar_connection *cnx, - struct VethLpEvent *event) + struct veth_lpevent *event) { unsigned long flags; spin_lock_irqsave(&cnx->lock, flags); - veth_printk(KERN_DEBUG, "Monitor ack returned for lpar %d\n", - cnx->remote_lp); - cnx->state |= VETH_STATE_RESET; - veth_kick_statemachine(cnx); + veth_debug("cnx %d: lost connection.\n", cnx->remote_lp); + + /* Avoid kicking the statemachine once we're shutdown. + * It's unnecessary and it could break veth_stop_connection(). */ + + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + cnx->state |= VETH_STATE_RESET; + veth_kick_statemachine(cnx); + } spin_unlock_irqrestore(&cnx->lock, flags); } -static void veth_handle_ack(struct VethLpEvent *event) +static void veth_handle_ack(struct veth_lpevent *event) { HvLpIndex rlp = event->base_event.xTargetLp; struct veth_lpar_connection *cnx = veth_cnx[rlp]; @@ -329,58 +527,67 @@ static void veth_handle_ack(struct VethLpEvent *event) BUG_ON(! cnx); switch (event->base_event.xSubtype) { - case VethEventTypeCap: + case VETH_EVENT_CAP: veth_take_cap_ack(cnx, event); break; - case VethEventTypeMonitor: + case VETH_EVENT_MONITOR: veth_take_monitor_ack(cnx, event); break; default: - veth_error("Unknown ack type %d from lpar %d\n", - event->base_event.xSubtype, rlp); + veth_error("Unknown ack type %d from LPAR %d.\n", + event->base_event.xSubtype, rlp); }; } -static void veth_handle_int(struct VethLpEvent *event) +static void veth_handle_int(struct veth_lpevent *event) { HvLpIndex rlp = event->base_event.xSourceLp; struct veth_lpar_connection *cnx = veth_cnx[rlp]; unsigned long flags; - int i; + int i, acked = 0; BUG_ON(! cnx); switch (event->base_event.xSubtype) { - case VethEventTypeCap: + case VETH_EVENT_CAP: veth_take_cap(cnx, event); break; - case VethEventTypeMonitor: + case VETH_EVENT_MONITOR: /* do nothing... this'll hang out here til we're dead, * and the hypervisor will return it for us. */ break; - case VethEventTypeFramesAck: + case VETH_EVENT_FRAMES_ACK: spin_lock_irqsave(&cnx->lock, flags); + for (i = 0; i < VETH_MAX_ACKS_PER_MSG; ++i) { u16 msgnum = event->u.frames_ack_data.token[i]; - if (msgnum < VETH_NUMBUFFERS) + if (msgnum < VETH_NUMBUFFERS) { veth_recycle_msg(cnx, cnx->msgs + msgnum); + cnx->outstanding_tx--; + acked++; + } + } + + if (acked > 0) { + cnx->last_contact = jiffies; + veth_wake_queues(cnx); } + spin_unlock_irqrestore(&cnx->lock, flags); - veth_flush_pending(cnx); break; - case VethEventTypeFrames: + case VETH_EVENT_FRAMES: veth_receive(cnx, event); break; default: - veth_error("Unknown interrupt type %d from lpar %d\n", - event->base_event.xSubtype, rlp); + veth_error("Unknown interrupt type %d from LPAR %d.\n", + event->base_event.xSubtype, rlp); }; } static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) { - struct VethLpEvent *veth_event = (struct VethLpEvent *)event; + struct veth_lpevent *veth_event = (struct veth_lpevent *)event; if (event->xFlags.xFunction == HvLpEvent_Function_Ack) veth_handle_ack(veth_event); @@ -390,7 +597,7 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) static int veth_process_caps(struct veth_lpar_connection *cnx) { - struct VethCapData *remote_caps = &cnx->remote_caps; + struct veth_cap_data *remote_caps = &cnx->remote_caps; int num_acks_needed; /* Convert timer to jiffies */ @@ -400,8 +607,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) || (remote_caps->ack_threshold > VETH_MAX_ACKS_PER_MSG) || (remote_caps->ack_threshold == 0) || (cnx->ack_timeout == 0) ) { - veth_error("Received incompatible capabilities from lpar %d\n", - cnx->remote_lp); + veth_error("Received incompatible capabilities from LPAR %d.\n", + cnx->remote_lp); return HvLpEvent_Rc_InvalidSubtypeData; } @@ -418,8 +625,8 @@ static int veth_process_caps(struct veth_lpar_connection *cnx) cnx->num_ack_events += num; if (cnx->num_ack_events < num_acks_needed) { - veth_error("Couldn't allocate enough ack events for lpar %d\n", - cnx->remote_lp); + veth_error("Couldn't allocate enough ack events " + "for LPAR %d.\n", cnx->remote_lp); return HvLpEvent_Rc_BufferNotAvailable; } @@ -440,15 +647,15 @@ static void veth_statemachine(void *p) restart: if (cnx->state & VETH_STATE_RESET) { - int i; - - del_timer(&cnx->ack_timer); - if (cnx->state & VETH_STATE_OPEN) HvCallEvent_closeLpEventPath(cnx->remote_lp, HvLpEvent_Type_VirtualLan); - /* reset ack data */ + /* + * Reset ack data. This prevents the ack_timer actually + * doing anything, even if it runs one more time when + * we drop the lock below. + */ memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); cnx->num_pending_acks = 0; @@ -458,14 +665,32 @@ static void veth_statemachine(void *p) | VETH_STATE_SENTCAPACK | VETH_STATE_READY); /* Clean up any leftover messages */ - if (cnx->msgs) + if (cnx->msgs) { + int i; for (i = 0; i < VETH_NUMBUFFERS; ++i) veth_recycle_msg(cnx, cnx->msgs + i); + } + + cnx->outstanding_tx = 0; + veth_wake_queues(cnx); + + /* Drop the lock so we can do stuff that might sleep or + * take other locks. */ spin_unlock_irq(&cnx->lock); - veth_flush_pending(cnx); + + del_timer_sync(&cnx->ack_timer); + del_timer_sync(&cnx->reset_timer); + spin_lock_irq(&cnx->lock); + if (cnx->state & VETH_STATE_RESET) goto restart; + + /* Hack, wait for the other end to reset itself. */ + if (! (cnx->state & VETH_STATE_SHUTDOWN)) { + schedule_delayed_work(&cnx->statemachine_wq, 5 * HZ); + goto out; + } } if (cnx->state & VETH_STATE_SHUTDOWN) @@ -488,7 +713,7 @@ static void veth_statemachine(void *p) if ( (cnx->state & VETH_STATE_OPEN) && !(cnx->state & VETH_STATE_SENTMON) ) { - rc = veth_signalevent(cnx, VethEventTypeMonitor, + rc = veth_signalevent(cnx, VETH_EVENT_MONITOR, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_DeferredAck, 0, 0, 0, 0, 0, 0); @@ -498,9 +723,8 @@ static void veth_statemachine(void *p) } else { if ( (rc != HvLpEvent_Rc_PartitionDead) && (rc != HvLpEvent_Rc_PathClosed) ) - veth_error("Error sending monitor to " - "lpar %d, rc=%x\n", - rlp, (int) rc); + veth_error("Error sending monitor to LPAR %d, " + "rc = %d\n", rlp, rc); /* Oh well, hope we get a cap from the other * end and do better when that kicks us */ @@ -512,7 +736,7 @@ static void veth_statemachine(void *p) && !(cnx->state & VETH_STATE_SENTCAPS)) { u64 *rawcap = (u64 *)&cnx->local_caps; - rc = veth_signalevent(cnx, VethEventTypeCap, + rc = veth_signalevent(cnx, VETH_EVENT_CAP, HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, 0, rawcap[0], rawcap[1], rawcap[2], @@ -523,9 +747,9 @@ static void veth_statemachine(void *p) } else { if ( (rc != HvLpEvent_Rc_PartitionDead) && (rc != HvLpEvent_Rc_PathClosed) ) - veth_error("Error sending caps to " - "lpar %d, rc=%x\n", - rlp, (int) rc); + veth_error("Error sending caps to LPAR %d, " + "rc = %d\n", rlp, rc); + /* Oh well, hope we get a cap from the other * end and do better when that kicks us */ goto out; @@ -534,7 +758,7 @@ static void veth_statemachine(void *p) if ((cnx->state & VETH_STATE_GOTCAPS) && !(cnx->state & VETH_STATE_SENTCAPACK)) { - struct VethCapData *remote_caps = &cnx->remote_caps; + struct veth_cap_data *remote_caps = &cnx->remote_caps; memcpy(remote_caps, &cnx->cap_event.u.caps_data, sizeof(*remote_caps)); @@ -565,10 +789,8 @@ static void veth_statemachine(void *p) add_timer(&cnx->ack_timer); cnx->state |= VETH_STATE_READY; } else { - veth_printk(KERN_ERR, "Caps rejected (rc=%d) by " - "lpar %d\n", - cnx->cap_ack_event.base_event.xRc, - rlp); + veth_error("Caps rejected by LPAR %d, rc = %d\n", + rlp, cnx->cap_ack_event.base_event.xRc); goto cant_cope; } } @@ -581,8 +803,8 @@ static void veth_statemachine(void *p) /* FIXME: we get here if something happens we really can't * cope with. The link will never work once we get here, and * all we can do is not lock the rest of the system up */ - veth_error("Badness on connection to lpar %d (state=%04lx) " - " - shutting down\n", rlp, cnx->state); + veth_error("Unrecoverable error on connection to LPAR %d, shutting down" + " (state = 0x%04lx)\n", rlp, cnx->state); cnx->state |= VETH_STATE_SHUTDOWN; spin_unlock_irq(&cnx->lock); } @@ -591,7 +813,7 @@ static int veth_init_connection(u8 rlp) { struct veth_lpar_connection *cnx; struct veth_msg *msgs; - int i; + int i, rc; if ( (rlp == this_lp) || ! HvLpConfig_doLpsCommunicateOnVirtualLan(this_lp, rlp) ) @@ -605,22 +827,36 @@ static int veth_init_connection(u8 rlp) cnx->remote_lp = rlp; spin_lock_init(&cnx->lock); INIT_WORK(&cnx->statemachine_wq, veth_statemachine, cnx); + init_timer(&cnx->ack_timer); cnx->ack_timer.function = veth_timed_ack; cnx->ack_timer.data = (unsigned long) cnx; + + init_timer(&cnx->reset_timer); + cnx->reset_timer.function = veth_timed_reset; + cnx->reset_timer.data = (unsigned long) cnx; + cnx->reset_timeout = 5 * HZ * (VETH_ACKTIMEOUT / 1000000); + memset(&cnx->pending_acks, 0xff, sizeof (cnx->pending_acks)); veth_cnx[rlp] = cnx; + /* This gets us 1 reference, which is held on behalf of the driver + * infrastructure. It's released at module unload. */ + kobject_init(&cnx->kobject); + cnx->kobject.ktype = &veth_lpar_connection_ktype; + rc = kobject_set_name(&cnx->kobject, "cnx%.2d", rlp); + if (rc != 0) + return rc; + msgs = kmalloc(VETH_NUMBUFFERS * sizeof(struct veth_msg), GFP_KERNEL); if (! msgs) { - veth_error("Can't allocate buffers for lpar %d\n", rlp); + veth_error("Can't allocate buffers for LPAR %d.\n", rlp); return -ENOMEM; } cnx->msgs = msgs; memset(msgs, 0, VETH_NUMBUFFERS * sizeof(struct veth_msg)); - spin_lock_init(&cnx->msg_stack_lock); for (i = 0; i < VETH_NUMBUFFERS; i++) { msgs[i].token = i; @@ -630,8 +866,7 @@ static int veth_init_connection(u8 rlp) cnx->num_events = veth_allocate_events(rlp, 2 + VETH_NUMBUFFERS); if (cnx->num_events < (2 + VETH_NUMBUFFERS)) { - veth_error("Can't allocate events for lpar %d, only got %d\n", - rlp, cnx->num_events); + veth_error("Can't allocate enough events for LPAR %d.\n", rlp); return -ENOMEM; } @@ -642,11 +877,9 @@ static int veth_init_connection(u8 rlp) return 0; } -static void veth_stop_connection(u8 rlp) +static void veth_stop_connection(struct veth_lpar_connection *cnx) { - struct veth_lpar_connection *cnx = veth_cnx[rlp]; - - if (! cnx) + if (!cnx) return; spin_lock_irq(&cnx->lock); @@ -654,12 +887,23 @@ static void veth_stop_connection(u8 rlp) veth_kick_statemachine(cnx); spin_unlock_irq(&cnx->lock); + /* There's a slim chance the reset code has just queued the + * statemachine to run in five seconds. If so we need to cancel + * that and requeue the work to run now. */ + if (cancel_delayed_work(&cnx->statemachine_wq)) { + spin_lock_irq(&cnx->lock); + veth_kick_statemachine(cnx); + spin_unlock_irq(&cnx->lock); + } + + /* Wait for the state machine to run. */ flush_scheduled_work(); +} - /* FIXME: not sure if this is necessary - will already have - * been deleted by the state machine, just want to make sure - * its not running any more */ - del_timer_sync(&cnx->ack_timer); +static void veth_destroy_connection(struct veth_lpar_connection *cnx) +{ + if (!cnx) + return; if (cnx->num_events > 0) mf_deallocate_lp_events(cnx->remote_lp, @@ -671,18 +915,18 @@ static void veth_stop_connection(u8 rlp) HvLpEvent_Type_VirtualLan, cnx->num_ack_events, NULL, NULL); -} - -static void veth_destroy_connection(u8 rlp) -{ - struct veth_lpar_connection *cnx = veth_cnx[rlp]; - - if (! cnx) - return; kfree(cnx->msgs); + veth_cnx[cnx->remote_lp] = NULL; kfree(cnx); - veth_cnx[rlp] = NULL; +} + +static void veth_release_connection(struct kobject *kobj) +{ + struct veth_lpar_connection *cnx; + cnx = container_of(kobj, struct veth_lpar_connection, kobject); + veth_stop_connection(cnx); + veth_destroy_connection(cnx); } /* @@ -726,17 +970,15 @@ static void veth_set_multicast_list(struct net_device *dev) write_lock_irqsave(&port->mcast_gate, flags); - if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ - printk(KERN_INFO "%s: Promiscuous mode enabled.\n", - dev->name); + if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || + (dev->mc_count > VETH_MAX_MCAST)) { port->promiscuous = 1; - } else if ( (dev->flags & IFF_ALLMULTI) - || (dev->mc_count > VETH_MAX_MCAST) ) { - port->all_mcast = 1; } else { struct dev_mc_list *dmi = dev->mc_list; int i; + port->promiscuous = 0; + /* Update table */ port->num_mcast = 0; @@ -758,9 +1000,10 @@ static void veth_set_multicast_list(struct net_device *dev) static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { - strncpy(info->driver, "veth", sizeof(info->driver) - 1); + strncpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); info->driver[sizeof(info->driver) - 1] = '\0'; - strncpy(info->version, "1.0", sizeof(info->version) - 1); + strncpy(info->version, DRV_VERSION, sizeof(info->version) - 1); + info->version[sizeof(info->version) - 1] = '\0'; } static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) @@ -791,49 +1034,6 @@ static struct ethtool_ops ops = { .get_link = veth_get_link, }; -static void veth_tx_timeout(struct net_device *dev) -{ - struct veth_port *port = (struct veth_port *)dev->priv; - struct net_device_stats *stats = &port->stats; - unsigned long flags; - int i; - - stats->tx_errors++; - - spin_lock_irqsave(&port->pending_gate, flags); - - if (!port->pending_lpmask) { - spin_unlock_irqrestore(&port->pending_gate, flags); - return; - } - - printk(KERN_WARNING "%s: Tx timeout! Resetting lp connections: %08x\n", - dev->name, port->pending_lpmask); - - for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { - struct veth_lpar_connection *cnx = veth_cnx[i]; - - if (! (port->pending_lpmask & (1<<i))) - continue; - - /* If we're pending on it, we must be connected to it, - * so we should certainly have a structure for it. */ - BUG_ON(! cnx); - - /* Theoretically we could be kicking a connection - * which doesn't deserve it, but in practice if we've - * had a Tx timeout, the pending_lpmask will have - * exactly one bit set - the connection causing the - * problem. */ - spin_lock(&cnx->lock); - cnx->state |= VETH_STATE_RESET; - veth_kick_statemachine(cnx); - spin_unlock(&cnx->lock); - } - - spin_unlock_irqrestore(&port->pending_gate, flags); -} - static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) { struct net_device *dev; @@ -848,8 +1048,9 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) port = (struct veth_port *) dev->priv; - spin_lock_init(&port->pending_gate); + spin_lock_init(&port->queue_lock); rwlock_init(&port->mcast_gate); + port->stopped_map = 0; for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { HvLpVirtualLanIndexMap map; @@ -882,22 +1083,24 @@ static struct net_device * __init veth_probe_one(int vlan, struct device *vdev) dev->set_multicast_list = veth_set_multicast_list; SET_ETHTOOL_OPS(dev, &ops); - dev->watchdog_timeo = 2 * (VETH_ACKTIMEOUT * HZ / 1000000); - dev->tx_timeout = veth_tx_timeout; - SET_NETDEV_DEV(dev, vdev); rc = register_netdev(dev); if (rc != 0) { - veth_printk(KERN_ERR, - "Failed to register ethernet device for vlan %d\n", - vlan); + veth_error("Failed registering net device for vlan%d.\n", vlan); free_netdev(dev); return NULL; } - veth_printk(KERN_DEBUG, "%s attached to iSeries vlan %d (lpar_map=0x%04x)\n", - dev->name, vlan, port->lpar_map); + kobject_init(&port->kobject); + port->kobject.parent = &dev->class_dev.kobj; + port->kobject.ktype = &veth_port_ktype; + kobject_set_name(&port->kobject, "veth_port"); + if (0 != kobject_add(&port->kobject)) + veth_error("Failed adding port for %s to sysfs.\n", dev->name); + + veth_info("%s attached to iSeries vlan %d (LPAR map = 0x%.4X)\n", + dev->name, vlan, port->lpar_map); return dev; } @@ -912,98 +1115,95 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp, struct veth_lpar_connection *cnx = veth_cnx[rlp]; struct veth_port *port = (struct veth_port *) dev->priv; HvLpEvent_Rc rc; - u32 dma_address, dma_length; struct veth_msg *msg = NULL; - int err = 0; unsigned long flags; - if (! cnx) { - port->stats.tx_errors++; - dev_kfree_skb(skb); + if (! cnx) return 0; - } spin_lock_irqsave(&cnx->lock, flags); if (! (cnx->state & VETH_STATE_READY)) - goto drop; + goto no_error; - if ((skb->len - 14) > VETH_MAX_MTU) + if ((skb->len - ETH_HLEN) > VETH_MAX_MTU) goto drop; msg = veth_stack_pop(cnx); - - if (! msg) { - err = 1; + if (! msg) goto drop; - } - dma_length = skb->len; - dma_address = dma_map_single(port->dev, skb->data, - dma_length, DMA_TO_DEVICE); + msg->in_use = 1; + msg->skb = skb_get(skb); + + msg->data.addr[0] = dma_map_single(port->dev, skb->data, + skb->len, DMA_TO_DEVICE); - if (dma_mapping_error(dma_address)) + if (dma_mapping_error(msg->data.addr[0])) goto recycle_and_drop; - /* Is it really necessary to check the length and address - * fields of the first entry here? */ - msg->skb = skb; msg->dev = port->dev; - msg->data.addr[0] = dma_address; - msg->data.len[0] = dma_length; + msg->data.len[0] = skb->len; msg->data.eofmask = 1 << VETH_EOF_SHIFT; - set_bit(0, &(msg->in_use)); - rc = veth_signaldata(cnx, VethEventTypeFrames, msg->token, &msg->data); + + rc = veth_signaldata(cnx, VETH_EVENT_FRAMES, msg->token, &msg->data); if (rc != HvLpEvent_Rc_Good) goto recycle_and_drop; + /* If the timer's not already running, start it now. */ + if (0 == cnx->outstanding_tx) + mod_timer(&cnx->reset_timer, jiffies + cnx->reset_timeout); + + cnx->last_contact = jiffies; + cnx->outstanding_tx++; + + if (veth_stack_is_empty(cnx)) + veth_stop_queues(cnx); + + no_error: spin_unlock_irqrestore(&cnx->lock, flags); return 0; recycle_and_drop: - msg->skb = NULL; - /* need to set in use to make veth_recycle_msg in case this - * was a mapping failure */ - set_bit(0, &msg->in_use); veth_recycle_msg(cnx, msg); drop: - port->stats.tx_errors++; - dev_kfree_skb(skb); spin_unlock_irqrestore(&cnx->lock, flags); - return err; + return 1; } -static HvLpIndexMap veth_transmit_to_many(struct sk_buff *skb, +static void veth_transmit_to_many(struct sk_buff *skb, HvLpIndexMap lpmask, struct net_device *dev) { struct veth_port *port = (struct veth_port *) dev->priv; - int i; - int rc; + int i, success, error; + + success = error = 0; for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { if ((lpmask & (1 << i)) == 0) continue; - rc = veth_transmit_to_one(skb_get(skb), i, dev); - if (! rc) - lpmask &= ~(1<<i); + if (veth_transmit_to_one(skb, i, dev)) + error = 1; + else + success = 1; } - if (! lpmask) { + if (error) + port->stats.tx_errors++; + + if (success) { port->stats.tx_packets++; port->stats.tx_bytes += skb->len; } - - return lpmask; } static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) { unsigned char *frame = skb->data; struct veth_port *port = (struct veth_port *) dev->priv; - unsigned long flags; HvLpIndexMap lpmask; if (! (frame[0] & 0x01)) { @@ -1020,44 +1220,27 @@ static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev) lpmask = port->lpar_map; } - spin_lock_irqsave(&port->pending_gate, flags); - - lpmask = veth_transmit_to_many(skb, lpmask, dev); - - dev->trans_start = jiffies; + veth_transmit_to_many(skb, lpmask, dev); - if (! lpmask) { - dev_kfree_skb(skb); - } else { - if (port->pending_skb) { - veth_error("%s: Tx while skb was pending!\n", - dev->name); - dev_kfree_skb(skb); - spin_unlock_irqrestore(&port->pending_gate, flags); - return 1; - } - - port->pending_skb = skb; - port->pending_lpmask = lpmask; - netif_stop_queue(dev); - } - - spin_unlock_irqrestore(&port->pending_gate, flags); + dev_kfree_skb(skb); return 0; } +/* You must hold the connection's lock when you call this function. */ static void veth_recycle_msg(struct veth_lpar_connection *cnx, struct veth_msg *msg) { u32 dma_address, dma_length; - if (test_and_clear_bit(0, &msg->in_use)) { + if (msg->in_use) { + msg->in_use = 0; dma_address = msg->data.addr[0]; dma_length = msg->data.len[0]; - dma_unmap_single(msg->dev, dma_address, dma_length, - DMA_TO_DEVICE); + if (!dma_mapping_error(dma_address)) + dma_unmap_single(msg->dev, dma_address, dma_length, + DMA_TO_DEVICE); if (msg->skb) { dev_kfree_skb_any(msg->skb); @@ -1066,15 +1249,16 @@ static void veth_recycle_msg(struct veth_lpar_connection *cnx, memset(&msg->data, 0, sizeof(msg->data)); veth_stack_push(cnx, msg); - } else - if (cnx->state & VETH_STATE_OPEN) - veth_error("Bogus frames ack from lpar %d (#%d)\n", - cnx->remote_lp, msg->token); + } else if (cnx->state & VETH_STATE_OPEN) { + veth_error("Non-pending frame (# %d) acked by LPAR %d.\n", + cnx->remote_lp, msg->token); + } } -static void veth_flush_pending(struct veth_lpar_connection *cnx) +static void veth_wake_queues(struct veth_lpar_connection *cnx) { int i; + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { struct net_device *dev = veth_dev[i]; struct veth_port *port; @@ -1088,20 +1272,77 @@ static void veth_flush_pending(struct veth_lpar_connection *cnx) if (! (port->lpar_map & (1<<cnx->remote_lp))) continue; - spin_lock_irqsave(&port->pending_gate, flags); - if (port->pending_skb) { - port->pending_lpmask = - veth_transmit_to_many(port->pending_skb, - port->pending_lpmask, - dev); - if (! port->pending_lpmask) { - dev_kfree_skb_any(port->pending_skb); - port->pending_skb = NULL; - netif_wake_queue(dev); - } + spin_lock_irqsave(&port->queue_lock, flags); + + port->stopped_map &= ~(1 << cnx->remote_lp); + + if (0 == port->stopped_map && netif_queue_stopped(dev)) { + veth_debug("cnx %d: woke queue for %s.\n", + cnx->remote_lp, dev->name); + netif_wake_queue(dev); + } + spin_unlock_irqrestore(&port->queue_lock, flags); + } +} + +static void veth_stop_queues(struct veth_lpar_connection *cnx) +{ + int i; + + for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) { + struct net_device *dev = veth_dev[i]; + struct veth_port *port; + + if (! dev) + continue; + + port = (struct veth_port *)dev->priv; + + /* If this cnx is not on the vlan for this port, continue */ + if (! (port->lpar_map & (1 << cnx->remote_lp))) + continue; + + spin_lock(&port->queue_lock); + + netif_stop_queue(dev); + port->stopped_map |= (1 << cnx->remote_lp); + + veth_debug("cnx %d: stopped queue for %s, map = 0x%x.\n", + cnx->remote_lp, dev->name, port->stopped_map); + + spin_unlock(&port->queue_lock); + } +} + +static void veth_timed_reset(unsigned long ptr) +{ + struct veth_lpar_connection *cnx = (struct veth_lpar_connection *)ptr; + unsigned long trigger_time, flags; + + /* FIXME is it possible this fires after veth_stop_connection()? + * That would reschedule the statemachine for 5 seconds and probably + * execute it after the module's been unloaded. Hmm. */ + + spin_lock_irqsave(&cnx->lock, flags); + + if (cnx->outstanding_tx > 0) { + trigger_time = cnx->last_contact + cnx->reset_timeout; + + if (trigger_time < jiffies) { + cnx->state |= VETH_STATE_RESET; + veth_kick_statemachine(cnx); + veth_error("%d packets not acked by LPAR %d within %d " + "seconds, resetting.\n", + cnx->outstanding_tx, cnx->remote_lp, + cnx->reset_timeout / HZ); + } else { + /* Reschedule the timer */ + trigger_time = jiffies + cnx->reset_timeout; + mod_timer(&cnx->reset_timer, trigger_time); } - spin_unlock_irqrestore(&port->pending_gate, flags); } + + spin_unlock_irqrestore(&cnx->lock, flags); } /* @@ -1117,12 +1358,9 @@ static inline int veth_frame_wanted(struct veth_port *port, u64 mac_addr) if ( (mac_addr == port->mac_addr) || (mac_addr == 0xffffffffffff0000) ) return 1; - if (! (((char *) &mac_addr)[0] & 0x01)) - return 0; - read_lock_irqsave(&port->mcast_gate, flags); - if (port->promiscuous || port->all_mcast) { + if (port->promiscuous) { wanted = 1; goto out; } @@ -1175,21 +1413,21 @@ static void veth_flush_acks(struct veth_lpar_connection *cnx) { HvLpEvent_Rc rc; - rc = veth_signaldata(cnx, VethEventTypeFramesAck, + rc = veth_signaldata(cnx, VETH_EVENT_FRAMES_ACK, 0, &cnx->pending_acks); if (rc != HvLpEvent_Rc_Good) - veth_error("Error 0x%x acking frames from lpar %d!\n", - (unsigned)rc, cnx->remote_lp); + veth_error("Failed acking frames from LPAR %d, rc = %d\n", + cnx->remote_lp, (int)rc); cnx->num_pending_acks = 0; memset(&cnx->pending_acks, 0xff, sizeof(cnx->pending_acks)); } static void veth_receive(struct veth_lpar_connection *cnx, - struct VethLpEvent *event) + struct veth_lpevent *event) { - struct VethFramesData *senddata = &event->u.frames_data; + struct veth_frames_data *senddata = &event->u.frames_data; int startchunk = 0; int nchunks; unsigned long flags; @@ -1216,9 +1454,10 @@ static void veth_receive(struct veth_lpar_connection *cnx, /* make sure that we have at least 1 EOF entry in the * remaining entries */ if (! (senddata->eofmask >> (startchunk + VETH_EOF_SHIFT))) { - veth_error("missing EOF frag in event " - "eofmask=0x%x startchunk=%d\n", - (unsigned) senddata->eofmask, startchunk); + veth_error("Missing EOF fragment in event " + "eofmask = 0x%x startchunk = %d\n", + (unsigned)senddata->eofmask, + startchunk); break; } @@ -1237,8 +1476,9 @@ static void veth_receive(struct veth_lpar_connection *cnx, /* nchunks == # of chunks in this frame */ if ((length - ETH_HLEN) > VETH_MAX_MTU) { - veth_error("Received oversize frame from lpar %d " - "(length=%d)\n", cnx->remote_lp, length); + veth_error("Received oversize frame from LPAR %d " + "(length = %d)\n", + cnx->remote_lp, length); continue; } @@ -1331,15 +1571,33 @@ static void veth_timed_ack(unsigned long ptr) static int veth_remove(struct vio_dev *vdev) { - int i = vdev->unit_address; + struct veth_lpar_connection *cnx; struct net_device *dev; + struct veth_port *port; + int i; - dev = veth_dev[i]; - if (dev != NULL) { - veth_dev[i] = NULL; - unregister_netdev(dev); - free_netdev(dev); + dev = veth_dev[vdev->unit_address]; + + if (! dev) + return 0; + + port = netdev_priv(dev); + + for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { + cnx = veth_cnx[i]; + + if (cnx && (port->lpar_map & (1 << i))) { + /* Drop our reference to connections on our VLAN */ + kobject_put(&cnx->kobject); + } } + + veth_dev[vdev->unit_address] = NULL; + kobject_del(&port->kobject); + kobject_put(&port->kobject); + unregister_netdev(dev); + free_netdev(dev); + return 0; } @@ -1347,6 +1605,7 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) { int i = vdev->unit_address; struct net_device *dev; + struct veth_port *port; dev = veth_probe_one(i, &vdev->dev); if (dev == NULL) { @@ -1355,11 +1614,23 @@ static int veth_probe(struct vio_dev *vdev, const struct vio_device_id *id) } veth_dev[i] = dev; - /* Start the state machine on each connection, to commence - * link negotiation */ - for (i = 0; i < HVMAXARCHITECTEDLPS; i++) - if (veth_cnx[i]) - veth_kick_statemachine(veth_cnx[i]); + port = (struct veth_port*)netdev_priv(dev); + + /* Start the state machine on each connection on this vlan. If we're + * the first dev to do so this will commence link negotiation */ + for (i = 0; i < HVMAXARCHITECTEDLPS; i++) { + struct veth_lpar_connection *cnx; + + if (! (port->lpar_map & (1 << i))) + continue; + + cnx = veth_cnx[i]; + if (!cnx) + continue; + + kobject_get(&cnx->kobject); + veth_kick_statemachine(cnx); + } return 0; } @@ -1375,7 +1646,7 @@ static struct vio_device_id veth_device_table[] __devinitdata = { MODULE_DEVICE_TABLE(vio, veth_device_table); static struct vio_driver veth_driver = { - .name = "iseries_veth", + .name = DRV_NAME, .id_table = veth_device_table, .probe = veth_probe, .remove = veth_remove @@ -1388,29 +1659,29 @@ static struct vio_driver veth_driver = { void __exit veth_module_cleanup(void) { int i; + struct veth_lpar_connection *cnx; - /* Stop the queues first to stop any new packets being sent. */ - for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) - if (veth_dev[i]) - netif_stop_queue(veth_dev[i]); - - /* Stop the connections before we unregister the driver. This - * ensures there's no skbs lying around holding the device open. */ - for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) - veth_stop_connection(i); - + /* Disconnect our "irq" to stop events coming from the Hypervisor. */ HvLpEvent_unregisterHandler(HvLpEvent_Type_VirtualLan); - /* Hypervisor callbacks may have scheduled more work while we - * were stoping connections. Now that we've disconnected from - * the hypervisor make sure everything's finished. */ + /* Make sure any work queued from Hypervisor callbacks is finished. */ flush_scheduled_work(); - vio_unregister_driver(&veth_driver); + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + cnx = veth_cnx[i]; + + if (!cnx) + continue; - for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) - veth_destroy_connection(i); + /* Remove the connection from sysfs */ + kobject_del(&cnx->kobject); + /* Drop the driver's reference to the connection */ + kobject_put(&cnx->kobject); + } + /* Unregister the driver, which will close all the netdevs and stop + * the connections when they're no longer referenced. */ + vio_unregister_driver(&veth_driver); } module_exit(veth_module_cleanup); @@ -1423,15 +1694,37 @@ int __init veth_module_init(void) for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { rc = veth_init_connection(i); - if (rc != 0) { - veth_module_cleanup(); - return rc; - } + if (rc != 0) + goto error; } HvLpEvent_registerHandler(HvLpEvent_Type_VirtualLan, &veth_handle_event); - return vio_register_driver(&veth_driver); + rc = vio_register_driver(&veth_driver); + if (rc != 0) + goto error; + + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + struct kobject *kobj; + + if (!veth_cnx[i]) + continue; + + kobj = &veth_cnx[i]->kobject; + kobj->parent = &veth_driver.driver.kobj; + /* If the add failes, complain but otherwise continue */ + if (0 != kobject_add(kobj)) + veth_error("cnx %d: Failed adding to sysfs.\n", i); + } + + return 0; + +error: + for (i = 0; i < HVMAXARCHITECTEDLPS; ++i) { + veth_destroy_connection(veth_cnx[i]); + } + + return rc; } module_init(veth_module_init); diff --git a/drivers/net/iseries_veth.h b/drivers/net/iseries_veth.h deleted file mode 100644 index d9370f79b83..00000000000 --- a/drivers/net/iseries_veth.h +++ /dev/null @@ -1,46 +0,0 @@ -/* File veth.h created by Kyle A. Lucke on Mon Aug 7 2000. */ - -#ifndef _ISERIES_VETH_H -#define _ISERIES_VETH_H - -#define VethEventTypeCap (0) -#define VethEventTypeFrames (1) -#define VethEventTypeMonitor (2) -#define VethEventTypeFramesAck (3) - -#define VETH_MAX_ACKS_PER_MSG (20) -#define VETH_MAX_FRAMES_PER_MSG (6) - -struct VethFramesData { - u32 addr[VETH_MAX_FRAMES_PER_MSG]; - u16 len[VETH_MAX_FRAMES_PER_MSG]; - u32 eofmask; -}; -#define VETH_EOF_SHIFT (32-VETH_MAX_FRAMES_PER_MSG) - -struct VethFramesAckData { - u16 token[VETH_MAX_ACKS_PER_MSG]; -}; - -struct VethCapData { - u8 caps_version; - u8 rsvd1; - u16 num_buffers; - u16 ack_threshold; - u16 rsvd2; - u32 ack_timeout; - u32 rsvd3; - u64 rsvd4[3]; -}; - -struct VethLpEvent { - struct HvLpEvent base_event; - union { - struct VethCapData caps_data; - struct VethFramesData frames_data; - struct VethFramesAckData frames_ack_data; - } u; - -}; - -#endif /* _ISERIES_VETH_H */ diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c index fc353e348f9..a22d00198e4 100644 --- a/drivers/net/tulip/de2104x.c +++ b/drivers/net/tulip/de2104x.c @@ -1934,7 +1934,7 @@ static int __init de_init_one (struct pci_dev *pdev, struct de_private *de; int rc; void __iomem *regs; - long pciaddr; + unsigned long pciaddr; static int board_idx = -1; board_idx++; diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index 05da5bea564..6266a9a7e6e 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -238,6 +238,7 @@ static struct pci_device_id tulip_pci_tbl[] = { { 0x17B3, 0xAB08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { 0x10b7, 0x9300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* 3Com 3CSOHO100B-TX */ { 0x14ea, 0xab08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, /* Planex FNW-3602-TX */ + { 0x1414, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET }, { } /* terminate list */ }; MODULE_DEVICE_TABLE(pci, tulip_pci_tbl); diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index 713c78f3a65..49bd2170231 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c @@ -21,13 +21,21 @@ * between the ROM and other resources, so enabling it may disable access * to MMIO registers or other card memory. */ -static void pci_enable_rom(struct pci_dev *pdev) +static int pci_enable_rom(struct pci_dev *pdev) { + struct resource *res = pdev->resource + PCI_ROM_RESOURCE; + struct pci_bus_region region; u32 rom_addr; + if (!res->flags) + return -1; + + pcibios_resource_to_bus(pdev, ®ion, res); pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr); - rom_addr |= PCI_ROM_ADDRESS_ENABLE; + rom_addr &= ~PCI_ROM_ADDRESS_MASK; + rom_addr |= region.start | PCI_ROM_ADDRESS_ENABLE; pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr); + return 0; } /** @@ -71,19 +79,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) } else { if (res->flags & IORESOURCE_ROM_COPY) { *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); - return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE); + return (void __iomem *)pci_resource_start(pdev, + PCI_ROM_RESOURCE); } else { /* assign the ROM an address if it doesn't have one */ - if (res->parent == NULL) - pci_assign_resource(pdev, PCI_ROM_RESOURCE); - + if (res->parent == NULL && + pci_assign_resource(pdev,PCI_ROM_RESOURCE)) + return NULL; start = pci_resource_start(pdev, PCI_ROM_RESOURCE); *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); if (*size == 0) return NULL; /* Enable ROM space decodes */ - pci_enable_rom(pdev); + if (pci_enable_rom(pdev)) + return NULL; } } diff --git a/drivers/serial/21285.c b/drivers/serial/21285.c index 0b10169961e..aec39fb261c 100644 --- a/drivers/serial/21285.c +++ b/drivers/serial/21285.c @@ -58,8 +58,7 @@ static const char serial21285_name[] = "Footbridge UART"; * int((BAUD_BASE - (baud >> 1)) / baud) */ -static void -serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void serial21285_stop_tx(struct uart_port *port) { if (tx_enabled(port)) { disable_irq(IRQ_CONTX); @@ -67,8 +66,7 @@ serial21285_stop_tx(struct uart_port *port, unsigned int tty_stop) } } -static void -serial21285_start_tx(struct uart_port *port, unsigned int tty_start) +static void serial21285_start_tx(struct uart_port *port) { if (!tx_enabled(port)) { enable_irq(IRQ_CONTX); @@ -148,7 +146,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r goto out; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - serial21285_stop_tx(port, 0); + serial21285_stop_tx(port); goto out; } @@ -164,7 +162,7 @@ static irqreturn_t serial21285_tx_chars(int irq, void *dev_id, struct pt_regs *r uart_write_wakeup(port); if (uart_circ_empty(xmit)) - serial21285_stop_tx(port, 0); + serial21285_stop_tx(port); out: return IRQ_HANDLED; diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 7e8fc7c1d4c..30a0a3d1014 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -1001,7 +1001,7 @@ static inline void __stop_tx(struct uart_8250_port *p) } } -static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void serial8250_stop_tx(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; @@ -1018,7 +1018,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) static void transmit_chars(struct uart_8250_port *up); -static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) +static void serial8250_start_tx(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; @@ -1158,7 +1158,11 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) up->port.x_char = 0; return; } - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { + if (uart_tx_stopped(&up->port)) { + serial8250_stop_tx(&up->port); + return; + } + if (uart_circ_empty(xmit)) { __stop_tx(up); return; } @@ -2586,82 +2590,3 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); #endif MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); - -/** - * register_serial - configure a 16x50 serial port at runtime - * @req: request structure - * - * Configure the serial port specified by the request. If the - * port exists and is in use an error is returned. If the port - * is not currently in the table it is added. - * - * The port is then probed and if necessary the IRQ is autodetected - * If this fails an error is returned. - * - * On success the port is ready to use and the line number is returned. - * - * Note: this function is deprecated - use serial8250_register_port - * instead. - */ -int register_serial(struct serial_struct *req) -{ - struct uart_port port; - - port.iobase = req->port; - port.membase = req->iomem_base; - port.irq = req->irq; - port.uartclk = req->baud_base * 16; - port.fifosize = req->xmit_fifo_size; - port.regshift = req->iomem_reg_shift; - port.iotype = req->io_type; - port.flags = req->flags | UPF_BOOT_AUTOCONF; - port.mapbase = req->iomap_base; - port.dev = NULL; - - if (share_irqs) - port.flags |= UPF_SHARE_IRQ; - - if (HIGH_BITS_OFFSET) - port.iobase |= (long) req->port_high << HIGH_BITS_OFFSET; - - /* - * If a clock rate wasn't specified by the low level driver, then - * default to the standard clock rate. This should be 115200 (*16) - * and should not depend on the architecture's BASE_BAUD definition. - * However, since this API will be deprecated, it's probably a - * better idea to convert the drivers to use the new API - * (serial8250_register_port and serial8250_unregister_port). - */ - if (port.uartclk == 0) { - printk(KERN_WARNING - "Serial: registering port at [%08x,%08lx,%p] irq %d with zero baud_base\n", - port.iobase, port.mapbase, port.membase, port.irq); - printk(KERN_WARNING "Serial: see %s:%d for more information\n", - __FILE__, __LINE__); - dump_stack(); - - /* - * Fix it up for now, but this is only a temporary measure. - */ - port.uartclk = BASE_BAUD * 16; - } - - return serial8250_register_port(&port); -} -EXPORT_SYMBOL(register_serial); - -/** - * unregister_serial - remove a 16x50 serial port at runtime - * @line: serial line number - * - * Remove one serial port. This may not be called from interrupt - * context. We hand the port back to our local PM control. - * - * Note: this function is deprecated - use serial8250_unregister_port - * instead. - */ -void unregister_serial(int line) -{ - serial8250_unregister_port(line); -} -EXPORT_SYMBOL(unregister_serial); diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index 9225c82faeb..b1b459efda5 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -16,11 +16,7 @@ */ #include <linux/config.h> - -int serial8250_register_port(struct uart_port *); -void serial8250_unregister_port(int line); -void serial8250_suspend_port(int line); -void serial8250_resume_port(int line); +#include <linux/serial_8250.h> struct old_serial_port { unsigned int uart; diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index d5797618a3b..74b80f7c062 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -830,7 +830,7 @@ config SERIAL_M32R_PLDSIO config SERIAL_TXX9 bool "TMPTX39XX/49XX SIO support" - depends HAS_TXX9_SERIAL + depends HAS_TXX9_SERIAL && BROKEN select SERIAL_CORE default y diff --git a/drivers/serial/amba-pl010.c b/drivers/serial/amba-pl010.c index 2884b310e54..978e12437e6 100644 --- a/drivers/serial/amba-pl010.c +++ b/drivers/serial/amba-pl010.c @@ -105,7 +105,7 @@ struct uart_amba_port { unsigned int old_status; }; -static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void pl010_stop_tx(struct uart_port *port) { unsigned int cr; @@ -114,7 +114,7 @@ static void pl010_stop_tx(struct uart_port *port, unsigned int tty_stop) UART_PUT_CR(port, cr); } -static void pl010_start_tx(struct uart_port *port, unsigned int tty_start) +static void pl010_start_tx(struct uart_port *port) { unsigned int cr; @@ -219,7 +219,7 @@ static void pl010_tx_chars(struct uart_port *port) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - pl010_stop_tx(port, 0); + pl010_stop_tx(port); return; } @@ -236,7 +236,7 @@ static void pl010_tx_chars(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - pl010_stop_tx(port, 0); + pl010_stop_tx(port); } static void pl010_modem_status(struct uart_port *port) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 7db88ee18f7..56071309744 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -74,7 +74,7 @@ struct uart_amba_port { unsigned int old_status; }; -static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void pl011_stop_tx(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -82,7 +82,7 @@ static void pl011_stop_tx(struct uart_port *port, unsigned int tty_stop) writew(uap->im, uap->port.membase + UART011_IMSC); } -static void pl011_start_tx(struct uart_port *port, unsigned int tty_start) +static void pl011_start_tx(struct uart_port *port) { struct uart_amba_port *uap = (struct uart_amba_port *)port; @@ -184,7 +184,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) { - pl011_stop_tx(&uap->port, 0); + pl011_stop_tx(&uap->port); return; } @@ -201,7 +201,7 @@ static void pl011_tx_chars(struct uart_amba_port *uap) uart_write_wakeup(&uap->port); if (uart_circ_empty(xmit)) - pl011_stop_tx(&uap->port, 0); + pl011_stop_tx(&uap->port); } static void pl011_modem_status(struct uart_amba_port *uap) diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c index 6104aeef124..a274ebf256a 100644 --- a/drivers/serial/au1x00_uart.c +++ b/drivers/serial/au1x00_uart.c @@ -200,7 +200,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) DEBUG_AUTOCONF("type=%s\n", uart_config[up->port.type].name); } -static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void serial8250_stop_tx(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; @@ -210,7 +210,7 @@ static void serial8250_stop_tx(struct uart_port *port, unsigned int tty_stop) } } -static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start) +static void serial8250_start_tx(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; @@ -337,7 +337,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - serial8250_stop_tx(&up->port, 0); + serial8250_stop_tx(&up->port); return; } @@ -356,7 +356,7 @@ static _INLINE_ void transmit_chars(struct uart_8250_port *up) DEBUG_INTR("THRE..."); if (uart_circ_empty(xmit)) - serial8250_stop_tx(&up->port, 0); + serial8250_stop_tx(&up->port); } static _INLINE_ void check_modem_status(struct uart_8250_port *up) diff --git a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c index e92522b33c4..d822896b488 100644 --- a/drivers/serial/clps711x.c +++ b/drivers/serial/clps711x.c @@ -69,8 +69,7 @@ #define tx_enabled(port) ((port)->unused[0]) -static void -clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void clps711xuart_stop_tx(struct uart_port *port) { if (tx_enabled(port)) { disable_irq(TX_IRQ(port)); @@ -78,8 +77,7 @@ clps711xuart_stop_tx(struct uart_port *port, unsigned int tty_stop) } } -static void -clps711xuart_start_tx(struct uart_port *port, unsigned int tty_start) +static void clps711xuart_start_tx(struct uart_port *port) { if (!tx_enabled(port)) { enable_irq(TX_IRQ(port)); @@ -165,7 +163,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re return IRQ_HANDLED; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - clps711xuart_stop_tx(port, 0); + clps711xuart_stop_tx(port); return IRQ_HANDLED; } @@ -182,7 +180,7 @@ static irqreturn_t clps711xuart_int_tx(int irq, void *dev_id, struct pt_regs *re uart_write_wakeup(port); if (uart_circ_empty(xmit)) - clps711xuart_stop_tx(port, 0); + clps711xuart_stop_tx(port); return IRQ_HANDLED; } diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c index d639ac92a11..282b32351d8 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c @@ -124,7 +124,7 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port) /* * Stop transmitter */ -static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void cpm_uart_stop_tx(struct uart_port *port) { struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; volatile smc_t *smcp = pinfo->smcp; @@ -141,7 +141,7 @@ static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) /* * Start transmitter */ -static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start) +static void cpm_uart_start_tx(struct uart_port *port) { struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port; volatile smc_t *smcp = pinfo->smcp; @@ -623,7 +623,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - cpm_uart_stop_tx(port, 0); + cpm_uart_stop_tx(port); return 0; } @@ -656,7 +656,7 @@ static int cpm_uart_tx_pump(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { - cpm_uart_stop_tx(port, 0); + cpm_uart_stop_tx(port); return 0; } diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index 97824eeeafa..e63b9dffc8d 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c @@ -112,7 +112,7 @@ static inline void dz_out(struct dz_port *dport, unsigned offset, * ------------------------------------------------------------ */ -static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop) +static void dz_stop_tx(struct uart_port *uport) { struct dz_port *dport = (struct dz_port *)uport; unsigned short tmp, mask = 1 << dport->port.line; @@ -125,7 +125,7 @@ static void dz_stop_tx(struct uart_port *uport, unsigned int tty_stop) spin_unlock_irqrestore(&dport->port.lock, flags); } -static void dz_start_tx(struct uart_port *uport, unsigned int tty_start) +static void dz_start_tx(struct uart_port *uport) { struct dz_port *dport = (struct dz_port *)uport; unsigned short tmp, mask = 1 << dport->port.line; @@ -290,7 +290,7 @@ static inline void dz_transmit_chars(struct dz_port *dport) } /* if nothing to do or stopped or hardware stopped */ if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { - dz_stop_tx(&dport->port, 0); + dz_stop_tx(&dport->port); return; } @@ -308,7 +308,7 @@ static inline void dz_transmit_chars(struct dz_port *dport) /* Are we done */ if (uart_circ_empty(xmit)) - dz_stop_tx(&dport->port, 0); + dz_stop_tx(&dport->port); } /* @@ -440,7 +440,7 @@ static int dz_startup(struct uart_port *uport) */ static void dz_shutdown(struct uart_port *uport) { - dz_stop_tx(uport, 0); + dz_stop_tx(uport); } /* diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index c112b32764e..79f8df4d66b 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -989,18 +989,16 @@ static unsigned int icom_get_mctrl(struct uart_port *port) return result; } -static void icom_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void icom_stop_tx(struct uart_port *port) { unsigned char cmdReg; - if (tty_stop) { - trace(ICOM_PORT, "STOP", 0); - cmdReg = readb(&ICOM_PORT->dram->CmdReg); - writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg); - } + trace(ICOM_PORT, "STOP", 0); + cmdReg = readb(&ICOM_PORT->dram->CmdReg); + writeb(cmdReg | CMD_HOLD_XMIT, &ICOM_PORT->dram->CmdReg); } -static void icom_start_tx(struct uart_port *port, unsigned int tty_start) +static void icom_start_tx(struct uart_port *port) { unsigned char cmdReg; diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 01a8726a3f9..4c985e6b378 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c @@ -124,7 +124,7 @@ static void imx_timeout(unsigned long data) /* * interrupts disabled on entry */ -static void imx_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void imx_stop_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; UCR1((u32)sport->port.membase) &= ~UCR1_TXMPTYEN; @@ -165,13 +165,13 @@ static inline void imx_transmit_buffer(struct imx_port *sport) } while (!(UTS((u32)sport->port.membase) & UTS_TXFULL)); if (uart_circ_empty(xmit)) - imx_stop_tx(&sport->port, 0); + imx_stop_tx(&sport->port); } /* * interrupts disabled on entry */ -static void imx_start_tx(struct uart_port *port, unsigned int tty_start) +static void imx_start_tx(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; @@ -196,7 +196,7 @@ static irqreturn_t imx_txint(int irq, void *dev_id, struct pt_regs *regs) } if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { - imx_stop_tx(&sport->port, 0); + imx_stop_tx(&sport->port); goto out; } @@ -291,13 +291,31 @@ static unsigned int imx_tx_empty(struct uart_port *port) return USR2((u32)sport->port.membase) & USR2_TXDC ? TIOCSER_TEMT : 0; } +/* + * We have a modem side uart, so the meanings of RTS and CTS are inverted. + */ static unsigned int imx_get_mctrl(struct uart_port *port) { - return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + struct imx_port *sport = (struct imx_port *)port; + unsigned int tmp = TIOCM_DSR | TIOCM_CAR; + + if (USR1((u32)sport->port.membase) & USR1_RTSS) + tmp |= TIOCM_CTS; + + if (UCR2((u32)sport->port.membase) & UCR2_CTS) + tmp |= TIOCM_RTS; + + return tmp; } static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) { + struct imx_port *sport = (struct imx_port *)port; + + if (mctrl & TIOCM_RTS) + UCR2((u32)sport->port.membase) |= UCR2_CTS; + else + UCR2((u32)sport->port.membase) &= ~UCR2_CTS; } /* diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c index 793c3a7cbe4..0c5c96a582b 100644 --- a/drivers/serial/ioc4_serial.c +++ b/drivers/serial/ioc4_serial.c @@ -2373,10 +2373,9 @@ static unsigned int ic4_tx_empty(struct uart_port *the_port) /** * ic4_stop_tx - stop the transmitter * @port: Port to operate on - * @tty_stop: Set to 1 if called via uart_stop * */ -static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop) +static void ic4_stop_tx(struct uart_port *the_port) { } @@ -2471,10 +2470,9 @@ static unsigned int ic4_get_mctrl(struct uart_port *the_port) /** * ic4_start_tx - Start transmitter, flush any output * @port: Port to operate on - * @tty_stop: Set to 1 if called via uart_start * */ -static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop) +static void ic4_start_tx(struct uart_port *the_port) { struct ioc4_port *port = get_ioc4_port(the_port); unsigned long flags; diff --git a/drivers/serial/ip22zilog.c b/drivers/serial/ip22zilog.c index ea5bf4d4daa..ef132349f31 100644 --- a/drivers/serial/ip22zilog.c +++ b/drivers/serial/ip22zilog.c @@ -592,7 +592,7 @@ static void ip22zilog_set_mctrl(struct uart_port *port, unsigned int mctrl) } /* The port lock is held and interrupts are disabled. */ -static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void ip22zilog_stop_tx(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; @@ -600,7 +600,7 @@ static void ip22zilog_stop_tx(struct uart_port *port, unsigned int tty_stop) } /* The port lock is held and interrupts are disabled. */ -static void ip22zilog_start_tx(struct uart_port *port, unsigned int tty_start) +static void ip22zilog_start_tx(struct uart_port *port) { struct uart_ip22zilog_port *up = (struct uart_ip22zilog_port *) port; struct zilog_channel *channel = ZILOG_CHANNEL_FROM_PORT(port); diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 98de2258fd0..6fa0d62d6f6 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c @@ -113,7 +113,7 @@ static void jsm_tty_set_mctrl(struct uart_port *port, unsigned int mctrl) udelay(10); } -static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start) +static void jsm_tty_start_tx(struct uart_port *port) { struct jsm_channel *channel = (struct jsm_channel *)port; @@ -125,7 +125,7 @@ static void jsm_tty_start_tx(struct uart_port *port, unsigned int tty_start) jsm_printk(IOCTL, INFO, &channel->ch_bd->pci_dev, "finish\n"); } -static void jsm_tty_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void jsm_tty_stop_tx(struct uart_port *port) { struct jsm_channel *channel = (struct jsm_channel *)port; diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c index 9b50560b9d1..b0ecc7537ce 100644 --- a/drivers/serial/m32r_sio.c +++ b/drivers/serial/m32r_sio.c @@ -275,7 +275,7 @@ serial_out(struct uart_sio_port *up, int offset, int value) __sio_out(value, offset); } -static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void m32r_sio_stop_tx(struct uart_port *port) { struct uart_sio_port *up = (struct uart_sio_port *)port; @@ -285,7 +285,7 @@ static void m32r_sio_stop_tx(struct uart_port *port, unsigned int tty_stop) } } -static void m32r_sio_start_tx(struct uart_port *port, unsigned int tty_start) +static void m32r_sio_start_tx(struct uart_port *port) { #ifdef CONFIG_SERIAL_M32R_PLDSIO struct uart_sio_port *up = (struct uart_sio_port *)port; @@ -425,7 +425,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - m32r_sio_stop_tx(&up->port, 0); + m32r_sio_stop_tx(&up->port); return; } @@ -446,7 +446,7 @@ static _INLINE_ void transmit_chars(struct uart_sio_port *up) DEBUG_INTR("THRE..."); if (uart_circ_empty(xmit)) - m32r_sio_stop_tx(&up->port, 0); + m32r_sio_stop_tx(&up->port); } /* diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 2a5cf174ca3..a3cd0ee8486 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c @@ -119,7 +119,7 @@ mpc52xx_uart_get_mctrl(struct uart_port *port) } static void -mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) +mpc52xx_uart_stop_tx(struct uart_port *port) { /* port->lock taken by caller */ port->read_status_mask &= ~MPC52xx_PSC_IMR_TXRDY; @@ -127,7 +127,7 @@ mpc52xx_uart_stop_tx(struct uart_port *port, unsigned int tty_stop) } static void -mpc52xx_uart_start_tx(struct uart_port *port, unsigned int tty_start) +mpc52xx_uart_start_tx(struct uart_port *port) { /* port->lock taken by caller */ port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY; @@ -485,7 +485,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) /* Nothing to do ? */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - mpc52xx_uart_stop_tx(port,0); + mpc52xx_uart_stop_tx(port); return 0; } @@ -504,7 +504,7 @@ mpc52xx_uart_int_tx_chars(struct uart_port *port) /* Maybe we're done after all */ if (uart_circ_empty(xmit)) { - mpc52xx_uart_stop_tx(port,0); + mpc52xx_uart_stop_tx(port); return 0; } diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c index e43276c6a95..efe79b1fd43 100644 --- a/drivers/serial/mpsc.c +++ b/drivers/serial/mpsc.c @@ -1072,18 +1072,18 @@ mpsc_get_mctrl(struct uart_port *port) } static void -mpsc_stop_tx(struct uart_port *port, uint tty_start) +mpsc_stop_tx(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; - pr_debug("mpsc_stop_tx[%d]: tty_start: %d\n", port->line, tty_start); + pr_debug("mpsc_stop_tx[%d]\n", port->line); mpsc_freeze(pi); return; } static void -mpsc_start_tx(struct uart_port *port, uint tty_start) +mpsc_start_tx(struct uart_port *port) { struct mpsc_port_info *pi = (struct mpsc_port_info *)port; @@ -1091,7 +1091,7 @@ mpsc_start_tx(struct uart_port *port, uint tty_start) mpsc_copy_tx_data(pi); mpsc_sdma_start_tx(pi); - pr_debug("mpsc_start_tx[%d]: tty_start: %d\n", port->line, tty_start); + pr_debug("mpsc_start_tx[%d]\n", port->line); return; } diff --git a/drivers/serial/mux.c b/drivers/serial/mux.c index dadd7e19714..18906460770 100644 --- a/drivers/serial/mux.c +++ b/drivers/serial/mux.c @@ -111,22 +111,20 @@ static unsigned int mux_get_mctrl(struct uart_port *port) /** * mux_stop_tx - Stop transmitting characters. * @port: Ptr to the uart_port. - * @tty_stop: tty layer issue this command? * * The Serial MUX does not support this function. */ -static void mux_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void mux_stop_tx(struct uart_port *port) { } /** * mux_start_tx - Start transmitting characters. * @port: Ptr to the uart_port. - * @tty_start: tty layer issue this command? * * The Serial Mux does not support this function. */ -static void mux_start_tx(struct uart_port *port, unsigned int tty_start) +static void mux_start_tx(struct uart_port *port) { } @@ -181,7 +179,7 @@ static void mux_write(struct uart_port *port) } if(uart_circ_empty(xmit) || uart_tx_stopped(port)) { - mux_stop_tx(port, 0); + mux_stop_tx(port); return; } @@ -202,7 +200,7 @@ static void mux_write(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - mux_stop_tx(port, 0); + mux_stop_tx(port); } /** diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index 7db2f37532c..5bfde99e245 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c @@ -630,11 +630,10 @@ static unsigned int pmz_get_mctrl(struct uart_port *port) /* * Stop TX side. Dealt like sunzilog at next Tx interrupt, - * though for DMA, we will have to do a bit more. What is - * the meaning of the tty_stop bit ? XXX + * though for DMA, we will have to do a bit more. * The port lock is held and interrupts are disabled. */ -static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void pmz_stop_tx(struct uart_port *port) { to_pmz(port)->flags |= PMACZILOG_FLAG_TX_STOPPED; } @@ -643,7 +642,7 @@ static void pmz_stop_tx(struct uart_port *port, unsigned int tty_stop) * Kick the Tx side. * The port lock is held and interrupts are disabled. */ -static void pmz_start_tx(struct uart_port *port, unsigned int tty_start) +static void pmz_start_tx(struct uart_port *port) { struct uart_pmac_port *uap = to_pmz(port); unsigned char status; diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c index 461c81c9320..eaa0af83529 100644 --- a/drivers/serial/pxa.c +++ b/drivers/serial/pxa.c @@ -80,7 +80,7 @@ static void serial_pxa_enable_ms(struct uart_port *port) serial_out(up, UART_IER, up->ier); } -static void serial_pxa_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void serial_pxa_stop_tx(struct uart_port *port) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; @@ -185,7 +185,7 @@ static void transmit_chars(struct uart_pxa_port *up) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - serial_pxa_stop_tx(&up->port, 0); + serial_pxa_stop_tx(&up->port); return; } @@ -203,10 +203,10 @@ static void transmit_chars(struct uart_pxa_port *up) if (uart_circ_empty(xmit)) - serial_pxa_stop_tx(&up->port, 0); + serial_pxa_stop_tx(&up->port); } -static void serial_pxa_start_tx(struct uart_port *port, unsigned int tty_start) +static void serial_pxa_start_tx(struct uart_port *port) { struct uart_pxa_port *up = (struct uart_pxa_port *)port; diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c index 7365d4b50b9..c361c6fb080 100644 --- a/drivers/serial/s3c2410.c +++ b/drivers/serial/s3c2410.c @@ -246,8 +246,7 @@ static void s3c24xx_serial_rx_disable(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); } -static void -s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void s3c24xx_serial_stop_tx(struct uart_port *port) { if (tx_enabled(port)) { disable_irq(TX_IRQ(port)); @@ -257,8 +256,7 @@ s3c24xx_serial_stop_tx(struct uart_port *port, unsigned int tty_stop) } } -static void -s3c24xx_serial_start_tx(struct uart_port *port, unsigned int tty_start) +static void s3c24xx_serial_start_tx(struct uart_port *port) { if (!tx_enabled(port)) { if (port->flags & UPF_CONS_FLOW) @@ -424,7 +422,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re */ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - s3c24xx_serial_stop_tx(port, 0); + s3c24xx_serial_stop_tx(port); goto out; } @@ -443,7 +441,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id, struct pt_regs *re uart_write_wakeup(port); if (uart_circ_empty(xmit)) - s3c24xx_serial_stop_tx(port, 0); + s3c24xx_serial_stop_tx(port); out: return IRQ_HANDLED; diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c index 98641c3f5ab..1225b14f6e9 100644 --- a/drivers/serial/sa1100.c +++ b/drivers/serial/sa1100.c @@ -145,7 +145,7 @@ static void sa1100_timeout(unsigned long data) /* * interrupts disabled on entry */ -static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void sa1100_stop_tx(struct uart_port *port) { struct sa1100_port *sport = (struct sa1100_port *)port; u32 utcr3; @@ -158,7 +158,7 @@ static void sa1100_stop_tx(struct uart_port *port, unsigned int tty_stop) /* * interrupts may not be disabled on entry */ -static void sa1100_start_tx(struct uart_port *port, unsigned int tty_start) +static void sa1100_start_tx(struct uart_port *port) { struct sa1100_port *sport = (struct sa1100_port *)port; unsigned long flags; @@ -264,7 +264,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) sa1100_mctrl_check(sport); if (uart_circ_empty(xmit) || uart_tx_stopped(&sport->port)) { - sa1100_stop_tx(&sport->port, 0); + sa1100_stop_tx(&sport->port); return; } @@ -284,7 +284,7 @@ static void sa1100_tx_chars(struct sa1100_port *sport) uart_write_wakeup(&sport->port); if (uart_circ_empty(xmit)) - sa1100_stop_tx(&sport->port, 0); + sa1100_stop_tx(&sport->port); } static irqreturn_t sa1100_int(int irq, void *dev_id, struct pt_regs *regs) diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 54699c3a00a..dea156a62d0 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -80,7 +80,7 @@ static void uart_stop(struct tty_struct *tty) unsigned long flags; spin_lock_irqsave(&port->lock, flags); - port->ops->stop_tx(port, 1); + port->ops->stop_tx(port); spin_unlock_irqrestore(&port->lock, flags); } @@ -91,7 +91,7 @@ static void __uart_start(struct tty_struct *tty) if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && !tty->stopped && !tty->hw_stopped) - port->ops->start_tx(port, 1); + port->ops->start_tx(port); } static void uart_start(struct tty_struct *tty) @@ -542,7 +542,7 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) port->x_char = ch; if (ch) { spin_lock_irqsave(&port->lock, flags); - port->ops->start_tx(port, 0); + port->ops->start_tx(port); spin_unlock_irqrestore(&port->lock, flags); } } @@ -1146,7 +1146,7 @@ static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios spin_lock_irqsave(&state->port->lock, flags); if (!(state->port->ops->get_mctrl(state->port) & TIOCM_CTS)) { tty->hw_stopped = 1; - state->port->ops->stop_tx(state->port, 0); + state->port->ops->stop_tx(state->port); } spin_unlock_irqrestore(&state->port->lock, flags); } @@ -1869,7 +1869,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *port) struct uart_ops *ops = port->ops; spin_lock_irq(&port->lock); - ops->stop_tx(port, 0); + ops->stop_tx(port); ops->set_mctrl(port, 0); ops->stop_rx(port); spin_unlock_irq(&port->lock); @@ -1935,7 +1935,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *port) uart_change_speed(state, NULL); spin_lock_irq(&port->lock); ops->set_mctrl(port, port->mctrl); - ops->start_tx(port, 0); + ops->start_tx(port); spin_unlock_irq(&port->lock); } @@ -2289,143 +2289,11 @@ int uart_match_port(struct uart_port *port1, struct uart_port *port2) } EXPORT_SYMBOL(uart_match_port); -/* - * Try to find an unused uart_state slot for a port. - */ -static struct uart_state * -uart_find_match_or_unused(struct uart_driver *drv, struct uart_port *port) -{ - int i; - - /* - * First, find a port entry which matches. Note: if we do - * find a matching entry, and it has a non-zero use count, - * then we can't register the port. - */ - for (i = 0; i < drv->nr; i++) - if (uart_match_port(drv->state[i].port, port)) - return &drv->state[i]; - - /* - * We didn't find a matching entry, so look for the first - * free entry. We look for one which hasn't been previously - * used (indicated by zero iobase). - */ - for (i = 0; i < drv->nr; i++) - if (drv->state[i].port->type == PORT_UNKNOWN && - drv->state[i].port->iobase == 0 && - drv->state[i].count == 0) - return &drv->state[i]; - - /* - * That also failed. Last resort is to find any currently - * entry which doesn't have a real port associated with it. - */ - for (i = 0; i < drv->nr; i++) - if (drv->state[i].port->type == PORT_UNKNOWN && - drv->state[i].count == 0) - return &drv->state[i]; - - return NULL; -} - -/** - * uart_register_port: register uart settings with a port - * @drv: pointer to the uart low level driver structure for this port - * @port: uart port structure describing the port - * - * Register UART settings with the specified low level driver. Detect - * the type of the port if UPF_BOOT_AUTOCONF is set, and detect the - * IRQ if UPF_AUTO_IRQ is set. - * - * We try to pick the same port for the same IO base address, so that - * when a modem is plugged in, unplugged and plugged back in, it gets - * allocated the same port. - * - * Returns negative error, or positive line number. - */ -int uart_register_port(struct uart_driver *drv, struct uart_port *port) -{ - struct uart_state *state; - int ret; - - down(&port_sem); - - state = uart_find_match_or_unused(drv, port); - - if (state) { - /* - * Ok, we've found a line that we can use. - * - * If we find a port that matches this one, and it appears - * to be in-use (even if it doesn't have a type) we shouldn't - * alter it underneath itself - the port may be open and - * trying to do useful work. - */ - if (uart_users(state) != 0) { - ret = -EBUSY; - goto out; - } - - /* - * If the port is already initialised, don't touch it. - */ - if (state->port->type == PORT_UNKNOWN) { - state->port->iobase = port->iobase; - state->port->membase = port->membase; - state->port->irq = port->irq; - state->port->uartclk = port->uartclk; - state->port->fifosize = port->fifosize; - state->port->regshift = port->regshift; - state->port->iotype = port->iotype; - state->port->flags = port->flags; - state->port->line = state - drv->state; - state->port->mapbase = port->mapbase; - - uart_configure_port(drv, state, state->port); - } - - ret = state->port->line; - } else - ret = -ENOSPC; - out: - up(&port_sem); - return ret; -} - -/** - * uart_unregister_port - de-allocate a port - * @drv: pointer to the uart low level driver structure for this port - * @line: line index previously returned from uart_register_port() - * - * Hang up the specified line associated with the low level driver, - * and mark the port as unused. - */ -void uart_unregister_port(struct uart_driver *drv, int line) -{ - struct uart_state *state; - - if (line < 0 || line >= drv->nr) { - printk(KERN_ERR "Attempt to unregister "); - printk("%s%d", drv->dev_name, line); - printk("\n"); - return; - } - - state = drv->state + line; - - down(&port_sem); - uart_unconfigure_port(drv, state); - up(&port_sem); -} - EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); EXPORT_SYMBOL(uart_suspend_port); EXPORT_SYMBOL(uart_resume_port); -EXPORT_SYMBOL(uart_register_port); -EXPORT_SYMBOL(uart_unregister_port); EXPORT_SYMBOL(uart_add_one_port); EXPORT_SYMBOL(uart_remove_one_port); diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c index 56f269b6bfb..32f808d157a 100644 --- a/drivers/serial/serial_lh7a40x.c +++ b/drivers/serial/serial_lh7a40x.c @@ -112,13 +112,12 @@ struct uart_port_lh7a40x { unsigned int statusPrev; /* Most recently read modem status */ }; -static void lh7a40xuart_stop_tx (struct uart_port* port, unsigned int tty_stop) +static void lh7a40xuart_stop_tx (struct uart_port* port) { BIT_CLR (port, UART_R_INTEN, TxInt); } -static void lh7a40xuart_start_tx (struct uart_port* port, - unsigned int tty_start) +static void lh7a40xuart_start_tx (struct uart_port* port) { BIT_SET (port, UART_R_INTEN, TxInt); diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index d085030df70..49afadbe461 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c @@ -253,7 +253,7 @@ sio_quot_set(struct uart_txx9_port *up, int quot) sio_out(up, TXX9_SIBGR, 0xff | TXX9_SIBGR_BCLK_T6); } -static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void serial_txx9_stop_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned long flags; @@ -263,7 +263,7 @@ static void serial_txx9_stop_tx(struct uart_port *port, unsigned int tty_stop) spin_unlock_irqrestore(&up->port.lock, flags); } -static void serial_txx9_start_tx(struct uart_port *port, unsigned int tty_start) +static void serial_txx9_start_tx(struct uart_port *port) { struct uart_txx9_port *up = (struct uart_txx9_port *)port; unsigned long flags; @@ -372,7 +372,7 @@ static inline void transmit_chars(struct uart_txx9_port *up) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - serial_txx9_stop_tx(&up->port, 0); + serial_txx9_stop_tx(&up->port); return; } @@ -389,7 +389,7 @@ static inline void transmit_chars(struct uart_txx9_port *up) uart_write_wakeup(&up->port); if (uart_circ_empty(xmit)) - serial_txx9_stop_tx(&up->port, 0); + serial_txx9_stop_tx(&up->port); } static irqreturn_t serial_txx9_interrupt(int irq, void *dev_id, struct pt_regs *regs) diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index ad5b776d779..51226630786 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -79,8 +79,8 @@ static struct sci_port *serial_console_port = 0; #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ /* Function prototypes */ -static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop); -static void sci_start_tx(struct uart_port *port, unsigned int tty_start); +static void sci_stop_tx(struct uart_port *port); +static void sci_start_tx(struct uart_port *port); static void sci_start_rx(struct uart_port *port, unsigned int tty_start); static void sci_stop_rx(struct uart_port *port); static int sci_request_irq(struct sci_port *port); @@ -455,7 +455,7 @@ static void sci_transmit_chars(struct uart_port *port) if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) uart_write_wakeup(port); if (uart_circ_empty(xmit)) { - sci_stop_tx(port, 0); + sci_stop_tx(port); } else { local_irq_save(flags); ctrl = sci_in(port, SCSCR); @@ -900,7 +900,7 @@ static unsigned int sci_get_mctrl(struct uart_port *port) return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR; } -static void sci_start_tx(struct uart_port *port, unsigned int tty_start) +static void sci_start_tx(struct uart_port *port) { struct sci_port *s = &sci_ports[port->line]; @@ -909,7 +909,7 @@ static void sci_start_tx(struct uart_port *port, unsigned int tty_start) enable_irq(s->irqs[SCIx_TXI_IRQ]); } -static void sci_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void sci_stop_tx(struct uart_port *port) { unsigned long flags; unsigned short ctrl; @@ -978,7 +978,7 @@ static void sci_shutdown(struct uart_port *port) struct sci_port *s = &sci_ports[port->line]; sci_stop_rx(port); - sci_stop_tx(port, 1); + sci_stop_tx(port); sci_free_irq(s); #if defined(__H8300S__) diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c index 12d1f14e78c..313f9df24a2 100644 --- a/drivers/serial/sn_console.c +++ b/drivers/serial/sn_console.c @@ -259,10 +259,9 @@ static unsigned int snp_tx_empty(struct uart_port *port) /** * snp_stop_tx - stop the transmitter - no-op for us * @port: Port to operat eon - we ignore - no-op function - * @tty_stop: Set to 1 if called via uart_stop * */ -static void snp_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void snp_stop_tx(struct uart_port *port) { } @@ -325,10 +324,9 @@ static void snp_stop_rx(struct uart_port *port) /** * snp_start_tx - Start transmitter * @port: Port to operate on - * @tty_stop: Set to 1 if called via uart_start * */ -static void snp_start_tx(struct uart_port *port, unsigned int tty_stop) +static void snp_start_tx(struct uart_port *port) { if (sal_console_port.sc_ops->sal_wakeup_transmit) sal_console_port.sc_ops->sal_wakeup_transmit(&sal_console_port, @@ -615,7 +613,7 @@ static void sn_transmit_chars(struct sn_cons_port *port, int raw) uart_write_wakeup(&port->sc_port); if (uart_circ_empty(xmit)) - snp_stop_tx(&port->sc_port, 0); /* no-op for us */ + snp_stop_tx(&port->sc_port); /* no-op for us */ } /** diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 8d198880756..e971156daa6 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c @@ -245,7 +245,7 @@ receive_chars(struct uart_sunsab_port *up, return tty; } -static void sunsab_stop_tx(struct uart_port *, unsigned int); +static void sunsab_stop_tx(struct uart_port *); static void sunsab_tx_idle(struct uart_sunsab_port *); static void transmit_chars(struct uart_sunsab_port *up, @@ -301,7 +301,7 @@ static void transmit_chars(struct uart_sunsab_port *up, uart_write_wakeup(&up->port); if (uart_circ_empty(xmit)) - sunsab_stop_tx(&up->port, 0); + sunsab_stop_tx(&up->port); } static void check_status(struct uart_sunsab_port *up, @@ -448,7 +448,7 @@ static unsigned int sunsab_get_mctrl(struct uart_port *port) } /* port->lock held by caller. */ -static void sunsab_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void sunsab_stop_tx(struct uart_port *port) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; @@ -476,7 +476,7 @@ static void sunsab_tx_idle(struct uart_sunsab_port *up) } /* port->lock held by caller. */ -static void sunsab_start_tx(struct uart_port *port, unsigned int tty_start) +static void sunsab_start_tx(struct uart_port *port) { struct uart_sunsab_port *up = (struct uart_sunsab_port *) port; struct circ_buf *xmit = &up->port.info->xmit; diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index d57a3553aea..0cc879eb1c0 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -255,21 +255,27 @@ static void disable_rsa(struct uart_sunsu_port *up) } #endif /* CONFIG_SERIAL_8250_RSA */ -static void sunsu_stop_tx(struct uart_port *port, unsigned int tty_stop) +static inline void __stop_tx(struct uart_sunsu_port *p) +{ + if (p->ier & UART_IER_THRI) { + p->ier &= ~UART_IER_THRI; + serial_out(p, UART_IER, p->ier); + } +} + +static void sunsu_stop_tx(struct uart_port *port) { struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; - if (up->ier & UART_IER_THRI) { - up->ier &= ~UART_IER_THRI; - serial_out(up, UART_IER, up->ier); - } - if (up->port.type == PORT_16C950 && tty_stop) { + __stop_tx(up); + + if (up->port.type == PORT_16C950 && tty_stop /*FIXME*/) { up->acr |= UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } } -static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start) +static void sunsu_start_tx(struct uart_port *port) { struct uart_sunsu_port *up = (struct uart_sunsu_port *) port; @@ -280,7 +286,7 @@ static void sunsu_start_tx(struct uart_port *port, unsigned int tty_start) /* * We only do this from uart_start */ - if (tty_start && up->port.type == PORT_16C950) { + if (tty_start && up->port.type == PORT_16C950 /*FIXME*/) { up->acr &= ~UART_ACR_TXDIS; serial_icr_write(up, UART_ACR, up->acr); } @@ -413,8 +419,12 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) up->port.x_char = 0; return; } - if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) { - sunsu_stop_tx(&up->port, 0); + if (uart_tx_stopped(&up->port)) { + sunsu_stop_tx(&up->port); + return; + } + if (uart_circ_empty(xmit)) { + __stop_tx(up); return; } @@ -431,7 +441,7 @@ static _INLINE_ void transmit_chars(struct uart_sunsu_port *up) uart_write_wakeup(&up->port); if (uart_circ_empty(xmit)) - sunsu_stop_tx(&up->port, 0); + __stop_tx(up); } static _INLINE_ void check_modem_status(struct uart_sunsu_port *up) diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index bff42a7b89d..d75445738c8 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -684,7 +684,7 @@ static void sunzilog_set_mctrl(struct uart_port *port, unsigned int mctrl) } /* The port lock is held and interrupts are disabled. */ -static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void sunzilog_stop_tx(struct uart_port *port) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; @@ -692,7 +692,7 @@ static void sunzilog_stop_tx(struct uart_port *port, unsigned int tty_stop) } /* The port lock is held and interrupts are disabled. */ -static void sunzilog_start_tx(struct uart_port *port, unsigned int tty_start) +static void sunzilog_start_tx(struct uart_port *port) { struct uart_sunzilog_port *up = (struct uart_sunzilog_port *) port; struct zilog_channel __iomem *channel = ZILOG_CHANNEL_FROM_PORT(port); diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c index 186f1300cea..47b504ff38b 100644 --- a/drivers/serial/uart00.c +++ b/drivers/serial/uart00.c @@ -87,7 +87,7 @@ #define UART_TX_READY(s) (((s) & UART_TSR_TX_LEVEL_MSK) < 15) //#define UART_TX_EMPTY(p) ((UART_GET_FR(p) & UART00_UARTFR_TMSK) == 0) -static void uart00_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void uart00_stop_tx(struct uart_port *port) { UART_PUT_IEC(port, UART_IEC_TIE_MSK); } @@ -199,7 +199,7 @@ static void uart00_tx_chars(struct uart_port *port) return; } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - uart00_stop_tx(port, 0); + uart00_stop_tx(port); return; } @@ -218,10 +218,10 @@ static void uart00_tx_chars(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - uart00_stop_tx(port, 0); + uart00_stop_tx(port); } -static void uart00_start_tx(struct uart_port *port, unsigned int tty_start) +static void uart00_start_tx(struct uart_port *port) { UART_PUT_IES(port, UART_IES_TIE_MSK); uart00_tx_chars(port); diff --git a/drivers/serial/v850e_uart.c b/drivers/serial/v850e_uart.c index bb482780a41..9378895a8d5 100644 --- a/drivers/serial/v850e_uart.c +++ b/drivers/serial/v850e_uart.c @@ -240,7 +240,7 @@ console_initcall(v850e_uart_console_init); /* TX/RX interrupt handlers. */ -static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop); +static void v850e_uart_stop_tx (struct uart_port *port); void v850e_uart_tx (struct uart_port *port) { @@ -339,14 +339,14 @@ static unsigned v850e_uart_get_mctrl (struct uart_port *port) return mctrl; } -static void v850e_uart_start_tx (struct uart_port *port, unsigned tty_start) +static void v850e_uart_start_tx (struct uart_port *port) { v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); v850e_uart_tx (port); v850e_intc_enable_irq (V850E_UART_TX_IRQ (port->line)); } -static void v850e_uart_stop_tx (struct uart_port *port, unsigned tty_stop) +static void v850e_uart_stop_tx (struct uart_port *port) { v850e_intc_disable_irq (V850E_UART_TX_IRQ (port->line)); } diff --git a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c index 1f985327b0d..0c5d65a08f6 100644 --- a/drivers/serial/vr41xx_siu.c +++ b/drivers/serial/vr41xx_siu.c @@ -284,7 +284,7 @@ static unsigned int siu_get_mctrl(struct uart_port *port) return mctrl; } -static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop) +static void siu_stop_tx(struct uart_port *port) { unsigned long flags; uint8_t ier; @@ -298,7 +298,7 @@ static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop) spin_unlock_irqrestore(&port->lock, flags); } -static void siu_start_tx(struct uart_port *port, unsigned int tty_start) +static void siu_start_tx(struct uart_port *port) { unsigned long flags; uint8_t ier; @@ -458,7 +458,7 @@ static inline void transmit_chars(struct uart_port *port) } if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { - siu_stop_tx(port, 0); + siu_stop_tx(port); return; } @@ -474,7 +474,7 @@ static inline void transmit_chars(struct uart_port *port) uart_write_wakeup(port); if (uart_circ_empty(xmit)) - siu_stop_tx(port, 0); + siu_stop_tx(port); } static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs) diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index c8998dc6688..7974efa107b 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -520,7 +520,7 @@ static int load_flat_file(struct linux_binprm * bprm, DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); down_write(¤t->mm->mmap_sem); - textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0); + textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0); up_write(¤t->mm->mmap_sem); if (!textpos || textpos >= (unsigned long) -4096) { if (!textpos) diff --git a/include/asm-arm/arch-ixp4xx/io.h b/include/asm-arm/arch-ixp4xx/io.h index 7495026e2c1..e350dcb544e 100644 --- a/include/asm-arm/arch-ixp4xx/io.h +++ b/include/asm-arm/arch-ixp4xx/io.h @@ -383,39 +383,45 @@ __ixp4xx_insl(u32 io_addr, u32 *vaddr, u32 count) *vaddr++ = inl(io_addr); } -#define __is_io_address(p) (((unsigned long)p >= 0x0) && \ - ((unsigned long)p <= 0x0000ffff)) +#define PIO_OFFSET 0x10000UL +#define PIO_MASK 0x0ffffUL + +#define __is_io_address(p) (((unsigned long)p >= PIO_OFFSET) && \ + ((unsigned long)p <= (PIO_MASK + PIO_OFFSET))) static inline unsigned int -__ixp4xx_ioread8(void __iomem *port) +__ixp4xx_ioread8(void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inb((unsigned int)port); + return (unsigned int)__ixp4xx_inb(port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - return (unsigned int)__raw_readb((u32)port); + return (unsigned int)__raw_readb(port); #else - return (unsigned int)__ixp4xx_readb((u32)port); + return (unsigned int)__ixp4xx_readb(port); #endif } static inline void -__ixp4xx_ioread8_rep(u32 port, u8 *vaddr, u32 count) +__ixp4xx_ioread8_rep(void __iomem *addr, void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insb(port, vaddr, count); + __ixp4xx_insb(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_readsb((void __iomem *)port, vaddr, count); + __raw_readsb(addr, vaddr, count); #else __ixp4xx_readsb(port, vaddr, count); #endif } static inline unsigned int -__ixp4xx_ioread16(void __iomem *port) +__ixp4xx_ioread16(void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inw((unsigned int)port); + return (unsigned int)__ixp4xx_inw(port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le16_to_cpu(__raw_readw((u32)port)); @@ -425,23 +431,25 @@ __ixp4xx_ioread16(void __iomem *port) } static inline void -__ixp4xx_ioread16_rep(u32 port, u16 *vaddr, u32 count) +__ixp4xx_ioread16_rep(void __iomem *addr, void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insw(port, vaddr, count); + __ixp4xx_insw(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_readsw((void __iomem *)port, vaddr, count); + __raw_readsw(addr, vaddr, count); #else __ixp4xx_readsw(port, vaddr, count); #endif } static inline unsigned int -__ixp4xx_ioread32(void __iomem *port) +__ixp4xx_ioread32(void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - return (unsigned int)__ixp4xx_inl((unsigned int)port); + return (unsigned int)__ixp4xx_inl(port & PIO_MASK); else { #ifndef CONFIG_IXP4XX_INDIRECT_PCI return le32_to_cpu(__raw_readl((u32)port)); @@ -452,90 +460,100 @@ __ixp4xx_ioread32(void __iomem *port) } static inline void -__ixp4xx_ioread32_rep(u32 port, u32 *vaddr, u32 count) +__ixp4xx_ioread32_rep(void __iomem *addr, void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_insl(port, vaddr, count); + __ixp4xx_insl(port & PIO_MASK, vaddr, count); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_readsl((void __iomem *)port, vaddr, count); + __raw_readsl(addr, vaddr, count); #else __ixp4xx_readsl(port, vaddr, count); #endif } static inline void -__ixp4xx_iowrite8(u8 value, void __iomem *port) +__ixp4xx_iowrite8(u8 value, void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outb(value, (unsigned int)port); + __ixp4xx_outb(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_writeb(value, (u32)port); + __raw_writeb(value, port); #else - __ixp4xx_writeb(value, (u32)port); + __ixp4xx_writeb(value, port); #endif } static inline void -__ixp4xx_iowrite8_rep(u32 port, u8 *vaddr, u32 count) +__ixp4xx_iowrite8_rep(void __iomem *addr, const void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsb(port, vaddr, count); + __ixp4xx_outsb(port & PIO_MASK, vaddr, count); + else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_writesb((void __iomem *)port, vaddr, count); + __raw_writesb(addr, vaddr, count); #else __ixp4xx_writesb(port, vaddr, count); #endif } static inline void -__ixp4xx_iowrite16(u16 value, void __iomem *port) +__ixp4xx_iowrite16(u16 value, void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outw(value, (unsigned int)port); + __ixp4xx_outw(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_writew(cpu_to_le16(value), (u32)port); + __raw_writew(cpu_to_le16(value), addr); #else - __ixp4xx_writew(value, (u32)port); + __ixp4xx_writew(value, port); #endif } static inline void -__ixp4xx_iowrite16_rep(u32 port, u16 *vaddr, u32 count) +__ixp4xx_iowrite16_rep(void __iomem *addr, const void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsw(port, vaddr, count); + __ixp4xx_outsw(port & PIO_MASK, vaddr, count); + else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_readsw((void __iomem *)port, vaddr, count); + __raw_writesw(addr, vaddr, count); #else __ixp4xx_writesw(port, vaddr, count); #endif } static inline void -__ixp4xx_iowrite32(u32 value, void __iomem *port) +__ixp4xx_iowrite32(u32 value, void __iomem *addr) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outl(value, (unsigned int)port); + __ixp4xx_outl(value, port & PIO_MASK); else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_writel(cpu_to_le32(value), (u32)port); + __raw_writel(cpu_to_le32(value), port); #else - __ixp4xx_writel(value, (u32)port); + __ixp4xx_writel(value, port); #endif } static inline void -__ixp4xx_iowrite32_rep(u32 port, u32 *vaddr, u32 count) +__ixp4xx_iowrite32_rep(void __iomem *addr, const void *vaddr, u32 count) { + unsigned long port = (unsigned long __force)addr; if (__is_io_address(port)) - __ixp4xx_outsl(port, vaddr, count); + __ixp4xx_outsl(port & PIO_MASK, vaddr, count); + else #ifndef CONFIG_IXP4XX_INDIRECT_PCI - __raw_readsl((void __iomem *)port, vaddr, count); + __raw_writesl(addr, vaddr, count); #else - __ixp4xx_outsl(port, vaddr, count); + __ixp4xx_writesl(port, vaddr, count); #endif } @@ -555,7 +573,7 @@ __ixp4xx_iowrite32_rep(u32 port, u32 *vaddr, u32 count) #define iowrite16_rep(p, v, c) __ixp4xx_iowrite16_rep(p, v, c) #define iowrite32_rep(p, v, c) __ixp4xx_iowrite32_rep(p, v, c) -#define ioport_map(port, nr) ((void __iomem*)port) +#define ioport_map(port, nr) ((void __iomem*)(port + PIO_OFFSET)) #define ioport_unmap(addr) #endif // __ASM_ARM_ARCH_IO_H diff --git a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h index 3a626c03ea2..d13ee7f78c7 100644 --- a/include/asm-arm/arch-ixp4xx/platform.h +++ b/include/asm-arm/arch-ixp4xx/platform.h @@ -83,17 +83,6 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); #define IXP4XX_GPIO_OUT 0x1 #define IXP4XX_GPIO_IN 0x2 -#define IXP4XX_GPIO_INTSTYLE_MASK 0x7C /* Bits [6:2] define interrupt style */ - -/* - * GPIO interrupt types. - */ -#define IXP4XX_GPIO_ACTIVE_HIGH 0x4 /* Default */ -#define IXP4XX_GPIO_ACTIVE_LOW 0x8 -#define IXP4XX_GPIO_RISING_EDGE 0x10 -#define IXP4XX_GPIO_FALLING_EDGE 0x20 -#define IXP4XX_GPIO_TRANSITIONAL 0x40 - /* GPIO signal types */ #define IXP4XX_GPIO_LOW 0 #define IXP4XX_GPIO_HIGH 1 @@ -102,7 +91,13 @@ extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); #define IXP4XX_GPIO_CLK_0 14 #define IXP4XX_GPIO_CLK_1 15 -extern void gpio_line_config(u8 line, u32 style); +static inline void gpio_line_config(u8 line, u32 direction) +{ + if (direction == IXP4XX_GPIO_OUT) + *IXP4XX_GPIO_GPOER |= (1 << line); + else + *IXP4XX_GPIO_GPOER &= ~(1 << line); +} static inline void gpio_line_get(u8 line, int *value) { diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index 51f0fe0ac16..939d9e5020a 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -818,6 +818,23 @@ #define UDCOTGICR_IEIDF (1 << 0) /* OTG ID Change Falling Edge Interrupt Enable */ +#define UP2OCR __REG(0x40600020) /* USB Port 2 Output Control register */ + +#define UP2OCR_CPVEN (1 << 0) /* Charge Pump Vbus Enable */ +#define UP2OCR_CPVPE (1 << 1) /* Charge Pump Vbus Pulse Enable */ +#define UP2OCR_DPPDE (1 << 2) /* Host Port 2 Transceiver D+ Pull Down Enable */ +#define UP2OCR_DMPDE (1 << 3) /* Host Port 2 Transceiver D- Pull Down Enable */ +#define UP2OCR_DPPUE (1 << 4) /* Host Port 2 Transceiver D+ Pull Up Enable */ +#define UP2OCR_DMPUE (1 << 5) /* Host Port 2 Transceiver D- Pull Up Enable */ +#define UP2OCR_DPPUBE (1 << 6) /* Host Port 2 Transceiver D+ Pull Up Bypass Enable */ +#define UP2OCR_DMPUBE (1 << 7) /* Host Port 2 Transceiver D- Pull Up Bypass Enable */ +#define UP2OCR_EXSP (1 << 8) /* External Transceiver Speed Control */ +#define UP2OCR_EXSUS (1 << 9) /* External Transceiver Speed Enable */ +#define UP2OCR_IDON (1 << 10) /* OTG ID Read Enable */ +#define UP2OCR_HXS (1 << 16) /* Host Port 2 Transceiver Output Select */ +#define UP2OCR_HXOE (1 << 17) /* Host Port 2 Transceiver Output Enable */ +#define UP2OCR_SEOS (1 << 24) /* Single-Ended Output Select */ + #define UDCCSN(x) __REG2(0x40600100, (x) << 2) #define UDCCSR0 __REG(0x40600100) /* UDC Control/Status register - Endpoint 0 */ #define UDCCSR0_SA (1 << 7) /* Setup Active */ @@ -1423,6 +1440,7 @@ #define GPIO84_NSSP_RX (84 | GPIO_ALT_FN_2_IN) #define GPIO85_nPCE_1_MD (85 | GPIO_ALT_FN_1_OUT) #define GPIO92_MMCDAT0_MD (92 | GPIO_ALT_FN_1_OUT) +#define GPIO104_pSKTSEL_MD (104 | GPIO_ALT_FN_1_OUT) #define GPIO109_MMCDAT1_MD (109 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCDAT2_MD (110 | GPIO_ALT_FN_1_OUT) #define GPIO110_MMCCS0_MD (110 | GPIO_ALT_FN_1_OUT) @@ -1510,6 +1528,8 @@ #define PSSR_BFS (1 << 1) /* Battery Fault Status */ #define PSSR_SSS (1 << 0) /* Software Sleep Status */ +#define PSLR_SL_ROD (1 << 20) /* Sleep-Mode/Depp-Sleep Mode nRESET_OUT Disable */ + #define PCFR_RO (1 << 15) /* RDH Override */ #define PCFR_PO (1 << 14) /* PH Override */ #define PCFR_GPROD (1 << 12) /* GPIO nRESET_OUT Disable */ @@ -1517,6 +1537,7 @@ #define PCFR_FVC (1 << 10) /* Frequency/Voltage Change */ #define PCFR_DC_EN (1 << 7) /* Sleep/deep-sleep DC-DC Converter Enable */ #define PCFR_PI2CEN (1 << 6) /* Enable PI2C controller */ +#define PCFR_GPR_EN (1 << 4) /* nRESET_GPIO Pin Enable */ #define PCFR_DS (1 << 3) /* Deep Sleep Mode */ #define PCFR_FS (1 << 2) /* Float Static Chip Selects */ #define PCFR_FP (1 << 1) /* Float PCMCIA controls */ @@ -1810,6 +1831,11 @@ #define LCCR0_PDD_S 12 #define LCCR0_BM (1 << 20) /* Branch mask */ #define LCCR0_OUM (1 << 21) /* Output FIFO underrun mask */ +#define LCCR0_LCDT (1 << 22) /* LCD panel type */ +#define LCCR0_RDSTM (1 << 23) /* Read status interrupt mask */ +#define LCCR0_CMDIM (1 << 24) /* Command interrupt mask */ +#define LCCR0_OUC (1 << 25) /* Overlay Underlay control bit */ +#define LCCR0_LDDALT (1 << 26) /* LDD alternate mapping control */ #define LCCR1_PPL Fld (10, 0) /* Pixels Per Line - 1 */ #define LCCR1_DisWdth(Pixel) /* Display Width [1..800 pix.] */ \ @@ -2062,7 +2088,10 @@ #define UHCFMN __REG(0x4C00003C) /* UHC Frame Number */ #define UHCPERS __REG(0x4C000040) /* UHC Periodic Start */ #define UHCLS __REG(0x4C000044) /* UHC Low Speed Threshold */ + #define UHCRHDA __REG(0x4C000048) /* UHC Root Hub Descriptor A */ +#define UHCRHDA_NOCP (1 << 12) /* No over current protection */ + #define UHCRHDB __REG(0x4C00004C) /* UHC Root Hub Descriptor B */ #define UHCRHS __REG(0x4C000050) /* UHC Root Hub Status */ #define UHCRHPS1 __REG(0x4C000054) /* UHC Root Hub Port 1 Status */ diff --git a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h index e5e938b79ac..16f4c3cc138 100644 --- a/include/asm-arm/arch-s3c2410/regs-clock.h +++ b/include/asm-arm/arch-s3c2410/regs-clock.h @@ -1,7 +1,7 @@ /* linux/include/asm/arch-s3c2410/regs-clock.h * - * Copyright (c) 2003,2004 Simtec Electronics <linux@simtec.co.uk> - * http://www.simtec.co.uk/products/SWLINUX/ + * Copyright (c) 2003,2004,2005 Simtec Electronics <linux@simtec.co.uk> + * http://armlinux.simtec.co.uk/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,6 +17,7 @@ * 29-Sep-2004 Ben Dooks Fixed usage for assembly inclusion * 10-Feb-2005 Ben Dooks Fixed CAMDIVN address (Guillaume Gourat) * 10-Mar-2005 Lucas Villa Real Changed S3C2410_VA to S3C24XX_VA + * 27-Aug-2005 Ben Dooks Add clock-slow info */ #ifndef __ASM_ARM_REGS_CLOCK @@ -74,6 +75,12 @@ #define S3C2410_CLKDIVN_PDIVN (1<<0) #define S3C2410_CLKDIVN_HDIVN (1<<1) +#define S3C2410_CLKSLOW_UCLK_OFF (1<<7) +#define S3C2410_CLKSLOW_MPLL_OFF (1<<5) +#define S3C2410_CLKSLOW_SLOW (1<<4) +#define S3C2410_CLKSLOW_SLOWVAL(x) (x) +#define S3C2410_CLKSLOW_GET_SLOWVAL(x) ((x) & 7) + #ifndef __ASSEMBLY__ static inline unsigned int diff --git a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h index abb36e54c96..278de61224d 100644 --- a/include/asm-arm/unistd.h +++ b/include/asm-arm/unistd.h @@ -295,7 +295,7 @@ #define __NR_fstatfs64 (__NR_SYSCALL_BASE+267) #define __NR_tgkill (__NR_SYSCALL_BASE+268) #define __NR_utimes (__NR_SYSCALL_BASE+269) -#define __NR_fadvise64_64 (__NR_SYSCALL_BASE+270) +#define __NR_arm_fadvise64_64 (__NR_SYSCALL_BASE+270) #define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271) #define __NR_pciconfig_read (__NR_SYSCALL_BASE+272) #define __NR_pciconfig_write (__NR_SYSCALL_BASE+273) @@ -515,7 +515,6 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6 #define __ARCH_WANT_SYS_TIME #define __ARCH_WANT_SYS_UTIME #define __ARCH_WANT_SYS_SOCKETCALL -#define __ARCH_WANT_SYS_FADVISE64 #define __ARCH_WANT_SYS_GETPGRP #define __ARCH_WANT_SYS_LLSEEK #define __ARCH_WANT_SYS_NICE diff --git a/include/asm-ia64/acpi.h b/include/asm-ia64/acpi.h index 4c06d455139..3a544ffc500 100644 --- a/include/asm-ia64/acpi.h +++ b/include/asm-ia64/acpi.h @@ -116,6 +116,11 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; extern u16 ia64_acpiid_to_sapicid[]; +/* + * Refer Intel ACPI _PDC support document for bit definitions + */ +#define ACPI_PDC_EST_CAPABILITY_SMP 0x8 + #endif /*__KERNEL__*/ #endif /*_ASM_ACPI_H*/ diff --git a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h index c9f8d835d0c..cee16ea1780 100644 --- a/include/asm-ia64/fcntl.h +++ b/include/asm-ia64/fcntl.h @@ -81,6 +81,7 @@ struct flock { #define F_LINUX_SPECIFIC_BASE 1024 -#define force_o_largefile() ( ! (current->personality & PER_LINUX32) ) +#define force_o_largefile() \ + (personality(current->personality) != PER_LINUX32) #endif /* _ASM_IA64_FCNTL_H */ diff --git a/include/asm-ia64/io.h b/include/asm-ia64/io.h index 54e7637a326..cf772a67f85 100644 --- a/include/asm-ia64/io.h +++ b/include/asm-ia64/io.h @@ -23,7 +23,7 @@ #define __SLOW_DOWN_IO do { } while (0) #define SLOW_DOWN_IO do { } while (0) -#define __IA64_UNCACHED_OFFSET 0xc000000000000000UL /* region 6 */ +#define __IA64_UNCACHED_OFFSET RGN_BASE(RGN_UNCACHED) /* * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but @@ -41,7 +41,7 @@ #define IO_SPACE_BASE(space) ((space) << IO_SPACE_BITS) #define IO_SPACE_PORT(port) ((port) & (IO_SPACE_SIZE - 1)) -#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | (p & 0xfff)) +#define IO_SPACE_SPARSE_ENCODING(p) ((((p) >> 2) << 12) | ((p) & 0xfff)) struct io_space { unsigned long mmio_base; /* base in MMIO space */ diff --git a/include/asm-ia64/mmu.h b/include/asm-ia64/mmu.h index ae1525352a2..611432ba579 100644 --- a/include/asm-ia64/mmu.h +++ b/include/asm-ia64/mmu.h @@ -2,10 +2,12 @@ #define __MMU_H /* - * Type for a context number. We declare it volatile to ensure proper ordering when it's - * accessed outside of spinlock'd critical sections (e.g., as done in activate_mm() and - * init_new_context()). + * Type for a context number. We declare it volatile to ensure proper + * ordering when it's accessed outside of spinlock'd critical sections + * (e.g., as done in activate_mm() and init_new_context()). */ typedef volatile unsigned long mm_context_t; +typedef unsigned long nv_mm_context_t; + #endif diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index e3e5fededb0..8d6e72f7b08 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h @@ -19,6 +19,7 @@ #define ia64_rid(ctx,addr) (((ctx) << 3) | (addr >> 61)) +# include <asm/page.h> # ifndef __ASSEMBLY__ #include <linux/compiler.h> @@ -55,34 +56,46 @@ static inline void delayed_tlb_flush (void) { extern void local_flush_tlb_all (void); + unsigned long flags; if (unlikely(__ia64_per_cpu_var(ia64_need_tlb_flush))) { - local_flush_tlb_all(); - __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; + spin_lock_irqsave(&ia64_ctx.lock, flags); + { + if (__ia64_per_cpu_var(ia64_need_tlb_flush)) { + local_flush_tlb_all(); + __ia64_per_cpu_var(ia64_need_tlb_flush) = 0; + } + } + spin_unlock_irqrestore(&ia64_ctx.lock, flags); } } -static inline mm_context_t +static inline nv_mm_context_t get_mmu_context (struct mm_struct *mm) { unsigned long flags; - mm_context_t context = mm->context; - - if (context) - return context; - - spin_lock_irqsave(&ia64_ctx.lock, flags); - { - /* re-check, now that we've got the lock: */ - context = mm->context; - if (context == 0) { - cpus_clear(mm->cpu_vm_mask); - if (ia64_ctx.next >= ia64_ctx.limit) - wrap_mmu_context(mm); - mm->context = context = ia64_ctx.next++; + nv_mm_context_t context = mm->context; + + if (unlikely(!context)) { + spin_lock_irqsave(&ia64_ctx.lock, flags); + { + /* re-check, now that we've got the lock: */ + context = mm->context; + if (context == 0) { + cpus_clear(mm->cpu_vm_mask); + if (ia64_ctx.next >= ia64_ctx.limit) + wrap_mmu_context(mm); + mm->context = context = ia64_ctx.next++; + } } + spin_unlock_irqrestore(&ia64_ctx.lock, flags); } - spin_unlock_irqrestore(&ia64_ctx.lock, flags); + /* + * Ensure we're not starting to use "context" before any old + * uses of it are gone from our TLB. + */ + delayed_tlb_flush(); + return context; } @@ -104,13 +117,13 @@ destroy_context (struct mm_struct *mm) } static inline void -reload_context (mm_context_t context) +reload_context (nv_mm_context_t context) { unsigned long rid; unsigned long rid_incr = 0; unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4; - old_rr4 = ia64_get_rr(0x8000000000000000UL); + old_rr4 = ia64_get_rr(RGN_BASE(RGN_HPAGE)); rid = context << 3; /* make space for encoding the region number */ rid_incr = 1 << 8; @@ -122,6 +135,10 @@ reload_context (mm_context_t context) rr4 = rr0 + 4*rid_incr; #ifdef CONFIG_HUGETLB_PAGE rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc); + +# if RGN_HPAGE != 4 +# error "reload_context assumes RGN_HPAGE is 4" +# endif #endif ia64_set_rr(0x0000000000000000UL, rr0); @@ -138,7 +155,7 @@ reload_context (mm_context_t context) static inline void activate_context (struct mm_struct *mm) { - mm_context_t context; + nv_mm_context_t context; do { context = get_mmu_context(mm); @@ -157,8 +174,6 @@ activate_context (struct mm_struct *mm) static inline void activate_mm (struct mm_struct *prev, struct mm_struct *next) { - delayed_tlb_flush(); - /* * We may get interrupts here, but that's OK because interrupt handlers cannot * touch user-space. diff --git a/include/asm-ia64/page.h b/include/asm-ia64/page.h index 08894f73abf..9edffad8c28 100644 --- a/include/asm-ia64/page.h +++ b/include/asm-ia64/page.h @@ -13,6 +13,19 @@ #include <asm/types.h> /* + * The top three bits of an IA64 address are its Region Number. + * Different regions are assigned to different purposes. + */ +#define RGN_SHIFT (61) +#define RGN_BASE(r) (__IA64_UL_CONST(r)<<RGN_SHIFT) +#define RGN_BITS (RGN_BASE(-1)) + +#define RGN_KERNEL 7 /* Identity mapped region */ +#define RGN_UNCACHED 6 /* Identity mapped I/O region */ +#define RGN_GATE 5 /* Gate page, Kernel text, etc */ +#define RGN_HPAGE 4 /* For Huge TLB pages */ + +/* * PAGE_SHIFT determines the actual kernel page size. */ #if defined(CONFIG_IA64_PAGE_SIZE_4KB) @@ -36,10 +49,9 @@ #define RGN_MAP_LIMIT ((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE) /* per region addr limit */ + #ifdef CONFIG_HUGETLB_PAGE -# define REGION_HPAGE (4UL) /* note: this is hardcoded in reload_context()!*/ -# define REGION_SHIFT 61 -# define HPAGE_REGION_BASE (REGION_HPAGE << REGION_SHIFT) +# define HPAGE_REGION_BASE RGN_BASE(RGN_HPAGE) # define HPAGE_SHIFT hpage_shift # define HPAGE_SHIFT_DEFAULT 28 /* check ia64 SDM for architecture supported size */ # define HPAGE_SIZE (__IA64_UL_CONST(1) << HPAGE_SHIFT) @@ -130,16 +142,13 @@ typedef union ia64_va { #define REGION_NUMBER(x) ({ia64_va _v; _v.l = (long) (x); _v.f.reg;}) #define REGION_OFFSET(x) ({ia64_va _v; _v.l = (long) (x); _v.f.off;}) -#define REGION_SIZE REGION_NUMBER(1) -#define REGION_KERNEL 7 - #ifdef CONFIG_HUGETLB_PAGE # define htlbpage_to_page(x) (((unsigned long) REGION_NUMBER(x) << 61) \ | (REGION_OFFSET(x) >> (HPAGE_SHIFT-PAGE_SHIFT))) # define HUGETLB_PAGE_ORDER (HPAGE_SHIFT - PAGE_SHIFT) # define is_hugepage_only_range(mm, addr, len) \ - (REGION_NUMBER(addr) == REGION_HPAGE && \ - REGION_NUMBER((addr)+(len)-1) == REGION_HPAGE) + (REGION_NUMBER(addr) == RGN_HPAGE && \ + REGION_NUMBER((addr)+(len)-1) == RGN_HPAGE) extern unsigned int hpage_shift; #endif @@ -197,7 +206,7 @@ get_order (unsigned long size) # define __pgprot(x) (x) #endif /* !STRICT_MM_TYPECHECKS */ -#define PAGE_OFFSET __IA64_UL_CONST(0xe000000000000000) +#define PAGE_OFFSET RGN_BASE(RGN_KERNEL) #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | \ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC | \ diff --git a/include/asm-ia64/pal.h b/include/asm-ia64/pal.h index 2303a10ee59..e828377ad29 100644 --- a/include/asm-ia64/pal.h +++ b/include/asm-ia64/pal.h @@ -75,6 +75,8 @@ #define PAL_CACHE_READ 259 /* read tag & data of cacheline for diagnostic testing */ #define PAL_CACHE_WRITE 260 /* write tag & data of cacheline for diagnostic testing */ #define PAL_VM_TR_READ 261 /* read contents of translation register */ +#define PAL_GET_PSTATE 262 /* get the current P-state */ +#define PAL_SET_PSTATE 263 /* set the P-state */ #ifndef __ASSEMBLY__ @@ -1111,6 +1113,25 @@ ia64_pal_halt_info (pal_power_mgmt_info_u_t *power_buf) return iprv.status; } +/* Get the current P-state information */ +static inline s64 +ia64_pal_get_pstate (u64 *pstate_index) +{ + struct ia64_pal_retval iprv; + PAL_CALL_STK(iprv, PAL_GET_PSTATE, 0, 0, 0); + *pstate_index = iprv.v0; + return iprv.status; +} + +/* Set the P-state */ +static inline s64 +ia64_pal_set_pstate (u64 pstate_index) +{ + struct ia64_pal_retval iprv; + PAL_CALL_STK(iprv, PAL_SET_PSTATE, pstate_index, 0, 0); + return iprv.status; +} + /* Cause the processor to enter LIGHT HALT state, where prefetching and execution are * suspended, but cache and TLB coherency is maintained. */ diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 48586e08f43..2e34c06e677 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -204,21 +204,18 @@ ia64_phys_addr_valid (unsigned long addr) #define set_pte(ptep, pteval) (*(ptep) = (pteval)) #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) -#define RGN_SIZE (1UL << 61) -#define RGN_KERNEL 7 - -#define VMALLOC_START 0xa000000200000000UL +#define VMALLOC_START (RGN_BASE(RGN_GATE) + 0x200000000UL) #ifdef CONFIG_VIRTUAL_MEM_MAP -# define VMALLOC_END_INIT (0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9))) +# define VMALLOC_END_INIT (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9))) # define VMALLOC_END vmalloc_end extern unsigned long vmalloc_end; #else -# define VMALLOC_END (0xa000000000000000UL + (1UL << (4*PAGE_SHIFT - 9))) +# define VMALLOC_END (RGN_BASE(RGN_GATE) + (1UL << (4*PAGE_SHIFT - 9))) #endif /* fs/proc/kcore.c */ -#define kc_vaddr_to_offset(v) ((v) - 0xa000000000000000UL) -#define kc_offset_to_vaddr(o) ((o) + 0xa000000000000000UL) +#define kc_vaddr_to_offset(v) ((v) - RGN_BASE(RGN_GATE)) +#define kc_offset_to_vaddr(o) ((o) + RGN_BASE(RGN_GATE)) /* * Conversion functions: convert page frame number (pfn) and a protection value to a page diff --git a/include/asm-ia64/rwsem.h b/include/asm-ia64/rwsem.h index 6ece5061dc1..e18b5ab0cb7 100644 --- a/include/asm-ia64/rwsem.h +++ b/include/asm-ia64/rwsem.h @@ -3,6 +3,7 @@ * * Copyright (C) 2003 Ken Chen <kenneth.w.chen@intel.com> * Copyright (C) 2003 Asit Mallick <asit.k.mallick@intel.com> + * Copyright (C) 2005 Christoph Lameter <clameter@sgi.com> * * Based on asm-i386/rwsem.h and other architecture implementation. * @@ -11,9 +12,9 @@ * * The lock count is initialized to 0 (no active and no waiting lockers). * - * When a writer subtracts WRITE_BIAS, it'll get 0xffff0001 for the case - * of an uncontended lock. Readers increment by 1 and see a positive value - * when uncontended, negative if there are writers (and maybe) readers + * When a writer subtracts WRITE_BIAS, it'll get 0xffffffff00000001 for + * the case of an uncontended lock. Readers increment by 1 and see a positive + * value when uncontended, negative if there are writers (and maybe) readers * waiting (in which case it goes to sleep). */ @@ -29,7 +30,7 @@ * the semaphore definition */ struct rw_semaphore { - signed int count; + signed long count; spinlock_t wait_lock; struct list_head wait_list; #if RWSEM_DEBUG @@ -37,10 +38,10 @@ struct rw_semaphore { #endif }; -#define RWSEM_UNLOCKED_VALUE 0x00000000 -#define RWSEM_ACTIVE_BIAS 0x00000001 -#define RWSEM_ACTIVE_MASK 0x0000ffff -#define RWSEM_WAITING_BIAS (-0x00010000) +#define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000) +#define RWSEM_ACTIVE_BIAS __IA64_UL_CONST(0x0000000000000001) +#define RWSEM_ACTIVE_MASK __IA64_UL_CONST(0x00000000ffffffff) +#define RWSEM_WAITING_BIAS -__IA64_UL_CONST(0x0000000100000000) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) @@ -83,7 +84,7 @@ init_rwsem (struct rw_semaphore *sem) static inline void __down_read (struct rw_semaphore *sem) { - int result = ia64_fetchadd4_acq((unsigned int *)&sem->count, 1); + long result = ia64_fetchadd8_acq((unsigned long *)&sem->count, 1); if (result < 0) rwsem_down_read_failed(sem); @@ -95,7 +96,7 @@ __down_read (struct rw_semaphore *sem) static inline void __down_write (struct rw_semaphore *sem) { - int old, new; + long old, new; do { old = sem->count; @@ -112,7 +113,7 @@ __down_write (struct rw_semaphore *sem) static inline void __up_read (struct rw_semaphore *sem) { - int result = ia64_fetchadd4_rel((unsigned int *)&sem->count, -1); + long result = ia64_fetchadd8_rel((unsigned long *)&sem->count, -1); if (result < 0 && (--result & RWSEM_ACTIVE_MASK) == 0) rwsem_wake(sem); @@ -124,7 +125,7 @@ __up_read (struct rw_semaphore *sem) static inline void __up_write (struct rw_semaphore *sem) { - int old, new; + long old, new; do { old = sem->count; @@ -141,7 +142,7 @@ __up_write (struct rw_semaphore *sem) static inline int __down_read_trylock (struct rw_semaphore *sem) { - int tmp; + long tmp; while ((tmp = sem->count) >= 0) { if (tmp == cmpxchg_acq(&sem->count, tmp, tmp+1)) { return 1; @@ -156,7 +157,7 @@ __down_read_trylock (struct rw_semaphore *sem) static inline int __down_write_trylock (struct rw_semaphore *sem) { - int tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE, + long tmp = cmpxchg_acq(&sem->count, RWSEM_UNLOCKED_VALUE, RWSEM_ACTIVE_WRITE_BIAS); return tmp == RWSEM_UNLOCKED_VALUE; } @@ -167,7 +168,7 @@ __down_write_trylock (struct rw_semaphore *sem) static inline void __downgrade_write (struct rw_semaphore *sem) { - int old, new; + long old, new; do { old = sem->count; @@ -182,7 +183,7 @@ __downgrade_write (struct rw_semaphore *sem) * Implement atomic add functionality. These used to be "inline" functions, but GCC v3.1 * doesn't quite optimize this stuff right and ends up with bad calls to fetchandadd. */ -#define rwsem_atomic_add(delta, sem) atomic_add(delta, (atomic_t *)(&(sem)->count)) -#define rwsem_atomic_update(delta, sem) atomic_add_return(delta, (atomic_t *)(&(sem)->count)) +#define rwsem_atomic_add(delta, sem) atomic64_add(delta, (atomic64_t *)(&(sem)->count)) +#define rwsem_atomic_update(delta, sem) atomic64_add_return(delta, (atomic64_t *)(&(sem)->count)) #endif /* _ASM_IA64_RWSEM_H */ diff --git a/include/asm-ia64/sn/addrs.h b/include/asm-ia64/sn/addrs.h index 103d745dc5f..2c32e4b77b5 100644 --- a/include/asm-ia64/sn/addrs.h +++ b/include/asm-ia64/sn/addrs.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (c) 1992-1999,2001-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (c) 1992-1999,2001-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_ADDRS_H @@ -65,7 +65,6 @@ #define NASID_MASK ((u64)NASID_BITMASK << NASID_SHIFT) #define AS_MASK ((u64)AS_BITMASK << AS_SHIFT) -#define REGION_BITS 0xe000000000000000UL /* @@ -79,38 +78,30 @@ #define AS_CAC_SPACE (AS_CAC_VAL << AS_SHIFT) -/* - * Base addresses for various address ranges. - */ -#define CACHED 0xe000000000000000UL -#define UNCACHED 0xc000000000000000UL -#define UNCACHED_PHYS 0x8000000000000000UL - - /* * Virtual Mode Local & Global MMR space. */ #define SH1_LOCAL_MMR_OFFSET 0x8000000000UL #define SH2_LOCAL_MMR_OFFSET 0x0200000000UL #define LOCAL_MMR_OFFSET (is_shub2() ? SH2_LOCAL_MMR_OFFSET : SH1_LOCAL_MMR_OFFSET) -#define LOCAL_MMR_SPACE (UNCACHED | LOCAL_MMR_OFFSET) -#define LOCAL_PHYS_MMR_SPACE (UNCACHED_PHYS | LOCAL_MMR_OFFSET) +#define LOCAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | LOCAL_MMR_OFFSET) +#define LOCAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | LOCAL_MMR_OFFSET) #define SH1_GLOBAL_MMR_OFFSET 0x0800000000UL #define SH2_GLOBAL_MMR_OFFSET 0x0300000000UL #define GLOBAL_MMR_OFFSET (is_shub2() ? SH2_GLOBAL_MMR_OFFSET : SH1_GLOBAL_MMR_OFFSET) -#define GLOBAL_MMR_SPACE (UNCACHED | GLOBAL_MMR_OFFSET) +#define GLOBAL_MMR_SPACE (__IA64_UNCACHED_OFFSET | GLOBAL_MMR_OFFSET) /* * Physical mode addresses */ -#define GLOBAL_PHYS_MMR_SPACE (UNCACHED_PHYS | GLOBAL_MMR_OFFSET) +#define GLOBAL_PHYS_MMR_SPACE (RGN_BASE(RGN_HPAGE) | GLOBAL_MMR_OFFSET) /* * Clear region & AS bits. */ -#define TO_PHYS_MASK (~(REGION_BITS | AS_MASK)) +#define TO_PHYS_MASK (~(RGN_BITS | AS_MASK)) /* @@ -126,6 +117,7 @@ #define GLOBAL_MMR_PHYS_ADDR(n,a) (GLOBAL_PHYS_MMR_SPACE | REMOTE_ADDR(n,a)) #define GLOBAL_CAC_ADDR(n,a) (CAC_BASE | REMOTE_ADDR(n,a)) #define CHANGE_NASID(n,x) ((void *)(((u64)(x) & ~NASID_MASK) | NASID_SPACE(n))) +#define IS_TIO_NASID(n) ((n) & 1) /* non-II mmr's start at top of big window space (4G) */ @@ -134,10 +126,10 @@ /* * general address defines */ -#define CAC_BASE (CACHED | AS_CAC_SPACE) -#define AMO_BASE (UNCACHED | AS_AMO_SPACE) -#define AMO_PHYS_BASE (UNCACHED_PHYS | AS_AMO_SPACE) -#define GET_BASE (CACHED | AS_GET_SPACE) +#define CAC_BASE (PAGE_OFFSET | AS_CAC_SPACE) +#define AMO_BASE (__IA64_UNCACHED_OFFSET | AS_AMO_SPACE) +#define AMO_PHYS_BASE (RGN_BASE(RGN_HPAGE) | AS_AMO_SPACE) +#define GET_BASE (PAGE_OFFSET | AS_GET_SPACE) /* * Convert Memory addresses between various addressing modes. @@ -155,17 +147,35 @@ * the chiplet id is zero. If we implement TIO-TIO dma, we might need * to insert a chiplet id into this macro. However, it is our belief * right now that this chiplet id will be ICE, which is also zero. - * Nasid starts on bit 40. */ -#define PHYS_TO_TIODMA(x) ( (((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x)) -#define PHYS_TO_DMA(x) ( (((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x)) +#define SH1_TIO_PHYS_TO_DMA(x) \ + ((((u64)(NASID_GET(x))) << 40) | NODE_OFFSET(x)) + +#define SH2_NETWORK_BANK_OFFSET(x) \ + ((u64)(x) & ((1UL << (sn_hub_info->nasid_shift - 4)) -1)) + +#define SH2_NETWORK_BANK_SELECT(x) \ + ((((u64)(x) & (0x3UL << (sn_hub_info->nasid_shift - 4))) \ + >> (sn_hub_info->nasid_shift - 4)) << 36) + +#define SH2_NETWORK_ADDRESS(x) \ + (SH2_NETWORK_BANK_OFFSET(x) | SH2_NETWORK_BANK_SELECT(x)) + +#define SH2_TIO_PHYS_TO_DMA(x) \ + (((u64)(NASID_GET(x)) << 40) | SH2_NETWORK_ADDRESS(x)) + +#define PHYS_TO_TIODMA(x) \ + (is_shub1() ? SH1_TIO_PHYS_TO_DMA(x) : SH2_TIO_PHYS_TO_DMA(x)) + +#define PHYS_TO_DMA(x) \ + ((((u64)(x) & NASID_MASK) >> 2) | NODE_OFFSET(x)) /* * Macros to test for address type. */ -#define IS_AMO_ADDRESS(x) (((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_BASE) -#define IS_AMO_PHYS_ADDRESS(x) (((u64)(x) & (REGION_BITS | AS_MASK)) == AMO_PHYS_BASE) +#define IS_AMO_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_BASE) +#define IS_AMO_PHYS_ADDRESS(x) (((u64)(x) & (RGN_BITS | AS_MASK)) == AMO_PHYS_BASE) /* @@ -180,18 +190,20 @@ #define TIO_SWIN_BASE(n, w) (TIO_IO_BASE(n) + \ ((u64) (w) << TIO_SWIN_SIZE_BITS)) #define NODE_IO_BASE(n) (GLOBAL_MMR_SPACE | NASID_SPACE(n)) -#define TIO_IO_BASE(n) (UNCACHED | NASID_SPACE(n)) +#define TIO_IO_BASE(n) (__IA64_UNCACHED_OFFSET | NASID_SPACE(n)) #define BWIN_SIZE (1UL << BWIN_SIZE_BITS) #define NODE_BWIN_BASE0(n) (NODE_IO_BASE(n) + BWIN_SIZE) #define NODE_BWIN_BASE(n, w) (NODE_BWIN_BASE0(n) + ((u64) (w) << BWIN_SIZE_BITS)) #define RAW_NODE_SWIN_BASE(n, w) (NODE_IO_BASE(n) + ((u64) (w) << SWIN_SIZE_BITS)) #define BWIN_WIDGET_MASK 0x7 #define BWIN_WINDOWNUM(x) (((x) >> BWIN_SIZE_BITS) & BWIN_WIDGET_MASK) +#define SH1_IS_BIG_WINDOW_ADDR(x) ((x) & BWIN_TOP) #define TIO_BWIN_WINDOW_SELECT_MASK 0x7 #define TIO_BWIN_WINDOWNUM(x) (((x) >> TIO_BWIN_SIZE_BITS) & TIO_BWIN_WINDOW_SELECT_MASK) - +#define TIO_HWIN_SHIFT_BITS 33 +#define TIO_HWIN(x) (NODE_OFFSET(x) >> TIO_HWIN_SHIFT_BITS) /* * The following definitions pertain to the IO special address @@ -216,10 +228,6 @@ #define TIO_SWIN_WIDGETNUM(x) (((x) >> TIO_SWIN_SIZE_BITS) & TIO_SWIN_WIDGET_MASK) -#define TIO_IOSPACE_ADDR(n,x) \ - /* Move in the Chiplet ID for TIO Local Block MMR */ \ - (REMOTE_ADDR(n,x) | 1UL << (NASID_SHIFT - 2)) - /* * The following macros produce the correct base virtual address for * the hub registers. The REMOTE_HUB_* macro produce @@ -234,18 +242,40 @@ * Otherwise, the recommended approach is to use *_HUB_L() and *_HUB_S(). * They're always safe. */ +/* Shub1 TIO & MMR addressing macros */ +#define SH1_TIO_IOSPACE_ADDR(n,x) \ + GLOBAL_MMR_ADDR(n,x) + +#define SH1_REMOTE_BWIN_MMR(n,x) \ + GLOBAL_MMR_ADDR(n,x) + +#define SH1_REMOTE_SWIN_MMR(n,x) \ + (NODE_SWIN_BASE(n,1) + 0x800000UL + (x)) + +#define SH1_REMOTE_MMR(n,x) \ + (SH1_IS_BIG_WINDOW_ADDR(x) ? SH1_REMOTE_BWIN_MMR(n,x) : \ + SH1_REMOTE_SWIN_MMR(n,x)) + +/* Shub1 TIO & MMR addressing macros */ +#define SH2_TIO_IOSPACE_ADDR(n,x) \ + ((__IA64_UNCACHED_OFFSET | REMOTE_ADDR(n,x) | 1UL << (NASID_SHIFT - 2))) + +#define SH2_REMOTE_MMR(n,x) \ + GLOBAL_MMR_ADDR(n,x) + + +/* TIO & MMR addressing macros that work on both shub1 & shub2 */ +#define TIO_IOSPACE_ADDR(n,x) \ + ((u64 *)(is_shub1() ? SH1_TIO_IOSPACE_ADDR(n,x) : \ + SH2_TIO_IOSPACE_ADDR(n,x))) + +#define SH_REMOTE_MMR(n,x) \ + (is_shub1() ? SH1_REMOTE_MMR(n,x) : SH2_REMOTE_MMR(n,x)) + #define REMOTE_HUB_ADDR(n,x) \ - ((n & 1) ? \ - /* TIO: */ \ - (is_shub2() ? \ - /* TIO on Shub2 */ \ - (volatile u64 *)(TIO_IOSPACE_ADDR(n,x)) \ - : /* TIO on shub1 */ \ - (volatile u64 *)(GLOBAL_MMR_ADDR(n,x))) \ - \ - : /* SHUB1 and SHUB2 MMRs: */ \ - (((x) & BWIN_TOP) ? ((volatile u64 *)(GLOBAL_MMR_ADDR(n,x))) \ - : ((volatile u64 *)(NODE_SWIN_BASE(n,1) + 0x800000 + (x))))) + (IS_TIO_NASID(n) ? ((volatile u64*)TIO_IOSPACE_ADDR(n,x)) : \ + ((volatile u64*)SH_REMOTE_MMR(n,x))) + #define HUB_L(x) (*((volatile typeof(*x) *)x)) #define HUB_S(x,d) (*((volatile typeof(*x) *)x) = (d)) diff --git a/include/asm-ia64/sn/geo.h b/include/asm-ia64/sn/geo.h index 84b254603b8..f083c943406 100644 --- a/include/asm-ia64/sn/geo.h +++ b/include/asm-ia64/sn/geo.h @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1992 - 1997, 2000-2004 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved. */ #ifndef _ASM_IA64_SN_GEO_H @@ -108,7 +108,6 @@ typedef union geoid_u { #define INVALID_SLAB (slabid_t)-1 #define INVALID_SLOT (slotid_t)-1 #define INVALID_MODULE ((moduleid_t)-1) -#define INVALID_PARTID ((partid_t)-1) static inline slabid_t geo_slab(geoid_t g) { diff --git a/include/asm-ia64/sn/intr.h b/include/asm-ia64/sn/intr.h index e190dd4213d..e35074f526d 100644 --- a/include/asm-ia64/sn/intr.h +++ b/include/asm-ia64/sn/intr.h @@ -12,13 +12,12 @@ #include <linux/rcupdate.h> #define SGI_UART_VECTOR (0xe9) -#define SGI_PCIBR_ERROR (0x33) /* Reserved IRQs : Note, not to exceed IA64_SN2_FIRST_DEVICE_VECTOR */ #define SGI_XPC_ACTIVATE (0x30) #define SGI_II_ERROR (0x31) #define SGI_XBOW_ERROR (0x32) -#define SGI_PCIBR_ERROR (0x33) +#define SGI_PCIASIC_ERROR (0x33) #define SGI_ACPI_SCI_INT (0x34) #define SGI_TIOCA_ERROR (0x35) #define SGI_TIO_ERROR (0x36) diff --git a/include/asm-ia64/sn/nodepda.h b/include/asm-ia64/sn/nodepda.h index 7138b1eafd6..47bb8100fd0 100644 --- a/include/asm-ia64/sn/nodepda.h +++ b/include/asm-ia64/sn/nodepda.h @@ -37,7 +37,6 @@ struct phys_cpuid { struct nodepda_s { void *pdinfo; /* Platform-dependent per-node info */ - spinlock_t bist_lock; /* * The BTEs on this node are shared by the local cpus @@ -55,6 +54,8 @@ struct nodepda_s { * Array of physical cpu identifiers. Indexed by cpuid. */ struct phys_cpuid phys_cpuid[NR_CPUS]; + spinlock_t ptc_lock ____cacheline_aligned_in_smp; + spinlock_t bist_lock; }; typedef struct nodepda_s nodepda_t; diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h index 976f5eff053..ad0e8e8ae53 100644 --- a/include/asm-ia64/sn/pcibus_provider_defs.h +++ b/include/asm-ia64/sn/pcibus_provider_defs.h @@ -18,8 +18,9 @@ #define PCIIO_ASIC_TYPE_PIC 2 #define PCIIO_ASIC_TYPE_TIOCP 3 #define PCIIO_ASIC_TYPE_TIOCA 4 +#define PCIIO_ASIC_TYPE_TIOCE 5 -#define PCIIO_ASIC_MAX_TYPES 5 +#define PCIIO_ASIC_MAX_TYPES 6 /* * Common pciio bus provider data. There should be one of these as the @@ -30,7 +31,8 @@ struct pcibus_bussoft { uint32_t bs_asic_type; /* chipset type */ uint32_t bs_xid; /* xwidget id */ - uint64_t bs_persist_busnum; /* Persistent Bus Number */ + uint32_t bs_persist_busnum; /* Persistent Bus Number */ + uint32_t bs_persist_segment; /* Segment Number */ uint64_t bs_legacy_io; /* legacy io pio addr */ uint64_t bs_legacy_mem; /* legacy mem pio addr */ uint64_t bs_base; /* widget base */ @@ -47,6 +49,8 @@ struct sn_pcibus_provider { dma_addr_t (*dma_map_consistent)(struct pci_dev *, unsigned long, size_t); void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); + void (*force_interrupt)(struct sn_irq_info *); + void (*target_interrupt)(struct sn_irq_info *); }; extern struct sn_pcibus_provider *sn_pci_provider[]; diff --git a/include/asm-ia64/sn/pda.h b/include/asm-ia64/sn/pda.h index ea5590c76ca..1c5108d44d8 100644 --- a/include/asm-ia64/sn/pda.h +++ b/include/asm-ia64/sn/pda.h @@ -39,7 +39,6 @@ typedef struct pda_s { unsigned long pio_write_status_val; volatile unsigned long *pio_shub_war_cam_addr; - unsigned long sn_soft_irr[4]; unsigned long sn_in_service_ivecs[4]; int sn_lb_int_war_ticks; int sn_last_irq; diff --git a/include/asm-ia64/sn/sn2/sn_hwperf.h b/include/asm-ia64/sn/sn2/sn_hwperf.h index df75f4c4aec..291ef3d69da 100644 --- a/include/asm-ia64/sn/sn2/sn_hwperf.h +++ b/include/asm-ia64/sn/sn2/sn_hwperf.h @@ -43,6 +43,7 @@ struct sn_hwperf_object_info { /* macros for object classification */ #define SN_HWPERF_IS_NODE(x) ((x) && strstr((x)->name, "SHub")) +#define SN_HWPERF_IS_NODE_SHUB2(x) ((x) && strstr((x)->name, "SHub 2.")) #define SN_HWPERF_IS_IONODE(x) ((x) && strstr((x)->name, "TIO")) #define SN_HWPERF_IS_ROUTER(x) ((x) && strstr((x)->name, "Router")) #define SN_HWPERF_IS_NL3ROUTER(x) ((x) && strstr((x)->name, "NL3Router")) @@ -214,6 +215,15 @@ struct sn_hwperf_ioctl_args { */ #define SN_HWPERF_GET_NODE_NASID (102|SN_HWPERF_OP_MEM_COPYOUT) +/* + * Given a node id, determine the id of the nearest node with CPUs + * and the id of the nearest node that has memory. The argument + * node would normally be a "headless" node, e.g. an "IO node". + * Return 0 on success. + */ +extern int sn_hwperf_get_nearest_node(cnodeid_t node, + cnodeid_t *near_mem, cnodeid_t *near_cpu); + /* return codes */ #define SN_HWPERF_OP_OK 0 #define SN_HWPERF_OP_NOMEM 1 diff --git a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h index 27976d22318..e67825ad193 100644 --- a/include/asm-ia64/sn/sn_sal.h +++ b/include/asm-ia64/sn/sn_sal.h @@ -55,7 +55,6 @@ #define SN_SAL_BUS_CONFIG 0x02000037 #define SN_SAL_SYS_SERIAL_GET 0x02000038 #define SN_SAL_PARTITION_SERIAL_GET 0x02000039 -#define SN_SAL_SYSCTL_PARTITION_GET 0x0200003a #define SN_SAL_SYSTEM_POWER_DOWN 0x0200003b #define SN_SAL_GET_MASTER_BASEIO_NASID 0x0200003c #define SN_SAL_COHERENCE 0x0200003d @@ -78,7 +77,8 @@ #define SN_SAL_HUB_ERROR_INTERRUPT 0x02000060 #define SN_SAL_BTE_RECOVER 0x02000061 -#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000062 +#define SN_SAL_RESERVED_DO_NOT_USE 0x02000062 +#define SN_SAL_IOIF_GET_PCI_TOPOLOGY 0x02000064 /* * Service-specific constants @@ -586,35 +586,6 @@ sn_partition_serial_number_val(void) { } /* - * Returns the partition id of the nasid passed in as an argument, - * or INVALID_PARTID if the partition id cannot be retrieved. - */ -static inline partid_t -ia64_sn_sysctl_partition_get(nasid_t nasid) -{ - struct ia64_sal_retval ret_stuff; - ia64_sal_oemcall_nolock(&ret_stuff, SN_SAL_SYSCTL_PARTITION_GET, nasid, - 0, 0, 0, 0, 0, 0); - if (ret_stuff.status != 0) - return INVALID_PARTID; - return ((partid_t)ret_stuff.v0); -} - -/* - * Returns the partition id of the current processor. - */ - -extern partid_t sn_partid; - -static inline partid_t -sn_local_partid(void) { - if (unlikely(sn_partid < 0)) { - sn_partid = ia64_sn_sysctl_partition_get(cpuid_to_nasid(smp_processor_id())); - } - return sn_partid; -} - -/* * Returns the physical address of the partition's reserved page through * an iterative number of calls. * @@ -749,7 +720,8 @@ ia64_sn_power_down(void) { struct ia64_sal_retval ret_stuff; SAL_CALL(ret_stuff, SN_SAL_SYSTEM_POWER_DOWN, 0, 0, 0, 0, 0, 0, 0); - while(1); + while(1) + cpu_relax(); /* never returns */ } @@ -1018,24 +990,6 @@ ia64_sn_get_sn_info(int fc, u8 *shubtype, u16 *nasid_bitmask, u8 *nasid_shift, ret_stuff.v2 = 0; SAL_CALL_NOLOCK(ret_stuff, SN_SAL_GET_SN_INFO, fc, 0, 0, 0, 0, 0, 0); -/***** BEGIN HACK - temp til old proms no longer supported ********/ - if (ret_stuff.status == SALRET_NOT_IMPLEMENTED) { - int nasid = get_sapicid() & 0xfff;; -#define SH_SHUB_ID_NODES_PER_BIT_MASK 0x001f000000000000UL -#define SH_SHUB_ID_NODES_PER_BIT_SHFT 48 - if (shubtype) *shubtype = 0; - if (nasid_bitmask) *nasid_bitmask = 0x7ff; - if (nasid_shift) *nasid_shift = 38; - if (systemsize) *systemsize = 11; - if (sharing_domain_size) *sharing_domain_size = 9; - if (partid) *partid = ia64_sn_sysctl_partition_get(nasid); - if (coher) *coher = nasid >> 9; - if (reg) *reg = (HUB_L((u64 *) LOCAL_MMR_ADDR(SH1_SHUB_ID)) & SH_SHUB_ID_NODES_PER_BIT_MASK) >> - SH_SHUB_ID_NODES_PER_BIT_SHFT; - return 0; - } -/***** END HACK *******/ - if (ret_stuff.status < 0) return ret_stuff.status; @@ -1068,12 +1022,10 @@ ia64_sn_hwperf_op(nasid_t nasid, u64 opcode, u64 a0, u64 a1, u64 a2, } static inline int -ia64_sn_ioif_get_pci_topology(u64 rack, u64 bay, u64 slot, u64 slab, - u64 buf, u64 len) +ia64_sn_ioif_get_pci_topology(u64 buf, u64 len) { struct ia64_sal_retval rv; - SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, - rack, bay, slot, slab, buf, len, 0); + SAL_CALL_NOLOCK(rv, SN_SAL_IOIF_GET_PCI_TOPOLOGY, buf, len, 0, 0, 0, 0, 0); return (int) rv.status; } diff --git a/include/asm-ia64/sn/tioce.h b/include/asm-ia64/sn/tioce.h new file mode 100644 index 00000000000..22879853e46 --- /dev/null +++ b/include/asm-ia64/sn/tioce.h @@ -0,0 +1,740 @@ +/************************************************************************** + * * + * Unpublished copyright (c) 2005, Silicon Graphics, Inc. * + * THIS IS UNPUBLISHED CONFIDENTIAL AND PROPRIETARY SOURCE CODE OF SGI. * + * * + * The copyright notice above does not evidence any actual or intended * + * publication or disclosure of this source code, which includes * + * information that is confidential and/or proprietary, and is a trade * + * secret, of Silicon Graphics, Inc. ANY REPRODUCTION, MODIFICATION, * + * DISTRIBUTION, PUBLIC PERFORMANCE, OR PUBLIC DISPLAY OF OR THROUGH * + * USE OF THIS SOURCE CODE WITHOUT THE EXPRESS WRITTEN CONSENT OF * + * SILICON GRAPHICS, INC. IS STRICTLY PROHIBITED, AND IN VIOLATION OF * + * APPLICABLE LAWS AND INTERNATIONAL TREATIES. THE RECEIPT OR * + * POSSESSION OF THIS SOURCE CODE AND/OR RELATED INFORMATION DOES NOT * + * CONVEY OR IMPLY ANY RIGHTS TO REPRODUCE, DISCLOSE OR DISTRIBUTE ITS * + * CONTENTS, OR TO MANUFACTURE, USE, OR SELL ANYTHING THAT IT MAY * + * DESCRIBE, IN WHOLE OR IN PART. * + * * + **************************************************************************/ + +#ifndef __ASM_IA64_SN_TIOCE_H__ +#define __ASM_IA64_SN_TIOCE_H__ + +/* CE ASIC part & mfgr information */ +#define TIOCE_PART_NUM 0xCE00 +#define TIOCE_MFGR_NUM 0x36 +#define TIOCE_REV_A 0x1 + +/* CE Virtual PPB Vendor/Device IDs */ +#define CE_VIRT_PPB_VENDOR_ID 0x10a9 +#define CE_VIRT_PPB_DEVICE_ID 0x4002 + +/* CE Host Bridge Vendor/Device IDs */ +#define CE_HOST_BRIDGE_VENDOR_ID 0x10a9 +#define CE_HOST_BRIDGE_DEVICE_ID 0x4003 + + +#define TIOCE_NUM_M40_ATES 4096 +#define TIOCE_NUM_M3240_ATES 2048 +#define TIOCE_NUM_PORTS 2 + +/* + * Register layout for TIOCE. MMR offsets are shown at the far right of the + * structure definition. + */ +typedef volatile struct tioce { + /* + * ADMIN : Administration Registers + */ + uint64_t ce_adm_id; /* 0x000000 */ + uint64_t ce_pad_000008; /* 0x000008 */ + uint64_t ce_adm_dyn_credit_status; /* 0x000010 */ + uint64_t ce_adm_last_credit_status; /* 0x000018 */ + uint64_t ce_adm_credit_limit; /* 0x000020 */ + uint64_t ce_adm_force_credit; /* 0x000028 */ + uint64_t ce_adm_control; /* 0x000030 */ + uint64_t ce_adm_mmr_chn_timeout; /* 0x000038 */ + uint64_t ce_adm_ssp_ure_timeout; /* 0x000040 */ + uint64_t ce_adm_ssp_dre_timeout; /* 0x000048 */ + uint64_t ce_adm_ssp_debug_sel; /* 0x000050 */ + uint64_t ce_adm_int_status; /* 0x000058 */ + uint64_t ce_adm_int_status_alias; /* 0x000060 */ + uint64_t ce_adm_int_mask; /* 0x000068 */ + uint64_t ce_adm_int_pending; /* 0x000070 */ + uint64_t ce_adm_force_int; /* 0x000078 */ + uint64_t ce_adm_ure_ups_buf_barrier_flush; /* 0x000080 */ + uint64_t ce_adm_int_dest[15]; /* 0x000088 -- 0x0000F8 */ + uint64_t ce_adm_error_summary; /* 0x000100 */ + uint64_t ce_adm_error_summary_alias; /* 0x000108 */ + uint64_t ce_adm_error_mask; /* 0x000110 */ + uint64_t ce_adm_first_error; /* 0x000118 */ + uint64_t ce_adm_error_overflow; /* 0x000120 */ + uint64_t ce_adm_error_overflow_alias; /* 0x000128 */ + uint64_t ce_pad_000130[2]; /* 0x000130 -- 0x000138 */ + uint64_t ce_adm_tnum_error; /* 0x000140 */ + uint64_t ce_adm_mmr_err_detail; /* 0x000148 */ + uint64_t ce_adm_msg_sram_perr_detail; /* 0x000150 */ + uint64_t ce_adm_bap_sram_perr_detail; /* 0x000158 */ + uint64_t ce_adm_ce_sram_perr_detail; /* 0x000160 */ + uint64_t ce_adm_ce_credit_oflow_detail; /* 0x000168 */ + uint64_t ce_adm_tx_link_idle_max_timer; /* 0x000170 */ + uint64_t ce_adm_pcie_debug_sel; /* 0x000178 */ + uint64_t ce_pad_000180[16]; /* 0x000180 -- 0x0001F8 */ + + uint64_t ce_adm_pcie_debug_sel_top; /* 0x000200 */ + uint64_t ce_adm_pcie_debug_lat_sel_lo_top; /* 0x000208 */ + uint64_t ce_adm_pcie_debug_lat_sel_hi_top; /* 0x000210 */ + uint64_t ce_adm_pcie_debug_trig_sel_top; /* 0x000218 */ + uint64_t ce_adm_pcie_debug_trig_lat_sel_lo_top; /* 0x000220 */ + uint64_t ce_adm_pcie_debug_trig_lat_sel_hi_top; /* 0x000228 */ + uint64_t ce_adm_pcie_trig_compare_top; /* 0x000230 */ + uint64_t ce_adm_pcie_trig_compare_en_top; /* 0x000238 */ + uint64_t ce_adm_ssp_debug_sel_top; /* 0x000240 */ + uint64_t ce_adm_ssp_debug_lat_sel_lo_top; /* 0x000248 */ + uint64_t ce_adm_ssp_debug_lat_sel_hi_top; /* 0x000250 */ + uint64_t ce_adm_ssp_debug_trig_sel_top; /* 0x000258 */ + uint64_t ce_adm_ssp_debug_trig_lat_sel_lo_top; /* 0x000260 */ + uint64_t ce_adm_ssp_debug_trig_lat_sel_hi_top; /* 0x000268 */ + uint64_t ce_adm_ssp_trig_compare_top; /* 0x000270 */ + uint64_t ce_adm_ssp_trig_compare_en_top; /* 0x000278 */ + uint64_t ce_pad_000280[48]; /* 0x000280 -- 0x0003F8 */ + + uint64_t ce_adm_bap_ctrl; /* 0x000400 */ + uint64_t ce_pad_000408[127]; /* 0x000408 -- 0x0007F8 */ + + uint64_t ce_msg_buf_data63_0[35]; /* 0x000800 -- 0x000918 */ + uint64_t ce_pad_000920[29]; /* 0x000920 -- 0x0009F8 */ + + uint64_t ce_msg_buf_data127_64[35]; /* 0x000A00 -- 0x000B18 */ + uint64_t ce_pad_000B20[29]; /* 0x000B20 -- 0x000BF8 */ + + uint64_t ce_msg_buf_parity[35]; /* 0x000C00 -- 0x000D18 */ + uint64_t ce_pad_000D20[29]; /* 0x000D20 -- 0x000DF8 */ + + uint64_t ce_pad_000E00[576]; /* 0x000E00 -- 0x001FF8 */ + + /* + * LSI : LSI's PCI Express Link Registers (Link#1 and Link#2) + * Link#1 MMRs at start at 0x002000, Link#2 MMRs at 0x003000 + * NOTE: the comment offsets at far right: let 'z' = {2 or 3} + */ + #define ce_lsi(link_num) ce_lsi[link_num-1] + struct ce_lsi_reg { + uint64_t ce_lsi_lpu_id; /* 0x00z000 */ + uint64_t ce_lsi_rst; /* 0x00z008 */ + uint64_t ce_lsi_dbg_stat; /* 0x00z010 */ + uint64_t ce_lsi_dbg_cfg; /* 0x00z018 */ + uint64_t ce_lsi_ltssm_ctrl; /* 0x00z020 */ + uint64_t ce_lsi_lk_stat; /* 0x00z028 */ + uint64_t ce_pad_00z030[2]; /* 0x00z030 -- 0x00z038 */ + uint64_t ce_lsi_int_and_stat; /* 0x00z040 */ + uint64_t ce_lsi_int_mask; /* 0x00z048 */ + uint64_t ce_pad_00z050[22]; /* 0x00z050 -- 0x00z0F8 */ + uint64_t ce_lsi_lk_perf_cnt_sel; /* 0x00z100 */ + uint64_t ce_pad_00z108; /* 0x00z108 */ + uint64_t ce_lsi_lk_perf_cnt_ctrl; /* 0x00z110 */ + uint64_t ce_pad_00z118; /* 0x00z118 */ + uint64_t ce_lsi_lk_perf_cnt1; /* 0x00z120 */ + uint64_t ce_lsi_lk_perf_cnt1_test; /* 0x00z128 */ + uint64_t ce_lsi_lk_perf_cnt2; /* 0x00z130 */ + uint64_t ce_lsi_lk_perf_cnt2_test; /* 0x00z138 */ + uint64_t ce_pad_00z140[24]; /* 0x00z140 -- 0x00z1F8 */ + uint64_t ce_lsi_lk_lyr_cfg; /* 0x00z200 */ + uint64_t ce_lsi_lk_lyr_status; /* 0x00z208 */ + uint64_t ce_lsi_lk_lyr_int_stat; /* 0x00z210 */ + uint64_t ce_lsi_lk_ly_int_stat_test; /* 0x00z218 */ + uint64_t ce_lsi_lk_ly_int_stat_mask; /* 0x00z220 */ + uint64_t ce_pad_00z228[3]; /* 0x00z228 -- 0x00z238 */ + uint64_t ce_lsi_fc_upd_ctl; /* 0x00z240 */ + uint64_t ce_pad_00z248[3]; /* 0x00z248 -- 0x00z258 */ + uint64_t ce_lsi_flw_ctl_upd_to_timer; /* 0x00z260 */ + uint64_t ce_lsi_flw_ctl_upd_timer0; /* 0x00z268 */ + uint64_t ce_lsi_flw_ctl_upd_timer1; /* 0x00z270 */ + uint64_t ce_pad_00z278[49]; /* 0x00z278 -- 0x00z3F8 */ + uint64_t ce_lsi_freq_nak_lat_thrsh; /* 0x00z400 */ + uint64_t ce_lsi_ack_nak_lat_tmr; /* 0x00z408 */ + uint64_t ce_lsi_rply_tmr_thr; /* 0x00z410 */ + uint64_t ce_lsi_rply_tmr; /* 0x00z418 */ + uint64_t ce_lsi_rply_num_stat; /* 0x00z420 */ + uint64_t ce_lsi_rty_buf_max_addr; /* 0x00z428 */ + uint64_t ce_lsi_rty_fifo_ptr; /* 0x00z430 */ + uint64_t ce_lsi_rty_fifo_rd_wr_ptr; /* 0x00z438 */ + uint64_t ce_lsi_rty_fifo_cred; /* 0x00z440 */ + uint64_t ce_lsi_seq_cnt; /* 0x00z448 */ + uint64_t ce_lsi_ack_sent_seq_num; /* 0x00z450 */ + uint64_t ce_lsi_seq_cnt_fifo_max_addr; /* 0x00z458 */ + uint64_t ce_lsi_seq_cnt_fifo_ptr; /* 0x00z460 */ + uint64_t ce_lsi_seq_cnt_rd_wr_ptr; /* 0x00z468 */ + uint64_t ce_lsi_tx_lk_ts_ctl; /* 0x00z470 */ + uint64_t ce_pad_00z478; /* 0x00z478 */ + uint64_t ce_lsi_mem_addr_ctl; /* 0x00z480 */ + uint64_t ce_lsi_mem_d_ld0; /* 0x00z488 */ + uint64_t ce_lsi_mem_d_ld1; /* 0x00z490 */ + uint64_t ce_lsi_mem_d_ld2; /* 0x00z498 */ + uint64_t ce_lsi_mem_d_ld3; /* 0x00z4A0 */ + uint64_t ce_lsi_mem_d_ld4; /* 0x00z4A8 */ + uint64_t ce_pad_00z4B0[2]; /* 0x00z4B0 -- 0x00z4B8 */ + uint64_t ce_lsi_rty_d_cnt; /* 0x00z4C0 */ + uint64_t ce_lsi_seq_buf_cnt; /* 0x00z4C8 */ + uint64_t ce_lsi_seq_buf_bt_d; /* 0x00z4D0 */ + uint64_t ce_pad_00z4D8; /* 0x00z4D8 */ + uint64_t ce_lsi_ack_lat_thr; /* 0x00z4E0 */ + uint64_t ce_pad_00z4E8[3]; /* 0x00z4E8 -- 0x00z4F8 */ + uint64_t ce_lsi_nxt_rcv_seq_1_cntr; /* 0x00z500 */ + uint64_t ce_lsi_unsp_dllp_rcvd; /* 0x00z508 */ + uint64_t ce_lsi_rcv_lk_ts_ctl; /* 0x00z510 */ + uint64_t ce_pad_00z518[29]; /* 0x00z518 -- 0x00z5F8 */ + uint64_t ce_lsi_phy_lyr_cfg; /* 0x00z600 */ + uint64_t ce_pad_00z608; /* 0x00z608 */ + uint64_t ce_lsi_phy_lyr_int_stat; /* 0x00z610 */ + uint64_t ce_lsi_phy_lyr_int_stat_test; /* 0x00z618 */ + uint64_t ce_lsi_phy_lyr_int_mask; /* 0x00z620 */ + uint64_t ce_pad_00z628[11]; /* 0x00z628 -- 0x00z678 */ + uint64_t ce_lsi_rcv_phy_cfg; /* 0x00z680 */ + uint64_t ce_lsi_rcv_phy_stat1; /* 0x00z688 */ + uint64_t ce_lsi_rcv_phy_stat2; /* 0x00z690 */ + uint64_t ce_lsi_rcv_phy_stat3; /* 0x00z698 */ + uint64_t ce_lsi_rcv_phy_int_stat; /* 0x00z6A0 */ + uint64_t ce_lsi_rcv_phy_int_stat_test; /* 0x00z6A8 */ + uint64_t ce_lsi_rcv_phy_int_mask; /* 0x00z6B0 */ + uint64_t ce_pad_00z6B8[9]; /* 0x00z6B8 -- 0x00z6F8 */ + uint64_t ce_lsi_tx_phy_cfg; /* 0x00z700 */ + uint64_t ce_lsi_tx_phy_stat; /* 0x00z708 */ + uint64_t ce_lsi_tx_phy_int_stat; /* 0x00z710 */ + uint64_t ce_lsi_tx_phy_int_stat_test; /* 0x00z718 */ + uint64_t ce_lsi_tx_phy_int_mask; /* 0x00z720 */ + uint64_t ce_lsi_tx_phy_stat2; /* 0x00z728 */ + uint64_t ce_pad_00z730[10]; /* 0x00z730 -- 0x00z77F */ + uint64_t ce_lsi_ltssm_cfg1; /* 0x00z780 */ + uint64_t ce_lsi_ltssm_cfg2; /* 0x00z788 */ + uint64_t ce_lsi_ltssm_cfg3; /* 0x00z790 */ + uint64_t ce_lsi_ltssm_cfg4; /* 0x00z798 */ + uint64_t ce_lsi_ltssm_cfg5; /* 0x00z7A0 */ + uint64_t ce_lsi_ltssm_stat1; /* 0x00z7A8 */ + uint64_t ce_lsi_ltssm_stat2; /* 0x00z7B0 */ + uint64_t ce_lsi_ltssm_int_stat; /* 0x00z7B8 */ + uint64_t ce_lsi_ltssm_int_stat_test; /* 0x00z7C0 */ + uint64_t ce_lsi_ltssm_int_mask; /* 0x00z7C8 */ + uint64_t ce_lsi_ltssm_stat_wr_en; /* 0x00z7D0 */ + uint64_t ce_pad_00z7D8[5]; /* 0x00z7D8 -- 0x00z7F8 */ + uint64_t ce_lsi_gb_cfg1; /* 0x00z800 */ + uint64_t ce_lsi_gb_cfg2; /* 0x00z808 */ + uint64_t ce_lsi_gb_cfg3; /* 0x00z810 */ + uint64_t ce_lsi_gb_cfg4; /* 0x00z818 */ + uint64_t ce_lsi_gb_stat; /* 0x00z820 */ + uint64_t ce_lsi_gb_int_stat; /* 0x00z828 */ + uint64_t ce_lsi_gb_int_stat_test; /* 0x00z830 */ + uint64_t ce_lsi_gb_int_mask; /* 0x00z838 */ + uint64_t ce_lsi_gb_pwr_dn1; /* 0x00z840 */ + uint64_t ce_lsi_gb_pwr_dn2; /* 0x00z848 */ + uint64_t ce_pad_00z850[246]; /* 0x00z850 -- 0x00zFF8 */ + } ce_lsi[2]; + + uint64_t ce_pad_004000[10]; /* 0x004000 -- 0x004048 */ + + /* + * CRM: Coretalk Receive Module Registers + */ + uint64_t ce_crm_debug_mux; /* 0x004050 */ + uint64_t ce_pad_004058; /* 0x004058 */ + uint64_t ce_crm_ssp_err_cmd_wrd; /* 0x004060 */ + uint64_t ce_crm_ssp_err_addr; /* 0x004068 */ + uint64_t ce_crm_ssp_err_syn; /* 0x004070 */ + + uint64_t ce_pad_004078[499]; /* 0x004078 -- 0x005008 */ + + /* + * CXM: Coretalk Xmit Module Registers + */ + uint64_t ce_cxm_dyn_credit_status; /* 0x005010 */ + uint64_t ce_cxm_last_credit_status; /* 0x005018 */ + uint64_t ce_cxm_credit_limit; /* 0x005020 */ + uint64_t ce_cxm_force_credit; /* 0x005028 */ + uint64_t ce_cxm_disable_bypass; /* 0x005030 */ + uint64_t ce_pad_005038[3]; /* 0x005038 -- 0x005048 */ + uint64_t ce_cxm_debug_mux; /* 0x005050 */ + + uint64_t ce_pad_005058[501]; /* 0x005058 -- 0x005FF8 */ + + /* + * DTL: Downstream Transaction Layer Regs (Link#1 and Link#2) + * DTL: Link#1 MMRs at start at 0x006000, Link#2 MMRs at 0x008000 + * DTL: the comment offsets at far right: let 'y' = {6 or 8} + * + * UTL: Downstream Transaction Layer Regs (Link#1 and Link#2) + * UTL: Link#1 MMRs at start at 0x007000, Link#2 MMRs at 0x009000 + * UTL: the comment offsets at far right: let 'z' = {7 or 9} + */ + #define ce_dtl(link_num) ce_dtl_utl[link_num-1] + #define ce_utl(link_num) ce_dtl_utl[link_num-1] + struct ce_dtl_utl_reg { + /* DTL */ + uint64_t ce_dtl_dtdr_credit_limit; /* 0x00y000 */ + uint64_t ce_dtl_dtdr_credit_force; /* 0x00y008 */ + uint64_t ce_dtl_dyn_credit_status; /* 0x00y010 */ + uint64_t ce_dtl_dtl_last_credit_stat; /* 0x00y018 */ + uint64_t ce_dtl_dtl_ctrl; /* 0x00y020 */ + uint64_t ce_pad_00y028[5]; /* 0x00y028 -- 0x00y048 */ + uint64_t ce_dtl_debug_sel; /* 0x00y050 */ + uint64_t ce_pad_00y058[501]; /* 0x00y058 -- 0x00yFF8 */ + + /* UTL */ + uint64_t ce_utl_utl_ctrl; /* 0x00z000 */ + uint64_t ce_utl_debug_sel; /* 0x00z008 */ + uint64_t ce_pad_00z010[510]; /* 0x00z010 -- 0x00zFF8 */ + } ce_dtl_utl[2]; + + uint64_t ce_pad_00A000[514]; /* 0x00A000 -- 0x00B008 */ + + /* + * URE: Upstream Request Engine + */ + uint64_t ce_ure_dyn_credit_status; /* 0x00B010 */ + uint64_t ce_ure_last_credit_status; /* 0x00B018 */ + uint64_t ce_ure_credit_limit; /* 0x00B020 */ + uint64_t ce_pad_00B028; /* 0x00B028 */ + uint64_t ce_ure_control; /* 0x00B030 */ + uint64_t ce_ure_status; /* 0x00B038 */ + uint64_t ce_pad_00B040[2]; /* 0x00B040 -- 0x00B048 */ + uint64_t ce_ure_debug_sel; /* 0x00B050 */ + uint64_t ce_ure_pcie_debug_sel; /* 0x00B058 */ + uint64_t ce_ure_ssp_err_cmd_wrd; /* 0x00B060 */ + uint64_t ce_ure_ssp_err_addr; /* 0x00B068 */ + uint64_t ce_ure_page_map; /* 0x00B070 */ + uint64_t ce_ure_dir_map[TIOCE_NUM_PORTS]; /* 0x00B078 */ + uint64_t ce_ure_pipe_sel1; /* 0x00B088 */ + uint64_t ce_ure_pipe_mask1; /* 0x00B090 */ + uint64_t ce_ure_pipe_sel2; /* 0x00B098 */ + uint64_t ce_ure_pipe_mask2; /* 0x00B0A0 */ + uint64_t ce_ure_pcie1_credits_sent; /* 0x00B0A8 */ + uint64_t ce_ure_pcie1_credits_used; /* 0x00B0B0 */ + uint64_t ce_ure_pcie1_credit_limit; /* 0x00B0B8 */ + uint64_t ce_ure_pcie2_credits_sent; /* 0x00B0C0 */ + uint64_t ce_ure_pcie2_credits_used; /* 0x00B0C8 */ + uint64_t ce_ure_pcie2_credit_limit; /* 0x00B0D0 */ + uint64_t ce_ure_pcie_force_credit; /* 0x00B0D8 */ + uint64_t ce_ure_rd_tnum_val; /* 0x00B0E0 */ + uint64_t ce_ure_rd_tnum_rsp_rcvd; /* 0x00B0E8 */ + uint64_t ce_ure_rd_tnum_esent_timer; /* 0x00B0F0 */ + uint64_t ce_ure_rd_tnum_error; /* 0x00B0F8 */ + uint64_t ce_ure_rd_tnum_first_cl; /* 0x00B100 */ + uint64_t ce_ure_rd_tnum_link_buf; /* 0x00B108 */ + uint64_t ce_ure_wr_tnum_val; /* 0x00B110 */ + uint64_t ce_ure_sram_err_addr0; /* 0x00B118 */ + uint64_t ce_ure_sram_err_addr1; /* 0x00B120 */ + uint64_t ce_ure_sram_err_addr2; /* 0x00B128 */ + uint64_t ce_ure_sram_rd_addr0; /* 0x00B130 */ + uint64_t ce_ure_sram_rd_addr1; /* 0x00B138 */ + uint64_t ce_ure_sram_rd_addr2; /* 0x00B140 */ + uint64_t ce_ure_sram_wr_addr0; /* 0x00B148 */ + uint64_t ce_ure_sram_wr_addr1; /* 0x00B150 */ + uint64_t ce_ure_sram_wr_addr2; /* 0x00B158 */ + uint64_t ce_ure_buf_flush10; /* 0x00B160 */ + uint64_t ce_ure_buf_flush11; /* 0x00B168 */ + uint64_t ce_ure_buf_flush12; /* 0x00B170 */ + uint64_t ce_ure_buf_flush13; /* 0x00B178 */ + uint64_t ce_ure_buf_flush20; /* 0x00B180 */ + uint64_t ce_ure_buf_flush21; /* 0x00B188 */ + uint64_t ce_ure_buf_flush22; /* 0x00B190 */ + uint64_t ce_ure_buf_flush23; /* 0x00B198 */ + uint64_t ce_ure_pcie_control1; /* 0x00B1A0 */ + uint64_t ce_ure_pcie_control2; /* 0x00B1A8 */ + + uint64_t ce_pad_00B1B0[458]; /* 0x00B1B0 -- 0x00BFF8 */ + + /* Upstream Data Buffer, Port1 */ + struct ce_ure_maint_ups_dat1_data { + uint64_t data63_0[512]; /* 0x00C000 -- 0x00CFF8 */ + uint64_t data127_64[512]; /* 0x00D000 -- 0x00DFF8 */ + uint64_t parity[512]; /* 0x00E000 -- 0x00EFF8 */ + } ce_ure_maint_ups_dat1; + + /* Upstream Header Buffer, Port1 */ + struct ce_ure_maint_ups_hdr1_data { + uint64_t data63_0[512]; /* 0x00F000 -- 0x00FFF8 */ + uint64_t data127_64[512]; /* 0x010000 -- 0x010FF8 */ + uint64_t parity[512]; /* 0x011000 -- 0x011FF8 */ + } ce_ure_maint_ups_hdr1; + + /* Upstream Data Buffer, Port2 */ + struct ce_ure_maint_ups_dat2_data { + uint64_t data63_0[512]; /* 0x012000 -- 0x012FF8 */ + uint64_t data127_64[512]; /* 0x013000 -- 0x013FF8 */ + uint64_t parity[512]; /* 0x014000 -- 0x014FF8 */ + } ce_ure_maint_ups_dat2; + + /* Upstream Header Buffer, Port2 */ + struct ce_ure_maint_ups_hdr2_data { + uint64_t data63_0[512]; /* 0x015000 -- 0x015FF8 */ + uint64_t data127_64[512]; /* 0x016000 -- 0x016FF8 */ + uint64_t parity[512]; /* 0x017000 -- 0x017FF8 */ + } ce_ure_maint_ups_hdr2; + + /* Downstream Data Buffer */ + struct ce_ure_maint_dns_dat_data { + uint64_t data63_0[512]; /* 0x018000 -- 0x018FF8 */ + uint64_t data127_64[512]; /* 0x019000 -- 0x019FF8 */ + uint64_t parity[512]; /* 0x01A000 -- 0x01AFF8 */ + } ce_ure_maint_dns_dat; + + /* Downstream Header Buffer */ + struct ce_ure_maint_dns_hdr_data { + uint64_t data31_0[64]; /* 0x01B000 -- 0x01B1F8 */ + uint64_t data95_32[64]; /* 0x01B200 -- 0x01B3F8 */ + uint64_t parity[64]; /* 0x01B400 -- 0x01B5F8 */ + } ce_ure_maint_dns_hdr; + + /* RCI Buffer Data */ + struct ce_ure_maint_rci_data { + uint64_t data41_0[64]; /* 0x01B600 -- 0x01B7F8 */ + uint64_t data69_42[64]; /* 0x01B800 -- 0x01B9F8 */ + } ce_ure_maint_rci; + + /* Response Queue */ + uint64_t ce_ure_maint_rspq[64]; /* 0x01BA00 -- 0x01BBF8 */ + + uint64_t ce_pad_01C000[4224]; /* 0x01BC00 -- 0x023FF8 */ + + /* Admin Build-a-Packet Buffer */ + struct ce_adm_maint_bap_buf_data { + uint64_t data63_0[258]; /* 0x024000 -- 0x024808 */ + uint64_t data127_64[258]; /* 0x024810 -- 0x025018 */ + uint64_t parity[258]; /* 0x025020 -- 0x025828 */ + } ce_adm_maint_bap_buf; + + uint64_t ce_pad_025830[5370]; /* 0x025830 -- 0x02FFF8 */ + + /* URE: 40bit PMU ATE Buffer */ /* 0x030000 -- 0x037FF8 */ + uint64_t ce_ure_ate40[TIOCE_NUM_M40_ATES]; + + /* URE: 32/40bit PMU ATE Buffer */ /* 0x038000 -- 0x03BFF8 */ + uint64_t ce_ure_ate3240[TIOCE_NUM_M3240_ATES]; + + uint64_t ce_pad_03C000[2050]; /* 0x03C000 -- 0x040008 */ + + /* + * DRE: Down Stream Request Engine + */ + uint64_t ce_dre_dyn_credit_status1; /* 0x040010 */ + uint64_t ce_dre_dyn_credit_status2; /* 0x040018 */ + uint64_t ce_dre_last_credit_status1; /* 0x040020 */ + uint64_t ce_dre_last_credit_status2; /* 0x040028 */ + uint64_t ce_dre_credit_limit1; /* 0x040030 */ + uint64_t ce_dre_credit_limit2; /* 0x040038 */ + uint64_t ce_dre_force_credit1; /* 0x040040 */ + uint64_t ce_dre_force_credit2; /* 0x040048 */ + uint64_t ce_dre_debug_mux1; /* 0x040050 */ + uint64_t ce_dre_debug_mux2; /* 0x040058 */ + uint64_t ce_dre_ssp_err_cmd_wrd; /* 0x040060 */ + uint64_t ce_dre_ssp_err_addr; /* 0x040068 */ + uint64_t ce_dre_comp_err_cmd_wrd; /* 0x040070 */ + uint64_t ce_dre_comp_err_addr; /* 0x040078 */ + uint64_t ce_dre_req_status; /* 0x040080 */ + uint64_t ce_dre_config1; /* 0x040088 */ + uint64_t ce_dre_config2; /* 0x040090 */ + uint64_t ce_dre_config_req_status; /* 0x040098 */ + uint64_t ce_pad_0400A0[12]; /* 0x0400A0 -- 0x0400F8 */ + uint64_t ce_dre_dyn_fifo; /* 0x040100 */ + uint64_t ce_pad_040108[3]; /* 0x040108 -- 0x040118 */ + uint64_t ce_dre_last_fifo; /* 0x040120 */ + + uint64_t ce_pad_040128[27]; /* 0x040128 -- 0x0401F8 */ + + /* DRE Downstream Head Queue */ + struct ce_dre_maint_ds_head_queue { + uint64_t data63_0[32]; /* 0x040200 -- 0x0402F8 */ + uint64_t data127_64[32]; /* 0x040300 -- 0x0403F8 */ + uint64_t parity[32]; /* 0x040400 -- 0x0404F8 */ + } ce_dre_maint_ds_head_q; + + uint64_t ce_pad_040500[352]; /* 0x040500 -- 0x040FF8 */ + + /* DRE Downstream Data Queue */ + struct ce_dre_maint_ds_data_queue { + uint64_t data63_0[256]; /* 0x041000 -- 0x0417F8 */ + uint64_t ce_pad_041800[256]; /* 0x041800 -- 0x041FF8 */ + uint64_t data127_64[256]; /* 0x042000 -- 0x0427F8 */ + uint64_t ce_pad_042800[256]; /* 0x042800 -- 0x042FF8 */ + uint64_t parity[256]; /* 0x043000 -- 0x0437F8 */ + uint64_t ce_pad_043800[256]; /* 0x043800 -- 0x043FF8 */ + } ce_dre_maint_ds_data_q; + + /* DRE URE Upstream Response Queue */ + struct ce_dre_maint_ure_us_rsp_queue { + uint64_t data63_0[8]; /* 0x044000 -- 0x044038 */ + uint64_t ce_pad_044040[24]; /* 0x044040 -- 0x0440F8 */ + uint64_t data127_64[8]; /* 0x044100 -- 0x044138 */ + uint64_t ce_pad_044140[24]; /* 0x044140 -- 0x0441F8 */ + uint64_t parity[8]; /* 0x044200 -- 0x044238 */ + uint64_t ce_pad_044240[24]; /* 0x044240 -- 0x0442F8 */ + } ce_dre_maint_ure_us_rsp_q; + + uint64_t ce_dre_maint_us_wrt_rsp[32];/* 0x044300 -- 0x0443F8 */ + + uint64_t ce_end_of_struct; /* 0x044400 */ +} tioce_t; + + +/* ce_adm_int_mask/ce_adm_int_status register bit defines */ +#define CE_ADM_INT_CE_ERROR_SHFT 0 +#define CE_ADM_INT_LSI1_IP_ERROR_SHFT 1 +#define CE_ADM_INT_LSI2_IP_ERROR_SHFT 2 +#define CE_ADM_INT_PCIE_ERROR_SHFT 3 +#define CE_ADM_INT_PORT1_HOTPLUG_EVENT_SHFT 4 +#define CE_ADM_INT_PORT2_HOTPLUG_EVENT_SHFT 5 +#define CE_ADM_INT_PCIE_PORT1_DEV_A_SHFT 6 +#define CE_ADM_INT_PCIE_PORT1_DEV_B_SHFT 7 +#define CE_ADM_INT_PCIE_PORT1_DEV_C_SHFT 8 +#define CE_ADM_INT_PCIE_PORT1_DEV_D_SHFT 9 +#define CE_ADM_INT_PCIE_PORT2_DEV_A_SHFT 10 +#define CE_ADM_INT_PCIE_PORT2_DEV_B_SHFT 11 +#define CE_ADM_INT_PCIE_PORT2_DEV_C_SHFT 12 +#define CE_ADM_INT_PCIE_PORT2_DEV_D_SHFT 13 +#define CE_ADM_INT_PCIE_MSG_SHFT 14 /*see int_dest_14*/ +#define CE_ADM_INT_PCIE_MSG_SLOT_0_SHFT 14 +#define CE_ADM_INT_PCIE_MSG_SLOT_1_SHFT 15 +#define CE_ADM_INT_PCIE_MSG_SLOT_2_SHFT 16 +#define CE_ADM_INT_PCIE_MSG_SLOT_3_SHFT 17 +#define CE_ADM_INT_PORT1_PM_PME_MSG_SHFT 22 +#define CE_ADM_INT_PORT2_PM_PME_MSG_SHFT 23 + +/* ce_adm_force_int register bit defines */ +#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_A_SHFT 0 +#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_B_SHFT 1 +#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_C_SHFT 2 +#define CE_ADM_FORCE_INT_PCIE_PORT1_DEV_D_SHFT 3 +#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_A_SHFT 4 +#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_B_SHFT 5 +#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_C_SHFT 6 +#define CE_ADM_FORCE_INT_PCIE_PORT2_DEV_D_SHFT 7 +#define CE_ADM_FORCE_INT_ALWAYS_SHFT 8 + +/* ce_adm_int_dest register bit masks & shifts */ +#define INTR_VECTOR_SHFT 56 + +/* ce_adm_error_mask and ce_adm_error_summary register bit masks */ +#define CE_ADM_ERR_CRM_SSP_REQ_INVALID (0x1ULL << 0) +#define CE_ADM_ERR_SSP_REQ_HEADER (0x1ULL << 1) +#define CE_ADM_ERR_SSP_RSP_HEADER (0x1ULL << 2) +#define CE_ADM_ERR_SSP_PROTOCOL_ERROR (0x1ULL << 3) +#define CE_ADM_ERR_SSP_SBE (0x1ULL << 4) +#define CE_ADM_ERR_SSP_MBE (0x1ULL << 5) +#define CE_ADM_ERR_CXM_CREDIT_OFLOW (0x1ULL << 6) +#define CE_ADM_ERR_DRE_SSP_REQ_INVAL (0x1ULL << 7) +#define CE_ADM_ERR_SSP_REQ_LONG (0x1ULL << 8) +#define CE_ADM_ERR_SSP_REQ_OFLOW (0x1ULL << 9) +#define CE_ADM_ERR_SSP_REQ_SHORT (0x1ULL << 10) +#define CE_ADM_ERR_SSP_REQ_SIDEBAND (0x1ULL << 11) +#define CE_ADM_ERR_SSP_REQ_ADDR_ERR (0x1ULL << 12) +#define CE_ADM_ERR_SSP_REQ_BAD_BE (0x1ULL << 13) +#define CE_ADM_ERR_PCIE_COMPL_TIMEOUT (0x1ULL << 14) +#define CE_ADM_ERR_PCIE_UNEXP_COMPL (0x1ULL << 15) +#define CE_ADM_ERR_PCIE_ERR_COMPL (0x1ULL << 16) +#define CE_ADM_ERR_DRE_CREDIT_OFLOW (0x1ULL << 17) +#define CE_ADM_ERR_DRE_SRAM_PE (0x1ULL << 18) +#define CE_ADM_ERR_SSP_RSP_INVALID (0x1ULL << 19) +#define CE_ADM_ERR_SSP_RSP_LONG (0x1ULL << 20) +#define CE_ADM_ERR_SSP_RSP_SHORT (0x1ULL << 21) +#define CE_ADM_ERR_SSP_RSP_SIDEBAND (0x1ULL << 22) +#define CE_ADM_ERR_URE_SSP_RSP_UNEXP (0x1ULL << 23) +#define CE_ADM_ERR_URE_SSP_WR_REQ_TIMEOUT (0x1ULL << 24) +#define CE_ADM_ERR_URE_SSP_RD_REQ_TIMEOUT (0x1ULL << 25) +#define CE_ADM_ERR_URE_ATE3240_PAGE_FAULT (0x1ULL << 26) +#define CE_ADM_ERR_URE_ATE40_PAGE_FAULT (0x1ULL << 27) +#define CE_ADM_ERR_URE_CREDIT_OFLOW (0x1ULL << 28) +#define CE_ADM_ERR_URE_SRAM_PE (0x1ULL << 29) +#define CE_ADM_ERR_ADM_SSP_RSP_UNEXP (0x1ULL << 30) +#define CE_ADM_ERR_ADM_SSP_REQ_TIMEOUT (0x1ULL << 31) +#define CE_ADM_ERR_MMR_ACCESS_ERROR (0x1ULL << 32) +#define CE_ADM_ERR_MMR_ADDR_ERROR (0x1ULL << 33) +#define CE_ADM_ERR_ADM_CREDIT_OFLOW (0x1ULL << 34) +#define CE_ADM_ERR_ADM_SRAM_PE (0x1ULL << 35) +#define CE_ADM_ERR_DTL1_MIN_PDATA_CREDIT_ERR (0x1ULL << 36) +#define CE_ADM_ERR_DTL1_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 37) +#define CE_ADM_ERR_DTL1_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 38) +#define CE_ADM_ERR_DTL1_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 39) +#define CE_ADM_ERR_DTL1_COMP_HD_CRED_MAX_ERR (0x1ULL << 40) +#define CE_ADM_ERR_DTL1_COMP_D_CRED_MAX_ERR (0x1ULL << 41) +#define CE_ADM_ERR_DTL1_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 42) +#define CE_ADM_ERR_DTL1_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 43) +#define CE_ADM_ERR_DTL1_POSTED_HD_CRED_MAX_ERR (0x1ULL << 44) +#define CE_ADM_ERR_DTL1_POSTED_D_CRED_MAX_ERR (0x1ULL << 45) +#define CE_ADM_ERR_DTL2_MIN_PDATA_CREDIT_ERR (0x1ULL << 46) +#define CE_ADM_ERR_DTL2_INF_COMPL_CRED_UPDT_ERR (0x1ULL << 47) +#define CE_ADM_ERR_DTL2_INF_POSTED_CRED_UPDT_ERR (0x1ULL << 48) +#define CE_ADM_ERR_DTL2_INF_NPOSTED_CRED_UPDT_ERR (0x1ULL << 49) +#define CE_ADM_ERR_DTL2_COMP_HD_CRED_MAX_ERR (0x1ULL << 50) +#define CE_ADM_ERR_DTL2_COMP_D_CRED_MAX_ERR (0x1ULL << 51) +#define CE_ADM_ERR_DTL2_NPOSTED_HD_CRED_MAX_ERR (0x1ULL << 52) +#define CE_ADM_ERR_DTL2_NPOSTED_D_CRED_MAX_ERR (0x1ULL << 53) +#define CE_ADM_ERR_DTL2_POSTED_HD_CRED_MAX_ERR (0x1ULL << 54) +#define CE_ADM_ERR_DTL2_POSTED_D_CRED_MAX_ERR (0x1ULL << 55) +#define CE_ADM_ERR_PORT1_PCIE_COR_ERR (0x1ULL << 56) +#define CE_ADM_ERR_PORT1_PCIE_NFAT_ERR (0x1ULL << 57) +#define CE_ADM_ERR_PORT1_PCIE_FAT_ERR (0x1ULL << 58) +#define CE_ADM_ERR_PORT2_PCIE_COR_ERR (0x1ULL << 59) +#define CE_ADM_ERR_PORT2_PCIE_NFAT_ERR (0x1ULL << 60) +#define CE_ADM_ERR_PORT2_PCIE_FAT_ERR (0x1ULL << 61) + +/* ce_adm_ure_ups_buf_barrier_flush register bit masks and shifts */ +#define FLUSH_SEL_PORT1_PIPE0_SHFT 0 +#define FLUSH_SEL_PORT1_PIPE1_SHFT 4 +#define FLUSH_SEL_PORT1_PIPE2_SHFT 8 +#define FLUSH_SEL_PORT1_PIPE3_SHFT 12 +#define FLUSH_SEL_PORT2_PIPE0_SHFT 16 +#define FLUSH_SEL_PORT2_PIPE1_SHFT 20 +#define FLUSH_SEL_PORT2_PIPE2_SHFT 24 +#define FLUSH_SEL_PORT2_PIPE3_SHFT 28 + +/* ce_dre_config1 register bit masks and shifts */ +#define CE_DRE_RO_ENABLE (0x1ULL << 0) +#define CE_DRE_DYN_RO_ENABLE (0x1ULL << 1) +#define CE_DRE_SUP_CONFIG_COMP_ERROR (0x1ULL << 2) +#define CE_DRE_SUP_IO_COMP_ERROR (0x1ULL << 3) +#define CE_DRE_ADDR_MODE_SHFT 4 + +/* ce_dre_config_req_status register bit masks */ +#define CE_DRE_LAST_CONFIG_COMPLETION (0x7ULL << 0) +#define CE_DRE_DOWNSTREAM_CONFIG_ERROR (0x1ULL << 3) +#define CE_DRE_CONFIG_COMPLETION_VALID (0x1ULL << 4) +#define CE_DRE_CONFIG_REQUEST_ACTIVE (0x1ULL << 5) + +/* ce_ure_control register bit masks & shifts */ +#define CE_URE_RD_MRG_ENABLE (0x1ULL << 0) +#define CE_URE_WRT_MRG_ENABLE1 (0x1ULL << 4) +#define CE_URE_WRT_MRG_ENABLE2 (0x1ULL << 5) +#define CE_URE_RSPQ_BYPASS_DISABLE (0x1ULL << 24) +#define CE_URE_UPS_DAT1_PAR_DISABLE (0x1ULL << 32) +#define CE_URE_UPS_HDR1_PAR_DISABLE (0x1ULL << 33) +#define CE_URE_UPS_DAT2_PAR_DISABLE (0x1ULL << 34) +#define CE_URE_UPS_HDR2_PAR_DISABLE (0x1ULL << 35) +#define CE_URE_ATE_PAR_DISABLE (0x1ULL << 36) +#define CE_URE_RCI_PAR_DISABLE (0x1ULL << 37) +#define CE_URE_RSPQ_PAR_DISABLE (0x1ULL << 38) +#define CE_URE_DNS_DAT_PAR_DISABLE (0x1ULL << 39) +#define CE_URE_DNS_HDR_PAR_DISABLE (0x1ULL << 40) +#define CE_URE_MALFORM_DISABLE (0x1ULL << 44) +#define CE_URE_UNSUP_DISABLE (0x1ULL << 45) + +/* ce_ure_page_map register bit masks & shifts */ +#define CE_URE_ATE3240_ENABLE (0x1ULL << 0) +#define CE_URE_ATE40_ENABLE (0x1ULL << 1) +#define CE_URE_PAGESIZE_SHFT 4 +#define CE_URE_PAGESIZE_MASK (0x7ULL << CE_URE_PAGESIZE_SHFT) +#define CE_URE_4K_PAGESIZE (0x0ULL << CE_URE_PAGESIZE_SHFT) +#define CE_URE_16K_PAGESIZE (0x1ULL << CE_URE_PAGESIZE_SHFT) +#define CE_URE_64K_PAGESIZE (0x2ULL << CE_URE_PAGESIZE_SHFT) +#define CE_URE_128K_PAGESIZE (0x3ULL << CE_URE_PAGESIZE_SHFT) +#define CE_URE_256K_PAGESIZE (0x4ULL << CE_URE_PAGESIZE_SHFT) + +/* ce_ure_pipe_sel register bit masks & shifts */ +#define PKT_TRAFIC_SHRT 16 +#define BUS_SRC_ID_SHFT 8 +#define DEV_SRC_ID_SHFT 3 +#define FNC_SRC_ID_SHFT 0 +#define CE_URE_TC_MASK (0x07ULL << PKT_TRAFIC_SHRT) +#define CE_URE_BUS_MASK (0xFFULL << BUS_SRC_ID_SHFT) +#define CE_URE_DEV_MASK (0x1FULL << DEV_SRC_ID_SHFT) +#define CE_URE_FNC_MASK (0x07ULL << FNC_SRC_ID_SHFT) +#define CE_URE_PIPE_BUS(b) (((uint64_t)(b) << BUS_SRC_ID_SHFT) & \ + CE_URE_BUS_MASK) +#define CE_URE_PIPE_DEV(d) (((uint64_t)(d) << DEV_SRC_ID_SHFT) & \ + CE_URE_DEV_MASK) +#define CE_URE_PIPE_FNC(f) (((uint64_t)(f) << FNC_SRC_ID_SHFT) & \ + CE_URE_FNC_MASK) + +#define CE_URE_SEL1_SHFT 0 +#define CE_URE_SEL2_SHFT 20 +#define CE_URE_SEL3_SHFT 40 +#define CE_URE_SEL1_MASK (0x7FFFFULL << CE_URE_SEL1_SHFT) +#define CE_URE_SEL2_MASK (0x7FFFFULL << CE_URE_SEL2_SHFT) +#define CE_URE_SEL3_MASK (0x7FFFFULL << CE_URE_SEL3_SHFT) + + +/* ce_ure_pipe_mask register bit masks & shifts */ +#define CE_URE_MASK1_SHFT 0 +#define CE_URE_MASK2_SHFT 20 +#define CE_URE_MASK3_SHFT 40 +#define CE_URE_MASK1_MASK (0x7FFFFULL << CE_URE_MASK1_SHFT) +#define CE_URE_MASK2_MASK (0x7FFFFULL << CE_URE_MASK2_SHFT) +#define CE_URE_MASK3_MASK (0x7FFFFULL << CE_URE_MASK3_SHFT) + + +/* ce_ure_pcie_control1 register bit masks & shifts */ +#define CE_URE_SI (0x1ULL << 0) +#define CE_URE_ELAL_SHFT 4 +#define CE_URE_ELAL_MASK (0x7ULL << CE_URE_ELAL_SHFT) +#define CE_URE_ELAL1_SHFT 8 +#define CE_URE_ELAL1_MASK (0x7ULL << CE_URE_ELAL1_SHFT) +#define CE_URE_SCC (0x1ULL << 12) +#define CE_URE_PN1_SHFT 16 +#define CE_URE_PN1_MASK (0xFFULL << CE_URE_PN1_SHFT) +#define CE_URE_PN2_SHFT 24 +#define CE_URE_PN2_MASK (0xFFULL << CE_URE_PN2_SHFT) +#define CE_URE_PN1_SET(n) (((uint64_t)(n) << CE_URE_PN1_SHFT) & \ + CE_URE_PN1_MASK) +#define CE_URE_PN2_SET(n) (((uint64_t)(n) << CE_URE_PN2_SHFT) & \ + CE_URE_PN2_MASK) + +/* ce_ure_pcie_control2 register bit masks & shifts */ +#define CE_URE_ABP (0x1ULL << 0) +#define CE_URE_PCP (0x1ULL << 1) +#define CE_URE_MSP (0x1ULL << 2) +#define CE_URE_AIP (0x1ULL << 3) +#define CE_URE_PIP (0x1ULL << 4) +#define CE_URE_HPS (0x1ULL << 5) +#define CE_URE_HPC (0x1ULL << 6) +#define CE_URE_SPLV_SHFT 7 +#define CE_URE_SPLV_MASK (0xFFULL << CE_URE_SPLV_SHFT) +#define CE_URE_SPLS_SHFT 15 +#define CE_URE_SPLS_MASK (0x3ULL << CE_URE_SPLS_SHFT) +#define CE_URE_PSN1_SHFT 19 +#define CE_URE_PSN1_MASK (0x1FFFULL << CE_URE_PSN1_SHFT) +#define CE_URE_PSN2_SHFT 32 +#define CE_URE_PSN2_MASK (0x1FFFULL << CE_URE_PSN2_SHFT) +#define CE_URE_PSN1_SET(n) (((uint64_t)(n) << CE_URE_PSN1_SHFT) & \ + CE_URE_PSN1_MASK) +#define CE_URE_PSN2_SET(n) (((uint64_t)(n) << CE_URE_PSN2_SHFT) & \ + CE_URE_PSN2_MASK) + +/* + * PIO address space ranges for CE + */ + +/* Local CE Registers Space */ +#define CE_PIO_MMR 0x00000000 +#define CE_PIO_MMR_LEN 0x04000000 + +/* PCI Compatible Config Space */ +#define CE_PIO_CONFIG_SPACE 0x04000000 +#define CE_PIO_CONFIG_SPACE_LEN 0x04000000 + +/* PCI I/O Space Alias */ +#define CE_PIO_IO_SPACE_ALIAS 0x08000000 +#define CE_PIO_IO_SPACE_ALIAS_LEN 0x08000000 + +/* PCI Enhanced Config Space */ +#define CE_PIO_E_CONFIG_SPACE 0x10000000 +#define CE_PIO_E_CONFIG_SPACE_LEN 0x10000000 + +/* PCI I/O Space */ +#define CE_PIO_IO_SPACE 0x100000000 +#define CE_PIO_IO_SPACE_LEN 0x100000000 + +/* PCI MEM Space */ +#define CE_PIO_MEM_SPACE 0x200000000 +#define CE_PIO_MEM_SPACE_LEN TIO_HWIN_SIZE + + +/* + * CE PCI Enhanced Config Space shifts & masks + */ +#define CE_E_CONFIG_BUS_SHFT 20 +#define CE_E_CONFIG_BUS_MASK (0xFF << CE_E_CONFIG_BUS_SHFT) +#define CE_E_CONFIG_DEVICE_SHFT 15 +#define CE_E_CONFIG_DEVICE_MASK (0x1F << CE_E_CONFIG_DEVICE_SHFT) +#define CE_E_CONFIG_FUNC_SHFT 12 +#define CE_E_CONFIG_FUNC_MASK (0x7 << CE_E_CONFIG_FUNC_SHFT) + +#endif /* __ASM_IA64_SN_TIOCE_H__ */ diff --git a/include/asm-ia64/sn/tioce_provider.h b/include/asm-ia64/sn/tioce_provider.h new file mode 100644 index 00000000000..7f63dec0a79 --- /dev/null +++ b/include/asm-ia64/sn/tioce_provider.h @@ -0,0 +1,66 @@ +/************************************************************************** + * Copyright (C) 2005, Silicon Graphics, Inc. * + * * + * These coded instructions, statements, and computer programs contain * + * unpublished proprietary information of Silicon Graphics, Inc., and * + * are protected by Federal copyright law. They may not be disclosed * + * to third parties or copied or duplicated in any form, in whole or * + * in part, without the prior written consent of Silicon Graphics, Inc. * + * * + **************************************************************************/ + +#ifndef _ASM_IA64_SN_CE_PROVIDER_H +#define _ASM_IA64_SN_CE_PROVIDER_H + +#include <asm/sn/pcibus_provider_defs.h> +#include <asm/sn/tioce.h> + +/* + * Common TIOCE structure shared between the prom and kernel + * + * DO NOT CHANGE THIS STRUCT WITHOUT MAKING CORRESPONDING CHANGES TO THE + * PROM VERSION. + */ +struct tioce_common { + struct pcibus_bussoft ce_pcibus; /* common pciio header */ + + uint32_t ce_rev; + uint64_t ce_kernel_private; + uint64_t ce_prom_private; +}; + +struct tioce_kernel { + struct tioce_common *ce_common; + spinlock_t ce_lock; + struct list_head ce_dmamap_list; + + uint64_t ce_ate40_shadow[TIOCE_NUM_M40_ATES]; + uint64_t ce_ate3240_shadow[TIOCE_NUM_M3240_ATES]; + uint32_t ce_ate3240_pagesize; + + uint8_t ce_port1_secondary; + + /* per-port resources */ + struct { + int dirmap_refcnt; + uint64_t dirmap_shadow; + } ce_port[TIOCE_NUM_PORTS]; +}; + +struct tioce_dmamap { + struct list_head ce_dmamap_list; /* headed by tioce_kernel */ + uint32_t refcnt; + + uint64_t nbytes; /* # bytes mapped */ + + uint64_t ct_start; /* coretalk start address */ + uint64_t pci_start; /* bus start address */ + + uint64_t *ate_hw; /* hw ptr of first ate in map */ + uint64_t *ate_shadow; /* shadow ptr of firat ate */ + uint16_t ate_count; /* # ate's in the map */ +}; + +extern int tioce_init_provider(void); + +#endif /* __ASM_IA64_SN_CE_PROVIDER_H */ diff --git a/include/asm-ia64/spinlock.h b/include/asm-ia64/spinlock.h index 909936f2551..d2430aa0d49 100644 --- a/include/asm-ia64/spinlock.h +++ b/include/asm-ia64/spinlock.h @@ -93,7 +93,15 @@ _raw_spin_lock_flags (spinlock_t *lock, unsigned long flags) # endif /* CONFIG_MCKINLEY */ #endif } + #define _raw_spin_lock(lock) _raw_spin_lock_flags(lock, 0) + +/* Unlock by doing an ordered store and releasing the cacheline with nta */ +static inline void _raw_spin_unlock(spinlock_t *x) { + barrier(); + asm volatile ("st4.rel.nta [%0] = r0\n\t" :: "r"(x)); +} + #else /* !ASM_SUPPORTED */ #define _raw_spin_lock_flags(lock, flags) _raw_spin_lock(lock) # define _raw_spin_lock(x) \ @@ -109,16 +117,16 @@ do { \ } while (ia64_spinlock_val); \ } \ } while (0) +#define _raw_spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) #endif /* !ASM_SUPPORTED */ #define spin_is_locked(x) ((x)->lock != 0) -#define _raw_spin_unlock(x) do { barrier(); ((spinlock_t *) x)->lock = 0; } while (0) #define _raw_spin_trylock(x) (cmpxchg_acq(&(x)->lock, 0, 1) == 0) #define spin_unlock_wait(x) do { barrier(); } while ((x)->lock) typedef struct { - volatile unsigned int read_counter : 31; - volatile unsigned int write_lock : 1; + volatile unsigned int read_counter : 24; + volatile unsigned int write_lock : 8; #ifdef CONFIG_PREEMPT unsigned int break_lock; #endif @@ -174,6 +182,13 @@ do { \ (result == 0); \ }) +static inline void _raw_write_unlock(rwlock_t *x) +{ + u8 *y = (u8 *)x; + barrier(); + asm volatile ("st1.rel.nta [%0] = r0\n\t" :: "r"(y+3) : "memory" ); +} + #else /* !ASM_SUPPORTED */ #define _raw_write_lock(l) \ @@ -195,14 +210,14 @@ do { \ (ia64_val == 0); \ }) +static inline void _raw_write_unlock(rwlock_t *x) +{ + barrier(); + x->write_lock = 0; +} + #endif /* !ASM_SUPPORTED */ #define _raw_read_trylock(lock) generic_raw_read_trylock(lock) -#define _raw_write_unlock(x) \ -({ \ - smp_mb__before_clear_bit(); /* need barrier before releasing lock... */ \ - clear_bit(31, (x)); \ -}) - #endif /* _ASM_IA64_SPINLOCK_H */ diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h index cd2cf76b2db..33256db4a7c 100644 --- a/include/asm-ia64/system.h +++ b/include/asm-ia64/system.h @@ -19,12 +19,13 @@ #include <asm/pal.h> #include <asm/percpu.h> -#define GATE_ADDR __IA64_UL_CONST(0xa000000000000000) +#define GATE_ADDR RGN_BASE(RGN_GATE) + /* * 0xa000000000000000+2*PERCPU_PAGE_SIZE * - 0xa000000000000000+3*PERCPU_PAGE_SIZE remain unmapped (guard page) */ -#define KERNEL_START __IA64_UL_CONST(0xa000000100000000) +#define KERNEL_START (GATE_ADDR+0x100000000) #define PERCPU_ADDR (-PERCPU_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/include/asm-m68knommu/page.h b/include/asm-m68knommu/page.h index 05e03df0ec2..ff6a9265ed1 100644 --- a/include/asm-m68knommu/page.h +++ b/include/asm-m68knommu/page.h @@ -73,8 +73,8 @@ extern unsigned long memory_end; #ifndef __ASSEMBLY__ -#define __pa(vaddr) virt_to_phys((void *)vaddr) -#define __va(paddr) phys_to_virt((unsigned long)paddr) +#define __pa(vaddr) virt_to_phys((void *)(vaddr)) +#define __va(paddr) phys_to_virt((unsigned long)(paddr)) #define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT) #define pfn_to_virt(pfn) __va((pfn) << PAGE_SHIFT) @@ -84,6 +84,7 @@ extern unsigned long memory_end; #define pfn_to_page(pfn) virt_to_page(pfn_to_virt(pfn)) #define page_to_pfn(page) virt_to_pfn(page_to_virt(page)) +#define pfn_valid(pfn) ((pfn) < max_mapnr) #define virt_addr_valid(kaddr) (((void *)(kaddr) >= (void *)PAGE_OFFSET) && \ ((void *)(kaddr) < (void *)memory_end)) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index e8904c0da68..86980c68234 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -8,7 +8,7 @@ * Basic handling of the devices is done in drivers/base/cpu.c * and system devices are handled in drivers/base/sys.c. * - * CPUs are exported via driverfs in the class/cpu/devices/ + * CPUs are exported via sysfs in the class/cpu/devices/ * directory. * * Per-cpu interfaces can be implemented using a struct device_interface. diff --git a/include/linux/serial.h b/include/linux/serial.h index 9f2d85284d0..12cd9cf65e8 100644 --- a/include/linux/serial.h +++ b/include/linux/serial.h @@ -176,10 +176,6 @@ struct serial_icounter_struct { #ifdef __KERNEL__ #include <linux/compiler.h> -/* Export to allow PCMCIA to use this - Dave Hinds */ -extern int __deprecated register_serial(struct serial_struct *req); -extern void __deprecated unregister_serial(int line); - /* Allow architectures to override entries in serial8250_ports[] at run time: */ struct uart_port; /* forward declaration */ extern int early_serial_setup(struct uart_port *port); diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 3e3c1fa35b0..d8a023d804d 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -14,6 +14,9 @@ #include <linux/serial_core.h> #include <linux/device.h> +/* + * This is the platform device platform_data structure + */ struct plat_serial8250_port { unsigned long iobase; /* io base address */ void __iomem *membase; /* ioremap cookie or NULL */ @@ -26,4 +29,17 @@ struct plat_serial8250_port { unsigned int flags; /* UPF_* flags */ }; +/* + * This should be used by drivers which want to register + * their own 8250 ports without registering their own + * platform device. Using these will make your driver + * dependent on the 8250 driver. + */ +struct uart_port; + +int serial8250_register_port(struct uart_port *); +void serial8250_unregister_port(int line); +void serial8250_suspend_port(int line); +void serial8250_resume_port(int line); + #endif diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index f6fca8f2f3c..cf0f64ea2bc 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -142,8 +142,8 @@ struct uart_ops { unsigned int (*tx_empty)(struct uart_port *); void (*set_mctrl)(struct uart_port *, unsigned int mctrl); unsigned int (*get_mctrl)(struct uart_port *); - void (*stop_tx)(struct uart_port *, unsigned int tty_stop); - void (*start_tx)(struct uart_port *, unsigned int tty_start); + void (*stop_tx)(struct uart_port *); + void (*start_tx)(struct uart_port *); void (*send_xchar)(struct uart_port *, char ch); void (*stop_rx)(struct uart_port *); void (*enable_ms)(struct uart_port *); @@ -360,8 +360,6 @@ struct tty_driver *uart_console_device(struct console *co, int *index); */ int uart_register_driver(struct uart_driver *uart); void uart_unregister_driver(struct uart_driver *uart); -void __deprecated uart_unregister_port(struct uart_driver *reg, int line); -int __deprecated uart_register_port(struct uart_driver *reg, struct uart_port *port); int uart_add_one_port(struct uart_driver *reg, struct uart_port *port); int uart_remove_one_port(struct uart_driver *reg, struct uart_port *port); int uart_match_port(struct uart_port *port1, struct uart_port *port2); @@ -468,13 +466,13 @@ uart_handle_cts_change(struct uart_port *port, unsigned int status) if (tty->hw_stopped) { if (status) { tty->hw_stopped = 0; - port->ops->start_tx(port, 0); + port->ops->start_tx(port); uart_write_wakeup(port); } } else { if (!status) { tty->hw_stopped = 1; - port->ops->stop_tx(port, 0); + port->ops->stop_tx(port); } } } diff --git a/init/do_mounts.c b/init/do_mounts.c index 4e11a9aaf14..b27c1106440 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -127,10 +127,10 @@ fail: * used when disk name of partitioned disk ends on a digit. * * If name doesn't have fall into the categories above, we return 0. - * Driverfs is used to check if something is a disk name - it has + * Sysfs is used to check if something is a disk name - it has * all known disks under bus/block/devices. If the disk name - * contains slashes, name of driverfs node has them replaced with - * bangs. try_name() does the actual checks, assuming that driverfs + * contains slashes, name of sysfs node has them replaced with + * bangs. try_name() does the actual checks, assuming that sysfs * is mounted on rootfs /sys. */ diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index fe1a73ce6cf..ded6c63f11e 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -3,7 +3,7 @@ * * Userland/kernel interface for rpcauth_gss. * Code shamelessly plagiarized from fs/nfsd/nfsctl.c - * and fs/driverfs/inode.c + * and fs/sysfs/inode.c * * Copyright (c) 2002, Trond Myklebust <trond.myklebust@fys.uio.no> * |