diff options
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/chrp_pci.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/chrp_setup.c | 8 | ||||
-rw-r--r-- | arch/ppc/kernel/gemini_setup.c | 13 | ||||
-rw-r--r-- | arch/ppc/kernel/irq.c | 7 | ||||
-rw-r--r-- | arch/ppc/kernel/local_irq.h | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/m8xx_setup.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/mbx_pci.c | 269 | ||||
-rw-r--r-- | arch/ppc/kernel/mbx_setup.c | 486 | ||||
-rw-r--r-- | arch/ppc/kernel/open_pic.c | 49 | ||||
-rw-r--r-- | arch/ppc/kernel/open_pic.h | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/pci.c | 16 | ||||
-rw-r--r-- | arch/ppc/kernel/pmac_pci.c | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/pmac_pic.c | 8 | ||||
-rw-r--r-- | arch/ppc/kernel/pmac_setup.c | 24 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 3 | ||||
-rw-r--r-- | arch/ppc/kernel/prep_pci.c | 5 | ||||
-rw-r--r-- | arch/ppc/kernel/prep_setup.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/process.c | 9 | ||||
-rw-r--r-- | arch/ppc/kernel/smp.c | 174 |
19 files changed, 173 insertions, 914 deletions
diff --git a/arch/ppc/kernel/chrp_pci.c b/arch/ppc/kernel/chrp_pci.c index 88686acc4..b93bc45f7 100644 --- a/arch/ppc/kernel/chrp_pci.c +++ b/arch/ppc/kernel/chrp_pci.c @@ -282,8 +282,7 @@ chrp_pcibios_fixup(void) } /* PCI interrupts are controlled by the OpenPIC */ - for( dev=pci_devices ; dev; dev=dev->next ) - { + pci_for_each_dev(dev) { if ( dev->irq ) dev->irq = openpic_to_irq( dev->irq ); /* these need to be absolute addrs for OF and Matrox FB -- Cort */ diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index 938cea36d..e76aa8dd9 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -249,7 +249,7 @@ chrp_setup_arch(void) else #endif ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */ - +sprintf(cmd_line, "console=ttyS0,9600 console=tty0"); printk("Boot arguments: %s\n", cmd_line); request_region(0x20,0x20,"pic1"); @@ -391,7 +391,7 @@ void chrp_post_irq(int irq) * openpic irq. So we just check to make sure the controller * is an openpic and if it is then eoi * - * We do it this way since our irq_desc[irq].ctl can change + * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ if ( irq >= open_pic.irq_offset) @@ -413,10 +413,10 @@ void __init chrp_init_IRQ(void) } open_pic.irq_offset = 16; for ( i = 16 ; i < NR_IRQS ; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_init(); #ifdef CONFIG_XMON request_irq(openpic_to_irq(HYDRA_INT_ADB_NMI), diff --git a/arch/ppc/kernel/gemini_setup.c b/arch/ppc/kernel/gemini_setup.c index 57ea34687..fadddda8b 100644 --- a/arch/ppc/kernel/gemini_setup.c +++ b/arch/ppc/kernel/gemini_setup.c @@ -332,10 +332,17 @@ void __init gemini_init_IRQ(void) /* gemini has no 8259 */ open_pic.irq_offset = 0; for( i=0; i < NR_IRQS; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); #ifdef __SMP__ - request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, 0, "IPI0", 0); + request_irq(OPENPIC_VEC_IPI, openpic_ipi_action, + 0, "IPI0", 0); + request_irq(OPENPIC_VEC_IPI+1, openpic_ipi_action, + 0, "IPI1 (invalidate TLB)", 0); + request_irq(OPENPIC_VEC_IPI+2, openpic_ipi_action, + 0, "IPI2 (stop CPU)", 0); + request_irq(OPENPIC_VEC_IPI+3, openpic_ipi_action, + 0, "IPI3 (reschedule)", 0); #endif /* __SMP__ */ } @@ -505,7 +512,7 @@ void gemini_post_irq(int irq) * openpic irq. So we just check to make sure the controller * is an openpic and if it is then eoi * - * We do it this way since our irq_desc[irq].ctl can change + * We do it this way since our irq_desc[irq].handler can change * with RTL and no longer be open_pic -- Cort */ if ( irq >= open_pic.irq_offset) diff --git a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c index 4427e801f..a09d6ad98 100644 --- a/arch/ppc/kernel/irq.c +++ b/arch/ppc/kernel/irq.c @@ -44,6 +44,7 @@ #include <linux/openpic.h> #include <linux/pci.h> #include <linux/delay.h> +#include <linux/irq.h> #include <asm/bitops.h> #include <asm/hydra.h> @@ -71,7 +72,7 @@ volatile unsigned char *chrp_int_ack_special; #define NR_MASK_WORDS ((NR_IRQS + 31) / 32) -struct irqdesc irq_desc[NR_IRQS] = {{0, 0}, }; +irq_desc_t irq_desc[NR_IRQS]; int ppc_spurious_interrupts = 0; unsigned int ppc_local_bh_count[NR_CPUS]; unsigned int ppc_local_irq_count[NR_CPUS]; @@ -244,8 +245,8 @@ int get_irq_list(char *buf) #else len += sprintf(buf+len, "%10u ", kstat_irqs(i)); #endif /* __SMP__ */ - if ( irq_desc[i].ctl ) - len += sprintf(buf+len, " %s ", irq_desc[i].ctl->typename ); + if ( irq_desc[i].handler ) + len += sprintf(buf+len, " %s ", irq_desc[i].handler->typename ); else len += sprintf(buf+len, " None "); len += sprintf(buf+len, " %s",action->name); diff --git a/arch/ppc/kernel/local_irq.h b/arch/ppc/kernel/local_irq.h index 8e9fe6df6..602192013 100644 --- a/arch/ppc/kernel/local_irq.h +++ b/arch/ppc/kernel/local_irq.h @@ -4,7 +4,7 @@ #include <linux/kernel_stat.h> #include <linux/interrupt.h> -#include <asm/irq_control.h> +#include <linux/irq.h> void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq); diff --git a/arch/ppc/kernel/m8xx_setup.c b/arch/ppc/kernel/m8xx_setup.c index 4d510612b..36e886d0c 100644 --- a/arch/ppc/kernel/m8xx_setup.c +++ b/arch/ppc/kernel/m8xx_setup.c @@ -278,7 +278,7 @@ m8xx_init_IRQ(void) ppc8xx_pic.irq_offset = 0; for ( i = 0 ; i < NR_SIU_INTS ; i++ ) - irq_desc[i].ctl = &ppc8xx_pic; + irq_desc[i].handler = &ppc8xx_pic; /* We could probably incorporate the CPM into the multilevel * interrupt structure. @@ -288,7 +288,7 @@ m8xx_init_IRQ(void) #if defined(CONFIG_PCI) for ( i = NR_SIU_INTS ; i < (NR_SIU_INTS + NR_8259_INTS) ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_pic.irq_offset = NR_SIU_INTS; i8259_init(); request_8xxirq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL); diff --git a/arch/ppc/kernel/mbx_pci.c b/arch/ppc/kernel/mbx_pci.c deleted file mode 100644 index d7473e128..000000000 --- a/arch/ppc/kernel/mbx_pci.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * MBX pci routines. - * The MBX uses the QSpan PCI bridge. The config address register - * is located 0x500 from the base of the bridge control/status registers. - * The data register is located at 0x504. - * This is a two step operation. First, the address register is written, - * then the data register is read/written as required. - * I don't know what to do about interrupts (yet). - */ - -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/bios32.h> -#include <linux/delay.h> -#include <linux/string.h> -#include <linux/init.h> - -#include <asm/io.h> -#include <asm/mbx.h> - - -/* - * This blows......The MBX uses the Tundra QSpan PCI bridge. When - * reading the configuration space, if something does not respond - * the bus times out and we get a machine check interrupt. So, the - * good ol' exception tables come to mind to trap it and return some - * value. - * - * On an error we just return a -1, since that is what the caller wants - * returned if nothing is present. I copied this from __get_user_asm, - * with the only difference of returning -1 instead of EFAULT. - * There is an associated hack in the machine check trap code. - * - * The QSPAN is also a big endian device, that is it makes the PCI - * look big endian to us. This presents a problem for the Linux PCI - * functions, which assume little endian. For example, we see the - * first 32-bit word like this: - * ------------------------ - * | Device ID | Vendor ID | - * ------------------------ - * If we read/write as a double word, that's OK. But in our world, - * when read as a word, device ID is at location 0, not location 2 as - * the little endian PCI would believe. We have to switch bits in - * the PCI addresses given to us to get the data to/from the correct - * byte lanes. - * - * The QSPAN only supports 4 bits of "slot" in the dev_fn instead of 5. - * It always forces the MS bit to zero. Therefore, dev_fn values - * greater than 128 are returned as "no device found" errors. - * - * The QSPAN can only perform long word (32-bit) configuration cycles. - * The "offset" must have the two LS bits set to zero. Read operations - * require we read the entire word and then sort out what should be - * returned. Write operations other than long word require that we - * read the long word, update the proper word or byte, then write the - * entire long word back. - * - * PCI Bridge hack. We assume (correctly) that bus 0 is the primary - * PCI bus from the QSPAN. If we are called with a bus number other - * than zero, we create a Type 1 configuration access that a downstream - * PCI bridge will interpret. - */ - -#define __get_mbx_pci_config(x, addr, op) \ - __asm__ __volatile__( \ - "1: "op" %0,0(%1)\n" \ - " eieio\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3: li %0,-1\n" \ - " b 2b\n" \ - ".section __ex_table,\"a\"\n" \ - " .align 2\n" \ - " .long 1b,3b\n" \ - ".text" \ - : "=r"(x) : "r"(addr)) - -#define QS_CONFIG_ADDR ((volatile uint *)(PCI_CSR_ADDR + 0x500)) -#define QS_CONFIG_DATA ((volatile uint *)(PCI_CSR_ADDR + 0x504)) - -#define mk_config_addr(bus, dev, offset) \ - (((bus)<<16) | ((dev)<<8) | (offset & 0xfc)) - -#define mk_config_type1(bus, dev, offset) \ - mk_config_addr(bus, dev, offset) | 1; - -int mbx_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char *val) -{ - uint temp; - u_char *cp; - - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz"); - - offset ^= 0x03; - cp = ((u_char *)&temp) + (offset & 0x03); - *val = *cp; - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short *val) -{ - uint temp; - ushort *sp; - - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(temp, QS_CONFIG_DATA, "lwz"); - offset ^= 0x02; - - sp = ((ushort *)&temp) + ((offset >> 1) & 1); - *val = *sp; - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int *val) -{ - if ((bus > 7) || (dev_fn > 127)) { - *val = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - __get_mbx_pci_config(*val, QS_CONFIG_DATA, "lwz"); - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned char val) -{ - uint temp; - u_char *cp; - - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp); - - offset ^= 0x03; - cp = ((u_char *)&temp) + (offset & 0x03); - *cp = val; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *QS_CONFIG_DATA = temp; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned short val) -{ - uint temp; - ushort *sp; - - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - mbx_pcibios_read_config_dword(bus, dev_fn, offset, &temp); - - offset ^= 0x02; - sp = ((ushort *)&temp) + ((offset >> 1) & 1); - *sp = val; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *QS_CONFIG_DATA = temp; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn, - unsigned char offset, unsigned int val) -{ - if ((bus > 7) || (dev_fn > 127)) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (bus == 0) - *QS_CONFIG_ADDR = mk_config_addr(bus, dev_fn, offset); - else - *QS_CONFIG_ADDR = mk_config_type1(bus, dev_fn, offset); - *(unsigned int *)QS_CONFIG_DATA = val; - - return PCIBIOS_SUCCESSFUL; -} - -int mbx_pcibios_find_device(unsigned short vendor, unsigned short dev_id, - unsigned short index, unsigned char *bus_ptr, - unsigned char *dev_fn_ptr) -{ - int num, devfn; - unsigned int x, vendev; - - if (vendor == 0xffff) - return PCIBIOS_BAD_VENDOR_ID; - vendev = (dev_id << 16) + vendor; - num = 0; - for (devfn = 0; devfn < 32; devfn++) { - mbx_pcibios_read_config_dword(0, devfn<<3, PCI_VENDOR_ID, &x); - if (x == vendev) { - if (index == num) { - *bus_ptr = 0; - *dev_fn_ptr = devfn<<3; - return PCIBIOS_SUCCESSFUL; - } - ++num; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} - -int mbx_pcibios_find_class(unsigned int class_code, unsigned short index, - unsigned char *bus_ptr, unsigned char *dev_fn_ptr) -{ - int devnr, x, num; - - num = 0; - for (devnr = 0; devnr < 32; devnr++) { - mbx_pcibios_read_config_dword(0, devnr<<3, PCI_CLASS_REVISION, &x); - if ((x>>8) == class_code) { - if (index == num) { - *bus_ptr = 0; - *dev_fn_ptr = devnr<<3; - return PCIBIOS_SUCCESSFUL; - } - ++num; - } - } - return PCIBIOS_DEVICE_NOT_FOUND; -} - -void __init -mbx_pcibios_fixup(void) -{ - /* Nothing to do here? */ -} - -void __init -mbx_setup_pci_ptrs(void) -{ - set_config_access_method(mbx); - - ppc_md.pcibios_fixup = mbx_pcibios_fixup; -} - diff --git a/arch/ppc/kernel/mbx_setup.c b/arch/ppc/kernel/mbx_setup.c deleted file mode 100644 index f6487783b..000000000 --- a/arch/ppc/kernel/mbx_setup.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * $Id: mbx_setup.c,v 1.12 1999/08/31 06:53:56 davem Exp $ - * - * linux/arch/ppc/kernel/setup.c - * - * Copyright (C) 1995 Linus Torvalds - * Adapted from 'alpha' version by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu) - * Modified for MBX using prep/chrp/pmac functions by Dan (dmalek@jlc.net) - */ - -/* - * bootup setup stuff.. - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/malloc.h> -#include <linux/user.h> -#include <linux/a.out.h> -#include <linux/tty.h> -#include <linux/major.h> -#include <linux/interrupt.h> -#include <linux/reboot.h> -#include <linux/init.h> -#include <linux/blk.h> -#include <linux/ide.h> -#include <linux/ioport.h> - -#include <asm/mmu.h> -#include <asm/processor.h> -#include <asm/residual.h> -#include <asm/io.h> -#include <asm/pgtable.h> -#include <asm/mbx.h> -#include <asm/machdep.h> - -#include "time.h" -#include "local_irq.h" - -static int mbx_set_rtc_time(unsigned long time); -unsigned long mbx_get_rtc_time(void); -void mbx_calibrate_decr(void); - -extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int mackbd_getkeycode(unsigned int scancode); -extern int mackbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char mackbd_unexpected_up(unsigned char keycode); -extern void mackbd_leds(unsigned char leds); -extern void mackbd_init_hw(void); - -extern unsigned long loops_per_sec; - -unsigned long empty_zero_page[1024]; - -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - -extern char saved_command_line[256]; - -extern unsigned long find_available_memory(void); -extern void m8xx_cpm_reset(uint); - -void __init adbdev_init(void) -{ -} - -void __init -mbx_setup_arch(void) -{ - int cpm_page; - extern char cmd_line[]; - - cpm_page = (int) alloc_bootmem_pages(PAGE_SIZE); - - sprintf(cmd_line, -"%s root=/dev/nfs nfsroot=/sys/mbxroot", - cmd_line); - printk("Boot arguments: %s\n", cmd_line); - - /* Reset the Communication Processor Module. - */ - m8xx_cpm_reset(cpm_page); - -#ifdef notdef - ROOT_DEV = to_kdev_t(0x0301); /* hda1 */ -#endif - -#ifdef CONFIG_BLK_DEV_INITRD -#if 0 - ROOT_DEV = to_kdev_t(0x0200); /* floppy */ - rd_prompt = 1; - rd_doload = 1; - rd_image_start = 0; -#endif -#if 0 /* XXX this may need to be updated for the new bootmem stuff, - or possibly just deleted (see set_phys_avail() in init.c). - - paulus. */ - /* initrd_start and size are setup by boot/head.S and kernel/head.S */ - if ( initrd_start ) - { - if (initrd_end > *memory_end_p) - { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end,*memory_end_p); - initrd_start = 0; - } - } -#endif -#endif - -#ifdef notdef - request_region(0x20,0x20,"pic1"); - request_region(0xa0,0x20,"pic2"); - request_region(0x00,0x20,"dma1"); - request_region(0x40,0x20,"timer"); - request_region(0x80,0x10,"dma page reg"); - request_region(0xc0,0x20,"dma2"); -#endif -} - -void -abort(void) -{ -#ifdef CONFIG_XMON - extern void xmon(void *); - xmon(0); -#endif - machine_restart(NULL); -} - -/* The decrementer counts at the system (internal) clock frequency divided by - * sixteen, or external oscillator divided by four. Currently, we only - * support the MBX, which is system clock divided by sixteen. - */ -void __init mbx_calibrate_decr(void) -{ - bd_t *binfo = (bd_t *)&res; - int freq, fp, divisor; - - if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0) - printk("WARNING: Wrong decrementer source clock.\n"); - - /* The manual says the frequency is in Hz, but it is really - * as MHz. The value 'fp' is the number of decrementer ticks - * per second. - */ - fp = (binfo->bi_intfreq * 1000000) / 16; - freq = fp*60; /* try to make freq/1e6 an integer */ - divisor = 60; - printk("time_init: decrementer frequency = %d/%d\n", freq, divisor); - decrementer_count = freq / HZ / divisor; - count_period_num = divisor; - count_period_den = freq / 1000000; -} - -/* A place holder for time base interrupts, if they are ever enabled. -*/ -void timebase_interrupt(int irq, void * dev, struct pt_regs * regs) -{ - printk("timebase_interrupt()\n"); -} - -/* The RTC on the MPC8xx is an internal register. - * We want to protect this during power down, so we need to unlock, - * modify, and re-lock. - */ -static int -mbx_set_rtc_time(unsigned long time) -{ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY; - return(0); -} - -unsigned long __init mbx_get_rtc_time(void) -{ - /* First, unlock all of the registers we are going to modify. - * To protect them from corruption during power down, registers - * that are maintained by keep alive power are "locked". To - * modify these registers we have to write the key value to - * the key location associated with the register. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY; - ((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY; - - - /* Disable the RTC one second and alarm interrupts. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &= - ~(RTCSC_SIE | RTCSC_ALE); - - /* Enabling the decrementer also enables the timebase interrupts - * (or from the other point of view, to get decrementer interrupts - * we have to enable the timebase). The decrementer interrupt - * is wired into the vector table, nothing to do here for that. - */ - ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr = - ((mk_int_int_mask(DEC_INTERRUPT) << 8) | - (TBSCR_TBF | TBSCR_TBE)); - if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0) - panic("Could not allocate timer IRQ!"); - - /* Get time from the RTC. - */ - return ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc; -} - -void -mbx_restart(char *cmd) -{ - extern void MBX_gorom(void); - - MBX_gorom(); -} - -void -mbx_power_off(void) -{ - mbx_restart(NULL); -} - -void -mbx_halt(void) -{ - mbx_restart(NULL) -} - - -int mbx_setup_residual(char *buffer) -{ - int len = 0; - bd_t *bp; - extern RESIDUAL *res; - - bp = (bd_t *)res; - - len += sprintf(len+buffer,"clock\t\t: %dMHz\n" - "bus clock\t: %dMHz\n", - bp->bi_intfreq /*/ 1000000*/, - bp->bi_busfreq /*/ 1000000*/); - - return len; -} - -void -mbx_do_IRQ(struct pt_regs *regs, - int cpu, - int isfake) -{ - int irq; - unsigned long bits = 0; - - /* For MPC8xx, read the SIVEC register and shift the bits down - * to get the irq number. */ - bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec; - irq = bits >> 26; - irq += ppc8xx_pic.irq_offset; - bits = 1UL << irq; - - if (irq < 0) { - printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n", - irq, regs->nip); - spurious_interrupts++; - } - else { - ppc_irq_dispatch_handler( regs, irq ); - } - -} - -static void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs) -{ - int bits, irq; - - /* A bug in the QSpan chip causes it to give us 0xff always - * when doing a character read. So read 32 bits and shift. - * This doesn't seem to return useful values anyway, but - * read it to make sure things are acked. - * -- Cort - */ - irq = (inl(0x508) >> 24)&0xff; - if ( irq != 0xff ) printk("iack %d\n", irq); - - outb(0x0C, 0x20); - irq = inb(0x20) & 7; - if (irq == 2) - { - outb(0x0C, 0xA0); - irq = inb(0xA0); - irq = (irq&7) + 8; - } - bits = 1UL << irq; - irq += i8259_pic.irq_offset; - ppc_irq_dispatch_handler( regs, irq ); -} - - -/* On MBX8xx, the interrupt control (SIEL) was set by EPPC-bug. External - * interrupts can be either edge or level triggered, but there is no - * reason for us to change the EPPC-bug values (it would not work if we did). - */ -void __init -mbx_init_IRQ(void) -{ - int i; - - ppc8xx_pic.irq_offset = 16; - for ( i = 16 ; i < 32 ; i++ ) - irq_desc[i].ctl = &ppc8xx_pic; - unmask_irq(CPM_INTERRUPT); - - for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; - i8259_init(); - request_irq(ISA_BRIDGE_INT, mbx_i8259_action, 0, "8259 cascade", NULL); - enable_irq(ISA_BRIDGE_INT); -} - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) -/* - * IDE stuff. - */ -void -mbx_ide_insw(ide_ioreg_t port, void *buf, int ns) -{ - ide_insw(port+_IO_BASE), buf, ns); -} - -void -mbx_ide_outsw(ide_ioreg_t port, void *buf, int ns) -{ - ide_outsw(port+_IO_BASE, buf, ns); -} - -int -mbx_ide_default_irq(ide_ioreg_t base) -{ - return 14; -} - -ide_ioreg_t -mbx_ide_default_io_base(int index) -{ - return index; -} - -int -mbx_ide_check_region(ide_ioreg_t from, unsigned int extent) -{ - return 0 -} - -void -mbx_ide_request_region(ide_ioreg_t from, - unsigned int extent, - const char *name) -{ -} - -void -mbx_ide_release_region(ide_ioreg_t from, - unsigned int extent) -{ -} - -void -mbx_ide_fix_driveid(struct hd_driveid *id) -{ - ppc_generic_ide_fix_driveid(id); -} - -void -mbx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) -{ - ide_ioreg_t reg = data_port; - int i; - - *irq = 0; - - if (data_port != 0) /* Only map the first ATA flash drive */ - return; - -#ifdef ATA_FLASH - - reg = (ide_ioreg_t) ioremap(PCMCIA_MEM_ADDR, 0x200); - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hw->io_ports[i] = reg; - reg += 1; - } - - /* Does not matter */ - - if (ctrl_port) { - hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; - } else { - hw->io_ports[IDE_CONTROL_OFFSET] = reg; - } - if (irq) - hw->irq = 13; -#endif -} -#endif - -void __init -mbx_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - - if ( r3 ) - memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) ); - -#ifdef CONFIG_PCI - mbx_setup_pci_ptrs(); -#endif - -#ifdef CONFIG_BLK_DEV_INITRD - /* take care of initrd if we have one */ - if ( r4 ) - { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - /* take care of cmd line */ - if ( r6 ) - { - - *(char *)(r7+KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6+KERNELBASE)); - } - - ppc_md.setup_arch = mbx_setup_arch; - ppc_md.setup_residual = mbx_setup_residual; - ppc_md.get_cpuinfo = NULL; - ppc_md.irq_cannonicalize = NULL; - ppc_md.init_IRQ = mbx_init_IRQ; - ppc_md.do_IRQ = mbx_do_IRQ; - ppc_md.init = NULL; - - ppc_md.restart = mbx_restart; - ppc_md.power_off = mbx_power_off; - ppc_md.halt = mbx_halt; - - ppc_md.time_init = NULL; - ppc_md.set_rtc_time = mbx_set_rtc_time; - ppc_md.get_rtc_time = mbx_get_rtc_time; - ppc_md.calibrate_decr = mbx_calibrate_decr; - - ppc_md.kbd_setkeycode = pckbd_setkeycode; - ppc_md.kbd_getkeycode = pckbd_getkeycode; - ppc_md.kbd_translate = pckbd_translate; - ppc_md.kbd_unexpected_up = pckbd_unexpected_up; - ppc_md.kbd_leds = pckbd_leds; - ppc_md.kbd_init_hw = pckbd_init_hw; -#ifdef CONFIG_MAGIC_SYSRQ - ppc_md.kbd_sysrq_xlate = pckbd_sysrq_xlate; -#endif - -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) - ppc_ide_md.insw = mbx_ide_insw; - ppc_ide_md.outsw = mbx_ide_outsw; - ppc_ide_md.default_irq = mbx_ide_default_irq; - ppc_ide_md.default_io_base = mbx_ide_default_io_base; - ppc_ide_md.ide_check_region = mbx_ide_check_region; - ppc_ide_md.ide_request_region = mbx_ide_request_region; - ppc_ide_md.ide_release_region = mbx_ide_release_region; - ppc_ide_md.fix_driveid = mbx_ide_fix_driveid; - ppc_ide_md.ide_init_hwif = mbx_ide_init_hwif_ports; - - ppc_ide_md.io_base = _IO_BASE; -#endif -} diff --git a/arch/ppc/kernel/open_pic.c b/arch/ppc/kernel/open_pic.c index 4b0375433..02e276729 100644 --- a/arch/ppc/kernel/open_pic.c +++ b/arch/ppc/kernel/open_pic.c @@ -64,14 +64,13 @@ struct hw_interrupt_type open_pic = { if (pri < 0 || pri >= OPENPIC_NUM_PRI) \ printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri); /* - * Turned this check off since the IPI's are treated as irqs - * but they're above NumSources -- Cort - */ -#define check_arg_irq(irq) -#if 0 - if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \ - printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq); -#endif + * I changed this to return to keep us from from trying to use irq #'s + * that we're using for IPI's. + * -- Cort + */ +#define check_arg_irq(irq) \ + /*if (irq < 0 || irq >= (NumSources+open_pic.irq_offset)) \ + printk("openpic.c:%d: illegal irq %d\n", __LINE__, irq);*/ #define check_arg_cpu(cpu) \ if (cpu < 0 || cpu >= NumProcessors) \ printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu); @@ -91,8 +90,7 @@ static void no_action(int ir1, void *dev, struct pt_regs *regs) #ifdef __SMP__ void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs) { -printk("openpic_ipi_action\n"); - smp_message_recv(); + smp_message_recv(cpl-OPENPIC_VEC_IPI); } #endif /* __SMP__ */ @@ -213,6 +211,9 @@ void __init openpic_init(int main_pic) /* Initialize external interrupts */ if ( ppc_md.progress ) ppc_md.progress("openpic ext",0x3bc); + /* SIOint (8259 cascade) is special */ + openpic_initirq(0, 8, open_pic.irq_offset, 1, 1); + openpic_mapirq(0, 1<<0); for (i = 1; i < NumSources; i++) { /* Enabled, Priority 8 */ openpic_initirq(i, 8, open_pic.irq_offset+i, 0, @@ -226,9 +227,6 @@ void __init openpic_init(int main_pic) openpic_set_spurious(OPENPIC_VEC_SPURIOUS); if ( _machine != _MACH_gemini ) { - /* SIOint (8259 cascade) is special */ - openpic_initirq(0, 8, open_pic.irq_offset, 1, 1); - openpic_mapirq(0, 1<<0); if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, "82c59 cascade", NULL)) printk("Unable to get OpenPIC IRQ 0 for cascade\n"); @@ -366,6 +364,27 @@ void openpic_enable_IPI(u_int ipi) } /* + * Do per-cpu setup for SMP systems. + * + * Get IPI's working and start taking interrupts. + * -- Cort + */ +void do_openpic_setup_cpu(void) +{ + int i; + + for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) + openpic_enable_IPI(i); +#if 0 + /* let the openpic know we want intrs */ + for ( i = 0; i < NumSources ; i++ ) + openpic_mapirq(i, openpic_read(&OpenPIC->Source[i].Destination) + | (1<<smp_processor_id()) ); +#endif + openpic_set_priority(smp_processor_id(), 0); +} + +/* * Initialize a timer interrupt (and disable it) * * timer: OpenPIC timer number @@ -397,13 +416,13 @@ void openpic_maptimer(u_int timer, u_int cpumask) void openpic_enable_irq(u_int irq) { check_arg_irq(irq); - openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_clearfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); } void openpic_disable_irq(u_int irq) { check_arg_irq(irq); - openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].ctl->irq_offset].Vector_Priority, OPENPIC_MASK); + openpic_setfield(&OpenPIC->Source[irq-irq_desc[irq].handler->irq_offset].Vector_Priority, OPENPIC_MASK); } /* diff --git a/arch/ppc/kernel/open_pic.h b/arch/ppc/kernel/open_pic.h index 1097c70bf..2673263cf 100644 --- a/arch/ppc/kernel/open_pic.h +++ b/arch/ppc/kernel/open_pic.h @@ -5,5 +5,6 @@ extern struct hw_interrupt_type open_pic; void openpic_ipi_action(int cpl, void *dev_id, struct pt_regs *regs); void openpic_enable_IPI(u_int ipi); +void do_openpic_setup_cpu(void); #endif /* _PPC_KERNEL_OPEN_PIC_H */ diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 054eee918..ec1ff3565 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -91,15 +91,17 @@ unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, return start; } -static void __init pcibios_claim_resources(struct pci_bus *bus) +static void __init pcibios_claim_resources(struct list_head *bus_list) { + struct list_head *ln, *dn; + struct pci_bus *bus; struct pci_dev *dev; int idx; - while (bus) - { - for (dev=bus->devices; dev; dev=dev->sibling) - { + for (ln=bus_list->next; ln != bus_list; ln=ln->next) { + bus = pci_bus_b(ln); + for (dn=bus->devices.next; dn != &bus->devices; dn=dn->next) { + dev = pci_dev_b(dn); for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) { struct resource *r = &dev->resource[idx]; @@ -114,9 +116,7 @@ static void __init pcibios_claim_resources(struct pci_bus *bus) } } } - if (bus->children) - pcibios_claim_resources(bus->children); - bus = bus->next; + pcibios_claim_resources(&bus->children); } } diff --git a/arch/ppc/kernel/pmac_pci.c b/arch/ppc/kernel/pmac_pci.c index a9166da34..75f8097fd 100644 --- a/arch/ppc/kernel/pmac_pci.c +++ b/arch/ppc/kernel/pmac_pci.c @@ -476,7 +476,7 @@ pmac_pcibios_fixup(void) * honor the existence of multi-function devices where * different functions have different interrupt pins. [mj] */ - for(dev=pci_devices; dev; dev=dev->next) + pci_for_each_dev(dev) { /* * Open Firmware often doesn't initialize the, diff --git a/arch/ppc/kernel/pmac_pic.c b/arch/ppc/kernel/pmac_pic.c index f7224f5dd..385e23327 100644 --- a/arch/ppc/kernel/pmac_pic.c +++ b/arch/ppc/kernel/pmac_pic.c @@ -135,7 +135,7 @@ static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs) * don't. Put this here to check for it. * -- Cort */ - if ( irq_desc[irq].ctl != &gatwick_pic ) + if ( irq_desc[irq].handler != &gatwick_pic ) printk("gatwick irq not from gatwick pic\n"); else ppc_irq_dispatch_handler( regs, irq ); @@ -159,7 +159,7 @@ pmac_do_IRQ(struct pt_regs *regs, if (xmon_2nd) xmon(regs); #endif - smp_message_recv(); + pmac_smp_message_recv(); return -1; } @@ -361,7 +361,7 @@ pmac_pic_init(void) max_irqs = 64; } for ( i = 0; i < max_real_irqs ; i++ ) - irq_desc[i].ctl = &pmac_pic; + irq_desc[i].handler = &pmac_pic; /* get addresses of first controller */ if (irqctrler) { @@ -401,7 +401,7 @@ pmac_pic_init(void) if (device_is_compatible(irqctrler, "gatwick")) pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs); for ( i = max_real_irqs ; i < max_irqs ; i++ ) - irq_desc[i].ctl = &gatwick_pic; + irq_desc[i].handler = &gatwick_pic; request_irq( second_irq, gatwick_action, SA_INTERRUPT, "gatwick cascade", 0 ); } diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index 4c3e9a790..72d23a934 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -198,32 +198,12 @@ pmac_get_cpuinfo(char *buffer) #ifdef CONFIG_SCSI /* Find the device number for the disk (if any) at target tgt - on host adaptor host. - XXX this really really should be in drivers/scsi/sd.c. */ + on host adaptor host. We just need to get the prototype from + sd.h */ #include <linux/blkdev.h> #include "../../../drivers/scsi/scsi.h" #include "../../../drivers/scsi/sd.h" -#include "../../../drivers/scsi/hosts.h" -#define SD_MAJOR(i) (!(i) ? SCSI_DISK0_MAJOR : SCSI_DISK1_MAJOR-1+(i)) -#define SD_MAJOR_NUMBER(i) SD_MAJOR((i) >> 8) -#define SD_MINOR_NUMBER(i) ((i) & 255) -#define MKDEV_SD_PARTITION(i) MKDEV(SD_MAJOR_NUMBER(i), SD_MINOR_NUMBER(i)) -#define MKDEV_SD(index) MKDEV_SD_PARTITION((index) << 4) - -__init -kdev_t sd_find_target(void *host, int tgt) -{ - Scsi_Disk *dp; - int i; -#ifdef CONFIG_BLK_DEV_SD - for (dp = rscsi_disks, i = 0; i < sd_template.dev_max; ++i, ++dp) - if (dp->device != NULL && dp->device->host == host - && dp->device->id == tgt) - return MKDEV_SD(i); -#endif /* CONFIG_BLK_DEV_SD */ - return 0; -} #endif /* diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index 11d2cd114..397685d43 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -9,6 +9,8 @@ #include <linux/vt_kern.h> #include <linux/nvram.h> #include <linux/spinlock.h> +#include <linux/console.h> +#include <linux/irq.h> #include <asm/page.h> #include <asm/semaphore.h> @@ -269,3 +271,4 @@ void ppc_irq_dispatch_handler(struct pt_regs *, int); EXPORT_SYMBOL(ppc_irq_dispatch_handler); EXPORT_SYMBOL(decrementer_count); EXPORT_SYMBOL(get_wchan); +EXPORT_SYMBOL(console_drivers); diff --git a/arch/ppc/kernel/prep_pci.c b/arch/ppc/kernel/prep_pci.c index a01962b12..633757875 100644 --- a/arch/ppc/kernel/prep_pci.c +++ b/arch/ppc/kernel/prep_pci.c @@ -998,7 +998,7 @@ prep_pcibios_fixup(void) printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name); if (OpenPIC) { /* PCI interrupts are controlled by the OpenPIC */ - for(dev=pci_devices; dev; dev=dev->next) { + pci_for_each_dev(dev) { if (dev->bus->number == 0) { dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]); pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_PIN, dev->irq); @@ -1007,8 +1007,7 @@ prep_pcibios_fixup(void) return; } - for(dev=pci_devices; dev; dev=dev->next) - { + pci_for_each_dev(dev) { /* * Use our old hard-coded kludge to figure out what * irq this device uses. This is necessary on things diff --git a/arch/ppc/kernel/prep_setup.c b/arch/ppc/kernel/prep_setup.c index e7f62c429..19ae61450 100644 --- a/arch/ppc/kernel/prep_setup.c +++ b/arch/ppc/kernel/prep_setup.c @@ -617,12 +617,12 @@ prep_init_IRQ(void) if (OpenPIC != NULL) { for ( i = 16 ; i < 36 ; i++ ) - irq_desc[i].ctl = &open_pic; + irq_desc[i].handler = &open_pic; openpic_init(1); } for ( i = 0 ; i < 16 ; i++ ) - irq_desc[i].ctl = &i8259_pic; + irq_desc[i].handler = &i8259_pic; i8259_init(); #ifdef __SMP__ request_irq(openpic_to_irq(OPENPIC_VEC_SPURIOUS), openpic_ipi_action, diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index 403213883..64b171042 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -204,15 +204,6 @@ _switch_to(struct task_struct *prev, struct task_struct *new, if ( (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) && prev->thread.vrsave ) giveup_altivec(prev); - /* - * The 750 doesn't broadcast invalidates with tlbie's - * so flush every processor switch. - * -- Cort - */ - if ( ((_get_PVR()>>16) == 8) && - (new->last_processor != NO_PROC_ID) && - (new->last_processor != new->processor) && new->mm ) - flush_tlb_mm(new->mm); prev->last_processor = prev->processor; current_set[smp_processor_id()] = new; #endif /* __SMP__ */ diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index fad7c7c1d..c2891e21f 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -108,34 +108,8 @@ void smp_local_timer_interrupt(struct pt_regs * regs) } } -/* - * Dirty hack to get smp message passing working. - * - * As it is now, if we're sending two message at the same time - * we have race conditions. The PowerSurge doesn't easily - * allow us to send IPI messages so we put the messages in - * smp_message[]. - * - * This is because don't have several IPI's on the PowerSurge even though - * we do on the chrp. It would be nice to use the actual IPI's on the chrp - * rather than this but having two methods of doing IPI isn't a good idea - * right now. - * -- Cort - */ -int smp_message[NR_CPUS]; -void smp_message_recv(void) +void smp_message_recv(int msg) { - int msg = smp_message[smp_processor_id()]; - - if ( _machine == _MACH_Pmac ) - { - /* clear interrupt */ - out_be32(PSURGE_INTR, ~0); - } - - /* make sure msg is for us */ - if ( msg == -1 ) return; - ipi_count++; switch( msg ) @@ -147,15 +121,54 @@ void smp_message_recv(void) case MSG_RESCHEDULE: current->need_resched = 1; break; - case 0xf0f0: /* syncing time bases - just return */ + case MSG_INVALIDATE_TLB: + _tlbia(); + case 0xf0f0: /* pmac syncing time bases - just return */ break; default: printk("SMP %d: smp_message_recv(): unknown msg %d\n", smp_processor_id(), msg); break; } - /* reset message */ - smp_message[smp_processor_id()] = -1; +} + +/* + * As it is now, if we're sending two message at the same time + * we have race conditions on Pmac. The PowerSurge doesn't easily + * allow us to send IPI messages so we put the messages in + * smp_message[]. + * + * This is because don't have several IPI's on the PowerSurge even though + * we do on the chrp. It would be nice to use actual IPI's such as with openpic + * rather than this. + * -- Cort + */ +int pmac_smp_message[NR_CPUS]; +void pmac_smp_message_recv(void) +{ + int msg = pmac_smp_message[smp_processor_id()]; + + /* clear interrupt */ + out_be32(PSURGE_INTR, ~0); + + /* make sure msg is for us */ + if ( msg == -1 ) return; + + smp_message_recv(msg); + + /* reset message */ + pmac_smp_message[smp_processor_id()] = -1; +} + +/* + * 750's don't broadcast tlb invalidates so + * we have to emulate that behavior. + * -- Cort + */ +void smp_send_tlb_invalidate(int cpu) +{ + if ( (_get_PVR()>>16) == 8 ) + smp_message_pass(MSG_ALL_BUT_SELF, MSG_INVALIDATE_TLB, 0, 0); } void smp_send_reschedule(int cpu) @@ -169,6 +182,8 @@ void smp_send_reschedule(int cpu) * as the timer). * -- Cort */ + /* This is only used if `cpu' is running an idle task, + so it will reschedule itself anyway... */ smp_message_pass(cpu, MSG_RESCHEDULE, 0, 0); } @@ -177,38 +192,39 @@ void smp_send_stop(void) smp_message_pass(MSG_ALL_BUT_SELF, MSG_STOP_CPU, 0, 0); } -spinlock_t mesg_pass_lock = SPIN_LOCK_UNLOCKED; void smp_message_pass(int target, int msg, unsigned long data, int wait) { int i; - if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_gemini)) ) + + if ( !(_machine & (_MACH_Pmac|_MACH_chrp|_MACH_prep|_MACH_gemini)) ) return; - spin_lock(&mesg_pass_lock); - - /* - * We assume here that the msg is not -1. If it is, - * the recipient won't know the message was destined - * for it. -- Cort - */ - - switch( target ) - { - case MSG_ALL: - smp_message[smp_processor_id()] = msg; - /* fall through */ - case MSG_ALL_BUT_SELF: - for ( i = 0 ; i < smp_num_cpus ; i++ ) - if ( i != smp_processor_id () ) - smp_message[i] = msg; - break; - default: - smp_message[target] = msg; - break; - } - - if ( _machine == _MACH_Pmac ) - { + switch (_machine) { + case _MACH_Pmac: + /* + * IPI's on the Pmac are a hack but without reasonable + * IPI hardware SMP on Pmac is a hack. + * + * We assume here that the msg is not -1. If it is, + * the recipient won't know the message was destined + * for it. -- Cort + */ + for ( i = 0; i <= smp_num_cpus ; i++ ) + pmac_smp_message[i] = -1; + switch( target ) + { + case MSG_ALL: + pmac_smp_message[smp_processor_id()] = msg; + /* fall through */ + case MSG_ALL_BUT_SELF: + for ( i = 0 ; i < smp_num_cpus ; i++ ) + if ( i != smp_processor_id () ) + pmac_smp_message[i] = msg; + break; + default: + pmac_smp_message[target] = msg; + break; + } /* interrupt secondary processor */ out_be32(PSURGE_INTR, ~0); out_be32(PSURGE_INTR, 0); @@ -218,40 +234,28 @@ void smp_message_pass(int target, int msg, unsigned long data, int wait) */ /* interrupt primary */ /**(volatile unsigned long *)(0xf3019000);*/ - } - - if ( _machine == _MACH_chrp ) - { - /* - * There has to be some way of doing this better - - * perhaps a send-to-all or send-to-all-but-self - * in the openpic. This gets us going for now, though. - * -- Cort - */ + break; + case _MACH_chrp: + case _MACH_prep: + case _MACH_gemini: + /* make sure we're sending something that translates to an IPI */ + if ( msg > 0x3 ) + break; switch ( target ) { case MSG_ALL: - openpic_cause_IPI(smp_processor_id(), 0, 0x0 ); - openpic_cause_IPI(smp_processor_id(), 0, 0xffffffff ); + openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff); break; case MSG_ALL_BUT_SELF: - for ( i = 0 ; i < smp_num_cpus ; i++ ) - if ( i != smp_processor_id () ) - { - openpic_cause_IPI(smp_processor_id(), 0, - 0x0 ); - openpic_cause_IPI(smp_processor_id(), 0, + openpic_cause_IPI(smp_processor_id(), msg, 0xffffffff & ~(1 << smp_processor_id())); - } break; default: - openpic_cause_IPI(smp_processor_id(), 0, 0x0 ); - openpic_cause_IPI(target, 0, 1U << target ); + openpic_cause_IPI(smp_processor_id(), msg, 1<<target); break; } + break; } - - spin_unlock(&mesg_pass_lock); } void __init smp_boot_cpus(void) @@ -387,6 +391,9 @@ void __init smp_boot_cpus(void) } } + if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) ) + do_openpic_setup_cpu(); + if ( _machine == _MACH_Pmac ) { /* reset the entry point so if we get another intr we won't @@ -432,6 +439,13 @@ void __init smp_callin(void) current->mm->mmap->vm_end = init_mm.mmap->vm_end; #endif cpu_callin_map[current->processor] = 1; + /* + * Each processor has to do this and this is the best + * place to stick it for now. + * -- Cort + */ + if ( _machine & (_MACH_gemini|_MACH_chrp|_MACH_prep) ) + do_openpic_setup_cpu(); while(!smp_commenced) barrier(); __sti(); |