---------- Forwarded message ---------- Date: Sat, 22 Dec 2001 17:39:48 +0100 (CET) From: Vivien Chappelier <glaurung@melkor.maisel.enst-bretagne.fr> To: Ralf Baechle <ralf@oss.sgi.com> Cc: ilya@theIlya.com, mips-linux@oss.sgi.com Subject: weekly O2 patches ;) Hi! Here are two patches, a general one to get ip32 and probably ip27 booting with the new 2.5.1 kernel, the other one for ip32 level 1 cache. The first one fixes a call to NULL upon initialization of the timer. The second one fixes a couple of things: - the second level cache was not enabled (just checked if present or not) resulting in incorrect cache size detection and incorrect cache flushing functions. This is fixed (i.e. size is ok now), but secondary cache is disabled as it still didn't work with it (i.e. functions are for l1 cache flushing, sprobe_cache returns no second cache) - on pci_unmap_single, pci_unmap_sg, cache was not flushed, this resulted in content of DMAd memory not being seen by the CPU when reading DMA buffers from device. - with 2.5.1, some calls to pci_map_sg/pci_unmap_sg use pages instead of adresses. This was not supported (by both ip27 and ip32) - the aic7xxx SCSI controller didn't use DMA for reading disk info, the flag unchecked_isa_dma was set to one to force using DMAable memory for this. Note that I'm still using the IP22 PAGE_OFFSET, and this works well, as the firmware is 32bit and loads the kernel at that address, this leaves 512Mb of addressable memory, I think we should leave PAGE_OFFSET to this value for now. If we need to address more memory, we'll have to write some code to remap the kernel elsewhere (maybe something like when setting CONFIG_MAPPED_KERNEL on IP27?). The problem still happens in reserve_bootmem, even with kernel 2.5.1 where code seems to have changed a lot there: when using 0x98000.. PAGE_OFFSET, the bootmem code sees no available memory. There are still bugs with IP32, both running cache or uncached that these patches don't fix (especially when doing cat /dev/sda > /dev/null or trying to boot nfsroot). Finally, when fixing ip32 for 2.5.1 (i.e. cacheing with pages and timer setup) I've tried to apply the same changes for the ip27 but I could not test them of course.. so please do :) regards, Vivien.
diff -Naur linux/arch/mips64/mm/r4xx0.c linux.patch/arch/mips64/mm/r4xx0.c --- linux/arch/mips64/mm/r4xx0.c Sun Dec 9 15:47:14 2001 +++ linux.patch/arch/mips64/mm/r4xx0.c Thu Dec 20 19:04:46 2001 @@ -2141,9 +2141,17 @@ unsigned long flags, addr, begin, end, pow2; int tmp; - tmp = ((config >> 17) & 1); + /* XXX: disabling secondary cache for now */ + change_cp0_config(CONF_SE, 0); + + tmp = ((config >> 17) & 1); /* check if cache present */ if(tmp) return 0; + + tmp = ((config >> 12) & 1); /* check if cache enabled */ + if(!tmp) + return 0; + tmp = ((config >> 22) & 3); switch(tmp) { case 0: diff -Naur linux/arch/mips64/sgi-ip27/ip27-pci-dma.c linux.patch/arch/mips64/sgi-ip27/ip27-pci-dma.c --- linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Sun Dec 9 15:47:15 2001 +++ linux.patch/arch/mips64/sgi-ip27/ip27-pci-dma.c Fri Dec 21 11:08:22 2001 @@ -112,7 +112,11 @@ /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nents; i++, sg++) { - sg->address = (char *)(bus_to_baddr[hwdev->bus->number] | __pa(sg->address)); + if(sg->address) + address = sg->address; + else + address = page_address(sg->page) + sg->offset; + sg->dvma_address = (char *)(bus_to_baddr[hwdev->bus->number] | __pa(address)); } return nents; diff -Naur linux/arch/mips64/sgi-ip32/ip32-irq.c linux.patch/arch/mips64/sgi-ip32/ip32-irq.c --- linux/arch/mips64/sgi-ip32/ip32-irq.c Thu Dec 20 18:30:20 2001 +++ linux.patch/arch/mips64/sgi-ip32/ip32-irq.c Sat Dec 22 14:35:52 2001 @@ -473,29 +473,34 @@ /* CRIME 1.1 appears to deliver all interrupts to this one pin. */ void ip32_irq0(struct pt_regs *regs) { - u64 crime_int = crime_read_64 (CRIME_INT_STAT); + u64 crime_int; + int count = 10000; int irq = 0; - - if (crime_int & CRIME_MACE_INT_MASK) { - crime_int &= CRIME_MACE_INT_MASK; - irq = ffs (crime_int); - } else if (crime_int & CRIME_MACEISA_INT_MASK) { - u32 mace_int; - mace_int = mace_read_32 (MACEISA_INT_STAT); - if (mace_int == 0) - irq = 0; - else - irq = ffs (mace_int) + 32; - } else if (crime_int & CRIME_MACEPCI_INT_MASK) { - crime_int &= CRIME_MACEPCI_INT_MASK; - crime_int >>= 8; - irq = ffs (crime_int) + 8; - } else if (crime_int & 0xffff0000) { - crime_int >>= 16; - irq = ffs (crime_int) + 16; - } + + do { + crime_int = crime_read_64(CRIME_INT_STAT); + if (crime_int & CRIME_MACE_INT_MASK) { + crime_int &= CRIME_MACE_INT_MASK; + irq = ffs (crime_int); + } else if (crime_int & CRIME_MACEISA_INT_MASK) { + u32 mace_int; + mace_int = mace_read_32 (MACEISA_INT_STAT); + if (mace_int == 0) + irq = 0; + else + irq = ffs (mace_int) + 32; + } else if (crime_int & CRIME_MACEPCI_INT_MASK) { + crime_int &= CRIME_MACEPCI_INT_MASK; + crime_int >>= 8; + irq = ffs (crime_int) + 8; + } else if (crime_int & 0xffff0000) { + crime_int >>= 16; + irq = ffs (crime_int) + 16; + } + } while(irq == 0 && count--); + if (irq == 0) - ip32_unknown_interrupt(regs); + ip32_unknown_interrupt(regs); DBG("*irq %u*\n", irq); do_IRQ(irq, regs); } diff -Naur linux/arch/mips64/sgi-ip32/ip32-pci-dma.c linux.patch/arch/mips64/sgi-ip32/ip32-pci-dma.c --- linux/arch/mips64/sgi-ip32/ip32-pci-dma.c Sun Dec 9 15:47:15 2001 +++ linux.patch/arch/mips64/sgi-ip32/ip32-pci-dma.c Fri Dec 21 11:07:33 2001 @@ -99,7 +99,10 @@ if (direction == PCI_DMA_NONE) BUG(); DPRINTK("pci_unmap_single\n"); - /* Nothing to do */ + if (direction != PCI_DMA_TODEVICE) { + mips_wbflush(); + dma_cache_wback_inv((unsigned long)__va(dma_addr), size); + } } /* @@ -122,6 +125,7 @@ int nents, int direction) { int i; + unsigned long address; if (direction == PCI_DMA_NONE) BUG(); @@ -131,9 +135,13 @@ DPRINTK("pci_map_sg\n"); /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nents; i++, sg++) { + if(sg->address) + address = sg->address; + else + address = page_address(sg->page) + sg->offset; mips_wbflush(); - dma_cache_wback_inv((unsigned long)sg->address, sg->length); - sg->address = (char *)(__pa(sg->address)); + dma_cache_wback_inv(address, sg->length); + sg->dvma_address = __pa(address); } return nents; @@ -147,10 +155,22 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction) { + int i; + unsigned long address; + if (direction == PCI_DMA_NONE) BUG(); DPRINTK("pci_unmap_sg\n"); - /* Nothing to do */ + for (i = 0; i < nents; i++, sg++) { + if (direction != PCI_DMA_TODEVICE) { + if(sg->address) + address = sg->address; + else + address = page_address(sg->page) + sg->offset; + mips_wbflush(); + dma_cache_wback_inv(address, sg->length); + } + } } /* @@ -188,13 +208,19 @@ int nelems, int direction) { int i; + unsigned long address; + if (direction == PCI_DMA_NONE) BUG(); DPRINTK("pci_dma_sync_sg\n"); /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++){ + if(sg->address) + address = sg->address; + else + address = page_address(sg->page) + sg->offset; mips_wbflush(); - dma_cache_wback_inv((unsigned long)__va(sg->address), sg->length); + dma_cache_wback_inv(address, sg->length); } /* if(direction==PCI_DMA_TODEVICE) mace_inv_read_buffers();*/ diff -Naur linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h linux.patch/drivers/scsi/aic7xxx/aic7xxx_linux_host.h --- linux/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Thu Dec 20 18:31:11 2001 +++ linux.patch/drivers/scsi/aic7xxx/aic7xxx_linux_host.h Thu Dec 20 21:43:31 2001 @@ -87,7 +87,7 @@ sg_tablesize: 0, /* max scatter-gather cmds */\ cmd_per_lun: 2, /* cmds per lun */\ present: 0, /* number of 7xxx's present */\ - unchecked_isa_dma: 0, /* no memory DMA restrictions */\ + unchecked_isa_dma: 1, \ use_clustering: ENABLE_CLUSTERING, \ highmem_io: 1 \ } diff -Naur linux/include/asm-mips64/mipsregs.h linux.patch/include/asm-mips64/mipsregs.h --- linux/include/asm-mips64/mipsregs.h Sun Dec 9 15:52:27 2001 +++ linux.patch/include/asm-mips64/mipsregs.h Fri Dec 21 11:28:06 2001 @@ -367,6 +367,7 @@ #define CONF_CM_CMASK 7 #define CONF_DB (1 << 4) #define CONF_IB (1 << 5) +#define CONF_SE (1 << 12) #define CONF_SC (1 << 17) #define CONF_AC (1 << 23) #define CONF_HALT (1 << 25) diff -Naur linux/include/asm-mips64/page.h linux.patch/include/asm-mips64/page.h --- linux/include/asm-mips64/page.h Thu Dec 20 18:48:30 2001 +++ linux.patch/include/asm-mips64/page.h Thu Dec 20 18:50:24 2001 @@ -60,11 +60,8 @@ * at XKPHYS with a suitable caching mode for kernels with more than that. */ #if defined(CONFIG_SGI_IP22) || defined(CONFIG_MIPS_ATLAS) || \ - defined(CONFIG_MIPS_MALTA) + defined(CONFIG_MIPS_MALTA) || defined(CONFIG_SGI_IP32) #define PAGE_OFFSET 0xffffffff80000000UL -#endif -#if defined(CONFIG_SGI_IP32) -#define PAGE_OFFSET 0x9800000000000000UL #endif #if defined(CONFIG_SGI_IP27) #define PAGE_OFFSET 0xa800000000000000UL diff -Naur linux/include/asm-mips64/pci.h linux.patch/include/asm-mips64/pci.h --- linux/include/asm-mips64/pci.h Thu Dec 20 18:32:18 2001 +++ linux.patch/include/asm-mips64/pci.h Fri Dec 21 11:10:08 2001 @@ -319,7 +319,7 @@ * returns, or alternatively stop on the first sg_dma_len(sg) which * is 0. */ -#define sg_dma_address(sg) ((unsigned long)((sg)->address)) +#define sg_dma_address(sg) ((sg)->dvma_address) #define sg_dma_len(sg) ((sg)->length) #endif /* __KERNEL__ */ diff -Naur linux/include/asm-mips64/pgtable.h linux.patch/include/asm-mips64/pgtable.h --- linux/include/asm-mips64/pgtable.h Thu Dec 20 18:32:18 2001 +++ linux.patch/include/asm-mips64/pgtable.h Thu Dec 20 20:03:07 2001 @@ -180,11 +180,11 @@ #ifdef CONFIG_MIPS_UNCACHED #define PAGE_CACHABLE_DEFAULT _CACHE_UNCACHED #else /* ! UNCACHED */ -#ifdef CONFIG_SGI_IP22 +#if defined(CONFIG_SGI_IP22) || defined(CONFIG_SGI_IP32) #define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_NONCOHERENT -#else /* ! IP22 */ +#else /* ! (IP22 || IP32)*/ #define PAGE_CACHABLE_DEFAULT _CACHE_CACHABLE_COW -#endif /* IP22 */ +#endif /* (IP22 || IP32) */ #endif /* UNCACHED */ #define PAGE_NONE __pgprot(_PAGE_PRESENT | PAGE_CACHABLE_DEFAULT) diff -Naur linux/include/asm-mips64/scatterlist.h linux.patch/include/asm-mips64/scatterlist.h --- linux/include/asm-mips64/scatterlist.h Thu Dec 20 18:32:18 2001 +++ linux.patch/include/asm-mips64/scatterlist.h Fri Dec 21 11:09:40 2001 @@ -7,7 +7,7 @@ unsigned int offset; unsigned int length; - __u32 dvma_address; + dma_addr_t dvma_address; }; struct mmu_sglist {
diff -Naur linux/arch/mips64/kernel/time.c linux.patch/arch/mips64/kernel/time.c --- linux/arch/mips64/kernel/time.c Wed Dec 19 01:03:03 2001 +++ linux.patch/arch/mips64/kernel/time.c Thu Dec 20 21:37:02 2001 @@ -457,7 +457,8 @@ * to be NULL function so that we are sure the high-level code * is not invoked accidentally. */ - board_timer_setup(&timer_irqaction); + if(board_timer_setup) + board_timer_setup(&timer_irqaction); } #define FEBRUARY 2 diff -Naur linux/arch/mips64/sgi-ip27/ip27-setup.c linux.patch/arch/mips64/sgi-ip27/ip27-setup.c --- linux/arch/mips64/sgi-ip27/ip27-setup.c Thu Dec 20 18:30:20 2001 +++ linux.patch/arch/mips64/sgi-ip27/ip27-setup.c Thu Dec 20 21:37:49 2001 @@ -311,4 +311,5 @@ mips_io_port_base = IO_BASE; board_time_init = ip27_time_init; + board_timer_setup = NULL; } diff -Naur linux/arch/mips64/sgi-ip32/ip32-setup.c linux.patch/arch/mips64/sgi-ip32/ip32-setup.c --- linux/arch/mips64/sgi-ip32/ip32-setup.c Thu Dec 20 18:30:20 2001 +++ linux.patch/arch/mips64/sgi-ip32/ip32-setup.c Thu Dec 20 21:37:59 2001 @@ -91,6 +91,7 @@ rtc_ops = &ip32_rtc_ops; board_time_init = ip32_time_init; + board_timer_setup = NULL; crime_init (); }