--- /dev/null |33935 -------------------------- CREDITS | 2 Documentation/DocBook/kernel-locking.tmpl | 7 Documentation/SubmittingPatches | 14 Documentation/devices.txt | 12 Documentation/fb/modedb.txt | 1 Documentation/fb/tridentfb.txt | 11 Documentation/filesystems/ntfs.txt | 3 Documentation/i2c/porting-clients | 5 Documentation/i386/zero-page.txt | 7 Documentation/kernel-parameters.txt | 53 Documentation/m68k/00-INDEX | 2 Documentation/networking/ip-sysctl.txt | 7 Documentation/networking/sk98lin.txt | 6 Documentation/power/swsusp.txt | 104 Documentation/power/video.txt | 36 Documentation/s390/driver-model.txt | 26 Documentation/scsi/qla2xxx.revision.notes | 457 Documentation/sh/kgdb.txt | 179 Documentation/sh/new-machine.txt | 259 Documentation/sysctl/kernel.txt | 19 MAINTAINERS | 49 arch/alpha/Kconfig | 1 arch/alpha/kernel/module.c | 2 arch/alpha/mm/extable.c | 5 arch/arm/mm/extable.c | 21 arch/arm26/mm/extable.c | 21 arch/cris/arch-v10/drivers/ds1302.c | 1 arch/cris/arch-v10/drivers/pcf8563.c | 1 arch/cris/mm/Makefile | 2 arch/h8300/mm/Makefile | 2 arch/i386/Kconfig | 1 arch/i386/kernel/acpi/wakeup.S | 9 arch/i386/kernel/cpu/cpufreq/Kconfig | 10 arch/i386/kernel/cpu/cpufreq/p4-clockmod.c | 55 arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 23 arch/i386/kernel/cpu/cpufreq/speedstep-lib.h | 6 arch/i386/kernel/cpu/intel.c | 31 arch/i386/kernel/dmi_scan.c | 10 arch/i386/kernel/efi.c | 4 arch/i386/kernel/time.c | 24 arch/i386/kernel/time_hpet.c | 4 arch/i386/mach-voyager/voyager_smp.c | 12 arch/i386/mm/extable.c | 22 arch/ia64/Kconfig | 33 arch/ia64/Makefile | 17 arch/ia64/configs/generic_defconfig | 1045 arch/ia64/configs/sn2_defconfig | 65 arch/ia64/hp/common/sba_iommu.c | 494 arch/ia64/ia32/sys_ia32.c | 2 arch/ia64/kernel/acpi.c | 3 arch/ia64/kernel/efi.c | 3 arch/ia64/kernel/ia64_ksyms.c | 132 arch/ia64/kernel/irq.c | 5 arch/ia64/kernel/irq_ia64.c | 2 arch/ia64/kernel/machvec.c | 4 arch/ia64/kernel/perfmon.c | 60 arch/ia64/kernel/process.c | 1 arch/ia64/kernel/setup.c | 13 arch/ia64/kernel/smp.c | 4 arch/ia64/kernel/smpboot.c | 13 arch/ia64/kernel/time.c | 1 arch/ia64/kernel/unwind.c | 9 arch/ia64/lib/Makefile | 4 arch/ia64/lib/io.c | 4 arch/ia64/lib/memcpy_mck.S | 6 arch/ia64/lib/memset.S | 6 arch/ia64/mm/extable.c | 5 arch/ia64/mm/init.c | 10 arch/ia64/mm/numa.c | 3 arch/ia64/mm/tlb.c | 3 arch/ia64/pci/pci.c | 3 arch/ia64/scripts/check-text-align.S | 6 arch/ia64/scripts/unwcheck.py | 64 arch/ia64/sn/Makefile | 2 arch/ia64/sn/fakeprom/README | 32 arch/ia64/sn/fakeprom/fprom.lds | 32 arch/ia64/sn/io/Makefile | 4 arch/ia64/sn/io/cdl.c | 16 arch/ia64/sn/io/drivers/Makefile | 2 arch/ia64/sn/io/drivers/ioconfig_bus.c | 110 arch/ia64/sn/io/hwgfs/Makefile | 2 arch/ia64/sn/io/hwgfs/hcl.c | 250 arch/ia64/sn/io/hwgfs/hcl_util.c | 67 arch/ia64/sn/io/hwgfs/interface.c | 36 arch/ia64/sn/io/hwgfs/labelcl.c | 1 arch/ia64/sn/io/hwgfs/ramfs.c | 32 arch/ia64/sn/io/io.c | 44 arch/ia64/sn/io/machvec/Makefile | 2 arch/ia64/sn/io/machvec/pci.c | 21 arch/ia64/sn/io/machvec/pci_bus_cvlink.c | 359 arch/ia64/sn/io/machvec/pci_dma.c | 125 arch/ia64/sn/io/platform_init/Makefile | 4 arch/ia64/sn/io/platform_init/sgi_io_init.c | 131 arch/ia64/sn/io/sn2/Makefile | 2 arch/ia64/sn/io/sn2/bte_error.c | 64 arch/ia64/sn/io/sn2/geo_op.c | 4 arch/ia64/sn/io/sn2/klconflib.c | 179 arch/ia64/sn/io/sn2/klgraph.c | 478 arch/ia64/sn/io/sn2/l1_command.c | 90 arch/ia64/sn/io/sn2/ml_SN_init.c | 72 arch/ia64/sn/io/sn2/ml_SN_intr.c | 5 arch/ia64/sn/io/sn2/ml_iograph.c | 311 arch/ia64/sn/io/sn2/module.c | 136 arch/ia64/sn/io/sn2/pcibr/Makefile | 9 arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c | 60 arch/ia64/sn/io/sn2/pcibr/pcibr_config.c | 29 arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c | 692 arch/ia64/sn/io/sn2/pcibr/pcibr_error.c | 454 arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c | 32 arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c | 226 arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c | 107 arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c | 70 arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c | 672 arch/ia64/sn/io/sn2/pciio.c | 504 arch/ia64/sn/io/sn2/pic.c | 106 arch/ia64/sn/io/sn2/shub.c | 50 arch/ia64/sn/io/sn2/shub_intr.c | 96 arch/ia64/sn/io/sn2/shuberror.c | 14 arch/ia64/sn/io/sn2/shubio.c | 22 arch/ia64/sn/io/sn2/xbow.c | 530 arch/ia64/sn/io/sn2/xtalk.c | 95 arch/ia64/sn/io/snia_if.c | 108 arch/ia64/sn/io/xswitch.c | 12 arch/ia64/sn/kernel/Makefile | 2 arch/ia64/sn/kernel/bte.c | 32 arch/ia64/sn/kernel/irq.c | 132 arch/ia64/sn/kernel/machvec.c | 32 arch/ia64/sn/kernel/mca.c | 32 arch/ia64/sn/kernel/probe.c | 32 arch/ia64/sn/kernel/setup.c | 88 arch/ia64/sn/kernel/sn2/Makefile | 2 arch/ia64/sn/kernel/sn2/cache.c | 5 arch/ia64/sn/kernel/sn2/sn2_smp.c | 32 arch/ia64/sn/kernel/sn2/sn_proc_fs.c | 31 arch/m68k/amiga/amisound.c | 2 arch/m68k/amiga/chipram.c | 4 arch/m68k/amiga/config.c | 24 arch/m68k/atari/hades-pci.c | 19 arch/m68k/bvme6000/rtc.c | 10 arch/m68k/kernel/head.S | 387 arch/m68k/kernel/traps.c | 210 arch/m68k/mac/config.c | 2 arch/m68k/mac/misc.c | 18 arch/m68k/math-emu/fp_arith.c | 5 arch/m68k/math-emu/fp_log.c | 2 arch/m68k/math-emu/multi_arith.h | 87 arch/m68k/mm/Makefile | 2 arch/m68k/mm/hwtest.c | 4 arch/m68k/mm/motorola.c | 2 arch/m68k/mvme16x/rtc.c | 7 arch/m68k/q40/q40ints.c | 26 arch/m68k/sun3/idprom.c | 46 arch/m68knommu/kernel/Makefile | 6 arch/m68knommu/kernel/module.c | 99 arch/m68knommu/kernel/time.c | 8 arch/m68knommu/lib/checksum.c | 1 arch/m68knommu/mm/Makefile | 2 arch/m68knommu/platform/5307/entry.S | 4 arch/mips/Kconfig | 1 arch/mips/mm/Makefile | 2 arch/parisc/Kconfig | 1 arch/parisc/kernel/sys_parisc.c | 8 arch/parisc/mm/Makefile | 2 arch/ppc/Kconfig | 1 arch/ppc/boot/prep/Makefile | 3 arch/ppc/boot/prep/head.S | 26 arch/ppc/boot/prep/misc.c | 52 arch/ppc/kernel/Makefile | 3 arch/ppc/kernel/misc.S | 1 arch/ppc/kernel/module.c | 5 arch/ppc/kernel/ppc_ksyms.c | 32 arch/ppc/kernel/syscalls.c | 2 arch/ppc/mm/Makefile | 2 arch/ppc/mm/cachemap.c | 2 arch/ppc64/Kconfig | 35 arch/ppc64/Makefile | 22 arch/ppc64/boot/ppc32-types.h | 6 arch/ppc64/kernel/HvCall.c | 113 arch/ppc64/kernel/ItLpQueue.c | 17 arch/ppc64/kernel/LparData.c | 52 arch/ppc64/kernel/Makefile | 30 arch/ppc64/kernel/XmPciLpEvent.c | 126 arch/ppc64/kernel/asm-offsets.c | 6 arch/ppc64/kernel/chrp_setup.c | 88 arch/ppc64/kernel/cputable.c | 36 arch/ppc64/kernel/eeh.c | 2 arch/ppc64/kernel/entry.S | 119 arch/ppc64/kernel/head.S | 262 arch/ppc64/kernel/iSeries_IoMmTable.c | 182 arch/ppc64/kernel/iSeries_IoMmTable.h | 88 arch/ppc64/kernel/iSeries_VpdInfo.c | 342 arch/ppc64/kernel/iSeries_htab.c | 197 arch/ppc64/kernel/iSeries_irq.c | 284 arch/ppc64/kernel/iSeries_pci.c | 1285 arch/ppc64/kernel/iSeries_pci_reset.c | 67 arch/ppc64/kernel/iSeries_proc.c | 61 arch/ppc64/kernel/iSeries_setup.c | 653 arch/ppc64/kernel/iSeries_setup.h | 39 arch/ppc64/kernel/idle.c | 191 arch/ppc64/kernel/irq.c | 45 arch/ppc64/kernel/lparcfg.c | 478 arch/ppc64/kernel/mf.c | 1159 arch/ppc64/kernel/mf_proc.c | 292 arch/ppc64/kernel/misc.S | 137 arch/ppc64/kernel/module.c | 4 arch/ppc64/kernel/nvram.c | 684 arch/ppc64/kernel/open_pic.c | 34 arch/ppc64/kernel/pSeries_htab.c | 29 arch/ppc64/kernel/pSeries_hvCall.S | 74 arch/ppc64/kernel/pSeries_lpar.c | 133 arch/ppc64/kernel/pSeries_pci.c | 171 arch/ppc64/kernel/pci.c | 23 arch/ppc64/kernel/pci_dma.c | 15 arch/ppc64/kernel/pci_dn.c | 4 arch/ppc64/kernel/ppc_ksyms.c | 15 arch/ppc64/kernel/proc_pmc.c | 24 arch/ppc64/kernel/proc_ppc64.c | 263 arch/ppc64/kernel/process.c | 105 arch/ppc64/kernel/prom.c | 895 arch/ppc64/kernel/ras.c | 39 arch/ppc64/kernel/rtas-proc.c | 56 arch/ppc64/kernel/rtas.c | 138 arch/ppc64/kernel/rtas_flash.c | 595 arch/ppc64/kernel/rtasd.c | 286 arch/ppc64/kernel/rtc.c | 1 arch/ppc64/kernel/scanlog.c | 13 arch/ppc64/kernel/setup.c | 134 arch/ppc64/kernel/signal.c | 186 arch/ppc64/kernel/signal32.c | 1140 arch/ppc64/kernel/smp.c | 110 arch/ppc64/kernel/sys_ppc32.c | 194 arch/ppc64/kernel/syscalls.c | 4 arch/ppc64/kernel/time.c | 30 arch/ppc64/kernel/traps.c | 33 arch/ppc64/kernel/udbg.c | 4 arch/ppc64/kernel/vio.c | 536 arch/ppc64/kernel/viopath.c | 757 arch/ppc64/kernel/vmlinux.lds.S | 231 arch/ppc64/kernel/xics.c | 22 arch/ppc64/mm/Makefile | 2 arch/ppc64/mm/hash_low.S | 283 arch/ppc64/mm/hash_utils.c | 358 arch/ppc64/mm/hugetlbpage.c | 10 arch/ppc64/mm/imalloc.c | 247 arch/ppc64/mm/init.c | 277 arch/ppc64/mm/numa.c | 27 arch/ppc64/xmon/xmon.c | 38 arch/s390/Kconfig | 2 arch/s390/defconfig | 30 arch/s390/kernel/compat_ioctl.c | 891 arch/s390/kernel/compat_linux.c | 153 arch/s390/kernel/compat_linux.h | 18 arch/s390/kernel/compat_signal.c | 3 arch/s390/kernel/compat_wrapper.S | 77 arch/s390/kernel/entry.S | 6 arch/s390/kernel/entry64.S | 15 arch/s390/kernel/head.S | 14 arch/s390/kernel/head64.S | 14 arch/s390/kernel/ptrace.c | 37 arch/s390/kernel/semaphore.c | 12 arch/s390/kernel/setup.c | 7 arch/s390/kernel/signal.c | 3 arch/s390/kernel/sys_s390.c | 36 arch/s390/kernel/syscalls.S | 23 arch/s390/kernel/traps.c | 8 arch/s390/kernel/vmlinux.lds.S | 3 arch/s390/lib/uaccess.S | 35 arch/s390/lib/uaccess64.S | 35 arch/s390/mm/Makefile | 2 arch/s390/mm/fault.c | 34 arch/sh/Kconfig | 503 arch/sh/Makefile | 67 arch/sh/boards/adx/Makefile | 2 arch/sh/boards/adx/setup.c | 34 arch/sh/boards/bigsur/Makefile | 4 arch/sh/boards/bigsur/io.c | 184 arch/sh/boards/bigsur/setup.c | 40 arch/sh/boards/cat68701/Makefile | 2 arch/sh/boards/cat68701/setup.c | 47 arch/sh/boards/cqreek/Makefile | 2 arch/sh/boards/cqreek/setup.c | 36 arch/sh/boards/dmida/mach.c | 14 arch/sh/boards/dreamcast/Makefile | 4 arch/sh/boards/dreamcast/setup.c | 23 arch/sh/boards/ec3104/Makefile | 2 arch/sh/boards/ec3104/setup.c | 33 arch/sh/boards/harp/mach.c | 14 arch/sh/boards/hp6xx/hp620/mach.c | 12 arch/sh/boards/hp6xx/hp680/mach.c | 12 arch/sh/boards/hp6xx/hp690/mach.c | 12 arch/sh/boards/mpc1211/Makefile | 2 arch/sh/boards/mpc1211/pci.c | 5 arch/sh/boards/mpc1211/rtc.c | 7 arch/sh/boards/mpc1211/setup.c | 72 arch/sh/boards/overdrive/mach.c | 12 arch/sh/boards/saturn/Makefile | 2 arch/sh/boards/saturn/irq.c | 7 arch/sh/boards/saturn/setup.c | 21 arch/sh/boards/saturn/smp.c | 4 arch/sh/boards/se/770x/io.c | 32 arch/sh/boards/se/770x/mach.c | 10 arch/sh/boards/se/7751/io.c | 60 arch/sh/boards/se/7751/mach.c | 14 arch/sh/boards/se/7751/pci.c | 29 arch/sh/boards/sh2000/Makefile | 2 arch/sh/boards/sh2000/setup.c | 25 arch/sh/boards/snapgear/Makefile | 10 arch/sh/boards/snapgear/io.c | 226 arch/sh/boards/snapgear/rtc.c | 333 arch/sh/boards/snapgear/setup.c | 220 arch/sh/boards/systemh/Makefile | 17 arch/sh/boards/systemh/io.c | 283 arch/sh/boards/systemh/irq.c | 111 arch/sh/boards/systemh/setup.c | 80 arch/sh/boot/compressed/Makefile | 4 arch/sh/boot/compressed/head.S | 51 arch/sh/boot/compressed/vmlinux.scr | 9 arch/sh/cchips/Kconfig | 76 arch/sh/cchips/hd6446x/hd64461/io.c | 37 arch/sh/cchips/hd6446x/hd64461/setup.c | 20 arch/sh/cchips/hd6446x/hd64465/io.c | 37 arch/sh/cchips/hd6446x/hd64465/setup.c | 22 arch/sh/configs/defconfig-adx | 6 arch/sh/configs/defconfig-cqreek | 6 arch/sh/configs/defconfig-dreamcast | 531 arch/sh/configs/defconfig-se7751 | 617 arch/sh/configs/defconfig-snapgear | 540 arch/sh/configs/defconfig-systemh | 372 arch/sh/drivers/Makefile | 7 arch/sh/drivers/dma/Kconfig | 42 arch/sh/drivers/dma/Makefile | 8 arch/sh/drivers/dma/dma-api.c | 193 arch/sh/drivers/dma/dma-g2.c | 173 arch/sh/drivers/dma/dma-isa.c | 93 arch/sh/drivers/dma/dma-pvr2.c | 111 arch/sh/drivers/dma/dma-sh.c | 271 arch/sh/drivers/dma/dma-sh.h | 48 arch/sh/drivers/pci/Kconfig | 46 arch/sh/drivers/pci/Makefile | 16 arch/sh/drivers/pci/dma-dreamcast.c | 61 arch/sh/drivers/pci/fixups-dreamcast.c | 85 arch/sh/drivers/pci/ops-bigsur.c | 88 arch/sh/drivers/pci/ops-dreamcast.c | 169 arch/sh/drivers/pci/ops-snapgear.c | 100 arch/sh/drivers/pci/pci-auto.c | 534 arch/sh/drivers/pci/pci-dma.c | 42 arch/sh/drivers/pci/pci-sh7751.c | 414 arch/sh/drivers/pci/pci-sh7751.h | 296 arch/sh/drivers/pci/pci-st40.c | 423 arch/sh/drivers/pci/pci-st40.h | 66 arch/sh/drivers/pci/pci.c | 153 arch/sh/kernel/Makefile | 6 arch/sh/kernel/cpu/Makefile | 3 arch/sh/kernel/cpu/init.c | 214 arch/sh/kernel/cpu/sh3/Makefile | 2 arch/sh/kernel/cpu/sh3/ex.S | 124 arch/sh/kernel/cpu/sh4/Makefile | 9 arch/sh/kernel/cpu/sh4/ex.S | 316 arch/sh/kernel/cpu/sh4/fpu.c | 21 arch/sh/kernel/cpu/sh4/sq.c | 484 arch/sh/kernel/entry.S | 441 arch/sh/kernel/head.S | 6 arch/sh/kernel/io.c | 185 arch/sh/kernel/irq.c | 114 arch/sh/kernel/kgdb_stub.c | 8 arch/sh/kernel/module.c | 4 arch/sh/kernel/process.c | 101 arch/sh/kernel/ptrace.c | 165 arch/sh/kernel/setup.c | 296 arch/sh/kernel/sh_bios.c | 2 arch/sh/kernel/sh_ksyms.c | 4 arch/sh/kernel/signal.c | 82 arch/sh/kernel/smp.c | 207 arch/sh/kernel/sys_sh.c | 40 arch/sh/kernel/time.c | 69 arch/sh/kernel/traps.c | 132 arch/sh/lib/Makefile | 3 arch/sh/lib/div64-generic.c | 19 arch/sh/lib/div64.S | 4 arch/sh/lib/udivdi3.c | 4 arch/sh/mm/Makefile | 10 arch/sh/mm/cache-sh3.c | 8 arch/sh/mm/cache-sh4.c | 79 arch/sh/mm/clear_page.S | 8 arch/sh/mm/copy_page.S | 8 arch/sh/mm/extable.c | 23 arch/sh/mm/fault.c | 58 arch/sh/mm/init.c | 106 arch/sh/mm/ioremap.c | 7 arch/sh/mm/pg-dma.c | 97 arch/sh/mm/pg-nommu.c | 36 arch/sh/mm/tlb-sh3.c | 12 arch/sh/oprofile/Kconfig | 23 arch/sh/oprofile/Makefile | 13 arch/sh/oprofile/op_model_null.c | 23 arch/sh/tools/mach-types | 2 arch/sparc/Kconfig | 1 arch/sparc/kernel/irq.c | 19 arch/sparc/mm/extable.c | 5 arch/sparc/mm/fault.c | 1 arch/sparc/mm/srmmu.c | 6 arch/sparc64/Kconfig | 17 arch/sparc64/defconfig | 6 arch/sparc64/kernel/head.S | 6 arch/sparc64/kernel/pci_common.c | 13 arch/sparc64/mm/extable.c | 5 arch/sparc64/prom/bootstr.c | 4 arch/um/Kconfig | 1 arch/x86_64/Kconfig | 1 arch/x86_64/mm/extable.c | 8 drivers/Kconfig | 2 drivers/acorn/char/i2c.c | 1 drivers/atm/atmdev_init.c | 6 drivers/atm/nicstar.c | 253 drivers/base/Makefile | 2 drivers/base/class.c | 14 drivers/base/class_simple.c | 201 drivers/base/core.c | 9 drivers/block/Kconfig | 2 drivers/block/as-iosched.c | 351 drivers/block/elevator.c | 1 drivers/block/floppy.c | 3 drivers/block/floppy98.c | 3 drivers/block/ll_rw_blk.c | 29 drivers/block/loop.c | 34 drivers/bluetooth/Kconfig | 47 drivers/bluetooth/Makefile | 2 drivers/bluetooth/bcm203x.c | 309 drivers/bluetooth/bfusb.c | 782 drivers/bluetooth/bluecard_cs.c | 42 drivers/bluetooth/bt3c_cs.c | 55 drivers/bluetooth/btuart_cs.c | 55 drivers/bluetooth/dtl1_cs.c | 53 drivers/bluetooth/hci_usb.c | 62 drivers/bluetooth/hci_usb.h | 9 drivers/cdrom/cdrom.c | 373 drivers/char/Kconfig | 2 drivers/char/efirtc.c | 1 drivers/char/genrtc.c | 107 drivers/char/hp600_keyb.c | 1 drivers/char/keyboard.c | 2 drivers/char/lp.c | 6 drivers/char/mem.c | 7 drivers/char/misc.c | 17 drivers/char/pcmcia/synclink_cs.c | 38 drivers/char/raw.c | 45 drivers/char/rtc.c | 3 drivers/char/sh-sci.c | 471 drivers/char/sh-sci.h | 56 drivers/char/sn_serial.c | 17 drivers/char/sysrq.c | 6 drivers/char/tty_io.c | 91 drivers/char/vt.c | 11 drivers/char/watchdog/acquirewdt.c | 48 drivers/char/watchdog/advantechwdt.c | 2 drivers/char/watchdog/alim1535_wdt.c | 4 drivers/char/watchdog/alim7101_wdt.c | 2 drivers/char/watchdog/amd7xx_tco.c | 83 drivers/char/watchdog/cpu5wdt.c | 34 drivers/char/watchdog/eurotechwdt.c | 94 drivers/char/watchdog/i810-tco.c | 38 drivers/char/watchdog/ib700wdt.c | 64 drivers/char/watchdog/indydog.c | 19 drivers/char/watchdog/machzwd.c | 148 drivers/char/watchdog/mixcomwd.c | 51 drivers/char/watchdog/pcwd.c | 79 drivers/char/watchdog/sa1100_wdt.c | 1 drivers/char/watchdog/sbc60xxwdt.c | 2 drivers/char/watchdog/sc1200wdt.c | 18 drivers/char/watchdog/scx200_wdt.c | 58 drivers/char/watchdog/shwdt.c | 14 drivers/char/watchdog/softdog.c | 29 drivers/char/watchdog/w83627hf_wdt.c | 2 drivers/char/watchdog/w83877f_wdt.c | 2 drivers/char/watchdog/wafer5823wdt.c | 4 drivers/char/watchdog/wdt.c | 119 drivers/char/watchdog/wdt285.c | 12 drivers/char/watchdog/wdt977.c | 15 drivers/char/watchdog/wdt_pci.c | 107 drivers/i2c/Kconfig | 32 drivers/i2c/algos/Kconfig | 1 drivers/i2c/algos/i2c-algo-pcf.h | 2 drivers/i2c/busses/Kconfig | 89 drivers/i2c/busses/Makefile | 2 drivers/i2c/busses/i2c-ali1535.c | 5 drivers/i2c/busses/i2c-ali15x3.c | 5 drivers/i2c/busses/i2c-amd756.c | 5 drivers/i2c/busses/i2c-amd8111.c | 5 drivers/i2c/busses/i2c-elektor.c | 19 drivers/i2c/busses/i2c-elv.c | 17 drivers/i2c/busses/i2c-frodo.c | 5 drivers/i2c/busses/i2c-i801.c | 5 drivers/i2c/busses/i2c-i810.c | 5 drivers/i2c/busses/i2c-ibm_iic.c | 8 drivers/i2c/busses/i2c-iop3xx.c | 9 drivers/i2c/busses/i2c-isa.c | 5 drivers/i2c/busses/i2c-ite.c | 24 drivers/i2c/busses/i2c-keywest.c | 36 drivers/i2c/busses/i2c-nforce2.c | 5 drivers/i2c/busses/i2c-parport-light.c | 179 drivers/i2c/busses/i2c-parport.c | 271 drivers/i2c/busses/i2c-parport.h | 87 drivers/i2c/busses/i2c-philips-par.c | 7 drivers/i2c/busses/i2c-piix4.c | 12 drivers/i2c/busses/i2c-prosavage.c | 5 drivers/i2c/busses/i2c-rpx.c | 9 drivers/i2c/busses/i2c-savage4.c | 5 drivers/i2c/busses/i2c-sis5595.c | 10 drivers/i2c/busses/i2c-sis630.c | 5 drivers/i2c/busses/i2c-sis96x.c | 5 drivers/i2c/busses/i2c-velleman.c | 12 drivers/i2c/busses/i2c-via.c | 5 drivers/i2c/busses/i2c-viapro.c | 5 drivers/i2c/busses/i2c-voodoo3.c | 5 drivers/i2c/busses/scx200_acb.c | 15 drivers/i2c/busses/scx200_i2c.c | 10 drivers/i2c/chips/Kconfig | 36 drivers/i2c/chips/Makefile | 5 drivers/i2c/chips/adm1021.c | 5 drivers/i2c/chips/asb100.c | 1055 drivers/i2c/chips/eeprom.c | 67 drivers/i2c/chips/it87.c | 13 drivers/i2c/chips/lm75.c | 5 drivers/i2c/chips/lm78.c | 7 drivers/i2c/chips/lm83.c | 7 drivers/i2c/chips/lm85.c | 5 drivers/i2c/chips/lm90.c | 525 drivers/i2c/chips/via686a.c | 5 drivers/i2c/chips/w83781d.c | 37 drivers/i2c/chips/w83l785ts.c | 314 drivers/i2c/i2c-core.c | 112 drivers/i2c/i2c-dev.c | 10 drivers/i2c/i2c-sensor.c | 5 drivers/ide/Kconfig | 24 drivers/ide/ide-cd.c | 215 drivers/ide/ide-cd.h | 11 drivers/ide/ide-disk.c | 39 drivers/ide/ide-taskfile.c | 25 drivers/ide/ide.c | 6 drivers/ide/legacy/buddha.c | 4 drivers/ide/legacy/gayle.c | 25 drivers/ide/legacy/ide-cs.c | 57 drivers/ide/legacy/pdc4030.c | 18 drivers/ide/pci/pdc202xx_old.c | 71 drivers/ide/pci/sgiioc4.c | 23 drivers/ide/pci/siimage.c | 21 drivers/ieee1394/Kconfig | 9 drivers/ieee1394/amdtp.c | 32 drivers/ieee1394/cmp.c | 38 drivers/ieee1394/csr.c | 93 drivers/ieee1394/dv1394.c | 43 drivers/ieee1394/eth1394.c | 43 drivers/ieee1394/highlevel.c | 146 drivers/ieee1394/highlevel.h | 23 drivers/ieee1394/hosts.c | 2 drivers/ieee1394/hosts.h | 2 drivers/ieee1394/ieee1394_core.c | 184 drivers/ieee1394/ieee1394_core.h | 32 drivers/ieee1394/ohci1394.c | 49 drivers/ieee1394/oui.db | 2927 +- drivers/ieee1394/raw1394.c | 24 drivers/ieee1394/sbp2.c | 25 drivers/ieee1394/video1394.c | 57 drivers/input/evdev.c | 4 drivers/input/input.c | 8 drivers/input/joydev.c | 4 drivers/input/keyboard/atkbd.c | 38 drivers/input/keyboard/maple_keyb.c | 1 drivers/input/keyboard/newtonkbd.c | 2 drivers/input/mouse/98busmouse.c | 21 drivers/input/mouse/Kconfig | 2 drivers/input/mouse/inport.c | 19 drivers/input/mouse/logibm.c | 17 drivers/input/mouse/psmouse-base.c | 30 drivers/input/mouse/synaptics.c | 11 drivers/input/mousedev.c | 117 drivers/input/serio/i8042.c | 100 drivers/input/tsdev.c | 27 drivers/isdn/Makefile | 1 drivers/isdn/hardware/Kconfig | 2 drivers/isdn/hardware/avm/avm_cs.c | 56 drivers/isdn/hardware/eicon/capifunc.c | 4 drivers/isdn/hardware/eicon/divamnt.c | 10 drivers/isdn/hardware/eicon/mntfunc.c | 15 drivers/isdn/hardware/eicon/platform.h | 4 drivers/isdn/hardware/eicon/s_bri.c | 2 drivers/isdn/hardware/eicon/um_idi.c | 4 drivers/isdn/hardware/eicon/xdi_adapter.h | 4 drivers/isdn/hisax/avma1_cs.c | 56 drivers/isdn/hisax/elsa_cs.c | 48 drivers/isdn/hisax/sedlbauer_cs.c | 57 drivers/macintosh/adb-iop.c | 34 drivers/macintosh/via-macii.c | 2 drivers/media/Kconfig | 17 drivers/media/common/Makefile | 2 drivers/media/common/ir-common.c | 218 drivers/media/video/Kconfig | 13 drivers/media/video/Makefile | 5 drivers/media/video/bt848.h | 3 drivers/media/video/bttv-cards.c | 582 drivers/media/video/bttv-driver.c | 468 drivers/media/video/bttv-gpio.c | 183 drivers/media/video/bttv-i2c.c | 471 drivers/media/video/bttv-if.c | 447 drivers/media/video/bttv-risc.c | 43 drivers/media/video/bttv-vbi.c | 4 drivers/media/video/bttv.h | 66 drivers/media/video/bttvp.h | 51 drivers/media/video/cx88/Makefile | 6 drivers/media/video/cx88/cx88-cards.c | 396 drivers/media/video/cx88/cx88-core.c | 612 drivers/media/video/cx88/cx88-i2c.c | 172 drivers/media/video/cx88/cx88-reg.h | 770 drivers/media/video/cx88/cx88-tvaudio.c | 472 drivers/media/video/cx88/cx88-video.c | 2246 + drivers/media/video/cx88/cx88.h | 339 drivers/media/video/ir-kbd-gpio.c | 379 drivers/media/video/ir-kbd-i2c.c | 372 drivers/media/video/msp3400.c | 38 drivers/media/video/saa7134/Makefile | 2 drivers/media/video/saa7134/saa6752hs.c | 21 drivers/media/video/saa7134/saa7134-cards.c | 392 drivers/media/video/saa7134/saa7134-core.c | 29 drivers/media/video/saa7134/saa7134-input.c | 218 drivers/media/video/saa7134/saa7134-oss.c | 11 drivers/media/video/saa7134/saa7134-ts.c | 6 drivers/media/video/saa7134/saa7134-tvaudio.c | 116 drivers/media/video/saa7134/saa7134-vbi.c | 2 drivers/media/video/saa7134/saa7134-video.c | 66 drivers/media/video/saa7134/saa7134.h | 33 drivers/media/video/saa7146.h | 1 drivers/media/video/tda7432.c | 5 drivers/media/video/tda9875.c | 5 drivers/media/video/tda9887.c | 18 drivers/media/video/tuner.c | 539 drivers/media/video/tvaudio.c | 18 drivers/media/video/tvmixer.c | 27 drivers/media/video/v4l1-compat.c | 43 drivers/media/video/v4l2-common.c | 74 drivers/media/video/video-buf.c | 65 drivers/media/video/videodev.c | 33 drivers/message/fusion/mptbase.h | 4 drivers/message/fusion/mptscsih.c | 4 drivers/mtd/maps/pcmciamtd.c | 35 drivers/net/3c527.c | 382 drivers/net/3c527.h | 6 drivers/net/3c59x.c | 4 drivers/net/Kconfig | 23 drivers/net/Makefile | 1 drivers/net/dummy.c | 42 drivers/net/forcedeth.c | 1501 + drivers/net/hamradio/bpqether.c | 25 drivers/net/irda/sir-dev.h | 1 drivers/net/irda/sir_dev.c | 62 drivers/net/irda/sir_kthread.c | 9 drivers/net/natsemi.c | 39 drivers/net/ne2k-pci.c | 3 drivers/net/pcmcia/3c574_cs.c | 40 drivers/net/pcmcia/3c589_cs.c | 38 drivers/net/pcmcia/Kconfig | 2 drivers/net/pcmcia/axnet_cs.c | 49 drivers/net/pcmcia/com20020_cs.c | 32 drivers/net/pcmcia/fmvj18x_cs.c | 76 drivers/net/pcmcia/ibmtr_cs.c | 46 drivers/net/pcmcia/nmclan_cs.c | 42 drivers/net/pcmcia/pcnet_cs.c | 69 drivers/net/pcmcia/smc91c92_cs.c | 75 drivers/net/pcmcia/xirc2ps_cs.c | 66 drivers/net/ppp_async.c | 104 drivers/net/pppoe.c | 6 drivers/net/sk98lin/Makefile | 2 drivers/net/sk98lin/h/skcsum.h | 12 drivers/net/sk98lin/h/skdrv1st.h | 30 drivers/net/sk98lin/h/skdrv2nd.h | 57 drivers/net/sk98lin/h/skgehw.h | 210 drivers/net/sk98lin/h/skgehwt.h | 23 drivers/net/sk98lin/h/skgei2c.h | 81 drivers/net/sk98lin/h/skgeinit.h | 54 drivers/net/sk98lin/h/skgepnmi.h | 63 drivers/net/sk98lin/h/ski2c.h | 28 drivers/net/sk98lin/h/skqueue.h | 29 drivers/net/sk98lin/h/sktimer.h | 39 drivers/net/sk98lin/h/sktypes.h | 10 drivers/net/sk98lin/h/skversion.h | 21 drivers/net/sk98lin/h/xmac_ii.h | 122 drivers/net/sk98lin/skcsum.c | 14 drivers/net/sk98lin/skdim.c | 20 drivers/net/sk98lin/skge.c | 972 drivers/net/sk98lin/skgehwt.c | 86 drivers/net/sk98lin/skgeinit.c | 86 drivers/net/sk98lin/skgemib.c | 54 drivers/net/sk98lin/skgepnmi.c | 371 drivers/net/sk98lin/skgesirq.c | 87 drivers/net/sk98lin/ski2c.c | 126 drivers/net/sk98lin/sklm80.c | 35 drivers/net/sk98lin/skproc.c | 569 drivers/net/sk98lin/skqueue.c | 121 drivers/net/sk98lin/sktimer.c | 153 drivers/net/sk98lin/skxmac2.c | 637 drivers/net/starfire.c | 1 drivers/net/stnic.c | 6 drivers/net/tokenring/olympic.c | 9 drivers/net/tokenring/smctr.c | 8 drivers/net/wan/Kconfig | 15 drivers/net/wan/Makefile | 1 drivers/net/wan/farsync.c | 3 drivers/net/wan/hd64572.h | 92 drivers/net/wan/lapbether.c | 10 drivers/net/wan/pc300_drv.c | 2 drivers/net/wan/pci200syn.c | 475 drivers/net/wireless/Kconfig | 2 drivers/net/wireless/airo.c | 13 drivers/net/wireless/airo_cs.c | 52 drivers/net/wireless/atmel.c | 523 drivers/net/wireless/atmel_cs.c | 84 drivers/net/wireless/netwave_cs.c | 37 drivers/net/wireless/orinoco_cs.c | 54 drivers/net/wireless/orinoco_pci.c | 1 drivers/net/wireless/ray_cs.c | 32 drivers/net/wireless/wavelan_cs.c | 41 drivers/net/wireless/wl3501_cs.c | 31 drivers/oprofile/oprofile_stats.c | 1 drivers/parport/parport_cs.c | 45 drivers/pci/pci.ids | 2 drivers/pci/quirks.c | 1 drivers/pcmcia/cs.c | 144 drivers/s390/block/dasd.c | 255 drivers/s390/block/dasd_3990_erp.c | 8 drivers/s390/block/dasd_devmap.c | 233 drivers/s390/block/dasd_diag.c | 4 drivers/s390/block/dasd_eckd.c | 43 drivers/s390/block/dasd_fba.c | 7 drivers/s390/block/dasd_genhd.c | 21 drivers/s390/block/dasd_int.h | 11 drivers/s390/block/dasd_proc.c | 11 drivers/s390/char/Makefile | 12 drivers/s390/char/con3215.c | 92 drivers/s390/char/con3270.c | 639 drivers/s390/char/defkeymap.c | 156 drivers/s390/char/defkeymap.map | 191 drivers/s390/char/fs3270.c | 373 drivers/s390/char/keyboard.c | 516 drivers/s390/char/keyboard.h | 57 drivers/s390/char/raw3270.c | 1256 drivers/s390/char/raw3270.h | 273 drivers/s390/char/sclp_con.c | 4 drivers/s390/char/sclp_rw.c | 16 drivers/s390/char/sclp_rw.h | 2 drivers/s390/char/sclp_tty.c | 38 drivers/s390/char/tape.h | 90 drivers/s390/char/tape_34xx.c | 657 drivers/s390/char/tape_block.c | 453 drivers/s390/char/tape_char.c | 173 drivers/s390/char/tape_core.c | 496 drivers/s390/char/tape_proc.c | 14 drivers/s390/char/tape_std.c | 225 drivers/s390/char/tape_std.h | 12 drivers/s390/char/tty3270.c | 1828 + drivers/s390/cio/blacklist.c | 122 drivers/s390/cio/ccwgroup.c | 16 drivers/s390/cio/chsc.c | 476 drivers/s390/cio/chsc.h | 12 drivers/s390/cio/cio.c | 92 drivers/s390/cio/cio.h | 7 drivers/s390/cio/css.c | 301 drivers/s390/cio/css.h | 15 drivers/s390/cio/device.c | 183 drivers/s390/cio/device.h | 8 drivers/s390/cio/device_fsm.c | 390 drivers/s390/cio/device_id.c | 45 drivers/s390/cio/device_ops.c | 43 drivers/s390/cio/device_pgid.c | 105 drivers/s390/cio/device_status.c | 7 drivers/s390/cio/qdio.c | 107 drivers/s390/cio/qdio.h | 18 drivers/s390/net/ctcmain.c | 18 drivers/s390/net/ctctty.c | 3 drivers/s390/net/cu3088.c | 25 drivers/s390/net/fsm.c | 6 drivers/s390/net/iucv.c | 37 drivers/s390/net/iucv.h | 2 drivers/s390/net/lcs.c | 17 drivers/s390/net/netiucv.c | 16 drivers/s390/net/qeth.c | 226 drivers/s390/net/qeth.h | 12 drivers/s390/net/qeth_mpc.h | 8 drivers/s390/s390mach.c | 26 drivers/s390/scsi/zfcp_aux.c | 206 drivers/s390/scsi/zfcp_ccw.c | 14 drivers/s390/scsi/zfcp_def.h | 22 drivers/s390/scsi/zfcp_erp.c | 132 drivers/s390/scsi/zfcp_ext.h | 10 drivers/s390/scsi/zfcp_fsf.c | 122 drivers/s390/scsi/zfcp_fsf.h | 3 drivers/s390/scsi/zfcp_qdio.c | 52 drivers/s390/scsi/zfcp_scsi.c | 228 drivers/s390/scsi/zfcp_sysfs_adapter.c | 12 drivers/s390/scsi/zfcp_sysfs_port.c | 28 drivers/s390/scsi/zfcp_sysfs_unit.c | 14 drivers/sbus/char/rtc.c | 1 drivers/scsi/53c7xx.c | 4 drivers/scsi/53c7xx.h | 4 drivers/scsi/Kconfig | 49 drivers/scsi/Makefile | 6 drivers/scsi/NCR53C9x.h | 3 drivers/scsi/aacraid/aachba.c | 1 drivers/scsi/aha152x.c | 83 drivers/scsi/aic7xxx/aic79xx_osm.c | 12 drivers/scsi/aic7xxx/aic7xxx_osm.c | 12 drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 5 drivers/scsi/aic7xxx_old/aic7xxx_proc.c | 4 drivers/scsi/amiga7xx.c | 155 drivers/scsi/atp870u.c | 669 drivers/scsi/atp870u.h | 54 drivers/scsi/bvme6000.c | 7 drivers/scsi/g_NCR5380.c | 9 drivers/scsi/ini9100u.c | 12 drivers/scsi/inia100.c | 36 drivers/scsi/ips.c | 178 drivers/scsi/ips.h | 34 drivers/scsi/mac_esp.c | 121 drivers/scsi/mac_scsi.c | 102 drivers/scsi/mvme16x.c | 3 drivers/scsi/nsp32.h | 5 drivers/scsi/nsp32_io.h | 10 drivers/scsi/pcmcia/aha152x_stub.c | 42 drivers/scsi/pcmcia/fdomain_stub.c | 42 drivers/scsi/pcmcia/nsp_cs.c | 58 drivers/scsi/pcmcia/nsp_cs.h | 2 drivers/scsi/pcmcia/qlogic_stub.c | 44 drivers/scsi/qla1280.c | 1596 - drivers/scsi/qla1280.h | 127 drivers/scsi/qla2xxx/Kconfig | 29 drivers/scsi/qla2xxx/Makefile | 12 drivers/scsi/qla2xxx/ql2100.c | 92 drivers/scsi/qla2xxx/ql2100_fw.c | 4858 +++ drivers/scsi/qla2xxx/ql2200.c | 92 drivers/scsi/qla2xxx/ql2200_fw.c | 5321 ++++ drivers/scsi/qla2xxx/ql2300.c | 161 drivers/scsi/qla2xxx/ql2300_fw.c | 6695 +++++ drivers/scsi/qla2xxx/qla_dbg.c | 1229 drivers/scsi/qla2xxx/qla_dbg.h | 229 drivers/scsi/qla2xxx/qla_def.h | 2371 + drivers/scsi/qla2xxx/qla_devtbl.h | 65 drivers/scsi/qla2xxx/qla_gbl.h | 327 drivers/scsi/qla2xxx/qla_gs.c | 681 drivers/scsi/qla2xxx/qla_init.c | 4260 +++ drivers/scsi/qla2xxx/qla_inline.h | 242 drivers/scsi/qla2xxx/qla_iocb.c | 764 drivers/scsi/qla2xxx/qla_isr.c | 1421 + drivers/scsi/qla2xxx/qla_listops.h | 351 drivers/scsi/qla2xxx/qla_mbx.c | 2778 ++ drivers/scsi/qla2xxx/qla_os.c | 4602 +++ drivers/scsi/qla2xxx/qla_os.h | 93 drivers/scsi/qla2xxx/qla_rscn.c | 1458 + drivers/scsi/qla2xxx/qla_settings.h | 66 drivers/scsi/qla2xxx/qla_sup.c | 680 drivers/scsi/qla2xxx/qla_version.h | 27 drivers/scsi/qlogicpti.c | 61 drivers/scsi/qlogicpti.h | 1 drivers/scsi/scsi.c | 17 drivers/scsi/scsi_error.c | 30 drivers/scsi/scsi_scan.c | 5 drivers/scsi/scsi_sysfs.c | 11 drivers/scsi/sr.c | 24 drivers/scsi/sym53c8xx_2/sym_glue.c | 2 drivers/scsi/sym53c8xx_2/sym_hipd.c | 22 drivers/scsi/sym53c8xx_2/sym_misc.c | 1 drivers/serial/8250_acpi.c | 67 drivers/serial/8250_hcdp.c | 2 drivers/serial/8250_pnp.c | 2 drivers/serial/Kconfig | 18 drivers/serial/serial_cs.c | 77 drivers/telephony/ixj_pcmcia.c | 45 drivers/video/Kconfig | 21 drivers/video/Makefile | 1 drivers/video/cirrusfb.c | 2 drivers/video/console/Kconfig | 3 drivers/video/fbmem.c | 6 drivers/video/kyro/Makefile | 13 drivers/video/kyro/STG4000InitDevice.c | 326 drivers/video/kyro/STG4000Interface.h | 60 drivers/video/kyro/STG4000OverlayDevice.c | 600 drivers/video/kyro/STG4000Ramdac.c | 164 drivers/video/kyro/STG4000Reg.h | 283 drivers/video/kyro/STG4000VTG.c | 170 drivers/video/kyro/fbdev.c | 808 drivers/video/macfb.c | 2 drivers/video/pvr2fb.c | 606 drivers/video/radeonfb.c | 32 drivers/video/tridentfb.c | 2 drivers/zorro/Makefile | 2 drivers/zorro/proc.c | 21 drivers/zorro/zorro-driver.c | 150 drivers/zorro/zorro-sysfs.c | 98 drivers/zorro/zorro.c | 95 drivers/zorro/zorro.h | 4 fs/afs/callback.c | 44 fs/afs/cell.c | 235 fs/afs/cell.h | 2 fs/afs/cmservice.c | 125 fs/afs/cmservice.h | 8 fs/afs/dir.c | 292 fs/afs/file.c | 74 fs/afs/fsclient.c | 315 fs/afs/fsclient.h | 31 fs/afs/inode.c | 20 fs/afs/internal.h | 30 fs/afs/kafsasyncd.c | 62 fs/afs/kafsasyncd.h | 17 fs/afs/kafstimod.c | 53 fs/afs/kafstimod.h | 10 fs/afs/main.c | 65 fs/afs/mntpt.c | 51 fs/afs/proc.c | 365 fs/afs/server.c | 150 fs/afs/server.h | 27 fs/afs/super.c | 22 fs/afs/types.h | 24 fs/afs/vlclient.c | 223 fs/afs/vlclient.h | 10 fs/afs/vlocation.c | 289 fs/afs/vnode.c | 125 fs/afs/vnode.h | 13 fs/afs/volume.c | 131 fs/binfmt_elf.c | 4 fs/bio.c | 6 fs/block_dev.c | 115 fs/buffer.c | 48 fs/coda/file.c | 1 fs/compat_ioctl.c | 537 fs/cramfs/inode.c | 50 fs/devfs/base.c | 18 fs/dnotify.c | 1 fs/eventpoll.c | 1 fs/exec.c | 10 fs/ext2/balloc.c | 6 fs/ext2/ialloc.c | 27 fs/ext2/inode.c | 2 fs/ext2/super.c | 1 fs/ext3/ialloc.c | 6 fs/ext3/inode.c | 2 fs/ext3/super.c | 3 fs/fcntl.c | 16 fs/file_table.c | 1 fs/freevxfs/vxfs_super.c | 2 fs/fs-writeback.c | 8 fs/hugetlbfs/inode.c | 1 fs/intermezzo/file.c | 2 fs/intermezzo/intermezzo_fs.h | 2 fs/intermezzo/journal.c | 4 fs/intermezzo/presto.c | 5 fs/intermezzo/vfs.c | 9 fs/ioctl.c | 2 fs/jbd/transaction.c | 4 fs/jffs/intrep.c | 6 fs/jfs/inode.c | 2 fs/jfs/super.c | 23 fs/jfs/xattr.c | 7 fs/libfs.c | 1 fs/locks.c | 4 fs/nfs/dir.c | 15 fs/nfs/file.c | 10 fs/nfs/inode.c | 9 fs/nfs/write.c | 23 fs/nfsd/nfsfh.c | 24 fs/nfsd/nfsxdr.c | 11 fs/nfsd/vfs.c | 12 fs/ntfs/ChangeLog | 8 fs/ntfs/Makefile | 2 fs/ntfs/inode.c | 4 fs/open.c | 7 fs/pipe.c | 1 fs/proc/base.c | 25 fs/proc/proc_devtree.c | 39 fs/proc/proc_misc.c | 6 fs/proc/task_mmu.c | 26 fs/read_write.c | 2 fs/reiserfs/file.c | 6 fs/reiserfs/inode.c | 2 fs/reiserfs/journal.c | 9 fs/xfs/Makefile | 47 fs/xfs/linux/xfs_aops.c | 229 fs/xfs/linux/xfs_file.c | 6 fs/xfs/linux/xfs_globals.c | 74 fs/xfs/linux/xfs_ioctl.c | 2 fs/xfs/linux/xfs_iomap.c | 122 fs/xfs/linux/xfs_iops.c | 247 fs/xfs/linux/xfs_iops.h | 29 fs/xfs/linux/xfs_linux.h | 18 fs/xfs/linux/xfs_lrw.c | 134 fs/xfs/linux/xfs_lrw.h | 52 fs/xfs/linux/xfs_super.c | 30 fs/xfs/linux/xfs_super.h | 12 fs/xfs/linux/xfs_sysctl.c | 2 fs/xfs/linux/xfs_version.h | 2 fs/xfs/linux/xfs_vfs.c | 2 fs/xfs/linux/xfs_vfs.h | 11 fs/xfs/linux/xfs_vnode.c | 11 fs/xfs/linux/xfs_vnode.h | 42 fs/xfs/pagebuf/page_buf.c | 316 fs/xfs/pagebuf/page_buf.h | 88 fs/xfs/quota/xfs_dquot.c | 46 fs/xfs/quota/xfs_dquot.h | 14 fs/xfs/quota/xfs_qm.c | 47 fs/xfs/quota/xfs_qm_syscalls.c | 5 fs/xfs/quota/xfs_trans_dquot.c | 7 fs/xfs/support/debug.h | 4 fs/xfs/support/kmem.h | 21 fs/xfs/support/ktrace.c | 33 fs/xfs/support/ktrace.h | 20 fs/xfs/support/qsort.c | 372 fs/xfs/xfs_acl.h | 4 fs/xfs/xfs_alloc.c | 11 fs/xfs/xfs_alloc.h | 24 fs/xfs/xfs_arch.h | 6 fs/xfs/xfs_attr.c | 319 fs/xfs/xfs_attr.h | 53 fs/xfs/xfs_attr_leaf.c | 53 fs/xfs/xfs_attr_leaf.h | 8 fs/xfs/xfs_attr_sf.h | 12 fs/xfs/xfs_bmap.c | 45 fs/xfs/xfs_bmap.h | 63 fs/xfs/xfs_bmap_btree.c | 12 fs/xfs/xfs_bmap_btree.h | 15 fs/xfs/xfs_buf.h | 21 fs/xfs/xfs_buf_item.c | 9 fs/xfs/xfs_buf_item.h | 28 fs/xfs/xfs_da_btree.c | 7 fs/xfs/xfs_dfrag.c | 4 fs/xfs/xfs_dir.c | 99 fs/xfs/xfs_dir.h | 8 fs/xfs/xfs_dir2_trace.c | 119 fs/xfs/xfs_dir2_trace.h | 15 fs/xfs/xfs_dir_sf.h | 20 fs/xfs/xfs_dmapi.h | 8 fs/xfs/xfs_dmops.c | 3 fs/xfs/xfs_error.c | 14 fs/xfs/xfs_fsops.c | 4 fs/xfs/xfs_iget.c | 14 fs/xfs/xfs_inode.c | 62 fs/xfs/xfs_inode.h | 31 fs/xfs/xfs_iocore.c | 1 fs/xfs/xfs_iomap.h | 107 fs/xfs/xfs_itable.c | 50 fs/xfs/xfs_itable.h | 10 fs/xfs/xfs_log.c | 46 fs/xfs/xfs_log.h | 4 fs/xfs/xfs_log_priv.h | 13 fs/xfs/xfs_mount.c | 2 fs/xfs/xfs_qmops.c | 2 fs/xfs/xfs_refcache.h | 66 fs/xfs/xfs_rename.c | 10 fs/xfs/xfs_rw.c | 56 fs/xfs/xfs_rw.h | 55 fs/xfs/xfs_trans.c | 2 fs/xfs/xfs_vfsops.c | 54 fs/xfs/xfs_vnodeops.c | 49 include/asm-alpha/processor.h | 11 include/asm-alpha/smp.h | 2 include/asm-alpha/socket.h | 2 include/asm-alpha/topology.h | 3 include/asm-arm/arch-ebsa285/io.h | 6 include/asm-arm/arch-nexuspci/io.h | 3 include/asm-arm/socket.h | 2 include/asm-arm26/socket.h | 2 include/asm-cris/arch-v10/byteorder.h | 5 include/asm-cris/socket.h | 2 include/asm-generic/percpu.h | 2 include/asm-generic/pgtable.h | 65 include/asm-h8300/socket.h | 2 include/asm-i386/byteorder.h | 20 include/asm-i386/genapic.h | 2 include/asm-i386/hpet.h | 4 include/asm-i386/mach-bigsmp/mach_apic.h | 5 include/asm-i386/mach-default/mach_apic.h | 5 include/asm-i386/mach-es7000/mach_apic.h | 5 include/asm-i386/mach-generic/mach_apic.h | 1 include/asm-i386/mach-numaq/mach_apic.h | 6 include/asm-i386/mach-summit/mach_apic.h | 11 include/asm-i386/mach-visws/mach_apic.h | 6 include/asm-i386/pgtable.h | 8 include/asm-i386/smp.h | 3 include/asm-i386/socket.h | 2 include/asm-ia64/acpi.h | 3 include/asm-ia64/asmmacro.h | 13 include/asm-ia64/byteorder.h | 7 include/asm-ia64/mmzone.h | 2 include/asm-ia64/numa.h | 1 include/asm-ia64/page.h | 2 include/asm-ia64/pgtable.h | 8 include/asm-ia64/smp.h | 2 include/asm-ia64/sn/addrs.h | 20 include/asm-ia64/sn/alenlist.h | 3 include/asm-ia64/sn/arch.h | 3 include/asm-ia64/sn/bte.h | 55 include/asm-ia64/sn/cdl.h | 5 include/asm-ia64/sn/clksupport.h | 3 include/asm-ia64/sn/dmamap.h | 29 include/asm-ia64/sn/driver.h | 3 include/asm-ia64/sn/geo.h | 9 include/asm-ia64/sn/hcl.h | 42 include/asm-ia64/sn/hcl_util.h | 5 include/asm-ia64/sn/hwgfs.h | 6 include/asm-ia64/sn/intr.h | 3 include/asm-ia64/sn/io.h | 4 include/asm-ia64/sn/ioc4.h | 29 include/asm-ia64/sn/ioconfig_bus.h | 39 include/asm-ia64/sn/ioerror.h | 7 include/asm-ia64/sn/ioerror_handling.h | 54 include/asm-ia64/sn/iograph.h | 80 include/asm-ia64/sn/klconfig.h | 366 include/asm-ia64/sn/ksys/elsc.h | 9 include/asm-ia64/sn/ksys/l1.h | 37 include/asm-ia64/sn/labelcl.h | 17 include/asm-ia64/sn/module.h | 4 include/asm-ia64/sn/nodepda.h | 3 include/asm-ia64/sn/pci/bridge.h | 16 include/asm-ia64/sn/pci/pci_bus_cvlink.h | 14 include/asm-ia64/sn/pci/pci_defs.h | 191 include/asm-ia64/sn/pci/pcibr.h | 26 include/asm-ia64/sn/pci/pcibr_private.h | 125 include/asm-ia64/sn/pci/pciio.h | 74 include/asm-ia64/sn/pci/pciio_private.h | 29 include/asm-ia64/sn/pci/pic.h | 1437 - include/asm-ia64/sn/pda.h | 2 include/asm-ia64/sn/pio.h | 7 include/asm-ia64/sn/prio.h | 3 include/asm-ia64/sn/router.h | 3 include/asm-ia64/sn/sgi.h | 124 include/asm-ia64/sn/slotnum.h | 3 include/asm-ia64/sn/sn2/addrs.h | 15 include/asm-ia64/sn/sn2/arch.h | 5 include/asm-ia64/sn/sn2/geo.h | 9 include/asm-ia64/sn/sn2/intr.h | 3 include/asm-ia64/sn/sn2/shub.h | 1 include/asm-ia64/sn/sn2/shub_md.h | 7 include/asm-ia64/sn/sn2/shubio.h | 12 include/asm-ia64/sn/sn2/sn_private.h | 85 include/asm-ia64/sn/sn_fru.h | 3 include/asm-ia64/sn/sn_private.h | 3 include/asm-ia64/sn/sn_sal.h | 43 include/asm-ia64/sn/sndrv.h | 32 include/asm-ia64/sn/vector.h | 3 include/asm-ia64/sn/xtalk/xbow.h | 227 include/asm-ia64/sn/xtalk/xbow_info.h | 55 include/asm-ia64/sn/xtalk/xswitch.h | 9 include/asm-ia64/sn/xtalk/xtalk.h | 26 include/asm-ia64/sn/xtalk/xtalk_private.h | 15 include/asm-ia64/sn/xtalk/xtalkaddrs.h | 9 include/asm-ia64/sn/xtalk/xwidget.h | 83 include/asm-ia64/socket.h | 2 include/asm-m68k/atariints.h | 8 include/asm-m68k/bitops.h | 70 include/asm-m68k/byteorder.h | 3 include/asm-m68k/cacheflush.h | 8 include/asm-m68k/delay.h | 5 include/asm-m68k/dvma.h | 3 include/asm-m68k/io.h | 8 include/asm-m68k/mac_psc.h | 12 include/asm-m68k/mac_via.h | 3 include/asm-m68k/mmu_context.h | 12 include/asm-m68k/motorola_pgtable.h | 71 include/asm-m68k/nubus.h | 8 include/asm-m68k/page.h | 2 include/asm-m68k/pci.h | 4 include/asm-m68k/pgtable.h | 6 include/asm-m68k/processor.h | 17 include/asm-m68k/sbus.h | 6 include/asm-m68k/semaphore.h | 10 include/asm-m68k/signal.h | 10 include/asm-m68k/socket.h | 2 include/asm-m68k/string.h | 5 include/asm-m68k/sun3_pgtable.h | 79 include/asm-m68k/sun3mmu.h | 14 include/asm-m68k/system.h | 4 include/asm-m68k/thread_info.h | 2 include/asm-m68k/tlbflush.h | 4 include/asm-m68k/uaccess.h | 2 include/asm-m68k/virtconvert.h | 4 include/asm-m68k/zorro.h | 16 include/asm-m68knommu/types.h | 67 include/asm-mips/dma-mapping.h | 12 include/asm-mips/pci.h | 3 include/asm-mips/smp.h | 2 include/asm-mips/socket.h | 2 include/asm-parisc/byteorder.h | 11 include/asm-parisc/mmu_context.h | 5 include/asm-parisc/pgtable.h | 8 include/asm-parisc/smp.h | 2 include/asm-parisc/socket.h | 2 include/asm-parisc/tlbflush.h | 2 include/asm-ppc/byteorder.h | 5 include/asm-ppc/highmem.h | 9 include/asm-ppc/ibm4xx.h | 3 include/asm-ppc/mpc8260.h | 34 include/asm-ppc/pci.h | 9 include/asm-ppc/pgtable.h | 9 include/asm-ppc/smp.h | 1 include/asm-ppc/socket.h | 2 include/asm-ppc/uaccess.h | 2 include/asm-ppc/unistd.h | 3 include/asm-ppc64/byteorder.h | 7 include/asm-ppc64/compat.h | 6 include/asm-ppc64/cputable.h | 35 include/asm-ppc64/elf.h | 110 include/asm-ppc64/hvcall.h | 58 include/asm-ppc64/iSeries/HvCall.h | 18 include/asm-ppc64/iSeries/HvCallCfg.h | 14 include/asm-ppc64/iSeries/HvCallEvent.h | 238 include/asm-ppc64/iSeries/HvCallHpt.h | 24 include/asm-ppc64/iSeries/HvCallPci.h | 78 include/asm-ppc64/iSeries/HvCallSc.h | 7 include/asm-ppc64/iSeries/HvCallSm.h | 14 include/asm-ppc64/iSeries/HvCallXm.h | 19 include/asm-ppc64/iSeries/HvLpConfig.h | 20 include/asm-ppc64/iSeries/HvLpEvent.h | 3 include/asm-ppc64/iSeries/HvReleaseData.h | 14 include/asm-ppc64/iSeries/HvTypes.h | 12 include/asm-ppc64/iSeries/IoHriProcessorVpd.h | 10 include/asm-ppc64/iSeries/ItExtVpdPanel.h | 8 include/asm-ppc64/iSeries/ItIplParmsReal.h | 12 include/asm-ppc64/iSeries/ItLpNaca.h | 8 include/asm-ppc64/iSeries/ItLpPaca.h | 16 include/asm-ppc64/iSeries/ItLpQueue.h | 13 include/asm-ppc64/iSeries/ItLpRegSave.h | 8 include/asm-ppc64/iSeries/ItVpdAreas.h | 12 include/asm-ppc64/iSeries/LparMap.h | 7 include/asm-ppc64/iSeries/iSeries_dma.h | 4 include/asm-ppc64/iSeries/iSeries_io.h | 10 include/asm-ppc64/iSeries/iSeries_irq.h | 8 include/asm-ppc64/iSeries/iSeries_pci.h | 108 include/asm-ppc64/iSeries/iSeries_proc.h | 7 include/asm-ppc64/iSeries/mf.h | 51 include/asm-ppc64/iSeries/vio.h | 129 include/asm-ppc64/io.h | 4 include/asm-ppc64/irq.h | 5 include/asm-ppc64/machdep.h | 12 include/asm-ppc64/memory.h | 25 include/asm-ppc64/mmu.h | 56 include/asm-ppc64/mmu_context.h | 13 include/asm-ppc64/naca.h | 7 include/asm-ppc64/nvram.h | 39 include/asm-ppc64/paca.h | 14 include/asm-ppc64/pci.h | 17 include/asm-ppc64/pgalloc.h | 55 include/asm-ppc64/pgtable.h | 93 include/asm-ppc64/ppc32.h | 47 include/asm-ppc64/ppc_asm.h | 13 include/asm-ppc64/proc_fs.h | 1 include/asm-ppc64/processor.h | 18 include/asm-ppc64/prom.h | 87 include/asm-ppc64/ptrace.h | 38 include/asm-ppc64/rtas.h | 51 include/asm-ppc64/sigcontext.h | 21 include/asm-ppc64/smp.h | 31 include/asm-ppc64/socket.h | 2 include/asm-ppc64/system.h | 3 include/asm-ppc64/tlb.h | 4 include/asm-ppc64/topology.h | 3 include/asm-ppc64/uaccess.h | 1 include/asm-ppc64/unistd.h | 24 include/asm-ppc64/vio.h | 130 include/asm-s390/bitops.h | 18 include/asm-s390/bug.h | 2 include/asm-s390/byteorder.h | 12 include/asm-s390/ccwdev.h | 10 include/asm-s390/ccwgroup.h | 5 include/asm-s390/checksum.h | 8 include/asm-s390/cio.h | 8 include/asm-s390/dasd.h | 6 include/asm-s390/hardirq.h | 15 include/asm-s390/idals.h | 6 include/asm-s390/ioctl.h | 16 include/asm-s390/mmu_context.h | 2 include/asm-s390/pgalloc.h | 33 include/asm-s390/pgtable.h | 170 include/asm-s390/scatterlist.h | 6 include/asm-s390/setup.h | 1 include/asm-s390/siginfo.h | 6 include/asm-s390/smp.h | 1 include/asm-s390/socket.h | 2 include/asm-s390/spinlock.h | 2 include/asm-s390/tlbflush.h | 23 include/asm-s390/uaccess.h | 23 include/asm-s390/unistd.h | 4 include/asm-sh/bigsur/io.h | 54 include/asm-sh/byteorder.h | 5 include/asm-sh/cache.h | 7 include/asm-sh/cat68701/io.h | 67 include/asm-sh/cpu-sh2/addrspace.h | 16 include/asm-sh/cpu-sh2/cache.h | 2 include/asm-sh/cpu-sh2/dma.h | 23 include/asm-sh/cpu-sh2/shmparam.h | 16 include/asm-sh/cpu-sh2/sigcontext.h | 17 include/asm-sh/cpu-sh2/ubc.h | 32 include/asm-sh/cpu-sh3/cache.h | 2 include/asm-sh/cpu-sh3/dma.h | 6 include/asm-sh/cpu-sh3/mmu_context.h | 1 include/asm-sh/cpu-sh3/sigcontext.h | 17 include/asm-sh/cpu-sh4/cache.h | 2 include/asm-sh/cpu-sh4/dma.h | 6 include/asm-sh/cpu-sh4/sigcontext.h | 24 include/asm-sh/cpu-sh4/sq.h | 48 include/asm-sh/dma.h | 136 include/asm-sh/dreamcast/dma.h | 34 include/asm-sh/dreamcast/pci.h | 25 include/asm-sh/dreamcast/sysasic.h | 8 include/asm-sh/ec3104/io.h | 38 include/asm-sh/flat.h | 23 include/asm-sh/hardirq.h | 25 include/asm-sh/hd64461/io.h | 45 include/asm-sh/hd64465/io.h | 46 include/asm-sh/io.h | 232 include/asm-sh/ipc.h | 2 include/asm-sh/irq.h | 80 include/asm-sh/kgdb.h | 14 include/asm-sh/local.h | 7 include/asm-sh/machvec.h | 8 include/asm-sh/mc146818rtc.h | 9 include/asm-sh/module.h | 8 include/asm-sh/mpc1211/io.h | 64 include/asm-sh/overdrive/io.h | 38 include/asm-sh/page.h | 11 include/asm-sh/pci.h | 59 include/asm-sh/pgalloc.h | 26 include/asm-sh/pgtable.h | 8 include/asm-sh/processor.h | 54 include/asm-sh/ptrace.h | 36 include/asm-sh/rtc.h | 6 include/asm-sh/saturn/io.h | 38 include/asm-sh/se/io.h | 45 include/asm-sh/se7751/io.h | 38 include/asm-sh/sections.h | 9 include/asm-sh/segment.h | 6 include/asm-sh/sigcontext.h | 22 include/asm-sh/smp.h | 20 include/asm-sh/snapgear/io.h | 92 include/asm-sh/socket.h | 2 include/asm-sh/spinlock.h | 18 include/asm-sh/system.h | 5 include/asm-sh/systemh/7751systemh.h | 68 include/asm-sh/systemh/io.h | 43 include/asm-sh/timex.h | 2 include/asm-sh/uaccess.h | 220 include/asm-sh/unistd.h | 10 include/asm-sparc/elf.h | 3 include/asm-sparc/socket.h | 2 include/asm-sparc64/floppy.h | 5 include/asm-sparc64/smp.h | 2 include/asm-sparc64/socket.h | 2 include/asm-sparc64/tlbflush.h | 3 include/asm-um/smp.h | 2 include/asm-v850/byteorder.h | 5 include/asm-v850/socket.h | 2 include/asm-x86_64/byteorder.h | 5 include/asm-x86_64/pgalloc.h | 9 include/asm-x86_64/pgtable.h | 8 include/asm-x86_64/smp.h | 3 include/asm-x86_64/socket.h | 2 include/asm-x86_64/spinlock.h | 18 include/linux/bio.h | 3 include/linux/bitmap.h | 140 include/linux/blkdev.h | 6 include/linux/buffer_head.h | 5 include/linux/byteorder/swab.h | 8 include/linux/cdrom.h | 286 include/linux/compat.h | 5 include/linux/compat_ioctl.h | 136 include/linux/compiler-gcc+.h | 1 include/linux/compiler-gcc2.h | 1 include/linux/compiler-gcc3.h | 1 include/linux/compiler.h | 18 include/linux/cpumask.h | 32 include/linux/dcache.h | 3 include/linux/device.h | 10 include/linux/efi.h | 16 include/linux/ext2_fs_sb.h | 1 include/linux/ext3_fs_sb.h | 1 include/linux/ext3_jbd.h | 17 include/linux/fs.h | 19 include/linux/genhd.h | 2 include/linux/highmem.h | 3 include/linux/i2c-id.h | 3 include/linux/ide.h | 58 include/linux/input.h | 3 include/linux/ipv6.h | 4 include/linux/kernel.h | 2 include/linux/kobject.h | 1 include/linux/miscdevice.h | 3 include/linux/mm.h | 62 include/linux/mmzone.h | 22 include/linux/module.h | 6 include/linux/moduleparam.h | 1 include/linux/net.h | 14 include/linux/netdevice.h | 4 include/linux/nfs_fs.h | 3 include/linux/nfsd/nfsfh.h | 17 include/linux/pci_ids.h | 7 include/linux/proc_fs.h | 2 include/linux/quotaops.h | 6 include/linux/rcupdate.h | 2 include/linux/rtnetlink.h | 47 include/linux/sched.h | 3 include/linux/security.h | 50 include/linux/signal.h | 1 include/linux/smp.h | 1 include/linux/smp_lock.h | 3 include/linux/sunrpc/sched.h | 2 include/linux/swap.h | 2 include/linux/sysctl.h | 5 include/linux/videodev.h | 4 include/linux/videodev2.h | 103 include/linux/zorro.h | 147 include/media/id.h | 3 include/media/ir-common.h | 61 include/media/tuner.h | 6 include/net/addrconf.h | 6 include/net/bluetooth/bluetooth.h | 5 include/net/bluetooth/hci.h | 10 include/net/bluetooth/hci_core.h | 14 include/net/bluetooth/rfcomm.h | 9 include/net/flow.h | 1 include/net/if_inet6.h | 5 include/net/inet_common.h | 4 include/net/ipv6.h | 4 include/net/irda/ircomm_tty.h | 3 include/net/irda/timer.h | 6 include/net/ndisc.h | 11 include/net/neighbour.h | 10 include/net/sock.h | 51 include/net/tcp.h | 6 include/net/udp.h | 2 include/pcmcia/cs.h | 6 include/rxrpc/call.h | 3 include/rxrpc/connection.h | 3 include/rxrpc/message.h | 3 include/rxrpc/peer.h | 3 include/rxrpc/transport.h | 3 include/scsi/scsi.h | 2 include/sound/core.h | 1 include/video/kyro.h | 94 init/main.c | 3 kernel/cpu.c | 2 kernel/dma.c | 15 kernel/exit.c | 3 kernel/extable.c | 11 kernel/fork.c | 83 kernel/futex.c | 1 kernel/module.c | 14 kernel/posix-timers.c | 2 kernel/printk.c | 42 kernel/sched.c | 402 kernel/sys.c | 3 kernel/sysctl.c | 20 kernel/timer.c | 5 kernel/workqueue.c | 18 lib/Makefile | 3 lib/bitmap.c | 141 lib/extable.c | 75 lib/kobject.c | 51 mm/fadvise.c | 4 mm/filemap.c | 48 mm/fremap.c | 20 mm/madvise.c | 2 mm/memory.c | 101 mm/mincore.c | 2 mm/mmap.c | 20 mm/mremap.c | 24 mm/msync.c | 32 mm/nommu.c | 9 mm/page-writeback.c | 1 mm/page_alloc.c | 24 mm/readahead.c | 14 mm/rmap.c | 29 mm/shmem.c | 3 mm/swapfile.c | 37 mm/vmscan.c | 32 net/appletalk/ddp.c | 4 net/atm/br2684.c | 4 net/atm/clip.c | 5 net/atm/common.c | 25 net/atm/common.h | 4 net/ax25/af_ax25.c | 12 net/bluetooth/Kconfig | 3 net/bluetooth/Makefile | 1 net/bluetooth/af_bluetooth.c | 7 net/bluetooth/bnep/core.c | 1 net/bluetooth/cmtp/Kconfig | 11 net/bluetooth/cmtp/Makefile | 7 net/bluetooth/cmtp/capi.c | 630 net/bluetooth/cmtp/cmtp.h | 136 net/bluetooth/cmtp/core.c | 507 net/bluetooth/cmtp/sock.c | 199 net/bluetooth/hci_conn.c | 2 net/bluetooth/hci_core.c | 1 net/bluetooth/hci_event.c | 27 net/bluetooth/hci_sock.c | 22 net/bluetooth/l2cap.c | 4 net/bluetooth/rfcomm/core.c | 63 net/bluetooth/rfcomm/sock.c | 11 net/bluetooth/sco.c | 4 net/bridge/br_if.c | 4 net/core/dev.c | 91 net/core/dev_mcast.c | 100 net/core/neighbour.c | 7 net/core/sock.c | 13 net/decnet/af_decnet.c | 27 net/econet/af_econet.c | 10 net/ipv4/af_inet.c | 4 net/ipv4/arp.c | 2 net/ipv4/devinet.c | 4 net/ipv4/igmp.c | 3 net/ipv4/ipcomp.c | 1 net/ipv4/ipmr.c | 3 net/ipv4/netfilter/Kconfig | 13 net/ipv4/netfilter/ip_tables.c | 2 net/ipv4/raw.c | 17 net/ipv4/route.c | 5 net/ipv4/tcp.c | 4 net/ipv4/udp.c | 17 net/ipv6/addrconf.c | 191 net/ipv6/af_inet6.c | 2 net/ipv6/ipv6_sockglue.c | 18 net/ipv6/mcast.c | 2 net/ipv6/ndisc.c | 22 net/ipv6/raw.c | 9 net/ipv6/udp.c | 11 net/ipx/af_ipx.c | 8 net/ipx/ipx_route.c | 4 net/irda/af_irda.c | 24 net/irda/ircomm/ircomm_tty.c | 6 net/irda/ircomm/ircomm_tty_ioctl.c | 77 net/irda/irlap_event.c | 24 net/irda/irlap_frame.c | 41 net/key/af_key.c | 8 net/llc/af_llc.c | 10 net/netlink/af_netlink.c | 8 net/netrom/af_netrom.c | 6 net/packet/af_packet.c | 19 net/rose/af_rose.c | 8 net/rxrpc/call.c | 12 net/rxrpc/krxiod.c | 10 net/rxrpc/krxsecd.c | 6 net/rxrpc/krxtimod.c | 6 net/rxrpc/transport.c | 14 net/sched/sch_teql.c | 9 net/sctp/socket.c | 14 net/socket.c | 14 net/unix/af_unix.c | 10 net/x25/af_x25.c | 29 net/xfrm/xfrm_algo.c | 2 net/xfrm/xfrm_policy.c | 27 net/xfrm/xfrm_user.c | 1 scripts/kconfig/mconf.c | 1 scripts/modpost.c | 1 security/Makefile | 4 security/dummy.c | 18 security/selinux/Makefile | 4 security/selinux/avc.c | 54 security/selinux/hooks.c | 588 security/selinux/include/av_perm_to_string.h | 5 security/selinux/include/av_permissions.h | 5 security/selinux/include/avc.h | 5 security/selinux/include/netif.h | 30 security/selinux/include/objsec.h | 13 security/selinux/netif.c | 239 security/selinux/ss/Makefile | 6 sound/core/sound.c | 34 sound/oss/dmabuf.c | 2 sound/oss/soundcard.c | 13 sound/oss/trident.c | 2477 + sound/oss/trident.h | 17 sound/pci/intel8x0.c | 1 sound/pcmcia/vx/vx_entry.c | 38 sound/sound_core.c | 10 1577 files changed, 118715 insertions(+), 69544 deletions(-) diff -puN arch/alpha/Kconfig~linus arch/alpha/Kconfig --- 25/arch/alpha/Kconfig~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/alpha/Kconfig 2004-01-19 22:17:09.000000000 -0800 @@ -509,6 +509,7 @@ config HAVE_DEC_LOCK config NR_CPUS int "Maximum number of CPUs (2-64)" + range 2 64 depends on SMP default "64" diff -puN arch/alpha/kernel/module.c~linus arch/alpha/kernel/module.c --- 25/arch/alpha/kernel/module.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/alpha/kernel/module.c 2004-01-19 22:17:09.000000000 -0800 @@ -259,7 +259,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, *(u64 *)location = value; break; case R_ALPHA_GPRELHIGH: - value = (value - gp + 0x8000) >> 16; + value = (long)(value - gp + 0x8000) >> 16; if ((short) value != value) goto reloc_overflow; *(u16 *)location = value; diff -puN arch/alpha/mm/extable.c~linus arch/alpha/mm/extable.c --- 25/arch/alpha/mm/extable.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/alpha/mm/extable.c 2004-01-19 22:17:09.000000000 -0800 @@ -6,6 +6,11 @@ #include #include +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish) +{ +} + const struct exception_table_entry * search_extable(const struct exception_table_entry *first, const struct exception_table_entry *last, diff -puN arch/arm26/mm/extable.c~linus arch/arm26/mm/extable.c --- 25/arch/arm26/mm/extable.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/arm26/mm/extable.c 2004-01-19 22:17:09.000000000 -0800 @@ -6,27 +6,6 @@ #include #include -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} - int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; diff -puN arch/arm/mm/extable.c~linus arch/arm/mm/extable.c --- 25/arch/arm/mm/extable.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/arm/mm/extable.c 2004-01-19 22:17:09.000000000 -0800 @@ -4,27 +4,6 @@ #include #include -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} - int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; diff -puN arch/cris/arch-v10/drivers/ds1302.c~linus arch/cris/arch-v10/drivers/ds1302.c --- 25/arch/cris/arch-v10/drivers/ds1302.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/cris/arch-v10/drivers/ds1302.c 2004-01-19 22:17:09.000000000 -0800 @@ -342,6 +342,7 @@ rtc_ioctl(struct inode *inode, struct fi { struct rtc_time rtc_tm; + memset(&rtc_tm, 0, sizeof (struct rtc_time)); get_rtc_time(&rtc_tm); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) return -EFAULT; diff -puN arch/cris/arch-v10/drivers/pcf8563.c~linus arch/cris/arch-v10/drivers/pcf8563.c --- 25/arch/cris/arch-v10/drivers/pcf8563.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/cris/arch-v10/drivers/pcf8563.c 2004-01-19 22:17:09.000000000 -0800 @@ -219,6 +219,7 @@ pcf8563_ioctl(struct inode *inode, struc unsigned long flags; struct rtc_time tm; + memset(&tm, 0, sizeof (struct rtc_time)); if (!capable(CAP_SYS_TIME)) return -EPERM; diff -puN -L arch/cris/mm/extable.c arch/cris/mm/extable.c~linus /dev/null --- 25/arch/cris/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,48 +0,0 @@ -/* - * linux/arch/cris/mm/extable.c - * - * $Log: generic-exception-table-sorting-2.patch,v $ - * Revision 1.1 2004/01/19 19:27:07 akpm - * foo - * - * Revision 1.4 2003/01/09 14:42:52 starvik - * Merge of Linux 2.5.55 - * - * Revision 1.3 2002/11/21 07:24:54 starvik - * Made search_exception_table similar to implementation for other archs - * (now compiles with CONFIG_MODULES) - * - * Revision 1.2 2002/11/18 07:36:55 starvik - * Removed warning - * - * Revision 1.1 2001/12/17 13:59:27 bjornw - * Initial revision - * - * Revision 1.3 2001/09/27 13:52:40 bjornw - * Harmonize underscore-ness with other parts - * - * - */ - -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; diff -puN arch/cris/mm/Makefile~linus arch/cris/mm/Makefile --- 25/arch/cris/mm/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/cris/mm/Makefile 2004-01-19 22:17:09.000000000 -0800 @@ -2,5 +2,5 @@ # Makefile for the linux cris-specific parts of the memory manager. # -obj-y := init.o fault.o tlb.o extable.o ioremap.o +obj-y := init.o fault.o tlb.o ioremap.o diff -puN -L arch/h8300/mm/extable.c arch/h8300/mm/extable.c~linus /dev/null --- 25/arch/h8300/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,30 +0,0 @@ -/* - * linux/arch/h8300/mm/extable.c - */ - -#include -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN arch/h8300/mm/Makefile~linus arch/h8300/mm/Makefile --- 25/arch/h8300/mm/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/h8300/mm/Makefile 2004-01-19 22:17:20.000000000 -0800 @@ -7,4 +7,4 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -obj-y := init.o fault.o memory.o kmap.o extable.o +obj-y := init.o fault.o memory.o kmap.o diff -puN arch/i386/Kconfig~linus arch/i386/Kconfig --- 25/arch/i386/Kconfig~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/Kconfig 2004-01-19 22:17:20.000000000 -0800 @@ -447,6 +447,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-255)" + range 2 255 depends on SMP default "32" if X86_NUMAQ || X86_SUMMIT || X86_BIGSMP || X86_ES7000 default "8" diff -puN arch/i386/kernel/acpi/wakeup.S~linus arch/i386/kernel/acpi/wakeup.S --- 25/arch/i386/kernel/acpi/wakeup.S~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/acpi/wakeup.S 2004-01-19 22:17:20.000000000 -0800 @@ -193,21 +193,12 @@ wakeup_pmode_return: # and restore the stack ... but you need gdt for this to work movl saved_context_esp, %esp - movw $0x0e00 + 'W', 0xb8018 - outl %eax, $0x80 - outl %eax, $0x80 - movw $0x0e00 + 'O', 0xb8018 - movl %cs:saved_magic, %eax cmpl $0x12345678, %eax jne bogus_magic # jump to place where we left off movl saved_eip,%eax - movw $0x0e00 + 'x', 0xb8018 - outl %eax, $0x80 - outl %eax, $0x80 - movw $0x0e00 + '!', 0xb801a jmp *%eax bogus_magic: diff -puN arch/i386/kernel/cpu/cpufreq/Kconfig~linus arch/i386/kernel/cpu/cpufreq/Kconfig --- 25/arch/i386/kernel/cpu/cpufreq/Kconfig~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/cpu/cpufreq/Kconfig 2004-01-19 22:17:20.000000000 -0800 @@ -145,11 +145,6 @@ config X86_SPEEDSTEP_SMI If in doubt, say N. -config X86_SPEEDSTEP_LIB - tristate - depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI) - default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI) - config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" depends on CPU_FREQ_TABLE @@ -161,6 +156,11 @@ config X86_P4_CLOCKMOD If in doubt, say N. +config X86_SPEEDSTEP_LIB + tristate + depends on (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) + default (X86_SPEEDSTEP_ICH || X86_SPEEDSTEP_SMI || X86_P4_CLOCKMOD) + config X86_LONGRUN tristate "Transmeta LongRun" depends on CPU_FREQ diff -puN arch/i386/kernel/cpu/cpufreq/p4-clockmod.c~linus arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- 25/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-01-19 22:17:20.000000000 -0800 @@ -33,6 +33,8 @@ #include #include +#include "speedstep-lib.h" + #define PFX "cpufreq: " /* @@ -174,51 +176,30 @@ static int cpufreq_p4_verify(struct cpuf return cpufreq_frequency_table_verify(policy, &p4clockmod_table[0]); } -/* copied from speedstep_lib, made SMP-compatible */ + static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) { - u32 msr_lo, msr_hi, mult; - unsigned int fsb = 0; + if ((c->x86 == 0x06) && (c->x86_model == 0x09)) { + /* Pentium M */ + printk(KERN_DEBUG PFX "Warning: Pentium M detected. The speedstep_centrino module\n"); + printk(KERN_DEBUG PFX "offers voltage scaling in addition of frequency scaling. You\n"); + printk(KERN_DEBUG PFX "should use that instead of p4-clockmod, if possible.\n"); + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM); + } if (c->x86 != 0xF) { - printk(KERN_DEBUG PFX "Unknown P4. Please send an e-mail to \n"); + printk(KERN_DEBUG PFX "Unknown p4-clockmod-capable CPU. Please send an e-mail to \n"); return 0; } - rdmsr(0x2c, msr_lo, msr_hi); - - /* printk(KERN_DEBUG PFX "P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); */ - /* decode the FSB: see IA-32 Intel (C) Architecture Software - * Developer's Manual, Volume 3: System Prgramming Guide, - * revision #12 in Table B-1: MSRs in the Pentium 4 and - * Intel Xeon Processors, on page B-4 and B-5. - */ - if (c->x86_model < 2) - fsb = 100 * 1000; - else { - u8 fsb_code = (msr_lo >> 16) & 0x7; - switch (fsb_code) { - case 0: - fsb = 100 * 1000; - break; - case 1: - fsb = 13333 * 10; - break; - case 2: - fsb = 200 * 1000; - break; - } - } - - if (!fsb) { - printk(KERN_DEBUG PFX "couldn't detect FSB speed. Please send an e-mail to \n"); - printk(KERN_DEBUG PFX "P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + if (speedstep_detect_processor() == SPEEDSTEP_PROCESSOR_P4M) { + printk(KERN_DEBUG PFX "Warning: Pentium 4-M detected. The speedstep-ich or acpi cpufreq \n"); + printk(KERN_DEBUG PFX "modules offers voltage scaling in addition of frequency scaling. You\n"); + printk(KERN_DEBUG PFX "should use either one instead of p4-clockmod, if possible.\n"); + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4M); } - /* Multiplier. */ - mult = msr_lo >> 24; - - return (fsb * mult); + return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_P4D); } @@ -315,6 +296,6 @@ MODULE_AUTHOR ("Zwane Mwaikambo > 22) & 0x1f; + dprintk(KERN_DEBUG "speedstep-lib: bits 22-26 are 0x%x\n", msr_tmp); + + return (msr_tmp * 100 * 10000); +} + + static unsigned int pentium4_get_frequency(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -151,6 +171,9 @@ static unsigned int pentium4_get_frequen unsigned int speedstep_get_processor_frequency(unsigned int processor) { switch (processor) { + case SPEEDSTEP_PROCESSOR_PM: + return pentiumM_get_frequency(); + case SPEEDSTEP_PROCESSOR_P4D: case SPEEDSTEP_PROCESSOR_P4M: return pentium4_get_frequency(); case SPEEDSTEP_PROCESSOR_PIII_T: diff -puN arch/i386/kernel/cpu/cpufreq/speedstep-lib.h~linus arch/i386/kernel/cpu/cpufreq/speedstep-lib.h --- 25/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h 2004-01-19 22:17:20.000000000 -0800 @@ -17,6 +17,12 @@ #define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ #define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M */ +/* the following processors are not speedstep-capable and are not auto-detected + * in speedstep_detect_processor(). However, their speed can be detected using + * the speedstep_get_processor_frequency() call. */ +#define SPEEDSTEP_PROCESSOR_PM 0xFFFFFF03 /* Pentium M */ +#define SPEEDSTEP_PROCESSOR_P4D 0xFFFFFF04 /* desktop P4 */ + /* speedstep states -- only two of them */ #define SPEEDSTEP_HIGH 0x00000000 diff -puN arch/i386/kernel/cpu/intel.c~linus arch/i386/kernel/cpu/intel.c --- 25/arch/i386/kernel/cpu/intel.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/cpu/intel.c 2004-01-19 22:17:20.000000000 -0800 @@ -1,5 +1,7 @@ +#include #include #include + #include #include #include @@ -11,6 +13,12 @@ #include "cpu.h" +#ifdef CONFIG_X86_LOCAL_APIC +#include +#include +#include +#endif + extern int trap_init_f00f_bug(void); #ifdef CONFIG_X86_INTEL_USERCOPY @@ -277,6 +285,7 @@ static void __init init_intel(struct cpu extern int phys_proc_id[NR_CPUS]; u32 eax, ebx, ecx, edx; + int index_lsb, index_msb, tmp; int cpu = smp_processor_id(); cpuid(1, &eax, &ebx, &ecx, &edx); @@ -285,6 +294,8 @@ static void __init init_intel(struct cpu if (smp_num_siblings == 1) { printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); } else if (smp_num_siblings > 1 ) { + index_lsb = 0; + index_msb = 31; /* * At this point we only support two siblings per * processor package. @@ -295,13 +306,19 @@ static void __init init_intel(struct cpu smp_num_siblings = 1; goto too_many_siblings; } - /* cpuid returns the value latched in the HW at reset, - * not the APIC ID register's value. For any box - * whose BIOS changes APIC IDs, like clustered APIC - * systems, we must use hard_smp_processor_id. - * See Intel's IA-32 SW Dev's Manual Vol2 under CPUID. - */ - phys_proc_id[cpu] = hard_smp_processor_id() & ~(smp_num_siblings - 1); + tmp = smp_num_siblings; + while ((tmp & 1) == 0) { + tmp >>=1 ; + index_lsb++; + } + tmp = smp_num_siblings; + while ((tmp & 0x80000000 ) == 0) { + tmp <<=1 ; + index_msb--; + } + if (index_lsb != index_msb ) + index_msb++; + phys_proc_id[cpu] = phys_pkg_id((ebx >> 24) & 0xFF, index_msb); printk(KERN_INFO "CPU: Physical Processor ID: %d\n", phys_proc_id[cpu]); diff -puN arch/i386/kernel/dmi_scan.c~linus arch/i386/kernel/dmi_scan.c --- 25/arch/i386/kernel/dmi_scan.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/dmi_scan.c 2004-01-19 22:17:20.000000000 -0800 @@ -107,15 +107,7 @@ static int __init dmi_iterate(void (*dec u8 buf[15]; u32 fp=0xF0000; -#ifdef CONFIG_SIMNOW - /* - * Skip on x86/64 with simnow. Will eventually go away - * If you see this ifdef in 2.6pre mail me ! - */ - return -1; -#endif - - while( fp < 0xFFFFF) + while (fp < 0xFFFFF) { isa_memcpy_fromio(buf, fp, 15); if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf)) diff -puN arch/i386/kernel/efi.c~linus arch/i386/kernel/efi.c --- 25/arch/i386/kernel/efi.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/efi.c 2004-01-19 22:17:20.000000000 -0800 @@ -174,7 +174,7 @@ phys_efi_get_time(efi_time_t *tm, efi_ti return status; } -int inline efi_set_rtc_mmss(unsigned long nowtime) +inline int efi_set_rtc_mmss(unsigned long nowtime) { int real_seconds, real_minutes; efi_status_t status; @@ -207,7 +207,7 @@ int inline efi_set_rtc_mmss(unsigned lon * services have been remapped, therefore, we'll need to call in physical * mode. Note, this call isn't used later, so mark it __init. */ -unsigned long inline __init efi_get_time(void) +inline unsigned long __init efi_get_time(void) { efi_status_t status; efi_time_t eft; diff -puN arch/i386/kernel/time.c~linus arch/i386/kernel/time.c --- 25/arch/i386/kernel/time.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/time.c 2004-01-19 22:17:20.000000000 -0800 @@ -307,7 +307,31 @@ unsigned long get_cmos_time(void) return retval; } +static long clock_cmos_diff; + +static int time_suspend(struct sys_device *dev, u32 state) +{ + /* + * Estimate time zone so that set_time can update the clock + */ + clock_cmos_diff = -get_cmos_time(); + clock_cmos_diff += get_seconds(); + return 0; +} + +static int time_resume(struct sys_device *dev) +{ + unsigned long sec = get_cmos_time() + clock_cmos_diff; + write_seqlock_irq(&xtime_lock); + xtime.tv_sec = sec; + xtime.tv_nsec = 0; + write_sequnlock_irq(&xtime_lock); + return 0; +} + static struct sysdev_class pit_sysclass = { + .resume = time_resume, + .suspend = time_suspend, set_kset_name("pit"), }; diff -puN arch/i386/kernel/time_hpet.c~linus arch/i386/kernel/time_hpet.c --- 25/arch/i386/kernel/time_hpet.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/kernel/time_hpet.c 2004-01-19 22:17:20.000000000 -0800 @@ -91,10 +91,6 @@ int __init hpet_enable(void) !(id & HPET_ID_LEGSUP)) return -1; - if (((id & HPET_ID_VENDOR) >> HPET_ID_VENDOR_SHIFT) != - HPET_ID_VENDOR_8086) - return -1; - hpet_period = hpet_readl(HPET_PERIOD); if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD)) return -1; diff -puN arch/i386/mach-voyager/voyager_smp.c~linus arch/i386/mach-voyager/voyager_smp.c --- 25/arch/i386/mach-voyager/voyager_smp.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/i386/mach-voyager/voyager_smp.c 2004-01-19 22:17:20.000000000 -0800 @@ -130,7 +130,7 @@ send_QIC_CPI(__u32 cpuset, __u8 cpi) { int cpu; - for_each_cpu(cpu, cpu_online_map) { + for_each_online_cpu(cpu) { if(cpuset & (1< #include -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} - int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; diff -puN /dev/null arch/ia64/configs/generic_defconfig --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ia64/configs/generic_defconfig 2004-01-19 22:17:20.000000000 -0800 @@ -0,0 +1,1045 @@ +# +# Automatically generated make config: don't edit +# + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=20 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +CONFIG_IA64=y +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_TIME_INTERPOLATION=y +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y +CONFIG_IA64_GENERIC=y +# CONFIG_IA64_DIG is not set +# CONFIG_IA64_HP_SIM is not set +# CONFIG_IA64_HP_ZX1 is not set +# CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_PAGE_SIZE_4KB is not set +# CONFIG_IA64_PAGE_SIZE_8KB is not set +CONFIG_IA64_PAGE_SIZE_16KB=y +# CONFIG_IA64_PAGE_SIZE_64KB is not set +CONFIG_ACPI=y +CONFIG_ACPI_INTERPRETER=y +CONFIG_ACPI_KERNEL_CONFIG=y +CONFIG_IA64_L1_CACHE_SHIFT=7 +# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set +CONFIG_NUMA=y +CONFIG_DISCONTIGMEM=y +CONFIG_VIRTUAL_MEM_MAP=y +CONFIG_IA64_MCA=y +CONFIG_PM=y +CONFIG_IOSAPIC=y +CONFIG_FORCE_MAX_ZONEORDER=18 +# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +CONFIG_HUGETLB_PAGE_SIZE_16MB=y +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set +# CONFIG_IA64_PAL_IDLE is not set +CONFIG_SMP=y +# CONFIG_PREEMPT is not set +CONFIG_IA32_SUPPORT=y +CONFIG_COMPAT=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_PERFMON=y +CONFIG_IA64_PALINFO=y +CONFIG_EFI=y +CONFIG_EFI_VARS=y +CONFIG_NR_CPUS=512 +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=m + +# +# ACPI (Advanced Configuration and Power Interface) Support +# +CONFIG_ACPI_BOOT=y +CONFIG_ACPI_BUTTON=m +CONFIG_ACPI_FAN=m +CONFIG_ACPI_PROCESSOR=m +CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_NUMA=y +# CONFIG_ACPI_DEBUG is not set +CONFIG_ACPI_BUS=y +CONFIG_ACPI_POWER=y +CONFIG_ACPI_PCI=y +CONFIG_ACPI_SYSTEM=y +# CONFIG_ACPI_RELAXED_AML is not set +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_HOTPLUG=y + +# +# PCI Hotplug Support +# +CONFIG_HOTPLUG_PCI=m +# CONFIG_HOTPLUG_PCI_FAKE is not set +CONFIG_HOTPLUG_PCI_ACPI=m +# CONFIG_HOTPLUG_PCI_CPCI is not set + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_CRYPTOLOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +CONFIG_BLK_DEV_IDEFLOPPY=y +CONFIG_BLK_DEV_IDESCSI=m +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +CONFIG_BLK_DEV_PIIX=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=m +CONFIG_MD_LINEAR=m +CONFIG_MD_RAID0=m +CONFIG_MD_RAID1=m +CONFIG_MD_RAID5=m +CONFIG_MD_MULTIPATH=m +CONFIG_BLK_DEV_DM=m +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +CONFIG_FUSION=y +CONFIG_FUSION_BOOT=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=m +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=m + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +CONFIG_SCSI_REPORT_LUNS=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +CONFIG_SCSI_QLOGIC_FC=y +# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set +CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# 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_IP_MROUTE is not set +CONFIG_ARPD=y +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q 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_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# 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=m +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +CONFIG_NET_TULIP=y +# CONFIG_DE2104X is not set +CONFIG_TULIP=m +# CONFIG_TULIP_MWI is not set +# CONFIG_TULIP_MMIO is not set +# CONFIG_DE4X5 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_DM9102 is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_DGRS is not set +CONFIG_EEPRO100=m +# CONFIG_EEPRO100_PIO is not set +CONFIG_E100=m +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +CONFIG_E1000=m +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +CONFIG_TIGON3=y + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +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 + +# +# Input I/O drivers +# +CONFIG_GAMEPORT=m +CONFIG_SOUND_GAMEPORT=m +# CONFIG_GAMEPORT_NS558 is not set +# CONFIG_GAMEPORT_L4 is not set +# CONFIG_GAMEPORT_EMU10K1 is not set +# CONFIG_GAMEPORT_VORTEX is not set +# CONFIG_GAMEPORT_FM801 is not set +# CONFIG_GAMEPORT_CS461x is not set +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +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 + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_ROCKETPORT is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_STALDRV is not set +CONFIG_SGI_L1_SERIAL=y +CONFIG_SGI_L1_SERIAL_CONSOLE=y + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_ACPI=y +CONFIG_SERIAL_8250_HCDP=y +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_GEN_RTC is not set +CONFIG_EFI_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +CONFIG_AGP=m +CONFIG_AGP_I460=m +CONFIG_AGP_HP_ZX1=m +CONFIG_DRM=y +CONFIG_DRM_TDFX=m +CONFIG_DRM_GAMMA=m +CONFIG_DRM_R128=m +CONFIG_DRM_RADEON=m +CONFIG_DRM_MGA=m +CONFIG_DRM_SIS=m +CONFIG_RAW_DRIVER=m +CONFIG_MAX_RAW_DEVS=256 + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_POSIX_ACL is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_NTFS_FS=m +# CONFIG_NTFS_DEBUG is not set +# CONFIG_NTFS_RW is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=m +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +CONFIG_NFS_DIRECTIO=y +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=m +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=m +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp437" +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_EFI_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_UTF8=m + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +CONFIG_SOUND=m + +# +# Advanced Linux Sound Architecture +# +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_OSSEMUL=y +CONFIG_SND_MIXER_OSS=m +CONFIG_SND_PCM_OSS=m +CONFIG_SND_SEQUENCER_OSS=y +CONFIG_SND_VERBOSE_PRINTK=y +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +CONFIG_SND_DUMMY=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m + +# +# PCI devices +# +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_AZT3328 is not set +CONFIG_SND_CS46XX=m +CONFIG_SND_CS46XX_NEW_DSP=y +CONFIG_SND_CS4281=m +CONFIG_SND_EMU10K1=m +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_MAESTRO3 is not set +CONFIG_SND_FM801=m +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VX222 is not set + +# +# ALSA USB devices +# +# CONFIG_SND_USB_AUDIO is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +CONFIG_USB=m +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_UHCI_HCD=m + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_BLUETOOTH_TTY is not set +# CONFIG_USB_MIDI is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set +CONFIG_USB_STORAGE=m +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=m +CONFIG_USB_HIDINPUT=y +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers +# +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_TEST is not set +# CONFIG_USB_GADGET is not set + +# +# Library routines +# +CONFIG_CRC32=y + +# +# HP Simulator drivers +# +# CONFIG_HP_SIMETH is not set +# CONFIG_HP_SIMSERIAL is not set +# CONFIG_HP_SIMSCSI is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +CONFIG_IA64_GRANULE_16MB=y +# CONFIG_IA64_GRANULE_64MB is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_IA64_PRINT_HAZARDS is not set +# CONFIG_DISABLE_VHPT is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_DEBUG_SLAB is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_IA64_DEBUG_CMPXCHG is not set +# CONFIG_IA64_DEBUG_IRQ is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_TEST is not set diff -puN arch/ia64/configs/sn2_defconfig~linus arch/ia64/configs/sn2_defconfig --- 25/arch/ia64/configs/sn2_defconfig~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/configs/sn2_defconfig 2004-01-19 22:17:20.000000000 -0800 @@ -15,8 +15,6 @@ CONFIG_STANDALONE=y CONFIG_SWAP=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_PAGG=y -CONFIG_PAGG_JOB=y CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=20 # CONFIG_IKCONFIG is not set @@ -27,6 +25,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -53,7 +52,6 @@ CONFIG_IA64_SGI_SN2=y CONFIG_IA64_PAGE_SIZE_16KB=y # CONFIG_IA64_PAGE_SIZE_64KB is not set CONFIG_ACPI=y -CONFIG_ACPI_EFI=y CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_KERNEL_CONFIG=y CONFIG_IA64_L1_CACHE_SHIFT=7 @@ -70,9 +68,10 @@ CONFIG_SMP=y # CONFIG_PREEMPT is not set CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +CONFIG_HAVE_DEC_LOCK=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y -CONFIG_IA64_SALINFO=y +CONFIG_EFI=y # CONFIG_EFI_VARS is not set CONFIG_NR_CPUS=512 CONFIG_BINFMT_ELF=y @@ -145,7 +144,60 @@ CONFIG_BLK_DEV_LOOP=y # # ATA/ATAPI/MFM/RLL support # -# CONFIG_IDE is not set +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_IDEDISK is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +CONFIG_BLK_DEV_SGIIOC4=y +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -216,6 +268,7 @@ CONFIG_SCSI_REPORT_LUNS=y # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set @@ -585,11 +638,11 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set CONFIG_EFI_PARTITION=y -CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set diff -puN arch/ia64/hp/common/sba_iommu.c~linus arch/ia64/hp/common/sba_iommu.c --- 25/arch/ia64/hp/common/sba_iommu.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/hp/common/sba_iommu.c 2004-01-19 22:17:20.000000000 -0800 @@ -1,9 +1,9 @@ /* ** IA64 System Bus Adapter (SBA) I/O MMU manager ** -** (c) Copyright 2002-2003 Alex Williamson +** (c) Copyright 2002-2004 Alex Williamson ** (c) Copyright 2002-2003 Grant Grundler -** (c) Copyright 2002-2003 Hewlett-Packard Company +** (c) Copyright 2002-2004 Hewlett-Packard Company ** ** Portions (c) 2000 Grant Grundler (from parisc I/O MMU code) ** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) @@ -39,12 +39,19 @@ #include /* PAGE_OFFSET */ #include #include /* wmb() */ +#include /* hweight64() */ #include #define PFX "IOC: " /* +** Enabling timing search of the pdir resource map. Output in /proc. +** Disabled by default to optimize performance. +*/ +#undef PDIR_SEARCH_TIMING + +/* ** This option allows cards capable of 64bit DMA to bypass the IOMMU. If ** not defined, all DMA will be 32bit and go through the TLB. ** There's potentially a conflict in the bio merge code with us @@ -54,11 +61,6 @@ */ #define ALLOW_IOV_BYPASS -#ifdef CONFIG_PROC_FS - /* turn it off for now; without per-CPU counters, it's too much of a scalability bottleneck: */ -# define SBA_PROC_FS 0 -#endif - /* ** If a device prefetches beyond the end of a valid pdir entry, it will cause ** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should @@ -160,21 +162,18 @@ #define ZX1_SBA_IOMMU_COOKIE 0x0000badbadc0ffeeUL /* -** IOC supports 4/8/16/64KB page sizes (see TCNFG register) -** It's safer (avoid memory corruption) to keep DMA page mappings -** equivalently sized to VM PAGE_SIZE. +** The zx1 IOC supports 4/8/16/64KB page sizes (see TCNFG register) ** -** We really can't avoid generating a new mapping for each -** page since the Virtual Coherence Index has to be generated -** and updated for each page. +** Some IOCs (sx1000) can run at the above pages sizes, but are +** really only supported using the IOC at a 4k page size. ** -** IOVP_SIZE could only be greater than PAGE_SIZE if we are +** iovp_size could only be greater than PAGE_SIZE if we are ** confident the drivers really only touch the next physical ** page iff that driver instance owns it. */ -#define IOVP_SIZE PAGE_SIZE -#define IOVP_SHIFT PAGE_SHIFT -#define IOVP_MASK PAGE_MASK +static unsigned long iovp_size; +static unsigned long iovp_shift; +static unsigned long iovp_mask; struct ioc { void *ioc_hpa; /* I/O MMU base address */ @@ -198,24 +197,10 @@ struct ioc { } saved[DELAYED_RESOURCE_CNT]; #endif -#if SBA_PROC_FS +#ifdef PDIR_SEARCH_TIMING #define SBA_SEARCH_SAMPLE 0x100 unsigned long avg_search[SBA_SEARCH_SAMPLE]; unsigned long avg_idx; /* current index into avg_search */ - unsigned long used_pages; - unsigned long msingle_calls; - unsigned long msingle_pages; - unsigned long msg_calls; - unsigned long msg_pages; - unsigned long usingle_calls; - unsigned long usingle_pages; - unsigned long usg_calls; - unsigned long usg_pages; -#ifdef ALLOW_IOV_BYPASS - unsigned long msingle_bypass; - unsigned long usingle_bypass; - unsigned long msg_bypass; -#endif #endif /* Stuff we don't need in performance path */ @@ -252,7 +237,7 @@ static u64 prefetch_spill_page; ** rather than the HW. I/O MMU allocation alogorithms can be ** faster with smaller size is (to some degree). */ -#define DMA_CHUNK_SIZE (BITS_PER_LONG*PAGE_SIZE) +#define DMA_CHUNK_SIZE (BITS_PER_LONG*iovp_size) #define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) @@ -416,18 +401,37 @@ sba_check_sg( struct ioc *ioc, struct sc #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset) | \ - ((hint_reg)<<(ioc->hint_shift_pdir))) -#define SBA_IOVP(ioc,iova) (((iova) & ioc->hint_mask_pdir) & ~(ioc->ibase)) +#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset)) +#define SBA_IOVP(ioc,iova) ((iova) & ~(ioc->ibase)) -/* FIXME : review these macros to verify correctness and usage */ -#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) +#define PDIR_ENTRY_SIZE sizeof(u64) + +#define PDIR_INDEX(iovp) ((iovp)>>iovp_shift) #define RESMAP_MASK(n) ~(~0UL << (n)) #define RESMAP_IDX_MASK (sizeof(unsigned long) - 1) /** + * For most cases the normal get_order is sufficient, however it limits us + * to PAGE_SIZE being the minimum mapping alignment and TC flush granularity. + * It only incurs about 1 clock cycle to use this one with the static variable + * and makes the code more intuitive. + */ +static SBA_INLINE int +get_iovp_order (unsigned long size) +{ + long double d = size - 1; + long order; + + order = ia64_getf_exp(d); + order = order - iovp_shift - 0xffff + 1; + if (order < 0) + order = 0; + return order; +} + +/** * sba_search_bitmap - find free space in IO PDIR resource bitmap * @ioc: IO MMU structure which owns the pdir we are interested in. * @bits_wanted: number of entries we need. @@ -465,7 +469,7 @@ sba_search_bitmap(struct ioc *ioc, unsig ** We need the alignment to invalidate I/O TLB using ** SBA HW features in the unmap path. */ - unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT); + unsigned long o = 1 << get_iovp_order(bits_wanted << iovp_shift); uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); unsigned long mask; @@ -521,16 +525,15 @@ sba_search_bitmap(struct ioc *ioc, unsig static int sba_alloc_range(struct ioc *ioc, size_t size) { - unsigned int pages_needed = size >> IOVP_SHIFT; -#if SBA_PROC_FS + unsigned int pages_needed = size >> iovp_shift; +#ifdef PDIR_SEARCH_TIMING unsigned long itc_start = ia64_get_itc(); #endif unsigned long pide; ASSERT(pages_needed); - ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE); ASSERT(pages_needed <= BITS_PER_LONG); - ASSERT(0 == (size & ~IOVP_MASK)); + ASSERT(0 == (size & ~iovp_mask)); /* ** "seek and ye shall find"...praying never hurts either... @@ -546,7 +549,7 @@ sba_alloc_range(struct ioc *ioc, size_t #ifdef ASSERT_PDIR_SANITY /* verify the first enable bit is clear */ - if(0x00 != ((u8 *) ioc->pdir_base)[pide*sizeof(u64) + 7]) { + if(0x00 != ((u8 *) ioc->pdir_base)[pide*PDIR_ENTRY_SIZE + 7]) { sba_dump_pdir_entry(ioc, "sba_search_bitmap() botched it?", pide); } #endif @@ -556,17 +559,9 @@ sba_alloc_range(struct ioc *ioc, size_t (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); -#if SBA_PROC_FS - { - unsigned long itc_end = ia64_get_itc(); - unsigned long tmp = itc_end - itc_start; - /* check for roll over */ - itc_start = (itc_end < itc_start) ? -(tmp) : (tmp); - } - ioc->avg_search[ioc->avg_idx++] = itc_start; +#ifdef PDIR_SEARCH_TIMING + ioc->avg_search[ioc->avg_idx++] = ia64_get_itc() - itc_start; ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; - - ioc->used_pages += pages_needed; #endif return (pide); @@ -589,7 +584,7 @@ sba_free_range(struct ioc *ioc, dma_addr unsigned int ridx = pide >> 3; /* convert bit to byte address */ unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]); - int bits_not_wanted = size >> IOVP_SHIFT; + int bits_not_wanted = size >> iovp_shift; /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ unsigned long m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1)); @@ -598,13 +593,9 @@ sba_free_range(struct ioc *ioc, dma_addr __FUNCTION__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); -#if SBA_PROC_FS - ioc->used_pages -= bits_not_wanted; -#endif - ASSERT(m != 0); ASSERT(bits_not_wanted); - ASSERT((bits_not_wanted * IOVP_SIZE) <= DMA_CHUNK_SIZE); + ASSERT((bits_not_wanted * iovp_size) <= DMA_CHUNK_SIZE); ASSERT(bits_not_wanted <= BITS_PER_LONG); ASSERT((*res_ptr & m) == m); /* verify same bits are set */ *res_ptr &= ~m; @@ -702,7 +693,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad /* Must be non-zero and rounded up */ ASSERT(byte_cnt > 0); - ASSERT(0 == (byte_cnt & ~IOVP_MASK)); + ASSERT(0 == (byte_cnt & ~iovp_mask)); #ifdef ASSERT_PDIR_SANITY /* Assert first pdir entry is set */ @@ -711,11 +702,11 @@ sba_mark_invalid(struct ioc *ioc, dma_ad } #endif - if (byte_cnt <= IOVP_SIZE) + if (byte_cnt <= iovp_size) { ASSERT(off < ioc->pdir_size); - iovp |= IOVP_SHIFT; /* set "size" field for PCOM */ + iovp |= iovp_shift; /* set "size" field for PCOM */ #ifndef FULL_VALID_PDIR /* @@ -734,7 +725,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); #endif } else { - u32 t = get_order(byte_cnt) + PAGE_SHIFT; + u32 t = get_iovp_order(byte_cnt) + iovp_shift; iovp |= t; ASSERT(t <= 31); /* 2GB! Max value of "size" field */ @@ -749,7 +740,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad ioc->pdir_base[off] = (0x80000000000000FFULL | prefetch_spill_page); #endif off++; - byte_cnt -= IOVP_SIZE; + byte_cnt -= iovp_size; } while (byte_cnt > 0); } @@ -790,11 +781,6 @@ sba_map_single(struct device *dev, void ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr */ -#if SBA_PROC_FS - spin_lock_irqsave(&ioc->res_lock, flags); - ioc->msingle_bypass++; - spin_unlock_irqrestore(&ioc->res_lock, flags); -#endif DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", *dev->dma_mask, pci_addr); return pci_addr; @@ -805,10 +791,10 @@ sba_map_single(struct device *dev, void ASSERT(size <= DMA_CHUNK_SIZE); /* save offset bits */ - offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK; + offset = ((dma_addr_t) (long) addr) & ~iovp_mask; - /* round up to nearest IOVP_SIZE */ - size = (size + offset + ~IOVP_MASK) & IOVP_MASK; + /* round up to nearest iovp_size */ + size = (size + offset + ~iovp_mask) & iovp_mask; spin_lock_irqsave(&ioc->res_lock, flags); #ifdef ASSERT_PDIR_SANITY @@ -816,12 +802,8 @@ sba_map_single(struct device *dev, void panic("Sanity check failed"); #endif -#if SBA_PROC_FS - ioc->msingle_calls++; - ioc->msingle_pages += size >> IOVP_SHIFT; -#endif pide = sba_alloc_range(ioc, size); - iovp = (dma_addr_t) pide << IOVP_SHIFT; + iovp = (dma_addr_t) pide << iovp_shift; DBG_RUN("%s() 0x%p -> 0x%lx\n", __FUNCTION__, addr, (long) iovp | offset); @@ -834,8 +816,8 @@ sba_map_single(struct device *dev, void DBG_RUN(" pdir 0x%p %lx\n", pdir_start, *pdir_start); - addr += IOVP_SIZE; - size -= IOVP_SIZE; + addr += iovp_size; + size -= iovp_size; pdir_start++; } /* force pdir update */ @@ -875,11 +857,6 @@ void sba_unmap_single(struct device *dev /* ** Address does not fall w/in IOVA, must be bypassing */ -#if SBA_PROC_FS - spin_lock_irqsave(&ioc->res_lock, flags); - ioc->usingle_bypass++; - spin_unlock_irqrestore(&ioc->res_lock, flags); -#endif DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova); #ifdef ENABLE_MARK_CLEAN @@ -890,20 +867,16 @@ void sba_unmap_single(struct device *dev return; } #endif - offset = iova & ~IOVP_MASK; + offset = iova & ~iovp_mask; DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); iova ^= offset; /* clear offset bits */ size += offset; - size = ROUNDUP(size, IOVP_SIZE); + size = ROUNDUP(size, iovp_size); spin_lock_irqsave(&ioc->res_lock, flags); -#if SBA_PROC_FS - ioc->usingle_calls++; - ioc->usingle_pages += size >> IOVP_SHIFT; -#endif #if DELAYED_RESOURCE_CNT > 0 d = &(ioc->saved[ioc->saved_cnt]); @@ -930,7 +903,7 @@ void sba_unmap_single(struct device *dev int off = PDIR_INDEX(iovp); void *addr; - if (size <= IOVP_SIZE) { + if (size <= iovp_size) { addr = phys_to_virt(ioc->pdir_base[off] & ~0xE000000000000FFFULL); mark_clean(addr, size); @@ -940,9 +913,9 @@ void sba_unmap_single(struct device *dev do { addr = phys_to_virt(ioc->pdir_base[off] & ~0xE000000000000FFFULL); - mark_clean(addr, min(byte_cnt, IOVP_SIZE)); + mark_clean(addr, min(byte_cnt, iovp_size)); off++; - byte_cnt -= IOVP_SIZE; + byte_cnt -= iovp_size; } while (byte_cnt > 0); } @@ -1061,11 +1034,11 @@ sba_fill_pdir( */ if (startsg->dma_address & PIDE_FLAG) { u32 pide = startsg->dma_address & ~PIDE_FLAG; - dma_offset = (unsigned long) pide & ~IOVP_MASK; + dma_offset = (unsigned long) pide & ~iovp_mask; startsg->dma_address = 0; dma_sg++; dma_sg->dma_address = pide | ioc->ibase; - pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]); + pdirp = &(ioc->pdir_base[pide >> iovp_shift]); n_mappings++; } @@ -1082,14 +1055,11 @@ sba_fill_pdir( dma_sg->dma_length += cnt; cnt += dma_offset; dma_offset=0; /* only want offset on first chunk */ - cnt = ROUNDUP(cnt, IOVP_SIZE); -#if SBA_PROC_FS - ioc->msg_pages += cnt >> IOVP_SHIFT; -#endif + cnt = ROUNDUP(cnt, iovp_size); do { sba_io_pdir_entry(pdirp, vaddr); - vaddr += IOVP_SIZE; - cnt -= IOVP_SIZE; + vaddr += iovp_size; + cnt -= iovp_size; pdirp++; } while (cnt > 0); } @@ -1107,12 +1077,12 @@ sba_fill_pdir( /* ** Two address ranges are DMA contiguous *iff* "end of prev" and -** "start of next" are both on a page boundry. +** "start of next" are both on an IOV page boundary. ** ** (shift left is a quick trick to mask off upper bits) */ #define DMA_CONTIG(__X, __Y) \ - (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) + (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - iovp_shift)) == 0UL) /** @@ -1150,7 +1120,7 @@ sba_coalesce_chunks( struct ioc *ioc, dma_sg = vcontig_sg = startsg; dma_len = vcontig_len = vcontig_end = startsg->length; vcontig_end += vaddr; - dma_offset = vaddr & ~IOVP_MASK; + dma_offset = vaddr & ~iovp_mask; /* PARANOID: clear entries */ startsg->dma_address = startsg->dma_length = 0; @@ -1175,7 +1145,7 @@ sba_coalesce_chunks( struct ioc *ioc, ** exceed DMA_CHUNK_SIZE if we coalesce the ** next entry. */ - if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) + if (((dma_len + dma_offset + startsg->length + ~iovp_mask) & iovp_mask) > DMA_CHUNK_SIZE) break; @@ -1194,7 +1164,7 @@ sba_coalesce_chunks( struct ioc *ioc, } #ifdef DEBUG_LARGE_SG_ENTRIES - dump_run_sg = (vcontig_len > IOVP_SIZE); + dump_run_sg = (vcontig_len > iovp_size); #endif /* @@ -1233,10 +1203,10 @@ sba_coalesce_chunks( struct ioc *ioc, ** Allocate space for DMA stream. */ vcontig_sg->dma_length = vcontig_len; - dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; + dma_len = (dma_len + dma_offset + ~iovp_mask) & iovp_mask; ASSERT(dma_len <= DMA_CHUNK_SIZE); dma_sg->dma_address = (dma_addr_t) (PIDE_FLAG - | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) + | (sba_alloc_range(ioc, dma_len) << iovp_shift) | dma_offset); n_mappings++; } @@ -1273,11 +1243,6 @@ int sba_map_sg(struct device *dev, struc sg->dma_length = sg->length; sg->dma_address = virt_to_phys(sba_sg_address(sg)); } -#if SBA_PROC_FS - spin_lock_irqsave(&ioc->res_lock, flags); - ioc->msg_bypass++; - spin_unlock_irqrestore(&ioc->res_lock, flags); -#endif return filled; } #endif @@ -1285,13 +1250,7 @@ int sba_map_sg(struct device *dev, struc if (nents == 1) { sglist->dma_length = sglist->length; sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, - dir); -#if SBA_PROC_FS - /* - ** Should probably do some stats counting, but trying to - ** be precise quickly starts wasting CPU time. - */ -#endif + dir); return 1; } @@ -1305,10 +1264,6 @@ int sba_map_sg(struct device *dev, struc } #endif -#if SBA_PROC_FS - ioc->msg_calls++; -#endif - /* ** First coalesce the chunks and allocate I/O pdir space ** @@ -1368,10 +1323,6 @@ void sba_unmap_sg (struct device *dev, s ioc = GET_IOC(dev); ASSERT(ioc); -#if SBA_PROC_FS - ioc->usg_calls++; -#endif - #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); sba_check_pdir(ioc,"Check before sba_unmap_sg()"); @@ -1381,16 +1332,6 @@ void sba_unmap_sg (struct device *dev, s while (nents && sglist->dma_length) { sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir); -#if SBA_PROC_FS - /* - ** This leaves inconsistent data in the stats, but we can't - ** tell which sg lists were mapped by map_single and which - ** were coalesced to a single entry. The stats are fun, - ** but speed is more important. - */ - ioc->usg_pages += ((sglist->dma_address & ~IOVP_MASK) + sglist->dma_length - + IOVP_SIZE - 1) >> PAGE_SHIFT; -#endif sglist++; nents--; } @@ -1414,8 +1355,7 @@ void sba_unmap_sg (struct device *dev, s static void __init ioc_iova_init(struct ioc *ioc) { - u32 iova_space_mask; - int iov_order, tcnfg; + int tcnfg; int agp_found = 0; struct pci_dev *device = NULL; #ifdef FULL_VALID_PDIR @@ -1428,23 +1368,27 @@ ioc_iova_init(struct ioc *ioc) ** IBASE and IMASK registers. */ ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1UL; - ioc->iov_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; + ioc->imask = READ_REG(ioc->ioc_hpa + IOC_IMASK) | 0xFFFFFFFF00000000UL; - /* - ** iov_order is always based on a 1GB IOVA space since we want to - ** turn on the other half for AGP GART. - */ - iov_order = get_order(ioc->iov_size >> (IOVP_SHIFT - PAGE_SHIFT)); - ioc->pdir_size = (ioc->iov_size / IOVP_SIZE) * sizeof(u64); + ioc->iov_size = ~ioc->imask + 1; - DBG_INIT("%s() hpa %p IOV %dMB (%d bits) PDIR size 0x%x\n", - __FUNCTION__, ioc->ioc_hpa, ioc->iov_size >> 20, - iov_order + PAGE_SHIFT, ioc->pdir_size); - - /* FIXME : DMA HINTs not used */ - ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; - ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT)); + DBG_INIT("%s() hpa %p IOV base 0x%lx mask 0x%lx (%dMB)\n", + __FUNCTION__, ioc->ioc_hpa, ioc->ibase, ioc->imask, + ioc->iov_size >> 20); + + switch (iovp_size) { + case 4*1024: tcnfg = 0; break; + case 8*1024: tcnfg = 1; break; + case 16*1024: tcnfg = 2; break; + case 64*1024: tcnfg = 3; break; + default: + panic(PFX "Unsupported IOTLB page size %ldK", + iovp_size >> 10); + break; + } + WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG); + ioc->pdir_size = (ioc->iov_size / iovp_size) * PDIR_ENTRY_SIZE; ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(ioc->pdir_size)); if (!ioc->pdir_base) @@ -1452,61 +1396,12 @@ ioc_iova_init(struct ioc *ioc) memset(ioc->pdir_base, 0, ioc->pdir_size); - DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", - __FUNCTION__, ioc->pdir_base, ioc->pdir_size, - ioc->hint_shift_pdir, ioc->hint_mask_pdir); + DBG_INIT("%s() IOV page size %ldK pdir %p size %x\n", __FUNCTION__, + iovp_size >> 10, ioc->pdir_base, ioc->pdir_size); - ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base); + ASSERT(ALIGN((unsigned long) ioc->pdir_base, 4*1024) == (unsigned long) ioc->pdir_base); WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE); - DBG_INIT(" base %p\n", ioc->pdir_base); - - /* build IMASK for IOC and Elroy */ - iova_space_mask = 0xffffffff; - iova_space_mask <<= (iov_order + PAGE_SHIFT); - ioc->imask = iova_space_mask; - - DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", - __FUNCTION__, ioc->ibase, ioc->imask); - - /* - ** FIXME: Hint registers are programmed with default hint - ** values during boot, so hints should be sane even if we - ** can't reprogram them the way drivers want. - */ - WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK); - - /* - ** Setting the upper bits makes checking for bypass addresses - ** a little faster later on. - */ - ioc->imask |= 0xFFFFFFFF00000000UL; - - /* Set I/O PDIR Page size to system page size */ - switch (PAGE_SHIFT) { - case 12: tcnfg = 0; break; /* 4K */ - case 13: tcnfg = 1; break; /* 8K */ - case 14: tcnfg = 2; break; /* 16K */ - case 16: tcnfg = 3; break; /* 64K */ - default: - panic(PFX "Unsupported system page size %d", - 1 << PAGE_SHIFT); - break; - } - WRITE_REG(tcnfg, ioc->ioc_hpa + IOC_TCNFG); - - /* - ** Program the IOC's ibase and enable IOVA translation - ** Bit zero == enable bit. - */ - WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE); - - /* - ** Clear I/O TLB of any possible entries. - ** (Yes. This is a bit paranoid...but so what) - */ - WRITE_REG(ioc->ibase | (iov_order+PAGE_SHIFT), ioc->ioc_hpa + IOC_PCOM); - /* ** If an AGP device is present, only use half of the IOV space ** for PCI DMA. Unfortunately we can't know ahead of time @@ -1519,8 +1414,8 @@ ioc_iova_init(struct ioc *ioc) agp_found |= pci_find_capability(device, PCI_CAP_ID_AGP); if (agp_found && reserve_sba_gart) { - DBG_INIT("%s: AGP device found, reserving half of IOVA for GART support\n", - __FUNCTION__); + printk(KERN_INFO PFX "reserving %dMb of IOVA space at 0x%lx for agpgart\n", + ioc->iov_size/2 >> 20, ioc->ibase + ioc->iov_size/2); ioc->pdir_size /= 2; ((u64 *)ioc->pdir_base)[PDIR_INDEX(ioc->iov_size/2)] = ZX1_SBA_IOMMU_COOKIE; } @@ -1534,12 +1429,12 @@ ioc_iova_init(struct ioc *ioc) int poison_size = 16; void *poison_addr, *addr; - addr = (void *)__get_free_pages(GFP_KERNEL, get_order(IOVP_SIZE)); + addr = (void *)__get_free_pages(GFP_KERNEL, get_order(iovp_size)); if (!addr) panic(PFX "Couldn't allocate PDIR spill page\n"); poison_addr = addr; - for ( ; (u64) poison_addr < addr + IOVP_SIZE; poison_addr += poison_size) + for ( ; (u64) poison_addr < addr + iovp_size; poison_addr += poison_size) memcpy(poison_addr, spill_poison, poison_size); prefetch_spill_page = virt_to_phys(addr); @@ -1549,10 +1444,17 @@ ioc_iova_init(struct ioc *ioc) /* ** Set all the PDIR entries valid w/ the spill page as the target */ - for (index = 0 ; index < (ioc->pdir_size / sizeof(u64)) ; index++) + for (index = 0 ; index < (ioc->pdir_size / PDIR_ENTRY_SIZE) ; index++) ((u64 *)ioc->pdir_base)[index] = (0x80000000000000FF | prefetch_spill_page); #endif + /* Clear I/O TLB of any possible entries */ + WRITE_REG(ioc->ibase | (get_iovp_order(ioc->iov_size) + iovp_shift), ioc->ioc_hpa + IOC_PCOM); + READ_REG(ioc->ioc_hpa + IOC_PCOM); + + /* Enable IOVA translation */ + WRITE_REG(ioc->ibase | 1, ioc->ioc_hpa + IOC_IBASE); + READ_REG(ioc->ioc_hpa + IOC_IBASE); } static void __init @@ -1561,7 +1463,7 @@ ioc_resource_init(struct ioc *ioc) spin_lock_init(&ioc->res_lock); /* resource map size dictated by pdir_size */ - ioc->res_size = ioc->pdir_size / sizeof(u64); /* entries */ + ioc->res_size = ioc->pdir_size / PDIR_ENTRY_SIZE; /* entries */ ioc->res_size >>= 3; /* convert bit count to byte count */ DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); @@ -1582,7 +1484,7 @@ ioc_resource_init(struct ioc *ioc) #ifdef FULL_VALID_PDIR /* Mark the last resource used so we don't prefetch beyond IOVA space */ ioc->res_map[ioc->res_size - 1] |= 0x80UL; /* res_map is chars */ - ioc->pdir_base[(ioc->pdir_size / sizeof(u64)) - 1] = (0x80000000000000FF + ioc->pdir_base[(ioc->pdir_size / PDIR_ENTRY_SIZE) - 1] = (0x80000000000000FF | prefetch_spill_page); #endif @@ -1627,6 +1529,23 @@ ioc_zx1_init(struct ioc *ioc) panic(PFX "IOC 2.0 or later required for IOMMU support\n"); ioc->dma_mask = 0xFFFFFFFFFFUL; + + if (!iovp_shift) { + /* 64k is max iommu page size */ + iovp_shift = min(PAGE_SHIFT, 16); + iovp_size = (1 << iovp_shift); + iovp_mask = ~(iovp_size - 1); + } +} + +static void __init +ioc_sx1000_init(struct ioc *ioc) +{ + if (!iovp_shift) { + iovp_shift = 12; /* 4K for now */ + iovp_size = (1 << iovp_shift); + iovp_mask = ~(iovp_size - 1); + } } typedef void (initfunc)(struct ioc *); @@ -1639,8 +1558,8 @@ struct ioc_iommu { static struct ioc_iommu ioc_iommu_info[] __initdata = { { ZX1_IOC_ID, "zx1", ioc_zx1_init }, - { REO_IOC_ID, "REO" }, - { SX1000_IOC_ID, "sx1000" }, + { REO_IOC_ID, "REO", ioc_sx1000_init }, + { SX1000_IOC_ID, "sx1000", ioc_sx1000_init }, }; static struct ioc * __init @@ -1665,6 +1584,11 @@ ioc_init(u64 hpa, void *handle) ioc->rev = READ_REG(ioc->ioc_hpa + IOC_FCLASS) & 0xFFUL; ioc->dma_mask = 0xFFFFFFFFFFFFFFFFUL; /* conservative */ + if (iovp_shift) { + iovp_size = (1 << iovp_shift); + iovp_mask = ~(iovp_size - 1); + } + for (info = ioc_iommu_info; info < ioc_iommu_info + ARRAY_SIZE(ioc_iommu_info); info++) { if (ioc->func_id == info->func_id) { ioc->name = info->name; @@ -1672,6 +1596,8 @@ ioc_init(u64 hpa, void *handle) (info->init)(ioc); } } + DBG_INIT("%s: PAGE_SIZE %ldK, iovp_size %ldK\n", __FUNCTION__, + PAGE_SIZE >> 10, iovp_size >> 10); if (!ioc->name) { ioc->name = kmalloc(24, GFP_KERNEL); @@ -1686,8 +1612,8 @@ ioc_init(u64 hpa, void *handle) ioc_resource_init(ioc); ioc_sac_init(ioc); - if ((long) ~IOVP_MASK > (long) ia64_max_iommu_merge_mask) - ia64_max_iommu_merge_mask = ~IOVP_MASK; + if ((long) ~iovp_mask > (long) ia64_max_iommu_merge_mask) + ia64_max_iommu_merge_mask = ~iovp_mask; MAX_DMA_ADDRESS = ~0UL; printk(KERN_INFO PFX @@ -1709,7 +1635,7 @@ ioc_init(u64 hpa, void *handle) ** **************************************************************************/ -#if SBA_PROC_FS +#ifdef CONFIG_PROC_FS static void * ioc_start(struct seq_file *s, loff_t *pos) { @@ -1741,55 +1667,37 @@ static int ioc_show(struct seq_file *s, void *v) { struct ioc *ioc = v; - int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ - unsigned long i = 0, avg = 0, min, max; + unsigned long *res_ptr = (unsigned long *)ioc->res_map; + int i, used = 0; seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); - seq_printf(s, "IO PDIR size : %d bytes (%d entries)\n", - (int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */ - total_pages); - - seq_printf(s, "IO PDIR entries : %ld free %ld used (%d%%)\n", - total_pages - ioc->used_pages, ioc->used_pages, - (int) (ioc->used_pages * 100 / total_pages)); - - seq_printf(s, "Resource bitmap : %d bytes (%d pages)\n", - ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ - - min = max = ioc->avg_search[0]; - for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { - avg += ioc->avg_search[i]; - if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; - if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; - } - avg /= SBA_SEARCH_SAMPLE; - seq_printf(s, " Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", min, avg, max); - - seq_printf(s, "pci_map_single(): %12ld calls %12ld pages (avg %d/1000)\n", - ioc->msingle_calls, ioc->msingle_pages, - (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); -#ifdef ALLOW_IOV_BYPASS - seq_printf(s, "pci_map_single(): %12ld bypasses\n", ioc->msingle_bypass); -#endif + seq_printf(s, "IOVA size : %d MB\n", ioc->iov_size/(1024*1024)); + seq_printf(s, "IOVA page size : %ld kb\n", iovp_size/1024); - seq_printf(s, "pci_unmap_single: %12ld calls %12ld pages (avg %d/1000)\n", - ioc->usingle_calls, ioc->usingle_pages, - (int) ((ioc->usingle_pages * 1000)/ioc->usingle_calls)); -#ifdef ALLOW_IOV_BYPASS - seq_printf(s, "pci_unmap_single: %12ld bypasses\n", ioc->usingle_bypass); -#endif - - seq_printf(s, "pci_map_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - ioc->msg_calls, ioc->msg_pages, - (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); -#ifdef ALLOW_IOV_BYPASS - seq_printf(s, "pci_map_sg() : %12ld bypasses\n", ioc->msg_bypass); -#endif + for (i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) + used += hweight64(*res_ptr); - seq_printf(s, "pci_unmap_sg() : %12ld calls %12ld pages (avg %d/1000)\n", - ioc->usg_calls, ioc->usg_pages, (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); + seq_printf(s, "PDIR size : %d entries\n", ioc->res_size << 3); + seq_printf(s, "PDIR used : %d entries\n", used); +#ifdef PDIR_SEARCH_TIMING + { + unsigned long i = 0, avg = 0, min, max; + min = max = ioc->avg_search[0]; + for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { + avg += ioc->avg_search[i]; + if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; + if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; + } + avg /= SBA_SEARCH_SAMPLE; + seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + min, avg, max); + } +#endif +#ifndef ALLOW_IOV_BYPASS + seq_printf(s, "IOVA bypass disabled\n"); +#endif return 0; } @@ -1813,39 +1721,6 @@ static struct file_operations ioc_fops = .release = seq_release }; -static int -ioc_map_show(struct seq_file *s, void *v) -{ - struct ioc *ioc = v; - unsigned int i, *res_ptr = (unsigned int *)ioc->res_map; - - for (i = 0; i < ioc->res_size / sizeof(unsigned int); ++i, ++res_ptr) - seq_printf(s, "%s%08x", (i & 7) ? " " : "\n ", *res_ptr); - seq_printf(s, "\n"); - - return 0; -} - -static struct seq_operations ioc_map_ops = { - .start = ioc_start, - .next = ioc_next, - .stop = ioc_stop, - .show = ioc_map_show -}; - -static int -ioc_map_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &ioc_map_ops); -} - -static struct file_operations ioc_map_fops = { - .open = ioc_map_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release -}; - static void __init ioc_proc_init(void) { @@ -1858,10 +1733,6 @@ ioc_proc_init(void) entry = create_proc_entry(ioc_list->name, 0, dir); if (entry) entry->proc_fops = &ioc_fops; - - entry = create_proc_entry("bitmap", 0, dir); - if (entry) - entry->proc_fops = &ioc_map_fops; } #endif @@ -1958,7 +1829,7 @@ sba_init(void) } #endif -#if SBA_PROC_FS +#ifdef CONFIG_PROC_FS ioc_proc_init(); #endif return 0; @@ -1982,6 +1853,29 @@ sba_dma_supported (struct device *dev, u __setup("nosbagart", nosbagart); +static int __init +sba_page_override(char *str) +{ + unsigned long page_size; + + page_size = memparse(str, &str); + switch (page_size) { + case 4096: + case 8192: + case 16384: + case 65536: + iovp_shift = ffs(page_size) - 1; + break; + default: + printk("%s: unknown/unsupported iommu page size %ld\n", + __FUNCTION__, page_size); + } + + return 1; +} + +__setup("sbapagesize=",sba_page_override); + EXPORT_SYMBOL(sba_map_single); EXPORT_SYMBOL(sba_unmap_single); EXPORT_SYMBOL(sba_map_sg); diff -puN arch/ia64/ia32/sys_ia32.c~linus arch/ia64/ia32/sys_ia32.c --- 25/arch/ia64/ia32/sys_ia32.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/ia32/sys_ia32.c 2004-01-19 22:17:20.000000000 -0800 @@ -741,7 +741,7 @@ filldir32 (void *__buf, const char *name || copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) return -EFAULT; - ((char *) dirent) += reclen; + dirent = (struct compat_dirent *) ((char *) dirent + reclen); buf->current_dir = dirent; buf->count -= reclen; return 0; diff -puN arch/ia64/Kconfig~linus arch/ia64/Kconfig --- 25/arch/ia64/Kconfig~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/Kconfig 2004-01-19 22:17:20.000000000 -0800 @@ -33,6 +33,10 @@ config TIME_INTERPOLATION bool default y +config EFI + bool + default y + choice prompt "IA-64 processor type" default ITANIUM @@ -66,26 +70,18 @@ config IA64_GENERIC will run on any supported IA-64 system. However, if you configure a kernel for your specific system, it will be faster and smaller. - To find out what type of IA-64 system you have, you may want to - check the IA-64 Linux web site at . - As of the time of this writing, most hardware is DIG compliant, - so the "DIG-compliant" option is usually the right choice. - - HP-simulator For the HP simulator - (). - HP-zx1 For HP zx1-based systems. - SGI-SN2 For SGI Altix systems DIG-compliant For DIG ("Developer's Interface Guide") compliant - systems. + systems + HP-zx1 For HP systems + SGI-SN2 For SGI Altix systems + Ski-simulator For the HP simulator + () If you don't know what to do, choose "generic". config IA64_DIG bool "DIG-compliant" -config IA64_HP_SIM - bool "HP-simulator" - config IA64_HP_ZX1 bool "HP-zx1" help @@ -96,6 +92,9 @@ config IA64_HP_ZX1 config IA64_SGI_SN2 bool "SGI-SN2" +config IA64_HP_SIM + bool "Ski-simulator" + endchoice choice @@ -395,11 +394,6 @@ config IA64_PALINFO support" (CONFIG_PROC_FS) is enabled, too. -config EFI - bool - depends on !IA64_HP_SIM - default y - config EFI_VARS tristate "/proc/efi/vars support" help @@ -411,7 +405,8 @@ config EFI_VARS support" (CONFIG_PROC_FS) is enabled, too. config NR_CPUS - int "Maximum number of CPUs" + int "Maximum number of CPUs (2-512)" + range 2 512 depends on SMP default "64" help diff -puN arch/ia64/kernel/acpi.c~linus arch/ia64/kernel/acpi.c --- 25/arch/ia64/kernel/acpi.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/acpi.c 2004-01-19 22:17:20.000000000 -0800 @@ -32,6 +32,7 @@ */ #include +#include #include #include #include @@ -53,6 +54,7 @@ #define PREFIX "ACPI: " void (*pm_idle) (void); +EXPORT_SYMBOL(pm_idle); void (*pm_power_off) (void); unsigned char acpi_kbd_controller_present = 1; @@ -629,5 +631,6 @@ acpi_register_irq (u32 gsi, u32 polarity (polarity == ACPI_ACTIVE_HIGH) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, (trigger == ACPI_EDGE_SENSITIVE) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); } +EXPORT_SYMBOL(acpi_register_irq); #endif /* CONFIG_ACPI_BOOT */ diff -puN arch/ia64/kernel/efi.c~linus arch/ia64/kernel/efi.c --- 25/arch/ia64/kernel/efi.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/efi.c 2004-01-19 22:17:20.000000000 -0800 @@ -19,6 +19,7 @@ * Skip non-WB memory and ignore empty memory ranges. */ #include +#include #include #include #include @@ -37,6 +38,7 @@ extern efi_status_t efi_call_phys (void *, ...); struct efi efi; +EXPORT_SYMBOL(efi); static efi_runtime_services_t *runtime; /* @@ -48,6 +50,7 @@ static efi_runtime_services_t *runtime; */ #ifdef CONFIG_PROC_FS struct proc_dir_entry *efi_dir; +EXPORT_SYMBOL(efi_dir); #endif static unsigned long mem_limit = ~0UL; diff -puN arch/ia64/kernel/ia64_ksyms.c~linus arch/ia64/kernel/ia64_ksyms.c --- 25/arch/ia64/kernel/ia64_ksyms.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/ia64_ksyms.c 2004-01-19 22:17:20.000000000 -0800 @@ -1,15 +1,18 @@ /* * Architecture-specific kernel symbols + * + * Don't put any exports here unless it's defined in an assembler file. + * All other exports should be put directly after the definition. */ #include #include #include -EXPORT_SYMBOL_NOVERS(memset); /* gcc generates direct calls to memset()... */ +EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(memcmp); -EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memscan); EXPORT_SYMBOL(strcat); @@ -25,77 +28,28 @@ EXPORT_SYMBOL(strrchr); EXPORT_SYMBOL(strstr); EXPORT_SYMBOL(strpbrk); -#include -EXPORT_SYMBOL(isa_irq_to_vector_map); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL(disable_irq_nosync); - -#include -EXPORT_SYMBOL(probe_irq_mask); - #include EXPORT_SYMBOL(ip_fast_csum); /* hand-coded assembly */ -#include -EXPORT_SYMBOL(__ia64_memcpy_fromio); -EXPORT_SYMBOL(__ia64_memcpy_toio); -EXPORT_SYMBOL(__ia64_memset_c_io); -EXPORT_SYMBOL(io_space); - #include -EXPORT_SYMBOL_NOVERS(__down); -EXPORT_SYMBOL_NOVERS(__down_interruptible); -EXPORT_SYMBOL_NOVERS(__down_trylock); -EXPORT_SYMBOL_NOVERS(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__up); #include EXPORT_SYMBOL(clear_page); #ifdef CONFIG_VIRTUAL_MEM_MAP #include -#include -EXPORT_SYMBOL(vmalloc_end); -EXPORT_SYMBOL(ia64_pfn_valid); EXPORT_SYMBOL(max_low_pfn); /* defined by bootmem.c, but not exported by generic code */ #endif #include EXPORT_SYMBOL(per_cpu__cpu_info); #ifdef CONFIG_SMP -EXPORT_SYMBOL(__per_cpu_offset); EXPORT_SYMBOL(per_cpu__local_per_cpu_offset); #endif -EXPORT_SYMBOL(kernel_thread); - -#include -#ifdef CONFIG_IA64_DEBUG_IRQ -EXPORT_SYMBOL(last_cli_ip); -#endif - -#include - -EXPORT_SYMBOL(flush_tlb_range); - -#ifdef CONFIG_SMP - -EXPORT_SYMBOL(smp_flush_tlb_all); - -#include -#include -EXPORT_SYMBOL(synchronize_irq); - -#include -EXPORT_SYMBOL(smp_call_function); -EXPORT_SYMBOL(smp_call_function_single); -EXPORT_SYMBOL(cpu_online_map); -EXPORT_SYMBOL(phys_cpu_present_map); -EXPORT_SYMBOL(ia64_cpu_to_sapicid); -#else /* !CONFIG_SMP */ - -EXPORT_SYMBOL(local_flush_tlb_all); - -#endif /* !CONFIG_SMP */ #include EXPORT_SYMBOL(__copy_user); @@ -117,14 +71,14 @@ extern void __udivdi3(void); extern void __moddi3(void); extern void __umoddi3(void); -EXPORT_SYMBOL_NOVERS(__divsi3); -EXPORT_SYMBOL_NOVERS(__udivsi3); -EXPORT_SYMBOL_NOVERS(__modsi3); -EXPORT_SYMBOL_NOVERS(__umodsi3); -EXPORT_SYMBOL_NOVERS(__divdi3); -EXPORT_SYMBOL_NOVERS(__udivdi3); -EXPORT_SYMBOL_NOVERS(__moddi3); -EXPORT_SYMBOL_NOVERS(__umoddi3); +EXPORT_SYMBOL(__divsi3); +EXPORT_SYMBOL(__udivsi3); +EXPORT_SYMBOL(__modsi3); +EXPORT_SYMBOL(__umodsi3); +EXPORT_SYMBOL(__divdi3); +EXPORT_SYMBOL(__udivdi3); +EXPORT_SYMBOL(__moddi3); +EXPORT_SYMBOL(__umoddi3); #if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE) extern void xor_ia64_2(void); @@ -132,15 +86,12 @@ extern void xor_ia64_3(void); extern void xor_ia64_4(void); extern void xor_ia64_5(void); -EXPORT_SYMBOL_NOVERS(xor_ia64_2); -EXPORT_SYMBOL_NOVERS(xor_ia64_3); -EXPORT_SYMBOL_NOVERS(xor_ia64_4); -EXPORT_SYMBOL_NOVERS(xor_ia64_5); +EXPORT_SYMBOL(xor_ia64_2); +EXPORT_SYMBOL(xor_ia64_3); +EXPORT_SYMBOL(xor_ia64_4); +EXPORT_SYMBOL(xor_ia64_5); #endif -extern unsigned long ia64_iobase; -EXPORT_SYMBOL(ia64_iobase); - #include EXPORT_SYMBOL(ia64_pal_call_phys_stacked); EXPORT_SYMBOL(ia64_pal_call_phys_static); @@ -149,44 +100,8 @@ EXPORT_SYMBOL(ia64_pal_call_static); EXPORT_SYMBOL(ia64_load_scratch_fpregs); EXPORT_SYMBOL(ia64_save_scratch_fpregs); -extern struct efi efi; -EXPORT_SYMBOL(efi); - -#include -extern struct proc_dir_entry *efi_dir; -EXPORT_SYMBOL(efi_dir); - -#include -#ifdef CONFIG_IA64_GENERIC -EXPORT_SYMBOL(ia64_mv); -#endif -EXPORT_SYMBOL(machvec_noop); -EXPORT_SYMBOL(machvec_memory_fence); -EXPORT_SYMBOL(zero_page_memmap_ptr); -#ifdef CONFIG_PERFMON -#include -EXPORT_SYMBOL(pfm_register_buffer_fmt); -EXPORT_SYMBOL(pfm_unregister_buffer_fmt); -EXPORT_SYMBOL(pfm_mod_fast_read_pmds); -EXPORT_SYMBOL(pfm_mod_read_pmds); -EXPORT_SYMBOL(pfm_mod_write_pmcs); -#endif - -#ifdef CONFIG_NUMA -#include -EXPORT_SYMBOL(cpu_to_node_map); -#endif - #include -EXPORT_SYMBOL(unw_init_from_blocked_task); EXPORT_SYMBOL(unw_init_running); -EXPORT_SYMBOL(unw_unwind); -EXPORT_SYMBOL(unw_unwind_to_user); -EXPORT_SYMBOL(unw_access_gr); -EXPORT_SYMBOL(unw_access_br); -EXPORT_SYMBOL(unw_access_fr); -EXPORT_SYMBOL(unw_access_ar); -EXPORT_SYMBOL(unw_access_pr); #ifdef CONFIG_SMP # if __GNUC__ < 3 || (__GNUC__ == 3 && __GNUC_MINOR__ < 3) @@ -205,8 +120,3 @@ extern char ia64_spinlock_contention; EXPORT_SYMBOL(ia64_spinlock_contention); # endif #endif - -EXPORT_SYMBOL(ia64_max_iommu_merge_mask); - -#include -EXPORT_SYMBOL(pm_idle); diff -puN arch/ia64/kernel/irq.c~linus arch/ia64/kernel/irq.c --- 25/arch/ia64/kernel/irq.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/irq.c 2004-01-19 22:17:20.000000000 -0800 @@ -226,6 +226,7 @@ inline void synchronize_irq(unsigned int while (irq_descp(irq)->status & IRQ_INPROGRESS) cpu_relax(); } +EXPORT_SYMBOL(synchronize_irq); #endif /* @@ -367,6 +368,7 @@ inline void disable_irq_nosync(unsigned } spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(disable_irq_nosync); /** * disable_irq - disable an irq and wait for completion @@ -389,6 +391,7 @@ void disable_irq(unsigned int irq) if (desc->action) synchronize_irq(irq); } +EXPORT_SYMBOL(disable_irq); /** * enable_irq - enable handling of an irq @@ -427,6 +430,7 @@ void enable_irq(unsigned int irq) } spin_unlock_irqrestore(&desc->lock, flags); } +EXPORT_SYMBOL(enable_irq); /* * do_IRQ handles all normal device IRQ's (the special @@ -795,6 +799,7 @@ unsigned int probe_irq_mask(unsigned lon return mask & val; } +EXPORT_SYMBOL(probe_irq_mask); /** * probe_irq_off - end an interrupt autodetect diff -puN arch/ia64/kernel/irq_ia64.c~linus arch/ia64/kernel/irq_ia64.c --- 25/arch/ia64/kernel/irq_ia64.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/irq_ia64.c 2004-01-19 22:17:20.000000000 -0800 @@ -13,6 +13,7 @@ */ #include +#include #include #include @@ -54,6 +55,7 @@ __u8 isa_irq_to_vector_map[16] = { 0x2f, 0x20, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21 }; +EXPORT_SYMBOL(isa_irq_to_vector_map); int ia64_alloc_vector (void) diff -puN arch/ia64/kernel/machvec.c~linus arch/ia64/kernel/machvec.c --- 25/arch/ia64/kernel/machvec.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/machvec.c 2004-01-19 22:17:20.000000000 -0800 @@ -1,4 +1,5 @@ #include +#include #include @@ -11,6 +12,7 @@ #include struct ia64_machine_vector ia64_mv; +EXPORT_SYMBOL(ia64_mv); static struct ia64_machine_vector * lookup_machvec (const char *name) @@ -45,9 +47,11 @@ void machvec_noop (void) { } +EXPORT_SYMBOL(machvec_noop); void machvec_memory_fence (void) { mb(); } +EXPORT_SYMBOL(machvec_memory_fence); diff -puN arch/ia64/kernel/perfmon.c~linus arch/ia64/kernel/perfmon.c --- 25/arch/ia64/kernel/perfmon.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/perfmon.c 2004-01-19 22:17:20.000000000 -0800 @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -1042,12 +1043,10 @@ pfm_restore_pmds(unsigned long *pmds, un int i; unsigned long val, ovfl_val = pmu_conf.ovfl_val; - DPRINT(("mask=0x%lx\n", mask)); for (i=0; mask; i++, mask>>=1) { if ((mask & 0x1) == 0) continue; val = PMD_IS_COUNTING(i) ? pmds[i] & ovfl_val : pmds[i]; ia64_set_pmd(i, val); - DPRINT(("pmd[%d]=0x%lx\n", i, val)); } ia64_srlz_d(); } @@ -1115,11 +1114,9 @@ pfm_restore_pmcs(unsigned long *pmcs, un { int i; - DPRINT(("mask=0x%lx\n", mask)); for (i=0; mask; i++, mask>>=1) { if ((mask & 0x1) == 0) continue; ia64_set_pmc(i, pmcs[i]); - DPRINT(("pmc[%d]=0x%lx\n", i, pmcs[i])); } ia64_srlz_d(); } @@ -1259,6 +1256,7 @@ out: spin_unlock(&pfm_buffer_fmt_lock); return ret; } +EXPORT_SYMBOL(pfm_register_buffer_fmt); int pfm_unregister_buffer_fmt(pfm_uuid_t uuid) @@ -1282,6 +1280,7 @@ out: return ret; } +EXPORT_SYMBOL(pfm_unregister_buffer_fmt); static int pfm_reserve_session(struct task_struct *task, int is_syswide, unsigned int cpu) @@ -2157,6 +2156,7 @@ pfm_alloc_fd(struct file **cfile) d_add(file->f_dentry, inode); file->f_vfsmnt = mntget(pfmfs_mnt); + file->f_mapping = inode->i_mapping; file->f_op = &pfm_file_ops; file->f_mode = FMODE_READ; @@ -3421,6 +3421,7 @@ pfm_mod_write_pmcs(struct task_struct *t return pfm_write_pmcs(ctx, req, nreq, regs); } +EXPORT_SYMBOL(pfm_mod_write_pmcs); long pfm_mod_read_pmds(struct task_struct *task, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs) @@ -3442,6 +3443,7 @@ pfm_mod_read_pmds(struct task_struct *ta return pfm_read_pmds(ctx, req, nreq, regs); } +EXPORT_SYMBOL(pfm_mod_read_pmds); long pfm_mod_fast_read_pmds(struct task_struct *task, unsigned long mask[4], unsigned long *addr, struct pt_regs *regs) @@ -3483,6 +3485,7 @@ pfm_mod_fast_read_pmds(struct task_struc } return 0; } +EXPORT_SYMBOL(pfm_mod_fast_read_pmds); /* * Only call this function when a process it trying to @@ -5670,7 +5673,7 @@ pfm_save_regs(struct task_struct *task) ctx = PFM_GET_CTX(task); - if (ctx == NULL) goto save_error; + if (ctx == NULL) return; t = &task->thread; /* @@ -5685,8 +5688,6 @@ pfm_save_regs(struct task_struct *task) pfm_clear_psr_up(); - DPRINT(("ctx zombie, forcing cleanup for [%d]\n", task->pid)); - pfm_force_cleanup(ctx, regs); BUG_ON(ctx->ctx_smpl_hdr); @@ -5701,12 +5702,7 @@ pfm_save_regs(struct task_struct *task) * sanity check */ if (ctx->ctx_last_activation != GET_ACTIVATION()) { - printk("ctx_activation=%lu activation=%lu state=%d: no save\n", - ctx->ctx_last_activation, - GET_ACTIVATION(), ctx->ctx_state); - pfm_unprotect_ctx_ctxsw(ctx, flags); - return; } @@ -5763,13 +5759,6 @@ pfm_save_regs(struct task_struct *task) * interrupts will still be masked after this call. */ pfm_unprotect_ctx_ctxsw(ctx, flags); - - return; - -save_error: - printk(KERN_ERR "perfmon: pfm_save_regs CPU%d [%d] NULL context PM_VALID=%ld\n", - smp_processor_id(), task->pid, - task->thread.flags & IA64_THREAD_PM_VALID); } #else /* !CONFIG_SMP */ @@ -5780,7 +5769,7 @@ pfm_save_regs(struct task_struct *task) u64 psr; ctx = PFM_GET_CTX(task); - if (ctx == NULL) goto save_error; + if (ctx == NULL) return; /* * save current PSR: needed because we modify it @@ -5802,12 +5791,6 @@ pfm_save_regs(struct task_struct *task) * keep a copy of psr.up (for reload) */ ctx->ctx_saved_psr_up = psr & IA64_PSR_UP; - - return; -save_error: - printk(KERN_ERR "perfmon: pfm_save_regs CPU%d [%d] NULL context PM_VALID=%ld\n", - smp_processor_id(), task->pid, - task->thread.flags & IA64_THREAD_PM_VALID); } static void @@ -5824,8 +5807,6 @@ pfm_lazy_save_regs (struct task_struct * ctx = PFM_GET_CTX(task); t = &task->thread; - DPRINT(("on [%d] used_pmds=0x%lx\n", task->pid, ctx->ctx_used_pmds[0])); - /* * we need to mask PMU overflow here to * make sure that we maintain pmc0 until @@ -5886,10 +5867,7 @@ pfm_load_regs (struct task_struct *task) u64 psr, psr_up; ctx = PFM_GET_CTX(task); - if (unlikely(ctx == NULL)) { - printk(KERN_ERR "perfmon: pfm_load_regs() null context\n"); - return; - } + if (unlikely(ctx == NULL)) return; BUG_ON(GET_PMU_OWNER()); @@ -5897,10 +5875,7 @@ pfm_load_regs (struct task_struct *task) /* * possible on unload */ - if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) { - printk("[%d] PM_VALID=0, nothing to do\n", task->pid); - return; - } + if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) return; /* * we always come here with interrupts ALREADY disabled by @@ -5918,8 +5893,6 @@ pfm_load_regs (struct task_struct *task) BUG_ON(ctx->ctx_smpl_hdr); - DPRINT(("ctx zombie, forcing cleanup for [%d]\n", task->pid)); - pfm_force_cleanup(ctx, regs); pfm_unprotect_ctx_ctxsw(ctx, flags); @@ -5957,7 +5930,6 @@ pfm_load_regs (struct task_struct *task) pmc_mask = ctx->ctx_reload_pmcs[0]; pmd_mask = ctx->ctx_reload_pmds[0]; - if (pmc_mask || pmd_mask) DPRINT(("partial reload [%d] pmd_mask=0x%lx pmc_mask=0x%lx\n", task->pid, pmd_mask, pmc_mask)); } else { /* * To avoid leaking information to the user level when psr.sp=0, @@ -5975,12 +5947,6 @@ pfm_load_regs (struct task_struct *task) * PMC0 is never in the mask. It is always restored separately. */ pmc_mask = ctx->ctx_all_pmcs[0]; - - DPRINT(("full reload for [%d] activation=%lu last_activation=%lu last_cpu=%d pmd_mask=0x%lx pmc_mask=0x%lx\n", - task->pid, - GET_ACTIVATION(), ctx->ctx_last_activation, - GET_LAST_CPU(ctx), pmd_mask, pmc_mask)); - } /* * when context is MASKED, we will restore PMC with plm=0 @@ -6008,7 +5974,6 @@ pfm_load_regs (struct task_struct *task) /* * will replay the PMU interrupt */ - DPRINT(("perfmon: resend irq for [%d]\n", task->pid)); hw_resend_irq(NULL, IA64_PERFMON_VECTOR); #endif pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++; @@ -6102,8 +6067,6 @@ pfm_load_regs (struct task_struct *task) return; } - DPRINT(("reload for [%d] owner=%d\n", task->pid, owner ? owner->pid : -1)); - /* * someone else is still using the PMU, first push it out and * then we'll be able to install our stuff ! @@ -6150,7 +6113,6 @@ pfm_load_regs (struct task_struct *task) /* * will replay the PMU interrupt */ - DPRINT(("perfmon: resend irq for [%d]\n", task->pid)); hw_resend_irq(NULL, IA64_PERFMON_VECTOR); #endif pfm_stats[smp_processor_id()].pfm_replay_ovfl_intr_count++; diff -puN arch/ia64/kernel/process.c~linus arch/ia64/kernel/process.c --- 25/arch/ia64/kernel/process.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/process.c 2004-01-19 22:17:20.000000000 -0800 @@ -598,6 +598,7 @@ kernel_thread (int (*fn)(void *), void * } return tid; } +EXPORT_SYMBOL(kernel_thread); /* * Flush thread state. This is called when a thread does an execve(). diff -puN arch/ia64/kernel/setup.c~linus arch/ia64/kernel/setup.c --- 25/arch/ia64/kernel/setup.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/setup.c 2004-01-19 22:17:20.000000000 -0800 @@ -17,6 +17,7 @@ * 06/24/99 W.Drummond added boot_cpu_data. */ #include +#include #include #include @@ -54,12 +55,9 @@ # error "struct cpuinfo_ia64 too big!" #endif -#ifdef CONFIG_EFI -int efi_enabled = 1; -#endif - #ifdef CONFIG_SMP unsigned long __per_cpu_offset[NR_CPUS]; +EXPORT_SYMBOL(__per_cpu_offset); #endif DEFINE_PER_CPU(struct cpuinfo_ia64, cpu_info); @@ -71,7 +69,9 @@ struct screen_info screen_info; unsigned long ia64_max_cacheline_size; unsigned long ia64_iobase; /* virtual address for I/O accesses */ +EXPORT_SYMBOL(ia64_iobase); struct io_space io_space[MAX_IO_SPACES]; +EXPORT_SYMBOL(io_space); unsigned int num_io_spaces; unsigned char aux_device_present = 0xaa; /* XXX remove this when legacy I/O is gone */ @@ -86,6 +86,7 @@ unsigned char aux_device_present = 0xaa; * page-size of 2^64. */ unsigned long ia64_max_iommu_merge_mask = ~0UL; +EXPORT_SYMBOL(ia64_max_iommu_merge_mask); #define COMMAND_LINE_SIZE 512 @@ -317,13 +318,13 @@ setup_arch (char **cmdline_p) #ifdef CONFIG_ACPI_BOOT acpi_boot_init(); #endif +#ifdef CONFIG_SERIAL_8250_CONSOLE #ifdef CONFIG_SERIAL_8250_HCDP if (efi.hcdp) { void setup_serial_hcdp(void *); setup_serial_hcdp(efi.hcdp); } #endif -#ifdef CONFIG_SERIAL_8250_CONSOLE /* * Without HCDP, we won't discover any serial ports until the serial driver looks * in the ACPI namespace. If ACPI claims there are some legacy devices, register @@ -520,8 +521,6 @@ identify_cpu (struct cpuinfo_ia64 *c) impl_va_msb = vm2.pal_vm_info_2_s.impl_va_msb; phys_addr_size = vm1.pal_vm_info_1_s.phys_add_size; } - printk(KERN_INFO "CPU %d: %lu virtual and %lu physical address bits\n", - smp_processor_id(), impl_va_msb + 1, phys_addr_size); c->unimpl_va_mask = ~((7L<<61) | ((1L << (impl_va_msb + 1)) - 1)); c->unimpl_pa_mask = ~((1L<<63) | ((1L << phys_addr_size) - 1)); } diff -puN arch/ia64/kernel/smpboot.c~linus arch/ia64/kernel/smpboot.c --- 25/arch/ia64/kernel/smpboot.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/smpboot.c 2004-01-19 22:17:20.000000000 -0800 @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -81,10 +82,13 @@ task_t *task_for_booting_cpu; /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map; +EXPORT_SYMBOL(cpu_online_map); cpumask_t phys_cpu_present_map; +EXPORT_SYMBOL(phys_cpu_present_map); /* which logical CPU number maps to which CPU (physical APIC ID) */ volatile int ia64_cpu_to_sapicid[NR_CPUS]; +EXPORT_SYMBOL(ia64_cpu_to_sapicid); static volatile cpumask_t cpu_callin_map; @@ -401,10 +405,7 @@ do_boot_cpu (int sapicid, int cpu) } Dprintk("\n"); - if (cpu_isset(cpu, cpu_callin_map)) { - /* number CPUs logically, starting from 1 (BSP is 0) */ - printk(KERN_INFO "CPU%d: CPU has booted.\n", cpu); - } else { + if (!cpu_isset(cpu, cpu_callin_map)) { printk(KERN_ERR "Processor 0x%x/0x%x is stuck.\n", cpu, sapicid); ia64_cpu_to_sapicid[cpu] = -1; cpu_clear(cpu, cpu_online_map); /* was set in smp_callin() */ @@ -467,6 +468,7 @@ smp_build_cpu_map (void) /* on which node is each logical CPU (one cacheline even for 64 CPUs) */ volatile u8 cpu_to_node_map[NR_CPUS] __cacheline_aligned; +EXPORT_SYMBOL(cpu_to_node_map); /* which logical CPUs are on which nodes */ volatile cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; @@ -578,14 +580,11 @@ __cpu_up (unsigned int cpu) if (sapicid == -1) return -EINVAL; - printk(KERN_INFO "Processor %d/%d is spinning up...\n", sapicid, cpu); - /* Processor goes to start_secondary(), sets online flag */ ret = do_boot_cpu(sapicid, cpu); if (ret < 0) return ret; - printk(KERN_INFO "Processor %d has spun up...\n", cpu); return 0; } diff -puN arch/ia64/kernel/smp.c~linus arch/ia64/kernel/smp.c --- 25/arch/ia64/kernel/smp.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/smp.c 2004-01-19 22:17:20.000000000 -0800 @@ -22,6 +22,7 @@ #include +#include #include #include #include @@ -210,6 +211,7 @@ smp_flush_tlb_all (void) { on_each_cpu((void (*)(void *))local_flush_tlb_all, 0, 1, 1); } +EXPORT_SYMBOL(smp_flush_tlb_all); void smp_flush_tlb_mm (struct mm_struct *mm) @@ -283,6 +285,7 @@ smp_call_function_single (int cpuid, voi put_cpu(); return 0; } +EXPORT_SYMBOL(smp_call_function_single); /* * this function sends a 'generic call function' IPI to all other CPUs @@ -337,6 +340,7 @@ smp_call_function (void (*func) (void *i spin_unlock(&call_lock); return 0; } +EXPORT_SYMBOL(smp_call_function); void smp_do_timer (struct pt_regs *regs) diff -puN arch/ia64/kernel/time.c~linus arch/ia64/kernel/time.c --- 25/arch/ia64/kernel/time.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/time.c 2004-01-19 22:17:20.000000000 -0800 @@ -39,6 +39,7 @@ EXPORT_SYMBOL(jiffies_64); #ifdef CONFIG_IA64_DEBUG_IRQ unsigned long last_cli_ip; +EXPORT_SYMBOL(last_cli_ip); #endif diff -puN arch/ia64/kernel/unwind.c~linus arch/ia64/kernel/unwind.c --- 25/arch/ia64/kernel/unwind.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/kernel/unwind.c 2004-01-19 22:17:20.000000000 -0800 @@ -26,6 +26,7 @@ * o if both the unw.lock spinlock and a script's read-write lock must be * acquired, then the read-write lock must be acquired first. */ +#include #include #include #include @@ -392,6 +393,7 @@ unw_access_gr (struct unw_frame_info *in } return 0; } +EXPORT_SYMBOL(unw_access_gr); int unw_access_br (struct unw_frame_info *info, int regnum, unsigned long *val, int write) @@ -423,6 +425,7 @@ unw_access_br (struct unw_frame_info *in *val = *addr; return 0; } +EXPORT_SYMBOL(unw_access_br); int unw_access_fr (struct unw_frame_info *info, int regnum, struct ia64_fpreg *val, int write) @@ -467,6 +470,7 @@ unw_access_fr (struct unw_frame_info *in *val = *addr; return 0; } +EXPORT_SYMBOL(unw_access_fr); int unw_access_ar (struct unw_frame_info *info, int regnum, unsigned long *val, int write) @@ -559,6 +563,7 @@ unw_access_ar (struct unw_frame_info *in *val = *addr; return 0; } +EXPORT_SYMBOL(unw_access_ar); int unw_access_pr (struct unw_frame_info *info, unsigned long *val, int write) @@ -575,6 +580,7 @@ unw_access_pr (struct unw_frame_info *in *val = *addr; return 0; } +EXPORT_SYMBOL(unw_access_pr); /* Routines to manipulate the state stack. */ @@ -1897,6 +1903,7 @@ unw_unwind (struct unw_frame_info *info) STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return retval; } +EXPORT_SYMBOL(unw_unwind); int unw_unwind_to_user (struct unw_frame_info *info) @@ -1917,6 +1924,7 @@ unw_unwind_to_user (struct unw_frame_inf UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); return -1; } +EXPORT_SYMBOL(unw_unwind_to_user); static void init_frame_info (struct unw_frame_info *info, struct task_struct *t, @@ -2014,6 +2022,7 @@ unw_init_from_blocked_task (struct unw_f UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__); unw_init_frame_info(info, t, sw); } +EXPORT_SYMBOL(unw_init_from_blocked_task); static void init_unwind_table (struct unw_table *table, const char *name, unsigned long segment_base, diff -puN arch/ia64/lib/io.c~linus arch/ia64/lib/io.c --- 25/arch/ia64/lib/io.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/lib/io.c 2004-01-19 22:17:20.000000000 -0800 @@ -1,4 +1,5 @@ #include +#include #include #include @@ -17,6 +18,7 @@ __ia64_memcpy_fromio (void * to, unsigne from++; } } +EXPORT_SYMBOL(__ia64_memcpy_fromio); /* * Copy data from "real" memory space to IO memory space. @@ -32,6 +34,7 @@ __ia64_memcpy_toio (unsigned long to, vo to++; } } +EXPORT_SYMBOL(__ia64_memcpy_toio); /* * "memset" on IO memory space. @@ -48,6 +51,7 @@ __ia64_memset_c_io (unsigned long dst, u dst++; } } +EXPORT_SYMBOL(__ia64_memset_c_io); #ifdef CONFIG_IA64_GENERIC diff -puN arch/ia64/lib/Makefile~linus arch/ia64/lib/Makefile --- 25/arch/ia64/lib/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/lib/Makefile 2004-01-19 22:17:20.000000000 -0800 @@ -2,11 +2,13 @@ # Makefile for ia64-specific library routines.. # +obj-y := io.o + lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o \ checksum.o clear_page.o csum_partial_copy.o copy_page.o \ clear_user.o strncpy_from_user.o strlen_user.o strnlen_user.o \ - flush.o io.o ip_fast_csum.o do_csum.o \ + flush.o ip_fast_csum.o do_csum.o \ memset.o strlen.o swiotlb.o lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o diff -puN arch/ia64/lib/memcpy_mck.S~linus arch/ia64/lib/memcpy_mck.S --- 25/arch/ia64/lib/memcpy_mck.S~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/lib/memcpy_mck.S 2004-01-19 22:17:20.000000000 -0800 @@ -155,7 +155,7 @@ GLOBAL_ENTRY(__copy_user) mov ar.ec=2 (p10) br.dpnt.few .aligned_src_tail ;; -// .align 32 + TEXT_ALIGN(32) 1: EX(.ex_handler, (p16) ld8 r34=[src0],16) EK(.ex_handler, (p16) ld8 r38=[src1],16) @@ -312,7 +312,7 @@ EK(.ex_handler, (p[D]) st8 [dst1] = t15, (p7) mov ar.lc = r21 (p8) mov ar.lc = r0 ;; -// .align 32 + TEXT_ALIGN(32) 1: lfetch.fault [src_pre_mem], 128 lfetch.fault.excl [dst_pre_mem], 128 br.cloop.dptk.few 1b @@ -518,7 +518,7 @@ EK(.ex_handler, (p17) st8 [dst1]=r39,8) shrp r21=r22,r38,shift; /* speculative work */ \ br.sptk.few .unaligned_src_tail /* branch out of jump table */ \ ;; -// .align 32 + TEXT_ALIGN(32) .jump_table: COPYU(8) // unaligned cases .jmp1: diff -puN arch/ia64/lib/memset.S~linus arch/ia64/lib/memset.S --- 25/arch/ia64/lib/memset.S~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/lib/memset.S 2004-01-19 22:17:20.000000000 -0800 @@ -125,7 +125,7 @@ GLOBAL_ENTRY(memset) (p_zr) br.cond.dptk.many .l1b // Jump to use stf.spill ;; } -// .align 32 // -------------------------- // L1A: store ahead into cache lines; fill later + TEXT_ALIGN(32) // --------------------- // L1A: store ahead into cache lines; fill later { .mmi and tmp = -(LINE_SIZE), cnt // compute end of range mov ptr9 = ptr1 // used for prefetching @@ -194,7 +194,7 @@ GLOBAL_ENTRY(memset) br.cond.dpnt.many .move_bytes_from_alignment // Branch no. 3 ;; } -// .align 32 + TEXT_ALIGN(32) .l1b: // ------------------------------------ // L1B: store ahead into cache lines; fill later { .mmi and tmp = -(LINE_SIZE), cnt // compute end of range @@ -261,7 +261,7 @@ GLOBAL_ENTRY(memset) and cnt = 0x1f, cnt // compute the remaining cnt mov.i ar.lc = loopcnt ;; } -// .align 32 + TEXT_ALIGN(32) .l2: // ------------------------------------ // L2A: store 32B in 2 cycles { .mmb stf8 [ptr1] = fvalue, 8 diff -puN arch/ia64/Makefile~linus arch/ia64/Makefile --- 25/arch/ia64/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/Makefile 2004-01-19 22:17:20.000000000 -0800 @@ -5,10 +5,11 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1998-2003 by David Mosberger-Tang +# Copyright (C) 1998-2004 by David Mosberger-Tang # NM := $(CROSS_COMPILE)nm -B +READELF := $(CROSS_COMPILE)readelf export AWK @@ -25,9 +26,8 @@ CFLAGS_KERNEL := -mconstant-gp GCC_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f1 -d'.') GCC_MINOR_VERSION=$(shell $(CC) -v 2>&1 | fgrep 'gcc version' | cut -f3 -d' ' | cut -f2 -d'.') -GAS_STATUS=$(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) - -CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP)) +GAS_STATUS = $(shell $(srctree)/arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) +CPPFLAGS += $(shell $(srctree)/arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP) $(READELF)) ifeq ($(GAS_STATUS),buggy) $(error Sorry, you need a newer version of the assember, one that is built from \ @@ -71,15 +71,15 @@ boot := arch/ia64/hp/sim/boot .PHONY: boot compressed check -all: compressed +all: compressed unwcheck compressed: vmlinux.gz vmlinux.gz: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -check: vmlinux - arch/ia64/scripts/unwcheck.sh $< +unwcheck: vmlinux + -$(Q)READELF=$(READELF) $(srctree)/arch/ia64/scripts/unwcheck.py $< archclean: $(Q)$(MAKE) $(clean)=$(boot) @@ -88,7 +88,7 @@ CLEAN_FILES += include/asm-ia64/.offsets prepare: include/asm-ia64/offsets.h -arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h +arch/ia64/kernel/asm-offsets.s: include/asm include/linux/version.h include/config/MARKER include/asm-ia64/offsets.h: arch/ia64/kernel/asm-offsets.s $(call filechk,gen-asm-offsets) @@ -108,4 +108,5 @@ boot: lib/lib.a vmlinux define archhelp echo '* compressed - Build compressed kernel image' echo ' boot - Build vmlinux and bootloader for Ski simulator' + echo '* unwcheck - Check vmlinux for invalid unwind info' endef diff -puN arch/ia64/mm/extable.c~linus arch/ia64/mm/extable.c --- 25/arch/ia64/mm/extable.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/mm/extable.c 2004-01-19 22:17:20.000000000 -0800 @@ -10,6 +10,11 @@ #include #include +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish) +{ +} + const struct exception_table_entry * search_extable (const struct exception_table_entry *first, const struct exception_table_entry *last, diff -puN arch/ia64/mm/init.c~linus arch/ia64/mm/init.c --- 25/arch/ia64/mm/init.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/mm/init.c 2004-01-19 22:17:20.000000000 -0800 @@ -43,15 +43,16 @@ extern void ia64_tlb_init (void); unsigned long MAX_DMA_ADDRESS = PAGE_OFFSET + 0x100000000UL; #ifdef CONFIG_VIRTUAL_MEM_MAP - unsigned long vmalloc_end = VMALLOC_END_INIT; - struct page *vmem_map; - - EXPORT_SYMBOL(vmem_map); +unsigned long vmalloc_end = VMALLOC_END_INIT; +EXPORT_SYMBOL(vmalloc_end); +struct page *vmem_map; +EXPORT_SYMBOL(vmem_map); #endif static int pgt_cache_water[2] = { 25, 50 }; struct page *zero_page_memmap_ptr; /* map entry for zero page */ +EXPORT_SYMBOL(zero_page_memmap_ptr); void check_pgt_cache (void) @@ -457,6 +458,7 @@ ia64_pfn_valid (unsigned long pfn) return __get_user(byte, (char *) pfn_to_page(pfn)) == 0; } +EXPORT_SYMBOL(ia64_pfn_valid); int find_largest_hole (u64 start, u64 end, void *arg) diff -puN arch/ia64/mm/numa.c~linus arch/ia64/mm/numa.c --- 25/arch/ia64/mm/numa.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/mm/numa.c 2004-01-19 22:17:20.000000000 -0800 @@ -18,6 +18,7 @@ #include #include #include +#include #include static struct memblk *sysfs_memblks; @@ -28,7 +29,7 @@ static struct cpu *sysfs_cpus; * The following structures are usually initialized by ACPI or * similar mechanisms and describe the NUMA characteristics of the machine. */ -int num_memblks = 0; +int num_memblks; struct node_memblk_s node_memblk[NR_MEMBLKS]; struct node_cpuid_s node_cpuid[NR_CPUS]; /* diff -puN arch/ia64/mm/tlb.c~linus arch/ia64/mm/tlb.c --- 25/arch/ia64/mm/tlb.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/mm/tlb.c 2004-01-19 22:17:20.000000000 -0800 @@ -10,6 +10,7 @@ * IPI based ptc implementation and A-step IPI implementation. */ #include +#include #include #include #include @@ -126,6 +127,7 @@ local_flush_tlb_all (void) local_irq_restore(flags); ia64_srlz_i(); /* srlz.i implies srlz.d */ } +EXPORT_SYMBOL(local_flush_tlb_all); void flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long end) @@ -162,6 +164,7 @@ flush_tlb_range (struct vm_area_struct * ia64_srlz_i(); /* srlz.i implies srlz.d */ } +EXPORT_SYMBOL(flush_tlb_range); void __init ia64_tlb_init (void) diff -puN arch/ia64/pci/pci.c~linus arch/ia64/pci/pci.c --- 25/arch/ia64/pci/pci.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/pci/pci.c 2004-01-19 22:17:20.000000000 -0800 @@ -223,6 +223,9 @@ add_window (struct acpi_resource *res, v status = acpi_resource_to_address64(res, &addr); if (ACPI_SUCCESS(status)) { + if (!addr.address_length) + return AE_OK; + if (addr.resource_type == ACPI_MEMORY_RANGE) { flags = IORESOURCE_MEM; root = &iomem_resource; diff -puN /dev/null arch/ia64/scripts/check-text-align.S --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ia64/scripts/check-text-align.S 2004-01-19 22:17:20.000000000 -0800 @@ -0,0 +1,6 @@ + .proc foo + .prologue +foo: .save rp, r2 + nop 0 + .align 64 + .endp foo diff -puN /dev/null arch/ia64/scripts/unwcheck.py --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ia64/scripts/unwcheck.py 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Usage: unwcheck.py FILE +# +# This script checks the unwind info of each function in file FILE +# and verifies that the sum of the region-lengths matches the total +# length of the function. +# +# Based on a shell/awk script originally written by Harish Patil, +# which was converted to Perl by Matthew Chapman, which was converted +# to Python by David Mosberger. +# +import os +import re +import sys + +if len(sys.argv) != 2: + print "Usage: %s FILE" % sys.argv[0] + sys.exit(2) + +readelf = os.getenv("READELF", "readelf") + +start_pattern = re.compile("<([^>]*)>: \[0x([0-9a-f]+)-0x([0-9a-f]+)\]") +rlen_pattern = re.compile(".*rlen=([0-9]+)") + +def check_func (func, slots, rlen_sum): + if slots != rlen_sum: + global num_errors + num_errors += 1 + if not func: func = "[%#x-%#x]" % (start, end) + print "ERROR: %s: %lu slots, total region length = %lu" % (func, slots, rlen_sum) + return + +num_funcs = 0 +num_errors = 0 +func = False +slots = 0 +rlen_sum = 0 +for line in os.popen("%s -u %s" % (readelf, sys.argv[1])): + m = start_pattern.match(line) + if m: + check_func(func, slots, rlen_sum) + + func = m.group(1) + start = long(m.group(2), 16) + end = long(m.group(3), 16) + slots = 3 * (end - start) / 16 + rlen_sum = 0L + num_funcs += 1 + else: + m = rlen_pattern.match(line) + if m: + rlen_sum += long(m.group(1)) +check_func(func, slots, rlen_sum) + +if num_errors == 0: + print "No errors detected in %u functions." % num_funcs +else: + if num_errors > 1: + err="errors" + else: + err="error" + print "%u %s detected in %u functions." % (num_errors, err, num_funcs) + sys.exit(1) diff -puN -L arch/ia64/scripts/unwcheck.sh arch/ia64/scripts/unwcheck.sh~linus /dev/null --- 25/arch/ia64/scripts/unwcheck.sh +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,109 +0,0 @@ -#!/bin/sh -# Usage: unwcheck.sh -# Pre-requisite: readelf [from Gnu binutils package] -# Purpose: Check the following invariant -# For each code range in the input binary: -# Sum[ lengths of unwind regions] = Number of slots in code range. -# Author : Harish Patil -# First version: January 2002 -# Modified : 2/13/2002 -# Modified : 3/15/2002: duplicate detection -readelf -u $1 | gawk '\ - function todec(hexstr){ - dec = 0; - l = length(hexstr); - for (i = 1; i <= l; i++) - { - c = substr(hexstr, i, 1); - if (c == "A") - dec = dec*16 + 10; - else if (c == "B") - dec = dec*16 + 11; - else if (c == "C") - dec = dec*16 + 12; - else if (c == "D") - dec = dec*16 + 13; - else if (c == "E") - dec = dec*16 + 14; - else if (c == "F") - dec = dec*16 + 15; - else - dec = dec*16 + c; - } - return dec; - } - BEGIN { first = 1; sum_rlen = 0; no_slots = 0; errors=0; no_code_ranges=0; } - { - if (NF==5 && $3=="info") - { - no_code_ranges += 1; - if (first == 0) - { - if (sum_rlen != no_slots) - { - print full_code_range; - print " ", "lo = ", lo, " hi =", hi; - print " ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots; - print " "," ", "*******ERROR ***********"; - print " "," ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots; - errors += 1; - } - sum_rlen = 0; - } - full_code_range = $0; - code_range = $2; - gsub("..$", "", code_range); - gsub("^.", "", code_range); - split(code_range, addr, "-"); - lo = toupper(addr[1]); - - code_range_lo[no_code_ranges] = addr[1]; - occurs[addr[1]] += 1; - full_range[addr[1]] = $0; - - gsub("0X.[0]*", "", lo); - hi = toupper(addr[2]); - gsub("0X.[0]*", "", hi); - no_slots = (todec(hi) - todec(lo))/ 16*3 - first = 0; - } - if (index($0,"rlen") > 0 ) - { - rlen_str = substr($0, index($0,"rlen")); - rlen = rlen_str; - gsub("rlen=", "", rlen); - gsub(")", "", rlen); - sum_rlen = sum_rlen + rlen; - } - } - END { - if (first == 0) - { - if (sum_rlen != no_slots) - { - print "code_range=", code_range; - print " ", "lo = ", lo, " hi =", hi; - print " ", "sum_rlen = ", sum_rlen, "no_slots = " no_slots; - print " "," ", "*******ERROR ***********"; - print " "," ", "sum_rlen:", sum_rlen, " != no_slots:" no_slots; - errors += 1; - } - } - no_duplicates = 0; - for (i=1; i<=no_code_ranges; i++) - { - cr = code_range_lo[i]; - if (reported_cr[cr]==1) continue; - if ( occurs[cr] > 1) - { - reported_cr[cr] = 1; - print "Code range low ", code_range_lo[i], ":", full_range[cr], " occurs: ", occurs[cr], " times."; - print " "; - no_duplicates++; - } - } - print "======================================" - print "Total errors:", errors, "/", no_code_ranges, " duplicates:", no_duplicates; - print "======================================" - } - ' diff -puN arch/ia64/sn/fakeprom/fprom.lds~linus arch/ia64/sn/fakeprom/fprom.lds --- 25/arch/ia64/sn/fakeprom/fprom.lds~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/fakeprom/fprom.lds 2004-01-19 22:17:21.000000000 -0800 @@ -1,33 +1,9 @@ /* + * 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) 2002-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ OUTPUT_FORMAT("elf64-ia64-little") diff -puN arch/ia64/sn/fakeprom/README~linus arch/ia64/sn/fakeprom/README --- 25/arch/ia64/sn/fakeprom/README~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/fakeprom/README 2004-01-19 22:17:21.000000000 -0800 @@ -1,33 +1,9 @@ /* + * 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) 2002-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ This directory contains the files required to build diff -puN arch/ia64/sn/io/cdl.c~linus arch/ia64/sn/io/cdl.c --- 25/arch/ia64/sn/io/cdl.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/cdl.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -11,18 +10,15 @@ #include #include #include -#include #include -#include +#include #include "asm/sn/ioerror_handling.h" #include /* these get called directly in cdl_add_connpt in fops bypass hack */ -extern int pcibr_attach(vertex_hdl_t); extern int xbow_attach(vertex_hdl_t); extern int pic_attach(vertex_hdl_t); - /* * cdl: Connection and Driver List * @@ -32,14 +28,12 @@ extern int pic_attach(vertex_hdl_t); * IO Infrastructure Drivers e.g. pcibr. */ -#define MAX_SGI_IO_INFRA_DRVR 7 +#define MAX_SGI_IO_INFRA_DRVR 5 static struct cdl sgi_infrastructure_drivers[MAX_SGI_IO_INFRA_DRVR] = { - { XBRIDGE_WIDGET_PART_NUM, XBRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, - { BRIDGE_WIDGET_PART_NUM, BRIDGE_WIDGET_MFGR_NUM, pcibr_attach /* &pcibr_fops */}, - { PIC_WIDGET_PART_NUM_BUS0, PIC_WIDGET_MFGR_NUM, pic_attach /* &pic_fops */}, - { PIC_WIDGET_PART_NUM_BUS1, PIC_WIDGET_MFGR_NUM, pic_attach /* &pic_fops */}, + { PIC_WIDGET_PART_NUM_BUS0, PIC_WIDGET_MFGR_NUM, pic_attach /* &pcibr_fops */}, + { PIC_WIDGET_PART_NUM_BUS1, PIC_WIDGET_MFGR_NUM, pic_attach /* &pcibr_fops */}, { XXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, { XBOW_WIDGET_PART_NUM, XBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, { PXBOW_WIDGET_PART_NUM, XXBOW_WIDGET_MFGR_NUM, xbow_attach /* &xbow_fops */}, diff -puN arch/ia64/sn/io/drivers/ioconfig_bus.c~linus arch/ia64/sn/io/drivers/ioconfig_bus.c --- 25/arch/ia64/sn/io/drivers/ioconfig_bus.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/drivers/ioconfig_bus.c 2004-01-19 22:17:21.000000000 -0800 @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -34,6 +33,7 @@ */ static vertex_hdl_t ioconfig_bus_handle; static unsigned long ioconfig_bus_debug; +static struct ioconfig_parm parm; #ifdef IOCONFIG_BUS_DEBUG #define DBG(x...) printk(x) @@ -41,8 +41,6 @@ static unsigned long ioconfig_bus_debug; #define DBG(x...) #endif -static u64 ioconfig_file; -static u64 ioconfig_file_size; static u64 ioconfig_activated; static char ioconfig_kernopts[128]; @@ -50,8 +48,6 @@ static char ioconfig_kernopts[128]; * For debugging purpose .. hardcode a table .. */ struct ascii_moduleid *ioconfig_bus_table; -u64 ioconfig_bus_table_size; - static int free_entry; static int new_entry; @@ -68,6 +64,8 @@ ioconfig_get_busnum(char *io_moduleid, i *bus_num = -1; temp = ioconfig_bus_table; + if (!ioconfig_bus_table) + return; for (index = 0; index < free_entry; temp++, index++) { if ( (io_moduleid[0] == temp->io_moduleid[0]) && (io_moduleid[1] == temp->io_moduleid[1]) && @@ -101,6 +99,10 @@ dump_ioconfig_table(void) struct ascii_moduleid *temp; temp = ioconfig_bus_table; + if (!temp) { + DBG("ioconfig_bus_table tabel empty\n"); + return; + } while (index < free_entry) { DBG("ASSCI Module ID %s\n", temp->io_moduleid); temp++; @@ -145,7 +147,7 @@ int nextline(char *buffer, char **next, * memory by ioconfig command in EFI and builds the * persistent pci bus naming table. */ -void +int build_moduleid_table(char *file_contents, struct ascii_moduleid *table) { /* @@ -160,8 +162,17 @@ build_moduleid_table(char *file_contents struct ascii_moduleid *moduleid; line = kmalloc(256, GFP_KERNEL); - memset(line, 0,256); name = kmalloc(125, GFP_KERNEL); + if (!line || !name) { + if (line) + kfree(line); + if (name) + kfree(name); + printk("build_moduleid_table(): Unabled to allocate memmory"); + return -ENOMEM; + } + + memset(line, 0,256); memset(name, 0, 125); moduleid = table; curr = file_contents; @@ -210,46 +221,21 @@ build_moduleid_table(char *file_contents kfree(line); kfree(name); - return; + return 0; } -void +int ioconfig_bus_init(void) { - struct ia64_sal_retval ret_stuff; - u64 *temp; - int cnode; - DBG("ioconfig_bus_init called.\n"); - for (cnode = 0; cnode < numnodes; cnode++) { - nasid_t nasid; - /* - * Make SAL call to get the address of the bus configuration table. - */ - ret_stuff.status = (uint64_t)0; - ret_stuff.v0 = (uint64_t)0; - ret_stuff.v1 = (uint64_t)0; - ret_stuff.v2 = (uint64_t)0; - nasid = COMPACT_TO_NASID_NODEID(cnode); - SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0); - temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0); - ioconfig_file = *temp; - DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid, - ret_stuff.v0); - if (ioconfig_file) { - ioconfig_file_size = ret_stuff.v1; - ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE); - ioconfig_activated = 1; - break; - } + ioconfig_bus_table = kmalloc( 512, GFP_KERNEL ); + if (!ioconfig_bus_table) { + printk("ioconfig_bus_init : cannot allocate memory\n"); + return -1; } - DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n", - ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size); - - ioconfig_bus_table = kmalloc( 512, GFP_KERNEL ); memset(ioconfig_bus_table, 0, 512); /* @@ -260,27 +246,17 @@ ioconfig_bus_init(void) * ioconfig="..." kernel options given. */ DBG("ioconfig_bus_init: Kernel Options given.\n"); - (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table); + if ( build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table) < 0 ) + return -1; (void) dump_ioconfig_table(); - return; } - - if (ioconfig_activated) { - DBG("ioconfig_bus_init: ioconfig file given.\n"); - (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table); - (void) dump_ioconfig_table(); - } else { - DBG("ioconfig_bus_init: ioconfig command not executed in prom\n"); - } - + return 0; } void ioconfig_bus_new_entries(void) { - - - int index = 0; + int index; struct ascii_moduleid *temp; if ((ioconfig_activated) && (free_entry > new_entry)) { @@ -290,6 +266,10 @@ ioconfig_bus_new_entries(void) return; index = new_entry; + if (!ioconfig_bus_table) { + printk("ioconfig_bus_table table is empty\n"); + return; + } temp = &ioconfig_bus_table[index]; while (index < free_entry) { printk("%s\n", (char *)temp); @@ -302,17 +282,21 @@ ioconfig_bus_new_entries(void) static int ioconfig_bus_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - - struct ioconfig_parm parm; - /* * Copy in the parameters. */ - copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)); + if (copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm))) + return -EFAULT; parm.number = free_entry - new_entry; parm.ioconfig_activated = ioconfig_activated; - copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)); - copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry)); + if (copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm))) + return -EFAULT; + + if (!ioconfig_bus_table) + return -EFAULT; + + if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry))) + return -EFAULT; return 0; } @@ -344,9 +328,9 @@ static int ioconfig_bus_close(struct ino } struct file_operations ioconfig_bus_fops = { - .ioctl = ioconfig_bus_ioctl, - .open = ioconfig_bus_open, /* open */ - .release = ioconfig_bus_close /* release */ + .ioctl = ioconfig_bus_ioctl, + .open = ioconfig_bus_open, /* open */ + .release=ioconfig_bus_close /* release */ }; @@ -357,7 +341,6 @@ struct file_operations ioconfig_bus_fops */ int init_ioconfig_bus(void) { - ioconfig_bus_handle = NULL; ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus", 0, 0, 0, 0, @@ -368,8 +351,7 @@ int init_ioconfig_bus(void) panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n"); } - return(0); - + return 0; } static int __init ioconfig_bus_setup (char *str) diff -puN arch/ia64/sn/io/drivers/Makefile~linus arch/ia64/sn/io/drivers/Makefile --- 25/arch/ia64/sn/io/drivers/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/drivers/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,6 +7,4 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += ioconfig_bus.o diff -puN arch/ia64/sn/io/hwgfs/hcl.c~linus arch/ia64/sn/io/hwgfs/hcl.c --- 25/arch/ia64/sn/io/hwgfs/hcl.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/hcl.c 2004-01-19 22:17:21.000000000 -0800 @@ -23,41 +23,16 @@ #include #include #include -#include #include #include #include -#define HCL_NAME "SGI-HWGRAPH COMPATIBILITY DRIVER" -#define HCL_TEMP_NAME "HCL_TEMP_NAME_USED_FOR_HWGRAPH_VERTEX_CREATE" -#define HCL_TEMP_NAME_LEN 44 -#define HCL_VERSION "1.0" - #define vertex_hdl_t hwgfs_handle_t + vertex_hdl_t hwgraph_root; vertex_hdl_t linux_busnum; - -extern void pci_bus_cvlink_init(void); - -/* - * Debug flag definition. - */ -#define OPTION_NONE 0x00 -#define HCL_DEBUG_NONE 0x00000 -#define HCL_DEBUG_ALL 0x0ffff -#if defined(CONFIG_HCL_DEBUG) -static unsigned int hcl_debug_init __initdata = HCL_DEBUG_NONE; -#endif -static unsigned int hcl_debug = HCL_DEBUG_NONE; -#if defined(CONFIG_HCL_DEBUG) && !defined(MODULE) -static unsigned int boot_options = OPTION_NONE; -#endif - -invplace_t invplace_none = { - GRAPH_VERTEX_NONE, - GRAPH_VERTEX_PLACE_NONE, - NULL -}; +extern int pci_bus_cvlink_init(void); +unsigned long hwgraph_debug_mask; /* * init_hcl() - Boot time initialization. @@ -71,19 +46,16 @@ int __init init_hcl(void) extern int init_hwgfs_fs(void); int rv = 0; - if (IS_RUNNING_ON_SIMULATOR()) { - extern u64 klgraph_addr[]; - klgraph_addr[0] = 0xe000003000030000; - } - init_hwgfs_fs(); /* * Create the hwgraph_root. */ rv = hwgraph_path_add(NULL, EDGE_LBL_HW, &hwgraph_root); - if (rv) - printk ("WARNING: init_hcl: Failed to create hwgraph_root. Error = %d.\n", rv); + if (rv) { + printk("init_hcl: Failed to create hwgraph_root.\n"); + return -1; + } /* * Initialize the HCL string table. @@ -96,66 +68,23 @@ int __init init_hcl(void) */ rv = hwgraph_path_add(hwgraph_root, EDGE_LBL_LINUX_BUS, &linux_busnum); if (linux_busnum == NULL) { - panic("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS); - return(0); + printk("HCL: Unable to create %s\n", EDGE_LBL_LINUX_BUS); + return -1; } - pci_bus_cvlink_init(); + if (pci_bus_cvlink_init() < 0 ) { + printk("init_hcl: Failed to create pcibus cvlink.\n"); + return -1; + } /* - * Initialize the ifconfgi_net driver that does network devices * Persistent Naming. */ init_ioconfig_bus(); - return(0); - -} - - -/* - * hcl_setup() - Process boot time parameters if given. - * "hcl=" - * This routine gets called only if "hcl=" is given in the - * boot line and before init_hcl(). - * - * We currently do not have any boot options .. when we do, - * functionalities can be added here. - * - */ -static int __init hcl_setup(char *str) -{ - while ( (*str != '\0') && !isspace (*str) ) - { -#ifdef CONFIG_HCL_DEBUG - if (strncmp (str, "all", 3) == 0) { - hcl_debug_init |= HCL_DEBUG_ALL; - str += 3; - } else - return 0; -#endif - if (*str != ',') return 0; - ++str; - } - - return 1; - -} - -__setup("hcl=", hcl_setup); - - -/* - * Set device specific "fast information". - * - */ -void -hwgraph_fastinfo_set(vertex_hdl_t de, arbitrary_info_t fastinfo) -{ - labelcl_info_replace_IDX(de, HWGRAPH_FASTINFO, fastinfo, NULL); + return 0; } - /* * Get device specific "fast information". * @@ -181,25 +110,6 @@ hwgraph_fastinfo_get(vertex_hdl_t de) /* - * hwgraph_connectpt_set - Sets the connect point handle in de to the - * given connect_de handle. By default, the connect point of the - * node is the parent. This effectively changes this assumption. - */ -int -hwgraph_connectpt_set(vertex_hdl_t de, vertex_hdl_t connect_de) -{ - int rv; - - if (!de) - return(-1); - - rv = labelcl_info_connectpt_set(de, connect_de); - - return(rv); -} - - -/* * hwgraph_connectpt_get: Returns the entry's connect point. * */ @@ -403,39 +313,6 @@ hwgraph_vertex_destroy(vertex_hdl_t de) return(0); } -#if 0 -/* - * hwgraph_edge_add - This routines has changed from the original conext. - * All it does now is to create a symbolic link from "from" to "to". - */ -/* ARGSUSED */ -int -hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name) -{ - - char *path, *link; - vertex_hdl_t handle = NULL; - int rv, i; - - handle = hwgfs_find_handle(from, name, 0, 0, 0, 1); - if (handle) { - return(0); - } - - path = kmalloc(1024, GFP_KERNEL); - memset(path, 0x0, 1024); - link = kmalloc(1024, GFP_KERNEL); - memset(path, 0x0, 1024); - i = hwgfs_generate_path (to, link, 1024); - rv = hwgfs_mk_symlink (from, (const char *)name, - DEVFS_FL_DEFAULT, link, - &handle, NULL); - return(0); - - -} -#endif - int hwgraph_edge_add(vertex_hdl_t from, vertex_hdl_t to, char *name) { @@ -448,8 +325,14 @@ hwgraph_edge_add(vertex_hdl_t from, vert int i, count; path = kmalloc(1024, GFP_KERNEL); + if (!path) + return -ENOMEM; memset((char *)path, 0x0, 1024); link = kmalloc(1024, GFP_KERNEL); + if (!link) { + kfree(path); + return -ENOMEM; + } memset((char *)link, 0x0, 1024); i = hwgfs_generate_path (from, path, 1024); @@ -706,39 +589,6 @@ hwgraph_traverse(vertex_hdl_t de, char * } /* - * hwgraph_path_to_vertex - Return the entry handle for the given - * pathname .. assume traverse symlinks too!. - */ -vertex_hdl_t -hwgraph_path_to_vertex(char *path) -{ - return(hwgfs_find_handle(NULL, /* start dir */ - path, /* path */ - 0, /* major */ - 0, /* minor */ - 0, /* char | block */ - 1)); /* traverse symlinks */ -} - -/* - * hwgraph_inventory_remove - Removes an inventory entry. - * - * Remove an inventory item associated with a vertex. It is the caller's - * responsibility to make sure that there are no races between removing - * inventory from a vertex and simultaneously removing that vertex. -*/ -int -hwgraph_inventory_remove( vertex_hdl_t de, - int class, - int type, - major_t controller, - minor_t unit, - int state) -{ - return(0); /* Just a Stub for IRIX code. */ -} - -/* * Find the canonical name for a given vertex by walking back through * connectpt's until we hit the hwgraph root vertex (or until we run * out of buffer space or until something goes wrong). @@ -750,7 +600,7 @@ hwgraph_inventory_remove( vertex_hdl_t d * "/" but rather it just stops right before /dev .. */ int -hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, uint buflen) +hwgraph_vertex_name_get(vertex_hdl_t vhdl, char *buf, unsigned int buflen) { char *locbuf; int pos; @@ -785,34 +635,60 @@ hwgraph_vertex_name_get(vertex_hdl_t vhd #define DEVNAME_UNKNOWN "UnknownDevice" char * -vertex_to_name(vertex_hdl_t vhdl, char *buf, uint buflen) +vertex_to_name(vertex_hdl_t vhdl, char *buf, unsigned int buflen) { - if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS) - return(buf); - else - return(DEVNAME_UNKNOWN); + if (hwgraph_vertex_name_get(vhdl, buf, buflen) == GRAPH_SUCCESS) + return(buf); + else + return(DEVNAME_UNKNOWN); } -graph_error_t -hwgraph_edge_remove(vertex_hdl_t from, char *name, vertex_hdl_t *toptr) -{ - return(GRAPH_ILLEGAL_REQUEST); -} -graph_error_t -hwgraph_vertex_unref(vertex_hdl_t vhdl) +void +hwgraph_debug(char *file, char * function, int line, vertex_hdl_t vhdl1, vertex_hdl_t vhdl2, char *format, ...) { - return(GRAPH_ILLEGAL_REQUEST); -} + int pos; + char *hwpath; + va_list ap; + + if ( !hwgraph_debug_mask ) + return; + + hwpath = kmalloc(MAXDEVNAME, GFP_KERNEL); + if (!hwpath) { + printk("HWGRAPH_DEBUG kmalloc fails at %d ", __LINE__); + return; + } + + printk("HWGRAPH_DEBUG %s %s %d : ", file, function, line); + + if (vhdl1){ + memset(hwpath, 0, MAXDEVNAME); + pos = hwgfs_generate_path(vhdl1, hwpath, MAXDEVNAME); + printk("vhdl1 = %s : ", &hwpath[pos]); + } + + if (vhdl2){ + memset(hwpath, 0, MAXDEVNAME); + pos = hwgfs_generate_path(vhdl2, hwpath, MAXDEVNAME); + printk("vhdl2 = %s :", &hwpath[pos]); + } + + memset(hwpath, 0, MAXDEVNAME); + va_start(ap, format); + vsnprintf(hwpath, 500, format, ap); + va_end(ap); + hwpath[MAXDEVNAME -1] = (char)0; /* Just in case. */ + printk(" %s", hwpath); + kfree(hwpath); +} EXPORT_SYMBOL(hwgraph_mk_dir); EXPORT_SYMBOL(hwgraph_path_add); EXPORT_SYMBOL(hwgraph_register); EXPORT_SYMBOL(hwgraph_vertex_destroy); EXPORT_SYMBOL(hwgraph_fastinfo_get); -EXPORT_SYMBOL(hwgraph_fastinfo_set); -EXPORT_SYMBOL(hwgraph_connectpt_set); EXPORT_SYMBOL(hwgraph_connectpt_get); EXPORT_SYMBOL(hwgraph_info_add_LBL); EXPORT_SYMBOL(hwgraph_info_remove_LBL); diff -puN arch/ia64/sn/io/hwgfs/hcl_util.c~linus arch/ia64/sn/io/hwgfs/hcl_util.c --- 25/arch/ia64/sn/io/hwgfs/hcl_util.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/hcl_util.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -14,16 +13,33 @@ #include #include #include -#include #include #include -#include #include #include static vertex_hdl_t hwgraph_all_cnodes = GRAPH_VERTEX_NONE; extern vertex_hdl_t hwgraph_root; +static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE; +extern int maxcpus; + +void +mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid) +{ + char cpuid_buffer[10]; + + if (cpuid == CPU_NONE) + return; + if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) { + (void)hwgraph_path_add( hwgraph_root, + EDGE_LBL_CPUNUM, + &hwgraph_all_cpuids); + } + + sprintf(cpuid_buffer, "%ld", cpuid); + (void)hwgraph_edge_add( hwgraph_all_cpuids, vhdl, cpuid_buffer); +} /* ** Return the "master" for a given vertex. A master vertex is a @@ -96,32 +112,6 @@ master_node_get(vertex_hdl_t vhdl) } } -static vertex_hdl_t hwgraph_all_cpuids = GRAPH_VERTEX_NONE; -extern int maxcpus; - -void -mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid) -{ - if (cpuid == CPU_NONE) - return; - - (void)labelcl_info_add_LBL(vhdl, INFO_LBL_CPUID, INFO_DESC_EXPORT, - (arbitrary_info_t)cpuid); - { - char cpuid_buffer[10]; - - if (hwgraph_all_cpuids == GRAPH_VERTEX_NONE) { - (void)hwgraph_path_add( hwgraph_root, - EDGE_LBL_CPUNUM, - &hwgraph_all_cpuids); - } - - sprintf(cpuid_buffer, "%ld", cpuid); - (void)hwgraph_edge_add( hwgraph_all_cpuids, - vhdl, - cpuid_buffer); - } -} /* ** If the specified device represents a node, return its @@ -161,25 +151,11 @@ mark_nodevertex_as_node(vertex_hdl_t vhd (void)hwgraph_edge_add( hwgraph_all_cnodes, vhdl, cnodeid_buffer); + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hwgraph_all_cnodes, NULL, "Creating path vhdl1\n")); } } /* -** If the specified device represents a CPU, return its cpuid; -** otherwise, return CPU_NONE. -*/ -cpuid_t -cpuvertex_to_cpuid(vertex_hdl_t vhdl) -{ - arbitrary_info_t cpuid = CPU_NONE; - - (void)labelcl_info_get_LBL(vhdl, INFO_LBL_CPUID, NULL, &cpuid); - - return((cpuid_t)cpuid); -} - - -/* ** dev_to_name converts a vertex_hdl_t into a canonical name. If the vertex_hdl_t ** represents a vertex in the hardware graph, it is converted in the ** normal way for vertices. If the vertex_hdl_t is an old vertex_hdl_t (one which @@ -197,4 +173,3 @@ dev_to_name(vertex_hdl_t dev, char *buf, return(vertex_to_name(dev, buf, buflen)); } - diff -puN arch/ia64/sn/io/hwgfs/interface.c~linus arch/ia64/sn/io/hwgfs/interface.c --- 25/arch/ia64/sn/io/hwgfs/interface.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/interface.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,36 +1,12 @@ /* + * 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 Silicon Graphics, Inc. All Rights Reserved. * * Portions based on Adam Richter's smalldevfs and thus * Copyright 2002-2003 Yggdrasil Computing, Inc. - * - * 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 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ #include @@ -40,7 +16,6 @@ #include #include #include -#include #include @@ -297,8 +272,7 @@ hwgfs_find_handle( nd.mnt = mntget(hwgfs_vfsmount); nd.dentry = dget(base ? base : hwgfs_vfsmount->mnt_sb->s_root); - if (traverse_symlinks) - nd.flags = LOOKUP_FOLLOW; + nd.flags = (traverse_symlinks ? LOOKUP_FOLLOW : 0); error = link_path_walk(name, &nd); if (likely(!error)) { diff -puN arch/ia64/sn/io/hwgfs/labelcl.c~linus arch/ia64/sn/io/hwgfs/labelcl.c --- 25/arch/ia64/sn/io/hwgfs/labelcl.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/labelcl.c 2004-01-19 22:17:21.000000000 -0800 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff -puN arch/ia64/sn/io/hwgfs/Makefile~linus arch/ia64/sn/io/hwgfs/Makefile --- 25/arch/ia64/sn/io/hwgfs/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,6 +7,4 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += hcl.o labelcl.o hcl_util.o ramfs.o interface.o diff -puN arch/ia64/sn/io/hwgfs/ramfs.c~linus arch/ia64/sn/io/hwgfs/ramfs.c --- 25/arch/ia64/sn/io/hwgfs/ramfs.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/hwgfs/ramfs.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,37 +1,13 @@ /* + * 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 Silicon Graphics, Inc. All Rights Reserved. * * Mostly shameless copied from Linus Torvalds' ramfs and thus * Copyright (C) 2000 Linus Torvalds. * 2000 Transmeta Corp. - * - * 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 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ #include diff -puN arch/ia64/sn/io/io.c~linus arch/ia64/sn/io/io.c --- 25/arch/ia64/sn/io/io.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id: io.c,v 1.2 2001/06/26 14:02:43 pfg Exp $ - * +/* * 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. @@ -20,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -29,7 +27,6 @@ #include extern xtalk_provider_t hub_provider; -extern void hub_intr_init(vertex_hdl_t hubv); static int force_fire_and_forget = 1; static int ignore_conveyor_override; @@ -86,7 +83,7 @@ hub_pio_init(vertex_hdl_t hubv) } hub_set_piomode(nasid, HUB_PIO_CONVEYOR); - mutex_spinlock_init(&hubinfo->h_bwlock); + spin_lock_init(&hubinfo->h_bwlock); init_waitqueue_head(&hubinfo->h_bwwait); } @@ -119,7 +116,6 @@ hub_piomap_alloc(vertex_hdl_t dev, /* se int bigwin, free_bw_index; nasid_t nasid; volatile hubreg_t junk; - unsigned long s; caddr_t kvaddr; #ifdef PIOMAP_UNC_ACC_SPACE uint64_t addr; @@ -167,7 +163,7 @@ hub_piomap_alloc(vertex_hdl_t dev, /* se */ tryagain: free_bw_index = -1; - s = mutex_spinlock(&hubinfo->h_bwlock); + spin_lock(&hubinfo->h_bwlock); for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { bw_piomap = hubinfo_bwin_piomap_get(hubinfo, bigwin); @@ -187,7 +183,7 @@ tryagain: if ( xtalk_addr == bw_piomap->hpio_xtalk_info.xp_xtalk_addr && widget == bw_piomap->hpio_xtalk_info.xp_target) { bw_piomap->hpio_holdcnt++; - mutex_spinunlock(&hubinfo->h_bwlock, s); + spin_unlock(&hubinfo->h_bwlock); return(bw_piomap); } } @@ -267,7 +263,7 @@ tryagain: bw_piomap->hpio_flags |= HUB_PIOMAP_IS_VALID; done: - mutex_spinunlock(&hubinfo->h_bwlock, s); + spin_unlock(&hubinfo->h_bwlock); return(bw_piomap); } @@ -287,7 +283,6 @@ hub_piomap_free(hub_piomap_t hub_piomap) vertex_hdl_t hubv; hubinfo_t hubinfo; nasid_t nasid; - unsigned long s; /* * Small windows are permanently mapped to corresponding widgets, @@ -303,7 +298,7 @@ hub_piomap_free(hub_piomap_t hub_piomap) hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; - s = mutex_spinlock(&hubinfo->h_bwlock); + spin_lock(&hubinfo->h_bwlock); /* * If this is the last hold on this mapping, free it. @@ -321,7 +316,7 @@ hub_piomap_free(hub_piomap_t hub_piomap) wake_up(&hubinfo->h_bwwait); } - mutex_spinunlock(&hubinfo->h_bwlock, s); + spin_unlock(&hubinfo->h_bwlock); } /* @@ -442,7 +437,7 @@ void hub_dmamap_free(hub_dmamap_t hub_dmamap) { hub_dmamap->hdma_flags &= ~HUB_DMAMAP_IS_VALID; - kern_free(hub_dmamap); + kfree(hub_dmamap); } /* @@ -463,12 +458,9 @@ hub_dmamap_addr( hub_dmamap_t dmamap, /* if (dmamap->hdma_flags & HUB_DMAMAP_USED) { /* If the map is FIXED, re-use is OK. */ if (!(dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + char name[MAXDEVNAME]; vhdl = dmamap->hdma_xtalk_info.xd_dev; -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_WARNING "%v: hub_dmamap_addr re-uses dmamap.\n",vhdl); -#else - printk(KERN_WARNING "%p: hub_dmamap_addr re-uses dmamap.\n", (void *)vhdl); -#endif + printk(KERN_WARNING "%s: hub_dmamap_addr re-uses dmamap.\n", vertex_to_name(vhdl, name, MAXDEVNAME)); } } else { dmamap->hdma_flags |= HUB_DMAMAP_USED; @@ -496,12 +488,9 @@ hub_dmamap_list(hub_dmamap_t hub_dmamap, if (hub_dmamap->hdma_flags & HUB_DMAMAP_USED) { /* If the map is FIXED, re-use is OK. */ if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + char name[MAXDEVNAME]; vhdl = hub_dmamap->hdma_xtalk_info.xd_dev; -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_WARNING "%v: hub_dmamap_list re-uses dmamap\n",vhdl); -#else - printk(KERN_WARNING "%p: hub_dmamap_list re-uses dmamap\n", (void *)vhdl); -#endif + printk(KERN_WARNING "%s: hub_dmamap_list re-uses dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME)); } } else { hub_dmamap->hdma_flags |= HUB_DMAMAP_USED; @@ -525,12 +514,9 @@ hub_dmamap_done(hub_dmamap_t hub_dmamap) } else { /* If the map is FIXED, re-done is OK. */ if (!(hub_dmamap->hdma_flags & HUB_DMAMAP_IS_FIXED)) { + char name[MAXDEVNAME]; vhdl = hub_dmamap->hdma_xtalk_info.xd_dev; -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_WARNING "%v: hub_dmamap_done already done with dmamap\n",vhdl); -#else - printk(KERN_WARNING "%p: hub_dmamap_done already done with dmamap\n", (void *)vhdl); -#endif + printk(KERN_WARNING "%s: hub_dmamap_done already done with dmamap\n", vertex_to_name(vhdl, name, MAXDEVNAME)); } } } @@ -601,7 +587,6 @@ void hub_provider_startup(vertex_hdl_t hubv) { hub_pio_init(hubv); - hub_intr_init(hubv); } /* @@ -808,4 +793,3 @@ xtalk_provider_t hub_provider = { (xtalk_provider_startup_f *) hub_provider_startup, (xtalk_provider_shutdown_f *) hub_provider_shutdown, }; - diff -puN arch/ia64/sn/io/machvec/Makefile~linus arch/ia64/sn/io/machvec/Makefile --- 25/arch/ia64/sn/io/machvec/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/machvec/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,6 +7,4 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += pci.o pci_dma.o pci_bus_cvlink.o iomv.o diff -puN arch/ia64/sn/io/machvec/pci_bus_cvlink.c~linus arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- 25/arch/ia64/sn/io/machvec/pci_bus_cvlink.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/machvec/pci_bus_cvlink.c 2004-01-19 22:17:21.000000000 -0800 @@ -6,37 +6,12 @@ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include -#include -#include -#include -#include -#include -#include +#include #include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include #include -#include +#include extern int bridge_rev_b_data_check_disable; @@ -53,29 +28,32 @@ vertex_hdl_t devfn_to_vertex(unsigned ch extern void register_pcibr_intr(int irq, pcibr_intr_t intr); void sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot); +extern int cbrick_type_get_nasid(nasid_t); +#define IS_OPUS(nasid) (cbrick_type_get_nasid(nasid) == MODULE_OPUSBRICK) +#define IS_ALTIX(nasid) (cbrick_type_get_nasid(nasid) == MODULE_CBRICK) /* - * For the given device, initialize whether it is a PIC device. + * Init the provider asic for a given device */ + static void -set_isPIC(struct sn_device_sysdata *device_sysdata) +set_pci_provider(struct sn_device_sysdata *device_sysdata) { pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); - pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - device_sysdata->isPIC = IS_PIC_SOFT(pcibr_soft);; + device_sysdata->pci_provider = pciio_info_pops_get(pciio_info); } /* * pci_bus_cvlink_init() - To be called once during initialization before * SGI IO Infrastructure init is called. */ -void +int pci_bus_cvlink_init(void) { - extern void ioconfig_bus_init(void); + extern int ioconfig_bus_init(void); memset(busnum_to_pcibr_vhdl, 0x0, sizeof(vertex_hdl_t) * MAX_PCI_XWIDGET); memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); @@ -84,7 +62,7 @@ pci_bus_cvlink_init(void) num_bridges = 0; - ioconfig_bus_init(); + return ioconfig_bus_init(); } /* @@ -170,62 +148,15 @@ devfn_to_vertex(unsigned char busnum, un return(device_vertex); } -/* - * For the given device, initialize the addresses for both the Device(x) Flush - * Write Buffer register and the Xbow Flush Register for the port the PCI bus - * is connected. - */ -static void -set_flush_addresses(struct pci_dev *device_dev, - struct sn_device_sysdata *device_sysdata) -{ - pciio_info_t pciio_info = pciio_info_get(device_sysdata->vhdl); - pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info); - pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - bridge_t *bridge = pcibr_soft->bs_base; - nasid_t nasid; - - /* - * Get the nasid from the bridge. - */ - nasid = NASID_GET(device_sysdata->dma_buf_sync); - if (IS_PIC_DEVICE(device_dev)) { - device_sysdata->dma_buf_sync = (volatile unsigned int *) - &bridge->b_wr_req_buf[pciio_slot].reg; - device_sysdata->xbow_buf_sync = (volatile unsigned int *) - XBOW_PRIO_LINKREGS_PTR(NODE_SWIN_BASE(nasid, 0), - pcibr_soft->bs_xid); - } else { - /* - * Accessing Xbridge and Xbow register when SHUB swapoper is on!. - */ - device_sysdata->dma_buf_sync = (volatile unsigned int *) - ((uint64_t)&(bridge->b_wr_req_buf[pciio_slot].reg)^4); - device_sysdata->xbow_buf_sync = (volatile unsigned int *) - ((uint64_t)(XBOW_PRIO_LINKREGS_PTR( - NODE_SWIN_BASE(nasid, 0), pcibr_soft->bs_xid)) ^ 4); - } - -#ifdef DEBUG - printk("set_flush_addresses: dma_buf_sync %p xbow_buf_sync %p\n", - device_sysdata->dma_buf_sync, device_sysdata->xbow_buf_sync); - -printk("set_flush_addresses: dma_buf_sync\n"); - while((volatile unsigned int )*device_sysdata->dma_buf_sync); -printk("set_flush_addresses: xbow_buf_sync\n"); - while((volatile unsigned int )*device_sysdata->xbow_buf_sync); -#endif - -} - struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS]; -// Initialize the data structures for flushing write buffers after a PIO read. -// The theory is: -// Take an unused int. pin and associate it with a pin that is in use. -// After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush -// on the in use pin. This will prevent the race condition between PIO read responses and -// DMA writes. +/* Initialize the data structures for flushing write buffers after a PIO read. + * The theory is: + * Take an unused int. pin and associate it with a pin that is in use. + * After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush + * on the in use pin. This will prevent the race condition between PIO read responses and + * DMA writes. + */ void sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot) { nasid_t nasid; @@ -247,101 +178,59 @@ sn_dma_flush_init(unsigned long start, u if (flush_nasid_list[nasid].widget_p == NULL) { flush_nasid_list[nasid].widget_p = (struct sn_flush_device_list **)kmalloc((HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *), GFP_KERNEL); + if (flush_nasid_list[nasid].widget_p <= 0) { + printk("sn_dma_flush_init: Cannot allocate memory for nasid list\n"); + return; + } memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *)); } if (bwin > 0) { - bwin--; - switch (bwin) { - case 0: - flush_nasid_list[nasid].iio_itte1 = HUB_L(IIO_ITTE_GET(nasid, 0)); - wid_num = ((flush_nasid_list[nasid].iio_itte1) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte1 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 1: - flush_nasid_list[nasid].iio_itte2 = HUB_L(IIO_ITTE_GET(nasid, 1)); - wid_num = ((flush_nasid_list[nasid].iio_itte2) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte2 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 2: - flush_nasid_list[nasid].iio_itte3 = HUB_L(IIO_ITTE_GET(nasid, 2)); - wid_num = ((flush_nasid_list[nasid].iio_itte3) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte3 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 3: - flush_nasid_list[nasid].iio_itte4 = HUB_L(IIO_ITTE_GET(nasid, 3)); - wid_num = ((flush_nasid_list[nasid].iio_itte4) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte4 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 4: - flush_nasid_list[nasid].iio_itte5 = HUB_L(IIO_ITTE_GET(nasid, 4)); - wid_num = ((flush_nasid_list[nasid].iio_itte5) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte5 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 5: - flush_nasid_list[nasid].iio_itte6 = HUB_L(IIO_ITTE_GET(nasid, 5)); - wid_num = ((flush_nasid_list[nasid].iio_itte6) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte6 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; - case 6: - flush_nasid_list[nasid].iio_itte7 = HUB_L(IIO_ITTE_GET(nasid, 6)); - wid_num = ((flush_nasid_list[nasid].iio_itte7) >> 8) & 0xf; - bus = flush_nasid_list[nasid].iio_itte7 & 0xf; - if (bus == 0x4 || bus == 0x8) - bus = 0; - else - bus = 1; - break; + int itte_index = bwin - 1; + unsigned long itte; + + itte = HUB_L(IIO_ITTE_GET(nasid, itte_index)); + flush_nasid_list[nasid].iio_itte[bwin] = itte; + wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & + IIO_ITTE_WIDGET_MASK; + bus = itte & IIO_ITTE_OFFSET_MASK; + if (bus == 0x4 || bus == 0x8) { + bus = 0; + } else { + bus = 1; } } - // if it's IO9, bus 1, we don't care about slots 1, 3, and 4. This is - // because these are the IOC4 slots and we don't flush them. + /* if it's IO9, bus 1, we don't care about slots 1 and 4. This is + * because these are the IOC4 slots and we don't flush them. + */ if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) { return; } if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) { flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc( DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL); + if (flush_nasid_list[nasid].widget_p[wid_num] <= 0) { + printk("sn_dma_flush_init: Cannot allocate memory for nasid sub-list\n"); + return; + } memset(flush_nasid_list[nasid].widget_p[wid_num], 0, DEV_PER_WIDGET * sizeof (struct sn_flush_device_list)); p = &flush_nasid_list[nasid].widget_p[wid_num][0]; for (i=0; ibus = -1; p->pin = -1; + p->slot = -1; p++; } } p = &flush_nasid_list[nasid].widget_p[wid_num][0]; for (i=0;ipin == pin && p->bus == bus) break; + if (p->pin == pin && p->bus == bus && p->slot == slot) break; if (p->pin < 0) { p->pin = pin; p->bus = bus; + p->slot = slot; break; } p++; @@ -356,25 +245,28 @@ sn_dma_flush_init(unsigned long start, u } b = (bridge_t *)(NODE_SWIN_BASE(nasid, wid_num) | (bus << 23) ); - // If it's IO9, then slot 2 maps to slot 7 and slot 6 maps to slot 8. - // To see this is non-trivial. By drawing pictures and reading manuals and talking - // to HW guys, we can see that on IO9 bus 1, slots 7 and 8 are always unused. - // Further, since we short-circuit slots 1, 3, and 4 above, we only have to worry - // about the case when there is a card in slot 2. A multifunction card will appear - // to be in slot 6 (from an interrupt point of view) also. That's the most we'll - // have to worry about. A four function card will overload the interrupt lines in - // slot 2 and 6. - // We also need to special case the 12160 device in slot 3. Fortunately, we have - // a spare intr. line for pin 4, so we'll use that for the 12160. - // All other buses have slot 3 and 4 and slots 7 and 8 unused. Since we can only - // see slots 1 and 2 and slots 5 and 6 coming through here for those buses (this - // is true only on Pxbricks with 2 physical slots per bus), we just need to add - // 2 to the slot number to find an unused slot. - // We have convinced ourselves that we will never see a case where two different cards - // in two different slots will ever share an interrupt line, so there is no need to - // special case this. - - if (isIO9(nasid) && wid_num == 0xc && bus == 0) { + /* If it's IO9, then slot 2 maps to slot 7 and slot 6 maps to slot 8. + * To see this is non-trivial. By drawing pictures and reading manuals and talking + * to HW guys, we can see that on IO9 bus 1, slots 7 and 8 are always unused. + * Further, since we short-circuit slots 1, 3, and 4 above, we only have to worry + * about the case when there is a card in slot 2. A multifunction card will appear + * to be in slot 6 (from an interrupt point of view) also. That's the most we'll + * have to worry about. A four function card will overload the interrupt lines in + * slot 2 and 6. + * We also need to special case the 12160 device in slot 3. Fortunately, we have + * a spare intr. line for pin 4, so we'll use that for the 12160. + * All other buses have slot 3 and 4 and slots 7 and 8 unused. Since we can only + * see slots 1 and 2 and slots 5 and 6 coming through here for those buses (this + * is true only on Pxbricks with 2 physical slots per bus), we just need to add + * 2 to the slot number to find an unused slot. + * We have convinced ourselves that we will never see a case where two different cards + * in two different slots will ever share an interrupt line, so there is no need to + * special case this. + */ + + if (isIO9(nasid) && ( (IS_ALTIX(nasid) && wid_num == 0xc) + || (IS_OPUS(nasid) && wid_num == 0xf) ) + && bus == 0) { if (slot == 2) { p->force_int_addr = (unsigned long)&b->b_force_always[6].intr; dev_sel = b->b_int_device; @@ -427,7 +319,7 @@ sn_pci_fixup(int arg) struct sn_widget_sysdata *widget_sysdata; struct sn_device_sysdata *device_sysdata; pcibr_intr_t intr_handle; - int cpuid; + pciio_provider_t *pci_provider; vertex_hdl_t device_vertex; pciio_intr_line_t lines; extern int numnodes; @@ -437,11 +329,10 @@ sn_pci_fixup(int arg) #ifdef CONFIG_PROC_FS extern void register_sn_procfs(void); #endif - extern void irix_io_init(void); + extern void sgi_master_io_infr_init(void); extern void sn_init_cpei_timer(void); - init_hcl(); - irix_io_init(); + sgi_master_io_infr_init(); for (cnode = 0; cnode < numnodes; cnode++) { extern void intr_init_vecblk(cnodeid_t); @@ -474,8 +365,13 @@ sn_pci_fixup(int arg) * set the root start and end so that drivers calling check_region() * won't see a conflict */ - ioport_resource.start = 0xc000000000000000; - ioport_resource.end = 0xcfffffffffffffff; + +#ifdef CONFIG_IA64_SGI_SN_SIM + if (! IS_RUNNING_ON_SIMULATOR()) { + ioport_resource.start = 0xc000000000000000; + ioport_resource.end = 0xcfffffffffffffff; + } +#endif /* * Set the root start and end for Mem Resource. @@ -490,6 +386,7 @@ sn_pci_fixup(int arg) unsigned int irq; int idx; u16 cmd; + vertex_hdl_t vhdl; unsigned long size; extern int bit_pos_to_irq(int); @@ -497,18 +394,16 @@ sn_pci_fixup(int arg) device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), GFP_KERNEL); + if (device_sysdata <= 0) { + printk("sn_pci_fixup: Cannot allocate memory for device sysdata\n"); + return; + } + device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); device_sysdata->isa64 = 0; - device_vertex = device_sysdata->vhdl; - device_dev->sysdata = (void *) device_sysdata; - set_isPIC(device_sysdata); + set_pci_provider(device_sysdata); - /* - * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush - * register addresses. - */ - set_flush_addresses(device_dev, device_sysdata); pci_read_config_word(device_dev, PCI_COMMAND, &cmd); /* @@ -517,22 +412,62 @@ sn_pci_fixup(int arg) * read from the card and it was set in the card by our * Infrastructure .. */ + vhdl = device_sysdata->vhdl; + /* Allocate the IORESOURCE_IO space first */ for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - size = 0; - size = device_dev->resource[idx].end - - device_dev->resource[idx].start; - if (size) { - device_dev->resource[idx].start = (unsigned long)pciio_pio_addr(device_vertex, 0, PCIIO_SPACE_WIN(idx), 0, size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); - device_dev->resource[idx].start |= __IA64_UNCACHED_OFFSET; - } - else - continue; + unsigned long start, end, addr; - device_dev->resource[idx].end = - device_dev->resource[idx].start + size; + if (!(device_dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = device_dev->resource[idx].start; + end = device_dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, 0, 0); + if (!addr) { + device_dev->resource[idx].start = 0; + device_dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", device_dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + device_dev->resource[idx].start = addr; + device_dev->resource[idx].end = addr + size; + } - if (device_dev->resource[idx].flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; + if (device_dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + } + + /* Allocate the IORESOURCE_MEM space next */ + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + unsigned long start, end, addr; + + if ((device_dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = device_dev->resource[idx].start; + end = device_dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, 0, 0); + if (!addr) { + device_dev->resource[idx].start = 0; + device_dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", device_dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + device_dev->resource[idx].start = addr; + device_dev->resource[idx].end = addr + size; + } if (device_dev->resource[idx].flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; @@ -544,17 +479,19 @@ sn_pci_fixup(int arg) cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ /* bit gets dropped .. no harm */ pci_write_config_word(device_dev, PCI_COMMAND, cmd); - + pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); - + device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; + device_vertex = device_sysdata->vhdl; + pci_provider = device_sysdata->pci_provider; + irqpdaindr->curr = device_dev; - intr_handle = pcibr_intr_alloc(device_vertex, NULL, lines, device_vertex); + intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex); irq = intr_handle->bi_irq; irqpdaindr->device_dev[irq] = device_dev; - cpuid = intr_handle->bi_cpu; - pcibr_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0); + (pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0); device_dev->irq = irq; register_pcibr_intr(irq, intr_handle); @@ -825,10 +762,8 @@ pci_bus_to_hcl_cvlink(void) devfs_hdl = hwgraph_path_to_vertex("hw/module"); for (i = 0; i < nummodules ; i++) { - for ( j = 0; j < 3; j++ ) { + for ( j = 0; j < 2; j++ ) { if ( j == 0 ) - brick_name = EDGE_LBL_PBRICK; - else if ( j == 1 ) brick_name = EDGE_LBL_PXBRICK; else brick_name = EDGE_LBL_IXBRICK; @@ -867,8 +802,8 @@ sn_pci_init (void) int i = 0; struct pci_controller *controller; - if (!ia64_platform_is("sn2")) - return 0; + if (!ia64_platform_is("sn2") || IS_RUNNING_ON_SIMULATOR()) + return 0; /* * set pci_raw_ops, etc. diff -puN arch/ia64/sn/io/machvec/pci.c~linus arch/ia64/sn/io/machvec/pci.c --- 25/arch/ia64/sn/io/machvec/pci.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/machvec/pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * SNI64 specific PCI support for SNI IO. * * This file is subject to the terms and conditions of the GNU General Public @@ -8,33 +7,15 @@ * * Copyright (c) 1997, 1998, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include /* * These routines are only used during sn_pci_init for probing each bus, and * can probably be removed with a little more cleanup now that the SAL routines * work on sn2. */ + extern vertex_hdl_t devfn_to_vertex(unsigned char bus, unsigned char devfn); int sn_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) diff -puN arch/ia64/sn/io/machvec/pci_dma.c~linus arch/ia64/sn/io/machvec/pci_dma.c --- 25/arch/ia64/sn/io/machvec/pci_dma.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/machvec/pci_dma.c 2004-01-19 22:17:21.000000000 -0800 @@ -9,27 +9,8 @@ * a description of how these routines should be used. */ -#include -#include -#include -#include -#include -#include #include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include /* * For ATE allocations @@ -130,10 +111,7 @@ find_sn_dma_map(dma_addr_t dma_addr, uns * * This interface is usually used for "command" streams (e.g. the command * queue for a SCSI controller). See Documentation/DMA-mapping.txt for - * more information. Note that this routine will always put a 32 bit - * DMA address into @dma_handle. This is because most devices - * that are capable of 64 bit PCI DMA transactions can't do 64 bit _coherent_ - * DMAs, and unfortunately this interface has to cater to the LCD. Oh well. + * more information. * * Also known as platform_pci_alloc_consistent() by the IA64 machvec code. */ @@ -146,11 +124,6 @@ sn_pci_alloc_consistent(struct pci_dev * unsigned long phys_addr; pcibr_dmamap_t dma_map = 0; - *dma_handle = 0; - - if (hwdev->dma_mask < 0xffffffffUL) - return NULL; - /* * Get hwgraph vertex for the device */ @@ -158,54 +131,48 @@ sn_pci_alloc_consistent(struct pci_dev * vhdl = device_sysdata->vhdl; /* - * Allocate the memory. FIXME: if we're allocating for - * two devices on the same bus, we should at least try to - * allocate memory in the same 2 GB window to avoid using - * ATEs for the translation. See the comment above about the - * 32 bit requirement for this function. + * Allocate the memory. + * FIXME: We should be doing alloc_pages_node for the node closest + * to the PCI device. */ - if(!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) + if (!(cpuaddr = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)))) return NULL; /* physical addr. of the memory we just got */ phys_addr = __pa(cpuaddr); /* - * This will try to use a Direct Map register to do the - * 32 bit DMA mapping, but it may not succeed if another - * device on the same bus is already mapped with different - * attributes or to a different memory region. - */ - *dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_CMD); - - /* - * If this device is in PCI-X mode, the system would have - * automatically allocated a 64Bits DMA Address. Error out if the - * device cannot support DAC. - */ - if (*dma_handle > hwdev->consistent_dma_mask) { - free_pages((unsigned long) cpuaddr, get_order(size)); - return NULL; + * 64 bit address translations should never fail. + * 32 bit translations can fail if there are insufficient mapping + * resources and the direct map is already wired to a different + * 2GB range. + * 32 bit translations can also return a > 32 bit address, because + * pcibr_dmatrans_addr ignores a missing PCIIO_DMA_A64 flag on + * PCI-X buses. + */ + if (hwdev->consistent_dma_mask == ~0UL) + *dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, + PCIIO_DMA_CMD | PCIIO_DMA_A64); + else { + dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_CMD); + if (dma_map) { + *dma_handle = (dma_addr_t) + pcibr_dmamap_addr(dma_map, phys_addr, size); + dma_map->bd_dma_addr = *dma_handle; + } + else { + *dma_handle = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, + PCIIO_DMA_CMD); + } } - /* - * It is a 32 bit card and we cannot do direct mapping, - * so we try to use an ATE. - */ - if (!(*dma_handle)) { - dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_CMD); - if (!dma_map) { - printk(KERN_ERR "sn_pci_alloc_consistent: Unable to " - "allocate anymore 32 bit page map entries.\n"); - return 0; + if (!*dma_handle || *dma_handle > hwdev->consistent_dma_mask) { + if (dma_map) { + pcibr_dmamap_done(dma_map); + pcibr_dmamap_free(dma_map); } - *dma_handle = (dma_addr_t) pcibr_dmamap_addr(dma_map,phys_addr, - size); - dma_map->bd_dma_addr = *dma_handle; + free_pages((unsigned long) cpuaddr, get_order(size)); + return NULL; } return cpuaddr; @@ -238,7 +205,6 @@ sn_pci_free_consistent(struct pci_dev *h if (dma_map) { pcibr_dmamap_done(dma_map); pcibr_dmamap_free(dma_map); - dma_map->bd_dma_addr = 0; } free_pages((unsigned long) vaddr, get_order(size)); } @@ -288,9 +254,7 @@ sn_pci_map_sg(struct pci_dev *hwdev, str if (IS_PCIA64(hwdev)) { sg->dma_address = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, sg->length, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_DATA | - PCIIO_DMA_A64); + PCIIO_DMA_DATA | PCIIO_DMA_A64); sg->dma_length = sg->length; continue; } @@ -300,9 +264,7 @@ sn_pci_map_sg(struct pci_dev *hwdev, str */ if (IS_PCI32G(hwdev)) { sg->dma_address = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, - sg->length, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_DATA); + sg->length, PCIIO_DMA_DATA); sg->dma_length = sg->length; /* * See if we got a direct map entry @@ -317,9 +279,7 @@ sn_pci_map_sg(struct pci_dev *hwdev, str * It is a 32 bit card and we cannot do direct mapping, * so we use an ATE. */ - dma_map = pcibr_dmamap_alloc(vhdl, NULL, sg->length, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_DATA); + dma_map = pcibr_dmamap_alloc(vhdl, NULL, sg->length, PCIIO_DMA_DATA); if (!dma_map) { printk(KERN_ERR "sn_pci_map_sg: Unable to allocate " "anymore 32 bit page map entries.\n"); @@ -369,7 +329,6 @@ sn_pci_unmap_sg(struct pci_dev *hwdev, s if (dma_map) { pcibr_dmamap_done(dma_map); pcibr_dmamap_free(dma_map); - dma_map->bd_dma_addr = 0; } } @@ -390,7 +349,7 @@ sn_pci_unmap_sg(struct pci_dev *hwdev, s * the IA64 machvec code. * * We map this to the one step pcibr_dmamap_trans interface rather than - * the two step pciio_dmamap_alloc/pciio_dmamap_addr because we have + * the two step pcibr_dmamap_alloc/pcibr_dmamap_addr because we have * no way of saving the dmamap handle from the alloc to later free * (which is pretty much unacceptable). * @@ -429,9 +388,7 @@ sn_pci_map_single(struct pci_dev *hwdev, if (IS_PCIA64(hwdev)) { /* This device supports 64 bit DMA addresses. */ dma_addr = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_DATA | - PCIIO_DMA_A64); + PCIIO_DMA_DATA | PCIIO_DMA_A64); return dma_addr; } @@ -443,7 +400,6 @@ sn_pci_map_single(struct pci_dev *hwdev, */ if (IS_PCI32G(hwdev)) { dma_addr = pcibr_dmatrans_addr(vhdl, NULL, phys_addr, size, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | PCIIO_DMA_DATA); if (dma_addr) return dma_addr; @@ -454,9 +410,7 @@ sn_pci_map_single(struct pci_dev *hwdev, * let's use the PMU instead. */ dma_map = NULL; - dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, - ((IS_PIC_DEVICE(hwdev)) ? 0 : PCIIO_BYTE_STREAM) | - PCIIO_DMA_DATA); + dma_map = pcibr_dmamap_alloc(vhdl, NULL, size, PCIIO_DMA_DATA); if (!dma_map) { printk(KERN_ERR "pci_map_single: Unable to allocate anymore " @@ -500,7 +454,6 @@ sn_pci_unmap_single(struct pci_dev *hwde if (dma_map) { pcibr_dmamap_done(dma_map); pcibr_dmamap_free(dma_map); - dma_map->bd_dma_addr = 0; } } diff -puN arch/ia64/sn/io/Makefile~linus arch/ia64/sn/io/Makefile --- 25/arch/ia64/sn/io/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,7 +9,5 @@ # Makefile for the sn io routines. # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - -obj-y += sgi_if.o xswitch.o sgi_io_sim.o cdl.o \ +obj-y += xswitch.o cdl.o snia_if.o \ io.o machvec/ drivers/ platform_init/ sn2/ hwgfs/ diff -puN -L arch/ia64/sn/io/platform_init/irix_io_init.c arch/ia64/sn/io/platform_init/irix_io_init.c~linus /dev/null --- 25/arch/ia64/sn/io/platform_init/irix_io_init.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,88 +0,0 @@ -/* $Id$ - * - * 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) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern void init_all_devices(void); -extern void klhwg_add_all_modules(vertex_hdl_t); -extern void klhwg_add_all_nodes(vertex_hdl_t); - -extern vertex_hdl_t hwgraph_root; -extern void io_module_init(void); -extern int pci_bus_to_hcl_cvlink(void); -extern void mlreset(void); - -/* #define DEBUG_IO_INIT 1 */ -#ifdef DEBUG_IO_INIT -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif /* DEBUG_IO_INIT */ - -/* - * This routine is responsible for the setup of all the IRIX hwgraph style - * stuff that's been pulled into linux. It's called by sn_pci_find_bios which - * is called just before the generic Linux PCI layer does its probing (by - * platform_pci_fixup aka sn_pci_fixup). - * - * It is very IMPORTANT that this call is only made by the Master CPU! - * - */ - -void -irix_io_init(void) -{ - cnodeid_t cnode; - - /* - * This is the Master CPU. Emulate mlsetup and main.c in Irix. - */ - mlreset(); - - /* - * Initialize platform-dependent vertices in the hwgraph: - * module - * node - * cpu - * memory - * slot - * hub - * router - * xbow - */ - - io_module_init(); /* Use to be called module_init() .. */ - klhwg_add_all_modules(hwgraph_root); - klhwg_add_all_nodes(hwgraph_root); - - for (cnode = 0; cnode < numnodes; cnode++) { - extern void per_hub_init(cnodeid_t); - per_hub_init(cnode); - } - - /* We can do headless hub cnodes here .. */ - - /* - * - * Our IO Infrastructure drivers are in place .. - * Initialize the whole IO Infrastructure .. xwidget/device probes. - * - */ - init_all_devices(); - pci_bus_to_hcl_cvlink(); -} diff -puN arch/ia64/sn/io/platform_init/Makefile~linus arch/ia64/sn/io/platform_init/Makefile --- 25/arch/ia64/sn/io/platform_init/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/platform_init/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,6 +7,4 @@ # # Makefile for the sn2 io routines. -EXTRA_CFLAGS := -DLITTLE_ENDIAN - -obj-y += sgi_io_init.o irix_io_init.o +obj-y += sgi_io_init.o diff -puN arch/ia64/sn/io/platform_init/sgi_io_init.c~linus arch/ia64/sn/io/platform_init/sgi_io_init.c --- 25/arch/ia64/sn/io/platform_init/sgi_io_init.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/platform_init/sgi_io_init.c 2004-01-19 22:17:21.000000000 -0800 @@ -17,19 +17,35 @@ #include #include +extern void init_all_devices(void); +extern void klhwg_add_all_modules(vertex_hdl_t); +extern void klhwg_add_all_nodes(vertex_hdl_t); + +extern int init_hcl(void); +extern vertex_hdl_t hwgraph_root; +extern void io_module_init(void); +extern int pci_bus_to_hcl_cvlink(void); + +cpuid_t master_procid; +nasid_t console_nasid = (nasid_t) - 1; +char master_baseio_wid; + +nasid_t master_baseio_nasid; +nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */ + /* * per_hub_init * * This code is executed once for each Hub chip. */ -void +static void per_hub_init(cnodeid_t cnode) { - nasid_t nasid; - nodepda_t *npdap; - ii_icmr_u_t ii_icmr; - ii_ibcr_u_t ii_ibcr; - ii_ilcsr_u_t ii_ilcsr; + nasid_t nasid; + nodepda_t *npdap; + ii_icmr_u_t ii_icmr; + ii_ibcr_u_t ii_ibcr; + ii_ilcsr_u_t ii_ilcsr; nasid = COMPACT_TO_NASID_NODEID(cnode); @@ -44,11 +60,11 @@ per_hub_init(cnodeid_t cnode) /* * Set the total number of CRBs that can be used. */ - ii_icmr.ii_icmr_regval= 0x0; + ii_icmr.ii_icmr_regval = 0x0; ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf; - if (enable_shub_wars_1_1() ) { + if (enable_shub_wars_1_1()) { // Set bit one of ICMR to prevent II from sending interrupt for II bug. - ii_icmr.ii_icmr_regval |= 0x1; + ii_icmr.ii_icmr_regval |= 0x1; } REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); @@ -56,25 +72,106 @@ per_hub_init(cnodeid_t cnode) * Set the number of CRBs that both of the BTEs combined * can use minus 1. */ - ii_ibcr.ii_ibcr_regval= 0x0; + ii_ibcr.ii_ibcr_regval = 0x0; ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR); if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) { - ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; + ii_ibcr.ii_ibcr_fld_s.i_count = 0x8; } else { - /* - * if the LLP is down, there is no attached I/O, so - * give BTE all the CRBs. - */ - ii_ibcr.ii_ibcr_fld_s.i_count = 0x14; + /* + * if the LLP is down, there is no attached I/O, so + * give BTE all the CRBs. + */ + ii_ibcr.ii_ibcr_fld_s.i_count = 0x14; } REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); /* * Set CRB timeout to be 10ms. */ - REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff ); + REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff); REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); /* Initialize error interrupts for this hub. */ hub_error_init(cnode); } + +/* + * This routine is responsible for the setup of all the IRIX hwgraph style + * stuff that's been pulled into linux. It's called by sn_pci_find_bios which + * is called just before the generic Linux PCI layer does its probing (by + * platform_pci_fixup aka sn_pci_fixup). + * + * It is very IMPORTANT that this call is only made by the Master CPU! + * + */ + +void __init +sgi_master_io_infr_init(void) +{ + cnodeid_t cnode; + + if (init_hcl() < 0) { /* Sets up the hwgraph compatibility layer */ + printk("sgi_master_io_infr_init: Cannot init hcl\n"); + return; + } + + /* + * Initialize platform-dependent vertices in the hwgraph: + * module + * node + * cpu + * memory + * slot + * hub + * router + * xbow + */ + + io_module_init(); /* Use to be called module_init() .. */ + klhwg_add_all_modules(hwgraph_root); + klhwg_add_all_nodes(hwgraph_root); + + for (cnode = 0; cnode < numnodes; cnode++) { + extern void per_hub_init(cnodeid_t); + per_hub_init(cnode); + } + + /* + * + * Our IO Infrastructure drivers are in place .. + * Initialize the whole IO Infrastructure .. xwidget/device probes. + * + */ + init_all_devices(); + pci_bus_to_hcl_cvlink(); +} + +inline int +check_nasid_equiv(nasid_t nasida, nasid_t nasidb) +{ + if ((nasida == nasidb) + || (nasida == NODEPDA(NASID_TO_COMPACT_NODEID(nasidb))->xbow_peer)) + return 1; + else + return 0; +} + +int +is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid) +{ + /* + * If the widget numbers are different, we're not the master. + */ + if (test_wid != (xwidgetnum_t) master_baseio_wid) { + return 0; + } + + /* + * If the NASIDs are the same or equivalent, we're the master. + */ + if (check_nasid_equiv(test_nasid, master_baseio_nasid)) { + return 1; + } else { + return 0; + } +} diff -puN -L arch/ia64/sn/io/sgi_if.c arch/ia64/sn/io/sgi_if.c~linus /dev/null --- 25/arch/ia64/sn/io/sgi_if.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,136 +0,0 @@ -/* $Id$ - * - * 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) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void * -snia_kmem_zalloc(size_t size, int flag) -{ - void *ptr = kmalloc(size, GFP_KERNEL); - if ( ptr ) - BZERO(ptr, size); - return(ptr); -} - -void -snia_kmem_free(void *ptr, size_t size) -{ - kfree(ptr); -} - -/* - * the alloc/free_node routines do a simple kmalloc for now .. - */ -void * -snia_kmem_alloc_node(register size_t size, register int flags, cnodeid_t node) -{ - /* someday will Allocate on node 'node' */ - return(kmalloc(size, GFP_KERNEL)); -} - -void * -snia_kmem_zalloc_node(register size_t size, register int flags, cnodeid_t node) -{ - void *ptr = kmalloc(size, GFP_KERNEL); - if ( ptr ) - BZERO(ptr, size); - return(ptr); -} - - -/* - * print_register() allows formatted printing of bit fields. individual - * bit fields are described by a struct reg_desc, multiple bit fields within - * a single word can be described by multiple reg_desc structures. - * %r outputs a string of the format "" - * %R outputs a string of the format "0x%x" - * - * The fields in a reg_desc are: - * unsigned long long rd_mask; An appropriate mask to isolate the bit field - * within a word, and'ed with val - * - * int rd_shift; A shift amount to be done to the isolated - * bit field. done before printing the isolate - * bit field with rd_format and before searching - * for symbolic value names in rd_values - * - * char *rd_name; If non-null, a bit field name to label any - * out from rd_format or searching rd_values. - * if neither rd_format or rd_values is non-null - * rd_name is printed only if the isolated - * bit field is non-null. - * - * char *rd_format; If non-null, the shifted bit field value - * is printed using this format. - * - * struct reg_values *rd_values; If non-null, a pointer to a table - * matching numeric values with symbolic names. - * rd_values are searched and the symbolic - * value is printed if a match is found, if no - * match is found "???" is printed. - * - */ - -void -print_register(unsigned long long reg, struct reg_desc *addr) -{ - register struct reg_desc *rd; - register struct reg_values *rv; - unsigned long long field; - int any; - - printk("<"); - any = 0; - for (rd = addr; rd->rd_mask; rd++) { - field = reg & rd->rd_mask; - field = (rd->rd_shift > 0) ? field << rd->rd_shift : field >> -rd->rd_shift; - if (any && (rd->rd_format || rd->rd_values || (rd->rd_name && field))) - printk(","); - if (rd->rd_name) { - if (rd->rd_format || rd->rd_values || field) { - printk("%s", rd->rd_name); - any = 1; - } - if (rd->rd_format || rd->rd_values) { - printk("="); - any = 1; - } - } - /* You can have any format so long as it is %x */ - if (rd->rd_format) { - printk("%llx", field); - any = 1; - if (rd->rd_values) - printk(":"); - } - if (rd->rd_values) { - any = 1; - for (rv = rd->rd_values; rv->rv_name; rv++) { - if (field == rv->rv_value) { - printk("%s", rv->rv_name); - break; - } - } - if (rv->rv_name == NULL) - printk("???"); - } - } - printk(">\n"); -} diff -puN -L arch/ia64/sn/io/sgi_io_sim.c arch/ia64/sn/io/sgi_io_sim.c~linus /dev/null --- 25/arch/ia64/sn/io/sgi_io_sim.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,79 +0,0 @@ -/* $Id$ - * - * 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) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -cpuid_t master_procid; -char arg_maxnodes[4]; - -/* - * Return non-zero if the given variable was specified - */ -int -is_specified(char *s) -{ - return (strlen(s) != 0); -} - -/* - * Routines provided by ml/SN/promif.c. - */ -static __psunsigned_t master_bridge_base; -nasid_t console_nasid = (nasid_t)-1; -char master_baseio_wid; -static char console_wid; -static char console_pcislot; - -void -set_master_bridge_base(void) -{ - console_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base); - console_pcislot = KL_CONFIG_CH_CONS_INFO(master_nasid)->npci; - master_bridge_base = (__psunsigned_t)NODE_SWIN_BASE(console_nasid, console_wid); - // FIXME("WARNING: set_master_bridge_base: NON NASID 0 DOES NOT WORK\n"); -} - -int -check_nasid_equiv(nasid_t nasida, nasid_t nasidb) -{ - if ((nasida == nasidb) || (nasida == NODEPDA(NASID_TO_COMPACT_NODEID(nasidb))->xbow_peer)) - return 1; - else - return 0; -} - -int -is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid) -{ - extern nasid_t master_baseio_nasid; - - /* - * If the widget numbers are different, we're not the master. - */ - if (test_wid != (xwidgetnum_t)master_baseio_wid) { - return 0; - } - - /* - * If the NASIDs are the same or equivalent, we're the master. - */ - if (check_nasid_equiv(test_nasid, master_baseio_nasid)) { - return 1; - } else { - return 0; - } -} diff -puN arch/ia64/sn/io/sn2/bte_error.c~linus arch/ia64/sn/io/sn2/bte_error.c --- 25/arch/ia64/sn/io/sn2/bte_error.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/bte_error.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,35 +1,9 @@ /* - * + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ @@ -39,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -89,36 +62,11 @@ bte_crb_error_handler(vertex_hdl_t hub_v * in the bte handle structure for the thread excercising the * interface to consume. */ - switch (ioe->ie_errortype) { - case IIO_ICRB_ECODE_PERR: - bte->bh_error = BTEFAIL_POISON; - break; - case IIO_ICRB_ECODE_WERR: - bte->bh_error = BTEFAIL_PROT; - break; - case IIO_ICRB_ECODE_AERR: - bte->bh_error = BTEFAIL_ACCESS; - break; - case IIO_ICRB_ECODE_TOUT: - bte->bh_error = BTEFAIL_TOUT; - break; - case IIO_ICRB_ECODE_XTERR: - bte->bh_error = BTEFAIL_XTERR; - break; - case IIO_ICRB_ECODE_DERR: - bte->bh_error = BTEFAIL_DIR; - break; - case IIO_ICRB_ECODE_PWERR: - case IIO_ICRB_ECODE_PRERR: - /* NO BREAK */ - default: - bte->bh_error = BTEFAIL_ERROR; - } - + bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET; bte->bte_error_count++; - BTE_PRINTK(("Got an error on cnode %d bte %d\n", - bte->bte_cnode, bte->bte_num)); + BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n", + bte->bte_cnode, bte->bte_num, ioe->ie_errortype)); bte_error_handler((unsigned long) hinfo->h_nodepda); } diff -puN arch/ia64/sn/io/sn2/geo_op.c~linus arch/ia64/sn/io/sn2/geo_op.c --- 25/arch/ia64/sn/io/sn2/geo_op.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/geo_op.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -29,7 +28,6 @@ #include #include #include -#include #include #include #include diff -puN arch/ia64/sn/io/sn2/klconflib.c~linus arch/ia64/sn/io/sn2/klconflib.c --- 25/arch/ia64/sn/io/sn2/klconflib.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/klconflib.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -15,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -23,11 +21,9 @@ #include #include #include +#include -#define LDEBUG 0 -#define NIC_UNKNOWN ((nic_t) -1) - #undef DEBUG_KLGRAPH #ifdef DEBUG_KLGRAPH #define DBG(x...) printk(x) @@ -35,11 +31,11 @@ #define DBG(x...) #endif /* DEBUG_KLGRAPH */ -u64 klgraph_addr[MAX_COMPACT_NODES]; +lboard_t *root_lboard[MAX_COMPACT_NODES]; static int hasmetarouter; -char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=012345"; +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#=vo^34567890123456789..."; lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) @@ -270,17 +266,11 @@ board_to_path(lboard_t *brd, char *path) board_name = EDGE_LBL_PXBRICK; else if (brd->brd_type == KLTYPE_IXBRICK) board_name = EDGE_LBL_IXBRICK; - else if (brd->brd_type == KLTYPE_PBRICK) - board_name = EDGE_LBL_PBRICK; - else if (brd->brd_type == KLTYPE_IBRICK) - board_name = EDGE_LBL_IBRICK; - else if (brd->brd_type == KLTYPE_XBRICK) - board_name = EDGE_LBL_XBRICK; - else if (brd->brd_type == KLTYPE_PEBRICK) - board_name = EDGE_LBL_PEBRICK; + else if (brd->brd_type == KLTYPE_OPUSBRICK) + board_name = EDGE_LBL_OPUSBRICK; else if (brd->brd_type == KLTYPE_CGBRICK) board_name = EDGE_LBL_CGBRICK; - else + else board_name = EDGE_LBL_IOBRICK; break; default: @@ -293,23 +283,6 @@ board_to_path(lboard_t *brd, char *path) sprintf(path, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d/%s", buffer, geo_slab(brd->brd_geoid), board_name); } -/* - * Get the module number for a NASID. - */ -moduleid_t -get_module_id(nasid_t nasid) -{ - lboard_t *brd; - - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); - - if (!brd) - return INVALID_MODULE; - else - return geo_module(brd->brd_geoid); -} - - #define MHZ 1000000 @@ -440,71 +413,24 @@ board_serial_number_get(lboard_t *board, break; } case KLCLASS_IO: { /* IO board */ - if (KLTYPE(board->brd_type) == KLTYPE_TPU) { - /* Special case for TPU boards */ - kltpu_t *tpu; + klbri_t *bridge; - /* Get the tpu component information */ - tpu = (kltpu_t *)find_first_component(board, - KLSTRUCT_TPU); - /* If we don't have a tpu component on a tpu board - * then we have a weird klconfig. - */ - if (!tpu) - return(1); - /* Get the serial number information from - * the tpu's manufacturing nic info - */ - if (component_serial_number_get(board, - tpu->tpu_mfg_nic, - serial_number, - "")) - return(1); - break; - } else if ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) || - (KLTYPE(board->brd_type) == KLTYPE_GSN_B)) { - /* Special case for GSN boards */ - klgsn_t *gsn; - - /* Get the gsn component information */ - gsn = (klgsn_t *)find_first_component(board, - ((KLTYPE(board->brd_type) == KLTYPE_GSN_A) ? - KLSTRUCT_GSN_A : KLSTRUCT_GSN_B)); - /* If we don't have a gsn component on a gsn board - * then we have a weird klconfig. - */ - if (!gsn) - return(1); - /* Get the serial number information from - * the gsn's manufacturing nic info - */ - if (component_serial_number_get(board, - gsn->gsn_mfg_nic, - serial_number, - "")) - return(1); - break; - } else { - klbri_t *bridge; - - /* Get the bridge component information */ - bridge = (klbri_t *)find_first_component(board, + /* Get the bridge component information */ + bridge = (klbri_t *)find_first_component(board, KLSTRUCT_BRI); - /* If we don't have a bridge component on an IO board - * then we have a weird klconfig. - */ - if (!bridge) - return(1); - /* Get the serial number information from - * the bridge's manufacturing nic info - */ - if (component_serial_number_get(board, - bridge->bri_mfg_nic, - serial_number, - "")) - return(1); - break; - } + /* If we don't have a bridge component on an IO board + * then we have a weird klconfig. + */ + if (!bridge) + return(1); + /* Get the serial number information from + * the bridge's manufacturing nic info + */ + if (component_serial_number_get(board, + bridge->bri_mfg_nic, + serial_number, "")) + return(1); + break; } case KLCLASS_ROUTER: { /* Router board */ klrou_t *router; @@ -558,6 +484,23 @@ board_serial_number_get(lboard_t *board, /* * Format a module id for printing. + * + * There are three possible formats: + * + * MODULE_FORMAT_BRIEF is the brief 6-character format, including + * the actual brick-type as recorded in the + * moduleid_t, eg. 002c15 for a C-brick, or + * 101#17 for a PX-brick. + * + * MODULE_FORMAT_LONG is the hwgraph format, eg. rack/002/bay/15 + * of rack/101/bay/17 (note that the brick + * type does not appear in this format). + * + * MODULE_FORMAT_LCD is like MODULE_FORMAT_BRIEF, except that it + * ensures that the module id provided appears + * exactly as it would on the LCD display of + * the corresponding brick, eg. still 002c15 + * for a C-brick, but 101p17 for a PX-brick. */ void format_module_id(char *buffer, moduleid_t m, int fmt) @@ -569,9 +512,25 @@ format_module_id(char *buffer, moduleid_ ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); brickchar = MODULE_GET_BTCHAR(m); + if (fmt == MODULE_FORMAT_LCD) { + /* Be sure we use the same brick type character as displayed + * on the brick's LCD + */ + switch (brickchar) + { + case L1_BRICKTYPE_PX: + brickchar = L1_BRICKTYPE_P; + break; + + case L1_BRICKTYPE_IX: + brickchar = L1_BRICKTYPE_I; + break; + } + } + position = MODULE_GET_BPOS(m); - if (fmt == MODULE_FORMAT_BRIEF) { + if ((fmt == MODULE_FORMAT_BRIEF) || (fmt == MODULE_FORMAT_LCD)) { /* Brief module number format, eg. 002c15 */ /* Decompress the rack number */ @@ -686,3 +645,27 @@ parse_module_id(char *buffer) /* avoid sign extending the moduleid_t */ return (int)(unsigned short)m; } + +int +cbrick_type_get_nasid(nasid_t nasid) +{ + lboard_t *brd; + moduleid_t module; + uint type; + int t; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + module = geo_module(brd->brd_geoid); + type = (module & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT; + /* convert brick_type to lower case */ + if ((type >= 'A') && (type <= 'Z')) + type = type - 'A' + 'a'; + + /* convert to a module.h brick type */ + for( t = 0; t < MAX_BRICK_TYPES; t++ ) { + if( brick_types[t] == type ) { + return t; + } + } + return -1; +} diff -puN arch/ia64/sn/io/sn2/klgraph.c~linus arch/ia64/sn/io/sn2/klgraph.c --- 25/arch/ia64/sn/io/sn2/klgraph.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/klgraph.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -15,196 +14,26 @@ #include #include +#include #include #include -#include #include -#include #include -#include -#include -#include -#include -#include #include +#include -// #define KLGRAPH_DEBUG 1 +/* #define KLGRAPH_DEBUG 1 */ #ifdef KLGRAPH_DEBUG #define GRPRINTF(x) printk x -#define CE_GRPANIC CE_PANIC #else #define GRPRINTF(x) -#define CE_GRPANIC CE_PANIC #endif -#include - -extern char arg_maxnodes[]; -extern u64 klgraph_addr[]; void mark_cpuvertex_as_cpu(vertex_hdl_t vhdl, cpuid_t cpuid); -/* - * Support for verbose inventory via hardware graph. - * klhwg_invent_alloc allocates the necessary size of inventory information - * and fills in the generic information. - */ -invent_generic_t * -klhwg_invent_alloc(cnodeid_t cnode, int class, int size) -{ - invent_generic_t *invent; - - invent = kern_malloc(size); - if (!invent) return NULL; - - invent->ig_module = NODE_MODULEID(cnode); - invent->ig_slot = SLOTNUM_GETSLOT(NODE_SLOTID(cnode)); - invent->ig_invclass = class; - - return invent; -} - -/* - * Add detailed disabled cpu inventory info to the hardware graph. - */ -void -klhwg_disabled_cpu_invent_info(vertex_hdl_t cpuv, - cnodeid_t cnode, - klcpu_t *cpu, slotid_t slot) -{ - invent_cpuinfo_t *cpu_invent; - diag_inv_t *diag_invent; - - cpu_invent = (invent_cpuinfo_t *) - klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t)); - if (!cpu_invent) - return; - - /* Diag information on this processor */ - diag_invent = (diag_inv_t *) - klhwg_invent_alloc(cnode, INV_CPUDIAGVAL, sizeof(diag_inv_t)); - - if (!diag_invent) - return; - - - /* Disabled CPU */ - cpu_invent->ic_gen.ig_flag = 0x0; - cpu_invent->ic_gen.ig_slot = slot; - cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid; - cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed; - cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed; - - cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz; - cpu_invent->ic_cpuid = cpu->cpu_info.virtid; - cpu_invent->ic_slice = cpu->cpu_info.physid; - - /* Disabled CPU label */ - hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT, - (arbitrary_info_t) cpu_invent); - hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT, - sizeof(invent_cpuinfo_t)); - - /* Diagval label - stores reason for disable +{virt,phys}id +diagval*/ - hwgraph_info_add_LBL(cpuv, INFO_LBL_DIAGVAL, - (arbitrary_info_t) diag_invent); - - hwgraph_info_export_LBL(cpuv, INFO_LBL_DIAGVAL, - sizeof(diag_inv_t)); -} - -/* - * Add detailed cpu inventory info to the hardware graph. - */ -void -klhwg_cpu_invent_info(vertex_hdl_t cpuv, - cnodeid_t cnode, - klcpu_t *cpu) -{ - invent_cpuinfo_t *cpu_invent; - - cpu_invent = (invent_cpuinfo_t *) - klhwg_invent_alloc(cnode, INV_PROCESSOR, sizeof(invent_cpuinfo_t)); - if (!cpu_invent) - return; - - if (KLCONFIG_INFO_ENABLED((klinfo_t *)cpu)) - cpu_invent->ic_gen.ig_flag = INVENT_ENABLED; - else - cpu_invent->ic_gen.ig_flag = 0x0; - - cpu_invent->ic_cpu_info.cpuflavor = cpu->cpu_prid; - cpu_invent->ic_cpu_info.cpufq = cpu->cpu_speed; - cpu_invent->ic_cpu_info.sdfreq = cpu->cpu_scachespeed; - - cpu_invent->ic_cpu_info.sdsize = cpu->cpu_scachesz; - cpu_invent->ic_cpuid = cpu->cpu_info.virtid; - cpu_invent->ic_slice = cpu_physical_id_to_slice(cpu->cpu_info.virtid); - - hwgraph_info_add_LBL(cpuv, INFO_LBL_DETAIL_INVENT, - (arbitrary_info_t) cpu_invent); - hwgraph_info_export_LBL(cpuv, INFO_LBL_DETAIL_INVENT, - sizeof(invent_cpuinfo_t)); -} - -/* - * Add information about the baseio prom version number - * as a part of detailed inventory info in the hwgraph. - */ -void -klhwg_baseio_inventory_add(vertex_hdl_t baseio_vhdl,cnodeid_t cnode) -{ - invent_miscinfo_t *baseio_inventory; - unsigned char version = 0,revision = 0; - - /* Allocate memory for the "detailed inventory" info - * for the baseio - */ - baseio_inventory = (invent_miscinfo_t *) - klhwg_invent_alloc(cnode, INV_PROM, sizeof(invent_miscinfo_t)); - baseio_inventory->im_type = INV_IO6PROM; - /* Store the revision info in the inventory */ - baseio_inventory->im_version = version; - baseio_inventory->im_rev = revision; - /* Put the inventory info in the hardware graph */ - hwgraph_info_add_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, - (arbitrary_info_t) baseio_inventory); - /* Make the information available to the user programs - * thru hwgfs. - */ - hwgraph_info_export_LBL(baseio_vhdl, INFO_LBL_DETAIL_INVENT, - sizeof(invent_miscinfo_t)); -} - -/* - * Add detailed cpu inventory info to the hardware graph. - */ -void -klhwg_hub_invent_info(vertex_hdl_t hubv, - cnodeid_t cnode, - klhub_t *hub) -{ - invent_miscinfo_t *hub_invent; - - hub_invent = (invent_miscinfo_t *) - klhwg_invent_alloc(cnode, INV_MISC, sizeof(invent_miscinfo_t)); - if (!hub_invent) - return; - - if (KLCONFIG_INFO_ENABLED((klinfo_t *)hub)) - hub_invent->im_gen.ig_flag = INVENT_ENABLED; - - hub_invent->im_type = INV_HUB; - hub_invent->im_rev = hub->hub_info.revision; - hub_invent->im_speed = hub->hub_speed; - hwgraph_info_add_LBL(hubv, INFO_LBL_DETAIL_INVENT, - (arbitrary_info_t) hub_invent); - hwgraph_info_export_LBL(hubv, INFO_LBL_DETAIL_INVENT, - sizeof(invent_miscinfo_t)); -} - /* ARGSUSED */ -void +static void __init klhwg_add_hub(vertex_hdl_t node_vertex, klhub_t *hub, cnodeid_t cnode) { vertex_hdl_t myhubv; @@ -212,18 +41,23 @@ klhwg_add_hub(vertex_hdl_t node_vertex, int rc; extern struct file_operations shub_mon_fops; - GRPRINTF(("klhwg_add_hub: adding %s\n", EDGE_LBL_HUB)); - (void) hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv); + hwgraph_path_add(node_vertex, EDGE_LBL_HUB, &myhubv); + + HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, myhubv, NULL, "Created path for hub vertex for Shub node.\n")); + rc = device_master_set(myhubv, node_vertex); + if (rc) { + printk("klhwg_add_hub: Unable to create hub vertex.\n"); + return; + } hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON, - 0, 0, - 0, 0, + 0, 0, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, &shub_mon_fops, (void *)(long)cnode); } /* ARGSUSED */ -void +static void __init klhwg_add_disabled_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) { vertex_hdl_t my_cpu; @@ -234,19 +68,19 @@ klhwg_add_disabled_cpu(vertex_hdl_t node nasid = COMPACT_TO_NASID_NODEID(cnode); cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid); if(cpu_id != -1){ - sprintf(name, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid); + snprintf(name, 120, "%s/%s/%c", EDGE_LBL_DISABLED, EDGE_LBL_CPU, 'a' + cpu->cpu_info.physid); (void) hwgraph_path_add(node_vertex, name, &my_cpu); + HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for disabled cpu slice.\n")); + mark_cpuvertex_as_cpu(my_cpu, cpu_id); device_master_set(my_cpu, node_vertex); - - klhwg_disabled_cpu_invent_info(my_cpu, cnode, cpu, slot); return; } } /* ARGSUSED */ -void +static void __init klhwg_add_cpu(vertex_hdl_t node_vertex, cnodeid_t cnode, klcpu_t *cpu) { vertex_hdl_t my_cpu, cpu_dir; @@ -257,27 +91,28 @@ klhwg_add_cpu(vertex_hdl_t node_vertex, nasid = COMPACT_TO_NASID_NODEID(cnode); cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid); - sprintf(name, "%s/%d/%c", + snprintf(name, 120, "%s/%d/%c", EDGE_LBL_CPUBUS, 0, 'a' + cpu->cpu_info.physid); - GRPRINTF(("klhwg_add_cpu: adding %s to vertex 0x%p\n", name, node_vertex)); (void) hwgraph_path_add(node_vertex, name, &my_cpu); - mark_cpuvertex_as_cpu(my_cpu, cpu_id); + + HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, my_cpu, NULL, "Created path for active cpu slice.\n")); + + mark_cpuvertex_as_cpu(my_cpu, cpu_id); device_master_set(my_cpu, node_vertex); /* Add an alias under the node's CPU directory */ if (hwgraph_edge_get(node_vertex, EDGE_LBL_CPU, &cpu_dir) == GRAPH_SUCCESS) { - sprintf(name, "%c", 'a' + cpu->cpu_info.physid); + snprintf(name, 120, "%c", 'a' + cpu->cpu_info.physid); (void) hwgraph_edge_add(cpu_dir, my_cpu, name); + HWGRAPH_DEBUG((__FILE__, __FUNCTION__,__LINE__, cpu_dir, my_cpu, "Created % from vhdl1 to vhdl2.\n", name)); } - - klhwg_cpu_invent_info(my_cpu, cnode, cpu); } -void +static void __init klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid) { lboard_t *brd; @@ -295,9 +130,6 @@ klhwg_add_xbow(cnodeid_t cnode, nasid_t if (KL_CONFIG_DUPLICATE_BOARD(brd)) return; - GRPRINTF(("klhwg_add_xbow: adding cnode %d nasid %d xbow edges\n", - cnode, nasid)); - if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) return; @@ -314,7 +146,7 @@ klhwg_add_xbow(cnodeid_t cnode, nasid_t hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid); - if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) { + if (hub_cnode == INVALID_CNODEID) { continue; } @@ -326,11 +158,15 @@ klhwg_add_xbow(cnodeid_t cnode, nasid_t printk(KERN_WARNING "klhwg_add_xbow: Check for " "working routers and router links!"); - PRINT_PANIC("klhwg_add_xbow: Failed to add " + printk("klhwg_add_xbow: Failed to add " "edge: vertex 0x%p to vertex 0x%p," "error %d\n", (void *)hubv, (void *)xbow_v, err); + return; } + + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, xbow_v, NULL, "Created path for xtalk.\n")); + xswitch_vertex_init(xbow_v); NODEPDA(hub_cnode)->xbow_vhdl = xbow_v; @@ -344,15 +180,12 @@ klhwg_add_xbow(cnodeid_t cnode, nasid_t NODEPDA(NASID_TO_COMPACT_NODEID(nasid))->xbow_peer = hub_nasid; } - - GRPRINTF(("klhwg_add_xbow: adding port nasid %d %s to vertex 0x%p\n", - hub_nasid, EDGE_LBL_XTALK, hubv)); } } /* ARGSUSED */ -void +static void __init klhwg_add_node(vertex_hdl_t hwgraph_root, cnodeid_t cnode) { nasid_t nasid; @@ -364,98 +197,78 @@ klhwg_add_node(vertex_hdl_t hwgraph_root char *s; int board_disabled = 0; klcpu_t *cpu; + vertex_hdl_t cpu_dir; nasid = COMPACT_TO_NASID_NODEID(cnode); brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); - GRPRINTF(("klhwg_add_node: Adding cnode %d, nasid %d, brd 0x%p\n", - cnode, nasid, brd)); ASSERT(brd); - do { - vertex_hdl_t cpu_dir; - - /* Generate a hardware graph path for this board. */ - board_to_path(brd, path_buffer); - - GRPRINTF(("klhwg_add_node: adding %s to vertex 0x%p\n", - path_buffer, hwgraph_root)); - rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); - - if (rv != GRAPH_SUCCESS) - PRINT_PANIC("Node vertex creation failed. " - "Path == %s", - path_buffer); + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + if (rv != GRAPH_SUCCESS) { + printk("Node vertex creation failed. Path == %s", path_buffer); + return; + } - hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); - ASSERT(hub); - if(hub->hub_info.flags & KLINFO_ENABLE) - board_disabled = 0; - else - board_disabled = 1; + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created path for SHUB node.\n")); + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + ASSERT(hub); + if(hub->hub_info.flags & KLINFO_ENABLE) + board_disabled = 0; + else + board_disabled = 1; - if(!board_disabled) { - mark_nodevertex_as_node(node_vertex, - cnode + board_disabled * numnodes); - - s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer)); - NODEPDA(cnode)->hwg_node_name = - kmalloc(strlen(s) + 1, - GFP_KERNEL); - ASSERT_ALWAYS(NODEPDA(cnode)->hwg_node_name != NULL); - strcpy(NODEPDA(cnode)->hwg_node_name, s); - - hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo); - - /* Set up node board's slot */ - NODEPDA(cnode)->slotdesc = brd->brd_slot; - - /* Set up the module we're in */ - NODEPDA(cnode)->geoid = brd->brd_geoid; - NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid)); + if(!board_disabled) { + mark_nodevertex_as_node(node_vertex, cnode); + s = dev_to_name(node_vertex, path_buffer, sizeof(path_buffer)); + NODEPDA(cnode)->hwg_node_name = + kmalloc(strlen(s) + 1, GFP_KERNEL); + if (NODEPDA(cnode)->hwg_node_name <= 0) { + printk("%s: no memory\n", __FUNCTION__); + return; } + strcpy(NODEPDA(cnode)->hwg_node_name, s); + hubinfo_set(node_vertex, NODEPDA(cnode)->pdinfo); + NODEPDA(cnode)->slotdesc = brd->brd_slot; + NODEPDA(cnode)->geoid = brd->brd_geoid; + NODEPDA(cnode)->module = module_lookup(geo_module(brd->brd_geoid)); + klhwg_add_hub(node_vertex, hub, cnode); + } - /* Get the first CPU structure */ - cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); + /* + * If there's at least 1 CPU, add a "cpu" directory to represent + * the collection of all CPUs attached to this node. + */ + cpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); + if (cpu) { + graph_error_t rv; + + rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir); + if (rv != GRAPH_SUCCESS) { + printk("klhwg_add_node: Cannot create CPU directory\n"); + return; + } + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, cpu_dir, NULL, "Created cpu directiry on SHUB node.\n")); - /* - * If there's at least 1 CPU, add a "cpu" directory to represent - * the collection of all CPUs attached to this node. - */ - if (cpu) { - graph_error_t rv; - - rv = hwgraph_path_add(node_vertex, EDGE_LBL_CPU, &cpu_dir); - if (rv != GRAPH_SUCCESS) - panic("klhwg_add_node: Cannot create CPU directory\n"); - } - - /* Add each CPU */ - while (cpu) { - cpuid_t cpu_id; - cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid); - if (cpu_online(cpu_id)) - klhwg_add_cpu(node_vertex, cnode, cpu); - else - klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot); - - cpu = (klcpu_t *) - find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU); - } /* while */ + } - if(!board_disabled) - klhwg_add_hub(node_vertex, hub, cnode); - - brd = KLCF_NEXT(brd); - if (brd) - brd = find_lboard(brd, KLTYPE_SNIA); + while (cpu) { + cpuid_t cpu_id; + cpu_id = nasid_slice_to_cpuid(nasid,cpu->cpu_info.physid); + if (cpu_online(cpu_id)) + klhwg_add_cpu(node_vertex, cnode, cpu); else - break; - } while(brd); + klhwg_add_disabled_cpu(node_vertex, cnode, cpu, brd->brd_slot); + + cpu = (klcpu_t *) + find_component(brd, (klinfo_t *)cpu, KLSTRUCT_CPU); + } } /* ARGSUSED */ -void +static void __init klhwg_add_all_routers(vertex_hdl_t hwgraph_root) { nasid_t nasid; @@ -467,10 +280,6 @@ klhwg_add_all_routers(vertex_hdl_t hwgra for (cnode = 0; cnode < numnodes; cnode++) { nasid = COMPACT_TO_NASID_NODEID(cnode); - - GRPRINTF(("klhwg_add_all_routers: adding router on cnode %d\n", - cnode)); - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_ROUTER); @@ -480,41 +289,32 @@ klhwg_add_all_routers(vertex_hdl_t hwgra do { ASSERT(brd); - GRPRINTF(("Router board struct is %p\n", brd)); /* Don't add duplicate boards. */ if (brd->brd_flags & DUPLICATE_BOARD) continue; - GRPRINTF(("Router 0x%p module number is %d\n", brd, brd->brd_geoid)); /* Generate a hardware graph path for this board. */ board_to_path(brd, path_buffer); - GRPRINTF(("Router path is %s\n", path_buffer)); - /* Add the router */ - GRPRINTF(("klhwg_add_all_routers: adding %s to vertex 0x%p\n", - path_buffer, hwgraph_root)); rv = hwgraph_path_add(hwgraph_root, path_buffer, &node_vertex); + if (rv != GRAPH_SUCCESS) { + printk("Router vertex creation " + "failed. Path == %s", path_buffer); + return; + } + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, node_vertex, NULL, "Created router path.\n")); - if (rv != GRAPH_SUCCESS) - PRINT_PANIC("Router vertex creation " - "failed. Path == %s", - path_buffer); - - GRPRINTF(("klhwg_add_all_routers: get next board from 0x%p\n", - brd)); /* Find the rest of the routers stored on this node. */ } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); - - GRPRINTF(("klhwg_add_all_routers: Done.\n")); } } /* ARGSUSED */ -void +static void __init klhwg_connect_one_router(vertex_hdl_t hwgraph_root, lboard_t *brd, cnodeid_t cnode, nasid_t nasid) { @@ -527,13 +327,8 @@ klhwg_connect_one_router(vertex_hdl_t hw int port; lboard_t *dest_brd; - GRPRINTF(("klhwg_connect_one_router: Connecting router on cnode %d\n", - cnode)); - /* Don't add duplicate boards. */ if (brd->brd_flags & DUPLICATE_BOARD) { - GRPRINTF(("klhwg_connect_one_router: Duplicate router 0x%p on cnode %d\n", - brd, cnode)); return; } @@ -542,7 +337,7 @@ klhwg_connect_one_router(vertex_hdl_t hw rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl); - if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes)) + if (rc != GRAPH_SUCCESS) return; if (rc != GRAPH_SUCCESS) @@ -550,7 +345,7 @@ klhwg_connect_one_router(vertex_hdl_t hw /* We don't know what to do with multiple router components */ if (brd->brd_numcompts != 1) { - PRINT_PANIC("klhwg_connect_one_router: %d cmpts on router\n", + printk("klhwg_connect_one_router: %d cmpts on router\n", brd->brd_numcompts); return; } @@ -567,7 +362,7 @@ klhwg_connect_one_router(vertex_hdl_t hw port)); continue; } - if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) + if (NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) == INVALID_CNODEID) { continue; } @@ -582,12 +377,11 @@ klhwg_connect_one_router(vertex_hdl_t hw rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); if (rc != GRAPH_SUCCESS) { - if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + if (KL_CONFIG_DUPLICATE_BOARD(dest_brd)) continue; - PRINT_PANIC("Can't find router: %s", dest_path); + printk("Can't find router: %s", dest_path); + return; } - GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n", - path_buffer, port, dest_path)); sprintf(dest_path, "%d", port); @@ -600,15 +394,18 @@ klhwg_connect_one_router(vertex_hdl_t hw continue; } - if (rc != GRAPH_SUCCESS && !is_specified(arg_maxnodes)) - PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n", + if (rc != GRAPH_SUCCESS) { + printk("Can't create edge: %s/%s to vertex 0x%p error 0x%x\n", path_buffer, dest_path, (void *)dest_hndl, rc); + return; + } + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, router_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", dest_path)); } } -void +static void __init klhwg_connect_routers(vertex_hdl_t hwgraph_root) { nasid_t nasid; @@ -617,10 +414,6 @@ klhwg_connect_routers(vertex_hdl_t hwgra for (cnode = 0; cnode < numnodes; cnode++) { nasid = COMPACT_TO_NASID_NODEID(cnode); - - GRPRINTF(("klhwg_connect_routers: Connecting routers on cnode %d\n", - cnode)); - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_ROUTER); @@ -641,7 +434,7 @@ klhwg_connect_routers(vertex_hdl_t hwgra -void +static void __init klhwg_connect_hubs(vertex_hdl_t hwgraph_root) { nasid_t nasid; @@ -656,12 +449,9 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_ graph_error_t rc; int port; - for (cnode = 0; cnode < numnodes; cnode++) { + for (cnode = 0; cnode < numionodes; cnode++) { nasid = COMPACT_TO_NASID_NODEID(cnode); - GRPRINTF(("klhwg_connect_hubs: Connecting hubs on cnode %d\n", - cnode)); - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); ASSERT(brd); @@ -669,19 +459,15 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_ ASSERT(hub); for (port = 1; port <= MAX_NI_PORTS; port++) { - /* See if the port's active */ if (hub->hub_port[port].port_nasid == INVALID_NASID) { - GRPRINTF(("klhwg_connect_hubs: port inactive.\n")); - continue; + continue; /* Port not active */ } - if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID) + if (NASID_TO_COMPACT_NODEID(hub->hub_port[port].port_nasid) == INVALID_CNODEID) continue; /* Generate a hardware graph path for this board. */ board_to_path(brd, path_buffer); - - GRPRINTF(("klhwg_connect_hubs: Hub path is %s.\n", path_buffer)); rc = hwgraph_traverse(hwgraph_root, path_buffer, &hub_hndl); if (rc != GRAPH_SUCCESS) @@ -697,26 +483,29 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_ rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); if (rc != GRAPH_SUCCESS) { - if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + if (KL_CONFIG_DUPLICATE_BOARD(dest_brd)) continue; - PRINT_PANIC("Can't find board: %s", dest_path); + printk("Can't find board: %s", dest_path); + return; } else { char buf[1024]; - - - GRPRINTF(("klhwg_connect_hubs: Link from %s to %s.\n", - path_buffer, dest_path)); rc = hwgraph_path_add(hub_hndl, EDGE_LBL_INTERCONNECT, &hub_hndl); + + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, NULL, "Created link path.\n")); + sprintf(buf,"%s/%s",path_buffer,EDGE_LBL_INTERCONNECT); rc = hwgraph_traverse(hwgraph_root, buf, &hub_hndl); sprintf(buf,"%d",port); rc = hwgraph_edge_add(hub_hndl, dest_hndl, buf); - if (rc != GRAPH_SUCCESS) - PRINT_PANIC("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n", - path_buffer, dest_path, (void *)dest_hndl, rc); + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, hub_hndl, dest_hndl, "Created edge %s from vhdl1 to vhdl2.\n", buf)); + if (rc != GRAPH_SUCCESS) { + printk("Can't create edge: %s/%s to vertex 0x%p, error 0x%x\n", + path_buffer, dest_path, (void *)dest_hndl, rc); + return; + } } } } @@ -726,7 +515,7 @@ klhwg_connect_hubs(vertex_hdl_t hwgraph_ * hints which can later be used by the drivers using the device/driver * admin interface. */ -void +static void __init klhwg_device_disable_hints_add(void) { cnodeid_t cnode; /* node we are looking at */ @@ -785,7 +574,7 @@ klhwg_device_disable_hints_add(void) } } -void +void __init klhwg_add_all_modules(vertex_hdl_t hwgraph_root) { cmoduleid_t cm; @@ -807,6 +596,7 @@ klhwg_add_all_modules(vertex_hdl_t hwgra rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl); ASSERT(rc == GRAPH_SUCCESS); rc = rc; + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, module_vhdl, NULL, "Created module path.\n")); hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]); @@ -818,24 +608,24 @@ klhwg_add_all_modules(vertex_hdl_t hwgra rc = hwgraph_path_add(hwgraph_root, name, &vhdl); ASSERT_ALWAYS(rc == GRAPH_SUCCESS); rc = rc; + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, vhdl, NULL, "Created L1 path.\n")); - hwgraph_info_add_LBL(vhdl, - INFO_LBL_ELSC, - (arbitrary_info_t) (__psint_t) 1); + hwgraph_info_add_LBL(vhdl, INFO_LBL_ELSC, + (arbitrary_info_t)1); } } -void +void __init klhwg_add_all_nodes(vertex_hdl_t hwgraph_root) { cnodeid_t cnode; - for (cnode = 0; cnode < numnodes; cnode++) { + for (cnode = 0; cnode < numionodes; cnode++) { klhwg_add_node(hwgraph_root, cnode); } - for (cnode = 0; cnode < numnodes; cnode++) { + for (cnode = 0; cnode < numionodes; cnode++) { klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode)); } diff -puN arch/ia64/sn/io/sn2/l1_command.c~linus arch/ia64/sn/io/sn2/l1_command.c --- 25/arch/ia64/sn/io/sn2/l1_command.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/l1_command.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -12,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -60,8 +58,6 @@ int iobrick_rack_bay_type_get( nasid_t n *rack = (result & MODULE_RACK_MASK) >> MODULE_RACK_SHFT; *bay = (result & MODULE_BPOS_MASK) >> MODULE_BPOS_SHFT; *brick_type = (result & MODULE_BTYPE_MASK) >> MODULE_BTYPE_SHFT; - *brick_type = toupper(*brick_type); - return 0; } @@ -76,63 +72,6 @@ int iomoduleid_get(nasid_t nasid) return result; } -int iobrick_module_get(nasid_t nasid) -{ - uint rnum, rack, bay, brick_type, t; - int ret; - - /* construct module ID from rack and slot info */ - - if ((ret = iobrick_rack_bay_type_get(nasid, &rnum, &bay, &brick_type)) < 0) - return ret; - - if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) - return ELSC_ERROR_MODULE; - - /* Build a moduleid_t-compatible rack number */ - - rack = 0; - t = rnum / 100; /* rack class (CPU/IO) */ - if (t > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) - return ELSC_ERROR_MODULE; - RACK_ADD_CLASS(rack, t); - rnum %= 100; - - t = rnum / 10; /* rack group */ - if (t > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) - return ELSC_ERROR_MODULE; - RACK_ADD_GROUP(rack, t); - - t = rnum % 10; /* rack number (one-based) */ - if (t-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) - return ELSC_ERROR_MODULE; - RACK_ADD_NUM(rack, t); - - switch( brick_type ) { - case L1_BRICKTYPE_IX: - brick_type = MODULE_IXBRICK; break; - case L1_BRICKTYPE_PX: - brick_type = MODULE_PXBRICK; break; - case L1_BRICKTYPE_I: - brick_type = MODULE_IBRICK; break; - case L1_BRICKTYPE_P: - brick_type = MODULE_PBRICK; break; - case L1_BRICKTYPE_X: - brick_type = MODULE_XBRICK; break; - } - - ret = RBT_TO_MODULE(rack, bay, brick_type); - - return ret; -} - -/* - * iobrick_module_get_nasid() returns a module_id which has the brick - * type encoded in bits 15-12, but this is not the true brick type... - * The module_id returned by iobrick_module_get_nasid() is modified - * to make a PEBRICKs & PXBRICKs look like a PBRICK. So this routine - * iobrick_type_get_nasid() returns the true unmodified brick type. - */ int iobrick_type_get_nasid(nasid_t nasid) { @@ -158,14 +97,6 @@ iobrick_type_get_nasid(nasid_t nasid) return -1; /* unknown brick */ } -int iobrick_module_get_nasid(nasid_t nasid) -{ - int io_moduleid; - - io_moduleid = iobrick_module_get(nasid); - return io_moduleid; -} - /* * given a L1 bricktype, return a bricktype string. This string is the * string that will be used in the hwpath for I/O bricks @@ -178,26 +109,23 @@ iobrick_L1bricktype_to_name(int type) default: return("Unknown"); - case L1_BRICKTYPE_X: - return("Xbrick"); - - case L1_BRICKTYPE_I: - return("Ibrick"); - - case L1_BRICKTYPE_P: - return("Pbrick"); - case L1_BRICKTYPE_PX: - return("PXbrick"); + return(EDGE_LBL_PXBRICK); + + case L1_BRICKTYPE_OPUS: + return(EDGE_LBL_OPUSBRICK); case L1_BRICKTYPE_IX: - return("IXbrick"); + return(EDGE_LBL_IXBRICK); case L1_BRICKTYPE_C: return("Cbrick"); case L1_BRICKTYPE_R: return("Rbrick"); + + case L1_BRICKTYPE_CHI_CG: + return(EDGE_LBL_CGBRICK); } } diff -puN arch/ia64/sn/io/sn2/Makefile~linus arch/ia64/sn/io/sn2/Makefile --- 25/arch/ia64/sn/io/sn2/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,8 +9,6 @@ # Makefile for the sn2 specific io routines. # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += pcibr/ ml_SN_intr.o shub_intr.o shuberror.o shub.o bte_error.o \ pic.o geo_op.o l1_command.o klconflib.o klgraph.o ml_SN_init.o \ ml_iograph.o module.o pciio.o xbow.o xtalk.o shubio.o diff -puN arch/ia64/sn/io/sn2/ml_iograph.c~linus arch/ia64/sn/io/sn2/ml_iograph.c --- 25/arch/ia64/sn/io/sn2/ml_iograph.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/ml_iograph.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -7,28 +6,16 @@ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include #include #include #include -#include -#include #include -#include #include #include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include #include +#include /* #define IOGRAPH_DEBUG */ #ifdef IOGRAPH_DEBUG @@ -37,8 +24,6 @@ #define DBG(x...) #endif /* IOGRAPH_DEBUG */ -/* #define PROBE_TEST */ - /* At most 2 hubs can be connected to an xswitch */ #define NUM_XSWITCH_VOLUNTEER 2 @@ -49,7 +34,7 @@ * xswitch vertex is created. */ typedef struct xswitch_vol_s { - mutex_t xswitch_volunteer_mutex; + struct semaphore xswitch_volunteer_mutex; int xswitch_volunteer_count; vertex_hdl_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; } *xswitch_vol_t; @@ -59,12 +44,15 @@ xswitch_vertex_init(vertex_hdl_t xswitch { xswitch_vol_t xvolinfo; int rc; - extern void * snia_kmem_zalloc(size_t size, int flag); - xvolinfo = snia_kmem_zalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL); - mutex_init(&xvolinfo->xswitch_volunteer_mutex); - rc = hwgraph_info_add_LBL(xswitch, - INFO_LBL_XSWITCH_VOL, + xvolinfo = kmalloc(sizeof(struct xswitch_vol_s), GFP_KERNEL); + if (xvolinfo <= 0 ) { + printk("xswitch_vertex_init: out of memory\n"); + return; + } + memset(xvolinfo, 0, sizeof(struct xswitch_vol_s)); + init_MUTEX(&xvolinfo->xswitch_volunteer_mutex); + rc = hwgraph_info_add_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t)xvolinfo); ASSERT(rc == GRAPH_SUCCESS); rc = rc; } @@ -79,12 +67,12 @@ xswitch_volunteer_delete(vertex_hdl_t xs { xswitch_vol_t xvolinfo; int rc; - extern void snia_kmem_free(void *ptr, size_t size); rc = hwgraph_info_remove_LBL(xswitch, INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); - snia_kmem_free(xvolinfo, sizeof(struct xswitch_vol_s)); + if (xvolinfo > 0) + kfree(xvolinfo); } /* * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. @@ -101,14 +89,16 @@ volunteer_for_widgets(vertex_hdl_t xswit INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { - if (!is_headless_node_vertex(master)) + if (!is_headless_node_vertex(master)) { + char name[MAXDEVNAME]; printk(KERN_WARNING - "volunteer for widgets: vertex 0x%p has no info label", - (void *)xswitch); + "volunteer for widgets: vertex %s has no info label", + vertex_to_name(xswitch, name, MAXDEVNAME)); + } return; } - mutex_lock(&xvolinfo->xswitch_volunteer_mutex); + down(&xvolinfo->xswitch_volunteer_mutex); ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; xvolinfo->xswitch_volunteer_count++; @@ -126,7 +116,7 @@ volunteer_for_widgets(vertex_hdl_t xswit xvolinfo->xswitch_volunteer[1] = hubv; } } - mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); + up(&xvolinfo->xswitch_volunteer_mutex); } extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum); @@ -158,11 +148,13 @@ assign_widgets_to_volunteers(vertex_hdl_ INFO_LBL_XSWITCH_VOL, (arbitrary_info_t *)&xvolinfo); if (xvolinfo == NULL) { - if (!is_headless_node_vertex(hubv)) + if (!is_headless_node_vertex(hubv)) { + char name[MAXDEVNAME]; printk(KERN_WARNING - "assign_widgets_to_volunteers:vertex 0x%p has " + "assign_widgets_to_volunteers:vertex %s has " " no info label", - (void *)xswitch); + vertex_to_name(xswitch, name, MAXDEVNAME)); + } return; } @@ -182,9 +174,6 @@ assign_widgets_to_volunteers(vertex_hdl_ for (widgetnum=HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { int i; - /* - * Ignore disabled/empty ports. - */ if (!xbow_port_io_enabled(nasid, widgetnum)) continue; @@ -193,16 +182,17 @@ assign_widgets_to_volunteers(vertex_hdl_ * hub that owned it in the prom. */ if (is_master_baseio_nasid_widget(nasid, widgetnum)) { - extern nasid_t get_master_baseio_nasid(void); + extern nasid_t snia_get_master_baseio_nasid(void); for (i=0; ixswitch_volunteer[i]; hubinfo_get(hubv, &hubinfo); nasid = hubinfo->h_nasid; - if (nasid == get_master_baseio_nasid()) + if (nasid == snia_get_master_baseio_nasid()) goto do_assignment; } - PRINT_PANIC("Nasid == %d, console nasid == %d", - nasid, get_master_baseio_nasid()); + printk("Nasid == %d, console nasid == %d", + nasid, snia_get_master_baseio_nasid()); + nasid = 0; } /* @@ -236,38 +226,6 @@ do_assignment: xswitch_volunteer_delete(xswitch); } -/* - * Early iograph initialization. Called by master CPU in mlreset(). - * Useful for including iograph.o in kernel.o. - */ -void -iograph_early_init(void) -{ -/* - * Need new way to get this information .. - */ - cnodeid_t cnode; - nasid_t nasid; - lboard_t *board; - - /* - * Init. the board-to-hwgraph link early, so FRU analyzer - * doesn't trip on leftover values if we panic early on. - */ - for(cnode = 0; cnode < numnodes; cnode++) { - nasid = COMPACT_TO_NASID_NODEID(cnode); - board = (lboard_t *)KL_CONFIG_INFO(nasid); - DBG("iograph_early_init: Found board 0x%p\n", board); - - /* Check out all the board info stored on a node */ - while(board) { - board->brd_graph_link = GRAPH_VERTEX_NONE; - board = KLCF_NEXT(board); - DBG("iograph_early_init: Found board 0x%p\n", board); - } - } -} - /* * Probe to see if this hub's xtalk link is active. If so, * return the Crosstalk Identification of the widget that we talk to. @@ -323,7 +281,7 @@ early_probe_for_widget(vertex_hdl_t hubv * */ -void +static void io_xswitch_widget_init(vertex_hdl_t xswitchv, vertex_hdl_t hubv, xwidgetnum_t widgetnum) @@ -424,11 +382,10 @@ io_xswitch_widget_init(vertex_hdl_t xs sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%s" "/%s/%d", buffer, geo_slab(board->brd_geoid), - (board->brd_type == KLTYPE_IBRICK) ? EDGE_LBL_IBRICK : - (board->brd_type == KLTYPE_PBRICK) ? EDGE_LBL_PBRICK : (board->brd_type == KLTYPE_PXBRICK) ? EDGE_LBL_PXBRICK : (board->brd_type == KLTYPE_IXBRICK) ? EDGE_LBL_IXBRICK : - (board->brd_type == KLTYPE_XBRICK) ? EDGE_LBL_XBRICK : "?brick", + (board->brd_type == KLTYPE_CGBRICK) ? EDGE_LBL_CGBRICK : + (board->brd_type == KLTYPE_OPUSBRICK) ? EDGE_LBL_OPUSBRICK : "?brick", EDGE_LBL_XTALK, widgetnum); DBG("io_xswitch_widget_init: path= %s\n", pathname); @@ -465,8 +422,7 @@ io_xswitch_widget_init(vertex_hdl_t xs (void)xwidget_register(&hwid, widgetv, widgetnum, hubv, hub_widgetid); - ia64_sn_sysctl_iobrick_module_get(nasid, &io_module); - + io_module = iomoduleid_get(nasid); if (io_module >= 0) { char buffer[16]; vertex_hdl_t to, from; @@ -477,8 +433,8 @@ io_xswitch_widget_init(vertex_hdl_t xs memset(buffer, 0, 16); format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); - if ( islower(MODULE_GET_BTCHAR(io_module)) ) { - bt = toupper(MODULE_GET_BTCHAR(io_module)); + if ( isupper(MODULE_GET_BTCHAR(io_module)) ) { + bt = tolower(MODULE_GET_BTCHAR(io_module)); } else { bt = MODULE_GET_BTCHAR(io_module); @@ -508,18 +464,12 @@ io_xswitch_widget_init(vertex_hdl_t xs ASSERT_ALWAYS(to); rc = hwgraph_edge_add(from, to, EDGE_LBL_INTERCONNECT); - if (rc == -EEXIST) - goto link_done; - if (rc != GRAPH_SUCCESS) { + if (rc != -EEXIST && rc != GRAPH_SUCCESS) { printk("%s: Unable to establish link" " for xbmon.", pathname); } -link_done: } -#ifdef SN0_USE_BTE - bte_bpush_war(cnode, (void *)board); -#endif } } @@ -540,70 +490,6 @@ io_init_xswitch_widgets(vertex_hdl_t xsw } /* - * For each PCI bridge connected to the xswitch, add a link from the - * board's klconfig info to the bridge's hwgraph vertex. This lets - * the FRU analyzer find the bridge without traversing the hardware - * graph and risking hangs. - */ -static void -io_link_xswitch_widgets(vertex_hdl_t xswitchv, cnodeid_t cnodeid) -{ - xwidgetnum_t widgetnum; - char pathname[128]; - vertex_hdl_t vhdl; - nasid_t nasid, peer_nasid; - lboard_t *board; - - - - /* And its connected hub's nasids */ - nasid = COMPACT_TO_NASID_NODEID(cnodeid); - peer_nasid = NODEPDA(cnodeid)->xbow_peer; - - /* - * Look for paths matching "/pci" under xswitchv. - * For every widget, init. its lboard's hwgraph link. If the - * board has a PCI bridge, point the link to it. - */ - for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; - widgetnum++) { - sprintf(pathname, "%d", widgetnum); - if (hwgraph_traverse(xswitchv, pathname, &vhdl) != - GRAPH_SUCCESS) - continue; - - board = find_lboard_module((lboard_t *)KL_CONFIG_INFO(nasid), - NODEPDA(cnodeid)->geoid); - if (board == NULL && peer_nasid != INVALID_NASID) { - /* - * Try to find the board on our peer - */ - board = find_lboard_module( - (lboard_t *)KL_CONFIG_INFO(peer_nasid), - NODEPDA(cnodeid)->geoid); - } - if (board == NULL) { - printk(KERN_WARNING "Could not find PROM info for vertex 0x%p, " - "FRU analyzer may fail", - (void *)vhdl); - return; - } - - /* Check both buses */ - sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); - if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) - board->brd_graph_link = vhdl; - else { - sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); - if (hwgraph_traverse(xswitchv, pathname, &vhdl) == GRAPH_SUCCESS) - board->brd_graph_link = vhdl; - else - board->brd_graph_link = GRAPH_VERTEX_NONE; - } - } -} - -/* * Initialize all I/O on the specified node. */ static void @@ -617,7 +503,6 @@ io_init_node(cnodeid_t cnodeid) nodepda_t *npdap; struct semaphore *peer_sema = 0; uint32_t widget_partnum; - cpu_cookie_t c = 0; npdap = NODEPDA(cnodeid); @@ -633,23 +518,11 @@ io_init_node(cnodeid_t cnodeid) ASSERT(hubv != GRAPH_VERTEX_NONE); - /* - * Read mfg info on this hub - */ - /* * If nothing connected to this hub's xtalk port, we're done. */ early_probe_for_widget(hubv, &hwid); if (hwid.part_num == XWIDGET_PART_NUM_NONE) { -#ifdef PROBE_TEST - if ((cnodeid == 1) || (cnodeid == 2)) { - int index; - - for (index = 0; index < 600; index++) - DBG("Interfering with device probing!!!\n"); - } -#endif DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); return; /* NOTREACHED */ @@ -694,16 +567,12 @@ io_init_node(cnodeid_t cnodeid) * accordingly. In particular, SN00 has direct connected bridge, * and hence widget id is Not 0. */ + widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE + (COMPACT_TO_NASID_NODEID(cnodeid), 0) + + WIDGET_ID))) & WIDGET_PART_NUM) + >> WIDGET_PART_NUM_SHFT; - widget_partnum = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + WIDGET_ID))) & WIDGET_PART_NUM) >> WIDGET_PART_NUM_SHFT; - - if (widget_partnum == BRIDGE_WIDGET_PART_NUM || - widget_partnum == XBRIDGE_WIDGET_PART_NUM){ - npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); - - DBG("io_init_node: Found XBRIDGE widget_partnum= 0x%x\n", widget_partnum); - - } else if ((widget_partnum == XBOW_WIDGET_PART_NUM) || + if ((widget_partnum == XBOW_WIDGET_PART_NUM) || (widget_partnum == XXBOW_WIDGET_PART_NUM) || (widget_partnum == PXBOW_WIDGET_PART_NUM) ) { /* @@ -714,11 +583,14 @@ io_init_node(cnodeid_t cnodeid) npdap->basew_id = 0; } else { - npdap->basew_id = (((*(volatile int32_t *)(NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0) + BRIDGE_WID_CONTROL))) & WIDGET_WIDGET_ID); + void *bridge; + extern uint64_t pcireg_control_get(void *); - panic(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv); + bridge = (void *)NODE_SWIN_BASE(COMPACT_TO_NASID_NODEID(cnodeid), 0); + npdap->basew_id = pcireg_control_get(bridge) & WIDGET_WIDGET_ID; - /*NOTREACHED*/ + printk(" ****io_init_node: Unknown Widget Part Number 0x%x Widget ID 0x%x attached to Hubv 0x%p ****\n", widget_partnum, npdap->basew_id, (void *)hubv); + return; } { char widname[10]; @@ -776,32 +648,22 @@ io_init_node(cnodeid_t cnodeid) /* Signal that we're done */ if (peer_sema) { - mutex_unlock(peer_sema); + up(peer_sema); } } else { /* Wait 'til master is done assigning widgets. */ - mutex_lock(&npdap->xbow_sema); + down(&npdap->xbow_sema); } -#ifdef PROBE_TEST - if ((cnodeid == 1) || (cnodeid == 2)) { - int index; - - for (index = 0; index < 500; index++) - DBG("Interfering with device probing!!!\n"); - } -#endif /* Now both nodes can safely inititialize widgets */ io_init_xswitch_widgets(switchv, cnodeid); - io_link_xswitch_widgets(switchv, cnodeid); DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid); } #include -/* #endif */ /* * Initialize all I/O devices. Starting closest to nodes, probe and @@ -810,75 +672,52 @@ io_init_node(cnodeid_t cnodeid) void init_all_devices(void) { - /* Governor on init threads..bump up when safe - * (beware many devfs races) - */ cnodeid_t cnodeid, active; active = 0; - for (cnodeid = 0; cnodeid < numnodes; cnodeid++) { + for (cnodeid = 0; cnodeid < numionodes; cnodeid++) { DBG("init_all_devices: Calling io_init_node() for cnode %d\n", cnodeid); io_init_node(cnodeid); DBG("init_all_devices: Done io_init_node() for cnode %d\n", cnodeid); } - for (cnodeid = 0; cnodeid < numnodes; cnodeid++) + for (cnodeid = 0; cnodeid < numnodes; cnodeid++) { /* * Update information generated by IO init. */ update_node_information(cnodeid); - -#if HWG_PRINT - hwgraph_print(); -#endif - + } } -#define toint(x) ((int)(x) - (int)('0')) - static struct io_brick_map_s io_brick_tab[] = { -/* Ibrick widget number to PCI bus number map */ - { MODULE_IBRICK, /* Ibrick type */ +/* PXbrick widget number to PCI bus number map */ + { MODULE_PXBRICK, /* PXbrick type */ /* PCI Bus # Widget # */ { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ 0, /* 0x8 */ 0, /* 0x9 */ 0, 0, /* 0xa - 0xb */ - 0, /* 0xc */ - 0, /* 0xd */ - 2, /* 0xe */ - 1 /* 0xf */ - } - }, - -/* Pbrick widget number to PCI bus number map */ - { MODULE_PBRICK, /* Pbrick type */ - /* PCI Bus # Widget # */ - { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ - 2, /* 0x8 */ - 1, /* 0x9 */ - 0, 0, /* 0xa - 0xb */ - 4, /* 0xc */ - 6, /* 0xd */ - 3, /* 0xe */ - 5 /* 0xf */ + 1, /* 0xc */ + 5, /* 0xd */ + 0, /* 0xe */ + 3 /* 0xf */ } }, -/* PXbrick widget number to PCI bus number map */ - { MODULE_PXBRICK, /* PXbrick type */ +/* OPUSbrick widget number to PCI bus number map */ + { MODULE_OPUSBRICK, /* OPUSbrick type */ /* PCI Bus # Widget # */ { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ 0, /* 0x8 */ 0, /* 0x9 */ 0, 0, /* 0xa - 0xb */ - 1, /* 0xc */ - 5, /* 0xd */ + 0, /* 0xc */ + 0, /* 0xd */ 0, /* 0xe */ - 3 /* 0xf */ + 1 /* 0xf */ } }, @@ -896,19 +735,19 @@ struct io_brick_map_s io_brick_tab[] = { } }, -/* Xbrick widget to XIO slot map */ - { MODULE_XBRICK, /* Xbrick type */ - /* XIO Slot # Widget # */ +/* CG brick widget number to PCI bus number map */ + { MODULE_CGBRICK, /* CG brick */ + /* PCI Bus # Widget # */ { 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ - 1, /* 0x8 */ - 3, /* 0x9 */ - 0, 0, /* 0xa - 0xb */ - 2, /* 0xc */ - 4, /* 0xd */ + 0, /* 0x8 */ + 0, /* 0x9 */ + 0, 1, /* 0xa - 0xb */ + 0, /* 0xc */ + 0, /* 0xd */ 0, /* 0xe */ 0 /* 0xf */ - } - } + } + }, }; /* diff -puN arch/ia64/sn/io/sn2/ml_SN_init.c~linus arch/ia64/sn/io/sn2/ml_SN_init.c --- 25/arch/ia64/sn/io/sn2/ml_SN_init.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/ml_SN_init.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -13,58 +12,16 @@ #include #include #include -#include #include #include #include #include #include -extern cpuid_t master_procid; int maxcpus; extern xwidgetnum_t hub_widget_id(nasid_t); -extern void iograph_early_init(void); - -nasid_t master_nasid = INVALID_NASID; /* This is the partition master nasid */ -nasid_t master_baseio_nasid = INVALID_NASID; /* This is the master base I/O nasid */ - - -/* - * mlreset(void) - * very early machine reset - at this point NO interrupts have been - * enabled; nor is memory, tlb, p0, etc setup. - * - * slave is zero when mlreset is called for the master processor and - * is nonzero thereafter. - */ - - -void -mlreset(int slave) -{ - /* - * We are the master cpu and node. - */ - master_nasid = get_nasid(); - set_master_bridge_base(); - - /* We're the master processor */ - master_procid = smp_processor_id(); - master_nasid = cpuid_to_nasid(master_procid); - - /* - * master_nasid we get back better be same as one from - * get_nasid() - */ - ASSERT_ALWAYS(master_nasid == get_nasid()); - - /* early initialization of iograph */ - iograph_early_init(); -} - - /* XXX - Move the meat of this to intr.c ? */ /* * Set up the platform-dependent fields in the nodepda. @@ -72,22 +29,26 @@ mlreset(int slave) void init_platform_nodepda(nodepda_t *npda, cnodeid_t node) { hubinfo_t hubinfo; + nasid_t nasid; extern void router_map_init(nodepda_t *); extern void router_queue_init(nodepda_t *,cnodeid_t); extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int); /* Allocate per-node platform-dependent data */ - hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s)); + + nasid = COMPACT_TO_NASID_NODEID(node); + if (node >= numnodes) /* Headless/memless IO nodes */ + hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(0), sizeof(struct hubinfo_s)); + else + hubinfo = (hubinfo_t)alloc_bootmem_node(NODE_DATA(node), sizeof(struct hubinfo_s)); npda->pdinfo = (void *)hubinfo; hubinfo->h_nodepda = npda; hubinfo->h_cnodeid = node; - hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node); spin_lock_init(&hubinfo->h_crblock); - hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid); npda->xbow_peer = INVALID_NASID; /* @@ -104,7 +65,22 @@ void init_platform_nodepda(nodepda_t *np npda->npda_rip_last = &npda->npda_rip_first; npda->geoid.any.type = GEO_TYPE_INVALID; - mutex_init_locked(&npda->xbow_sema); /* init it locked? */ + init_MUTEX_LOCKED(&npda->xbow_sema); /* init it locked? */ +} + +void +init_platform_hubinfo(nodepda_t **nodepdaindr) { + cnodeid_t cnode; + hubinfo_t hubinfo; + nodepda_t *npda; + extern int numionodes; + + for (cnode = 0; cnode < numionodes; cnode++) { + npda = nodepdaindr[cnode]; + hubinfo = (hubinfo_t)npda->pdinfo; + hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(cnode); + hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid); + } } void diff -puN arch/ia64/sn/io/sn2/ml_SN_intr.c~linus arch/ia64/sn/io/sn2/ml_SN_intr.c --- 25/arch/ia64/sn/io/sn2/ml_SN_intr.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/ml_SN_intr.c 2004-01-19 22:17:21.000000000 -0800 @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -82,7 +81,7 @@ void intr_init_vecblk(cnodeid_t node) /* Config and enable UART interrupt, all nodes. */ local5_config.sh_local_int5_config_regval = 0; local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR; - local5_config.sh_local_int5_config_s.pid = cpu0; + local5_config.sh_local_int5_config_s.pid = cpu; HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG), local5_config.sh_local_int5_config_regval); @@ -223,7 +222,7 @@ static cpuid_t intr_cpu_choose_from_node int intrs; cpu = cnode_slice_to_cpuid(cnode, slice); - if (cpu == num_online_cpus()) + if (cpu == NR_CPUS) continue; if (!cpu_online(cpu)) continue; diff -puN arch/ia64/sn/io/sn2/module.c~linus arch/ia64/sn/io/sn2/module.c --- 25/arch/ia64/sn/io/sn2/module.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/module.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -9,14 +8,14 @@ #include #include +#include +#include #include #include #include -#include #include #include #include -#include #include #include #include @@ -40,40 +39,8 @@ int nummodules; #define SN00_SERIAL_FUDGE 0x3b1af409d513c2 #define SN0_SERIAL_FUDGE 0x6e -void -encode_int_serial(uint64_t src,uint64_t *dest) -{ - uint64_t val; - int i; - - val = src + SN00_SERIAL_FUDGE; - - - for (i = 0; i < sizeof(long long); i++) { - ((char*)dest)[i] = - ((char*)&val)[sizeof(long long)/2 + - ((i%2) ? ((i/2 * -1) - 1) : (i/2))]; - } -} - - -void -decode_int_serial(uint64_t src, uint64_t *dest) -{ - uint64_t val; - int i; - - for (i = 0; i < sizeof(long long); i++) { - ((char*)&val)[sizeof(long long)/2 + - ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = - ((char*)&src)[i]; - } - - *dest = val - SN00_SERIAL_FUDGE; -} - -void +static void __init encode_str_serial(const char *src, char *dest) { int i; @@ -86,20 +53,8 @@ encode_str_serial(const char *src, char } } -void -decode_str_serial(const char *src, char *dest) -{ - int i; - - for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { - dest[MAX_SERIAL_NUM_SIZE/2 + - ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] - - SN0_SERIAL_FUDGE; - } -} - - -module_t *module_lookup(moduleid_t id) +module_t * __init +module_lookup(moduleid_t id) { int i; @@ -121,13 +76,14 @@ module_t *module_lookup(moduleid_t id) * * The node number is added to the list of nodes in the module. */ - -module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid) +static module_t * __init +module_add_node(geoid_t geoid, cnodeid_t cnodeid) { module_t *m; int i; char buffer[16]; moduleid_t moduleid; + slabid_t slab_number; memset(buffer, 0, 16); moduleid = geo_module(geoid); @@ -136,14 +92,16 @@ module_t *module_add_node(geoid_t geoid, if ((m = module_lookup(moduleid)) == 0) { m = kmalloc(sizeof (module_t), GFP_KERNEL); - memset(m, 0 , sizeof(module_t)); ASSERT_ALWAYS(m); + memset(m, 0 , sizeof(module_t)); + + for (slab_number = 0; slab_number <= MAX_SLABS; slab_number++) { + m->nodes[slab_number] = -1; + } m->id = moduleid; spin_lock_init(&m->lock); - mutex_init_locked(&m->thdcnt); - /* Insert in sorted order by module number */ for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--) @@ -153,16 +111,26 @@ module_t *module_add_node(geoid_t geoid, nummodules++; } - m->nodes[m->nodecnt] = cnodeid; - m->geoid[m->nodecnt] = geoid; - m->nodecnt++; + /* + * Save this information in the correct slab number of the node in the + * module. + */ + slab_number = geo_slab(geoid); + DPRINTF("slab number added 0x%x\n", slab_number); + + if (m->nodes[slab_number] != -1) { + printk("module_add_node .. slab previously found\n"); + return NULL; + } - DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt); + m->nodes[slab_number] = cnodeid; + m->geoid[slab_number] = geoid; return m; } -int module_probe_snum(module_t *m, nasid_t nasid) +static int __init +module_probe_snum(module_t *m, nasid_t host_nasid, nasid_t nasid) { lboard_t *board; klmod_serial_num_t *comp; @@ -171,13 +139,10 @@ int module_probe_snum(module_t *m, nasid /* * record brick serial number */ - board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + board = find_lboard((lboard_t *) KL_CONFIG_INFO(host_nasid), KLTYPE_SNIA); if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) { -#if LDEBUG - printf ("module_probe_snum: no IP35 board found!\n"); -#endif return 0; } @@ -186,12 +151,6 @@ int module_probe_snum(module_t *m, nasid encode_str_serial( serial_number, m->snum.snum_str ); m->snum_valid = 1; } -#if LDEBUG - else { - printf("module_probe_snum: brick serial number is null!\n"); - } - printf("module_probe_snum: brick serial number == %s\n", serial_number); -#endif /* DEBUG */ board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW); @@ -202,22 +161,10 @@ int module_probe_snum(module_t *m, nasid comp = GET_SNUM_COMP(board); if (comp) { -#if LDEBUG - int i; - - printf("********found module with id %x and string", m->id); - - for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) - printf(" %x ", comp->snum.snum_str[i]); - - printf("\n"); /* Fudged string is not ASCII */ -#endif - if (comp->snum.snum_str[0] != '\0') { - memcpy(m->sys_snum, - comp->snum.snum_str, - MAX_SERIAL_NUM_SIZE); - m->sys_snum_valid = 1; + memcpy(m->sys_snum, comp->snum.snum_str, + MAX_SERIAL_NUM_SIZE); + m->sys_snum_valid = 1; } } @@ -230,7 +177,7 @@ int module_probe_snum(module_t *m, nasid } } -void +void __init io_module_init(void) { cnodeid_t node; @@ -243,21 +190,20 @@ io_module_init(void) nserial = 0; + /* + * First pass just scan for compute node boards KLTYPE_SNIA. + * We do not support memoryless compute nodes. + */ for (node = 0; node < numnodes; node++) { nasid = COMPACT_TO_NASID_NODEID(node); board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA); ASSERT(board); - m = module_add_node(board->brd_geoid, node); + HWGRAPH_DEBUG((__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found Shub lboard 0x%lx nasid 0x%x cnode 0x%x \n", (unsigned long)board, (int)nasid, (int)node)); - if (! m->snum_valid && module_probe_snum(m, nasid)) + m = module_add_node(board->brd_geoid, node); + if (! m->snum_valid && module_probe_snum(m, nasid, nasid)) nserial++; } - - DPRINTF("********found total of %d serial numbers in the system\n", - nserial); - - if (nserial == 0) - DPRINTF(KERN_WARNING "io_module_init: No serial number found.\n"); } diff -puN arch/ia64/sn/io/sn2/pcibr/Makefile~linus arch/ia64/sn/io/sn2/pcibr/Makefile --- 25/arch/ia64/sn/io/sn2/pcibr/Makefile~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,7 +9,8 @@ # Makefile for the sn2 specific pci bridge routines. # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - -obj-y += pcibr_ate.o pcibr_config.o pcibr_dvr.o pcibr_hints.o pcibr_intr.o pcibr_rrb.o \ - pcibr_slot.o pcibr_error.o +obj-y += pcibr_ate.o pcibr_config.o \ + pcibr_dvr.o pcibr_hints.o \ + pcibr_intr.o pcibr_rrb.o \ + pcibr_slot.o pcibr_error.o \ + pcibr_reg.o diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,30 +7,12 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include -#include - -#ifndef LOCAL -#define LOCAL static -#endif /* * functions @@ -62,7 +43,7 @@ void ate_thaw(pcibr_dmamap_t pcibr_dmama #define ATE_NUM_ENTRIES(n) _ate_info[n] /* Possible choices for number of ATE entries in Bridge's SSRAM */ -LOCAL int _ate_info[] = +static int _ate_info[] = { 0, /* 0 entries */ 8 * 1024, /* 8K entries */ @@ -85,7 +66,6 @@ pcibr_init_ext_ate_ram(bridge_t *bridge) int num_entries, entry; int i, j; bridgereg_t old_enable, new_enable; - int s; /* Probe SSRAM to determine its size. */ old_enable = bridge->b_int_enable; @@ -112,12 +92,10 @@ pcibr_init_ext_ate_ram(bridge_t *bridge) * The read following the write is required for the Bridge war */ - s = splhi(); bridge->b_wid_control = (bridge->b_wid_control & ~BRIDGE_CTRL_SSRAM_SIZE_MASK) | BRIDGE_CTRL_SSRAM_SIZE(largest_working_size); bridge->b_wid_control; /* inval addr bug war */ - splx(s); num_entries = ATE_NUM_ENTRIES(largest_working_size); @@ -381,25 +359,9 @@ ate_write(pcibr_soft_t pcibr_soft, int ate_count, bridge_ate_t ate) { - if (IS_PIC_SOFT(pcibr_soft) ) { - while (ate_count-- > 0) { - *ate_ptr++ = ate; - ate += IOPGSIZE; - } - } - else { - if (io_get_sh_swapper(NASID_GET(ate_ptr))) { - while (ate_count-- > 0) { - *ate_ptr++ = __swab64(ate); - ate += IOPGSIZE; - } - } - else { - while (ate_count-- > 0) { - *ate_ptr++ = ate; - ate += IOPGSIZE; - } - } + while (ate_count-- > 0) { + *ate_ptr++ = ate; + ate += IOPGSIZE; } } @@ -441,19 +403,7 @@ ate_thaw(pcibr_dmamap_t pcibr_dmamap, for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) { if ((cmd_reg = cmd_regs[slot]) & PCI_CMD_BUS_MASTER) { - if ( IS_PIC_SOFT(pcibr_soft) ) { - pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg); - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = __swab32(cmd_reg); - } - else { -// BUG(); /* Does this really work if called when io_get_sh_swapper = 0? */ -// bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg; - pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg); - } - } + pcibr_slot_config_set(bridge, slot, PCI_CFG_COMMAND/4, cmd_reg); } } pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY; diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_config.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_config.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,27 +7,12 @@ */ #include -#include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include -#include extern pcibr_info_t pcibr_info_get(vertex_hdl_t); @@ -38,23 +22,12 @@ void pcibr_config_set(verte void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); /* - * on sn-ia we need to twiddle the the addresses going out - * the pci bus because we use the unswizzled synergy space - * (the alternative is to use the swizzled synergy space - * and byte swap the data) + * fancy snia bit twiddling.... */ -#define CB(b,r) (((volatile uint8_t *) b)[((r)^4)]) -#define CS(b,r) (((volatile uint16_t *) b)[((r^4)/2)]) -#define CW(b,r) (((volatile uint32_t *) b)[((r^4)/4)]) - #define CBP(b,r) (((volatile uint8_t *) b)[(r)]) #define CSP(b,r) (((volatile uint16_t *) b)[((r)/2)]) #define CWP(b,r) (((volatile uint32_t *) b)[(r)/4]) -#define SCB(b,r) (((volatile uint8_t *) b)[((r)^3)]) -#define SCS(b,r) (((volatile uint16_t *) b)[((r^2)/2)]) -#define SCW(b,r) (((volatile uint32_t *) b)[((r)/4)]) - /* * Return a config space address for given slot / func / offset. Note the * returned pointer is a 32bit word (ie. cfg_p) aligned pointer pointing to diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -7,31 +6,18 @@ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include #include #include #include -#include #include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include + +#include #include /* @@ -39,36 +25,15 @@ * -pcibr_debug_mask is the mask of the different types of debugging * you want to enable. See sys/PCI/pcibr_private.h * -pcibr_debug_module is the module you want to trace. By default - * all modules are trace. For IP35 this value has the format of - * something like "001c10". For IP27 this value is a node number, - * i.e. "1", "2"... For IP30 this is undefined and should be set to - * 'all'. - * -pcibr_debug_widget is the widget you want to trace. For IP27 - * the widget isn't exposed in the hwpath so use the xio slot num. - * i.e. for 'io2' set pcibr_debug_widget to "2". + * all modules are trace. The format is something like "001c10". + * -pcibr_debug_widget is the widget you want to trace. For TIO + * based bricks use the corelet id. * -pcibr_debug_slot is the pci slot you want to trace. */ uint32_t pcibr_debug_mask = 0x0; /* 0x00000000 to disable */ -char *pcibr_debug_module = "all"; /* 'all' for all modules */ -int pcibr_debug_widget = -1; /* '-1' for all widgets */ -int pcibr_debug_slot = -1; /* '-1' for all slots */ - -/* - * Macros related to the Lucent USS 302/312 usb timeout workaround. It - * appears that if the lucent part can get into a retry loop if it sees a - * DAC on the bus during a pio read retry. The loop is broken after about - * 1ms, so we need to set up bridges holding this part to allow at least - * 1ms for pio. - */ - -#define USS302_TIMEOUT_WAR - -#ifdef USS302_TIMEOUT_WAR -#define LUCENT_USBHC_VENDOR_ID_NUM 0x11c1 -#define LUCENT_USBHC302_DEVICE_ID_NUM 0x5801 -#define LUCENT_USBHC312_DEVICE_ID_NUM 0x5802 -#define USS302_BRIDGE_TIMEOUT_HLD 4 -#endif +static char *pcibr_debug_module = "all"; /* 'all' for all modules */ +static int pcibr_debug_widget = -1; /* '-1' for all widgets */ +static int pcibr_debug_slot = -1; /* '-1' for all slots */ /* kbrick widgetnum-to-bus layout */ int p_busnum[MAX_PORT_NUM] = { /* widget# */ @@ -82,6 +47,24 @@ int p_busnum[MAX_PORT_NUM] = { 3, /* 0xf */ }; +char *pci_space[] = {"NONE", + "ROM", + "IO", + "", + "MEM", + "MEM32", + "MEM64", + "CFG", + "WIN0", + "WIN1", + "WIN2", + "WIN3", + "WIN4", + "WIN5", + "", + "BAD"}; + + #if PCIBR_SOFT_LIST pcibr_list_p pcibr_list = 0; #endif @@ -289,12 +272,10 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ bridgereg_t xmask; xmask = mask; - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - if (mask == BRIDGE_DEV_PMU_BITS) - xmask = XBRIDGE_DEV_PMU_BITS; - if (mask == BRIDGE_DEV_D64_BITS) - xmask = XBRIDGE_DEV_D64_BITS; - } + if (mask == BRIDGE_DEV_PMU_BITS) + xmask = XBRIDGE_DEV_PMU_BITS; + if (mask == BRIDGE_DEV_D64_BITS) + xmask = XBRIDGE_DEV_D64_BITS; slotp = &pcibr_soft->bs_slot[slot]; @@ -376,11 +357,9 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ new &= ~BRIDGE_DEV_WRGA_BITS; if (flags & PCIIO_BYTE_STREAM) - new |= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ? - BRIDGE_DEV_SWAP_DIR : BRIDGE_DEV_SWAP_BITS; + new |= BRIDGE_DEV_SWAP_DIR; if (flags & PCIIO_WORD_VALUES) - new &= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ? - ~BRIDGE_DEV_SWAP_DIR : ~BRIDGE_DEV_SWAP_BITS; + new &= ~BRIDGE_DEV_SWAP_DIR; /* Provider-specific flags */ @@ -410,7 +389,7 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ * device. The bit is only intended for 64-bit devices and, on * PIC, can cause problems for 32-bit devices. */ - if (IS_PIC_SOFT(pcibr_soft) && mask == BRIDGE_DEV_D64_BITS && + if (mask == BRIDGE_DEV_D64_BITS && PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) { if (flags & PCIBR_VCHAN1) { new |= BRIDGE_DEV_VIRTUAL_EN; @@ -418,6 +397,11 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ } } + /* PIC BRINGUP WAR (PV# 878674): Don't allow 64bit PIO accesses */ + if (IS_PIC_SOFT(pcibr_soft) && (flags & PCIBR_64BIT) && + PCIBR_WAR_ENABLED(PV878674, pcibr_soft)) { + new &= ~(1ull << 22); + } chg = old ^ new; /* what are we changing, */ chg &= xmask; /* of the interesting bits */ @@ -425,13 +409,8 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ if (chg) { badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0; - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0; - badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0; - } else { - badpmu = slotp->bss_pmu_uctr ? (BRIDGE_DEV_PMU_BITS & chg) : 0; - badd64 = slotp->bss_d64_uctr ? (BRIDGE_DEV_D64_BITS & chg) : 0; - } + badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0; + badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0; bad = badpmu | badd32 | badd64; if (bad) { @@ -473,6 +452,8 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ */ if (bad) { pcibr_unlock(pcibr_soft, s); + PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl, + "pcibr_try_set_device: mod blocked by 0x%x\n", bad)); return bad; } } @@ -495,25 +476,13 @@ pcibr_try_set_device(pcibr_soft_t pcibr_ pcibr_unlock(pcibr_soft, s); return 0; } - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_device[slot].reg = new; - slotp->bss_device = new; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_device[slot].reg)) = __swab32(new); - slotp->bss_device = new; - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */ - } else { - bridge->b_device[slot].reg = new; - slotp->bss_device = new; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - } + bridge->b_device[slot].reg = new; + slotp->bss_device = new; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ pcibr_unlock(pcibr_soft, s); - printk("pcibr_try_set_device: Device(%d): %x\n", slot, new); + PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl, + "pcibr_try_set_device: Device(%d): 0x%x\n", slot, new)); return 0; } @@ -548,22 +517,13 @@ pcibr_device_write_gather_flush(pcibr_so { bridge_t *bridge; unsigned long s; - volatile uint32_t wrf; + volatile uint32_t wrf; s = pcibr_lock(pcibr_soft); bridge = pcibr_soft->bs_base; - - if ( IS_PIC_SOFT(pcibr_soft) ) { - wrf = bridge->b_wr_req_buf[slot].reg; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - wrf = BRIDGE_REG_GET32((&bridge->b_wr_req_buf[slot].reg)); - } else { - wrf = bridge->b_wr_req_buf[slot].reg; - } - } + + wrf = bridge->b_wr_req_buf[slot].reg; pcibr_unlock(pcibr_soft, s); -} +} /* ===================================================================== * Bridge (pcibr) "Device Driver" entry points @@ -662,7 +622,12 @@ pcibr_device_info_new( * passed into us, into its external representation. See comment * for the PCIBR_DEVICE_TO_SLOT macro for more information. */ - NEW(pcibr_info); + pcibr_info = kmalloc(sizeof (*(pcibr_info)), GFP_KERNEL); + if ( !pcibr_info ) { + return NULL; + } + memset(pcibr_info, 0, sizeof (*(pcibr_info))); + pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl, PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), rfunc, vendor, device); @@ -720,7 +685,7 @@ pcibr_device_unregister(vertex_hdl_t pco pcibr_soft_t pcibr_soft; bridge_t *bridge; int count_vchan0, count_vchan1; - unsigned s; + unsigned long s; int error_call; int error = 0; @@ -746,9 +711,6 @@ pcibr_device_unregister(vertex_hdl_t pco s = pcibr_lock(pcibr_soft); - /* PIC NOTE: If this is a BRIDGE, VCHAN2 & VCHAN3 will be zero so - * no need to conditionalize this (ie. "if (IS_PIC_SOFT())" ). - */ pcibr_soft->bs_rrb_res[slot] = pcibr_soft->bs_rrb_res[slot] + pcibr_soft->bs_rrb_valid[slot][VCHAN0] + pcibr_soft->bs_rrb_valid[slot][VCHAN1] + @@ -983,18 +945,15 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b char devnm[MAXDEVNAME], *s; pcibr_hints_t pcibr_hints; uint64_t int_enable; - bridgereg_t int_enable_32; picreg_t int_enable_64; unsigned rrb_fixed = 0; - int spl_level; - #if PCI_FBBE int fast_back_to_back_enable; #endif nasid_t nasid; int iobrick_type_get_nasid(nasid_t nasid); - int iobrick_module_get_nasid(nasid_t nasid); + int iomoduleid_get(nasid_t nasid); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum)); @@ -1025,10 +984,13 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * allocate soft state structure, fill in some * fields, and hook it up to our vertex. */ - NEW(pcibr_soft); + pcibr_soft = kmalloc(sizeof(*(pcibr_soft)), GFP_KERNEL); if (ret_softp) *ret_softp = pcibr_soft; - BZERO(pcibr_soft, sizeof *pcibr_soft); + if (!pcibr_soft) + return -1; + + memset(pcibr_soft, 0, sizeof *pcibr_soft); pcibr_soft_set(pcibr_vhdl, pcibr_soft); pcibr_soft->bs_conn = xconn_vhdl; pcibr_soft->bs_vhdl = pcibr_vhdl; @@ -1094,7 +1056,10 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b { pcibr_list_p self; - NEW(self); + self = kmalloc(sizeof(*(self)), GFP_KERNEL); + if (!self) + return -1; + memset(self, 0, sizeof(*(self))); self->bl_soft = pcibr_soft; self->bl_vhdl = pcibr_vhdl; self->bl_next = pcibr_list; @@ -1112,8 +1077,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl, "pcibr_attach2: %s ASIC: rev %s (code=0x%x)\n", - IS_XBRIDGE_SOFT(pcibr_soft) ? "XBridge" : - IS_PIC_SOFT(pcibr_soft) ? "PIC" : "Bridge", + "PIC", (rev == BRIDGE_PART_REV_A) ? "A" : (rev == BRIDGE_PART_REV_B) ? "B" : (rev == BRIDGE_PART_REV_C) ? "C" : @@ -1143,7 +1107,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b printk(KERN_WARNING "0x%p: Unknown bricktype : 0x%x\n", (void *)xconn_vhdl, (unsigned int)pcibr_soft->bs_bricktype); - pcibr_soft->bs_moduleid = iobrick_module_get_nasid(nasid); + pcibr_soft->bs_moduleid = iomoduleid_get(nasid); if (pcibr_soft->bs_bricktype > 0) { switch (pcibr_soft->bs_bricktype) { @@ -1268,12 +1232,8 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * is a wrapper routine we register that will call the real error handler * pcibr_error_handler() with the correct pcibr_soft struct. */ - if (IS_PIC_SOFT(pcibr_soft)) { - if (busnum == 0) { - xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft); - } - } else { - xwidget_error_register(xconn_vhdl, pcibr_error_handler, pcibr_soft); + if (busnum == 0) { + xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft); } /* @@ -1293,7 +1253,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); /* Initialize some PIC specific registers. */ - if (IS_PIC_SOFT(pcibr_soft)) { + { picreg_t pic_ctrl_reg = bridge->p_wid_control_64; /* Bridges Requester ID: bus = busnum, dev = 0, func = 0 */ @@ -1317,19 +1277,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b bridge->p_wid_control_64 = pic_ctrl_reg; } - - /* - * Until otherwise set up, - * assume all interrupts are - * from slot 7(Bridge/Xbridge) or 3(PIC). - * XXX. Not sure why we're doing this, made change for PIC - * just to avoid setting reserved bits. - */ - if (IS_PIC_SOFT(pcibr_soft)) - bridge->b_int_device = (uint32_t) 0x006db6db; - else - bridge->b_int_device = (uint32_t) 0xffffffff; - + bridge->b_int_device = (uint32_t) 0x006db6db; { bridgereg_t dirmap; paddr_t paddr; @@ -1367,7 +1315,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * for the lowest hunk of memory. */ xbase = xtalk_dmatrans_addr(xconn_vhdl, 0, - paddr, _PAGESZ, 0); + paddr, PAGE_SIZE, 0); if (xbase != XIO_NOWHERE) { if (XIO_PACKED(xbase)) { @@ -1397,24 +1345,14 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * ensure that we write and read without any interruption. * The read following the write is required for the Bridge war */ - spl_level = splhi(); #if IOPGSIZE == 4096 - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE; - } else { - bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE; - } + bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE; #elif IOPGSIZE == 16384 - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE; - } else { - bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE; - } + bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE; #else <<>>; #endif bridge->b_wid_control; /* inval addr bug war */ - splx(spl_level); /* Initialize internal mapping entries */ for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++) { @@ -1441,10 +1379,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * time. */ - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) - num_entries = 0; - else - num_entries = pcibr_init_ext_ate_ram(bridge); + num_entries = 0; /* we always have 128 ATEs (512 for Xbridge) inside the chip * even if disabled for debugging. @@ -1552,24 +1487,8 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * enable all of them. * NOTE: some PCI ints may already be enabled. */ - /* We read the INT_ENABLE register as a 64bit picreg_t for PIC and a - * 32bit bridgereg_t for BRIDGE, but always process the result as a - * 64bit value so the code can be "common" for both PIC and BRIDGE... - */ - if (IS_PIC_SOFT(pcibr_soft)) { - int_enable_64 = bridge->p_int_enable_64 | BRIDGE_ISR_ERRORS; - int_enable = (uint64_t)int_enable_64; -#ifdef PFG_TEST - int_enable = (uint64_t)0x7ffffeff7ffffeff; -#endif - } else { - int_enable_32 = bridge->b_int_enable | (BRIDGE_ISR_ERRORS & 0xffffffff); - int_enable = ((uint64_t)int_enable_32 & 0xffffffff); -#ifdef PFG_TEST - int_enable = (uint64_t)0x7ffffeff; -#endif - } - + int_enable_64 = bridge->p_int_enable_64 | BRIDGE_ISR_ERRORS; + int_enable = (uint64_t)int_enable_64; #if BRIDGE_ERROR_INTR_WAR if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) { @@ -1609,7 +1528,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * locked out to be freed up sooner (by timing out) so that the * read tnums are never completely used up. */ - if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) { int_enable &= ~PIC_ISR_PCIX_REQ_TOUT; int_enable &= ~BRIDGE_ISR_XREAD_REQ_TIMEOUT; @@ -1621,16 +1540,12 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b * RRB0, RRB8, RRB1, and RRB9. Assign them to DEVICE[2|3]--VCHAN3 * so they are not used */ - if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) { bridge->b_even_resp |= 0x000f000f; bridge->b_odd_resp |= 0x000f000f; } - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_int_enable_64 = (picreg_t)int_enable; - } else { - bridge->b_int_enable = (bridgereg_t)int_enable; - } + bridge->p_int_enable_64 = (picreg_t)int_enable; bridge->b_int_mode = 0; /* do not send "clear interrupt" packets */ bridge->b_wid_tflush; /* wait until Bridge PIO complete */ @@ -1690,7 +1605,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b /* Setup the Bus's PCI IO Root Resource. */ pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE; pcibr_soft->bs_io_win_root_resource.end = 0xffffffff; - res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); + res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL); if (!res) panic("PCIBR:Unable to allocate resource structure\n"); @@ -1702,13 +1617,13 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b panic("PCIBR:Unable to request_resource()\n"); /* Setup the Small Window Root Resource */ - pcibr_soft->bs_swin_root_resource.start = _PAGESZ; + pcibr_soft->bs_swin_root_resource.start = PAGE_SIZE; pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF; /* Setup the Bus's PCI Memory Root Resource */ pcibr_soft->bs_mem_win_root_resource.start = 0x200000; pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff; - res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); + res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL); if (!res) panic("PCIBR:Unable to allocate resource structure\n"); @@ -1776,8 +1691,7 @@ pcibr_attach2(vertex_hdl_t xconn_vhdl, b } /* Set up convenience links */ - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) - pcibr_bus_cnvlink(pcibr_soft->bs_vhdl); + pcibr_bus_cnvlink(pcibr_soft->bs_vhdl); for (slot = pcibr_soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) @@ -1881,11 +1795,7 @@ pcibr_detach(vertex_hdl_t xconn) s = pcibr_lock(pcibr_soft); /* Disable the interrupts from the bridge */ - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_int_enable_64 = 0; - } else { - bridge->b_int_enable = 0; - } + bridge->p_int_enable_64 = 0; pcibr_unlock(pcibr_soft, s); /* Detach all the PCI devices talking to this bridge */ @@ -1898,7 +1808,6 @@ pcibr_detach(vertex_hdl_t xconn) pciio_device_info_unregister(pcibr_vhdl, &(pcibr_soft->bs_noslot_info->f_c)); - spin_lock_destroy(&pcibr_soft->bs_lock); kfree(pcibr_soft->bs_name); /* Disconnect the error interrupt and free the xtalk resources @@ -1910,13 +1819,14 @@ pcibr_detach(vertex_hdl_t xconn) /* Clear the software state maintained by the bridge driver for this * bridge. */ - DEL(pcibr_soft); + kfree(pcibr_soft); + /* Remove the Bridge revision labelled info */ (void)hwgraph_info_remove_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, NULL); /* Remove the character device associated with this bridge */ - (void)hwgraph_edge_remove(pcibr_vhdl, EDGE_LBL_CONTROLLER, NULL); + hwgraph_edge_remove(pcibr_vhdl, EDGE_LBL_CONTROLLER, NULL); /* Remove the PCI bridge vertex */ - (void)hwgraph_edge_remove(xconn, EDGE_LBL_PCI, NULL); + hwgraph_edge_remove(xconn, EDGE_LBL_PCI, NULL); return(0); } @@ -1994,7 +1904,6 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn iopaddr_t mbase; /* base of devio(x) mapped area on PCI */ size_t msize; /* size of devio(x) mapped area on PCI */ size_t mmask; /* addr bits stored in Device(x) */ - char tmp_str[512]; unsigned long s; @@ -2171,27 +2080,13 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn devreg &= ~BRIDGE_DEV_DEV_SWAP; if (pcibr_soft->bs_slot[win].bss_device != devreg) { - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_device[win].reg = devreg; - pcibr_soft->bs_slot[win].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_device[win].reg)) = __swab32(devreg); - pcibr_soft->bs_slot[win].bss_device = devreg; - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */ - } else { - bridge->b_device[win].reg = devreg; - pcibr_soft->bs_slot[win].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - } - + bridge->b_device[win].reg = devreg; + pcibr_soft->bs_slot[win].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ #ifdef PCI_LATER PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pconn_vhdl, - "pcibr_addr_pci_to_xio: Device(%d): %x\n", - win, devreg, device_bits)); + "pcibr_addr_pci_to_xio: Device(%d): 0x%x\n", + win, devreg)); #endif } pcibr_soft->bs_slot[win].bss_devio.bssd_space = space; @@ -2205,18 +2100,12 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn if (bar != -1) pcibr_info->f_window[bar].w_devio_index = win; - /* - * The kernel only allows functions to have so many variable args, - * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printk - * arguments fails so sprintf() it into a temporary string. - */ - if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) { - sprintf(tmp_str, "pcibr_addr_pci_to_xio: map to [%lx..%lx] for " - "slot %d allocates DevIO(%d) Device(%d) set to %lx\n", - (unsigned long)pci_addr, (unsigned long)(pci_addr + req_size - 1), - (unsigned int)slot, win, win, (unsigned long)devreg); - PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str)); - } + PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_addr_pci_to_xio: map to space %s [0x%lx..0x%lx] " + "for slot %d allocates DevIO(%d) Device(%d) set to %lx\n", + pci_space[space], pci_addr, pci_addr + req_size - 1, + slot, win, win, devreg)); + goto done; } /* endif DevIO(x) not pointed */ mbase = pcibr_soft->bs_slot[win].bss_devio.bssd_base; @@ -2244,9 +2133,10 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn if (bar != -1) pcibr_info->f_window[bar].w_devio_index = win; - if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) { - PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str)); - } + PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_addr_pci_to_xio: map to space %s [0x%lx..0x%lx] " + "for slot %d uses DevIO(%d)\n", pci_space[space], + pci_addr, pci_addr + req_size - 1, slot, win)); goto done; } @@ -2271,9 +2161,9 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn } else if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 1)) { /* PIC bus 1 */ base = PICBRIDGE1_PCI_MEM32_BASE; limit = PICBRIDGE1_PCI_MEM32_LIMIT; - } else { /* Bridge/Xbridge */ - base = BRIDGE_PCI_MEM32_BASE; - limit = BRIDGE_PCI_MEM32_LIMIT; + } else { + printk("pcibr_addr_pci_to_xio(): unknown bridge type"); + return (iopaddr_t)0; } if ((pci_addr + base + req_size - 1) <= limit) @@ -2287,9 +2177,9 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn } else if (IS_PIC_BUSNUM_SOFT(pcibr_soft, 1)) { /* PIC bus 1 */ base = PICBRIDGE1_PCI_MEM64_BASE; limit = PICBRIDGE1_PCI_MEM64_LIMIT; - } else { /* Bridge/Xbridge */ - base = BRIDGE_PCI_MEM64_BASE; - limit = BRIDGE_PCI_MEM64_LIMIT; + } else { + printk("pcibr_addr_pci_to_xio(): unknown bridge type"); + return (iopaddr_t)0; } if ((pci_addr + base + req_size - 1) <= limit) @@ -2300,20 +2190,7 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn /* * PIC bridges do not support big-window aliases into PCI I/O space */ - if (IS_PIC_SOFT(pcibr_soft)) { - xio_addr = XIO_NOWHERE; - break; - } - - /* Bridge Hardware Bug WAR #482741: - * The 4G area that maps directly from - * XIO space to PCI I/O space is busted - * until Bridge Rev D. - */ - if ((pcibr_soft->bs_rev_num > BRIDGE_PART_REV_C) && - ((pci_addr + BRIDGE_PCI_IO_BASE + req_size - 1) <= - BRIDGE_PCI_IO_LIMIT)) - xio_addr = pci_addr + BRIDGE_PCI_IO_BASE; + xio_addr = XIO_NOWHERE; break; } @@ -2340,41 +2217,29 @@ pcibr_addr_pci_to_xio(vertex_hdl_t pconn if (bfn == bfo) { /* we already match. */ ; } else if (bfo != 0) { /* we have a conflict. */ - if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) { - PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str)); - } + PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_addr_pci_to_xio: swap conflict in %s, " + "was%s%s, want%s%s\n", pci_space[space], + bfo & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfo & PCIIO_WORD_VALUES ? " WORD_VALUES" : "", + bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "")); xio_addr = XIO_NOWHERE; } else { /* OK to make the change. */ + picreg_t octl, nctl; swb = (space == PCIIO_SPACE_IO) ? BRIDGE_CTRL_IO_SWAP : BRIDGE_CTRL_MEM_SWAP; - if ( IS_PIC_SOFT(pcibr_soft) ) { - picreg_t octl, nctl; - octl = bridge->p_wid_control_64; - nctl = bst ? octl | (uint64_t)swb : octl & ((uint64_t)~swb); + octl = bridge->p_wid_control_64; + nctl = bst ? octl | (uint64_t)swb : octl & ((uint64_t)~swb); - if (octl != nctl) /* make the change if any */ - bridge->b_wid_control = nctl; - } - else { - picreg_t octl, nctl; - if (io_get_sh_swapper(NASID_GET(bridge))) { - octl = BRIDGE_REG_GET32((&bridge->b_wid_control)); - nctl = bst ? octl | swb : octl & ~swb; - - if (octl != nctl) /* make the change if any */ - BRIDGE_REG_SET32((&bridge->b_wid_control)) = __swab32(nctl); - } else { - octl = bridge->b_wid_control; - nctl = bst ? octl | swb : octl & ~swb; - - if (octl != nctl) /* make the change if any */ - bridge->b_wid_control = nctl; - } - } + if (octl != nctl) /* make the change if any */ + bridge->b_wid_control = nctl; *bfp = bfn; /* record the assignment */ - if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) { - PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str)); - } + PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_addr_pci_to_xio: swap for %s set to%s%s\n", + pci_space[space], + bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "", + bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "")); } } done: @@ -2443,7 +2308,13 @@ pcibr_piomap_alloc(vertex_hdl_t pconn_vh mapptr = NULL; else { pcibr_unlock(pcibr_soft, s); - NEW(pcibr_piomap); + pcibr_piomap = kmalloc(sizeof (*(pcibr_piomap)), GFP_KERNEL); + if ( !pcibr_piomap ) { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_piomap_alloc: malloc fails\n")); + return NULL; + } + memset(pcibr_piomap, 0, sizeof (*(pcibr_piomap))); } pcibr_piomap->bp_dev = pconn_vhdl; @@ -2480,7 +2351,7 @@ pcibr_piomap_alloc(vertex_hdl_t pconn_vh } PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, - "pcibr_piomap_alloc: map=0x%x\n", pcibr_piomap)); + "pcibr_piomap_alloc: map=0x%lx\n", pcibr_piomap)); return pcibr_piomap; } @@ -2490,7 +2361,7 @@ void pcibr_piomap_free(pcibr_piomap_t pcibr_piomap) { PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev, - "pcibr_piomap_free: map=0x%x\n", pcibr_piomap)); + "pcibr_piomap_free: map=0x%lx\n", pcibr_piomap)); xtalk_piomap_free(pcibr_piomap->bp_xtalk_pio); pcibr_piomap->bp_xtalk_pio = 0; @@ -2509,7 +2380,7 @@ pcibr_piomap_addr(pcibr_piomap_t pcibr_p pci_addr - pcibr_piomap->bp_pciaddr, req_size); PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev, - "pcibr_piomap_free: map=0x%x, addr=0x%x\n", + "pcibr_piomap_addr: map=0x%lx, addr=0x%lx\n", pcibr_piomap, addr)); return(addr); @@ -2520,7 +2391,7 @@ void pcibr_piomap_done(pcibr_piomap_t pcibr_piomap) { PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev, - "pcibr_piomap_done: map=0x%x\n", pcibr_piomap)); + "pcibr_piomap_done: map=0x%lx\n", pcibr_piomap)); xtalk_piomap_done(pcibr_piomap->bp_xtalk_pio); } @@ -2551,7 +2422,7 @@ pcibr_piotrans_addr(vertex_hdl_t pconn_v addr = xtalk_piotrans_addr(xconn_vhdl, 0, xio_addr, req_size, flags & PIOMAP_FLAGS); PCIBR_DEBUG((PCIBR_DEBUG_PIODIR, pconn_vhdl, - "pcibr_piotrans_addr: xio_addr=0x%x, addr=0x%x\n", + "pcibr_piotrans_addr: xio_addr=0x%lx, addr=0x%lx\n", xio_addr, addr)); return(addr); } @@ -2586,7 +2457,7 @@ pcibr_piospace_alloc(vertex_hdl_t pconn_ /* * Check for proper alignment */ - ASSERT(alignment >= NBPP); + ASSERT(alignment >= PAGE_SIZE); ASSERT((alignment & (alignment - 1)) == 0); align_mask = alignment - 1; @@ -2595,7 +2466,8 @@ pcibr_piospace_alloc(vertex_hdl_t pconn_ /* * First look if a previously allocated chunk exists. */ - if ((piosp = pcibr_info->f_piospace)) { + piosp = pcibr_info->f_piospace; + if (piosp) { /* * Look through the list for a right sized free chunk. */ @@ -2647,11 +2519,18 @@ pcibr_piospace_alloc(vertex_hdl_t pconn_ if (!start_addr) { pcibr_unlock(pcibr_soft, s); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl, - "pcibr_piospace_alloc: request 0x%x to big\n", req_size)); + "pcibr_piospace_alloc: request 0x%lx to big\n", req_size)); return 0; } - NEW(piosp); + piosp = kmalloc(sizeof (*(piosp)), GFP_KERNEL); + if ( !piosp ) { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl, + "pcibr_piospace_alloc: malloc fails\n")); + return 0; + } + memset(piosp, 0, sizeof (*(piosp))); + piosp->free = 0; piosp->space = space; piosp->start = start_addr; @@ -2662,7 +2541,7 @@ pcibr_piospace_alloc(vertex_hdl_t pconn_ pcibr_unlock(pcibr_soft, s); PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, - "pcibr_piospace_alloc: piosp=0x%x\n", piosp)); + "pcibr_piospace_alloc: piosp=0x%lx\n", piosp)); return start_addr; } @@ -2675,6 +2554,7 @@ pcibr_piospace_free(vertex_hdl_t pconn_v size_t req_size) { pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl); + pcibr_soft_t pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast; pciio_piospace_t piosp; unsigned long s; char name[1024]; @@ -2718,7 +2598,7 @@ pcibr_piospace_free(vertex_hdl_t pconn_v pcibr_unlock(pcibr_soft, s); PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, - "pcibr_piospace_free: piosp=0x%x\n", piosp)); + "pcibr_piospace_free: piosp=0x%lx\n", piosp)); return; } @@ -2777,12 +2657,10 @@ pcibr_flags_to_d64(unsigned flags, pcibr attributes &= ~PCI64_ATTR_PREF; /* the swap bit is in the address attributes for xbridge */ - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - if (flags & PCIIO_BYTE_STREAM) - attributes |= PCI64_ATTR_SWAP; - if (flags & PCIIO_WORD_VALUES) - attributes &= ~PCI64_ATTR_SWAP; - } + if (flags & PCIIO_BYTE_STREAM) + attributes |= PCI64_ATTR_SWAP; + if (flags & PCIIO_WORD_VALUES) + attributes &= ~PCI64_ATTR_SWAP; /* Provider-specific flags */ @@ -2832,6 +2710,7 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh int ate_count; int ate_index; int vchan = VCHAN0; + unsigned long s; /* merge in forced flags */ flags |= pcibr_soft->bs_dma_flags; @@ -2840,7 +2719,9 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh * On SNIA64, these maps are pre-allocated because pcibr_dmamap_alloc() * can be called within an interrupt thread. */ + s = pcibr_lock(pcibr_soft); pcibr_dmamap = (pcibr_dmamap_t)get_free_pciio_dmamap(pcibr_soft->bs_vhdl); + pcibr_unlock(pcibr_soft, s); if (!pcibr_dmamap) return 0; @@ -2899,16 +2780,19 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh } } PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmamap_alloc: using direct64, map=0x%x\n", + "pcibr_dmamap_alloc: using direct64, map=0x%lx\n", pcibr_dmamap)); return pcibr_dmamap; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl, "pcibr_dmamap_alloc: unable to use direct64\n")); - /* PIC only supports 64-bit direct mapping in PCI-X mode. */ + /* PIC in PCI-X mode only supports 64-bit direct mapping so + * don't fall thru and try 32-bit direct mapping or 32-bit + * page mapping + */ if (IS_PCIX(pcibr_soft)) { - DEL(pcibr_dmamap); + kfree(pcibr_dmamap); return 0; } @@ -2927,7 +2811,7 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh * is outside the direct32 range. */ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmamap_alloc: using direct32, map=0x%x\n", + "pcibr_dmamap_alloc: using direct32, map=0x%lx\n", pcibr_dmamap)); pcibr_dmamap->bd_flags = flags; pcibr_dmamap->bd_xio_addr = pcibr_soft->bs_dir_xbase; @@ -2971,29 +2855,25 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pconn_vhdl, "pcibr_dmamap_alloc: using PMU, ate_index=%d, " - "pcibr_dmamap=0x%x\n", ate_index, pcibr_dmamap)); + "pcibr_dmamap=0x%lx\n", ate_index, pcibr_dmamap)); ate_proto = pcibr_flags_to_ate(flags); pcibr_dmamap->bd_flags = flags; pcibr_dmamap->bd_pci_addr = PCI32_MAPPED_BASE + IOPGSIZE * ate_index; + + if (flags & PCIIO_BYTE_STREAM) + ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); /* - * for xbridge the byte-swap bit == bit 29 of PCI address + * If swap was set in bss_device in pcibr_endian_set() + * we need to change the address bit. */ - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - if (flags & PCIIO_BYTE_STREAM) - ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); - /* - * If swap was set in bss_device in pcibr_endian_set() - * we need to change the address bit. - */ - if (pcibr_soft->bs_slot[slot].bss_device & - BRIDGE_DEV_SWAP_PMU) - ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); - if (flags & PCIIO_WORD_VALUES) - ATE_SWAP_OFF(pcibr_dmamap->bd_pci_addr); - } + if (pcibr_soft->bs_slot[slot].bss_device & + BRIDGE_DEV_SWAP_PMU) + ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr); + if (flags & PCIIO_WORD_VALUES) + ATE_SWAP_OFF(pcibr_dmamap->bd_pci_addr); pcibr_dmamap->bd_xio_addr = 0; pcibr_dmamap->bd_ate_ptr = pcibr_ate_addr(pcibr_soft, ate_index); pcibr_dmamap->bd_ate_index = ate_index; @@ -3014,32 +2894,6 @@ pcibr_dmamap_alloc(vertex_hdl_t pconn_vh min_rrbs - have_rrbs); } } - if (ate_index >= pcibr_soft->bs_int_ate_size && - !IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - bridge_t *bridge = pcibr_soft->bs_base; - volatile unsigned *cmd_regp; - unsigned cmd_reg; - unsigned long s; - - pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM; - - s = pcibr_lock(pcibr_soft); - cmd_regp = pcibr_slot_config_addr(bridge, slot, - PCI_CFG_COMMAND/4); - if ( IS_PIC_SOFT(pcibr_soft) ) { - cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4); - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&cmd_reg)) = __swab32(*cmd_regp); - } else { - cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4); - } - } - pcibr_soft->bs_slot[slot].bss_cmd_pointer = cmd_regp; - pcibr_soft->bs_slot[slot].bss_cmd_shadow = cmd_reg; - pcibr_unlock(pcibr_soft, s); - } return pcibr_dmamap; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pconn_vhdl, @@ -3089,7 +2943,7 @@ pcibr_dmamap_free(pcibr_dmamap_t pcibr_d } PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_free: pcibr_dmamap=0x%x\n", pcibr_dmamap)); + "pcibr_dmamap_free: pcibr_dmamap=0x%lx\n", pcibr_dmamap)); free_pciio_dmamap(pcibr_dmamap); } @@ -3132,16 +2986,8 @@ pcibr_addr_xio_to_pci(pcibr_soft_t soft, return pci_addr; } } else { - if ((xio_addr >= BRIDGE_PCI_MEM32_BASE) && - (xio_lim <= BRIDGE_PCI_MEM32_LIMIT)) { - pci_addr = xio_addr - BRIDGE_PCI_MEM32_BASE; - return pci_addr; - } - if ((xio_addr >= BRIDGE_PCI_MEM64_BASE) && - (xio_lim <= BRIDGE_PCI_MEM64_LIMIT)) { - pci_addr = xio_addr - BRIDGE_PCI_MEM64_BASE; - return pci_addr; - } + printk("pcibr_addr_xio_to_pci(): unknown bridge type"); + return (iopaddr_t)0; } for (slot = soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(soft); ++slot) if ((xio_addr >= PCIBR_BRIDGE_DEVIO(soft, slot)) && @@ -3215,8 +3061,8 @@ pcibr_dmamap_addr(pcibr_dmamap_t pcibr_d PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pcibr_dmamap->bd_dev, - "pcibr_dmamap_addr: (direct64): wanted paddr [0x%x..0x%x] " - "XIO port 0x%x offset 0x%x, returning PCI 0x%x\n", + "pcibr_dmamap_addr: (direct64): wanted paddr [0x%lx..0x%lx] " + "XIO port 0x%x offset 0x%lx, returning PCI 0x%lx\n", paddr, paddr + req_size - 1, xio_port, xio_addr, pci_addr)); } else if (flags & PCIIO_FIXED) { @@ -3240,8 +3086,8 @@ pcibr_dmamap_addr(pcibr_dmamap_t pcibr_d PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pcibr_dmamap->bd_dev, - "pcibr_dmamap_addr (direct32): wanted paddr [0x%x..0x%x] " - "XIO port 0x%x offset 0x%x, returning PCI 0x%x\n", + "pcibr_dmamap_addr (direct32): wanted paddr [0x%lx..0x%lx] " + "XIO port 0x%x offset 0x%lx, returning PCI 0x%lx\n", paddr, paddr + req_size - 1, xio_port, xio_addr, pci_addr)); } else { @@ -3285,19 +3131,10 @@ pcibr_dmamap_addr(pcibr_dmamap_t pcibr_d ATE_FREEZE(); ATE_WRITE(); ATE_THAW(); - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_GET32((&bridge->b_wid_tflush)); - } else { - bridge->b_wid_tflush; - } - } + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, "pcibr_dmamap_addr (PMU) : wanted paddr " - "[0x%x..0x%x] returning PCI 0x%x\n", + "[0x%lx..0x%lx] returning PCI 0x%lx\n", paddr, paddr + req_size - 1, pci_addr)); } else { @@ -3311,7 +3148,7 @@ pcibr_dmamap_addr(pcibr_dmamap_t pcibr_d */ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, "pcibr_dmamap_addr (PMU) : wanted paddr " - "[0x%x..0x%x] ate_count 0x%x bd_ate_count 0x%x " + "[0x%lx..0x%lx] ate_count 0x%x bd_ate_count 0x%x " "ATE's required > number allocated\n", paddr, paddr + req_size - 1, ate_count, pcibr_dmamap->bd_ate_count)); @@ -3342,7 +3179,7 @@ pcibr_dmamap_done(pcibr_dmamap_t pcibr_d xtalk_dmamap_done(pcibr_dmamap->bd_xtalk); PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev, - "pcibr_dmamap_done: pcibr_dmamap=0x%x\n", pcibr_dmamap)); + "pcibr_dmamap_done: pcibr_dmamap=0x%lx\n", pcibr_dmamap)); } @@ -3393,8 +3230,8 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v flags & DMAMAP_FLAGS); if (!xio_addr) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " - "xtalk_dmatrans_addr failed with 0x%x\n", + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " + "xtalk_dmatrans_addr failed with 0x%lx\n", paddr, paddr + req_size - 1, xio_addr)); return 0; } @@ -3404,7 +3241,7 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v if (XIO_PACKED(xio_addr)) { if (xio_addr == XIO_NOWHERE) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " "xtalk_dmatrans_addr failed with XIO_NOWHERE\n", paddr, paddr + req_size - 1)); return 0; @@ -3425,8 +3262,8 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v if (xio_port == pcibr_soft->bs_xid) { pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, req_size); PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " - "xio_port=0x%x, pci_addr=0x%x\n", + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " + "xio_port=0x%x, pci_addr=0x%lx\n", paddr, paddr + req_size - 1, xio_port, pci_addr)); return pci_addr; } @@ -3480,19 +3317,16 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v min_rrbs - have_rrbs); } } -#if HWG_PERF_CHECK - if (xio_addr != 0x20000000) -#endif - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " - "xio_port=0x%x, direct64: pci_addr=0x%x, " - "new flags: 0x%x\n", paddr, paddr + req_size - 1, - xio_addr, pci_addr, (uint64_t) flags)); + PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " + "xio_port=0x%x, direct64: pci_addr=0x%lx, " + "new flags: 0x%x\n", paddr, paddr + req_size - 1, + xio_addr, pci_addr, (uint64_t) flags)); return (pci_addr); } PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " "xio_port=0x%x, Unable to set direct64 Device(x) bits\n", paddr, paddr + req_size - 1, xio_addr)); @@ -3503,6 +3337,11 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v /* our flags conflict with Device(x). try direct32*/ flags = flags & ~(PCIIO_DMA_A64 | PCIBR_VCHAN0); + } else { + /* BUS in PCI-X mode only supports 64-bit direct mapping */ + if (IS_PCIX(pcibr_soft)) { + return 0; + } } /* Try to satisfy the request with the 32-bit direct * map. This can fail if the configuration bits in @@ -3521,7 +3360,7 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v (endoff > map_size)) { PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " "xio_port=0x%x, xio region outside direct32 target\n", paddr, paddr + req_size - 1, xio_addr)); } else { @@ -3532,8 +3371,8 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v pci_addr |= offset; PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " - "xio_port=0x%x, direct32: pci_addr=0x%x\n", + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx]," + " xio_port=0x%x, direct32: pci_addr=0x%lx\n", paddr, paddr + req_size - 1, xio_addr, pci_addr)); return (pci_addr); @@ -3559,12 +3398,9 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v vchan, min_rrbs - have_rrbs); } } -#if HWG_PERF_CHECK - if (xio_addr != 0x20000000) -#endif - PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " - "xio_port=0x%x, direct32: pci_addr=0x%x, " + PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx]," + " xio_port=0x%x, direct32: pci_addr=0x%lx, " "new flags: 0x%x\n", paddr, paddr + req_size - 1, xio_addr, pci_addr, (uint64_t) flags)); @@ -3573,14 +3409,14 @@ pcibr_dmatrans_addr(vertex_hdl_t pconn_v /* our flags conflict with Device(x). */ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " "xio_port=0x%x, Unable to set direct32 Device(x) bits\n", paddr, paddr + req_size - 1, xio_port)); } } PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl, - "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], " + "pcibr_dmatrans_addr: wanted paddr [0x%lx..0x%lx], " "xio_port=0x%x, No acceptable PCI address found\n", paddr, paddr + req_size - 1, xio_port)); @@ -3680,22 +3516,9 @@ pcibr_endian_set(vertex_hdl_t pconn_vhdl if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { bridge_t *bridge = pcibr_soft->bs_base; - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg); - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */ - } else { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - } + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } pcibr_unlock(pcibr_soft, s); @@ -3767,22 +3590,9 @@ pcibr_priority_bits_set(pcibr_soft_t pci if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { bridge_t *bridge = pcibr_soft->bs_base; - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg); - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */ - } else { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - } + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } pcibr_unlock(pcibr_soft, s); @@ -3865,25 +3675,15 @@ pcibr_device_flags_set(vertex_hdl_t pcon if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) { bridge_t *bridge = pcibr_soft->bs_base; - if ( IS_PIC_SOFT(pcibr_soft) ) { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg); - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */ - } else { - bridge->b_device[pciio_slot].reg = devreg; - pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } - } + bridge->b_device[pciio_slot].reg = devreg; + pcibr_soft->bs_slot[pciio_slot].bss_device = devreg; + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } pcibr_unlock(pcibr_soft, s); - printk("pcibr_device_flags_set: Device(%d): %x\n", pciio_slot, devreg); + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pconn_vhdl, + "pcibr_device_flags_set: Device(%d): 0x%x\n", + pciio_slot, devreg)); } return (1); } @@ -3967,25 +3767,12 @@ pciio_provider_t pcibr_provider = (pciio_priority_set_f *) pcibr_priority_set, (pciio_config_get_f *) pcibr_config_get, (pciio_config_set_f *) pcibr_config_set, - (pciio_error_devenable_f *) 0, (pciio_error_extract_f *) 0, (pciio_driver_reg_callback_f *) 0, (pciio_driver_unreg_callback_f *) 0, (pciio_device_unregister_f *) pcibr_device_unregister, - (pciio_dma_enabled_f *) pcibr_dma_enabled, }; -int -pcibr_dma_enabled(vertex_hdl_t pconn_vhdl) -{ - pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); - pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info); - - - return xtalk_dma_enabled(pcibr_soft->bs_conn); -} - - /* * pcibr_debug() is used to print pcibr debug messages to the console. A * user enables tracing by setting the following global variables: @@ -4020,23 +3807,26 @@ pcibr_debug(uint32_t type, vertex_hdl_t if (strcmp(module, pcibr_debug_module)) { /* use a copy */ (void)strcpy(copy_of_hwpath, hwpath); - cp = strstr(copy_of_hwpath, "/module/"); + cp = strstr(copy_of_hwpath, "/" EDGE_LBL_MODULE "/"); if (cp) { - cp += strlen("/module"); - module = strsep(&cp, "/"); + cp += strlen("/" EDGE_LBL_MODULE "/"); + module = strsep(&cp, "/"); } } if (pcibr_debug_widget != -1) { - cp = strstr(hwpath, "/xtalk/"); + cp = strstr(hwpath, "/" EDGE_LBL_XTALK "/"); if (cp) { - cp += strlen("/xtalk/"); + cp += strlen("/" EDGE_LBL_XTALK "/"); widget = simple_strtoul(cp, NULL, 0); } } if (pcibr_debug_slot != -1) { - cp = strstr(hwpath, "/pci/"); + cp = strstr(hwpath, "/" EDGE_LBL_PCIX_0 "/"); + if (!cp) { + cp = strstr(hwpath, "/" EDGE_LBL_PCIX_1 "/"); + } if (cp) { - cp += strlen("/pci/"); + cp += strlen("/" EDGE_LBL_PCIX_0 "/"); slot = simple_strtoul(cp, NULL, 0); } } diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_error.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_error.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,26 +7,15 @@ */ #include -#include -#include +#include #include -#include #include -#include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include -#include + extern int hubii_check_widget_disabled(nasid_t, int); @@ -43,12 +31,9 @@ extern int hubii_check_widget_disabled(n #define BRIDGE_PIOERR_TIMEOUT 40 /* Timeout in debug mode */ #endif #else -#define BRIDGE_PIOERR_TIMEOUT 1 /* Timeout in non-debug mode */ +#define BRIDGE_PIOERR_TIMEOUT 1 /* Timeout in non-debug mode */ #endif -/* PIC has 64bit interrupt error registers, but BRIDGE has 32bit registers. - * Thus 'bridge_errors_to_dump needs' to default to the larger of the two. - */ #ifdef DEBUG #ifdef ERROR_DEBUG uint64_t bridge_errors_to_dump = ~BRIDGE_ISR_INT_MSK; @@ -62,7 +47,29 @@ uint64_t bridge_errors_to_dump = BRIDGE_ int pcibr_llp_control_war_cnt; /* PCIBR_LLP_CONTROL_WAR */ -static struct reg_values xio_cmd_pactyp[] = +/* + * register values + * map between numeric values and symbolic values + */ +struct reg_values { + unsigned long long rv_value; + char *rv_name; +}; + +/* + * register descriptors are used for formatted prints of register values + * rd_mask and rd_shift must be defined, other entries may be null + */ +struct reg_desc { + unsigned long long rd_mask; /* mask to extract field */ + int rd_shift; /* shift for extracted value, - >>, + << */ + char *rd_name; /* field name */ + char *rd_format; /* format to print field */ + struct reg_values *rd_values; /* symbolic names of values */ +}; + +/* Crosstalk Packet Types */ +static struct reg_values xtalk_cmd_pactyp[] = { {0x0, "RdReq"}, {0x1, "RdResp"}, @@ -83,11 +90,11 @@ static struct reg_values xio_cmd_pactyp[ {0} }; -static struct reg_desc xio_cmd_bits[] = +static struct reg_desc xtalk_cmd_bits[] = { {WIDGET_DIDN, -28, "DIDN", "%x"}, {WIDGET_SIDN, -24, "SIDN", "%x"}, - {WIDGET_PACTYP, -20, "PACTYP", 0, xio_cmd_pactyp}, + {WIDGET_PACTYP, -20, "PACTYP", 0, xtalk_cmd_pactyp}, {WIDGET_TNUM, -15, "TNUM", "%x"}, {WIDGET_COHERENT, 0, "COHERENT"}, {WIDGET_DS, 0, "DS"}, @@ -118,46 +125,16 @@ static struct reg_values space_v[] {PCIIO_SPACE_BAD, "BAD"}, {0} }; -static struct reg_desc space_desc[] = +struct reg_desc space_desc[] = { {0xFF, 0, "space", 0, space_v}, {0} }; -#define device_desc device_bits -static struct reg_desc device_bits[] = -{ - {BRIDGE_DEV_ERR_LOCK_EN, 0, "ERR_LOCK_EN"}, - {BRIDGE_DEV_PAGE_CHK_DIS, 0, "PAGE_CHK_DIS"}, - {BRIDGE_DEV_FORCE_PCI_PAR, 0, "FORCE_PCI_PAR"}, - {BRIDGE_DEV_VIRTUAL_EN, 0, "VIRTUAL_EN"}, - {BRIDGE_DEV_PMU_WRGA_EN, 0, "PMU_WRGA_EN"}, - {BRIDGE_DEV_DIR_WRGA_EN, 0, "DIR_WRGA_EN"}, - {BRIDGE_DEV_DEV_SIZE, 0, "DEV_SIZE"}, - {BRIDGE_DEV_RT, 0, "RT"}, - {BRIDGE_DEV_SWAP_PMU, 0, "SWAP_PMU"}, - {BRIDGE_DEV_SWAP_DIR, 0, "SWAP_DIR"}, - {BRIDGE_DEV_PREF, 0, "PREF"}, - {BRIDGE_DEV_PRECISE, 0, "PRECISE"}, - {BRIDGE_DEV_COH, 0, "COH"}, - {BRIDGE_DEV_BARRIER, 0, "BARRIER"}, - {BRIDGE_DEV_GBR, 0, "GBR"}, - {BRIDGE_DEV_DEV_SWAP, 0, "DEV_SWAP"}, - {BRIDGE_DEV_DEV_IO_MEM, 0, "DEV_IO_MEM"}, - {BRIDGE_DEV_OFF_MASK, BRIDGE_DEV_OFF_ADDR_SHFT, "DEV_OFF", "%x"}, - {0} -}; - -static void -print_bridge_errcmd(uint32_t cmdword, char *errtype) -{ - printk("\t Bridge %s Error Command Word Register ", errtype); - print_register(cmdword, xio_cmd_bits); -} static char *pcibr_isr_errs[] = { "", "", "", "", "", "", "", "", - "08: GIO non-contiguous byte enable in crosstalk packet", /* BRIDGE ONLY */ + "08: Reserved Bit 08", "09: PCI to Crosstalk read request timeout", "10: PCI retry operation count exhausted.", "11: PCI bus device select timeout", @@ -165,12 +142,12 @@ static char *pcibr_isr_errs[ "13: PCI Address/Cmd parity error ", "14: PCI Bridge detected parity error", "15: PCI abort condition", - "16: SSRAM parity error", /* BRIDGE ONLY */ - "17: LLP Transmitter Retry count wrapped", - "18: LLP Transmitter side required Retry", - "19: LLP Receiver retry count wrapped", - "20: LLP Receiver check bit error", - "21: LLP Receiver sequence number error", + "16: Reserved Bit 16", + "17: LLP Transmitter Retry count wrapped", /* PIC ONLY */ + "18: LLP Transmitter side required Retry", /* PIC ONLY */ + "19: LLP Receiver retry count wrapped", /* PIC ONLY */ + "20: LLP Receiver check bit error", /* PIC ONLY */ + "21: LLP Receiver sequence number error", /* PIC ONLY */ "22: Request packet overflow", "23: Request operation not supported by bridge", "24: Request packet has invalid address for bridge widget", @@ -180,9 +157,7 @@ static char *pcibr_isr_errs[ "28: Framing error, response cmd data size does not match actual", "29: Unexpected response arrived", "30: PMU Access Fault", - "31: Multiple errors occurred", /* BRIDGE ONLY */ - - /* bits 32-45 are PIC ONLY */ + "31: Reserved Bit 31", "32: PCI-X address or attribute cycle parity error", "33: PCI-X data cycle parity error", "34: PCI-X master timeout (ie. master abort)", @@ -199,11 +174,86 @@ static char *pcibr_isr_errs[ "45: PCI-X split completion message parity error", }; -#define BEM_ADD_STR(s) printk("%s", (s)) -#define BEM_ADD_VAR(v) printk("\t%20s: 0x%llx\n", #v, ((unsigned long long)v)) -#define BEM_ADD_REG(r) printk("\t%20s: ", #r); print_register((r), r ## _desc) -#define BEM_ADD_NSPC(n,s) printk("\t%20s: ", n); print_register(s, space_desc) -#define BEM_ADD_SPC(s) BEM_ADD_NSPC(#s, s) +/* + * print_register() allows formatted printing of bit fields. individual + * bit fields are described by a struct reg_desc, multiple bit fields within + * a single word can be described by multiple reg_desc structures. + * %r outputs a string of the format "" + * %R outputs a string of the format "0x%x" + * + * The fields in a reg_desc are: + * unsigned long long rd_mask; An appropriate mask to isolate the bit field + * within a word, and'ed with val + * + * int rd_shift; A shift amount to be done to the isolated + * bit field. done before printing the isolate + * bit field with rd_format and before searching + * for symbolic value names in rd_values + * + * char *rd_name; If non-null, a bit field name to label any + * out from rd_format or searching rd_values. + * if neither rd_format or rd_values is non-null + * rd_name is printed only if the isolated + * bit field is non-null. + * + * char *rd_format; If non-null, the shifted bit field value + * is printed using this format. + * + * struct reg_values *rd_values; If non-null, a pointer to a table + * matching numeric values with symbolic names. + * rd_values are searched and the symbolic + * value is printed if a match is found, if no + * match is found "???" is printed. + * + */ + +static void +print_register(unsigned long long reg, struct reg_desc *addr) +{ + register struct reg_desc *rd; + register struct reg_values *rv; + unsigned long long field; + int any; + + printk("<"); + any = 0; + for (rd = addr; rd->rd_mask; rd++) { + field = reg & rd->rd_mask; + field = (rd->rd_shift > 0) ? field << rd->rd_shift : field >> -rd->rd_shift; + if (any && (rd->rd_format || rd->rd_values || (rd->rd_name && field))) + printk(","); + if (rd->rd_name) { + if (rd->rd_format || rd->rd_values || field) { + printk("%s", rd->rd_name); + any = 1; + } + if (rd->rd_format || rd->rd_values) { + printk("="); + any = 1; + } + } + /* You can have any format so long as it is %x */ + if (rd->rd_format) { + printk("%llx", field); + any = 1; + if (rd->rd_values) + printk(":"); + } + if (rd->rd_values) { + any = 1; + for (rv = rd->rd_values; rv->rv_name; rv++) { + if (field == rv->rv_value) { + printk("%s", rv->rv_name); + break; + } + } + if (rv->rv_name == NULL) + printk("???"); + } + } + printk(">\n"); +} + /* * display memory directory state @@ -225,6 +275,13 @@ pcibr_show_dir_state(paddr_t paddr, char #endif } +static void +print_bridge_errcmd(uint32_t cmdword, char *errtype) +{ + printk("\t Bridge %s Error Command Word Register ", errtype); + print_register(cmdword, xtalk_cmd_bits); +} + /* * Dump relevant error information for Bridge error interrupts. @@ -235,10 +292,8 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft { bridge_t *bridge = pcibr_soft->bs_base; uint64_t int_status; - bridgereg_t int_status_32; picreg_t int_status_64; uint64_t mult_int; - bridgereg_t mult_int_32; picreg_t mult_int_64; uint64_t bit; int number_bits; @@ -246,19 +301,9 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft char *reg_desc; paddr_t addr = (paddr_t)0; - /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a - * 32bit bridgereg_t for BRIDGE, but always process the result as a - * 64bit value so the code can be "common" for both PIC and BRIDGE... - */ - if (IS_PIC_SOFT(pcibr_soft)) { - int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); - int_status = (uint64_t)int_status_64; - number_bits = PCIBR_ISR_MAX_ERRS_PIC; - } else { - int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK); - int_status = ((uint64_t)int_status_32) & 0xffffffff; - number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE; - } + int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); + int_status = (uint64_t)int_status_64; + number_bits = PCIBR_ISR_MAX_ERRS_PIC; if (!int_status) { /* No error bits set */ @@ -273,8 +318,7 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft printk(KERN_ALERT "PCI BRIDGE ERROR: int_status is 0x%lx for %s\n" " Dumping relevant %s registers for each bit set...\n", int_status, pcibr_soft->bs_name, - (IS_PIC_SOFT(pcibr_soft) ? "PIC" : - (IS_BRIDGE_SOFT(pcibr_soft) ? "BRIDGE" : "XBRIDGE"))); + "PIC"); for (i = PCIBR_ISR_ERR_START; i < number_bits; i++) { bit = 1ull << i; @@ -283,15 +327,14 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft * A number of int_status bits are only defined for Bridge. * Ignore them in the case of an XBridge or PIC. */ - if ((IS_XBRIDGE_SOFT(pcibr_soft) || IS_PIC_SOFT(pcibr_soft)) && - ((bit == BRIDGE_ISR_MULTI_ERR) || + if (((bit == BRIDGE_ISR_MULTI_ERR) || (bit == BRIDGE_ISR_SSRAM_PERR) || (bit == BRIDGE_ISR_GIO_B_ENBL_ERR))) { continue; } /* A number of int_status bits are only valid for PIC's bus0 */ - if ((IS_PIC_SOFT(pcibr_soft) && (pcibr_soft->bs_busnum != 0)) && + if (((pcibr_soft->bs_busnum != 0)) && ((bit == BRIDGE_ISR_UNSUPPORTED_XOP) || (bit == BRIDGE_ISR_LLP_REC_SNERR) || (bit == BRIDGE_ISR_LLP_REC_CBERR) || @@ -314,7 +357,7 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft case PIC_ISR_PCIX_ARB_ERR: /* bit40 PCI_X_ARB_ERR */ /* XXX: should breakdown meaning of bits in reg */ - printk( "\t Arbitration Reg: 0x%x\n", + printk( "\t Arbitration Reg: 0x%lx\n", bridge->b_arb); break; @@ -357,10 +400,7 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft break; case BRIDGE_ISR_PAGE_FAULT: /* bit30 PMU_PAGE_FAULT */ - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) - reg_desc = "Map Fault Address"; - else - reg_desc = "SSRAM Parity Error"; + reg_desc = "Map Fault Address"; printk( "\t %s Register: 0x%x\n", reg_desc, bridge->b_ram_perr_or_map_fault); @@ -370,7 +410,7 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); /* PIC in PCI-X mode, dump the PCIX DMA Request registers */ - if (IS_PIC_SOFT(pcibr_soft) && IS_PCIX(pcibr_soft)) { + if (IS_PCIX(pcibr_soft)) { /* XXX: should breakdown meaning of attr bit */ printk( "\t PCI-X DMA Request Error Addr Reg: 0x%lx\n" @@ -382,32 +422,14 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft case BRIDGE_ISR_BAD_XRESP_PKT: /* bit28 BAD_RESP_PACKET */ case BRIDGE_ISR_RESP_XTLK_ERR: /* bit26 RESP_XTALK_ERROR */ - if (IS_PIC_SOFT(pcibr_soft)) { - print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); - } + print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); - /* If PIC in PCI-X mode, DMA Request Error registers are - * valid. But PIC in PCI mode, Response Buffer Address - * register are valid. - */ - if (IS_PCIX(pcibr_soft)) { - /* XXX: should breakdown meaning of attribute bit */ - printk( + /* XXX: should breakdown meaning of attribute bit */ + printk( "\t PCI-X DMA Request Error Addr Reg: 0x%lx\n" "\t PCI-X DMA Request Error Attribute Reg: 0x%lx\n", bridge->p_pcix_dma_req_err_addr_64, bridge->p_pcix_dma_req_err_attr_64); - } else { - addr= (((uint64_t)(bridge->b_wid_resp_upper & 0xFFFF)<<32) - | bridge->b_wid_resp_lower); - printk("\t Bridge Response Buf Error Upper Addr Reg: 0x%x\n" - "\t Bridge Response Buf Error Lower Addr Reg: 0x%x\n" - "\t dev-num %d buff-num %d addr 0x%lx\n", - bridge->b_wid_resp_upper, bridge->b_wid_resp_lower, - ((bridge->b_wid_resp_upper >> 20) & 0x3), - ((bridge->b_wid_resp_upper >> 16) & 0xF), - addr); - } if (bit == BRIDGE_ISR_RESP_XTLK_ERR) { /* display memory directory associated with cacheline */ pcibr_show_dir_state(addr, "\t "); @@ -429,40 +451,17 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft break; case BRIDGE_ISR_UNSUPPORTED_XOP:/* bit23 UNSUPPORTED_XOP */ - if (IS_PIC_SOFT(pcibr_soft)) { - print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); - printk( + print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); + printk( "\t Address Holding Link Side Error Reg: 0x%lx\n", - bridge->p_addr_lkerr_64); - } else { - print_bridge_errcmd(bridge->b_wid_err_cmdword, ""); - printk( - "\t Bridge Error Upper Address Register: 0x%lx\n" - "\t Bridge Error Lower Address Register: 0x%lx\n" - "\t Bridge Error Address: 0x%lx\n", - (uint64_t) bridge->b_wid_err_upper, - (uint64_t) bridge->b_wid_err_lower, - (((uint64_t) bridge->b_wid_err_upper << 32) | - bridge->b_wid_err_lower)); - } + bridge->p_addr_lkerr_64); break; case BRIDGE_ISR_XREQ_FIFO_OFLOW:/* bit22 XREQ_FIFO_OFLOW */ - /* Link side error registers are only valid for PIC */ - if (IS_PIC_SOFT(pcibr_soft)) { - print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); - printk( + print_bridge_errcmd(bridge->b_wid_aux_err, "Aux "); + printk( "\t Address Holding Link Side Error Reg: 0x%lx\n", - bridge->p_addr_lkerr_64); - } - break; - - case BRIDGE_ISR_SSRAM_PERR: /* bit16 SSRAM_PERR */ - if (IS_BRIDGE_SOFT(pcibr_soft)) { - printk( - "\t Bridge SSRAM Parity Error Register: 0x%x\n", - bridge->b_ram_perr); - } + bridge->p_addr_lkerr_64); break; case BRIDGE_ISR_PCI_ABORT: /* bit15 PCI_ABORT */ @@ -498,23 +497,13 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft } } - /* We read the INT_MULT register as a 64bit picreg_t for PIC and a - * 32bit bridgereg_t for BRIDGE, but always process the result as a - * 64bit value so the code can be "common" for both PIC and BRIDGE... - */ - if (IS_PIC_SOFT(pcibr_soft)) { - mult_int_64 = (bridge->p_mult_int_64 & ~BRIDGE_ISR_INT_MSK); - mult_int = (uint64_t)mult_int_64; - number_bits = PCIBR_ISR_MAX_ERRS_PIC; - } else { - mult_int_32 = (bridge->b_mult_int & ~BRIDGE_ISR_INT_MSK); - mult_int = ((uint64_t)mult_int_32) & 0xffffffff; - number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE; - } + mult_int_64 = (bridge->p_mult_int_64 & ~BRIDGE_ISR_INT_MSK); + mult_int = (uint64_t)mult_int_64; + number_bits = PCIBR_ISR_MAX_ERRS_PIC; - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)&&(mult_int & ~BRIDGE_ISR_INT_MSK)) { + if (mult_int & ~BRIDGE_ISR_INT_MSK) { printk( " %s Multiple Interrupt Register is 0x%lx\n", - IS_PIC_SOFT(pcibr_soft) ? "PIC" : "XBridge", mult_int); + "PIC", mult_int); for (i = PCIBR_ISR_ERR_START; i < number_bits; i++) { if (mult_int & (1ull << i)) printk( "\t%s\n", pcibr_isr_errs[i]); @@ -522,29 +511,6 @@ pcibr_error_dump(pcibr_soft_t pcibr_soft } } -static uint32_t -pcibr_errintr_group(uint32_t error) -{ - uint32_t group = BRIDGE_IRR_MULTI_CLR; - - if (error & BRIDGE_IRR_PCI_GRP) - group |= BRIDGE_IRR_PCI_GRP_CLR; - if (error & BRIDGE_IRR_SSRAM_GRP) - group |= BRIDGE_IRR_SSRAM_GRP_CLR; - if (error & BRIDGE_IRR_LLP_GRP) - group |= BRIDGE_IRR_LLP_GRP_CLR; - if (error & BRIDGE_IRR_REQ_DSP_GRP) - group |= BRIDGE_IRR_REQ_DSP_GRP_CLR; - if (error & BRIDGE_IRR_RESP_BUF_GRP) - group |= BRIDGE_IRR_RESP_BUF_GRP_CLR; - if (error & BRIDGE_IRR_CRP_GRP) - group |= BRIDGE_IRR_CRP_GRP_CLR; - - return group; - -} - - /* pcibr_pioerr_check(): * Check to see if this pcibr has a PCI PIO * TIMEOUT error; if so, bump the timeout-count @@ -555,7 +521,6 @@ pcibr_pioerr_check(pcibr_soft_t soft) { bridge_t *bridge; uint64_t int_status; - bridgereg_t int_status_32; picreg_t int_status_64; bridgereg_t pci_err_lower; bridgereg_t pci_err_upper; @@ -568,18 +533,8 @@ pcibr_pioerr_check(pcibr_soft_t soft) int func; bridge = soft->bs_base; - - /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a - * 32bit bridgereg_t for BRIDGE, but always process the result as a - * 64bit value so the code can be "common" for both PIC and BRIDGE... - */ - if (IS_PIC_SOFT(soft)) { - int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); - int_status = (uint64_t)int_status_64; - } else { - int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK); - int_status = ((uint64_t)int_status_32) & 0xffffffff; - } + int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); + int_status = (uint64_t)int_status_64; if (int_status & BRIDGE_ISR_PCIBUS_PIOERR) { pci_err_lower = bridge->b_pci_err_lower; @@ -636,14 +591,13 @@ pcibr_pioerr_check(pcibr_soft_t soft) * due to read or write error!. */ -void +irqreturn_t pcibr_error_intr_handler(int irq, void *arg, struct pt_regs *ep) { pcibr_soft_t pcibr_soft; bridge_t *bridge; uint64_t int_status; uint64_t err_status; - bridgereg_t int_status_32; picreg_t int_status_64; int number_bits; int i; @@ -662,7 +616,9 @@ pcibr_error_intr_handler(int irq, void * entry = pcibr_list; while (1) { if (entry == NULL) { - PRINT_PANIC("pcibr_error_intr_handler:\tmy parameter (0x%p) is not a pcibr_soft!", arg); + printk("pcibr_error_intr_handler: (0x%lx) is not a pcibr_soft!", + (uint64_t)arg); + return IRQ_NONE; } if ((intr_arg_t) entry->bl_soft == arg) break; @@ -706,22 +662,12 @@ pcibr_error_intr_handler(int irq, void * return(pcibr_error_intr_handler(irq, arg, ep)); } - /* We read the INT_STATUS register as a 64bit picreg_t for PIC and a - * 32bit bridgereg_t for BRIDGE, but always process the result as a - * 64bit value so the code can be "common" for both PIC and BRIDGE... - */ - if (IS_PIC_SOFT(pcibr_soft)) { - int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); - int_status = (uint64_t)int_status_64; - number_bits = PCIBR_ISR_MAX_ERRS_PIC; - } else { - int_status_32 = (bridge->b_int_status & ~BRIDGE_ISR_INT_MSK); - int_status = ((uint64_t)int_status_32) & 0xffffffff; - number_bits = PCIBR_ISR_MAX_ERRS_BRIDGE; - } + int_status_64 = (bridge->p_int_status_64 & ~BRIDGE_ISR_INT_MSK); + int_status = (uint64_t)int_status_64; + number_bits = PCIBR_ISR_MAX_ERRS_PIC; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ERROR, pcibr_soft->bs_conn, - "pcibr_error_intr_handler: int_status=0x%x\n", int_status)); + "pcibr_error_intr_handler: int_status=0x%lx\n", int_status)); /* int_status is which bits we have to clear; * err_status is the bits we haven't handled yet. @@ -732,7 +678,7 @@ pcibr_error_intr_handler(int irq, void * /* * No error bit set!!. */ - return; + return IRQ_HANDLED; } /* * If we have a PCIBUS_PIOERR, hand it to the logger. @@ -853,8 +799,7 @@ pcibr_error_intr_handler(int irq, void * * interrupt inorder to clear the DEV_BROKE bits in * b_arb register to re-enable the device. */ - if (IS_PIC_SOFT(pcibr_soft) && - !(err_status & PIC_ISR_PCIX_ARB_ERR) && + if (!(err_status & PIC_ISR_PCIX_ARB_ERR) && PCIBR_WAR_ENABLED(PV856155, pcibr_soft)) { if (bs_estat->bs_errcount_total > PCIBR_ERRINTR_DISABLE_LEVEL) { @@ -876,17 +821,13 @@ pcibr_error_intr_handler(int irq, void * } if (disable_errintr_mask) { - unsigned s; + unsigned long s; /* * Disable some high frequency errors as they * could eat up too much cpu time. */ s = pcibr_lock(pcibr_soft); - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_int_enable_64 &= (picreg_t)(~disable_errintr_mask); - } else { - bridge->b_int_enable &= (bridgereg_t)(~disable_errintr_mask); - } + bridge->p_int_enable_64 &= (picreg_t)(~disable_errintr_mask); pcibr_unlock(pcibr_soft, s); } /* @@ -931,15 +872,15 @@ pcibr_error_intr_handler(int irq, void * * so we know we've hit the problem defined in PV 867308 that we believe * has only been seen in simulation */ - if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV867308, pcibr_soft) && + if (PCIBR_WAR_ENABLED(PV867308, pcibr_soft) && (err_status & (BRIDGE_ISR_LLP_REC_SNERR | BRIDGE_ISR_LLP_REC_CBERR))) { printk("BRIDGE ERR_STATUS 0x%lx\n", err_status); pcibr_error_dump(pcibr_soft); - PRINT_PANIC("PCI Bridge Error interrupt killed the system"); + panic("PCI Bridge Error interrupt killed the system"); } if (err_status & BRIDGE_ISR_ERROR_FATAL) { - PRINT_PANIC("PCI Bridge Error interrupt killed the system"); + panic("PCI Bridge Error interrupt killed the system"); /*NOTREACHED */ } @@ -952,24 +893,20 @@ pcibr_error_intr_handler(int irq, void * * * PIC doesn't require groups of interrupts to be cleared... */ - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_int_rst_stat_64 = (picreg_t)(int_status | BRIDGE_IRR_MULTI_CLR); - } else { - bridge->b_int_rst_stat = (bridgereg_t)pcibr_errintr_group(int_status); - } + bridge->p_int_rst_stat_64 = (picreg_t)(int_status | BRIDGE_IRR_MULTI_CLR); /* PIC BRINGUP WAR (PV# 856155): * On a PCI_X_ARB_ERR error interrupt clear the DEV_BROKE bits from * the b_arb register to re-enable the device. */ - if (IS_PIC_SOFT(pcibr_soft) && - (err_status & PIC_ISR_PCIX_ARB_ERR) && + if ((err_status & PIC_ISR_PCIX_ARB_ERR) && PCIBR_WAR_ENABLED(PV856155, pcibr_soft)) { bridge->b_arb |= (0xf << 20); } /* Zero out bserr_intstat field */ pcibr_soft->bs_errinfo.bserr_intstat = 0; + return IRQ_HANDLED; } void @@ -980,14 +917,9 @@ pcibr_error_cleanup(pcibr_soft_t pcibr_s ASSERT(error_code & IOECODE_PIO); error_code = error_code; - if (IS_PIC_SOFT(pcibr_soft)) { - bridge->p_int_rst_stat_64 = BRIDGE_IRR_PCI_GRP_CLR | + bridge->p_int_rst_stat_64 = BRIDGE_IRR_PCI_GRP_CLR | PIC_PCIX_GRP_CLR | BRIDGE_IRR_MULTI_CLR; - } else { - bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR | BRIDGE_IRR_MULTI_CLR; - } - (void) bridge->b_wid_tflush; /* flushbus */ } @@ -1079,8 +1011,6 @@ pcibr_pioerror( int retval = IOERROR_HANDLED; vertex_hdl_t pcibr_vhdl = pcibr_soft->bs_vhdl; - bridge_t *bridge = pcibr_soft->bs_base; - iopaddr_t bad_xaddr; pciio_space_t raw_space; /* raw PCI space */ @@ -1106,7 +1036,7 @@ pcibr_pioerror( IOERROR_GETVALUE(bad_xaddr, ioe, xtalkaddr); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn, - "pcibr_pioerror: pcibr_soft=0x%x, bad_xaddr=0x%x\n", + "pcibr_pioerror: pcibr_soft=0x%lx, bad_xaddr=0x%lx\n", pcibr_soft, bad_xaddr)); slot = PCIIO_SLOT_NONE; @@ -1405,47 +1335,8 @@ pcibr_pioerror( printk(KERN_ALERT "PIO Error on PCI Bus %s", pcibr_soft->bs_name); - /* this decodes part of the ioe; our caller - * will dump the raw details in DEBUG and - * kdebug kernels. - */ BEM_ADD_IOE(ioe); } -#if defined(FORCE_ERRORS) - if (0) { -#elif !DEBUG - if (kdebug) { -#endif - /* - * Dump raw data from Bridge/PCI layer. - */ - - BEM_ADD_STR("Raw info from Bridge/PCI layer:\n"); - if (IS_PIC_SOFT(pcibr_soft)) { - if (bridge->p_int_status_64 & (picreg_t)BRIDGE_ISR_PCIBUS_PIOERR) - pcibr_error_dump(pcibr_soft); - } else { - if (bridge->b_int_status & (bridgereg_t)BRIDGE_ISR_PCIBUS_PIOERR) - pcibr_error_dump(pcibr_soft); - } - BEM_ADD_SPC(raw_space); - BEM_ADD_VAR(raw_paddr); - if (IOERROR_FIELDVALID(ioe, widgetdev)) { - short widdev; - IOERROR_GETVALUE(widdev, ioe, widgetdev); - slot = pciio_widgetdev_slot_get(widdev); - func = pciio_widgetdev_func_get(widdev); - if (slot < PCIBR_NUM_SLOTS(pcibr_soft)) { - bridgereg_t device = bridge->b_device[slot].reg; - - BEM_ADD_VAR(slot); - BEM_ADD_VAR(func); - BEM_ADD_REG(device); - } - } -#if !DEBUG || defined(FORCE_ERRORS) - } -#endif /* * Since error could not be handled at lower level, @@ -1506,7 +1397,6 @@ pcibr_dmard_error( IOERROR_GETVALUE(tmp, ioe, widgetnum); ASSERT(tmp == pcibr_soft->bs_xid); } - ASSERT(bridge); /* * read error log registers @@ -1637,7 +1527,7 @@ pcibr_error_handler( pcibr_soft = (pcibr_soft_t) einfo; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn, - "pcibr_error_handler: pcibr_soft=0x%x, error_code=0x%x\n", + "pcibr_error_handler: pcibr_soft=0x%lx, error_code=0x%x\n", pcibr_soft, error_code)); #if DEBUG && ERROR_DEBUG @@ -1701,7 +1591,7 @@ pcibr_error_handler_wrapper( int dma_retval = -1; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ERROR_HDLR, pcibr_soft->bs_conn, - "pcibr_error_handler_wrapper: pcibr_soft=0x%x, " + "pcibr_error_handler_wrapper: pcibr_soft=0x%lx, " "error_code=0x%x\n", pcibr_soft, error_code)); /* @@ -1735,7 +1625,7 @@ pcibr_error_handler_wrapper( if (!pcibr_soft) { #if DEBUG printk(KERN_WARNING "pcibr_error_handler: " - "bs_peers_soft==NULL. bad_xaddr= 0x%x mode= 0x%x\n", + "bs_peers_soft==NULL. bad_xaddr= 0x%lx mode= 0x%lx\n", bad_xaddr, mode); #endif pio_retval = IOERROR_HANDLED; diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_hints.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,26 +7,11 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include #include #include -#include -#include -#include -#include pcibr_hints_t pcibr_hints_get(vertex_hdl_t, int); void pcibr_hints_fix_rrbs(vertex_hdl_t); @@ -48,7 +32,11 @@ pcibr_hints_get(vertex_hdl_t xconn_vhdl, if (alloc && (rv != GRAPH_SUCCESS)) { - NEW(hint); + hint = kmalloc(sizeof (*(hint)), GFP_KERNEL); + if ( !hint ) + goto abnormal_exit; + memset(hint, 0, sizeof (*(hint))); + hint->rrb_alloc_funct = NULL; hint->ph_intr_bits = NULL; rv = hwgraph_info_add_LBL(xconn_vhdl, @@ -68,10 +56,7 @@ pcibr_hints_get(vertex_hdl_t xconn_vhdl, return (pcibr_hints_t) ainfo; abnormal_exit: -#ifdef LATER - printf("SHOULD NOT BE HERE\n"); -#endif - DEL(hint); + kfree(hint); return(NULL); } @@ -162,18 +147,19 @@ pcibr_hints_subdevs(vertex_hdl_t xconn_v if (ainfo == 0) { uint64_t *subdevp; - NEW(subdevp); + subdevp = kmalloc(sizeof (*(subdevp)), GFP_KERNEL); if (!subdevp) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_hints_subdevs: subdev ptr alloc failed\n")); return; } + memset(subdevp, 0, sizeof (*(subdevp))); *subdevp = subdevs; hwgraph_info_add_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, (arbitrary_info_t) subdevp); hwgraph_info_get_LBL(pconn_vhdl, INFO_LBL_SUBDEVS, &ainfo); if (ainfo == (arbitrary_info_t) subdevp) return; - DEL(subdevp); + kfree(subdevp); if (ainfo == (arbitrary_info_t) NULL) { PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, xconn_vhdl, "pcibr_hints_subdevs: null subdevs ptr\n")); diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,24 +7,14 @@ */ #include -#include #include #include -#include -#include #include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include #include #include @@ -33,7 +22,7 @@ inline int compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr) { - FIXME("compare_and_swap_ptr : NOT ATOMIC"); + /* FIXME - compare_and_swap_ptr NOT ATOMIC */ if (*location == old_ptr) { *location = new_ptr; return(1); @@ -94,49 +83,6 @@ pcibr_intr_bits(pciio_info_t info, /* - * Get the next wrapper pointer queued in the interrupt circular buffer. - */ -pcibr_intr_wrap_t -pcibr_wrap_get(pcibr_intr_cbuf_t cbuf) -{ - pcibr_intr_wrap_t wrap; - - if (cbuf->ib_in == cbuf->ib_out) - PRINT_PANIC( "pcibr intr circular buffer empty, cbuf=0x%p, ib_in=ib_out=%d\n", - (void *)cbuf, cbuf->ib_out); - - wrap = cbuf->ib_cbuf[cbuf->ib_out++]; - cbuf->ib_out = cbuf->ib_out % IBUFSIZE; - return(wrap); -} - -/* - * Queue a wrapper pointer in the interrupt circular buffer. - */ -void -pcibr_wrap_put(pcibr_intr_wrap_t wrap, pcibr_intr_cbuf_t cbuf) -{ - int in; - int s; - - /* - * Multiple CPUs could be executing this code simultaneously - * if a handler has registered multiple interrupt lines and - * the interrupts are directed to different CPUs. - */ - s = mutex_spinlock(&cbuf->ib_lock); - in = (cbuf->ib_in + 1) % IBUFSIZE; - if (in == cbuf->ib_out) - PRINT_PANIC( "pcibr intr circular buffer full, cbuf=0x%p, ib_in=%d\n", - (void *)cbuf, cbuf->ib_in); - - cbuf->ib_cbuf[cbuf->ib_in] = wrap; - cbuf->ib_in = in; - mutex_spinunlock(&cbuf->ib_lock, s); - return; -} - -/* * On SN systems there is a race condition between a PIO read response * and DMA's. In rare cases, the read response may beat the DMA, causing * the driver to think that data in memory is complete and meaningful. @@ -168,36 +114,16 @@ sn_dma_flush(unsigned long addr) { if (flush_nasid_list[nasid].widget_p == NULL) return; if (bwin > 0) { - bwin--; - switch (bwin) { - case 0: - wid_num = ((flush_nasid_list[nasid].iio_itte1) >> 8) & 0xf; - break; - case 1: - wid_num = ((flush_nasid_list[nasid].iio_itte2) >> 8) & 0xf; - break; - case 2: - wid_num = ((flush_nasid_list[nasid].iio_itte3) >> 8) & 0xf; - break; - case 3: - wid_num = ((flush_nasid_list[nasid].iio_itte4) >> 8) & 0xf; - break; - case 4: - wid_num = ((flush_nasid_list[nasid].iio_itte5) >> 8) & 0xf; - break; - case 5: - wid_num = ((flush_nasid_list[nasid].iio_itte6) >> 8) & 0xf; - break; - case 6: - wid_num = ((flush_nasid_list[nasid].iio_itte7) >> 8) & 0xf; - break; - } + unsigned long itte = flush_nasid_list[nasid].iio_itte[bwin]; + + wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & + IIO_ITTE_WIDGET_MASK; } if (flush_nasid_list[nasid].widget_p == NULL) return; if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) return; p = &flush_nasid_list[nasid].widget_p[wid_num][0]; - // find a matching BAR + /* find a matching BAR */ for (i=0; iflush_addr = 0; - // force an interrupt. + /* force an interrupt. */ *(bridgereg_t *)(p->force_int_addr) = 1; - // wait for the interrupt to come back. + /* wait for the interrupt to come back. */ while (p->flush_addr != 0x10f); - // okay, everything is synched up. + /* okay, everything is synched up. */ spin_unlock_irqrestore(&p->flush_lock, flags); return; @@ -283,9 +209,7 @@ pcibr_force_interrupt(pcibr_intr_t intr) PCIBR_DEBUG((PCIBR_DEBUG_INTR, pcibr_soft->bs_vhdl, "pcibr_force_interrupt: bit=0x%x\n", bit)); - if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) { - bridge->b_force_pin[bit].intr = 1; - } + bridge->b_force_pin[bit].intr = 1; } } } @@ -326,9 +250,10 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl lines & 4 ? " INTC" : "", lines & 8 ? " INTD" : "")); - NEW(pcibr_intr); + pcibr_intr = kmalloc(sizeof (*(pcibr_intr)), GFP_KERNEL); if (!pcibr_intr) return NULL; + memset(pcibr_intr, 0, sizeof (*(pcibr_intr))); pcibr_intr->bi_dev = pconn_vhdl; pcibr_intr->bi_lines = lines; @@ -340,7 +265,7 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl pcibr_intr->bi_mustruncpu = CPU_NONE; pcibr_intr->bi_ibuf.ib_in = 0; pcibr_intr->bi_ibuf.ib_out = 0; - mutex_spinlock_init(&pcibr_intr->bi_ibuf.ib_lock); + spin_lock_init(&pcibr_intr->bi_ibuf.ib_lock); pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines, PCIBR_NUM_SLOTS(pcibr_soft)); @@ -384,7 +309,7 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl owner_dev); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl, - "pcibr_intr_alloc: xtalk_intr=0x%x\n", xtalk_intr)); + "pcibr_intr_alloc: xtalk_intr=0x%lx\n", xtalk_intr)); /* both an assert and a runtime check on this: * we need to check in non-DEBUG kernels, and @@ -400,15 +325,9 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl * in xtalk_intr_p. */ if (!*xtalk_intr_p) { -#ifdef SUPPORT_PRINTING_V_FORMAT - printk(KERN_ALERT - "pcibr_intr_alloc %v: unable to get xtalk interrupt resources", - xconn_vhdl); -#else - printk(KERN_ALERT - "pcibr_intr_alloc 0x%p: unable to get xtalk interrupt resources", - (void *)xconn_vhdl); -#endif + printk(KERN_ALERT "pcibr_intr_alloc %s: " + "unable to get xtalk interrupt resources", + pcibr_soft->bs_name); /* yes, we leak resources here. */ return 0; } @@ -432,25 +351,20 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl */ xtalk_intr_free(xtalk_intr); xtalk_intr = *xtalk_intr_p; -#if PARANOID - /* once xtalk_intr is set, we never clear it, - * so if the CAS fails above, this condition - * can "never happen" ... - */ - if (!xtalk_intr) { - printk(KERN_ALERT - "pcibr_intr_alloc %v: unable to set xtalk interrupt resources", - xconn_vhdl); - /* yes, we leak resources here. */ - return 0; - } -#endif } } pcibr_intr->bi_ibits |= 1 << pcibr_int_bit; - NEW(intr_entry); + intr_entry = kmalloc(sizeof (*(intr_entry)), GFP_KERNEL); + if ( !intr_entry ) { + printk(KERN_ALERT "pcibr_intr_alloc %s: " + "unable to get memory", + pcibr_soft->bs_name); + return 0; + } + memset(intr_entry, 0, sizeof (*(intr_entry))); + intr_entry->il_next = NULL; intr_entry->il_intr = pcibr_intr; intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg); @@ -458,8 +372,8 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl, - "Bridge bit 0x%x wrap=0x%x\n", pcibr_int_bit, - pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap)); + "Bridge bit 0x%x wrap=0x%lx\n", pcibr_int_bit, + &(pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap))); if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) { /* we are the first interrupt on this bridge bit. @@ -476,7 +390,7 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl * and we replaced it, so we * don't need our intr_entry. */ - DEL(intr_entry); + kfree(intr_entry); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl, "INT 0x%x (bridge bit %d) replaces erased first\n", pcibr_int_bits, pcibr_int_bit)); @@ -499,7 +413,7 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl * and we replaced it, so we * don't need our intr_entry. */ - DEL(intr_entry); + kfree(intr_entry); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl, "INT 0x%x (bridge bit %d) replaces erase Nth\n", @@ -522,12 +436,11 @@ pcibr_intr_alloc(vertex_hdl_t pconn_vhdl } } -#if DEBUG && INTR_DEBUG - printk("%v pcibr_intr_alloc complete\n", pconn_vhdl); -#endif hub_intr = (hub_intr_t)xtalk_intr; pcibr_intr->bi_irq = hub_intr->i_bit; pcibr_intr->bi_cpu = hub_intr->i_cpuid; + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pconn_vhdl, + "pcibr_intr_alloc complete: pcibr_intr=0x%lx\n", pcibr_intr)); return pcibr_intr; } @@ -582,7 +495,7 @@ pcibr_intr_free(pcibr_intr_t pcibr_intr) } } } - DEL(pcibr_intr); + kfree(pcibr_intr); } void @@ -619,8 +532,8 @@ pcibr_intr_connect(pcibr_intr_t pcibr_in return -1; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_intr->bi_dev, - "pcibr_intr_connect: intr_func=0x%x\n", - pcibr_intr)); + "pcibr_intr_connect: intr_func=0x%lx, intr_arg=0x%lx\n", + intr_func, intr_arg)); pcibr_intr->bi_func = intr_func; pcibr_intr->bi_arg = intr_arg; @@ -653,10 +566,7 @@ pcibr_intr_connect(pcibr_intr_t pcibr_in * Use the pcibr wrapper function to handle all Bridge interrupts * regardless of whether the interrupt line is shared or not. */ - if (IS_PIC_SOFT(pcibr_soft)) - int_addr = (void *)&(bridge->p_int_addr_64[pcibr_int_bit]); - else - int_addr = (void *)&(bridge->b_int_addr[pcibr_int_bit].addr); + int_addr = (void *)&(bridge->p_int_addr_64[pcibr_int_bit]); xtalk_intr_connect(xtalk_intr, pcibr_intr_func, (intr_arg_t) intr_wrap, (xtalk_intr_setfunc_t) pcibr_setpciint, @@ -675,8 +585,7 @@ pcibr_intr_connect(pcibr_intr_t pcibr_in * On PIC we must write 64-bit MMRs with 64-bit stores */ s = pcibr_lock(pcibr_soft); - if (IS_PIC_SOFT(pcibr_soft) && - PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { int_enable = bridge->p_int_enable_64; int_enable |= pcibr_int_bits; bridge->p_int_enable_64 = int_enable; @@ -726,11 +635,8 @@ pcibr_intr_disconnect(pcibr_intr_t pcibr if (!pcibr_int_bits) return; - /* PIC WAR. PV# 854697 - * On PIC we must write 64-bit MMRs with 64-bit stores - */ s = pcibr_lock(pcibr_soft); - if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { int_enable = bridge->p_int_enable_64; int_enable &= ~pcibr_int_bits; bridge->p_int_enable_64 = int_enable; @@ -775,10 +681,7 @@ pcibr_intr_disconnect(pcibr_intr_t pcibr if (!pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared) continue; - if (IS_PIC_SOFT(pcibr_soft)) - int_addr = (void *)&(bridge->p_int_addr_64[pcibr_int_bit]); - else - int_addr = (void *)&(bridge->b_int_addr[pcibr_int_bit].addr); + int_addr = (void *)&(bridge->p_int_addr_64[pcibr_int_bit]); xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr, pcibr_intr_func, (intr_arg_t) intr_wrap, @@ -856,7 +759,7 @@ pcibr_setwidint(xtalk_intr_t intr) printk(KERN_WARNING "NEW=0x%x/0x%x OLD=0x%x/0x%x\n", NEW_b_wid_int_upper, NEW_b_wid_int_lower, OLD_b_wid_int_upper, OLD_b_wid_int_lower); - PRINT_PANIC("PCI Bridge interrupt targetting error\n"); + panic("PCI Bridge interrupt targetting error\n"); } } @@ -950,8 +853,7 @@ pcibr_intr_func(intr_arg_t arg) * interrupt problem. Briefly disable the enable bit for * this device. */ - if (IS_PIC_SOFT(pcibr_soft) && - PCIBR_WAR_ENABLED(PV855272, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV855272, pcibr_soft)) { unsigned s; /* disable-enable interrupts for this bridge pin */ @@ -986,26 +888,27 @@ pcibr_intr_func(intr_arg_t arg) for (list = wrap->iw_list; list != NULL; list = list->il_next) { if ((intr = list->il_intr) && (intr->bi_flags & PCIIO_INTR_CONNECTED)) { - /* - * This device may have initiated write - * requests since the bridge last saw - * an edge on this interrupt input; flushing - * the buffer prior to invoking the handler - * should help but may not be sufficient if we - * get more requests after the flush, followed - * by the card deciding it wants service, before - * the interrupt handler checks to see if things need - * to be done. - * - * There is a similar race condition if - * an interrupt handler loops around and - * notices further service is required. - * Perhaps we need to have an explicit - * call that interrupt handlers need to - * do between noticing that DMA to memory - * has completed, but before observing the - * contents of memory? - */ + + /* + * This device may have initiated write + * requests since the bridge last saw + * an edge on this interrupt input; flushing + * the buffer prior to invoking the handler + * should help but may not be sufficient if we + * get more requests after the flush, followed + * by the card deciding it wants service, before + * the interrupt handler checks to see if things need + * to be done. + * + * There is a similar race condition if + * an interrupt handler loops around and + * notices further service is requred. + * Perhaps we need to have an explicit + * call that interrupt handlers need to + * do between noticing that DMA to memory + * has completed, but before observing the + * contents of memory? + */ if ((do_nonthreaded) && (!is_threaded)) { /* Non-threaded - Call the interrupt handler at interrupt level */ @@ -1061,8 +964,7 @@ pcibr_intr_func(intr_arg_t arg) * On PIC we must write 64-bit MMRs with 64-bit stores */ s = pcibr_lock(pcibr_soft); - if (IS_PIC_SOFT(pcibr_soft) && - PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { + if (PCIBR_WAR_ENABLED(PV854697, pcibr_soft)) { int_enable = bridge->p_int_enable_64; int_enable &= ~mask; bridge->p_int_enable_64 = int_enable; diff -puN /dev/null arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,107 @@ +/* + * 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 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define IS_IOADDR(ptr) (!(((uint64_t)(ptr) & CAC_BASE) == CAC_BASE)) + +/* + * Control Register Access -- Read/Write 0000_0020 + */ + +uint64_t +pcireg_control_get(void *ptr) +{ + uint64_t ret = 0; + pic_t *bridge; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + + ret = ((pic_t *) bridge)->p_wid_control; + return ret; +} + +/* + * Interrupt Status Register Access -- Read Only 0000_0100 + */ +uint64_t +pcireg_intr_status_get(void *ptr) +{ + short bridge_type; + pic_t *bridge; + uint64_t ret = 0; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + + ret = ((pic_t *) bridge)->p_int_status; + return ret; +} + +void +pcireg_intr_enable_bit_clr(void *ptr, uint64_t bits) +{ + pic_t *bridge; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + bridge->p_int_enable &= ~bits; +} + +void +pcireg_intr_enable_bit_set(void *ptr, uint64_t bits) +{ + pic_t *bridge; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + bridge->p_int_enable |= bits; +} + +void +pcireg_intr_addr_addr_set(void *ptr, int int_n, uint64_t addr) +{ + pic_t *bridge; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + bridge->p_int_addr[int_n] &= ~(0x0000FFFFFFFFFFFF); + bridge->p_int_addr[int_n] |= (addr & 0x0000FFFFFFFFFFFF); +} + +/* + * Force Interrupt Register Access -- Write Only 0000_01C0 - 0000_01F8 + */ +void +pcireg_force_intr_set(void *ptr, int int_n) +{ + pic_t *bridge; + + if (IS_IOADDR(ptr)) + bridge = (pic_t *) ptr; + else + bridge = (pic_t *) ((pcibr_soft_t) (ptr))->bs_base; + bridge->p_force_pin[int_n] = 1; +} diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,26 +7,12 @@ */ #include -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include -#include void do_pcibr_rrb_clear(bridge_t *, int); void do_pcibr_rrb_flush(bridge_t *, int); @@ -87,7 +72,7 @@ do_pcibr_rrb_count_valid(bridge_t *bridg pciio_slot_t slot, int vchan) { - bridgereg_t tmp; + uint64_t tmp; uint16_t enable_bit, vchan_bits, pdev_bits, rrb_bits; int rrb_index, cnt=0; @@ -120,7 +105,7 @@ int do_pcibr_rrb_count_avail(bridge_t *bridge, pciio_slot_t slot) { - bridgereg_t tmp; + uint64_t tmp; uint16_t enable_bit; int rrb_index, cnt=0; @@ -156,7 +141,7 @@ do_pcibr_rrb_alloc(bridge_t *bridge, int vchan, int more) { - bridgereg_t reg, tmp = (bridgereg_t)0; + uint64_t reg, tmp = 0; uint16_t enable_bit, vchan_bits, pdev_bits, rrb_bits; int rrb_index; @@ -201,7 +186,7 @@ do_pcibr_rrb_free(bridge_t *bridge, int vchan, int less) { - bridgereg_t reg, tmp = (bridgereg_t)0, clr = 0; + uint64_t reg, tmp = 0, clr = 0; uint16_t enable_bit, vchan_bits, pdev_bits, rrb_bits; int rrb_index; @@ -273,7 +258,7 @@ do_pcibr_rrb_free_all(pcibr_soft_t pcibr void do_pcibr_rrb_clear(bridge_t *bridge, int rrb) { - bridgereg_t status; + uint64_t status; /* bridge_lock must be held; * this RRB must be disabled. @@ -365,7 +350,7 @@ pcibr_rrb_flush(vertex_hdl_t pconn_vhdl) pciio_slot_t slot = PCIBR_INFO_SLOT_GET_INT(pciio_info); bridge_t *bridge = pcibr_soft->bs_base; - bridgereg_t tmp; + uint64_t tmp; uint16_t enable_bit, pdev_bits, rrb_bits, rrb_mask; int rrb_index; unsigned long s; @@ -402,18 +387,8 @@ pcibr_wrb_flush(vertex_hdl_t pconn_vhdl) volatile bridgereg_t *wrb_flush; wrb_flush = &(bridge->b_wr_req_buf[pciio_slot].reg); - if ( IS_PIC_SOFT(pcibr_soft) ) { - while (*wrb_flush) - ; - } - else { - if (io_get_sh_swapper(NASID_GET(bridge))) { - while (BRIDGE_REG_GET32((wrb_flush))); - } else { - while (*wrb_flush) - ; - } - } + while (*wrb_flush) + ; return(0); } @@ -711,24 +686,17 @@ pcibr_slot_initial_rrb_alloc(vertex_hdl_ for (vchan = 0; vchan < vchan_total; vchan++) chan[vchan] = do_pcibr_rrb_count_valid(bridge, slot, vchan); - if (IS_PIC_SOFT(pcibr_soft)) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_vhdl, + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_vhdl, "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%d+%d+%d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), chan[VCHAN0], chan[VCHAN1], chan[VCHAN2], chan[VCHAN3])); - } else { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_vhdl, - "pcibr_slot_initial_rrb_alloc: slot %d started with %d+%d\n", - PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), - chan[VCHAN0], chan[VCHAN1])); - } /* Do we really need any? */ pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; pcibr_info = pcibr_infoh[0]; - if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft) && IS_PIC_SOFT(pcibr_soft) && + if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft) && (slot == 2 || slot == 3) && (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE) && !pcibr_soft->bs_slot[slot].has_host) { @@ -868,13 +836,8 @@ pcibr_rrb_debug(char *calling_func, pcib "%s: rrbs available, even=%d, odd=%d\n", calling_func, pcibr_soft->bs_rrb_avail[0], pcibr_soft->bs_rrb_avail[1])); - if (IS_PIC_SOFT(pcibr_soft)) { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "\tslot\tvchan0\tvchan1\tvchan2\tvchan3\treserved\n")); - } else { - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, - "\tslot\tvchan0\tvchan1\treserved\n")); - } for (slot=0; slot < PCIBR_NUM_SLOTS(pcibr_soft); slot++) { /* @@ -882,22 +845,13 @@ pcibr_rrb_debug(char *calling_func, pcib * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printf * arguments fails so sprintf() it into a temporary string. */ - if (IS_PIC_SOFT(pcibr_soft)) { - sprintf(tmp_str, "\t %d\t %d\t %d\t %d\t %d\t %d\n", + sprintf(tmp_str, "\t %d\t %d\t %d\t %d\t %d\t %d\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN0], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN1], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN2], 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN3], pcibr_soft->bs_rrb_res[slot]); - } else { - sprintf(tmp_str, "\t %d\t %d\t %d\t %d\n", - PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), - 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN0], - 0xFFF & pcibr_soft->bs_rrb_valid[slot][VCHAN1], - pcibr_soft->bs_rrb_res[slot]); - } - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RRB, pcibr_soft->bs_vhdl, "%s", tmp_str)); } diff -puN arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c~linus arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c --- 25/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,26 +7,14 @@ */ #include -#include -#include -#include #include #include -#include -#include +#include #include -#include -#include -#include -#include -#include #include #include #include #include -#include -#include -#include #include extern pcibr_info_t pcibr_info_get(vertex_hdl_t); @@ -36,6 +23,8 @@ extern pcibr_info_t pcibr_device_inf extern int pcibr_slot_initial_rrb_alloc(vertex_hdl_t,pciio_slot_t); extern int pcibr_pcix_rbars_calc(pcibr_soft_t); +extern char *pci_space[]; + int pcibr_slot_info_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); int pcibr_slot_info_free(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); int pcibr_slot_addr_space_init(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot); @@ -57,24 +46,6 @@ cfg_p pcibr_find_capability(cfg_p, unsig extern uint64_t do_pcibr_config_get(cfg_p, unsigned, unsigned); void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t); -int pcibr_slot_attach(vertex_hdl_t pcibr_vhdl, pciio_slot_t slot, - int drv_flags, char *l1_msg, int *sub_errorp); - -int pcibr_slot_info_return(pcibr_soft_t pcibr_soft, pciio_slot_t slot, - pcibr_slot_info_resp_t respp); - -extern vertex_hdl_t baseio_pci_vhdl; -int scsi_ctlr_nums_add(vertex_hdl_t, vertex_hdl_t); - - -/* For now .... */ -/* - * PCI Hot-Plug Capability Flags - - */ -#define D_PCI_HOT_PLUG_ATTACH 0x200 /* Driver supports PCI hot-plug attach */ -#define D_PCI_HOT_PLUG_DETACH 0x400 /* Driver supports PCI hot-plug detach */ - /* * PCI-X Max Outstanding Split Transactions translation array and Max Memory @@ -86,158 +57,6 @@ int scsi_ctlr_nums_add(vertex_hdl_t, ver int max_splittrans_to_numbuf[MAX_SPLIT_TABLE] = {1, 2, 3, 4, 8, 12, 16, 32}; int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 }; - -/*========================================================================== - * BRIDGE PCI SLOT RELATED IOCTLs - */ - -/* - * pcibr_slot_startup - * Software start-up the PCI slot. - */ - -#ifdef PIC_LATER - -int -pcibr_slot_startup(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) -{ - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - pciio_slot_t slot; - int error = 0; - char l1_msg[BRL1_QSIZE+1]; - struct pcibr_slot_up_resp_s tmp_up_resp; - - /* Make sure that we are dealing with a bridge device vertex */ - if (!pcibr_soft) { - return(PCI_NOT_A_BRIDGE); - } - - /* req_slot is the 'external' slot number, convert for internal use */ - slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); - - /* Check for the valid slot */ - if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) - return(PCI_NOT_A_SLOT); - -#ifdef PIC_LATER - /* Acquire update access to the bus */ - mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO); -#endif - - if (pcibr_soft->bs_slot[slot].slot_status & SLOT_STARTUP_CMPLT) { - error = PCI_SLOT_ALREADY_UP; - goto startup_unlock; - } - - error = pcibr_slot_attach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_ATTACH, - l1_msg, &tmp_up_resp.resp_sub_errno); - - strncpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE); - tmp_up_resp.resp_l1_msg[L1_QSIZE] = '\0'; - - if (COPYOUT(&tmp_up_resp, reqp->req_respp.up, reqp->req_size)) { - return(EFAULT); - } - - startup_unlock: - -#ifdef PIC_LATER - /* Release the bus lock */ - mrunlock(pcibr_soft->bs_bus_lock); -#endif - return(error); -} - -/* - * pcibr_slot_shutdown - * Software shut-down the PCI slot - */ -int -pcibr_slot_shutdown(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) -{ - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - bridge_t *bridge; - pciio_slot_t slot; - int error = 0; - char l1_msg[BRL1_QSIZE+1]; - struct pcibr_slot_down_resp_s tmp_down_resp; - pciio_slot_t tmp_slot; - - /* Make sure that we are dealing with a bridge device vertex */ - if (!pcibr_soft) { - return(PCI_NOT_A_BRIDGE); - } - - /* req_slot is the 'external' slot number, convert for internal use */ - slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); - - bridge = pcibr_soft->bs_base; - - /* Check for valid slot */ - if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) - return(PCI_NOT_A_SLOT); - -#ifdef PIC_LATER - /* Acquire update access to the bus */ - mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO); -#endif - - if ((pcibr_soft->bs_slot[slot].slot_status & SLOT_SHUTDOWN_CMPLT) || - ((pcibr_soft->bs_slot[slot].slot_status & SLOT_STATUS_MASK) == 0)) { - error = PCI_SLOT_ALREADY_DOWN; - /* - * RJR - Should we invoke an L1 slot power-down command just in case - * a previous shut-down failed to power-down the slot? - */ - goto shutdown_unlock; - } - - /* Do not allow a multi-function card to be hot-plug removed */ - if (pcibr_soft->bs_slot[slot].bss_ninfo > 1) { - tmp_down_resp.resp_sub_errno = EPERM; - error = PCI_MULTI_FUNC_ERR; - goto shutdown_copyout; - } - - /* Do not allow the last 33 MHz card to be removed */ - if ((bridge->b_wid_control & BRIDGE_CTRL_BUS_SPEED_MASK) == - BRIDGE_CTRL_BUS_SPEED_33) { - for (tmp_slot = pcibr_soft->bs_first_slot; - tmp_slot <= pcibr_soft->bs_last_slot; tmp_slot++) - if (tmp_slot != slot) - if (pcibr_soft->bs_slot[tmp_slot].slot_status & SLOT_POWER_UP) { - error++; - break; - } - if (!error) { - error = PCI_EMPTY_33MHZ; - goto shutdown_unlock; - } - } - - error = pcibr_slot_detach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_DETACH, - l1_msg, &tmp_down_resp.resp_sub_errno); - - strncpy(tmp_down_resp.resp_l1_msg, l1_msg, L1_QSIZE); - tmp_down_resp.resp_l1_msg[L1_QSIZE] = '\0'; - - shutdown_copyout: - - if (COPYOUT(&tmp_down_resp, reqp->req_respp.down, reqp->req_size)) { - return(EFAULT); - } - - shutdown_unlock: - -#ifdef PIC_LATER - /* Release the bus lock */ - mrunlock(pcibr_soft->bs_bus_lock); -#endif - - return(error); -} -#endif /* PIC_LATER */ - char *pci_space_name[] = {"NONE", "ROM", "IO", @@ -255,252 +74,6 @@ char *pci_space_name[] = {"NONE", "", "BAD"}; -void -pcibr_slot_func_info_return(pcibr_info_h pcibr_infoh, - int func, - pcibr_slot_func_info_resp_t funcp) -{ - pcibr_info_t pcibr_info = pcibr_infoh[func]; - int win; - - funcp->resp_f_status = 0; - - if (!pcibr_info) { - return; - } - - funcp->resp_f_status |= FUNC_IS_VALID; -#if defined(SUPPORT_PRINTING_V_FORMAT) - sprintf(funcp->resp_f_slot_name, "%v", pcibr_info->f_vertex); -#endif - - funcp->resp_f_bus = pcibr_info->f_bus; - funcp->resp_f_slot = PCIBR_INFO_SLOT_GET_EXT(pcibr_info); - funcp->resp_f_func = pcibr_info->f_func; -#if defined(SUPPORT_PRINTING_V_FORMAT) - sprintf(funcp->resp_f_master_name, "%v", pcibr_info->f_master); -#endif - funcp->resp_f_pops = pcibr_info->f_pops; - funcp->resp_f_efunc = pcibr_info->f_efunc; - funcp->resp_f_einfo = pcibr_info->f_einfo; - - funcp->resp_f_vendor = pcibr_info->f_vendor; - funcp->resp_f_device = pcibr_info->f_device; - - for(win = 0 ; win < 6 ; win++) { - funcp->resp_f_window[win].resp_w_base = - pcibr_info->f_window[win].w_base; - funcp->resp_f_window[win].resp_w_size = - pcibr_info->f_window[win].w_size; - sprintf(funcp->resp_f_window[win].resp_w_space, - "%s", - pci_space_name[pcibr_info->f_window[win].w_space]); - } - - funcp->resp_f_rbase = pcibr_info->f_rbase; - funcp->resp_f_rsize = pcibr_info->f_rsize; - - for (win = 0 ; win < 4; win++) { - funcp->resp_f_ibit[win] = pcibr_info->f_ibit[win]; - } - - funcp->resp_f_att_det_error = pcibr_info->f_att_det_error; - -} - -int -pcibr_slot_info_return(pcibr_soft_t pcibr_soft, - pciio_slot_t slot, - pcibr_slot_info_resp_t respp) -{ - pcibr_soft_slot_t pss; - int func; - bridge_t *bridge = pcibr_soft->bs_base; - reg_p b_respp; - pcibr_slot_info_resp_t slotp; - pcibr_slot_func_info_resp_t funcp; - extern void snia_kmem_free(void *, int); - - slotp = snia_kmem_zalloc(sizeof(*slotp), 0); - if (slotp == NULL) { - return(ENOMEM); - } - - pss = &pcibr_soft->bs_slot[slot]; - - slotp->resp_bs_bridge_mode = pcibr_soft->bs_bridge_mode; - slotp->resp_bs_bridge_type = pcibr_soft->bs_bridge_type; - - slotp->resp_has_host = pss->has_host; - slotp->resp_host_slot = pss->host_slot; -#if defined(SUPPORT_PRINTING_V_FORMAT) - sprintf(slotp->resp_slot_conn_name, "%v", pss->slot_conn); -#else - sprintf(slotp->resp_slot_conn_name, "%p", (void *)pss->slot_conn); -#endif - slotp->resp_slot_status = pss->slot_status; - - slotp->resp_l1_bus_num = pcibr_widget_to_bus(pcibr_soft->bs_vhdl); - slotp->resp_bss_ninfo = pss->bss_ninfo; - - for (func = 0; func < pss->bss_ninfo; func++) { - funcp = &(slotp->resp_func[func]); - pcibr_slot_func_info_return(pss->bss_infos, func, funcp); - } - - sprintf(slotp->resp_bss_devio_bssd_space, "%s", - pci_space_name[pss->bss_devio.bssd_space]); - slotp->resp_bss_devio_bssd_base = pss->bss_devio.bssd_base; - slotp->resp_bss_device = pss->bss_device; - - slotp->resp_bss_pmu_uctr = pss->bss_pmu_uctr; - slotp->resp_bss_d32_uctr = pss->bss_d32_uctr; - slotp->resp_bss_d64_uctr = pss->bss_d64_uctr; - - slotp->resp_bss_d64_base = pss->bss_d64_base; - slotp->resp_bss_d64_flags = pss->bss_d64_flags; - slotp->resp_bss_d32_base = pss->bss_d32_base; - slotp->resp_bss_d32_flags = pss->bss_d32_flags; - - slotp->resp_bss_ext_ates_active = pss->bss_ext_ates_active; - - slotp->resp_bss_cmd_pointer = pss->bss_cmd_pointer; - slotp->resp_bss_cmd_shadow = pss->bss_cmd_shadow; - - slotp->resp_bs_rrb_valid = pcibr_soft->bs_rrb_valid[slot][VCHAN0]; - slotp->resp_bs_rrb_valid_v1 = pcibr_soft->bs_rrb_valid[slot][VCHAN1]; - slotp->resp_bs_rrb_valid_v2 = pcibr_soft->bs_rrb_valid[slot][VCHAN2]; - slotp->resp_bs_rrb_valid_v3 = pcibr_soft->bs_rrb_valid[slot][VCHAN3]; - slotp->resp_bs_rrb_res = pcibr_soft->bs_rrb_res[slot]; - - if (slot & 1) { - b_respp = &bridge->b_odd_resp; - } else { - b_respp = &bridge->b_even_resp; - } - - slotp->resp_b_resp = *b_respp; - - slotp->resp_b_int_device = bridge->b_int_device; - - if (IS_PIC_SOFT(pcibr_soft)) { - slotp->resp_p_int_enable = bridge->p_int_enable_64; - slotp->resp_p_int_host = bridge->p_int_addr_64[slot]; - } else { - slotp->resp_b_int_enable = bridge->b_int_enable; - slotp->resp_b_int_host = bridge->b_int_addr[slot].addr; - } - - if (COPYOUT(slotp, respp, sizeof(*respp))) { - return(EFAULT); - } - - snia_kmem_free(slotp, sizeof(*slotp)); - - return(0); -} - -/* - * pcibr_slot_query - * Return information about the PCI slot maintained by the infrastructure. - * Information is requested in the request structure. - * - * Information returned in the response structure: - * Slot hwgraph name - * Vendor/Device info - * Base register info - * Interrupt mapping from device pins to the bridge pins - * Devio register - * Software RRB info - * RRB register info - * Host/Gues info - * PCI Bus #,slot #, function # - * Slot provider hwgraph name - * Provider Functions - * Error handler - * DMA mapping usage counters - * DMA direct translation info - * External SSRAM workaround info - */ -int -pcibr_slot_query(vertex_hdl_t pcibr_vhdl, pcibr_slot_req_t reqp) -{ - pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); - pciio_slot_t slot; - pciio_slot_t tmp_slot; - pcibr_slot_info_resp_t respp = reqp->req_respp.query; - int size = reqp->req_size; - int error = 0; - - /* Make sure that we are dealing with a bridge device vertex */ - if (!pcibr_soft) { - return(PCI_NOT_A_BRIDGE); - } - - /* req_slot is the 'external' slot number, convert for internal use */ - slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); - - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl, - "pcibr_slot_query: pcibr_soft=0x%x, slot=%d, reqp=0x%x\n", - pcibr_soft, slot, reqp)); - - /* Make sure that we have a valid PCI slot number or PCIIO_SLOT_NONE */ - if ((!PCIBR_VALID_SLOT(pcibr_soft, slot)) && (slot != PCIIO_SLOT_NONE)) { - return(PCI_NOT_A_SLOT); - } - - /* Return information for the requested PCI slot */ - if (slot != PCIIO_SLOT_NONE) { - if (size < sizeof(*respp)) { - return(PCI_RESP_AREA_TOO_SMALL); - } - -#ifdef PIC_LATER - /* Acquire read access to the bus */ - mrlock(pcibr_soft->bs_bus_lock, MR_ACCESS, PZERO); -#endif - error = pcibr_slot_info_return(pcibr_soft, slot, respp); - -#ifdef PIC_LATER - /* Release the bus lock */ - mrunlock(pcibr_soft->bs_bus_lock); -#endif - return(error); - } - - /* Return information for all the slots */ - for (tmp_slot = pcibr_soft->bs_min_slot; - tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); tmp_slot++) { - - if (size < sizeof(*respp)) { - return(PCI_RESP_AREA_TOO_SMALL); - } - -#ifdef PIC_LATER - /* Acquire read access to the bus */ - mrlock(pcibr_soft->bs_bus_lock, MR_ACCESS, PZERO); -#endif - error = pcibr_slot_info_return(pcibr_soft, tmp_slot, respp); - -#ifdef PCI_LATER - /* Release the bus lock */ - mrunlock(pcibr_soft->bs_bus_lock); -#endif - if (error) { - return(error); - } - - ++respp; - size -= sizeof(*respp); - } - - return(error); -} - -#define PROBE_LOCK 0 /* FIXME: we're attempting to lock around accesses - * to b_int_enable. This hangs pcibr_probe_slot() - */ - /* * pcibr_slot_info_init * Probe for this slot and see if it is populated. @@ -553,14 +126,8 @@ pcibr_slot_info_init(vertex_hdl_t pcibr /* Try to read the device-id/vendor-id from the config space */ cfgw = pcibr_slot_config_addr(bridge, slot, 0); -#if PROBE_LOCK - s = pcibr_lock(pcibr_soft); -#endif if (pcibr_probe_slot(bridge, cfgw, &idword)) return(ENODEV); -#if PROBE_LOCK - pcibr_unlock(pcibr_soft, s); -#endif slotp = &pcibr_soft->bs_slot[slot]; slotp->slot_status |= SLOT_POWER_UP; @@ -591,16 +158,10 @@ pcibr_slot_info_init(vertex_hdl_t pcibr if (htype & 0x80) { /* MULTIFUNCTION */ for (func = 1; func < 8; ++func) { cfgw = pcibr_func_config_addr(bridge, 0, slot, func, 0); -#if PROBE_LOCK - s = pcibr_lock(pcibr_soft); -#endif if (pcibr_probe_slot(bridge, cfgw, &idwords[func])) { pfail |= 1 << func; continue; } -#if PROBE_LOCK - pcibr_unlock(pcibr_soft, s); -#endif vendor = 0xFFFF & idwords[func]; if (vendor == 0xFFFF) { pfail |= 1 << func; @@ -611,7 +172,11 @@ pcibr_slot_info_init(vertex_hdl_t pcibr } cfgw = pcibr_slot_config_addr(bridge, slot, 0); } - NEWA(pcibr_infoh, nfunc); + pcibr_infoh = kmalloc(nfunc*sizeof (*(pcibr_infoh)), GFP_KERNEL); + if ( !pcibr_infoh ) { + return ENOMEM; + } + memset(pcibr_infoh, 0, nfunc*sizeof (*(pcibr_infoh))); pcibr_soft->bs_slot[slot].bss_ninfo = nfunc; pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh; @@ -641,39 +206,9 @@ pcibr_slot_info_init(vertex_hdl_t pcibr } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_CONFIG, pcibr_vhdl, - "pcibr_slot_info_init: slot=%d, func=%d, cfgw=0x%x\n", + "pcibr_slot_info_init: slot=%d, func=%d, cfgw=0x%lx\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft,slot), func, cfgw)); -#ifdef PIC_LATER - /* - * Check for a Quad ATM PCI "card" and return all the PCI bus - * memory and I/O space. This will work-around an apparent - * hardware problem with the Quad ATM XIO card handling large - * PIO addresses. Releasing all the space for use by the card - * will lower the PIO addresses with the PCI bus address space. - * This is OK since the PROM did not assign any BAR addresses. - * - * Only release all the PCI bus addresses once. - * - */ - if ((vendor == LINC_VENDOR_ID_NUM) && (device == LINC_DEVICE_ID_NUM)) { - iopaddr_t prom_base_addr = pcibr_soft->bs_xid << 24; - int prom_base_size = 0x1000000; - - if (!(pcibr_soft->bs_bus_addr_status & PCIBR_BUS_ADDR_MEM_FREED)) { - pciio_device_win_populate(&pcibr_soft->bs_mem_win_map, - prom_base_addr, prom_base_size); - pcibr_soft->bs_bus_addr_status |= PCIBR_BUS_ADDR_MEM_FREED; - } - - if (!(pcibr_soft->bs_bus_addr_status & PCIBR_BUS_ADDR_IO_FREED)) { - pciio_device_win_populate(&pcibr_soft->bs_io_win_map, - prom_base_addr, prom_base_size); - pcibr_soft->bs_bus_addr_status |= PCIBR_BUS_ADDR_IO_FREED; - } - } -#endif /* PIC_LATER */ - /* * If the latency timer has already been set, by prom or by the * card itself, use that value. Otherwise look at the device's @@ -745,19 +280,15 @@ pcibr_slot_info_init(vertex_hdl_t pcibr */ if (!(pcix_cap = pcibr_find_capability(cfgw, PCI_CAP_PCIX))) { printk(KERN_WARNING -#if defined(SUPPORT_PRINTING_V_FORMAT) - "%v: Bus running in PCI-X mode, But card in slot %d, " - "func %d not PCI-X capable\n", pcibr_vhdl, slot, func); -#else - "0x%lx: Bus running in PCI-X mode, But card in slot %d, " - "func %d not PCI-X capable\n", (unsigned long)pcibr_vhdl, slot, func); -#endif + "%s: Bus running in PCI-X mode, But card in slot %d, " + "func %d not PCI-X capable\n", + pcibr_soft->bs_name, slot, func); pcibr_device_info_new(pcibr_soft, slot, PCIIO_FUNC_NONE, PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE); continue; } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_CONFIG, pcibr_vhdl, - "pcibr_slot_info_init: PCI-X capability at 0x%x for " + "pcibr_slot_info_init: PCI-X capability at 0x%lx for " "slot=%d, func=%d\n", pcix_cap, PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func)); } else { @@ -957,7 +488,7 @@ pcibr_slot_info_free(vertex_hdl_t pcibr_ pcibr_device_info_free(pcibr_vhdl, slot); pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos; - DELA(pcibr_infoh,nfunc); + kfree(pcibr_infoh); pcibr_soft->bs_slot[slot].bss_ninfo = 0; return(0); @@ -973,7 +504,6 @@ pcibr_slot_pcix_rbar_init(pcibr_soft_t p { pcibr_info_h pcibr_infoh; pcibr_info_t pcibr_info; - char tmp_str[256]; int nfunc; int func; @@ -1047,21 +577,14 @@ pcibr_slot_pcix_rbar_init(pcibr_soft_t p pcibr_soft->bs_pcix_rbar_avail -= num_rbar; pcix_cmdreg_p->max_mem_read_cnt = pcix_statreg_p->max_mem_read_cnt; } - /* - * The kernel only allows functions to have so many variable args, - * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printf - * arguments fails so sprintf() it into a temporary string. - */ - if (pcibr_debug_mask & PCIBR_DEBUG_RBAR) { - sprintf(tmp_str,"\t %d/%d \t %d \t %d \t %d \t %d\n", - PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, - max_splittrans_to_numbuf[pcix_statreg_p->max_out_split], - max_splittrans_to_numbuf[pcix_cmdreg_p->max_split], - pcibr_soft->bs_pcix_rbar_inuse, - pcibr_soft->bs_pcix_rbar_avail); - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RBAR, pcibr_soft->bs_vhdl, - "%s", tmp_str)); - } + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_RBAR, pcibr_soft->bs_vhdl, + "\t %d/%d \t %d \t %d \t %d \t %d\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, + max_splittrans_to_numbuf[pcix_statreg_p->max_out_split], + max_splittrans_to_numbuf[pcix_cmdreg_p->max_split], + pcibr_soft->bs_pcix_rbar_inuse, + pcibr_soft->bs_pcix_rbar_avail)); } return(0); } @@ -1126,8 +649,7 @@ pcibr_slot_addr_space_init(vertex_hdl_t * the entire "lo" area is only a * megabyte, total ... */ - align_slot = 0x100000; - align = align_slot; + align_slot = (slot < 2) ? 0x200000 : 0x100000; for (func = 0; func < nfunc; ++func) { cfg_p cfgw; @@ -1135,9 +657,6 @@ pcibr_slot_addr_space_init(vertex_hdl_t pciio_space_t space; iopaddr_t base; size_t size; -#ifdef PCI_LATER - char tmp_str[256]; -#endif unsigned pci_cfg_cmd_reg; unsigned pci_cfg_cmd_reg_add = 0; @@ -1166,29 +685,21 @@ pcibr_slot_addr_space_init(vertex_hdl_t continue; if (base >= size) { - /* - * The kernel only allows functions to have so many variable - * args attempting to call PCIBR_DEBUG_ALWAYS() with more than - * 5 printf arguments fails so sprintf() it into a temporary - * string (tmp_str). - */ -#if defined(SUPPORT_PRINTING_R_FORMAT) - if (pcibr_debug_mask & PCIBR_DEBUG_BAR) { - sprintf(tmp_str, "pcibr_slot_addr_space_init: slot=%d, " - "func=%d win %d is in %r [0x%x..0x%x], allocated by " - "prom\n", PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), - func, win, space, space_desc, base, base + size - 1); - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, - "%s",tmp_str)); - } -#endif /* SUPPORT_PRINTING_R_FORMAT */ + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, + "pcibr_slot_addr_space_init: slot=%d, " + "func=%d win %d is in space %s [0x%lx..0x%lx], " + "allocated by prom\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, + pci_space[space], (uint64_t)base, + (uint64_t)(base + size - 1))); + continue; /* already allocated */ } align = (win) ? size : align_slot; - if (align < _PAGESZ) - align = _PAGESZ; /* ie. 0x00004000 */ + if (align < PAGE_SIZE) + align = PAGE_SIZE; /* ie. 0x00004000 */ switch (space) { case PCIIO_SPACE_IO: @@ -1232,28 +743,20 @@ pcibr_slot_addr_space_init(vertex_hdl_t pcibr_info->f_window[win].w_base = base; do_pcibr_config_set(wptr, (win * 4), 4, base); -#if defined(SUPPORT_PRINTING_R_FORMAT) - if (pcibr_debug_mask & PCIBR_DEBUG_BAR) { - if (base >= size) { - sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func=" - "%d, win %d is in %r[0x%x..0x%x], " - "allocated by pcibr\n", - PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), - func, win, space, space_desc, base, - base + size - 1); - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, - "%s",tmp_str)); - } - else { - sprintf(tmp_str,"pcibr_slot_addr_space_init: slot=%d, func=" - "%d, win %d, unable to alloc 0x%x in %r\n", - PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), - func, win, size, space, space_desc); - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, - "%s",tmp_str)); - } + if (base >= size) { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, + "pcibr_slot_addr_space_init: slot=%d, func=%d. win %d " + "is in space %s [0x%lx..0x%lx], allocated by pcibr\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, + pci_space[space], (uint64_t)base, + (uint64_t)(base + size - 1))); + } else { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_BAR, pcibr_vhdl, + "pcibr_slot_addr_space_init: slot=%d, func=%d, win %d, " + "unable to alloc 0x%lx in space %s\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, win, + (uint64_t)size, pci_space[space])); } -#endif /* SUPPORT_PRINTING_R_FORMAT */ } /* next base */ /* @@ -1313,11 +816,6 @@ pcibr_slot_addr_space_init(vertex_hdl_t pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER; pci_cfg_cmd_reg = do_pcibr_config_get(cfgw, PCI_CFG_COMMAND, 4); - -#if PCI_FBBE /* XXX- check here to see if dev can do fast-back-to-back */ - if (!((pci_cfg_cmd_reg >> 16) & PCI_STAT_F_BK_BK_CAP)) - fast_back_to_back_enable = 0; -#endif pci_cfg_cmd_reg &= 0xFFFF; if (pci_cfg_cmd_reg_add & ~pci_cfg_cmd_reg) do_pcibr_config_set(cfgw, PCI_CFG_COMMAND, 4, @@ -1363,18 +861,12 @@ pcibr_slot_device_init(vertex_hdl_t pcib * for 64-bit devices). We set the bit in pcibr_try_set_device() * if we're 64-bit and requesting virtual channels. */ - if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) + if (PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) devreg |= BRIDGE_DEV_COH; else devreg |= BRIDGE_DEV_COH | BRIDGE_DEV_VIRTUAL_EN; pcibr_soft->bs_slot[slot].bss_device = devreg; bridge->b_device[slot].reg = devreg; - -#ifdef PIC_LATER - PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pcibr_vhdl, - "pcibr_slot_device_init: Device(%d): %R\n", - slot, devreg, device_bits)); -#endif return(0); } @@ -1407,7 +899,12 @@ pcibr_slot_guest_info_init(vertex_hdl_t * build verticies for them). */ if (pcibr_soft->bs_slot[slot].bss_ninfo < 1) { - NEWA(pcibr_infoh, 1); + pcibr_infoh = kmalloc(sizeof (*(pcibr_infoh)), GFP_KERNEL); + if ( !pcibr_infoh ) { + return ENOMEM; + } + memset(pcibr_infoh, 0, sizeof (*(pcibr_infoh))); + pcibr_soft->bs_slot[slot].bss_ninfo = 1; pcibr_soft->bs_slot[slot].bss_infos = pcibr_infoh; @@ -1461,16 +958,10 @@ pcibr_slot_call_device_attach(vertex_hdl pcibr_info_t pcibr_info; int func; vertex_hdl_t xconn_vhdl, conn_vhdl; -#ifdef PIC_LATER - vertex_hdl_t scsi_vhdl; -#endif int nfunc; int error_func; int error_slot = 0; int error = ENODEV; -#ifdef PIC_LATER - int hwg_err; -#endif pcibr_soft = pcibr_soft_get(pcibr_vhdl); @@ -1501,43 +992,13 @@ pcibr_slot_call_device_attach(vertex_hdl conn_vhdl = pcibr_info->f_vertex; - error_func = pciio_device_attach(conn_vhdl, drv_flags); -#ifdef PIC_LATER - /* - * Try to assign well-known SCSI controller numbers for hot-plug - * insert - */ - if (drv_flags) { - - hwg_err = hwgraph_path_lookup(conn_vhdl, EDGE_LBL_SCSI_CTLR "/0", - &scsi_vhdl, NULL); - - if (hwg_err == GRAPH_SUCCESS) - scsi_ctlr_nums_add(baseio_pci_vhdl, scsi_vhdl); - - /* scsi_vhdl will be the final vertex in either the complete path - * on success or a partial path on failure; in either case, - * unreference that vertex. - */ - hwgraph_vertex_unref(scsi_vhdl); - - hwg_err = hwgraph_path_lookup(conn_vhdl, EDGE_LBL_SCSI_CTLR "/1", - &scsi_vhdl, NULL); - - if (hwg_err == GRAPH_SUCCESS) - scsi_ctlr_nums_add(baseio_pci_vhdl, scsi_vhdl); - - /* scsi_vhdl will be the final vertex in either the complete path - * on success or a partial path on failure; in either case, - * unreference that vertex. - */ - hwgraph_vertex_unref(scsi_vhdl); - - } -#endif /* PIC_LATER */ - + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEV_ATTACH, pcibr_vhdl, + "pcibr_slot_call_device_attach: slot=%d, func=%d " + "drv_flags=0x%x, pciio_device_attach returned %d\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, + drv_flags, error_func)); pcibr_info->f_att_det_error = error_func; if (error_func) @@ -1616,6 +1077,12 @@ pcibr_slot_call_device_detach(vertex_hdl error_func = pciio_device_detach(conn_vhdl, drv_flags); + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEV_DETACH, pcibr_vhdl, + "pcibr_slot_call_device_detach: slot=%d, func=%d " + "drv_flags=0x%x, pciio_device_detach returned %d\n", + PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot), func, + drv_flags, error_func)); + pcibr_info->f_att_det_error = error_func; if (error_func) @@ -1656,9 +1123,6 @@ pcibr_slot_attach(vertex_hdl_t pcibr_vhd int *sub_errorp) { pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); -#ifdef PIC_LATER - timespec_t ts; -#endif int error; /* Do not allow a multi-function card to be hot-plug inserted */ @@ -1739,7 +1203,7 @@ pcibr_probe_slot_pic(bridge_t *bridge, { int rv; picreg_t p_old_enable = (picreg_t)0, p_new_enable; - extern int badaddr_val(volatile void *, int, volatile void *); + extern int snia_badaddr_val(volatile void *, int, volatile void *); p_old_enable = bridge->p_int_enable_64; p_new_enable = p_old_enable & ~(BRIDGE_IMR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT); @@ -1752,7 +1216,7 @@ pcibr_probe_slot_pic(bridge_t *bridge, bridge->p_int_rst_stat_64 = (BRIDGE_IRR_PCI_GRP_CLR | PIC_PCIX_GRP_CLR); (void) bridge->b_wid_tflush; /* flushbus */ } - rv = badaddr_val((void *) cfg, 4, valp); + rv = snia_badaddr_val((void *) cfg, 4, valp); if (bridge->p_err_int_view_64 & (BRIDGE_ISR_PCI_MST_TIMEOUT | PIC_ISR_PCIX_MTOUT)) { bridge->p_int_rst_stat_64 = BRIDGE_IRR_MULTI_CLR; rv = 1; /* unoccupied slot */ @@ -1790,7 +1254,7 @@ pcibr_device_info_free(vertex_hdl_t pcib int nfunc = slotp->bss_ninfo; int bar; int devio_index; - int s; + unsigned long s; unsigned cmd_reg; @@ -1840,7 +1304,7 @@ pcibr_device_info_free(vertex_hdl_t pcib pciio_device_info_unregister(pcibr_vhdl, &pcibr_info->f_c); pciio_device_info_free(&pcibr_info->f_c); - DEL(pcibr_info); + kfree(pcibr_info); } /* Reset the mapping usage counters */ diff -puN arch/ia64/sn/io/sn2/pciio.c~linus arch/ia64/sn/io/sn2/pciio.c --- 25/arch/ia64/sn/io/sn2/pciio.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pciio.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -7,115 +6,11 @@ * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* Must be before iograph.h to get MAX_PORT_NUM */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#define DEBUG_PCIIO -#undef DEBUG_PCIIO /* turn this on for yet more console output */ - - char pciio_info_fingerprint[] = "pciio_info"; -int -badaddr_val(volatile void *addr, int len, volatile void *ptr) -{ - int ret = 0; - volatile void *new_addr; - - switch (len) { - case 4: - new_addr = (void *) addr; - ret = ia64_sn_probe_io_slot((long)new_addr, len, (void *)ptr); - break; - default: - printk(KERN_WARNING "badaddr_val given len %x but supports len of 4 only\n", len); - } - - if (ret < 0) - panic("badaddr_val: unexpected status (%d) in probing", ret); - return(ret); - -} - - -nasid_t -get_console_nasid(void) -{ - extern nasid_t console_nasid; - extern nasid_t master_baseio_nasid; - - if (console_nasid < 0) { - console_nasid = ia64_sn_get_console_nasid(); - if (console_nasid < 0) { -// ZZZ What do we do if we don't get a console nasid on the hardware???? - if (IS_RUNNING_ON_SIMULATOR() ) - console_nasid = master_baseio_nasid; - } - } - return console_nasid; -} - -nasid_t -get_master_baseio_nasid(void) -{ - extern nasid_t master_baseio_nasid; - extern char master_baseio_wid; - - if (master_baseio_nasid < 0) { - master_baseio_nasid = ia64_sn_get_master_baseio_nasid(); - - if ( master_baseio_nasid >= 0 ) { - master_baseio_wid = WIDGETID_GET(KL_CONFIG_CH_CONS_INFO(master_baseio_nasid)->memory_base); - } - } - return master_baseio_nasid; -} - -int -hub_dma_enabled(vertex_hdl_t xconn_vhdl) -{ - return(0); -} - -int -hub_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code) -{ - return(0); -} - -void -ioerror_dump(char *name, int error_code, int error_mode, ioerror_t *ioerror) -{ -} - -/****** - ****** end hack defines ...... - ******/ - - - - /* ===================================================================== * PCI Generic Bus Provider * Implement PCI provider operations. The pciio* layer provides a @@ -124,111 +19,6 @@ ioerror_dump(char *name, int error_code, */ /* ===================================================================== - * Provider Function Location SHORTCUT - * - * On platforms with only one possible PCI provider, macros can be - * set up at the top that cause the table lookups and indirections to - * completely disappear. - */ - - -/* ===================================================================== - * Function Table of Contents - */ - -#if !defined(DEV_FUNC) -static pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev); -#endif - -pciio_piomap_t pciio_piomap_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned); -void pciio_piomap_free(pciio_piomap_t); -caddr_t pciio_piomap_addr(pciio_piomap_t, iopaddr_t, size_t); - -void pciio_piomap_done(pciio_piomap_t); -caddr_t pciio_piotrans_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); -caddr_t pciio_pio_addr(vertex_hdl_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); - -iopaddr_t pciio_piospace_alloc(vertex_hdl_t, device_desc_t, pciio_space_t, size_t, size_t); -void pciio_piospace_free(vertex_hdl_t, pciio_space_t, iopaddr_t, size_t); - -pciio_dmamap_t pciio_dmamap_alloc(vertex_hdl_t, device_desc_t, size_t, unsigned); -void pciio_dmamap_free(pciio_dmamap_t); -iopaddr_t pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); -void pciio_dmamap_done(pciio_dmamap_t); -iopaddr_t pciio_dmatrans_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, unsigned); -void pciio_dmamap_drain(pciio_dmamap_t); -void pciio_dmaaddr_drain(vertex_hdl_t, paddr_t, size_t); -void pciio_dmalist_drain(vertex_hdl_t, alenlist_t); -iopaddr_t pciio_dma_addr(vertex_hdl_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); - -pciio_intr_t pciio_intr_alloc(vertex_hdl_t, device_desc_t, pciio_intr_line_t, vertex_hdl_t); -void pciio_intr_free(pciio_intr_t); -int pciio_intr_connect(pciio_intr_t, intr_func_t, intr_arg_t); -void pciio_intr_disconnect(pciio_intr_t); -vertex_hdl_t pciio_intr_cpu_get(pciio_intr_t); - -void pciio_slot_func_to_name(char *, pciio_slot_t, pciio_function_t); - -void pciio_provider_startup(vertex_hdl_t); -void pciio_provider_shutdown(vertex_hdl_t); - -pciio_endian_t pciio_endian_set(vertex_hdl_t, pciio_endian_t, pciio_endian_t); -pciio_priority_t pciio_priority_set(vertex_hdl_t, pciio_priority_t); -vertex_hdl_t pciio_intr_dev_get(pciio_intr_t); - -vertex_hdl_t pciio_pio_dev_get(pciio_piomap_t); -pciio_slot_t pciio_pio_slot_get(pciio_piomap_t); -pciio_space_t pciio_pio_space_get(pciio_piomap_t); -iopaddr_t pciio_pio_pciaddr_get(pciio_piomap_t); -ulong pciio_pio_mapsz_get(pciio_piomap_t); -caddr_t pciio_pio_kvaddr_get(pciio_piomap_t); - -vertex_hdl_t pciio_dma_dev_get(pciio_dmamap_t); -pciio_slot_t pciio_dma_slot_get(pciio_dmamap_t); - -pciio_info_t pciio_info_chk(vertex_hdl_t); -pciio_info_t pciio_info_get(vertex_hdl_t); -void pciio_info_set(vertex_hdl_t, pciio_info_t); -vertex_hdl_t pciio_info_dev_get(pciio_info_t); -pciio_slot_t pciio_info_slot_get(pciio_info_t); -pciio_function_t pciio_info_function_get(pciio_info_t); -pciio_vendor_id_t pciio_info_vendor_id_get(pciio_info_t); -pciio_device_id_t pciio_info_device_id_get(pciio_info_t); -vertex_hdl_t pciio_info_master_get(pciio_info_t); -arbitrary_info_t pciio_info_mfast_get(pciio_info_t); -pciio_provider_t *pciio_info_pops_get(pciio_info_t); -error_handler_f *pciio_info_efunc_get(pciio_info_t); -error_handler_arg_t *pciio_info_einfo_get(pciio_info_t); -pciio_space_t pciio_info_bar_space_get(pciio_info_t, int); -iopaddr_t pciio_info_bar_base_get(pciio_info_t, int); -size_t pciio_info_bar_size_get(pciio_info_t, int); -iopaddr_t pciio_info_rom_base_get(pciio_info_t); -size_t pciio_info_rom_size_get(pciio_info_t); - -int pciio_attach(vertex_hdl_t); - -void pciio_provider_register(vertex_hdl_t, pciio_provider_t *pciio_fns); -void pciio_provider_unregister(vertex_hdl_t); -pciio_provider_t *pciio_provider_fns_get(vertex_hdl_t); - -int pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned); - -vertex_hdl_t pciio_device_register(vertex_hdl_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); - -void pciio_device_unregister(vertex_hdl_t); -pciio_info_t pciio_device_info_new(pciio_info_t, vertex_hdl_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); -void pciio_device_info_free(pciio_info_t); -vertex_hdl_t pciio_device_info_register(vertex_hdl_t, pciio_info_t); -void pciio_device_info_unregister(vertex_hdl_t, pciio_info_t); -int pciio_device_attach(vertex_hdl_t, int); -int pciio_device_detach(vertex_hdl_t, int); -void pciio_error_register(vertex_hdl_t, error_handler_f *, error_handler_arg_t); - -int pciio_reset(vertex_hdl_t); -int pciio_write_gather_flush(vertex_hdl_t); -int pciio_slot_inuse(vertex_hdl_t); - -/* ===================================================================== * Provider Function Location * * If there is more than one possible provider for @@ -238,9 +28,7 @@ int pciio_slot_inuse * appropriately named member. */ -#if !defined(DEV_FUNC) - -static pciio_provider_t * +pciio_provider_t * pciio_to_provider_fns(vertex_hdl_t dev) { pciio_info_t card_info; @@ -261,13 +49,10 @@ pciio_to_provider_fns(vertex_hdl_t dev) } } - if (provider_fns == NULL) -#if defined(SUPPORT_PRINTING_V_FORMAT) - PRINT_PANIC("%v: provider_fns == NULL", dev); -#else - PRINT_PANIC("0x%p: provider_fns == NULL", (void *)dev); -#endif - + if (provider_fns == NULL) { + char devname[MAXDEVNAME]; + panic("%s: provider_fns == NULL", vertex_to_name(dev, devname, MAXDEVNAME)); + } return provider_fns; } @@ -276,7 +61,6 @@ pciio_to_provider_fns(vertex_hdl_t dev) #define CAST_PIOMAP(x) ((pciio_piomap_t)(x)) #define CAST_DMAMAP(x) ((pciio_dmamap_t)(x)) #define CAST_INTR(x) ((pciio_intr_t)(x)) -#endif /* * Many functions are not passed their vertex @@ -396,8 +180,8 @@ pciio_piospace_alloc(vertex_hdl_t dev, / size_t byte_count, /* Size of mapping */ size_t align) { /* Alignment needed */ - if (align < NBPP) - align = NBPP; + if (align < PAGE_SIZE) + align = PAGE_SIZE; return DEV_FUNC(dev, piospace_alloc) (dev, dev_desc, space, byte_count, align); } @@ -753,50 +537,6 @@ pciio_provider_shutdown(vertex_hdl_t pci } /* - * Specify endianness constraints. The driver tells us what the device - * does and how it would like to see things in memory. We reply with - * how things will actually appear in memory. - */ -pciio_endian_t -pciio_endian_set(vertex_hdl_t dev, - pciio_endian_t device_end, - pciio_endian_t desired_end) -{ - ASSERT((device_end == PCIDMA_ENDIAN_BIG) || (device_end == PCIDMA_ENDIAN_LITTLE)); - ASSERT((desired_end == PCIDMA_ENDIAN_BIG) || (desired_end == PCIDMA_ENDIAN_LITTLE)); - -#if DEBUG -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_ALERT "%v: pciio_endian_set is going away.\n" - "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n" - "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n", - dev); -#else - printk(KERN_ALERT "0x%x: pciio_endian_set is going away.\n" - "\tplease use PCIIO_BYTE_STREAM or PCIIO_WORD_VALUES in your\n" - "\tpciio_dmamap_alloc and pciio_dmatrans calls instead.\n", - dev); -#endif -#endif - - return DEV_FUNC(dev, endian_set) - (dev, device_end, desired_end); -} - -/* - * Specify PCI arbitration priority. - */ -pciio_priority_t -pciio_priority_set(vertex_hdl_t dev, - pciio_priority_t device_prio) -{ - ASSERT((device_prio == PCI_PRIO_HIGH) || (device_prio == PCI_PRIO_LOW)); - - return DEV_FUNC(dev, priority_set) - (dev, device_prio); -} - -/* * Read value of configuration register */ uint64_t @@ -865,71 +605,6 @@ pciio_reset(vertex_hdl_t dev) return DEV_FUNC(dev, reset) (dev); } -/* - * flush write gather buffers - */ -int -pciio_write_gather_flush(vertex_hdl_t dev) -{ - return DEV_FUNC(dev, write_gather_flush) (dev); -} - -vertex_hdl_t -pciio_intr_dev_get(pciio_intr_t pciio_intr) -{ - return (pciio_intr->pi_dev); -} - -/****** Generic crosstalk pio interfaces ******/ -vertex_hdl_t -pciio_pio_dev_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_dev); -} - -pciio_slot_t -pciio_pio_slot_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_slot); -} - -pciio_space_t -pciio_pio_space_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_space); -} - -iopaddr_t -pciio_pio_pciaddr_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_pciaddr); -} - -ulong -pciio_pio_mapsz_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_mapsz); -} - -caddr_t -pciio_pio_kvaddr_get(pciio_piomap_t pciio_piomap) -{ - return (pciio_piomap->pp_kvaddr); -} - -/****** Generic crosstalk dma interfaces ******/ -vertex_hdl_t -pciio_dma_dev_get(pciio_dmamap_t pciio_dmamap) -{ - return (pciio_dmamap->pd_dev); -} - -pciio_slot_t -pciio_dma_slot_get(pciio_dmamap_t pciio_dmamap) -{ - return (pciio_dmamap->pd_slot); -} - /****** Generic pci slot information interfaces ******/ pciio_info_t @@ -979,6 +654,13 @@ pciio_info_dev_get(pciio_info_t pciio_in return (pciio_info->c_vertex); } +/*ARGSUSED*/ +pciio_bus_t +pciio_info_bus_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_bus); +} + pciio_slot_t pciio_info_slot_get(pciio_info_t pciio_info) { @@ -1021,49 +703,30 @@ pciio_info_pops_get(pciio_info_t pciio_i return (pciio_info->c_pops); } -error_handler_f * -pciio_info_efunc_get(pciio_info_t pciio_info) -{ - return (pciio_info->c_efunc); -} - -error_handler_arg_t * -pciio_info_einfo_get(pciio_info_t pciio_info) -{ - return (pciio_info->c_einfo); -} - -pciio_space_t -pciio_info_bar_space_get(pciio_info_t info, int win) -{ - return info->c_window[win].w_space; -} - -iopaddr_t -pciio_info_bar_base_get(pciio_info_t info, int win) +int +pciio_businfo_multi_master_get(pciio_businfo_t businfo) { - return info->c_window[win].w_base; + return businfo->bi_multi_master; } -size_t -pciio_info_bar_size_get(pciio_info_t info, int win) +pciio_asic_type_t +pciio_businfo_asic_type_get(pciio_businfo_t businfo) { - return info->c_window[win].w_size; + return businfo->bi_asic_type; } -iopaddr_t -pciio_info_rom_base_get(pciio_info_t info) +pciio_bus_type_t +pciio_businfo_bus_type_get(pciio_businfo_t businfo) { - return info->c_rbase; + return businfo->bi_bus_type; } -size_t -pciio_info_rom_size_get(pciio_info_t info) +pciio_bus_speed_t +pciio_businfo_bus_speed_get(pciio_businfo_t businfo) { - return info->c_rsize; + return businfo->bi_bus_speed; } - /* ===================================================================== * GENERIC PCI INITIALIZATION FUNCTIONS */ @@ -1077,11 +740,8 @@ int pciio_attach(vertex_hdl_t pciio) { #if DEBUG && ATTACH_DEBUG -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk("%v: pciio_attach\n", pciio); -#else - printk("0x%x: pciio_attach\n", pciio); -#endif + char devname[MAXDEVNAME]; + printk("%s: pciio_attach\n", vertex_to_name(pciio, devname, MAXDEVNAME)); #endif return 0; } @@ -1119,37 +779,6 @@ pciio_provider_fns_get(vertex_hdl_t prov return (pciio_provider_t *) ainfo; } -/*ARGSUSED4 */ -int -pciio_driver_register( - pciio_vendor_id_t vendor_id, - pciio_device_id_t device_id, - char *driver_prefix, - unsigned flags) -{ - return(0); -} - -vertex_hdl_t -pciio_device_register( - vertex_hdl_t connectpt, /* vertex for /hw/.../pciio/%d */ - vertex_hdl_t master, /* card's master ASIC (PCI provider) */ - pciio_slot_t slot, /* card's slot */ - pciio_function_t func, /* card's func */ - pciio_vendor_id_t vendor_id, - pciio_device_id_t device_id) -{ - return pciio_device_info_register - (connectpt, pciio_device_info_new (NULL, master, slot, func, - vendor_id, device_id)); -} - -void -pciio_device_unregister(vertex_hdl_t pconn) -{ - DEV_FUNC(pconn,device_unregister)(pconn); -} - pciio_info_t pciio_device_info_new( pciio_info_t pciio_info, @@ -1159,8 +788,11 @@ pciio_device_info_new( pciio_vendor_id_t vendor_id, pciio_device_id_t device_id) { - if (!pciio_info) - NEW(pciio_info); + if (!pciio_info) { + pciio_info = kmalloc(sizeof (*(pciio_info)), GFP_KERNEL); + if ( pciio_info ) + memset(pciio_info, 0, sizeof (*(pciio_info))); + } ASSERT(pciio_info != NULL); pciio_info->c_slot = slot; @@ -1182,7 +814,7 @@ pciio_device_info_free(pciio_info_t pcii /* NOTE : pciio_info is a structure within the pcibr_info * and not a pointer to memory allocated on the heap !! */ - BZERO((char *)pciio_info,sizeof(pciio_info)); + memset((char *)pciio_info, 0, sizeof(pciio_info)); } vertex_hdl_t @@ -1293,14 +925,26 @@ pciio_device_win_alloc(struct resource * { struct resource *new_res; - int status = 0; - - new_res = (struct resource *) kmalloc( sizeof(struct resource), KM_NOSLEEP); + int status; - status = allocate_resource( root_resource, new_res, + new_res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL); + if (!new_res) + return 0; + + if (start > 0) { + status = allocate_resource( root_resource, new_res, + size, start /* Min start addr. */, + (start + size) - 1, 1, + NULL, NULL); + } else { + if (size > align) + align = size; + status = allocate_resource( root_resource, new_res, size, align /* Min start addr. */, root_resource->end, align, NULL, NULL); + } + if (status) { kfree(new_res); return((iopaddr_t) NULL); @@ -1326,8 +970,7 @@ pciio_device_win_alloc(struct resource * void pciio_device_win_free(pciio_win_alloc_t win_alloc) { - - int status = 0; + int status; if (win_alloc->wa_resource) { status = release_resource(win_alloc->wa_resource); @@ -1389,47 +1032,16 @@ pciio_slot_inuse(vertex_hdl_t pconn_vhdl } int -pciio_dma_enabled(vertex_hdl_t pconn_vhdl) -{ - return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl); -} - -int pciio_info_type1_get(pciio_info_t pci_info) { - return(0); + return (pci_info->c_type1); } -/* - * XXX: should probably be called __sn2_pci_rrb_alloc - */ -/* used by qla1280 */ -int -snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, - int *count_vchan0, - int *count_vchan1) +pciio_businfo_t +pciio_businfo_get(vertex_hdl_t conn) { - vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); + pciio_info_t info; - return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1); -} -EXPORT_SYMBOL(snia_pcibr_rrb_alloc); - -/* - * XXX: interface should be more like - * - * int __sn2_pci_enable_bwswap(struct pci_dev *dev); - * void __sn2_pci_disable_bswap(struct pci_dev *dev); - */ -/* used by ioc4 ide */ -pciio_endian_t -snia_pciio_endian_set(struct pci_dev *pci_dev, - pciio_endian_t device_end, - pciio_endian_t desired_end) -{ - vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); - - return DEV_FUNC(dev, endian_set) - (dev, device_end, desired_end); + info = pciio_info_get(conn); + return DEV_FUNC(conn, businfo_get)(conn); } -EXPORT_SYMBOL(snia_pciio_endian_set); diff -puN arch/ia64/sn/io/sn2/pic.c~linus arch/ia64/sn/io/sn2/pic.c --- 25/arch/ia64/sn/io/sn2/pic.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/pic.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -7,26 +6,15 @@ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. */ -#include -#include -#include -#include +#include #include -#include -#include #include -#include -#include -#include -#include -#include +#include #include #include #include #include -#include -#include -#include +#include #include @@ -38,34 +26,9 @@ extern void pcibr_driver_unreg_callback( /* - * copy inventory_t from conn_v to peer_conn_v - */ -int -pic_bus1_inventory_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v) -{ - inventory_t *pinv, *peer_pinv; - - if (hwgraph_info_get_LBL(conn_v, INFO_LBL_INVENT, - (arbitrary_info_t *)&pinv) == GRAPH_SUCCESS) - { - NEW(peer_pinv); - memcpy(peer_pinv, pinv, sizeof(inventory_t)); - if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_INVENT, - (arbitrary_info_t)peer_pinv) != GRAPH_SUCCESS) { - DEL(peer_pinv); - return 0; - } - return 1; - } - - printk("pic_bus1_inventory_dup: cannot get INFO_LBL_INVENT from 0x%lx\n ", (uint64_t)conn_v); - return 0; -} - -/* * copy xwidget_info_t from conn_v to peer_conn_v */ -int +static int pic_bus1_widget_info_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v, cnodeid_t xbow_peer) { @@ -83,21 +46,27 @@ pic_bus1_widget_info_dup(vertex_hdl_t co if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) { - NEW(peer_widget_info); - peer_widget_info->w_vertex = peer_conn_v; - peer_widget_info->w_id = widget_info->w_id; - peer_widget_info->w_master = peer_hubv; - peer_widget_info->w_masterid = peer_hub_info->h_widgetid; + peer_widget_info = kmalloc(sizeof (*(peer_widget_info)), GFP_KERNEL); + if ( !peer_widget_info ) { + return 0; + } + memset(peer_widget_info, 0, sizeof (*(peer_widget_info))); + + peer_widget_info->w_fingerprint = widget_info_fingerprint; + peer_widget_info->w_vertex = peer_conn_v; + peer_widget_info->w_id = widget_info->w_id; + peer_widget_info->w_master = peer_hubv; + peer_widget_info->w_masterid = peer_hub_info->h_widgetid; /* structure copy */ - peer_widget_info->w_hwid = widget_info->w_hwid; - peer_widget_info->w_efunc = 0; - peer_widget_info->w_einfo = 0; + peer_widget_info->w_hwid = widget_info->w_hwid; + peer_widget_info->w_efunc = 0; + peer_widget_info->w_einfo = 0; peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); strcpy(peer_widget_info->w_name, peer_path); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { - DEL(peer_widget_info); + kfree(peer_widget_info); return 0; } @@ -119,7 +88,7 @@ pic_bus1_widget_info_dup(vertex_hdl_t co * If not successful, return zero and both buses will attach to the * vertex passed into pic_attach(). */ -vertex_hdl_t +static vertex_hdl_t pic_bus1_redist(nasid_t nasid, vertex_hdl_t conn_v) { cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); @@ -172,11 +141,6 @@ pic_bus1_redist(nasid_t nasid, vertex_hd * vertex but that should be safe and we don't * really expect the additions to fail anyway. */ -#if 0 - if (!pic_bus1_inventory_dup(conn_v, peer_conn_v)) - return 0; - pic_bus1_device_desc_dup(conn_v, peer_conn_v); -#endif if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, xbow_peer)) return 0; @@ -196,6 +160,8 @@ pic_attach(vertex_hdl_t conn_v) vertex_hdl_t pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0; pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; vertex_hdl_t conn_v0, conn_v1, peer_conn_v; + int bricktype; + int iobrick_type_get_nasid(nasid_t nasid); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); @@ -204,13 +170,14 @@ pic_attach(vertex_hdl_t conn_v) bridge1 = (bridge_t *)((char *)bridge0 + PIC_BUS1_OFFSET); PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, - "pic_attach: bridge0=0x%x, bridge1=0x%x\n", + "pic_attach: bridge0=0x%lx, bridge1=0x%lx\n", bridge0, bridge1)); conn_v0 = conn_v1 = conn_v; /* If dual-ported then split the two PIC buses across both Cbricks */ - if ((peer_conn_v = (pic_bus1_redist(NASID_GET(bridge0), conn_v)))) + peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v); + if (peer_conn_v) conn_v1 = peer_conn_v; /* @@ -224,14 +191,21 @@ pic_attach(vertex_hdl_t conn_v) * Opening this vertex will provide access to * the Bridge registers themselves. */ - /* FIXME: what should the hwgraph path look like ? */ - rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); - ASSERT(rc == GRAPH_SUCCESS); - rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); - ASSERT(rc == GRAPH_SUCCESS); + bricktype = iobrick_type_get_nasid(NASID_GET(bridge0)); + if ( bricktype == MODULE_CGBRICK ) { + rc = hwgraph_path_add(conn_v0, EDGE_LBL_AGP_0, &pcibr_vhdl0); + ASSERT(rc == GRAPH_SUCCESS); + rc = hwgraph_path_add(conn_v1, EDGE_LBL_AGP_1, &pcibr_vhdl1); + ASSERT(rc == GRAPH_SUCCESS); + } else { + rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0); + ASSERT(rc == GRAPH_SUCCESS); + rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1); + ASSERT(rc == GRAPH_SUCCESS); + } PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, - "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n", + "pic_attach: pcibr_vhdl0=0x%lx, pcibr_vhdl1=0x%lx\n", pcibr_vhdl0, pcibr_vhdl1)); /* register pci provider array */ @@ -249,7 +223,7 @@ pic_attach(vertex_hdl_t conn_v) bus1_soft->bs_peers_soft = bus0_soft; PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, - "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n", + "pic_attach: bus0_soft=0x%lx, bus1_soft=0x%lx\n", bus0_soft, bus1_soft)); return 0; @@ -294,10 +268,8 @@ pciio_provider_t pci_pic_provider (pciio_priority_set_f *) pcibr_priority_set, (pciio_config_get_f *) pcibr_config_get, (pciio_config_set_f *) pcibr_config_set, - (pciio_error_devenable_f *) 0, (pciio_error_extract_f *) 0, (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback, (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback, (pciio_device_unregister_f *) pcibr_device_unregister, - (pciio_dma_enabled_f *) pcibr_dma_enabled, }; diff -puN arch/ia64/sn/io/sn2/shub.c~linus arch/ia64/sn/io/sn2/shub.c --- 25/arch/ia64/sn/io/sn2/shub.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/shub.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -7,18 +6,18 @@ * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All Rights Reserved. */ -#ident "$Revision: 1.167 $" - #include #include #include +#include +#include #include #include #include #include #include +#include #include -#include #include #include #include @@ -30,49 +29,12 @@ #include #include #include +#include #include #include #include #include #include -#include - -/* - * Shub WAR for Xbridge Little Endian problem: - * Xbridge has to run in BIG ENDIAN even with Shub. - */ - - -/* - * io_sh_swapper: Turn on Shub byte swapping. - * All data destined to and from Shub to XIO are byte-swapped. - */ -void -io_sh_swapper(nasid_t nasid, int onoff) -{ - ii_iwc_u_t ii_iwc; - - ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); - - ii_iwc.ii_iwc_fld_s.i_dma_byte_swap = onoff; - REMOTE_HUB_S(nasid, IIO_IWC, ii_iwc.ii_iwc_regval); - ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); - -} - -/* - * io_get_sh_swapper: Return current Swap mode. - * 1 = Swap on, 0 = Swap off. - */ -int -io_get_sh_swapper(nasid_t nasid) -{ - ii_iwc_u_t ii_iwc; - - ii_iwc.ii_iwc_regval = REMOTE_HUB_L(nasid, IIO_IWC); - return(ii_iwc.ii_iwc_fld_s.i_dma_byte_swap); - -} #define SHUB_NUM_ECF_REGISTERS 8 @@ -204,6 +166,8 @@ shubstats_ioctl(struct inode *inode, str int nasid; cnode = (cnodeid_t)file->f_dentry->d_fsdata; + if (cnode < 0 || cnode >= numnodes) + return -ENODEV; switch (cmd) { case SNDRV_SHUB_CONFIGURE: diff -puN arch/ia64/sn/io/sn2/shuberror.c~linus arch/ia64/sn/io/sn2/shuberror.c --- 25/arch/ia64/sn/io/sn2/shuberror.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/shuberror.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id: shuberror.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $ - * +/* * 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. @@ -17,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +29,7 @@ #include #include #include +#include #include extern void hubni_eint_init(cnodeid_t cnode); @@ -173,7 +172,6 @@ hubii_eint_handler (int irq, void *arg, hubinfo_t hinfo; ii_wstat_u_t wstat; hubreg_t idsr; - ii_ilcsr_u_t ilcsr; /* two levels of casting avoids compiler warning.!! */ @@ -228,11 +226,9 @@ hubii_eint_handler (int irq, void *arg, } /* - * Note: we may never be able to print this, if the II talking - * to Xbow which hosts the console is dead. + * Only print the II_ECRAZY message if there is an attached xbow. */ - ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR); - if (ilcsr.ii_ilcsr_fld_s.i_llp_en == 1) { /* Link is enabled */ + if (NODEPDA(hinfo->h_cnodeid)->xbow_vhdl != 0) { printk("Hub %d, cnode %d to Xtalk Link failed (II_ECRAZY) Reason: %s", hinfo->h_nasid, hinfo->h_cnodeid, reason); } @@ -299,7 +295,7 @@ hubiio_crb_free(hubinfo_t hinfo, int crb * Wait till hub indicates it's done. */ while (REMOTE_HUB_L(hinfo->h_nasid, IIO_ICDR) & IIO_ICDR_PND) - us_delay(1); + udelay(1); } diff -puN arch/ia64/sn/io/sn2/shub_intr.c~linus arch/ia64/sn/io/sn2/shub_intr.c --- 25/arch/ia64/sn/io/sn2/shub_intr.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/shub_intr.c 2004-01-19 22:17:21.000000000 -0800 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -26,6 +25,8 @@ #include #include #include +#include +#include /* ARGSUSED */ void @@ -36,11 +37,15 @@ hub_intr_init(vertex_hdl_t hubv) xwidgetnum_t hub_widget_id(nasid_t nasid) { - hubii_wcr_t ii_wcr; /* the control status register */ - - ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR); - - return ii_wcr.wcr_fields_s.wcr_widget_id; + + if (!(nasid & 1)) { + hubii_wcr_t ii_wcr; /* the control status register */ + ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR); + return ii_wcr.wcr_fields_s.wcr_widget_id; + } else { + /* ICE does not have widget id. */ + return(-1); + } } static hub_intr_t @@ -49,7 +54,7 @@ do_hub_intr_alloc(vertex_hdl_t dev, vertex_hdl_t owner_dev, int uncond_nothread) { - cpuid_t cpu = 0; + cpuid_t cpu; int vector; hub_intr_t intr_hdl; cnodeid_t cnode; @@ -58,7 +63,6 @@ do_hub_intr_alloc(vertex_hdl_t dev, iopaddr_t xtalk_addr; struct xtalk_intr_s *xtalk_info; xwidget_info_t xwidget_info; - ilvl_t intr_swlevel = 0; cpu = intr_heuristic(dev, -1, &vector); if (cpu == CPU_NONE) { @@ -77,8 +81,9 @@ do_hub_intr_alloc(vertex_hdl_t dev, xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47); } - intr_hdl = snia_kmem_alloc_node(sizeof(struct hub_intr_s), KM_NOSLEEP, cnode); + intr_hdl = kmalloc(sizeof(struct hub_intr_s), GFP_KERNEL); ASSERT_ALWAYS(intr_hdl); + memset(intr_hdl, 0, sizeof(struct hub_intr_s)); xtalk_info = &intr_hdl->i_xtalk_info; xtalk_info->xi_dev = dev; @@ -90,12 +95,11 @@ do_hub_intr_alloc(vertex_hdl_t dev, xtalk_info->xi_target = xwidget_info_masterid_get(xwidget_info); } - intr_hdl->i_swlevel = intr_swlevel; intr_hdl->i_cpuid = cpu; intr_hdl->i_bit = vector; intr_hdl->i_flags |= HUB_INTR_IS_ALLOCED; - return(intr_hdl); + return intr_hdl; } hub_intr_t @@ -185,3 +189,73 @@ hub_intr_disconnect(hub_intr_t intr_hdl) ASSERT(rv == 0); intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED; } + +/* + * Redirect an interrupt to another cpu. + */ + +void +sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu) +{ + unsigned long bit; + int cpuphys, slice; + nasid_t nasid; + unsigned long xtalk_addr; + void *bridge = intr->bi_soft->bs_base; + int irq; + int i; + int old_cpu; + int new_cpu; + + cpuphys = cpu_physical_id(cpu); + slice = cpu_physical_id_to_slice(cpuphys); + nasid = cpu_physical_id_to_nasid(cpuphys); + + for (i = CPUS_PER_NODE - 1; i >= 0; i--) { + new_cpu = nasid_slice_to_cpuid(nasid, i); + if (new_cpu == NR_CPUS) { + continue; + } + + if (!cpu_online(new_cpu)) { + continue; + } + break; + } + + if (enable_shub_wars_1_1() && slice != i) { + printk("smp_affinity WARNING: SHUB 1.1 present: cannot target cpu %d, targeting cpu %d instead.\n",(int)cpu, new_cpu); + cpu = new_cpu; + slice = i; + } + + if (slice) { + xtalk_addr = SH_II_INT1 | ((unsigned long)nasid << 36) | (1UL << 47); + } else { + xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47); + } + + for (bit = 0; bit < 8; bit++) { + if (intr->bi_ibits & (1 << bit) ) { + /* Disable interrupts. */ + pcireg_intr_enable_bit_clr(bridge, bit); + /* Reset Host address (Interrupt destination) */ + pcireg_intr_addr_addr_set(bridge, bit, xtalk_addr); + /* Enable interrupt */ + pcireg_intr_enable_bit_set(bridge, bit); + /* Force an interrupt, just in case. */ + pcireg_force_intr_set(bridge, bit); + } + } + irq = intr->bi_irq; + old_cpu = intr->bi_cpu; + if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) { + pdacpu(cpu)->sn_first_irq = irq; + } + if (pdacpu(cpu)->sn_last_irq < irq) { + pdacpu(cpu)->sn_last_irq = irq; + } + pdacpu(old_cpu)->sn_num_irqs--; + pdacpu(cpu)->sn_num_irqs++; + intr->bi_cpu = (int)cpu; +} diff -puN arch/ia64/sn/io/sn2/shubio.c~linus arch/ia64/sn/io/sn2/shubio.c --- 25/arch/ia64/sn/io/sn2/shubio.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/shubio.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id: shubio.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $ - * +/* * 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. @@ -14,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -160,8 +158,6 @@ hub_ioerror_handler( iopaddr_t p; caddr_t cp; - IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror); - hubinfo_get(hub_v, &hinfo); if (!hinfo){ @@ -287,8 +283,6 @@ hub_ioerror_handler( IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); } else { - IOERROR_DUMP("hub_ioerror_handler", error_code, - mode, ioerror); IOERR_PRINTF(printk( "hub_ioerror_handler: Invalid address passed")); @@ -308,11 +302,6 @@ hub_ioerror_handler( * widget is enabled. */ if (!is_widget_pio_enabled(ioerror)) { - if (error_state_get(hub_v) == - ERROR_STATE_ACTION) - ioerror_dump("No outbound widget" - " access - ", - error_code, mode, ioerror); return(IOERROR_HANDLED); } @@ -350,11 +339,6 @@ hub_ioerror_handler( */ if (!is_widget_pio_enabled(ioerror)) { - if (error_state_get(hub_v) == - ERROR_STATE_ACTION) - ioerror_dump("No outbound widget" - " access - ", - error_code, mode, ioerror); return(IOERROR_HANDLED); } @@ -478,7 +462,7 @@ error_return_code_t error_state_set(vertex_hdl_t v,error_state_t new_state) { error_state_t old_state; - boolean_t replace = B_TRUE; + int replace = 1; /* Check if we have a valid hwgraph vertex */ if ( v == (vertex_hdl_t)0 ) @@ -497,7 +481,7 @@ error_state_set(vertex_hdl_t v,error_sta * for this vertex. */ if (v_error_state_get(v,old_state) != GRAPH_SUCCESS) - replace = B_FALSE; + replace = 0; if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) { return(ERROR_RETURN_CODE_CANNOT_SET_STATE); diff -puN arch/ia64/sn/io/sn2/xbow.c~linus arch/ia64/sn/io/sn2/xbow.c --- 25/arch/ia64/sn/io/sn2/xbow.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/xbow.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -7,47 +6,24 @@ * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved. */ -#include #include #include -#include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include #include +#include +#include /* #define DEBUG 1 */ /* #define XBOW_DEBUG 1 */ -/* #define DEBUG_ERROR 1 */ - - -/* - * Files needed to get the device driver entry points - */ - -#include -#include -#include -#include - -#include -#include +#define kdebug 0 -#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) -#define DEL(ptr) (kfree(ptr)) /* * This file supports the Xbow chip. Main functions: initializtion, - * error handling, and GBR. + * error handling. */ /* @@ -55,7 +31,6 @@ * has a "fastinfo" pointer pointing at one * of these things. */ -typedef struct xbow_soft_s *xbow_soft_t; struct xbow_soft_s { vertex_hdl_t conn; /* our connection point */ @@ -64,30 +39,24 @@ struct xbow_soft_s { xbow_t *base; /* PIO pointer to crossbow chip */ char *name; /* hwgraph name */ - xbow_perf_t xbow_perfcnt[XBOW_PERF_COUNTERS]; - xbow_perf_link_t xbow_perflink[MAX_XBOW_PORTS]; xbow_link_status_t xbow_link_status[MAX_XBOW_PORTS]; - spinlock_t xbow_perf_lock; - int link_monitor; widget_cfg_t *wpio[MAX_XBOW_PORTS]; /* cached PIO pointer */ /* Bandwidth allocation state. Bandwidth values are for the * destination port since contention happens there. * Implicit mapping from xbow ports (8..f) -> (0..7) array indices. */ - spinlock_t xbow_bw_alloc_lock; /* bw allocation lock */ unsigned long long bw_hiwm[MAX_XBOW_PORTS]; /* hiwater mark values */ unsigned long long bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */ }; #define xbow_soft_set(v,i) hwgraph_fastinfo_set((v), (arbitrary_info_t)(i)) -#define xbow_soft_get(v) ((xbow_soft_t)hwgraph_fastinfo_get((v))) +#define xbow_soft_get(v) ((struct xbow_soft_s *)hwgraph_fastinfo_get((v))) /* * Function Table of Contents */ -void xbow_mlreset(xbow_t *); int xbow_attach(vertex_hdl_t); int xbow_widget_present(xbow_t *, int); @@ -95,19 +64,6 @@ static int xbow_link_alive( vertex_hdl_t xbow_widget_lookup(vertex_hdl_t, int); void xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); - - - -void xbow_update_perf_counters(vertex_hdl_t); -xbow_perf_link_t *xbow_get_perf_counters(vertex_hdl_t); -int xbow_enable_perf_counter(vertex_hdl_t, int, int, int); -xbow_link_status_t *xbow_get_llp_status(vertex_hdl_t); -void xbow_update_llp_status(vertex_hdl_t); - -int xbow_disable_llp_monitor(vertex_hdl_t); -int xbow_enable_llp_monitor(vertex_hdl_t); -int xbow_prio_bw_alloc(vertex_hdl_t, xwidgetnum_t, xwidgetnum_t, - unsigned long long, unsigned long long); static void xbow_setwidint(xtalk_intr_t); xswitch_reset_link_f xbow_reset_link; @@ -122,12 +78,12 @@ static int xbow_mmap(struct file * file, struct vm_area_struct * vma) { unsigned long phys_addr; - int error = 0; + int error; phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_flags |= VM_RESERVED | VM_IO; - error = io_remap_page_range(vma, phys_addr, vma->vm_start, + error = io_remap_page_range(vma, vma->vm_start, phys_addr, vma->vm_end-vma->vm_start, vma->vm_page_prot); return(error); @@ -143,23 +99,6 @@ struct file_operations xbow_fops = { .mmap = xbow_mmap, }; -/* - * xbow_mlreset: called at mlreset time if the - * platform specific code determines that there is - * a crossbow in a critical path that must be - * functional before the driver would normally get - * the device properly set up. - * - * what do we need to do, that the boot prom can - * not be counted on to have already done, that is - * generic across all platforms using crossbows? - */ -/*ARGSUSED */ -void -xbow_mlreset(xbow_t * xbow) -{ -} - #ifdef XBRIDGE_REGS_SIM /* xbow_set_simulated_regs: sets xbow regs as needed * for powering through the boot @@ -201,8 +140,8 @@ xbow_attach(vertex_hdl_t conn) /*REFERENCED */ vertex_hdl_t vhdl; vertex_hdl_t busv; - xbow_t *xbow; - xbow_soft_t soft; + xbow_t *xbow; + struct xbow_soft_s *soft; int port; xswitch_info_t info; xtalk_intr_t intr_hdl; @@ -211,15 +150,14 @@ xbow_attach(vertex_hdl_t conn) int rev; int i; int xbow_num; +#if DEBUG && ATTACH_DEBUG + char name[MAXDEVNAME]; +#endif static void xbow_errintr_handler(int, void *, struct pt_regs *); #if DEBUG && ATTACH_DEBUG -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk("%v: xbow_attach\n", conn); -#else - printk("0x%x: xbow_attach\n", conn); -#endif + printk("%s: xbow_attach\n", vertex_to_name(conn, name, MAXDEVNAME)); #endif /* @@ -229,6 +167,8 @@ xbow_attach(vertex_hdl_t conn) #ifdef XBRIDGE_REGS_SIM printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t)); xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL); + if (!xbow) + return -ENOMEM; /* * turn on ports e and f like in a real live ibrick */ @@ -260,7 +200,6 @@ xbow_attach(vertex_hdl_t conn) * Register a xbow driver with hwgraph. * file ops. */ - vhdl = NULL; vhdl = hwgraph_register(conn, EDGE_LBL_XBOW, 0, 0, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, @@ -274,7 +213,9 @@ xbow_attach(vertex_hdl_t conn) * Allocate the soft state structure and attach * it to the xbow's vertex */ - NEW(soft); + soft = kmalloc(sizeof(*soft), GFP_KERNEL); + if (!soft) + return -ENOMEM; soft->conn = conn; soft->vhdl = vhdl; soft->busv = busv; @@ -298,6 +239,10 @@ xbow_attach(vertex_hdl_t conn) s = dev_to_name(vhdl, devnm, MAXDEVNAME); soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, GFP_KERNEL); + if (!soft->name) { + kfree(soft); + return -ENOMEM; + } sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num); #ifdef XBRIDGE_REGS_SIM @@ -311,14 +256,6 @@ xbow_attach(vertex_hdl_t conn) #endif /* XBRIDGE_REGS_SIM */ rev = XWIDGET_PART_REV_NUM(id); - mutex_spinlock_init(&soft->xbow_perf_lock); - soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a; - soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b; - - /* Initialization for GBR bw allocation */ - mutex_spinlock_init(&soft->xbow_bw_alloc_lock); - -#define XBOW_8_BIT_PORT_BW_MAX (400 * 1000 * 1000) /* 400 MB/s */ #define XBOW_16_BIT_PORT_BW_MAX (800 * 1000 * 1000) /* 800 MB/s */ /* Set bandwidth hiwatermark and current values */ @@ -419,43 +356,6 @@ xbow_attach(vertex_hdl_t conn) return 0; /* attach successful */ } -/* This contains special-case code for grio. There are plans to make - * this general sometime in the future, but till then this should - * be good enough. - */ -xwidgetnum_t -xbow_widget_num_get(vertex_hdl_t dev) -{ - vertex_hdl_t tdev; - char devname[MAXDEVNAME]; - xwidget_info_t xwidget_info; - int i; - - vertex_to_name(dev, devname, MAXDEVNAME); - - /* If this is a pci controller vertex, traverse up using - * the ".." links to get to the widget. - */ - if (strstr(devname, EDGE_LBL_PCI) && - strstr(devname, EDGE_LBL_CONTROLLER)) { - tdev = dev; - for (i=0; i< 2; i++) { - if (hwgraph_edge_get(tdev, - HWGRAPH_EDGELBL_DOTDOT, &tdev) != - GRAPH_SUCCESS) - return XWIDGET_NONE; - } - - if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) { - return (xwidget_info_id_get(xwidget_info)); - } else { - return XWIDGET_NONE; - } - } - - return XWIDGET_NONE; -} - /* * xbow_widget_present: See if a device is present * on the specified port of this crossbow. @@ -477,6 +377,10 @@ xbow_widget_present(xbow_t *xbow, int po IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) { return 1; } + else if ( IS_PIC_XBOW(xbow->xb_wid_id) && port==0xb ) { + /* for opus the present bit doesn't work on port 0xb */ + return 1; + } return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT; } } @@ -562,10 +466,8 @@ xbow_intr_preset(void *which_widget, XEM_ADD_NVAR("ioe." #n, p); \ } -int xbow_xmit_retry_errors; - int -xbow_xmit_retry_error(xbow_soft_t soft, +xbow_xmit_retry_error(struct xbow_soft_s *soft, int port) { xswitch_info_t info; @@ -600,46 +502,18 @@ xbow_xmit_retry_error(xbow_soft_t soft, part = XWIDGET_PART_NUM(id); mfgr = XWIDGET_MFG_NUM(id); - /* If this thing is not a Bridge, - * do not activate the WAR, and - * tell our caller we do not need - * to be called again. - */ - if ((part != BRIDGE_WIDGET_PART_NUM) || - (mfgr != BRIDGE_WIDGET_MFGR_NUM)) { - /* FIXME: add Xbridge to the WAR. - * Shouldn't hurt anything. Later need to - * check if we can remove this. - */ - if ((part != XBRIDGE_WIDGET_PART_NUM) || - (mfgr != XBRIDGE_WIDGET_MFGR_NUM)) - return 0; - } - - /* count how many times we - * have picked up after - * LLP Transmit problems. - */ - xbow_xmit_retry_errors++; - - /* rewrite the control register - * to fix things up. - */ - wid->w_control = wid->w_control; - wid->w_control; - - return 1; + return 0; } /* * xbow_errintr_handler will be called if the xbow * sends an interrupt request to report an error. */ -static void +static irqreturn_t xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep) { ioerror_t ioe[1]; - xbow_soft_t soft = (xbow_soft_t) arg; + struct xbow_soft_s *soft = (struct xbow_soft_s *)arg; xbow_t *xbow = soft->base; xbowreg_t wid_control; xbowreg_t wid_stat; @@ -805,8 +679,9 @@ xbow_errintr_handler(int irq, void *arg, XEM_ADD_VAR(wid_err_upper); XEM_ADD_VAR(wid_err_lower); XEM_ADD_VAR(wid_err_addr); - PRINT_PANIC("XIO Bus Error"); + panic("XIO Bus Error"); } + return IRQ_HANDLED; } /* @@ -831,10 +706,10 @@ xbow_error_handler( ioerror_mode_t mode, ioerror_t *ioerror) { - int retval = IOERROR_WIDGETLEVEL; + int retval = IOERROR_WIDGETLEVEL; - xbow_soft_t soft = (xbow_soft_t) einfo; - int port; + struct xbow_soft_s *soft = (struct xbow_soft_s *) einfo; + int port; vertex_hdl_t conn; vertex_hdl_t busv; @@ -958,8 +833,9 @@ xbow_error_handler( if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) && IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf)) ; - else - if (!(link_aux_status & XB_AUX_STAT_PRESENT)) { + else if (IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xb)) + ; /* WAR for opus this is missing on 0xb */ + else if (!(link_aux_status & XB_AUX_STAT_PRESENT)) { /* nobody connected. */ if (mode == MODE_DEVPROBE) return IOERROR_HANDLED; @@ -1087,173 +963,6 @@ xbow_error_handler( return retval; } -void -xbow_update_perf_counters(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; - xbow_perf_link_t *xbow_plink = xbow_soft->xbow_perflink; - xbow_perfcount_t perf_reg; - unsigned long s; - int link, i; - - for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) { - if (xbow_perf->xp_mode == XBOW_MONITOR_NONE) - continue; - - s = mutex_spinlock(&xbow_soft->xbow_perf_lock); - - perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; - - link = perf_reg.xb_perf.link_select; - - (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] += - ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK); - xbow_perf->xp_current = perf_reg.xb_perf.count; - - mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); - } -} - -xbow_perf_link_t * -xbow_get_perf_counters(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - xbow_perf_link_t *xbow_perf_link = xbow_soft->xbow_perflink; - - return xbow_perf_link; -} - -int -xbow_enable_perf_counter(vertex_hdl_t vhdl, int link, int mode, int counter) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - xbow_perf_t *xbow_perf = xbow_soft->xbow_perfcnt; - xbow_linkctrl_t xbow_link_ctrl; - xbow_t *xbow = xbow_soft->base; - xbow_perfcount_t perf_reg; - unsigned long s; - int i; - - link -= BASE_XBOW_PORT; - if ((link < 0) || (link >= MAX_XBOW_PORTS)) - return -1; - - if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK)) - return -1; - - if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS)) - return -1; - - s = mutex_spinlock(&xbow_soft->xbow_perf_lock); - - if ((xbow_perf + counter)->xp_mode && mode) { - mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); - return -1; - } - for (i = 0; i < XBOW_PERF_COUNTERS; i++) { - if (i == counter) - continue; - if (((xbow_perf + i)->xp_link == link) && - ((xbow_perf + i)->xp_mode)) { - mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); - return -1; - } - } - xbow_perf += counter; - - xbow_perf->xp_curlink = xbow_perf->xp_link = link; - xbow_perf->xp_curmode = xbow_perf->xp_mode = mode; - - xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control; - xbow_link_ctrl.xb_linkcontrol.perf_mode = mode; - xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword; - - perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg; - perf_reg.xb_perf.link_select = link; - *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val; - xbow_perf->xp_current = perf_reg.xb_perf.count; - - mutex_spinunlock(&xbow_soft->xbow_perf_lock, s); - return 0; -} - -xbow_link_status_t * -xbow_get_llp_status(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; - - return xbow_llp_status; -} - -void -xbow_update_llp_status(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - xbow_link_status_t *xbow_llp_status = xbow_soft->xbow_link_status; - xbow_t *xbow; - xbwX_stat_t lnk_sts; - xbow_aux_link_status_t aux_sts; - int link; - vertex_hdl_t xwidget_vhdl; - char *xwidget_name; - - xbow = (xbow_t *) xbow_soft->base; - for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) { - /* Get the widget name corresponding the current link. - * Note : 0 <= link < MAX_XBOW_PORTS(8). - * BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10) - */ - xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT); - xwidget_name = xwidget_name_get(xwidget_vhdl); - aux_sts.aux_linkstatus - = xbow->xb_link_raw[link].link_aux_status; - lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr; - - if (lnk_sts.link_alive == 0) - continue; - - xbow_llp_status->rx_err_count += - aux_sts.xb_aux_linkstatus.rx_err_cnt; - - xbow_llp_status->tx_retry_count += - aux_sts.xb_aux_linkstatus.tx_retry_cnt; - - if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) { -#ifdef LATER - printk(KERN_WARNING "link %d[%s]: bad status 0x%x\n", - link, xwidget_name, lnk_sts.linkstatus); -#endif - } - } -} - -int -xbow_disable_llp_monitor(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - int port; - - for (port = 0; port < MAX_XBOW_PORTS; port++) { - xbow_soft->xbow_link_status[port].rx_err_count = 0; - xbow_soft->xbow_link_status[port].tx_retry_count = 0; - } - - xbow_soft->link_monitor = 0; - return 0; -} - -int -xbow_enable_llp_monitor(vertex_hdl_t vhdl) -{ - xbow_soft_t xbow_soft = xbow_soft_get(vhdl); - - xbow_soft->link_monitor = 1; - return 0; -} - - int xbow_reset_link(vertex_hdl_t xconn_vhdl) { @@ -1262,15 +971,10 @@ xbow_reset_link(vertex_hdl_t xconn_vhdl) xbow_t *xbow; xbowreg_t ctrl; xbwX_stat_t stat; - unsigned itick; - unsigned dtick; - static int ticks_per_ms = 0; - - if (!ticks_per_ms) { - itick = get_timestamp(); - us_delay(1000); - ticks_per_ms = get_timestamp() - itick; - } + unsigned long itick; + unsigned int dtick; + static long ticks_to_wait = HZ / 1000; + widget_info = xwidget_info_get(xconn_vhdl); port = xwidget_info_id_get(widget_info); @@ -1279,7 +983,7 @@ xbow_reset_link(vertex_hdl_t xconn_vhdl) #else { vertex_hdl_t xbow_vhdl; - xbow_soft_t xbow_soft; + struct xbow_soft_s *xbow_soft; hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl); xbow_soft = xbow_soft_get(xbow_vhdl); @@ -1296,155 +1000,17 @@ xbow_reset_link(vertex_hdl_t xconn_vhdl) */ ctrl = xbow->xb_link(port).link_control; xbow->xb_link(port).link_reset = 0; - itick = get_timestamp(); + itick = jiffies; while (1) { stat.linkstatus = xbow->xb_link(port).link_status; if (stat.link_alive) break; - dtick = get_timestamp() - itick; - if (dtick > ticks_per_ms) { + dtick = jiffies - itick; + if (dtick > ticks_to_wait) { return -1; /* never came out of reset */ } - DELAY(2); /* don't beat on link_status */ + udelay(2); /* don't beat on link_status */ } xbow->xb_link(port).link_control = ctrl; return 0; } - -#define XBOW_ARB_RELOAD_TICKS 25 - /* granularity: 4 MB/s, max: 124 MB/s */ -#define GRANULARITY ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS) - -#define XBOW_BYTES_TO_GBR(BYTES_per_s) (int) (BYTES_per_s / GRANULARITY) - -#define XBOW_GBR_TO_BYTES(cnt) (bandwidth_t) ((cnt) * GRANULARITY) - -#define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec) \ - ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr) - -#define XBOW_ARB_GBR_MAX 31 - -#define ABS(x) ((x > 0) ? (x) : (-1 * x)) - /* absolute value */ - -int -xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec) -{ - int gbr_granted; - int new_total_gbr; - int change_gbr; - bandwidth_t new_total_bw; - -#ifdef GRIO_DEBUG - printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n", - old_bytes_per_sec, bytes_per_sec); -#endif /* GRIO_DEBUG */ - - gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)), - old_bytes_per_sec); - new_total_bw = old_bytes_per_sec + bytes_per_sec; - new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)), - new_total_bw); - - change_gbr = new_total_gbr - gbr_granted; - -#ifdef GRIO_DEBUG - printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n", - gbr_granted, new_total_gbr, change_gbr); -#endif /* GRIO_DEBUG */ - - return (change_gbr); -} - -/* Conversion from GBR to bytes */ -bandwidth_t -xbow_gbr_to_bytes(int gbr) -{ - return (XBOW_GBR_TO_BYTES(gbr)); -} - -/* Given the vhdl for the desired xbow, the src and dest. widget ids - * and the req_bw value, this xbow driver entry point accesses the - * xbow registers and allocates the desired bandwidth if available. - * - * If bandwidth allocation is successful, return success else return failure. - */ -int -xbow_prio_bw_alloc(vertex_hdl_t vhdl, - xwidgetnum_t src_wid, - xwidgetnum_t dest_wid, - unsigned long long old_alloc_bw, - unsigned long long req_bw) -{ - xbow_soft_t soft = xbow_soft_get(vhdl); - volatile xbowreg_t *xreg; - xbowreg_t mask; - unsigned long s; - int error = 0; - bandwidth_t old_bw_BYTES, req_bw_BYTES; - xbowreg_t old_xreg; - int old_bw_GBR, req_bw_GBR, new_bw_GBR; - -#ifdef GRIO_DEBUG - printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n", - (int) vhdl, (int) src_wid, (int) dest_wid, req_bw); -#endif - - ASSERT(XBOW_WIDGET_IS_VALID(src_wid)); - ASSERT(XBOW_WIDGET_IS_VALID(dest_wid)); - - s = mutex_spinlock(&soft->xbow_bw_alloc_lock); - - /* Get pointer to the correct register */ - xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid); - - /* Get mask for GBR count value */ - mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid); - - req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw); - req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR))) - : xbow_gbr_to_bytes(req_bw_GBR); - -#ifdef GRIO_DEBUG - printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n", - req_bw, req_bw_BYTES, req_bw_GBR); -#endif /* GRIO_DEBUG */ - - old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS]; - old_xreg = *xreg; - old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid)); - -#ifdef GRIO_DEBUG - ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR); - - printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR); - - printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n", - req_bw_BYTES, old_bw_BYTES, - soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]); - -#endif /* GRIO_DEBUG */ - - /* Accept the request only if we don't exceed the destination - * port HIWATER_MARK *AND* the max. link GBR arbitration count - */ - if (((old_bw_BYTES + req_bw_BYTES) <= - soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) && - (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) { - - new_bw_GBR = (old_bw_GBR + req_bw_GBR); - - /* Set this in the xbow link register */ - *xreg = (old_xreg & ~mask) | \ - (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask); - - soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] = - xbow_gbr_to_bytes(new_bw_GBR); - } else { - error = 1; - } - - mutex_spinunlock(&soft->xbow_bw_alloc_lock, s); - - return (error); -} diff -puN arch/ia64/sn/io/sn2/xtalk.c~linus arch/ia64/sn/io/sn2/xtalk.c --- 25/arch/ia64/sn/io/sn2/xtalk.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/sn2/xtalk.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -13,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -23,9 +21,9 @@ #include /* - * Implement crosstalk provider operations. The xtalk* layer provides a - * platform-independent interface for crosstalk devices. This layer - * switches among the possible implementations of a crosstalk adapter. + * Implement io channel provider operations. The xtalk* layer provides a + * platform-independent interface for io channel devices. This layer + * switches among the possible implementations of a io channel adapter. * * On platforms with only one possible xtalk provider, macros can be * set up at the top that cause the table lookups and indirections to @@ -37,11 +35,6 @@ char widget_info_fingerprint[] = "widget_info"; -#define DEV_FUNC(dev,func) hub_##func -#define CAST_PIOMAP(x) ((hub_piomap_t)(x)) -#define CAST_DMAMAP(x) ((hub_dmamap_t)(x)) -#define CAST_INTR(x) ((hub_intr_t)(x)) - /* ===================================================================== * Function Table of Contents */ @@ -71,7 +64,6 @@ int xtalk_intr_conne void xtalk_intr_disconnect(xtalk_intr_t); vertex_hdl_t xtalk_intr_cpu_get(xtalk_intr_t); int xtalk_error_handler(vertex_hdl_t, int, ioerror_mode_t, ioerror_t *); -int xtalk_error_devenable(vertex_hdl_t, int, int); void xtalk_provider_startup(vertex_hdl_t); void xtalk_provider_shutdown(vertex_hdl_t); vertex_hdl_t xtalk_intr_dev_get(xtalk_intr_t); @@ -121,6 +113,7 @@ char *xwidget_name_get(vertex_hdl_t); #define CAST_PIOMAP(x) ((xtalk_piomap_t)(x)) #define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x)) #define CAST_INTR(x) ((xtalk_intr_t)(x)) +xtalk_provider_t * xwidget_info_pops_get(xwidget_info_t info); static xtalk_provider_t * xwidget_to_provider_fns(vertex_hdl_t xconn) @@ -136,6 +129,17 @@ xwidget_to_provider_fns(vertex_hdl_t xco return (provider_fns); } + +xtalk_provider_t * +xwidget_info_pops_get(xwidget_info_t info) { + vertex_hdl_t master = info->w_master; + xtalk_provider_t *provider_fns; + + provider_fns = xtalk_provider_fns_get(master); + + ASSERT(provider_fns != NULL); + return provider_fns; +} #endif /* @@ -273,13 +277,13 @@ xtalk_set_early_piotrans_addr(xtalk_earl } /* xtalk_early_piotrans_addr: - * figure out a PIO address for the "nth" crosstalk widget that + * figure out a PIO address for the "nth" io channel widget that * matches the specified part and mfgr number. Returns NULL if * there is no such widget, or if the requested mapping can not * be constructed. - * Limitations on which crosstalk slots (and busses) are + * Limitations on which io channel slots (and busses) are * checked, and definitions of the ordering of the search across - * the crosstalk slots, are defined by the platform. + * the io channel slots, are defined by the platform. */ caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t part_num, @@ -310,7 +314,7 @@ null_xtalk_early_piotrans_addr(xwidget_p unsigned flags) { #if DEBUG - PRINT_PANIC("null_xtalk_early_piotrans_addr"); + panic("null_xtalk_early_piotrans_addr"); #endif return NULL; } @@ -318,7 +322,7 @@ null_xtalk_early_piotrans_addr(xwidget_p /* ===================================================================== * DMA MANAGEMENT * - * For mapping from crosstalk space to system + * For mapping from io channel space to system * physical space. */ @@ -415,7 +419,7 @@ xtalk_dmalist_drain(vertex_hdl_t dev, al /* ===================================================================== * INTERRUPT MANAGEMENT * - * Allow crosstalk devices to establish interrupts + * Allow io channel devices to establish interrupts */ /* @@ -510,8 +514,8 @@ xtalk_intr_cpu_get(xtalk_intr_t intr_hdl * This routine plays two roles during error delivery * to most widgets: first, the external agent (heart, * hub, or whatever) calls in with the error and the - * connect point representing the crosstalk switch, - * or whatever crosstalk device is directly connected + * connect point representing the io channel switch, + * or whatever io channel device is directly connected * to the agent. * * If there is a switch, it will generally look at the @@ -528,6 +532,8 @@ xtalk_error_handler( ioerror_t *ioerror) { xwidget_info_t xwidget_info; + char name[MAXDEVNAME]; + xwidget_info = xwidget_info_get(xconn); /* Make sure that xwidget_info is a valid pointer before derefencing it. @@ -548,46 +554,33 @@ xtalk_error_handler( (mode == MODE_DEVREENABLE)) return IOERROR_HANDLED; -#if defined(SUPPORT_PRINTING_V_FORMAT) - printk(KERN_WARNING "Xbow at %v encountered Fatal error", xconn); -#else - printk(KERN_WARNING "Xbow at 0x%p encountered Fatal error", (void *)xconn); -#endif - ioerror_dump("xtalk", error_code, mode, ioerror); + printk(KERN_WARNING "Xbow at %s encountered Fatal error", vertex_to_name(xconn, name, MAXDEVNAME)); return IOERROR_UNHANDLED; } -int -xtalk_error_devenable(vertex_hdl_t xconn_vhdl, int devnum, int error_code) -{ - return DEV_FUNC(xconn_vhdl, error_devenable) (xconn_vhdl, devnum, error_code); -} - /* ===================================================================== * CONFIGURATION MANAGEMENT */ /* - * Startup a crosstalk provider + * Startup an io channel provider */ void xtalk_provider_startup(vertex_hdl_t xtalk_provider) { - DEV_FUNC(xtalk_provider, provider_startup) - (xtalk_provider); + ((xtalk_provider_t *) hwgraph_fastinfo_get(xtalk_provider))->provider_startup(xtalk_provider); } /* - * Shutdown a crosstalk provider + * Shutdown an io channel provider */ void xtalk_provider_shutdown(vertex_hdl_t xtalk_provider) { - DEV_FUNC(xtalk_provider, provider_shutdown) - (xtalk_provider); + ((xtalk_provider_t *) hwgraph_fastinfo_get(xtalk_provider))->provider_shutdown(xtalk_provider); } /* @@ -608,17 +601,12 @@ xtalk_widgetdev_shutdown(vertex_hdl_t xc return; } -int -xtalk_dma_enabled(vertex_hdl_t xconn_vhdl) -{ - return DEV_FUNC(xconn_vhdl, dma_enabled) (xconn_vhdl); -} /* - * Generic crosstalk functions, for use with all crosstalk providers - * and all crosstalk devices. + * Generic io channel functions, for use with all io channel providers + * and all io channel devices. */ -/****** Generic crosstalk interrupt interfaces ******/ +/* Generic io channel interrupt interfaces */ vertex_hdl_t xtalk_intr_dev_get(xtalk_intr_t xtalk_intr) { @@ -649,7 +637,7 @@ xtalk_intr_sfarg_get(xtalk_intr_t xtalk_ return (xtalk_intr->xi_sfarg); } -/****** Generic crosstalk pio interfaces ******/ +/* Generic io channel pio interfaces */ vertex_hdl_t xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap) { @@ -681,7 +669,7 @@ xtalk_pio_kvaddr_get(xtalk_piomap_t xtal } -/****** Generic crosstalk dma interfaces ******/ +/* Generic io channel dma interfaces */ vertex_hdl_t xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap) { @@ -695,7 +683,7 @@ xtalk_dma_target_get(xtalk_dmamap_t xtal } -/****** Generic crosstalk widget information interfaces ******/ +/* Generic io channel widget information interfaces */ /* xwidget_info_chk: * check to see if this vertex is a widget; @@ -797,7 +785,7 @@ xwidget_info_name_get(xwidget_info_t xwi panic("xwidget_info_name_get: null xwidget_info"); return(xwidget_info->w_name); } -/****** Generic crosstalk initialization interfaces ******/ +/* Generic io channel initialization interfaces */ /* * Associate a set of xtalk_provider functions with a vertex. @@ -912,16 +900,11 @@ xwidget_unregister(vertex_hdl_t widget) if (!(widget_info = xwidget_info_get(widget))) return(1); - /* Remove the inventory information associated - * with the widget. - */ - hwgraph_inventory_remove(widget, -1, -1, -1, -1, -1); - hwid = &(widget_info->w_hwid); /* Clean out the xwidget information */ (void)kfree(widget_info->w_name); - BZERO((void *)widget_info, sizeof(widget_info)); + memset((void *)widget_info, 0, sizeof(widget_info)); DEL(widget_info); return(0); diff -puN /dev/null arch/ia64/sn/io/snia_if.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ia64/sn/io/snia_if.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,108 @@ +/* + * 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 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include + +extern pciio_provider_t *pciio_to_provider_fns(vertex_hdl_t dev); + +int +snia_badaddr_val(volatile void *addr, int len, volatile void *ptr) +{ + int ret = 0; + volatile void *new_addr; + + switch (len) { + case 4: + new_addr = (void *) addr; + ret = ia64_sn_probe_io_slot((long) new_addr, len, (void *) ptr); + break; + default: + printk(KERN_WARNING + "snia_badaddr_val given len %x but supports len of 4 only\n", + len); + } + + if (ret < 0) + panic("snia_badaddr_val: unexpected status (%d) in probing", + ret); + return (ret); + +} + +nasid_t +snia_get_console_nasid(void) +{ + extern nasid_t console_nasid; + extern nasid_t master_baseio_nasid; + + if (console_nasid < 0) { + console_nasid = ia64_sn_get_console_nasid(); + if (console_nasid < 0) { +// ZZZ What do we do if we don't get a console nasid on the hardware???? + if (IS_RUNNING_ON_SIMULATOR()) + console_nasid = master_baseio_nasid; + } + } + return console_nasid; +} + +nasid_t +snia_get_master_baseio_nasid(void) +{ + extern nasid_t master_baseio_nasid; + extern char master_baseio_wid; + + if (master_baseio_nasid < 0) { + master_baseio_nasid = ia64_sn_get_master_baseio_nasid(); + + if (master_baseio_nasid >= 0) { + master_baseio_wid = + WIDGETID_GET(KL_CONFIG_CH_CONS_INFO + (master_baseio_nasid)->memory_base); + } + } + return master_baseio_nasid; +} + +/* + * XXX: should probably be called __sn2_pci_rrb_alloc + * used by qla1280 + */ + +int +snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, int *count_vchan1) +{ + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); + + return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1); +} + +/* + * XXX: interface should be more like + * + * int __sn2_pci_enable_bwswap(struct pci_dev *dev); + * void __sn2_pci_disable_bswap(struct pci_dev *dev); + */ +/* used by ioc4 ide */ + +pciio_endian_t +snia_pciio_endian_set(struct pci_dev * pci_dev, + pciio_endian_t device_end, pciio_endian_t desired_end) +{ + vertex_hdl_t dev = PCIDEV_VERTEX(pci_dev); + + return ((pciio_to_provider_fns(dev))->endian_set) + (dev, device_end, desired_end); +} + +EXPORT_SYMBOL(snia_pciio_endian_set); +EXPORT_SYMBOL(snia_pcibr_rrb_alloc); diff -puN arch/ia64/sn/io/xswitch.c~linus arch/ia64/sn/io/xswitch.c --- 25/arch/ia64/sn/io/xswitch.c~linus 2004-01-19 22:17:03.000000000 -0800 +++ 25-akpm/arch/ia64/sn/io/xswitch.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ -/* $Id$ - * +/* * 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. @@ -12,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -65,7 +63,7 @@ xswitch_info_vhdl_set(xswitch_info_t xsw if (port > XSWITCH_CENSUS_PORT_MAX) return; - xswitch_info->vhdl[port] = xwidget; + xswitch_info->vhdl[(int)port] = xwidget; } vertex_hdl_t @@ -75,7 +73,7 @@ xswitch_info_vhdl_get(xswitch_info_t xsw if (port > XSWITCH_CENSUS_PORT_MAX) return GRAPH_VERTEX_NONE; - return xswitch_info->vhdl[port]; + return xswitch_info->vhdl[(int)port]; } /* @@ -91,7 +89,7 @@ xswitch_info_master_assignment_set(xswit if (port > XSWITCH_CENSUS_PORT_MAX) return; - xswitch_info->master_vhdl[port] = master_vhdl; + xswitch_info->master_vhdl[(int)port] = master_vhdl; } vertex_hdl_t @@ -101,7 +99,7 @@ xswitch_info_master_assignment_get(xswit if (port > XSWITCH_CENSUS_PORT_MAX) return GRAPH_VERTEX_NONE; - return xswitch_info->master_vhdl[port]; + return xswitch_info->master_vhdl[(int)port]; } void diff -puN arch/ia64/sn/kernel/bte.c~linus arch/ia64/sn/kernel/bte.c --- 25/arch/ia64/sn/kernel/bte.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/bte.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,35 +1,9 @@ /* - * + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include diff -puN arch/ia64/sn/kernel/irq.c~linus arch/ia64/sn/kernel/irq.c --- 25/arch/ia64/sn/kernel/irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,35 +1,11 @@ /* * Platform dependent support for SGI SN * + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include @@ -42,10 +18,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -62,11 +36,12 @@ #include #include -int irq_to_bit_pos(int irq); static void force_interrupt(int irq); extern void pcibr_force_interrupt(pcibr_intr_t intr); extern int sn_force_interrupt_flag; +static pcibr_intr_list_t *pcibr_intr_list; + static unsigned int @@ -139,8 +114,32 @@ sn_end_irq(unsigned int irq) } static void -sn_set_affinity_irq(unsigned int irq, unsigned long mask) +sn_set_affinity_irq(unsigned int irq, cpumask_t mask) { +#if CONFIG_SMP + int redir = 0; + pcibr_intr_list_t p = pcibr_intr_list[irq]; + pcibr_intr_t intr; + int cpu; + extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu); + extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu); + + if (p == NULL) + return; + + intr = p->il_intr; + + if (intr == NULL) + return; + + cpu = first_cpu(mask); + if (IS_PIC_SOFT(intr->bi_soft) ) { + sn_shub_redirect_intr(intr, cpu); + } else { + return; + } + (void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir); +#endif /* CONFIG_SMP */ } @@ -187,41 +186,18 @@ sn_irq_init (void) } } -int -bit_pos_to_irq(int bit) { -#define BIT_TO_IRQ 64 - if (bit > 118) bit = 118; - - return bit + BIT_TO_IRQ; -} - -int -irq_to_bit_pos(int irq) { -#define IRQ_TO_BIT 64 - int bit = irq - IRQ_TO_BIT; - - return bit; -} - -struct pcibr_intr_list_t { - struct pcibr_intr_list_t *next; - pcibr_intr_t intr; -}; - -static struct pcibr_intr_list_t **pcibr_intr_list; - void register_pcibr_intr(int irq, pcibr_intr_t intr) { - struct pcibr_intr_list_t *p = kmalloc(sizeof(struct pcibr_intr_list_t), GFP_KERNEL); - struct pcibr_intr_list_t *list; + pcibr_intr_list_t p = kmalloc(sizeof(struct pcibr_intr_list_s), GFP_KERNEL); + pcibr_intr_list_t list; int cpu = SN_CPU_FROM_IRQ(irq); if (pcibr_intr_list == NULL) { - pcibr_intr_list = kmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS, GFP_KERNEL); + pcibr_intr_list = kmalloc(sizeof(pcibr_intr_list_t) * NR_IRQS, GFP_KERNEL); if (pcibr_intr_list == NULL) - pcibr_intr_list = vmalloc(sizeof(struct pcibr_intr_list_t *) * NR_IRQS); + pcibr_intr_list = vmalloc(sizeof(pcibr_intr_list_t) * NR_IRQS); if (pcibr_intr_list == NULL) panic("Could not allocate memory for pcibr_intr_list\n"); - memset( (void *)pcibr_intr_list, 0, sizeof(struct pcibr_intr_list_t *) * NR_IRQS); + memset( (void *)pcibr_intr_list, 0, sizeof(pcibr_intr_list_t) * NR_IRQS); } if (pdacpu(cpu)->sn_last_irq < irq) { pdacpu(cpu)->sn_last_irq = irq; @@ -229,42 +205,42 @@ register_pcibr_intr(int irq, pcibr_intr_ if (pdacpu(cpu)->sn_first_irq > irq) pdacpu(cpu)->sn_first_irq = irq; if (!p) panic("Could not allocate memory for pcibr_intr_list_t\n"); if ((list = pcibr_intr_list[irq])) { - while (list->next) list = list->next; - list->next = p; - p->next = NULL; - p->intr = intr; + while (list->il_next) list = list->il_next; + list->il_next = p; + p->il_next = NULL; + p->il_intr = intr; } else { pcibr_intr_list[irq] = p; - p->next = NULL; - p->intr = intr; + p->il_next = NULL; + p->il_intr = intr; } } void force_polled_int(void) { int i; - struct pcibr_intr_list_t *p; + pcibr_intr_list_t p; for (i=0; iintr){ - pcibr_force_interrupt(p->intr); + if (p->il_intr){ + pcibr_force_interrupt(p->il_intr); } - p = p->next; + p = p->il_next; } } } static void force_interrupt(int irq) { - struct pcibr_intr_list_t *p = pcibr_intr_list[irq]; + pcibr_intr_list_t p = pcibr_intr_list[irq]; while (p) { - if (p->intr) { - pcibr_force_interrupt(p->intr); + if (p->il_intr) { + pcibr_force_interrupt(p->il_intr); } - p = p->next; + p = p->il_next; } } @@ -286,7 +262,7 @@ sn_check_intr(int irq, pcibr_intr_t intr unsigned long irr_reg; - regval = intr->bi_soft->bs_base->p_int_status_64; + regval = pcireg_intr_status_get(intr->bi_soft->bs_base); irr_reg_num = irq_to_vector(irq) / 64; irr_bit = irq_to_vector(irq) % 64; switch (irr_reg_num) { @@ -324,13 +300,13 @@ sn_lb_int_war_check(void) { if (pda->sn_first_irq == 0) return; for (i=pda->sn_first_irq; i <= pda->sn_last_irq; i++) { - struct pcibr_intr_list_t *p = pcibr_intr_list[i]; + pcibr_intr_list_t p = pcibr_intr_list[i]; if (p == NULL) { continue; } while (p) { - sn_check_intr(i, p->intr); - p = p->next; + sn_check_intr(i, p->il_intr); + p = p->il_next; } } } diff -puN arch/ia64/sn/kernel/machvec.c~linus arch/ia64/sn/kernel/machvec.c --- 25/arch/ia64/sn/kernel/machvec.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/machvec.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,33 +1,9 @@ /* + * 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) 2002-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #define MACHVEC_PLATFORM_NAME sn2 diff -puN arch/ia64/sn/kernel/Makefile~linus arch/ia64/sn/kernel/Makefile --- 25/arch/ia64/sn/kernel/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,7 +7,5 @@ # Copyright (C) 1999,2001-2003 Silicon Graphics, Inc. All Rights Reserved. # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += probe.o setup.o bte.o irq.o mca.o idle.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o diff -puN arch/ia64/sn/kernel/mca.c~linus arch/ia64/sn/kernel/mca.c --- 25/arch/ia64/sn/kernel/mca.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/mca.c 2004-01-19 22:17:21.000000000 -0800 @@ -2,35 +2,11 @@ * File: mca.c * Purpose: SN specific MCA code. * + * 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) 2001-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include diff -puN arch/ia64/sn/kernel/probe.c~linus arch/ia64/sn/kernel/probe.c --- 25/arch/ia64/sn/kernel/probe.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/probe.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,35 +1,11 @@ /* * Platform dependent support for IO probing. * + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include diff -puN arch/ia64/sn/kernel/setup.c~linus arch/ia64/sn/kernel/setup.c --- 25/arch/ia64/sn/kernel/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,33 +1,9 @@ /* + * 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) 1999,2001-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include @@ -82,6 +58,7 @@ extern void bte_init_node (nodepda_t *, extern void bte_init_cpu (void); extern void sn_timer_init(void); extern unsigned long last_time_offset; +extern void init_platform_hubinfo(nodepda_t **nodepdaindr); extern void (*ia64_mark_idle)(int); extern void snidle(int); @@ -93,6 +70,8 @@ u64 sn_partition_serial_number; short physical_node_map[MAX_PHYSNODE_ID]; +int numionodes; + /* * This is the address of the RRegs in the HSpace of the global * master. It is used by a hack in serial.c (serial_[in|out], @@ -240,9 +219,10 @@ sn_setup(char **cmdline_p) long status, ticks_per_sec, drift; int pxm; int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); - extern void io_sh_swapper(int, int); - extern nasid_t get_master_baseio_nasid(void); + extern nasid_t snia_get_master_baseio_nasid(void); extern void sn_cpu_init(void); + extern nasid_t snia_get_console_nasid(void); + MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY; @@ -263,11 +243,9 @@ sn_setup(char **cmdline_p) panic("PROM version too old\n"); } - io_sh_swapper(get_nasid(), 0); - master_nasid = get_nasid(); - (void)get_console_nasid(); - (void)get_master_baseio_nasid(); + (void)snia_get_console_nasid(); + (void)snia_get_master_baseio_nasid(); status = ia64_sal_freq_base(SAL_FREQ_BASE_REALTIME_CLOCK, &ticks_per_sec, &drift); if (status != 0 || ticks_per_sec < 100000) { @@ -312,6 +290,12 @@ sn_setup(char **cmdline_p) */ sn_cpu_init(); + /* + * Setup hubinfo stuff. Has to happen AFTER sn_cpu_init(), + * because it uses the cnode to nasid tables. + */ + init_platform_hubinfo(nodepdaindr); + #ifdef CONFIG_SMP init_smp_config(); #endif @@ -329,6 +313,7 @@ void sn_init_pdas(char **cmdline_p) { cnodeid_t cnode; + void scan_for_ionodes(void); /* * Make sure that the PDA fits entirely in the same page as the @@ -341,6 +326,9 @@ sn_init_pdas(char **cmdline_p) for (cnode=0; cnodecnodeid_to_nasid_table[cnode] = pxm_to_nasid(nid_to_pxm_map[cnode]); + numionodes = numnodes; + scan_for_ionodes(); + /* * Allocate & initalize the nodepda for each node. */ @@ -398,9 +386,6 @@ sn_cpu_init(void) cnode = nasid_to_cnodeid(nasid); slice = cpu_physical_id_to_slice(cpuphyid); - printk("CPU %d: nasid %d, slice %d, cnode %d\n", - smp_processor_id(), nasid, slice, cnode); - memset(pda, 0, sizeof(pda)); pda->p_nodepda = nodepdaindr[cnode]; pda->led_address = (typeof(pda->led_address)) (LED0 + (slice< + ch_board_info); + } +} diff -puN arch/ia64/sn/kernel/sn2/cache.c~linus arch/ia64/sn/kernel/sn2/cache.c --- 25/arch/ia64/sn/kernel/sn2/cache.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/sn2/cache.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,4 @@ /* - * * 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. @@ -8,9 +7,7 @@ * */ -#include -#include -#include +#include /** * sn_flush_all_caches - flush a range of address from all caches (incl. L4) diff -puN arch/ia64/sn/kernel/sn2/Makefile~linus arch/ia64/sn/kernel/sn2/Makefile --- 25/arch/ia64/sn/kernel/sn2/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/sn2/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,7 +9,5 @@ # sn2 specific kernel files # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \ prominfo_proc.o timer.o diff -puN arch/ia64/sn/kernel/sn2/sn2_smp.c~linus arch/ia64/sn/kernel/sn2/sn2_smp.c --- 25/arch/ia64/sn/kernel/sn2/sn2_smp.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,35 +1,11 @@ /* * SN2 Platform specific SMP Support * + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include diff -puN arch/ia64/sn/kernel/sn2/sn_proc_fs.c~linus arch/ia64/sn/kernel/sn2/sn_proc_fs.c --- 25/arch/ia64/sn/kernel/sn2/sn_proc_fs.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/kernel/sn2/sn_proc_fs.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,34 +1,9 @@ /* + * 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) 2000-2003 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 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/NoticeExplan */ #include #include diff -puN arch/ia64/sn/Makefile~linus arch/ia64/sn/Makefile --- 25/arch/ia64/sn/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ia64/sn/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,6 +9,4 @@ # Makefile for the sn ia64 subplatform # -EXTRA_CFLAGS := -DLITTLE_ENDIAN - obj-y += kernel/ io/ diff -puN arch/m68k/amiga/amisound.c~linus arch/m68k/amiga/amisound.c --- 25/arch/m68k/amiga/amisound.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/amiga/amisound.c 2004-01-19 22:17:21.000000000 -0800 @@ -44,7 +44,7 @@ static unsigned long clock_constant; void __init amiga_init_sound(void) { - static struct resource beep_res = { "Beep" }; + static struct resource beep_res = { .name = "Beep" }; snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res); if (!snd_data) { diff -puN arch/m68k/amiga/chipram.c~linus arch/m68k/amiga/chipram.c --- 25/arch/m68k/amiga/chipram.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/amiga/chipram.c 2004-01-19 22:17:21.000000000 -0800 @@ -19,7 +19,9 @@ unsigned long amiga_chip_size; -static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR }; +static struct resource chipram_res = { + .name = "Chip RAM", .start = CHIP_PHYSADDR +}; static unsigned long chipavail; diff -puN arch/m68k/amiga/config.c~linus arch/m68k/amiga/config.c --- 25/arch/m68k/amiga/config.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/amiga/config.c 2004-01-19 22:17:21.000000000 -0800 @@ -121,14 +121,22 @@ static struct console amiga_console_driv static struct { struct resource _ciab, _ciaa, _custom, _kickstart; } mb_resources = { - ._ciab = { "CIA B", 0x00bfd000, 0x00bfdfff }, - ._ciaa = { "CIA A", 0x00bfe000, 0x00bfefff }, - ._custom = { "Custom I/O", 0x00dff000, 0x00dfffff }, - ._kickstart = { "Kickstart ROM", 0x00f80000, 0x00ffffff } + ._ciab = { + .name = "CIA B", .start = 0x00bfd000, .end = 0x00bfdfff + }, + ._ciaa = { + .name = "CIA A", .start = 0x00bfe000, .end = 0x00bfefff + }, + ._custom = { + .name = "Custom I/O", .start = 0x00dff000, .end = 0x00dfffff + }, + ._kickstart = { + .name = "Kickstart ROM", .start = 0x00f80000, .end = 0x00ffffff + } }; static struct resource rtc_resource = { - NULL, 0x00dc0000, 0x00dcffff + .start = 0x00dc0000, .end = 0x00dcffff }; static struct resource ram_resource[NUM_MEMINFO]; @@ -495,7 +503,7 @@ static void __init amiga_sched_init(irqr struct pt_regs *)) { static struct resource sched_res = { - "timer", 0x00bfd400, 0x00bfd5ff, + .name = "timer", .start = 0x00bfd400, .end = 0x00bfd5ff, }; jiffy_ticks = (amiga_eclock+HZ/2)/HZ; @@ -798,12 +806,12 @@ static void amiga_mem_console_write(stru static void amiga_savekmsg_init(void) { - static struct resource debug_res = { "Debug" }; + static struct resource debug_res = { .name = "Debug" }; savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; - savekmsg->magicptr = virt_to_phys(savekmsg); + savekmsg->magicptr = ZTWO_PADDR(savekmsg); savekmsg->size = 0; } diff -puN arch/m68k/atari/hades-pci.c~linus arch/m68k/atari/hades-pci.c --- 25/arch/m68k/atari/hades-pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/atari/hades-pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -40,13 +40,20 @@ static const char pci_mem_name[] = "PCI static const char pci_io_name[] = "PCI I/O space"; static const char pci_config_name[] = "PCI config space"; -static struct resource config_space = { pci_config_name, HADES_CONFIG_BASE, - HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1 }; -static struct resource io_space = { pci_io_name, HADES_IO_BASE, HADES_IO_BASE + - HADES_IO_SIZE - 1 }; +static struct resource config_space = { + .name = pci_config_name, + .start = HADES_CONFIG_BASE, + .end = HADES_CONFIG_BASE + HADES_CONFIG_SIZE - 1 +}; +static struct resource io_space = { + .name = pci_io_name, + .start = HADES_IO_BASE, + .end = HADES_IO_BASE + HADES_IO_SIZE - 1 +}; -static const unsigned long pci_conf_base_phys[] = { 0xA0080000, 0xA0040000, - 0xA0020000, 0xA0010000 }; +static const unsigned long pci_conf_base_phys[] = { + 0xA0080000, 0xA0040000, 0xA0020000, 0xA0010000 +}; static unsigned long pci_conf_base_virt[N_SLOTS]; static unsigned long pci_io_base_virt; diff -puN arch/m68k/bvme6000/rtc.c~linus arch/m68k/bvme6000/rtc.c --- 25/arch/m68k/bvme6000/rtc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/bvme6000/rtc.c 2004-01-19 22:17:21.000000000 -0800 @@ -53,6 +53,7 @@ static int rtc_ioctl(struct inode *inode /* Ensure clock and real-time-mode-register are accessible */ msr = rtc->msr & 0xc0; rtc->msr = 0x40; + memset(&wtime, 0, sizeof(struct rtc_time)); do { wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); @@ -164,11 +165,10 @@ static struct file_operations rtc_fops = .release = rtc_release, }; -static struct miscdevice rtc_dev= -{ - RTC_MINOR, - "rtc", - &rtc_fops +static struct miscdevice rtc_dev = { + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops }; int __init rtc_DP8570A_init(void) diff -puN arch/m68k/kernel/head.S~linus arch/m68k/kernel/head.S --- 25/arch/m68k/kernel/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/kernel/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -23,7 +23,7 @@ ** 98/04/25 Phil Blundell: added HP300 support ** 1998/08/30 David Kilzer: Added support for font_desc structures ** for linux-2.1.115 -** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) +** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) ** ** This file is subject to the terms and conditions of the GNU General Public ** License. See the file README.legal in the main directory of this archive @@ -100,14 +100,14 @@ * * While this essentially describes the function in the abstract, you'll * find more indepth description of other parameters at the implementation site. - * + * * mmu_get_root_table_entry * ------------------------ * mmu_get_ptr_table_entry * ----------------------- * mmu_get_page_table_entry * ------------------------ - * + * * These routines are used by other mmu routines to get a pointer into * a table, if necessary a new table is allocated. These routines are working * basically like pmd_alloc() and pte_alloc() in . The root @@ -273,6 +273,7 @@ */ #define CONSOLE +#define CONSOLE_PENGUIN /* * Macintosh serial debug support; outputs boot info to the printer @@ -310,8 +311,8 @@ .globl mvme_bdid #endif #ifdef CONFIG_Q40 -.globl q40_mem_cptr -#endif +.globl q40_mem_cptr +#endif #ifdef CONFIG_HP300 .globl hp300_phys_ram_base #endif @@ -422,7 +423,7 @@ PAGE_INDEX_SHIFT = 12 L(\name): linkw %a6,#-\stack moveml \saveregs,%sp@- -.set stackstart,-\stack +.set stackstart,-\stack .macro func_return_\name moveml %sp@+,\saveregs @@ -483,6 +484,12 @@ func_define set_leds func_define serial_putc,1 func_define console_putc,1 +func_define console_init +func_define console_put_stats +func_define console_put_penguin +func_define console_plot_pixel,3 +func_define console_scroll + .macro putc ch #if defined(CONSOLE) || defined(SERIAL_DEBUG) pea \ch @@ -586,7 +593,7 @@ ENTRY(_stext) .long MACH_MVME16x, MVME16x_BOOTI_VERSION .long MACH_BVME6000, BVME6000_BOOTI_VERSION .long MACH_MAC, MAC_BOOTI_VERSION - .long MACH_Q40, Q40_BOOTI_VERSION + .long MACH_Q40, Q40_BOOTI_VERSION .long 0 1: jra __start @@ -604,8 +611,8 @@ ENTRY(__start) address (apparently 0xff002000 in practice) which is not good if we need to be able to map this to VA 0x1000. We could do it with pagetables but a better solution seems to be to relocate the kernel in physical memory - before we start. - + before we start. + So, we copy the entire kernel image (code+data+bss) down to the 16MB boundary that marks the start of RAM. This is slightly tricky because we must not overwrite the copying code itself. :-) */ @@ -650,7 +657,7 @@ Lcopystart: movel %d6,%a0 addl #Lstart1,%a0 jmp %a0@ -Lcopyend: +Lcopyend: Lstart1: moveb #0x3f,%d7 @@ -960,11 +967,11 @@ L(gvtdone): #ifdef CONFIG_MAC is_not_mac(L(nocon)) #ifdef CONSOLE - jbsr L(console_init) + console_init #ifdef CONSOLE_PENGUIN - jbsr L(console_put_penguin) + console_put_penguin #endif /* CONSOLE_PENGUIN */ - jbsr L(console_put_stats) + console_put_stats #endif /* CONSOLE */ L(nocon): #endif /* CONFIG_MAC */ @@ -1108,12 +1115,12 @@ L(mmu_init_not_atari): mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S - + jbra L(mmu_init_done) - -L(notq40): -#endif - + +L(notq40): +#endif + #ifdef CONFIG_HP300 is_not_hp300(L(nothp300)) @@ -1130,18 +1137,18 @@ L(nothp300): #ifdef CONFIG_MVME147 - is_not_mvme147(L(not147)) + is_not_mvme147(L(not147)) - /* - * On MVME147 we have already created kernel page tables for - * 4MB of RAM at address 0, so now need to do a transparent - * mapping of the top of memory space. Make it 0.5GByte for now, - * so we can access on-board i/o areas. - */ + /* + * On MVME147 we have already created kernel page tables for + * 4MB of RAM at address 0, so now need to do a transparent + * mapping of the top of memory space. Make it 0.5GByte for now, + * so we can access on-board i/o areas. + */ - mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 + mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 - jbra L(mmu_init_done) + jbra L(mmu_init_done) L(not147): #endif /* CONFIG_MVME147 */ @@ -1226,10 +1233,6 @@ L(mmu_init_mac): putc 'F' - lea %pc@(L(mac_videobase)),%a0 - lea %pc@(L(console_video_virtual)),%a1 - movel %a0@,%a1@ - is_not_040_or_060(1f) moveq #_PAGE_NOCACHE_S,%d3 @@ -1243,14 +1246,14 @@ L(mmu_init_mac): */ movel #VIDEOMEMMASK,%d0 - andl L(mac_videobase),%d0 + andl %pc@(L(mac_videobase)),%d0 mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3 - /* The ROM starts at 4000 0000 */ + /* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */ mmu_map_eq #0x40000000,#0x02000000,%d3 - /* IO devices */ + /* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */ mmu_map_eq #0x50000000,#0x03000000,%d3 - /* NuBus slot space */ + /* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */ mmu_map_tt #1,#0xf8000000,#0x08000000,%d3 jbra L(mmu_init_done) @@ -1284,7 +1287,7 @@ L(mmu_init_not_mac): andl #PAGE_TABLE_SIZE-1, %d0 mmu_get_page_table_entry %a0,%d0 - /* this is where the prom page table lives */ + /* this is where the prom page table lives */ movel 0xfefe00d4, %a1 movel %a1@, %a1 @@ -1295,11 +1298,11 @@ L(mmu_init_not_mac): movel %d3,%a0@+ addl #0x1000,%d3 movel %d3,%a0@+ - - dbra %d1,1b - + + dbra %d1,1b + /* setup tt1 for I/O */ - mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S + mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S jbra L(mmu_init_done) L(notsun3x): @@ -1310,8 +1313,8 @@ L(notsun3x): putc 'P' mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 - -L(notapollo): + +L(notapollo): jbra L(mmu_init_done) #endif @@ -1342,7 +1345,7 @@ L(mmu_fixup): #endif /* first fix the page at the start of the kernel, that - * contains also kernel_pg_dir. + * contains also kernel_pg_dir. */ movel %pc@(L(phys_kernel_start)),%d0 subl #PAGE_OFFSET,%d0 @@ -1462,9 +1465,15 @@ L(mmu_fixup_done): andl L(mac_videobase),%d0 addl #VIDEOMEMBASE,%d0 movel %d0,L(mac_videobase) +#if defined(CONSOLE) + movel %pc@(L(phys_kernel_start)),%d0 + subl #PAGE_OFFSET,%d0 + subl %d0,L(console_font) + subl %d0,L(console_font_data) +#endif #ifdef MAC_SERIAL_DEBUG orl #0x50000000,L(mac_sccbase) -#endif +#endif 1: #endif @@ -1486,20 +1495,20 @@ L(mmu_fixup_done): is_not_sun3x(1f) /* enable copro */ - oriw #0x4000,0x61000000 + oriw #0x4000,0x61000000 1: #endif #ifdef CONFIG_APOLLO is_not_apollo(1f) - /* + /* * Fix up the iobase before printing - */ - movel #0x80000000,L(iobase) + */ + movel #0x80000000,L(iobase) 1: #endif - + putc 'I' leds 0x10 @@ -1889,7 +1898,7 @@ mmu_030_print: movel %a4,%d5 addil #PAGESIZE<<13,%d5 movel %a0@+,%d6 - btst #1,%d6 /* is it a ptr? */ + btst #1,%d6 /* is it a table ptr? */ jbne 31f /* yes */ btst #0,%d6 /* is it early terminating? */ jbeq 1f /* no */ @@ -1906,9 +1915,9 @@ mmu_030_print: movel %a4,%d5 addil #PAGESIZE<<6,%d5 movel %a1@+,%d6 - btst #1,%d6 - jbne 33f - btst #0,%d6 + btst #1,%d6 /* is it a table ptr? */ + jbne 33f /* yes */ + btst #0,%d6 /* is it a page descriptor? */ jbeq 1f /* no */ jbsr mmu_030_print_helper jbra 37f @@ -2981,7 +2990,7 @@ L(serial_init_not_mac): - check for '%LX$' signature in SRAM */ lea %pc@(q40_mem_cptr),%a1 move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */ - move.l #0xff020000,%a1 + move.l #0xff020000,%a1 cmp.b #'%',%a1@ bne 2f /*nodbg*/ addq.w #4,%a1 @@ -2996,10 +3005,10 @@ L(serial_init_not_mac): /* signature OK */ lea %pc@(L(q40_do_debug)),%a1 tas %a1@ -/*nodbg: q40_do_debug is 0 by default*/ -2: -#endif - +/*nodbg: q40_do_debug is 0 by default*/ +2: +#endif + #ifdef CONFIG_APOLLO /* We count on the PROM initializing SIO1 */ #endif @@ -3152,7 +3161,7 @@ func_start serial_putc,%d0/%d1/%a0/%a1 moveml %sp@+,%d0-%d7/%a2-%a6 jbra L(serial_putc_done) 2: -#endif CONFIG_MVME16x +#endif /* CONFIG_MVME16x */ #ifdef CONFIG_BVME6000 is_not_bvme6000(2f) @@ -3167,15 +3176,15 @@ func_start serial_putc,%d0/%d1/%a0/%a1 #endif #ifdef CONFIG_SUN3X - is_not_sun3x(2f) + is_not_sun3x(2f) movel %d0,-(%sp) movel 0xFEFE0018,%a1 jbsr (%a1) addq #4,%sp jbra L(serial_putc_done) -2: +2: #endif - + #ifdef CONFIG_Q40 is_not_q40(2f) tst.l %pc@(L(q40_do_debug)) /* only debug if requested */ @@ -3186,16 +3195,16 @@ func_start serial_putc,%d0/%d1/%a0/%a1 addq.l #4,%a0 move.l %a0,%a1@ jbra L(serial_putc_done) -2: -#endif +2: +#endif #ifdef CONFIG_APOLLO is_not_apollo(2f) movl %pc@(L(iobase)),%a1 - moveb %d0,%a1@(LTHRB0) + moveb %d0,%a1@(LTHRB0) 1: moveb %a1@(LSRB0),%d0 - andb #0x4,%d0 - beq 1b + andb #0x4,%d0 + beq 1b 2: #endif @@ -3212,7 +3221,7 @@ func_start puts,%d0/%a0 1: #ifdef CONSOLE console_putc %d0 -#endif +#endif #ifdef SERIAL_DEBUG serial_putc %d0 #endif @@ -3241,7 +3250,7 @@ func_start putn,%d0-%d2 2: #ifdef CONSOLE console_putc %d2 -#endif +#endif #ifdef SERIAL_DEBUG serial_putc %d2 #endif @@ -3290,7 +3299,7 @@ func_start set_leds,%d0/%a0 moveb %d0,%a0@(0x1ffff) jra 2f #endif -1: +1: #ifdef CONFIG_APOLLO movel %pc@(L(iobase)),%a0 lsll #8,%d0 @@ -3313,7 +3322,7 @@ func_return set_leds #define Lconsole_struct_left_edge 16 #define Lconsole_struct_penguin_putc 20 -L(console_init): +func_start console_init,%a0-%a4/%d0-%d7 /* * Some of the register usage that follows * a0 = pointer to boot_info @@ -3327,30 +3336,27 @@ L(console_init): * d5 = number of bytes per scan line * d6 = number of bytes on the entire screen */ - moveml %a0-%a4/%d0-%d7,%sp@- lea %pc@(L(console_globals)),%a2 - lea %pc@(L(mac_videobase)),%a0 - movel %a0@,%a1 - lea %pc@(L(mac_rowbytes)),%a0 - movel %a0@,%d5 - lea %pc@(L(mac_dimensions)),%a0 - movel %a0@,%d3 /* -> low byte */ + movel %pc@(L(mac_videobase)),%a1 + movel %pc@(L(mac_rowbytes)),%d5 + movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */ movel %d3,%d4 swap %d4 /* -> high byte */ andl #0xffff,%d3 /* d3 = screen width in pixels */ andl #0xffff,%d4 /* d4 = screen height in pixels */ movel %d5,%d6 - subl #20,%d6 +| subl #20,%d6 mulul %d4,%d6 /* scan line bytes x num scan lines */ divul #8,%d6 /* we'll clear 8 bytes at a time */ + moveq #-1,%d0 /* Mac_black */ subq #1,%d6 -console_clear_loop: - movel #0xffffffff,%a1@+ /* Mac_black */ - movel #0xffffffff,%a1@+ /* Mac_black */ - dbra %d6,console_clear_loop +L(console_clear_loop): + movel %d0,%a1@+ + movel %d0,%a1@+ + dbra %d6,L(console_clear_loop) /* Calculate font size */ @@ -3368,12 +3374,17 @@ console_clear_loop: /* * At this point we make a shift in register usage - * a1 = address of Lconsole_font pointer + * a1 = address of console_font pointer */ lea %pc@(L(console_font)),%a1 - movel %a0,%a1@ /* store pointer to struct font_desc in Lconsole_font */ + movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */ tstl %a0 jeq 1f + lea %pc@(L(console_font_data)),%a4 + movel %a0@(FONT_DESC_DATA),%d0 + subl #L(console_font),%a1 + addl %a1,%d0 + movel %d0,%a4@ /* * Calculate global maxs @@ -3382,11 +3393,11 @@ console_clear_loop: * 6 x 11 also supported */ /* ASSERT: a0 = contents of Lconsole_font */ - movel %d3,%d0 /* screen width in pixels */ - divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */ + movel %d3,%d0 /* screen width in pixels */ + divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */ - movel %d4,%d1 /* screen height in pixels */ - divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */ + movel %d4,%d1 /* screen height in pixels */ + divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */ movel %d0,%a2@(Lconsole_struct_num_columns) movel %d1,%a2@(Lconsole_struct_num_rows) @@ -3401,17 +3412,15 @@ console_clear_loop: /* * Initialization is complete */ -1: moveml %sp@+,%a0-%a4/%d0-%d7 - rts +1: +func_return console_init -L(console_put_stats): +func_start console_put_stats,%a0/%d7 /* * Some of the register usage that follows * a0 = pointer to boot_info * d7 = value of boot_info fields */ - moveml %a0/%d7,%sp@- - puts "\nMacLinux\n\n" #ifdef SERIAL_DEBUG @@ -3433,58 +3442,57 @@ L(console_put_stats): #ifdef MAC_SERIAL_DEBUG putn %pc@(L(mac_sccbase)) putc '\n' -#endif +#endif # if defined(MMU_PRINT) jbsr mmu_print_machine_cpu_types # endif /* MMU_PRINT */ #endif /* SERIAL_DEBUG */ - moveml %sp@+,%a0/%d7 - rts +func_return console_put_stats #ifdef CONSOLE_PENGUIN -L(console_put_penguin): +func_start console_put_penguin,%a0-%a1/%d0-%d7 /* * Get 'that_penguin' onto the screen in the upper right corner * penguin is 64 x 74 pixels, align against right edge of screen */ - moveml %a0-%a1/%d0-%d7,%sp@- - lea %pc@(L(mac_dimensions)),%a0 movel %a0@,%d0 andil #0xffff,%d0 subil #64,%d0 /* snug up against the right edge */ clrl %d1 /* start at the top */ movel #73,%d7 - lea %pc@(that_penguin),%a1 -console_penguin_row: + lea %pc@(L(that_penguin)),%a1 +L(console_penguin_row): movel #31,%d6 -console_penguin_pixel_pair: +L(console_penguin_pixel_pair): moveb %a1@,%d2 lsrb #4,%d2 - jbsr console_plot_pixel + console_plot_pixel %d0,%d1,%d2 addq #1,%d0 moveb %a1@+,%d2 - jbsr console_plot_pixel + console_plot_pixel %d0,%d1,%d2 addq #1,%d0 - dbra %d6,console_penguin_pixel_pair + dbra %d6,L(console_penguin_pixel_pair) subil #64,%d0 addq #1,%d1 - dbra %d7,console_penguin_row + dbra %d7,L(console_penguin_row) - moveml %sp@+,%a0-%a1/%d0-%d7 - rts -#endif +func_return console_put_penguin -console_scroll: - moveml %a0-%a4/%d0-%d7,%sp@- +/* include penguin bitmap */ +L(that_penguin): +#include "../mac/mac_penguin.S" +#endif /* * Calculate source and destination addresses * output a1 = dest * a2 = source */ + +func_start console_scroll,%a0-%a4/%d0-%d7 lea %pc@(L(mac_videobase)),%a0 movel %a0@,%a1 movel %a1,%a2 @@ -3517,7 +3525,7 @@ console_scroll: divul #32,%d6 /* we'll move 8 longs at a time */ subq #1,%d6 -console_scroll_loop: +L(console_scroll_loop): movel %a2@+,%a1@+ movel %a2@+,%a1@+ movel %a2@+,%a1@+ @@ -3526,7 +3534,7 @@ console_scroll_loop: movel %a2@+,%a1@+ movel %a2@+,%a1@+ movel %a2@+,%a1@+ - dbra %d6,console_scroll_loop + dbra %d6,L(console_scroll_loop) lea %pc@(L(mac_rowbytes)),%a0 movel %a0@,%d6 @@ -3536,7 +3544,7 @@ console_scroll_loop: subq #1,%d6 moveq #-1,%d0 -console_scroll_clear_loop: +L(console_scroll_clear_loop): movel %d0,%a1@+ movel %d0,%a1@+ movel %d0,%a1@+ @@ -3545,17 +3553,17 @@ console_scroll_clear_loop: movel %d0,%a1@+ movel %d0,%a1@+ movel %d0,%a1@+ - dbra %d6,console_scroll_clear_loop + dbra %d6,L(console_scroll_clear_loop) -1: moveml %sp@+,%a0-%a4/%d0-%d7 - rts +1: +func_return console_scroll func_start console_putc,%a0/%a1/%d0-%d7 - is_not_mac(console_exit) + is_not_mac(L(console_exit)) tstl %pc@(L(console_font)) - jeq console_exit + jeq L(console_exit) /* Output character in d7 on console. */ @@ -3569,7 +3577,7 @@ func_start console_putc,%a0/%a1/%d0-%d7 lea %pc@(L(console_globals)),%a0 cmpib #10,%d7 - jne console_not_lf + jne L(console_not_lf) movel %a0@(Lconsole_struct_cur_row),%d0 addil #1,%d0 movel %d0,%a0@(Lconsole_struct_cur_row) @@ -3578,22 +3586,22 @@ func_start console_putc,%a0/%a1/%d0-%d7 jcs 1f subil #1,%d0 movel %d0,%a0@(Lconsole_struct_cur_row) - jbsr console_scroll + console_scroll 1: - jra console_exit + jra L(console_exit) -console_not_lf: +L(console_not_lf): cmpib #13,%d7 - jne console_not_cr + jne L(console_not_cr) clrl %a0@(Lconsole_struct_cur_column) - jra console_exit + jra L(console_exit) -console_not_cr: +L(console_not_cr): cmpib #1,%d7 - jne console_not_home + jne L(console_not_home) clrl %a0@(Lconsole_struct_cur_row) clrl %a0@(Lconsole_struct_cur_column) - jra console_exit + jra L(console_exit) /* * At this point we know that the %d7 character is going to be @@ -3604,9 +3612,9 @@ console_not_cr: * d1 = cursor row to draw the character * d7 = character number */ -console_not_home: +L(console_not_home): movel %a0@(Lconsole_struct_cur_column),%d0 - addil #1,%a0@(Lconsole_struct_cur_column) + addql #1,%a0@(Lconsole_struct_cur_column) movel %a0@(Lconsole_struct_num_columns),%d1 cmpl %d1,%d0 jcs 1f @@ -3616,10 +3624,10 @@ console_not_home: /* * At this point we make a shift in register usage - * a0 = address of pointer to font data (font_desc) + * a0 = address of pointer to font data (fbcon_font_desc) */ movel %pc@(L(console_font)),%a0 - movel %a0@(FONT_DESC_DATA),%a1 /* Load font_desc.data into a1 */ + movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */ andl #0x000000ff,%d7 /* ASSERT: a0 = contents of Lconsole_font */ mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */ @@ -3637,32 +3645,30 @@ console_not_home: /* ASSERT: a0 = contents of Lconsole_font */ mulul %a0@(FONT_DESC_WIDTH),%d0 mulul %a0@(FONT_DESC_HEIGHT),%d1 - movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load font_desc.height into d7 */ + movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */ subq #1,%d7 -console_read_char_scanline: +L(console_read_char_scanline): moveb %a1@+,%d3 /* ASSERT: a0 = contents of Lconsole_font */ - movel %a0@(FONT_DESC_WIDTH),%d6 /* Load font_desc.width into d6 */ + movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */ subql #1,%d6 -console_do_font_scanline: +L(console_do_font_scanline): lslb #1,%d3 scsb %d2 /* convert 1 bit into a byte */ - jbsr console_plot_pixel + console_plot_pixel %d0,%d1,%d2 addq #1,%d0 - dbra %d6,console_do_font_scanline + dbra %d6,L(console_do_font_scanline) /* ASSERT: a0 = contents of Lconsole_font */ subl %a0@(FONT_DESC_WIDTH),%d0 addq #1,%d1 - dbra %d7,console_read_char_scanline - -console_exit: + dbra %d7,L(console_read_char_scanline) +L(console_exit): func_return console_putc -console_plot_pixel: /* * Input: * d0 = x coordinate @@ -3670,14 +3676,14 @@ console_plot_pixel: * d2 = (bit 0) 1/0 for white/black (!) * All registers are preserved */ - moveml %a0-%a1/%d0-%d4,%sp@- +func_start console_plot_pixel,%a0-%a1/%d0-%d4 - lea %pc@(L(mac_videobase)),%a0 - movel %a0@,%a1 - lea %pc@(L(mac_videodepth)),%a0 - movel %a0@,%d3 - lea %pc@(L(mac_rowbytes)),%a0 - mulul %a0@,%d1 + movel %pc@(L(mac_videobase)),%a1 + movel %pc@(L(mac_videodepth)),%d3 + movel ARG1,%d0 + movel ARG2,%d1 + mulul %pc@(L(mac_rowbytes)),%d1 + movel ARG3,%d2 /* * Register usage: @@ -3686,13 +3692,10 @@ console_plot_pixel: * d2 = black or white (0/1) * d3 = video depth * d4 = temp of x (d0) for many bit depths - * d5 = unused - * d6 = unused - * d7 = unused */ -test_1bit: +L(test_1bit): cmpb #1,%d3 - jbne test_2bit + jbne L(test_2bit) movel %d0,%d4 /* we need the low order 3 bits! */ divul #8,%d0 addal %d0,%a1 @@ -3700,16 +3703,16 @@ test_1bit: andb #7,%d4 eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */ andb #1,%d2 - jbne white_1 + jbne L(white_1) bsetb %d4,%a1@ - jbra console_plot_pixel_exit -white_1: + jbra L(console_plot_pixel_exit) +L(white_1): bclrb %d4,%a1@ - jbra console_plot_pixel_exit + jbra L(console_plot_pixel_exit) -test_2bit: +L(test_2bit): cmpb #2,%d3 - jbne test_4bit + jbne L(test_4bit) movel %d0,%d4 /* we need the low order 2 bits! */ divul #4,%d0 addal %d0,%a1 @@ -3718,20 +3721,20 @@ test_2bit: eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */ lsll #1,%d4 /* ! */ andb #1,%d2 - jbne white_2 + jbne L(white_2) bsetb %d4,%a1@ addq #1,%d4 bsetb %d4,%a1@ - jbra console_plot_pixel_exit -white_2: + jbra L(console_plot_pixel_exit) +L(white_2): bclrb %d4,%a1@ addq #1,%d4 bclrb %d4,%a1@ - jbra console_plot_pixel_exit + jbra L(console_plot_pixel_exit) -test_4bit: +L(test_4bit): cmpb #4,%d3 - jbne test_8bit + jbne L(test_8bit) movel %d0,%d4 /* we need the low order bit! */ divul #2,%d0 addal %d0,%a1 @@ -3740,7 +3743,7 @@ test_4bit: eorb #1,%d4 lsll #2,%d4 /* ! */ andb #1,%d2 - jbne white_4 + jbne L(white_4) bsetb %d4,%a1@ addq #1,%d4 bsetb %d4,%a1@ @@ -3748,8 +3751,8 @@ test_4bit: bsetb %d4,%a1@ addq #1,%d4 bsetb %d4,%a1@ - jbra console_plot_pixel_exit -white_4: + jbra L(console_plot_pixel_exit) +L(white_4): bclrb %d4,%a1@ addq #1,%d4 bclrb %d4,%a1@ @@ -3757,38 +3760,37 @@ white_4: bclrb %d4,%a1@ addq #1,%d4 bclrb %d4,%a1@ - jbra console_plot_pixel_exit + jbra L(console_plot_pixel_exit) -test_8bit: +L(test_8bit): cmpb #8,%d3 - jbne test_16bit + jbne L(test_16bit) addal %d0,%a1 addal %d1,%a1 andb #1,%d2 - jbne white_8 + jbne L(white_8) moveb #0xff,%a1@ - jbra console_plot_pixel_exit -white_8: + jbra L(console_plot_pixel_exit) +L(white_8): clrb %a1@ - jbra console_plot_pixel_exit + jbra L(console_plot_pixel_exit) -test_16bit: +L(test_16bit): cmpb #16,%d3 - jbne console_plot_pixel_exit + jbne L(console_plot_pixel_exit) addal %d0,%a1 addal %d0,%a1 addal %d1,%a1 andb #1,%d2 - jbne white_16 + jbne L(white_16) clrw %a1@ - jbra console_plot_pixel_exit -white_16: + jbra L(console_plot_pixel_exit) +L(white_16): movew #0x0fff,%a1@ - jbra console_plot_pixel_exit + jbra L(console_plot_pixel_exit) -console_plot_pixel_exit: - moveml %sp@+,%a0-%a1/%d0-%d4 - rts +L(console_plot_pixel_exit): +func_return console_plot_pixel #endif /* CONSOLE */ #if 0 @@ -3838,11 +3840,6 @@ L(iobase): .long 0 #endif -#ifdef CONFIG_MAC -L(console_video_virtual): - .long 0 -#endif /* CONFIG_MAC */ - #if defined(CONSOLE) L(console_globals): .long 0 /* cursor column */ @@ -3853,6 +3850,8 @@ L(console_globals): .long 0 /* mac putc */ L(console_font): .long 0 /* pointer to console font (struct font_desc) */ +L(console_font_data): + .long 0 /* pointer to console font data */ #endif /* CONSOLE */ #if defined(MMU_PRINT) @@ -3941,7 +3940,7 @@ mvme_bdid: #endif #if defined(CONFIG_Q40) q40_mem_cptr: - .long 0 -L(q40_do_debug): - .long 0 + .long 0 +L(q40_do_debug): + .long 0 #endif diff -puN arch/m68k/kernel/traps.c~linus arch/m68k/kernel/traps.c --- 25/arch/m68k/kernel/traps.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/kernel/traps.c 2004-01-19 22:17:21.000000000 -0800 @@ -447,7 +447,7 @@ extern int mmu_emu_handle_fault (unsigne /* sun3 version of bus_error030 */ -extern inline void bus_error030 (struct frame *fp) +static inline void bus_error030 (struct frame *fp) { unsigned char buserr_type = sun3_get_buserr (); unsigned long addr, errorcode; @@ -583,12 +583,9 @@ static inline void bus_error030 (struct unsigned short mmusr; unsigned long addr, errorcode; unsigned short ssw = fp->un.fmtb.ssw; - int user_space_fault = 1; #if DEBUG unsigned long desc; -#endif -#if DEBUG printk ("pid = %x ", current->pid); printk ("SSW=%#06x ", ssw); @@ -605,128 +602,116 @@ static inline void bus_error030 (struct space_names[ssw & DFC], fp->ptregs.pc); #endif - if (fp->ptregs.sr & PS_S) { - /* kernel fault must be a data fault to user space */ - if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { - /* instruction fault or kernel data fault! */ - if (ssw & (FC | FB)) - printk ("Instruction fault at %#010lx\n", - fp->ptregs.pc); - if (ssw & DF) { - printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", - ssw & RW ? "read" : "write", - fp->un.fmtb.daddr, - space_names[ssw & DFC], fp->ptregs.pc); - } - printk ("BAD KERNEL BUSERR\n"); - die_if_kernel("Oops",&fp->ptregs,0); - force_sig(SIGKILL, current); - return; - } - } else { - /* user fault */ - if (!(ssw & (FC | FB)) && !(ssw & DF)) - /* not an instruction fault or data fault! BAD */ - panic ("USER BUSERR w/o instruction or data fault"); - user_space_fault = 1; -#if DEBUG - printk("User space bus-error\n"); -#endif - } - /* ++andreas: If a data fault and an instruction fault happen at the same time map in both pages. */ /* First handle the data fault, if any. */ - if (ssw & DF) - { - addr = fp->un.fmtb.daddr; + if (ssw & DF) { + addr = fp->un.fmtb.daddr; - mmusr = MMU_I; - if (user_space_fault) { #if DEBUG - asm volatile ("ptestr #1,%2@,#7,%0\n\t" - "pmove %/psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr)); + asm volatile ("ptestr %3,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr), "d" (ssw)); #else - asm volatile ("ptestr #1,%1@,#7\n\t" - "pmove %/psr,%0@" - : : "a" (&temp), "a" (addr)); -#endif - mmusr = temp; - } - -#if DEBUG - printk ("mmusr is %#x for addr %#lx in task %p\n", - mmusr, addr, current); - printk ("descriptor address is %#lx, contents %#lx\n", - __va(desc), *(unsigned long *)__va(desc)); + asm volatile ("ptestr %2,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr), "d" (ssw)); #endif + mmusr = temp; - errorcode = (mmusr & MMU_I) ? 0 : 1; - if (!(ssw & RW) || (ssw & RM)) - errorcode |= 2; - - if (mmusr & (MMU_I | MMU_WP)) { - /* Don't try to do anything further if an exception was - handled. */ - if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) +#if DEBUG + printk("mmusr is %#x for addr %#lx in task %p\n", + mmusr, addr, current); + printk("descriptor address is %#lx, contents %#lx\n", + __va(desc), *(unsigned long *)__va(desc)); +#endif + + errorcode = (mmusr & MMU_I) ? 0 : 1; + if (!(ssw & RW) || (ssw & RM)) + errorcode |= 2; + + if (mmusr & (MMU_I | MMU_WP)) { + if (ssw & 4) { + printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", + ssw & RW ? "read" : "write", + fp->un.fmtb.daddr, + space_names[ssw & DFC], fp->ptregs.pc); + goto buserr; + } + /* Don't try to do anything further if an exception was + handled. */ + if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) + return; + } else if (!(mmusr & MMU_I)) { + /* propably a 020 cas fault */ + if (!(ssw & RM)) + printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); + } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { + printk("invalid %s access at %#lx from pc %#lx\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc); + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); return; - } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { - printk ("invalid %s access at %#lx from pc %#lx\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc); - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } else { + } else { #if 0 - static volatile long tlong; + static volatile long tlong; #endif - printk ("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", - !(ssw & RW) ? "write" : "read", addr, - fp->ptregs.pc, ssw); - asm volatile ("ptestr #1,%1@,#0\n\t" - "pmove %/psr,%0@" - : /* no outputs */ - : "a" (&temp), "a" (addr)); - mmusr = temp; + printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", + !(ssw & RW) ? "write" : "read", addr, + fp->ptregs.pc, ssw); + asm volatile ("ptestr #1,%1@,#0\n\t" + "pmove %%psr,%0@" + : /* no outputs */ + : "a" (&temp), "a" (addr)); + mmusr = temp; - printk ("level 0 mmusr is %#x\n", mmusr); + printk ("level 0 mmusr is %#x\n", mmusr); #if 0 - asm volatile ("pmove %/tt0,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk ("tt0 is %#lx, ", tlong); - asm volatile ("pmove %/tt1,%0@" - : /* no outputs */ - : "a" (&tlong)); - printk ("tt1 is %#lx\n", tlong); + asm volatile ("pmove %%tt0,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt0 is %#lx, ", tlong); + asm volatile ("pmove %%tt1,%0@" + : /* no outputs */ + : "a" (&tlong)); + printk("tt1 is %#lx\n", tlong); #endif #if DEBUG - printk("Unknown SIGSEGV - 1\n"); + printk("Unknown SIGSEGV - 1\n"); #endif - die_if_kernel("Oops",&fp->ptregs,mmusr); - force_sig(SIGSEGV, current); - return; - } - - /* setup an ATC entry for the access about to be retried */ - if (!(ssw & RW)) - asm volatile ("ploadw %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - else - asm volatile ("ploadr %1,%0@" : /* no outputs */ - : "a" (addr), "d" (ssw)); - } + die_if_kernel("Oops",&fp->ptregs,mmusr); + force_sig(SIGSEGV, current); + return; + } + + /* setup an ATC entry for the access about to be retried */ + if (!(ssw & RW) || (ssw & RM)) + asm volatile ("ploadw %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + else + asm volatile ("ploadr %1,%0@" : /* no outputs */ + : "a" (addr), "d" (ssw)); + } /* Now handle the instruction fault. */ if (!(ssw & (FC|FB))) return; + if (fp->ptregs.sr & PS_S) { + printk("Instruction fault at %#010lx\n", + fp->ptregs.pc); + buserr: + printk ("BAD KERNEL BUSERR\n"); + die_if_kernel("Oops",&fp->ptregs,0); + force_sig(SIGKILL, current); + return; + } + /* get the fault address */ if (fp->ptregs.format == 10) addr = fp->ptregs.pc + 4; @@ -740,21 +725,18 @@ static inline void bus_error030 (struct should still create the ATC entry. */ goto create_atc_entry; - mmusr = MMU_I; - if (user_space_fault) { #if DEBUG - asm volatile ("ptestr #1,%2@,#7,%0\n\t" - "pmove %/psr,%1@" - : "=a&" (desc) - : "a" (&temp), "a" (addr)); + asm volatile ("ptestr #1,%2@,#7,%0\n\t" + "pmove %%psr,%1@" + : "=a&" (desc) + : "a" (&temp), "a" (addr)); #else - asm volatile ("ptestr #1,%1@,#7\n\t" - "pmove %/psr,%0@" - : : "a" (&temp), "a" (addr)); + asm volatile ("ptestr #1,%1@,#7\n\t" + "pmove %%psr,%0@" + : : "a" (&temp), "a" (addr)); #endif - mmusr = temp; - } - + mmusr = temp; + #ifdef DEBUG printk ("mmusr is %#x for addr %#lx in task %p\n", mmusr, addr, current); diff -puN arch/m68k/mac/config.c~linus arch/m68k/mac/config.c --- 25/arch/m68k/mac/config.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mac/config.c 2004-01-19 22:17:21.000000000 -0800 @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -267,6 +268,7 @@ void __init config_mac(void) */ struct mac_model *macintosh_config; +EXPORT_SYMBOL(macintosh_config); static struct mac_model mac_data_table[]= { diff -puN arch/m68k/mac/misc.c~linus arch/m68k/mac/misc.c --- 25/arch/m68k/mac/misc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mac/misc.c 2004-01-19 22:17:21.000000000 -0800 @@ -39,6 +39,7 @@ extern struct mac_booter_data mac_bi_data; static void (*rom_reset)(void); +#ifdef CONFIG_ADB /* * Return the current time as the number of seconds since January 1, 1904. */ @@ -103,6 +104,7 @@ static void adb_write_pram(int offset, _ (offset >> 8) & 0xFF, offset & 0xFF, data); } +#endif /* CONFIG_ADB */ /* * VIA PRAM/RTC access routines @@ -356,7 +358,11 @@ void mac_pram_read(int offset, __u8 *buf macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2 || macintosh_config->adb_type == MAC_ADB_CUDA) { +#ifdef CONFIG_ADB func = adb_read_pram; +#else + return; +#endif } else { func = via_read_pram; } @@ -374,7 +380,11 @@ void mac_pram_write(int offset, __u8 *bu macintosh_config->adb_type == MAC_ADB_PB1 || macintosh_config->adb_type == MAC_ADB_PB2 || macintosh_config->adb_type == MAC_ADB_CUDA) { +#ifdef CONFIG_ADB func = adb_write_pram; +#else + return; +#endif } else { func = via_write_pram; } @@ -580,12 +590,16 @@ int mac_hwclk(int op, struct rtc_time *t if (!op) { /* read */ if (macintosh_config->adb_type == MAC_ADB_II) { now = via_read_time(); - } else if ((macintosh_config->adb_type == MAC_ADB_IISI) || + } else +#ifdef CONFIG_ADB + if ((macintosh_config->adb_type == MAC_ADB_IISI) || (macintosh_config->adb_type == MAC_ADB_PB1) || (macintosh_config->adb_type == MAC_ADB_PB2) || (macintosh_config->adb_type == MAC_ADB_CUDA)) { now = adb_read_time(); - } else if (macintosh_config->adb_type == MAC_ADB_IOP) { + } else +#endif + if (macintosh_config->adb_type == MAC_ADB_IOP) { now = via_read_time(); } else { now = 0; diff -puN arch/m68k/math-emu/fp_arith.c~linus arch/m68k/math-emu/fp_arith.c --- 25/arch/m68k/math-emu/fp_arith.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/math-emu/fp_arith.c 2004-01-19 22:17:21.000000000 -0800 @@ -19,12 +19,13 @@ const struct fp_ext fp_QNaN = { - 0, 0, 0x7fff, { ~0 } + .exp = 0x7fff, + .mant = { .m64 = ~0 } }; const struct fp_ext fp_Inf = { - 0, 0, 0x7fff, { 0 } + .exp = 0x7fff, }; /* let's start with the easy ones */ diff -puN arch/m68k/math-emu/fp_log.c~linus arch/m68k/math-emu/fp_log.c --- 25/arch/m68k/math-emu/fp_log.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/math-emu/fp_log.c 2004-01-19 22:17:21.000000000 -0800 @@ -19,7 +19,7 @@ static const struct fp_ext fp_one = { - 0, 0, 0x3fff, { 0 } + .exp = 0x3fff, }; extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src); diff -puN arch/m68k/math-emu/multi_arith.h~linus arch/m68k/math-emu/multi_arith.h --- 25/arch/m68k/math-emu/multi_arith.h~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/math-emu/multi_arith.h 2004-01-19 22:17:21.000000000 -0800 @@ -38,17 +38,14 @@ enum { /* Convenience functions to stuff various integer values into int128s */ -extern inline void zero128(int128 a) +static inline void zero128(int128 a) { a[LSW128] = a[NLSW128] = a[NMSW128] = a[MSW128] = 0; } /* Human-readable word order in the arguments */ -extern inline void set128(unsigned int i3, - unsigned int i2, - unsigned int i1, - unsigned int i0, - int128 a) +static inline void set128(unsigned int i3, unsigned int i2, unsigned int i1, + unsigned int i0, int128 a) { a[LSW128] = i0; a[NLSW128] = i1; @@ -57,21 +54,19 @@ extern inline void set128(unsigned int i } /* Convenience functions (for testing as well) */ -extern inline void int64_to_128(unsigned long long src, - int128 dest) +static inline void int64_to_128(unsigned long long src, int128 dest) { dest[LSW128] = (unsigned int) src; dest[NLSW128] = src >> 32; dest[NMSW128] = dest[MSW128] = 0; } -extern inline void int128_to_64(const int128 src, - unsigned long long *dest) +static inline void int128_to_64(const int128 src, unsigned long long *dest) { *dest = src[LSW128] | (long long) src[NLSW128] << 32; } -extern inline void put_i128(const int128 a) +static inline void put_i128(const int128 a) { printk("%08x %08x %08x %08x\n", a[MSW128], a[NMSW128], a[NLSW128], a[LSW128]); @@ -82,7 +77,7 @@ extern inline void put_i128(const int128 Note that these are only good for 0 < count < 32. */ -extern inline void _lsl128(unsigned int count, int128 a) +static inline void _lsl128(unsigned int count, int128 a) { a[MSW128] = (a[MSW128] << count) | (a[NMSW128] >> (32 - count)); a[NMSW128] = (a[NMSW128] << count) | (a[NLSW128] >> (32 - count)); @@ -90,7 +85,7 @@ extern inline void _lsl128(unsigned int a[LSW128] <<= count; } -extern inline void _lsr128(unsigned int count, int128 a) +static inline void _lsr128(unsigned int count, int128 a) { a[LSW128] = (a[LSW128] >> count) | (a[NLSW128] << (32 - count)); a[NLSW128] = (a[NLSW128] >> count) | (a[NMSW128] << (32 - count)); @@ -100,7 +95,7 @@ extern inline void _lsr128(unsigned int /* Should be faster, one would hope */ -extern inline void lslone128(int128 a) +static inline void lslone128(int128 a) { asm volatile ("lsl.l #1,%0\n" "roxl.l #1,%1\n" @@ -118,7 +113,7 @@ extern inline void lslone128(int128 a) "3"(a[MSW128])); } -extern inline void lsrone128(int128 a) +static inline void lsrone128(int128 a) { asm volatile ("lsr.l #1,%0\n" "roxr.l #1,%1\n" @@ -140,7 +135,7 @@ extern inline void lsrone128(int128 a) These bit-shift to a multiple of 32, then move whole longwords. */ -extern inline void lsl128(unsigned int count, int128 a) +static inline void lsl128(unsigned int count, int128 a) { int wordcount, i; @@ -159,7 +154,7 @@ extern inline void lsl128(unsigned int c } } -extern inline void lsr128(unsigned int count, int128 a) +static inline void lsr128(unsigned int count, int128 a) { int wordcount, i; @@ -177,18 +172,18 @@ extern inline void lsr128(unsigned int c } } -extern inline int orl128(int a, int128 b) +static inline int orl128(int a, int128 b) { b[LSW128] |= a; } -extern inline int btsthi128(const int128 a) +static inline int btsthi128(const int128 a) { return a[MSW128] & 0x80000000; } /* test bits (numbered from 0 = LSB) up to and including "top" */ -extern inline int bftestlo128(int top, const int128 a) +static inline int bftestlo128(int top, const int128 a) { int r = 0; @@ -206,7 +201,7 @@ extern inline int bftestlo128(int top, c /* Aargh. We need these because GCC is broken */ /* FIXME: do them in assembly, for goodness' sake! */ -extern inline void mask64(int pos, unsigned long long *mask) +static inline void mask64(int pos, unsigned long long *mask) { *mask = 0; @@ -218,7 +213,7 @@ extern inline void mask64(int pos, unsig HI_WORD(*mask) = (1 << (pos - 32)) - 1; } -extern inline void bset64(int pos, unsigned long long *dest) +static inline void bset64(int pos, unsigned long long *dest) { /* This conditional will be optimized away. Thanks, GCC! */ if (pos < 32) @@ -229,7 +224,7 @@ extern inline void bset64(int pos, unsig (HI_WORD(*dest)):"id"(pos - 32)); } -extern inline int btst64(int pos, unsigned long long dest) +static inline int btst64(int pos, unsigned long long dest) { if (pos < 32) return (0 != (LO_WORD(dest) & (1 << pos))); @@ -237,7 +232,7 @@ extern inline int btst64(int pos, unsign return (0 != (HI_WORD(dest) & (1 << (pos - 32)))); } -extern inline void lsl64(int count, unsigned long long *dest) +static inline void lsl64(int count, unsigned long long *dest) { if (count < 32) { HI_WORD(*dest) = (HI_WORD(*dest) << count) @@ -250,7 +245,7 @@ extern inline void lsl64(int count, unsi LO_WORD(*dest) = 0; } -extern inline void lsr64(int count, unsigned long long *dest) +static inline void lsr64(int count, unsigned long long *dest) { if (count < 32) { LO_WORD(*dest) = (LO_WORD(*dest) >> count) @@ -264,7 +259,7 @@ extern inline void lsr64(int count, unsi } #endif -extern inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt) +static inline void fp_denormalize(struct fp_ext *reg, unsigned int cnt) { reg->exp += cnt; @@ -306,7 +301,7 @@ extern inline void fp_denormalize(struct } } -extern inline int fp_overnormalize(struct fp_ext *reg) +static inline int fp_overnormalize(struct fp_ext *reg) { int shift; @@ -324,7 +319,7 @@ extern inline int fp_overnormalize(struc return shift; } -extern inline int fp_addmant(struct fp_ext *dest, struct fp_ext *src) +static inline int fp_addmant(struct fp_ext *dest, struct fp_ext *src) { int carry; @@ -340,7 +335,7 @@ extern inline int fp_addmant(struct fp_e return carry; } -extern inline int fp_addcarry(struct fp_ext *reg) +static inline int fp_addcarry(struct fp_ext *reg) { if (++reg->exp == 0x7fff) { if (reg->mant.m64) @@ -357,7 +352,8 @@ extern inline int fp_addcarry(struct fp_ return 1; } -extern inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, struct fp_ext *src2) +static inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, + struct fp_ext *src2) { /* we assume here, gcc only insert move and a clr instr */ asm volatile ("sub.b %1,%0" : "=d,g" (dest->lowmant) @@ -407,7 +403,8 @@ extern inline void fp_submant(struct fp_ carry; \ }) -extern inline void fp_multiplymant(union fp_mant128 *dest, struct fp_ext *src1, struct fp_ext *src2) +static inline void fp_multiplymant(union fp_mant128 *dest, struct fp_ext *src1, + struct fp_ext *src2) { union fp_mant64 temp; @@ -421,7 +418,8 @@ extern inline void fp_multiplymant(union fp_addx96(dest, temp); } -extern inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src, struct fp_ext *div) +static inline void fp_dividemant(union fp_mant128 *dest, struct fp_ext *src, + struct fp_ext *div) { union fp_mant128 tmp; union fp_mant64 tmp64; @@ -484,7 +482,7 @@ extern inline void fp_dividemant(union f } #if 0 -extern inline unsigned int fp_fls128(union fp_mant128 *src) +static inline unsigned int fp_fls128(union fp_mant128 *src) { unsigned long data; unsigned int res, off; @@ -504,7 +502,7 @@ extern inline unsigned int fp_fls128(uni return res + off; } -extern inline void fp_shiftmant128(union fp_mant128 *src, int shift) +static inline void fp_shiftmant128(union fp_mant128 *src, int shift) { unsigned long sticky; @@ -594,7 +592,8 @@ extern inline void fp_shiftmant128(union } #endif -extern inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src, int shift) +static inline void fp_putmant128(struct fp_ext *dest, union fp_mant128 *src, + int shift) { unsigned long tmp; @@ -639,7 +638,7 @@ extern inline void fp_putmant128(struct } #if 0 /* old code... */ -extern inline int fls(unsigned int a) +static inline int fls(unsigned int a) { int r; @@ -649,7 +648,7 @@ extern inline int fls(unsigned int a) } /* fls = "find last set" (cf. ffs(3)) */ -extern inline int fls128(const int128 a) +static inline int fls128(const int128 a) { if (a[MSW128]) return fls(a[MSW128]); @@ -668,12 +667,12 @@ extern inline int fls128(const int128 a) return -1; } -extern inline int zerop128(const int128 a) +static inline int zerop128(const int128 a) { return !(a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]); } -extern inline int nonzerop128(const int128 a) +static inline int nonzerop128(const int128 a) { return (a[LSW128] | a[NLSW128] | a[NMSW128] | a[MSW128]); } @@ -681,7 +680,7 @@ extern inline int nonzerop128(const int1 /* Addition and subtraction */ /* Do these in "pure" assembly, because "extended" asm is unmanageable here */ -extern inline void add128(const int128 a, int128 b) +static inline void add128(const int128 a, int128 b) { /* rotating carry flags */ unsigned int carry[2]; @@ -699,7 +698,7 @@ extern inline void add128(const int128 a } /* Note: assembler semantics: "b -= a" */ -extern inline void sub128(const int128 a, int128 b) +static inline void sub128(const int128 a, int128 b) { /* rotating borrow flags */ unsigned int borrow[2]; @@ -717,9 +716,7 @@ extern inline void sub128(const int128 a } /* Poor man's 64-bit expanding multiply */ -extern inline void mul64(unsigned long long a, - unsigned long long b, - int128 c) +static inline void mul64(unsigned long long a, unsigned long long b, int128 c) { unsigned long long acc; int128 acc128; @@ -756,7 +753,7 @@ extern inline void mul64(unsigned long l } /* Note: unsigned */ -extern inline int cmp128(int128 a, int128 b) +static inline int cmp128(int128 a, int128 b) { if (a[MSW128] < b[MSW128]) return -1; diff -puN -L arch/m68k/mm/extable.c arch/m68k/mm/extable.c~linus /dev/null --- 25/arch/m68k/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,33 +0,0 @@ -/* - * linux/arch/m68k/mm/extable.c - */ - -#include -#include -#include - -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = value - mid->insn; - if (diff >= 0 && diff <= 2) - return mid; - else if (diff > 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} - diff -puN arch/m68k/mm/hwtest.c~linus arch/m68k/mm/hwtest.c --- 25/arch/m68k/mm/hwtest.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mm/hwtest.c 2004-01-19 22:17:21.000000000 -0800 @@ -23,6 +23,8 @@ * a temporary VBR and a vector table for the duration of the test. */ +#include + int hwreg_present( volatile void *regp ) { int ret = 0; @@ -47,6 +49,7 @@ int hwreg_present( volatile void *regp ) return( ret ); } +EXPORT_SYMBOL(hwreg_present); /* Basically the same, but writes a value into a word register, protected * by a bus error handler. Returns 1 if successful, 0 otherwise. @@ -78,4 +81,5 @@ int hwreg_write( volatile void *regp, un return( ret ); } +EXPORT_SYMBOL(hwreg_write); diff -puN arch/m68k/mm/Makefile~linus arch/m68k/mm/Makefile --- 25/arch/m68k/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,7 +2,7 @@ # Makefile for the linux m68k-specific parts of the memory manager. # -obj-y := init.o fault.o extable.o hwtest.o +obj-y := init.o fault.o hwtest.o ifndef CONFIG_SUN3 obj-y += kmap.o memory.o motorola.o diff -puN arch/m68k/mm/motorola.c~linus arch/m68k/mm/motorola.c --- 25/arch/m68k/mm/motorola.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mm/motorola.c 2004-01-19 22:17:21.000000000 -0800 @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -40,6 +41,7 @@ * For 68040, this is _PAGE_CACHE040 (cachable, copyback) */ unsigned long mm_cachebits = 0; +EXPORT_SYMBOL(mm_cachebits); #endif static pte_t * __init kernel_page_table(void) diff -puN arch/m68k/mvme16x/rtc.c~linus arch/m68k/mvme16x/rtc.c --- 25/arch/m68k/mvme16x/rtc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/mvme16x/rtc.c 2004-01-19 22:17:21.000000000 -0800 @@ -51,6 +51,7 @@ static int rtc_ioctl(struct inode *inode local_irq_save(flags); /* Ensure clock and real-time-mode-register are accessible */ rtc->ctrl = RTC_READ; + memset(&wtime, 0, sizeof(struct rtc_time)); wtime.tm_sec = BCD2BIN(rtc->bcd_sec); wtime.tm_min = BCD2BIN(rtc->bcd_min); wtime.tm_hour = BCD2BIN(rtc->bcd_hr); @@ -155,9 +156,9 @@ static struct file_operations rtc_fops = static struct miscdevice rtc_dev= { - RTC_MINOR, - "rtc", - &rtc_fops + .minor = RTC_MINOR, + .name = "rtc", + .fops = &rtc_fops }; int __init rtc_MK48T08_init(void) diff -puN arch/m68knommu/kernel/Makefile~linus arch/m68knommu/kernel/Makefile --- 25/arch/m68knommu/kernel/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68knommu/kernel/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -4,8 +4,8 @@ extra-y := vmlinux.lds.s -obj-y += entry.o init_task.o m68k_ksyms.o process.o ptrace.o \ - semaphore.o setup.o signal.o syscalltable.o sys_m68k.o time.o \ - traps.o +obj-y += entry.o init_task.o m68k_ksyms.o process.o ptrace.o semaphore.o \ + setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o +obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_COMEMPCI) += comempci.o diff -puN /dev/null arch/m68knommu/kernel/module.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/m68knommu/kernel/module.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include +#include + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* We don't need anything special. */ +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; + Elf32_Sym *sym; + uint32_t *location; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + + rel[i].r_offset; + /* This is the symbol it is referring to. Note that all + undefined symbols have been resolved. */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_addr + + ELF32_R_SYM(rel[i].r_info); + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_68K_32: + /* We add the value into the location given */ + *location += sym->st_value; + break; + case R_68K_PC32: + /* Add the value, subtract its postition */ + *location += sym->st_value - (uint32_t)location; + break; + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff -puN arch/m68knommu/kernel/time.c~linus arch/m68knommu/kernel/time.c --- 25/arch/m68knommu/kernel/time.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68knommu/kernel/time.c 2004-01-19 22:17:21.000000000 -0800 @@ -202,4 +202,12 @@ int do_settimeofday(struct timespec *tv) return 0; } +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies * (1000000000 / HZ); +} + EXPORT_SYMBOL(do_settimeofday); diff -puN arch/m68knommu/lib/checksum.c~linus arch/m68knommu/lib/checksum.c --- 25/arch/m68knommu/lib/checksum.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68knommu/lib/checksum.c 2004-01-19 22:17:21.000000000 -0800 @@ -32,7 +32,6 @@ of the assembly has to go. */ #include -#include static inline unsigned short from32to16(unsigned long x) { diff -puN -L arch/m68knommu/mm/extable.c arch/m68knommu/mm/extable.c~linus /dev/null --- 25/arch/m68knommu/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,30 +0,0 @@ -/* - * linux/arch/m68knommu/mm/extable.c - */ - -#include -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN arch/m68knommu/mm/Makefile~linus arch/m68knommu/mm/Makefile --- 25/arch/m68knommu/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68knommu/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,4 +2,4 @@ # Makefile for the linux m68knommu specific parts of the memory manager. # -obj-y += init.o fault.o memory.o kmap.o extable.o +obj-y += init.o fault.o memory.o kmap.o diff -puN arch/m68knommu/platform/5307/entry.S~linus arch/m68knommu/platform/5307/entry.S --- 25/arch/m68knommu/platform/5307/entry.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68knommu/platform/5307/entry.S 2004-01-19 22:17:21.000000000 -0800 @@ -182,7 +182,7 @@ ENTRY(inthandler) movew %sp@(LFORMATVEC),%d0 /* put exception # in d0 */ andl #0x03fc,%d0 /* mask out vector only */ - leal kstat__per_cpu+STAT_IRQ,%a0 + leal per_cpu__kstat+STAT_IRQ,%a0 addql #1,%a0@(%d0) lsrl #2,%d0 /* calculate real vector # */ @@ -213,7 +213,7 @@ ENTRY(fasthandler) movew %sp@(LFORMATVEC),%d0 andl #0x03fc,%d0 /* mask out vector only */ - leal kstat__per_cpu+STAT_IRQ,%a0 + leal per_cpu__kstat+STAT_IRQ,%a0 addql #1,%a0@(%d0) movel %sp,%sp@- /* push regs arg onto stack */ diff -puN arch/m68k/q40/q40ints.c~linus arch/m68k/q40/q40ints.c --- 25/arch/m68k/q40/q40ints.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/q40/q40ints.c 2004-01-19 22:17:21.000000000 -0800 @@ -281,21 +281,17 @@ static struct IRQ_TABLE iirqs[]={ {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD}, {0,0}}; #endif -static struct IRQ_TABLE eirqs[]={ - {Q40_IRQ3_MASK,3}, /* ser 1 */ - {Q40_IRQ4_MASK,4}, /* ser 2 */ - {Q40_IRQ14_MASK,14}, /* IDE 1 */ - {Q40_IRQ15_MASK,15}, /* IDE 2 */ - {Q40_IRQ6_MASK,6}, /* floppy, handled elsewhere */ - {Q40_IRQ7_MASK,7}, /* par */ - - {Q40_IRQ5_MASK,5}, - {Q40_IRQ10_MASK,10}, - - - - - {0,0}}; +static struct IRQ_TABLE eirqs[] = { + { .mask = Q40_IRQ3_MASK, .irq = 3 }, /* ser 1 */ + { .mask = Q40_IRQ4_MASK, .irq = 4 }, /* ser 2 */ + { .mask = Q40_IRQ14_MASK, .irq = 14 }, /* IDE 1 */ + { .mask = Q40_IRQ15_MASK, .irq = 15 }, /* IDE 2 */ + { .mask = Q40_IRQ6_MASK, .irq = 6 }, /* floppy, handled elsewhere */ + { .mask = Q40_IRQ7_MASK, .irq = 7 }, /* par */ + { .mask = Q40_IRQ5_MASK, .irq = 5 }, + { .mask = Q40_IRQ10_MASK, .irq = 10 }, + {0,0} +}; /* complain only this many times about spurious ints : */ static int ccleirq=60; /* ISA dev IRQ's*/ diff -puN arch/m68k/sun3/idprom.c~linus arch/m68k/sun3/idprom.c --- 25/arch/m68k/sun3/idprom.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/m68k/sun3/idprom.c 2004-01-19 22:17:21.000000000 -0800 @@ -24,34 +24,34 @@ static struct idprom idprom_buffer; */ struct Sun_Machine_Models Sun_Machines[NUM_SUN_MACHINES] = { /* First, Sun3's */ -{ "Sun 3/160 Series", (SM_SUN3 | SM_3_160) }, -{ "Sun 3/50", (SM_SUN3 | SM_3_50) }, -{ "Sun 3/260 Series", (SM_SUN3 | SM_3_260) }, -{ "Sun 3/110 Series", (SM_SUN3 | SM_3_110) }, -{ "Sun 3/60", (SM_SUN3 | SM_3_60) }, -{ "Sun 3/E", (SM_SUN3 | SM_3_E) }, + { .name = "Sun 3/160 Series", .id_machtype = (SM_SUN3 | SM_3_160) }, + { .name = "Sun 3/50", .id_machtype = (SM_SUN3 | SM_3_50) }, + { .name = "Sun 3/260 Series", .id_machtype = (SM_SUN3 | SM_3_260) }, + { .name = "Sun 3/110 Series", .id_machtype = (SM_SUN3 | SM_3_110) }, + { .name = "Sun 3/60", .id_machtype = (SM_SUN3 | SM_3_60) }, + { .name = "Sun 3/E", .id_machtype = (SM_SUN3 | SM_3_E) }, /* Now, Sun3x's */ -{ "Sun 3/460 Series", (SM_SUN3X | SM_3_460) }, -{ "Sun 3/80", (SM_SUN3X | SM_3_80) }, + { .name = "Sun 3/460 Series", .id_machtype = (SM_SUN3X | SM_3_460) }, + { .name = "Sun 3/80", .id_machtype = (SM_SUN3X | SM_3_80) }, /* Then, Sun4's */ -//{ "Sun 4/100 Series", (SM_SUN4 | SM_4_110) }, -//{ "Sun 4/200 Series", (SM_SUN4 | SM_4_260) }, -//{ "Sun 4/300 Series", (SM_SUN4 | SM_4_330) }, -//{ "Sun 4/400 Series", (SM_SUN4 | SM_4_470) }, +// { .name = "Sun 4/100 Series", .id_machtype = (SM_SUN4 | SM_4_110) }, +// { .name = "Sun 4/200 Series", .id_machtype = (SM_SUN4 | SM_4_260) }, +// { .name = "Sun 4/300 Series", .id_machtype = (SM_SUN4 | SM_4_330) }, +// { .name = "Sun 4/400 Series", .id_machtype = (SM_SUN4 | SM_4_470) }, /* And now, Sun4c's */ -//{ "Sun4c SparcStation 1", (SM_SUN4C | SM_4C_SS1) }, -//{ "Sun4c SparcStation IPC", (SM_SUN4C | SM_4C_IPC) }, -//{ "Sun4c SparcStation 1+", (SM_SUN4C | SM_4C_SS1PLUS) }, -//{ "Sun4c SparcStation SLC", (SM_SUN4C | SM_4C_SLC) }, -//{ "Sun4c SparcStation 2", (SM_SUN4C | SM_4C_SS2) }, -//{ "Sun4c SparcStation ELC", (SM_SUN4C | SM_4C_ELC) }, -//{ "Sun4c SparcStation IPX", (SM_SUN4C | SM_4C_IPX) }, +// { .name = "Sun4c SparcStation 1", .id_machtype = (SM_SUN4C | SM_4C_SS1) }, +// { .name = "Sun4c SparcStation IPC", .id_machtype = (SM_SUN4C | SM_4C_IPC) }, +// { .name = "Sun4c SparcStation 1+", .id_machtype = (SM_SUN4C | SM_4C_SS1PLUS) }, +// { .name = "Sun4c SparcStation SLC", .id_machtype = (SM_SUN4C | SM_4C_SLC) }, +// { .name = "Sun4c SparcStation 2", .id_machtype = (SM_SUN4C | SM_4C_SS2) }, +// { .name = "Sun4c SparcStation ELC", .id_machtype = (SM_SUN4C | SM_4C_ELC) }, +// { .name = "Sun4c SparcStation IPX", .id_machtype = (SM_SUN4C | SM_4C_IPX) }, /* Finally, early Sun4m's */ -//{ "Sun4m SparcSystem600", (SM_SUN4M | SM_4M_SS60) }, -//{ "Sun4m SparcStation10/20", (SM_SUN4M | SM_4M_SS50) }, -//{ "Sun4m SparcStation5", (SM_SUN4M | SM_4M_SS40) }, +// { .name = "Sun4m SparcSystem600", .id_machtype = (SM_SUN4M | SM_4M_SS60) }, +// { .name = "Sun4m SparcStation10/20", .id_machtype = (SM_SUN4M | SM_4M_SS50) }, +// { .name = "Sun4m SparcStation5", .id_machtype = (SM_SUN4M | SM_4M_SS40) }, /* One entry for the OBP arch's which are sun4d, sun4e, and newer sun4m's */ -//{ "Sun4M OBP based system", (SM_SUN4M_OBP | 0x0) } +// { .name = "Sun4M OBP based system", .id_machtype = (SM_SUN4M_OBP | 0x0) } }; static void __init display_system_type(unsigned char machtype) diff -puN arch/mips/Kconfig~linus arch/mips/Kconfig --- 25/arch/mips/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/mips/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -981,6 +981,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "32" help diff -puN -L arch/mips/mm/extable.c arch/mips/mm/extable.c~linus /dev/null --- 25/arch/mips/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,30 +0,0 @@ -/* - * linux/arch/i386/mm/extable.c - */ - -#include -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN arch/mips/mm/Makefile~linus arch/mips/mm/Makefile --- 25/arch/mips/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/mips/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,7 +2,7 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y += cache.o extable.o fault.o loadmmu.o pgtable.o +obj-y += cache.o fault.o loadmmu.o pgtable.o obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o obj-$(CONFIG_MIPS64) += pgtable-64.o diff -puN arch/parisc/Kconfig~linus arch/parisc/Kconfig --- 25/arch/parisc/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/parisc/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -154,6 +154,7 @@ config HPUX config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "32" diff -puN arch/parisc/kernel/sys_parisc.c~linus arch/parisc/kernel/sys_parisc.c --- 25/arch/parisc/kernel/sys_parisc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/parisc/kernel/sys_parisc.c 2004-01-19 22:17:21.000000000 -0800 @@ -93,17 +93,13 @@ static unsigned long get_shared_area(str unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { - struct inode *inode; - if (len > TASK_SIZE) return -ENOMEM; if (!addr) addr = TASK_UNMAPPED_BASE; - inode = filp ? filp->f_dentry->d_inode : NULL; - - if (inode && (flags & MAP_SHARED)) { - addr = get_shared_area(inode->i_mapping, addr, len, pgoff); + if (filp && (flags & MAP_SHARED)) { + addr = get_shared_area(filp->f_mapping, addr, len, pgoff); } else { addr = get_unshared_area(addr, len); } diff -puN -L arch/parisc/mm/extable.c arch/parisc/mm/extable.c~linus /dev/null --- 25/arch/parisc/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,37 +0,0 @@ -/* - * Kernel exception handling table support. Derived from arch/i386/mm/extable.c. - * - * Copyright (C) 2000 Hewlett-Packard Co - * Copyright (C) 2000 John Marvin (jsm@fc.hp.com) - */ - -#include - -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long addr) -{ - /* Abort early if the search value is out of range. */ - - if ((addr < first->addr) || (addr > last->addr)) - return 0; - - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = first + ((last - first)/2); - diff = mid->addr - addr; - - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - - return 0; -} - diff -puN arch/parisc/mm/Makefile~linus arch/parisc/mm/Makefile --- 25/arch/parisc/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/parisc/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,4 +2,4 @@ # Makefile for arch/parisc/mm # -obj-y := init.o fault.o extable.o ioremap.o +obj-y := init.o fault.o ioremap.o diff -puN arch/ppc64/boot/ppc32-types.h~linus arch/ppc64/boot/ppc32-types.h --- 25/arch/ppc64/boot/ppc32-types.h~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/boot/ppc32-types.h 2004-01-19 22:17:21.000000000 -0800 @@ -25,6 +25,12 @@ typedef unsigned int u32; typedef signed long long s64; typedef unsigned long long u64; +typedef struct { + __u32 u[4]; +} __attribute((aligned(16))) __vector128; + #define BITS_PER_LONG 32 +typedef __vector128 vector128; + #endif /* _PPC64_TYPES_H */ diff -puN arch/ppc64/Kconfig~linus arch/ppc64/Kconfig --- 25/arch/ppc64/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -72,6 +72,21 @@ config PPC64 bool default y +# VMX is pSeries only for now until somebody writes the iSeries +# exception vectors for it +config ALTIVEC + bool "Support for VMX (Altivec) vector unit" + depends on PPC_PSERIES + default y + +config POWER4_ONLY + bool "Optimize for POWER4" + default n + ---help--- + Cause the compiler to optimize for POWER4 processors. The resulting + binary will not work on POWER3 or RS64 processors when compiled with + binutils 2.15 or later. + config SMP bool "Symmetric multi-processing support" ---help--- @@ -97,6 +112,7 @@ config IRQ_ALL_CPUS config NR_CPUS int "Maximum number of CPUs (2-128)" + range 2 128 depends on SMP default "32" @@ -130,17 +146,24 @@ config MSCHUNKS depends on PPC_ISERIES default y + +config PPC_RTAS + bool "Proc interface to RTAS" + depends on !PPC_ISERIES + config RTAS_FLASH tristate "Firmware flash interface" - depends on !PPC_ISERIES + depends on PPC_RTAS config SCANLOG tristate "Scanlog dump interface" - depends on !PPC_ISERIES + depends on PPC_RTAS -config PPC_RTAS - bool "Proc interface to RTAS" - depends on !PPC_ISERIES +config LPARCFG + bool "LPAR Configuration Data" + help + Provide system capacity information via human readable + = pairs through a /proc/ppc64/lparcfg interface. endmenu @@ -318,7 +341,7 @@ endmenu config VIOPATH bool - depends on PPC_ISERIES + depends on VIOCONS || VIODASD || VIOCD || VIOTAPE || VETH default y source "arch/ppc64/oprofile/Kconfig" diff -puN arch/ppc64/kernel/asm-offsets.c~linus arch/ppc64/kernel/asm-offsets.c --- 25/arch/ppc64/kernel/asm-offsets.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/asm-offsets.c 2004-01-19 22:17:21.000000000 -0800 @@ -56,6 +56,12 @@ int main(void) DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); DEFINE(KSP, offsetof(struct thread_struct, ksp)); +#ifdef CONFIG_ALTIVEC + DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); + DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); + DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); + DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); +#endif /* CONFIG_ALTIVEC */ DEFINE(MM, offsetof(struct task_struct, mm)); /* naca */ diff -puN arch/ppc64/kernel/chrp_setup.c~linus arch/ppc64/kernel/chrp_setup.c --- 25/arch/ppc64/kernel/chrp_setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/chrp_setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -57,6 +57,7 @@ #include #include #include +#include #include "i8259.h" #include "open_pic.h" @@ -64,8 +65,6 @@ #include #include -extern volatile unsigned char *chrp_int_ack_special; - void chrp_progress(char *, unsigned short); extern void openpic_init_IRQ(void); @@ -96,16 +95,19 @@ chrp_get_cpuinfo(struct seq_file *m) seq_printf(m, "timebase\t: %lu\n", ppc_tb_freq); - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) model = get_property(root, "model", NULL); seq_printf(m, "machine\t\t: CHRP %s\n", model); + of_node_put(root); } #define I8042_DATA_REG 0x60 -void __init chrp_request_regions(void) +void __init chrp_request_regions(void) { + struct device_node *i8042; + request_region(0x20,0x20,"pic1"); request_region(0xa0,0x20,"pic2"); request_region(0x00,0x20,"dma1"); @@ -118,8 +120,9 @@ void __init chrp_request_regions(void) * tree and reserve the region if it does not appear. Later on * the i8042 code will try and reserve this region and fail. */ - if (!find_type_devices("8042")) + if (!(i8042 = of_find_node_by_type(NULL, "8042"))) request_region(I8042_DATA_REG, 16, "reserved (no i8042)"); + of_node_put(i8042); } void __init @@ -158,7 +161,7 @@ chrp_setup_arch(void) #endif /* Find the Open PIC if present */ - root = find_path_device("/"); + root = of_find_node_by_path("/"); opprop = (unsigned int *) get_property(root, "platform-open-pic", NULL); if (opprop != 0) { @@ -170,6 +173,7 @@ chrp_setup_arch(void) printk(KERN_DEBUG "OpenPIC addr: %lx\n", openpic); OpenPIC_Addr = __ioremap(openpic, 0x40000, _PAGE_NO_CACHE); } + of_node_put(root); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; @@ -229,6 +233,10 @@ void __init chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { + struct device_node * dn; + char * hypertas; + unsigned int len; + #if 0 /* PPPBBB remove this later... -Peter */ #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ @@ -262,36 +270,40 @@ chrp_init(unsigned long r3, unsigned lon ppc_md.set_rtc_time = pSeries_set_rtc_time; ppc_md.calibrate_decr = pSeries_calibrate_decr; - ppc_md.progress = chrp_progress; + ppc_md.progress = chrp_progress; + + ppc_md.nvram_read = pSeries_nvram_read; + ppc_md.nvram_write = pSeries_nvram_write; - /* build up the firmware_features bitmask field + /* Build up the firmware_features bitmask field * using contents of device-tree/ibm,hypertas-functions. * Ultimately this functionality may be moved into prom.c prom_init(). */ - struct device_node * dn; - char * hypertas; - unsigned int len; - dn = find_path_device("/rtas"); + dn = of_find_node_by_path("/rtas"); cur_cpu_spec->firmware_features = 0; hypertas = get_property(dn, "ibm,hypertas-functions", &len); if (hypertas) { - while (len > 0){ - int i; - /* check value against table of strings */ - for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { - if ((firmware_features_table[i].name) && (strcmp(firmware_features_table[i].name,hypertas))==0) { - /* we have a match */ - cur_cpu_spec->firmware_features |= (1UL << firmware_features_table[i].val); - break; - } + while (len > 0){ + int i, hypertas_len; + /* check value against table of strings */ + for(i=0; i < FIRMWARE_MAX_FEATURES ;i++) { + if ((firmware_features_table[i].name) && + (strcmp(firmware_features_table[i].name,hypertas))==0) { + /* we have a match */ + cur_cpu_spec->firmware_features |= + (firmware_features_table[i].val); + break; + } + } + hypertas_len = strlen(hypertas); + len -= hypertas_len +1; + hypertas+= hypertas_len +1; } - int hypertas_len = strlen(hypertas); - len -= hypertas_len +1; - hypertas+= hypertas_len +1; - } } - udbg_printf("firmware_features bitmask: 0x%x \n", - cur_cpu_spec->firmware_features); + + of_node_put(dn); + printk(KERN_INFO "firmware_features = 0x%lx\n", + cur_cpu_spec->firmware_features); } void @@ -319,6 +331,13 @@ chrp_progress(char *s, unsigned short he display_character = rtas_token("display-character"); set_indicator = rtas_token("set-indicator"); } + if (display_character == RTAS_UNKNOWN_SERVICE) { + /* use hex display */ + if (set_indicator == RTAS_UNKNOWN_SERVICE) + return; + rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex); + return; + } if(display_character == RTAS_UNKNOWN_SERVICE) { /* use hex display if available */ @@ -405,11 +424,11 @@ void __init pSeries_calibrate_decr(void) /* * The cpu node should have a timebase-frequency property - * to tell us the rate at which the decrementer counts. + * to tell us the rate at which the decrementer counts. */ freq = 16666000; /* hardcoded default */ - cpu = find_type_devices("cpu"); - if (cpu != 0) { + cpu = of_find_node_by_type(NULL, "cpu"); + if (cpu != 0) { fp = (int *) get_property(cpu, "timebase-frequency", NULL); if (fp != 0) freq = *fp; @@ -422,11 +441,12 @@ void __init pSeries_calibrate_decr(void) processor_freq = *fp; } ppc_proc_freq = processor_freq; - - printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", - freq/1000000, freq%1000000 ); + of_node_put(cpu); + + printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", + freq/1000000, freq%1000000); printk("time_init: processor frequency = %lu.%.6lu MHz\n", - processor_freq/1000000, processor_freq%1000000 ); + processor_freq/1000000, processor_freq%1000000); tb_ticks_per_jiffy = freq / HZ; tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; diff -puN arch/ppc64/kernel/cputable.c~linus arch/ppc64/kernel/cputable.c --- 25/arch/ppc64/kernel/cputable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/cputable.c 2004-01-19 22:17:21.000000000 -0800 @@ -21,6 +21,13 @@ struct cpu_spec* cur_cpu_spec = NULL; +/* NOTE: + * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's + * the responsibility of the appropriate CPU save/restore functions to + * eventually copy these settings over. Those save/restore aren't yet + * part of the cputable though. That has to be fixed for both ppc32 + * and ppc64 + */ extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); @@ -30,8 +37,10 @@ extern void __setup_cpu_power4(unsigned */ #ifdef CONFIG_ALTIVEC #define CPU_FTR_ALTIVEC_COMP CPU_FTR_ALTIVEC +#define PPC_FEATURE_HAS_ALTIVEC_COMP PPC_FEATURE_HAS_ALTIVEC #else #define CPU_FTR_ALTIVEC_COMP 0 +#define PPC_FEATURE_HAS_ALTIVEC_COMP 0 #endif struct cpu_spec cpu_specs[] = { @@ -107,6 +116,24 @@ struct cpu_spec cpu_specs[] = { __setup_cpu_power4, COMMON_PPC64_FW }, + { /* PPC970 */ + 0xffff0000, 0x00390000, "PPC970", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP, + COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, + 128, 128, + __setup_cpu_power4, + COMMON_PPC64_FW + }, + { /* Power5 */ + 0xffff0000, 0x003a0000, "Power5", + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_PPCAS_ARCH_V2, + COMMON_USER_PPC64, + 128, 128, + __setup_cpu_power4, + COMMON_PPC64_FW + }, { /* default match */ 0x00000000, 0x00000000, "(Power4-Compatible)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | @@ -130,4 +157,13 @@ firmware_feature_t firmware_features_tab {FW_FEATURE_DUMP, "hcall-dump"}, {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, {FW_FEATURE_MIGRATE, "hcall-migrate"}, + {FW_FEATURE_PERFMON, "hcall-perfmon"}, + {FW_FEATURE_CRQ, "hcall-crq"}, + {FW_FEATURE_VIO, "hcall-vio"}, + {FW_FEATURE_RDMA, "hcall-rdma"}, + {FW_FEATURE_LLAN, "hcall-lLAN"}, + {FW_FEATURE_BULK, "hcall-bulk"}, + {FW_FEATURE_XDABR, "hcall-xdabr"}, + {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, + {FW_FEATURE_SPLPAR, "hcall-splpar"}, }; diff -puN arch/ppc64/kernel/eeh.c~linus arch/ppc64/kernel/eeh.c --- 25/arch/ppc64/kernel/eeh.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/eeh.c 2004-01-19 22:17:21.000000000 -0800 @@ -257,7 +257,7 @@ void eeh_init(void) /* Enable EEH for all adapters. Note that eeh requires buid's */ info.adapters_enabled = 0; - for (phb = find_devices("pci"); phb; phb = phb->next) { + for (phb = of_find_node_by_name(NULL, "pci"); phb; phb = of_find_node_by_name(phb, "pci")) { int len; int *buid_vals = (int *) get_property(phb, "ibm,fw-phb-id", &len); if (!buid_vals) diff -puN arch/ppc64/kernel/entry.S~linus arch/ppc64/kernel/entry.S --- 25/arch/ppc64/kernel/entry.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/entry.S 2004-01-19 22:17:21.000000000 -0800 @@ -29,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -211,6 +212,15 @@ _GLOBAL(ret_from_syscall_2) .align 2,0 #endif + +_GLOBAL(ppc32_swapcontext) + bl .sys32_swapcontext + b 80f + +_GLOBAL(ppc64_swapcontext) + bl .sys_swapcontext + b 80f + _GLOBAL(ppc32_sigreturn) bl .sys32_sigreturn b 80f @@ -261,10 +271,17 @@ _GLOBAL(_switch) SAVE_10GPRS(22, r1) mflr r20 /* Return to switch caller */ mfmsr r22 - andi. r21, r22, MSR_FP + li r0, MSR_FP +#ifdef CONFIG_ALTIVEC +BEGIN_FTR_SECTION + oris r0,r0,MSR_VEC@h /* Disable altivec */ + mfspr r24,SPRN_VRSAVE /* save vrsave register value */ + std r24,THREAD_VRSAVE(r3) +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) +#endif /* CONFIG_ALTIVEC */ + and. r0,r0,r22 beq+ 1f - li r6,MSR_FP /* Disable floating-point */ - andc r22,r22,r6 + andc r22,r22,r0 mtmsrd r22 isync 1: std r20,_NIP(r1) @@ -275,22 +292,30 @@ _GLOBAL(_switch) addi r6,r4,-THREAD /* Convert THREAD to 'current' */ std r6,PACACURRENT(r13) /* Set new 'current' */ -#ifdef CONFIG_PPC_ISERIES -#error fixme - ld r7,TI_FLAGS(r4) /* Get run light flag */ - mfspr r9,CTRLF - srdi r7,r7,1 /* Align to run light bit in CTRL reg */ - insrdi r9,r7,1,63 /* Insert run light into CTRL */ - mtspr CTRLT,r9 -#endif - ld r1,KSP(r4) /* Load new stack pointer */ ld r6,_CCR(r1) mtcrf 0xFF,r6 + +#ifdef CONFIG_ALTIVEC +BEGIN_FTR_SECTION + ld r0,THREAD_VRSAVE(r4) + mtspr SPRN_VRSAVE,r0 /* if G4, restore VRSAVE reg */ +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) +#endif /* CONFIG_ALTIVEC */ + /* r3-r13 are destroyed -- Cort */ REST_8GPRS(14, r1) REST_10GPRS(22, r1) +#ifdef CONFIG_PPC_ISERIES + clrrdi r7,r1,THREAD_SHIFT /* get current_thread_info() */ + ld r7,TI_FLAGS(r7) /* Get run light flag */ + mfspr r9,CTRLF + srdi r7,r7,TIF_RUN_LIGHT + insrdi r9,r7,1,63 /* Insert run light into CTRL */ + mtspr CTRLT,r9 +#endif + /* convert old thread to its task_struct for return value */ addi r3,r3,-THREAD ld r7,_NIP(r1) /* Return to _switch caller in new task */ @@ -308,39 +333,16 @@ _GLOBAL(ret_from_fork) b .ret_from_except _GLOBAL(ret_from_except) -#ifdef CONFIG_PPC_ISERIES - ld r5,SOFTE(r1) - cmpdi 0,r5,0 - beq 4f -irq_recheck: - /* Check for pending interrupts (iSeries) */ - CHECKANYINT(r3,r4) - beq+ 4f /* skip do_IRQ if no interrupts */ - -#warning FIX ISERIES - mfspr r5,SPRG3 - li r3,0 - stb r3,PACAPROCENABLED(r5) /* ensure we are disabled */ - addi r3,r1,STACK_FRAME_OVERHEAD - bl .do_IRQ - b irq_recheck /* loop back and handle more */ -4: -#endif /* * Disable interrupts so that current_thread_info()->flags * can't change between when we test it and when we return * from the interrupt. */ -recheck: mfmsr r10 /* Get current interrupt state */ li r4,0 ori r4,r4,MSR_EE - andc r10,r10,r4 /* clear MSR_EE */ - mtmsrd r10,1 /* Update machine state */ - -#ifdef CONFIG_PPC_ISERIES -#error fix iSeries soft disable -#endif + andc r9,r10,r4 /* clear MSR_EE */ + mtmsrd r9,1 /* Update machine state */ ld r3,_MSR(r1) /* Returning to user mode? */ andi. r3,r3,MSR_PR @@ -364,6 +366,28 @@ recheck: REST_GPR(13,r1) restore: +#ifdef CONFIG_PPC_ISERIES + ld r5,SOFTE(r1) + mfspr r4,SPRG3 /* get paca address */ + cmpdi 0,r5,0 + beq 4f + /* Check for pending interrupts (iSeries) */ + /* this is CHECKANYINT except that we already have the paca address */ + ld r3,PACALPPACA+LPPACAANYINT(r4) + cmpdi r3,0 + beq+ 4f /* skip do_IRQ if no interrupts */ + + mfspr r13,SPRG3 /* get paca pointer back */ + li r3,0 + stb r3,PACAPROCENABLED(r13) /* ensure we are soft-disabled */ + mtmsrd r10 /* hard-enable again */ + addi r3,r1,STACK_FRAME_OVERHEAD + bl .do_IRQ + b .ret_from_except /* loop back and handle more */ + +4: stb r5,PACAPROCENABLED(r4) +#endif + ld r3,_CTR(r1) ld r0,_LINK(r1) mtctr r3 @@ -377,12 +401,6 @@ restore: stdcx. r0,0,r1 /* to clear the reservation */ -#ifdef DO_SOFT_DISABLE - /* XXX do this in do_work, r13 isnt valid here */ - ld r0,SOFTE(r1) - stb r0,PACAPROCENABLED(r13) -#endif - mfmsr r0 li r2, MSR_RI andc r0,r0,r2 @@ -407,21 +425,21 @@ restore: /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: /* Enable interrupts */ - ori r10,r10,MSR_EE mtmsrd r10,1 andi. r0,r3,_TIF_NEED_RESCHED beq 1f bl .schedule - b recheck + b .ret_from_except 1: andi. r0,r3,_TIF_SIGPENDING - beq recheck + beq .ret_from_except li r3,0 addi r4,r1,STACK_FRAME_OVERHEAD bl .do_signal - b recheck + b .ret_from_except +#ifdef CONFIG_PPC_PSERIES /* * On CHRP, the Run-Time Abstraction Services (RTAS) have to be * called with the MMU off. @@ -498,6 +516,12 @@ _STATIC(rtas_return_loc) mfspr r4,SPRG3 /* Get PACA */ SET_REG_TO_CONST(r5, KERNELBASE) sub r4,r4,r5 /* RELOC the PACA base pointer */ + + mfmsr r6 + li r0,MSR_RI + andc r6,r6,r0 + sync + mtmsrd r6 ld r1,PACAR1(r4) /* Restore our SP */ LOADADDR(r3,.rtas_restore_regs) @@ -626,3 +650,4 @@ _GLOBAL(enter_prom) mtlr r0 blr /* return to caller */ +#endif /* defined(CONFIG_PPC_PSERIES) */ diff -puN arch/ppc64/kernel/head.S~linus arch/ppc64/kernel/head.S --- 25/arch/ppc64/kernel/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -91,20 +91,26 @@ .text .globl _stext _stext: +#ifdef CONFIG_PPC_PSERIES _STATIC(__start) b .__start_initialization_pSeries +#endif #ifdef CONFIG_PPC_ISERIES - /* At offset 0x20, there is a pointer to iSeries LPAR data. - * This is required by the hypervisor */ + /* + * At offset 0x20, there is a pointer to iSeries LPAR data. + * This is required by the hypervisor + */ . = 0x20 .llong hvReleaseData-KERNELBASE - /* At offset 0x28 and 0x30 are offsets to the msChunks + /* + * At offset 0x28 and 0x30 are offsets to the msChunks * array (used by the iSeries LPAR debugger to do translation * between physical addresses and absolute addresses) and - * to the pidhash table (also used by the debugger) */ + * to the pidhash table (also used by the debugger) + */ .llong msChunks-KERNELBASE - .llong pidhash-KERNELBASE + .llong 0 /* pidhash-KERNELBASE SFRXXX */ /* Offset 0x38 - Pointer to start of embedded System.map */ .globl embedded_sysmap_start @@ -114,7 +120,7 @@ embedded_sysmap_start: .globl embedded_sysmap_end embedded_sysmap_end: .llong 0 -#endif +#else /* Secondary processors spin on this value until it goes to 1. */ .globl __secondary_hold_spinloop @@ -147,6 +153,7 @@ _GLOBAL(__secondary_hold) /* Relocation is off & we are located at an address less */ /* than 0x100, so only need to grab low order offset. */ std r24,__secondary_hold_acknowledge@l(0) + sync /* All secondary cpu's wait here until told to start. */ 100: ld r4,__secondary_hold_spinloop@l(0) @@ -163,6 +170,7 @@ _GLOBAL(__secondary_hold) BUG_OPCODE #endif #endif +#endif /* * The following macros define the code that appears as @@ -244,6 +252,14 @@ _GLOBAL(__secondary_hold) std r22,EX_SRR0(r21); /* save SRR0 in exc. frame */ \ ld r23,LPPACA+LPPACASRR1(r20); /* Get SRR1 from ItLpPaca */ \ std r23,EX_SRR1(r21); /* save SRR1 in exc. frame */ \ + \ + mfspr r23,DAR; /* Save DAR in exc. frame */ \ + std r23,EX_DAR(r21); \ + mfspr r23,DSISR; /* Save DSISR in exc. frame */ \ + stw r23,EX_DSISR(r21); \ + mfspr r23,SPRG2; /* Save r20 in exc. frame */ \ + std r23,EX_R20(r21); \ + \ mfcr r23; /* save CR in r23 */ /* @@ -375,9 +391,34 @@ __start_interrupts: STD_EXCEPTION_PSERIES( 0xc00, SystemCall ) STD_EXCEPTION_PSERIES( 0xd00, SingleStep ) STD_EXCEPTION_PSERIES( 0xe00, Trap_0e ) - STD_EXCEPTION_PSERIES( 0xf00, PerformanceMonitor ) + + /* We need to deal with the Altivec unavailable exception + * here which is at 0xf20, thus in the middle of the + * prolog code of the PerformanceMonitor one. A little + * trickery is thus necessary + */ + . = 0xf00 + b .PerformanceMonitor_Pseries + . = 0xf20 + b .AltivecUnavailable_Pseries + STD_EXCEPTION_PSERIES( 0x1300, InstructionBreakpoint ) + STD_EXCEPTION_PSERIES( 0x1700, AltivecAssist ) + /* Here are the "moved" performance monitor and + * altivec unavailable exceptions + */ + . = 0x3000 + .globl PerformanceMonitor_Pseries; +.PerformanceMonitor_Pseries: + EXCEPTION_PROLOG_PSERIES(0xf00, PerformanceMonitor_common) + + . = 0x3100 + .globl AltivecUnavailable_Pseries; +.AltivecUnavailable_Pseries: + EXCEPTION_PROLOG_PSERIES(0xf20, AltivecUnavailable_common) + + /* Space for the naca. Architected to be located at real address * NACA_PHYS_ADDR. Various tools rely on this location being fixed. * The first dword of the naca is required by iSeries LPAR to @@ -564,7 +605,11 @@ __end_stab: STD_EXCEPTION_COMMON( 0xe00, Trap_0e, .UnknownException ) STD_EXCEPTION_COMMON( 0xf00, PerformanceMonitor, .PerformanceMonitorException ) STD_EXCEPTION_COMMON(0x1300, InstructionBreakpoint, .InstructionBreakpointException ) - +#ifdef CONFIG_ALTIVEC + STD_EXCEPTION_COMMON(0x1700, AltivecAssist, .AltivecAssistException ) +#else + STD_EXCEPTION_COMMON(0x1700, AltivecAssist, .UnknownException ) +#endif /* * Return from an exception which is handled without calling * save_remaining_regs. The caller is assumed to have done @@ -739,6 +784,23 @@ FPUnavailable_common: bl .KernelFPUnavailableException BUG_OPCODE + .globl AltivecUnavailable_common +AltivecUnavailable_common: + EXCEPTION_PROLOG_COMMON +#ifdef CONFIG_ALTIVEC + bne .load_up_altivec /* if from user, just load it up */ +#endif + addi r3,r1,STACK_FRAME_OVERHEAD + DO_COPY_EE() + li r6,0xf20 + bl .save_remaining_regs +#ifdef CONFIG_ALTIVEC + bl .KernelAltivecUnavailableException +#else + bl .UnknownException +#endif + BUG_OPCODE + .globl SystemCall_common SystemCall_common: EXCEPTION_PROLOG_COMMON @@ -1113,7 +1175,6 @@ _GLOBAL(save_remaining_regs) SET_REG_TO_CONST(r22, MSR_KERNEL) #ifdef DO_SOFT_DISABLE -#warning FIX ISERIES stb r20,PACAPROCENABLED(r13) /* possibly soft enable */ ori r22,r22,MSR_EE /* always hard enable */ #else @@ -1187,7 +1248,21 @@ _GLOBAL(pseries_secondary_smp_init) b 1b /* Loop until told to go */ #ifdef CONFIG_PPC_ISERIES _GLOBAL(__start_initialization_iSeries) + /* Clear out the BSS */ + LOADADDR(r11,__bss_stop) + + LOADADDR(r8,__bss_start) + sub r11,r11,r8 /* bss size */ + addi r11,r11,7 /* round up to an even double word */ + rldicl. r11,r11,61,3 /* shift right by 3 */ + beq 4f + addi r8,r8,-8 + li r0,0 + mtctr r11 /* zero this many doublewords */ +3: stdu r0,8(r8) + bdnz 3b +4: LOADADDR(r1,init_thread_union) addi r1,r1,THREAD_SIZE li r0,0 @@ -1216,9 +1291,12 @@ _GLOBAL(__start_initialization_iSeries) bl .iSeries_fixup_klimit + /* relocation is on at this point */ + b .start_here_common #endif +#ifdef CONFIG_PPC_PSERIES _GLOBAL(__start_initialization_pSeries) mr r31,r3 /* save parameters */ mr r30,r4 @@ -1238,20 +1316,6 @@ _GLOBAL(__start_initialization_pSeries) /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 - /* setup the systemcfg pointer which is needed by prom_init */ - LOADADDR(r9,systemcfg) - sub r9,r9,r3 /* addr of the variable systemcfg */ - SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR) - sub r4,r4,r3 - std r4,0(r9) /* set the value of systemcfg */ - - /* setup the naca pointer which is needed by prom_init */ - LOADADDR(r9,naca) - sub r9,r9,r3 /* addr of the variable naca */ - SET_REG_TO_CONST(r4, NACA_VIRT_ADDR) - sub r4,r4,r3 - std r4,0(r9) /* set the value of naca */ - /* DRENG / PPPBBB Fix the following comment!!! -Peter */ /* The following copies the first 0x100 bytes of code from the */ /* load addr to physical addr 0x0. This code causes secondary */ @@ -1328,6 +1392,7 @@ _STATIC(__after_prom_start) sub r5,r5,r27 bl .copy_and_flush /* copy the rest */ b .start_here_pSeries +#endif /* * Copy routine used to copy the kernel to start at physical address 0 @@ -1466,6 +1531,126 @@ _GLOBAL(giveup_fpu) #endif /* CONFIG_SMP */ blr + +#ifdef CONFIG_ALTIVEC + +/* + * load_up_altivec(unused, unused, tsk) + * Disable VMX for the task which had it previously, + * and save its vector registers in its thread_struct. + * Enables the VMX for use in the kernel on return. + * On SMP we know the VMX is free, since we give it up every + * switch (ie, no lazy save of the vector registers). + * On entry: r13 == 'current' && last_task_used_altivec != 'current' + */ +_STATIC(load_up_altivec) + mfmsr r5 /* grab the current MSR */ + oris r5,r5,MSR_VEC@h + mtmsrd r5 /* enable use of VMX now */ + isync + +/* + * For SMP, we don't do lazy VMX switching because it just gets too + * horrendously complex, especially when a task switches from one CPU + * to another. Instead we call giveup_altvec in switch_to. + * VRSAVE isn't dealt with here, that is done in the normal context + * switch code. Note that we could rely on vrsave value to eventually + * avoid saving all of the VREGs here... + */ +#ifndef CONFIG_SMP + LOADBASE(r3,last_task_used_altivec) + ld r4,last_task_used_altivec@l(r3) + cmpi 0,r4,0 + beq 1f + /* Save VMX state to last_task_used_altivec's THREAD struct */ + addi r4,r4,THREAD + SAVE_32VRS(0,r5,r4) + mfvscr vr0 + li r10,THREAD_VSCR + stvx vr0,r10,r4 + /* Disable VMX for last_task_used_altivec */ + ld r5,PT_REGS(r4) + ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r20,MSR_VEC@h + andc r4,r4,r20 + std r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#endif /* CONFIG_SMP */ + /* Hack: if we get an altivec unavailable trap with VRSAVE + * set to all zeros, we assume this is a broken application + * that fails to set it properly, and thus we switch it to + * all 1's + */ + mfspr r4,SPRN_VRSAVE + cmpi 0,r4,0 + bne+ 1f + li r4,-1 + mtspr SPRN_VRSAVE,r4 +1: + /* enable use of VMX after return */ + ld r4,PACACURRENT(r13) + addi r5,r4,THREAD /* Get THREAD */ + oris r23,r23,MSR_VEC@h + li r4,1 + li r10,THREAD_VSCR + stw r4,THREAD_USED_VR(r5) + lvx vr0,r10,r5 + REST_32VRS(0,r4,r5) +#ifndef CONFIG_SMP + /* Update last_task_used_math to 'current' */ + subi r4,r5,THREAD /* Back to 'current' */ + std r4,last_task_used_altivec@l(r3) +#endif /* CONFIG_SMP */ + /* restore registers and return */ + b fast_exception_return + +/* + * disable_kernel_altivec() + * Disable the VMX. + */ +_GLOBAL(disable_kernel_altivec) + mfmsr r3 + rldicl r0,r3,(63-MSR_VEC_LG),1 + rldicl r3,r0,(MSR_VEC_LG+1),0 + mtmsrd r3 /* disable use of VMX now */ + isync + blr + +/* + * giveup_altivec(tsk) + * Disable VMX for the task given as the argument, + * and save the vector registers in its thread_struct. + * Enables the VMX for use in the kernel on return. + */ +_GLOBAL(giveup_altivec) + mfmsr r5 + oris r5,r5,MSR_VEC@h + mtmsrd r5 /* enable use of VMX now */ + isync + cmpi 0,r3,0 + beqlr- /* if no previous owner, done */ + addi r3,r3,THREAD /* want THREAD of task */ + ld r5,PT_REGS(r3) + cmpi 0,r5,0 + SAVE_32VRS(0,r4,r3) + mfvscr vr0 + li r4,THREAD_VSCR + stvx vr0,r4,r3 + beq 1f + ld r4,_MSR-STACK_FRAME_OVERHEAD(r5) + lis r3,MSR_VEC@h + andc r4,r4,r3 /* disable FP for previous task */ + std r4,_MSR-STACK_FRAME_OVERHEAD(r5) +1: +#ifndef CONFIG_SMP + li r5,0 + LOADBASE(r4,last_task_used_altivec) + std r5,last_task_used_altivec@l(r4) +#endif /* CONFIG_SMP */ + blr + +#endif /* CONFIG_ALTIVEC */ + #ifdef CONFIG_SMP /* * This function is called after the master CPU has released the @@ -1594,6 +1779,7 @@ _GLOBAL(enable_32b_mode) isync blr +#ifdef CONFIG_PPC_PSERIES /* * This is where the main kernel code starts. */ @@ -1729,27 +1915,11 @@ _STATIC(start_here_pSeries) mtspr SRR0,r3 mtspr SRR1,r4 rfid +#endif /* CONFIG_PPC_PSERIES */ /* This is where all platforms converge execution */ _STATIC(start_here_common) - /* relocation is on at this point */ - - /* Clear out the BSS */ - LOADADDR(r11,_end) - - LOADADDR(r8,__bss_start) - - sub r11,r11,r8 /* bss size */ - addi r11,r11,7 /* round up to an even double word */ - rldicl. r11,r11,61,3 /* shift right by 3 */ - beq 4f - addi r8,r8,-8 - li r0,0 - mtctr r11 /* zero this many doublewords */ -3: stdu r0,8(r8) - bdnz 3b -4: - + /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ @@ -1765,6 +1935,12 @@ _STATIC(start_here_common) addi r2,r2,0x4000 addi r2,r2,0x4000 + /* Apply the CPUs-specific fixups (nop out sections not relevant + * to this CPU + */ + li r3,0 + bl .do_cpu_ftr_fixups + /* setup the systemcfg pointer */ LOADADDR(r9,systemcfg) SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR) @@ -1803,10 +1979,8 @@ _STATIC(start_here_common) /* Load up the kernel context */ 5: #ifdef DO_SOFT_DISABLE -#warning FIX ISERIES - mfspr r4,SPRG3 li r5,0 - stb r5,PACAPROCENABLED(r4) /* Soft Disabled */ + stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5 diff -puN -L arch/ppc64/kernel/htab.c arch/ppc64/kernel/htab.c~linus /dev/null --- 25/arch/ppc64/kernel/htab.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,491 +0,0 @@ -/* - * PowerPC64 port by Mike Corrigan and Dave Engebretsen - * {mikejc|engebret}@us.ibm.com - * - * Copyright (c) 2000 Mike Corrigan - * - * SMP scalability work: - * Copyright (C) 2001 Anton Blanchard , IBM - * - * Module name: htab.c - * - * Description: - * PowerPC Hashed Page Table functions - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Note: pte --> Linux PTE - * HPTE --> PowerPC Hashed Page Table Entry - * - * Execution context: - * htab_initialize is called with the MMU off (of course), but - * the kernel has been copied down to zero so it can directly - * reference global data. At this point it is very difficult - * to print debug info. - * - */ - -HTAB htab_data = {NULL, 0, 0, 0, 0}; - -extern unsigned long _SDR1; - -#define KB (1024) -#define MB (1024*KB) - -static inline void -loop_forever(void) -{ - volatile unsigned long x = 1; - for(;x;x|=1) - ; -} - -static inline void -create_pte_mapping(unsigned long start, unsigned long end, - unsigned long mode, int large) -{ - unsigned long addr; - unsigned int step; - - if (large) - step = 16*MB; - else - step = 4*KB; - - for (addr = start; addr < end; addr += step) { - unsigned long vpn, hash, hpteg; - unsigned long vsid = get_kernel_vsid(addr); - unsigned long va = (vsid << 28) | (addr & 0xfffffff); - int ret; - - if (large) - vpn = va >> LARGE_PAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - - hash = hpt_hash(vpn, large); - - hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); - - if (systemcfg->platform == PLATFORM_PSERIES_LPAR) - ret = pSeries_lpar_hpte_insert(hpteg, va, - (unsigned long)__v2a(addr) >> PAGE_SHIFT, - 0, mode, 1, large); - else - ret = pSeries_hpte_insert(hpteg, va, - (unsigned long)__v2a(addr) >> PAGE_SHIFT, - 0, mode, 1, large); - - if (ret == -1) { - ppc64_terminate_msg(0x20, "create_pte_mapping"); - loop_forever(); - } - } -} - -void -htab_initialize(void) -{ - unsigned long table, htab_size_bytes; - unsigned long pteg_count; - unsigned long mode_rw; - - /* - * Calculate the required size of the htab. We want the number of - * PTEGs to equal one half the number of real pages. - */ - htab_size_bytes = 1UL << naca->pftSize; - pteg_count = htab_size_bytes >> 7; - - /* For debug, make the HTAB 1/8 as big as it normally would be. */ - ifppcdebug(PPCDBG_HTABSIZE) { - pteg_count >>= 3; - htab_size_bytes = pteg_count << 7; - } - - htab_data.htab_num_ptegs = pteg_count; - htab_data.htab_hash_mask = pteg_count - 1; - - if (systemcfg->platform == PLATFORM_PSERIES) { - /* Find storage for the HPT. Must be contiguous in - * the absolute address space. - */ - table = lmb_alloc(htab_size_bytes, htab_size_bytes); - if ( !table ) { - ppc64_terminate_msg(0x20, "hpt space"); - loop_forever(); - } - htab_data.htab = (HPTE *)__a2v(table); - - /* htab absolute addr + encoded htabsize */ - _SDR1 = table + __ilog2(pteg_count) - 11; - - /* Initialize the HPT with no entries */ - memset((void *)table, 0, htab_size_bytes); - } else { - /* Using a hypervisor which owns the htab */ - htab_data.htab = NULL; - _SDR1 = 0; - } - - mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; - - /* XXX we currently map kernel text rw, should fix this */ - if ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) - && systemcfg->physicalMemorySize > 256*MB) { - create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE + 256*MB, mode_rw, 0); - create_pte_mapping((unsigned long)KERNELBASE + 256*MB, - KERNELBASE + (systemcfg->physicalMemorySize), - mode_rw, 1); - } else { - create_pte_mapping((unsigned long)KERNELBASE, - KERNELBASE+(systemcfg->physicalMemorySize), - mode_rw, 0); - } -} -#undef KB -#undef MB - -/* - * find_linux_pte returns the address of a linux pte for a given - * effective address and directory. If not found, it returns zero. - */ -pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea) -{ - pgd_t *pg; - pmd_t *pm; - pte_t *pt = NULL; - pte_t pte; - - pg = pgdir + pgd_index(ea); - if (!pgd_none(*pg)) { - - pm = pmd_offset(pg, ea); - if (pmd_present(*pm)) { - pt = pte_offset_kernel(pm, ea); - pte = *pt; - if (!pte_present(pte)) - pt = NULL; - } - } - - return pt; -} - -static inline unsigned long computeHptePP(unsigned long pte) -{ - return (pte & _PAGE_USER) | - (((pte & _PAGE_USER) >> 1) & - ((~((pte >> 2) & /* _PAGE_RW */ - (pte >> 7))) & /* _PAGE_DIRTY */ - 1)); -} - -/* - * Handle a fault by adding an HPTE. If the address can't be determined - * to be valid via Linux page tables, return 1. If handled return 0 - */ -int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - pte_t *ptep, unsigned long trap, int local) -{ - unsigned long va, vpn; - unsigned long newpp, prpn; - unsigned long hpteflags; - long slot; - pte_t old_pte, new_pte; - - /* XXX fix for large ptes */ - int large = 0; - - /* Search the Linux page table for a match with va */ - va = (vsid << 28) | (ea & 0x0fffffff); - - if (large) - vpn = va >> LARGE_PAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - - /* - * If no pte found or not present, send the problem up to - * do_page_fault - */ - if (unlikely(!ptep || !pte_present(*ptep))) - return 1; - - /* - * Check the user's access rights to the page. If access should be - * prevented then send the problem up to do_page_fault. - */ - access |= _PAGE_PRESENT; - if (unlikely(access & ~(pte_val(*ptep)))) - return 1; - - /* - * At this point, we have a pte (old_pte) which can be used to build - * or update an HPTE. There are 2 cases: - * - * 1. There is a valid (present) pte with no associated HPTE (this is - * the most common case) - * 2. There is a valid (present) pte with an associated HPTE. The - * current values of the pp bits in the HPTE prevent access - * because we are doing software DIRTY bit management and the - * page is currently not DIRTY. - */ - - old_pte = *ptep; - new_pte = old_pte; - /* If the attempted access was a store */ - if (access & _PAGE_RW) - pte_val(new_pte) |= _PAGE_ACCESSED | _PAGE_DIRTY; - else - pte_val(new_pte) |= _PAGE_ACCESSED; - - newpp = computeHptePP(pte_val(new_pte)); - -#define PPC64_HWNOEXEC (1 << 2) - - /* We do lazy icache flushing on cpus that support it */ - if (unlikely((cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE) - && pfn_valid(pte_pfn(new_pte)))) { - struct page *page = pte_page(new_pte); - - /* page is dirty */ - if (!PageReserved(page) && - !test_bit(PG_arch_1, &page->flags)) { - if (trap == 0x400) { - __flush_dcache_icache(page_address(page)); - set_bit(PG_arch_1, &page->flags); - } else { - newpp |= PPC64_HWNOEXEC; - } - } - } - - /* Check if pte already has an hpte (case 2) */ - if (unlikely(pte_val(old_pte) & _PAGE_HASHPTE)) { - /* There MIGHT be an HPTE for this pte */ - unsigned long hash, slot, secondary; - - hash = hpt_hash(vpn, large); - secondary = (pte_val(old_pte) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(old_pte) & _PAGE_GROUP_IX) >> 12; - - if (ppc_md.hpte_updatepp(slot, newpp, va, large, local) == -1) - pte_val(old_pte) &= ~_PAGE_HPTEFLAGS; - else - if (!pte_same(old_pte, new_pte)) - *ptep = new_pte; - } - - if (likely(!(pte_val(old_pte) & _PAGE_HASHPTE))) { - unsigned long hash = hpt_hash(vpn, large); - unsigned long hpte_group; - prpn = pte_val(old_pte) >> PTE_SHIFT; - -repeat: - hpte_group = ((hash & htab_data.htab_hash_mask) * - HPTES_PER_GROUP) & ~0x7UL; - - /* Update the linux pte with the HPTE slot */ - pte_val(new_pte) &= ~_PAGE_HPTEFLAGS; - pte_val(new_pte) |= _PAGE_HASHPTE; - - /* copy appropriate flags from linux pte */ - hpteflags = (pte_val(new_pte) & 0x1f8) | newpp; - - slot = ppc_md.hpte_insert(hpte_group, va, prpn, 0, - hpteflags, 0, large); - - /* Primary is full, try the secondary */ - if (unlikely(slot == -1)) { - pte_val(new_pte) |= 1 << 15; - hpte_group = ((~hash & htab_data.htab_hash_mask) * - HPTES_PER_GROUP) & ~0x7UL; - slot = ppc_md.hpte_insert(hpte_group, va, prpn, - 1, hpteflags, 0, large); - if (slot == -1) { - if (mftb() & 0x1) - hpte_group = ((hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; - - ppc_md.hpte_remove(hpte_group); - goto repeat; - } - } - - if (unlikely(slot == -2)) - panic("hash_page: pte_insert failed\n"); - - pte_val(new_pte) |= (slot<<12) & _PAGE_GROUP_IX; - - /* - * No need to use ldarx/stdcx here because all who - * might be updating the pte will hold the - * page_table_lock or the hash_table_lock - * (we hold both) - */ - *ptep = new_pte; - } - - return 0; -} - -int hash_page(unsigned long ea, unsigned long access, unsigned long trap) -{ - void *pgdir; - unsigned long vsid; - struct mm_struct *mm; - pte_t *ptep; - int ret; - int user_region = 0; - int local = 0; - cpumask_t tmp; - - /* Check for invalid addresses. */ - if (!IS_VALID_EA(ea)) - return 1; - - switch (REGION_ID(ea)) { - case USER_REGION_ID: - user_region = 1; - mm = current->mm; - if (mm == NULL) - return 1; - - vsid = get_vsid(mm->context, ea); - break; - case IO_REGION_ID: - mm = &ioremap_mm; - vsid = get_kernel_vsid(ea); - break; - case VMALLOC_REGION_ID: - mm = &init_mm; - vsid = get_kernel_vsid(ea); - break; -#if 0 - case EEH_REGION_ID: - /* - * Should only be hit if there is an access to MMIO space - * which is protected by EEH. - * Send the problem up to do_page_fault - */ - case KERNEL_REGION_ID: - /* - * Should never get here - entire 0xC0... region is bolted. - * Send the problem up to do_page_fault - */ -#endif - default: - /* Not a valid range - * Send the problem up to do_page_fault - */ - return 1; - break; - } - - pgdir = mm->pgd; - - if (pgdir == NULL) - return 1; - - /* - * Lock the Linux page table to prevent mmap and kswapd - * from modifying entries while we search and update - */ - spin_lock(&mm->page_table_lock); - - tmp = cpumask_of_cpu(smp_processor_id()); - if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) - local = 1; - - ret = hash_huge_page(mm, access, ea, vsid, local); - if (ret < 0) { - ptep = find_linux_pte(pgdir, ea); - ret = __hash_page(ea, access, vsid, ptep, trap, local); - } - - spin_unlock(&mm->page_table_lock); - - return ret; -} - -void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, - int local) -{ - unsigned long vsid, vpn, va, hash, secondary, slot; - - /* XXX fix for large ptes */ - unsigned long large = 0; - - if ((ea >= USER_START) && (ea <= USER_END)) - vsid = get_vsid(context, ea); - else - vsid = get_kernel_vsid(ea); - - va = (vsid << 28) | (ea & 0x0fffffff); - if (large) - vpn = va >> LARGE_PAGE_SHIFT; - else - vpn = va >> PAGE_SHIFT; - hash = hpt_hash(vpn, large); - secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; - if (secondary) - hash = ~hash; - slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; - slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; - - ppc_md.hpte_invalidate(slot, va, large, local); -} - -void flush_hash_range(unsigned long context, unsigned long number, int local) -{ - if (ppc_md.flush_hash_range) { - ppc_md.flush_hash_range(context, number, local); - } else { - int i; - struct ppc64_tlb_batch *batch = - &ppc64_tlb_batch[smp_processor_id()]; - - for (i = 0; i < number; i++) - flush_hash_page(context, batch->addr[i], batch->pte[i], - local); - } -} diff -puN arch/ppc64/kernel/HvCall.c~linus arch/ppc64/kernel/HvCall.c --- 25/arch/ppc64/kernel/HvCall.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/HvCall.c 2004-01-19 22:17:21.000000000 -0800 @@ -8,108 +8,29 @@ * (at your option) any later version. */ -#include -#include -#include -#include -#include #include +#include #include -#ifndef _HVCALLSC_H #include -#endif -#include - -#ifndef _HVTYPES_H #include -#endif -/*===================================================================== - * Note that this call takes at MOST one page worth of data - */ -int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen) +void HvCall_writeLogBuffer(const void *buffer, u64 len) { - struct HvLpBufferList *bufList; - u64 bytesLeft = bufLen; - u64 leftThisPage; - u64 curPtr = virt_to_absolute( (unsigned long) buffer ); - u64 retVal; - int npages; - int i; - - npages = 0; - while (bytesLeft) { - npages++; - leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; - - if (leftThisPage > bytesLeft) - bytesLeft = 0; - else - bytesLeft -= leftThisPage; - - curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; + struct HvLpBufferList hv_buf; + u64 left_this_page; + u64 cur = virt_to_absolute((unsigned long)buffer); + + while (len) { + hv_buf.addr = cur; + left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur; + if (left_this_page > len) + left_this_page = len; + hv_buf.len = left_this_page; + len -= left_this_page; + HvCall2(HvCallBaseWriteLogBuffer, + virt_to_absolute((unsigned long)&hv_buf), + left_this_page); + cur = (cur & PAGE_MASK) + PAGE_SIZE; } - - if (npages == 0) - return 0; - - bufList = (struct HvLpBufferList *) - kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC); - bytesLeft = bufLen; - curPtr = virt_to_absolute( (unsigned long) buffer ); - for(i=0; i bytesLeft) { - bufList[i].len = bytesLeft; - bytesLeft = 0; - } else { - bufList[i].len = leftThisPage; - bytesLeft -= leftThisPage; - } - - curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; - } - - - retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex, - virt_to_absolute((unsigned long)bufList), bufLen); - - kfree(bufList); - - return (int)retVal; -} - -/*===================================================================== - */ -void HvCall_writeLogBuffer(const void *buffer, u64 bufLen) -{ - struct HvLpBufferList bufList; - u64 bytesLeft = bufLen; - u64 leftThisPage; - u64 curPtr = virt_to_absolute( (unsigned long) buffer ); - - while (bytesLeft) { - bufList.addr = curPtr; - - leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; - - if (leftThisPage > bytesLeft) { - bufList.len = bytesLeft; - bytesLeft = 0; - } else { - bufList.len = leftThisPage; - bytesLeft -= leftThisPage; - } - - curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE; - } - - - HvCall2(HvCallBaseWriteLogBuffer, - virt_to_absolute((unsigned long)&bufList), bufLen); - } diff -puN arch/ppc64/kernel/idle.c~linus arch/ppc64/kernel/idle.c --- 25/arch/ppc64/kernel/idle.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/idle.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,13 @@ /* - * idle.c + * Idle daemon for PowerPC. Idle daemon will handle any action + * that needs to be taken when the system becomes idle. + * + * Originally Written by Cort Dougan (cort@cs.nmt.edu) + * + * iSeries supported added by Mike Corrigan + * + * Additional shared processor, SMT, and firmware support + * Copyright (c) 2003 Dave Engebretsen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -26,14 +34,18 @@ #include #include #include +#include #include - -#ifdef CONFIG_PPC_ISERIES - #include #include #include +extern long cede_processor(void); +extern long poll_pending(void); + +int (*idle_loop)(void); + +#ifdef CONFIG_PPC_ISERIES unsigned long maxYieldTime = 0; unsigned long minYieldTime = 0xffffffffffffffffUL; @@ -66,24 +78,24 @@ static void yield_shared_processor(void) process_iSeries_events(); } -int cpu_idle(void) +int iSeries_idle(void) { struct paca_struct *lpaca; long oldval; unsigned long CTRL; -#warning fix iseries run light -#if 0 /* ensure iSeries run light will be out when idle */ - current->thread.flags &= ~PPC_FLAG_RUN_LIGHT; + clear_thread_flag(TIF_RUN_LIGHT); CTRL = mfspr(CTRLF); CTRL &= ~RUNLATCH; mtspr(CTRLT, CTRL); +#if 0 + init_idle(); #endif lpaca = get_paca(); - while (1) { + for (;;) { if (lpaca->xLpPaca.xSharedProc) { if (ItLpQueue_isLpIntPending(lpaca->lpQueuePtr)) process_iSeries_events(); @@ -109,16 +121,13 @@ int cpu_idle(void) } } - if (need_resched()) - schedule(); + schedule(); } - return 0; } +#endif -#else /* CONFIG_PPC_ISERIES */ - -int cpu_idle(void) +int default_idle(void) { long oldval; @@ -145,9 +154,155 @@ int cpu_idle(void) return 0; } -#endif /* CONFIG_PPC_ISERIES */ +#ifdef CONFIG_PPC_PSERIES +int dedicated_idle(void) +{ + long oldval; + struct paca_struct *lpaca = get_paca(), *ppaca; + unsigned long start_snooze; + + ppaca = &paca[(lpaca->xPacaIndex) ^ 1]; + + while (1) { + /* Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. */ + lpaca->xLpPaca.xIdle = 1; + + oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); + if (!oldval) { + set_thread_flag(TIF_POLLING_NRFLAG); + start_snooze = __get_tb(); + while (!need_resched()) { + /* need_resched could be 1 or 0 at this + * point. If it is 0, set it to 0, so + * an IPI/Prod is sent. If it is 1, keep + * it that way & schedule work. + */ + if (__get_tb() < + (start_snooze + + naca->smt_snooze_delay*tb_ticks_per_usec)) { + HMT_low(); /* Low thread priority */ + continue; + } + + HMT_very_low(); /* Low power mode */ + + /* If the SMT mode is system controlled & the + * partner thread is doing work, switch into + * ST mode. + */ + if((naca->smt_state == SMT_DYNAMIC) && + (!(ppaca->xLpPaca.xIdle))) { + /* Indicate we are no longer polling for + * work, and then clear need_resched. If + * need_resched was 1, set it back to 1 + * and schedule work + */ + clear_thread_flag(TIF_POLLING_NRFLAG); + oldval = test_and_clear_thread_flag(TIF_NEED_RESCHED); + if(oldval == 1) { + set_need_resched(); + break; + } + + /* DRENG: Go HMT_medium here ? */ + local_irq_disable(); + lpaca->yielded = 1; + + /* SMT dynamic mode. Cede will result + * in this thread going dormant, if the + * partner thread is still doing work. + * Thread wakes up if partner goes idle, + * an interrupt is presented, or a prod + * occurs. Returning from the cede + * enables external interrupts. + */ + cede_processor(); + + lpaca->yielded = 0; + } else { + /* Give the HV an opportunity at the + * processor, since we are not doing + * any work. + */ + poll_pending(); + } + } + } else { + set_need_resched(); + } + + HMT_medium(); + lpaca->xLpPaca.xIdle = 0; + schedule(); + } + return 0; +} + +int shared_idle(void) +{ + struct paca_struct *lpaca = get_paca(); + + while (1) { + /* Indicate to the HV that we are idle. Now would be + * a good time to find other work to dispatch. */ + lpaca->xLpPaca.xIdle = 1; + + if (!need_resched()) { + local_irq_disable(); + lpaca->yielded = 1; + + /* + * Yield the processor to the hypervisor. We return if + * an external interrupt occurs (which are driven prior + * to returning here) or if a prod occurs from another + * processor. When returning here, external interrupts + * are enabled. + */ + cede_processor(); + + lpaca->yielded = 0; + } + + HMT_medium(); + lpaca->xLpPaca.xIdle = 0; + schedule(); + } + + return 0; +} +#endif + +int cpu_idle(void) +{ + idle_loop(); + return 0; +} -void default_idle(void) +int idle_setup(void) { - barrier(); +#ifdef CONFIG_PPC_ISERIES + idle_loop = iSeries_idle; +#else + if (systemcfg->platform & PLATFORM_PSERIES) { + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + if(get_paca()->xLpPaca.xSharedProc) { + printk("idle = shared_idle\n"); + idle_loop = shared_idle; + } else { + printk("idle = dedicated_idle\n"); + idle_loop = dedicated_idle; + } + } else { + printk("idle = default_idle\n"); + idle_loop = default_idle; + } + } else { + printk("idle_setup: unknown platform, use default_idle\n"); + idle_loop = default_idle; + } +#endif + + return 1; } + diff -puN arch/ppc64/kernel/irq.c~linus arch/ppc64/kernel/irq.c --- 25/arch/ppc64/kernel/irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -59,7 +59,6 @@ extern void iSeries_smp_message_recv( struct pt_regs * ); #endif -volatile unsigned char *chrp_int_ack_special; static void register_irq_proc (unsigned int irq); irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { @@ -300,7 +299,7 @@ void enable_irq(unsigned int irq) spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 1: { - unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); + unsigned int status = desc->status & ~IRQ_DISABLED; desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { desc->status = status | IRQ_REPLAY; @@ -561,17 +560,14 @@ out: spin_unlock(&desc->lock); } +#ifdef CONFIG_PPC_ISERIES int do_IRQ(struct pt_regs *regs) { - int irq, first = 1; -#ifdef CONFIG_PPC_ISERIES struct paca_struct *lpaca; struct ItLpQueue *lpq; -#endif irq_enter(); -#ifdef CONFIG_PPC_ISERIES lpaca = get_paca(); #ifdef CONFIG_SMP if (lpaca->xLpPaca.xIntDword.xFields.xIpiCnt) { @@ -582,7 +578,26 @@ int do_IRQ(struct pt_regs *regs) lpq = lpaca->lpQueuePtr; if (lpq && ItLpQueue_isLpIntPending(lpq)) lpEvent_count += ItLpQueue_process(lpq, regs); -#else + + irq_exit(); + + if (lpaca->xLpPaca.xIntDword.xFields.xDecrInt) { + lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 0; + /* Signal a fake decrementer interrupt */ + timer_interrupt(regs); + } + + return 1; /* lets ret_from_int know we can do checks */ +} + +#else /* CONFIG_PPC_ISERIES */ + +int do_IRQ(struct pt_regs *regs) +{ + int irq, first = 1; + + irq_enter(); + /* * Every arch is required to implement ppc_md.get_irq. * This function will either return an irq number or -1 to @@ -598,20 +613,12 @@ int do_IRQ(struct pt_regs *regs) if (irq != -2 && first) /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; -#endif irq_exit(); -#ifdef CONFIG_PPC_ISERIES - if (lpaca->xLpPaca.xIntDword.xFields.xDecrInt) { - lpaca->xLpPaca.xIntDword.xFields.xDecrInt = 0; - /* Signal a fake decrementer interrupt */ - timer_interrupt(regs); - } -#endif - return 1; /* lets ret_from_int know we can do checks */ } +#endif /* CONFIG_PPC_ISERIES */ unsigned long probe_irq_on (void) { @@ -636,10 +643,10 @@ void __init init_IRQ(void) { static int once = 0; - if ( once ) + if (once) return; - else - once++; + + once++; ppc_md.init_IRQ(); } diff -puN /dev/null arch/ppc64/kernel/iSeries_htab.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/kernel/iSeries_htab.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,197 @@ +/* + * iSeries hashtable management. + * Derived from pSeries_htab.c + * + * SMP scalability work: + * Copyright (C) 2001 Anton Blanchard , IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include + +#if 0 +#include +#include +#include +#include + +#include +#include +#include +#endif + +static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va, + unsigned long prpn, int secondary, + unsigned long hpteflags, int bolted, int large) +{ + long slot; + HPTE lhpte; + + /* + * The hypervisor tries both primary and secondary. + * If we are being called to insert in the secondary, + * it means we have already tried both primary and secondary, + * so we return failure immediately. + */ + if (secondary) + return -1; + + slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT); + if (lhpte.dw0.dw0.v) + panic("select_hpte_slot found entry already valid\n"); + + if (slot == -1) /* No available entry found in either group */ + return -1; + + if (slot < 0) { /* MSB set means secondary group */ + secondary = 1; + slot &= 0x7fffffffffffffff; + } + + lhpte.dw1.dword1 = 0; + lhpte.dw1.dw1.rpn = physRpn_to_absRpn(prpn); + lhpte.dw1.flags.flags = hpteflags; + + lhpte.dw0.dword0 = 0; + lhpte.dw0.dw0.avpn = va >> 23; + lhpte.dw0.dw0.h = secondary; + lhpte.dw0.dw0.bolted = bolted; + lhpte.dw0.dw0.v = 1; + + /* Now fill in the actual HPTE */ + HvCallHpt_addValidate(slot, secondary, &lhpte); + + return (secondary << 3) | (slot & 7); +} + +static unsigned long iSeries_hpte_getword0(unsigned long slot) +{ + unsigned long dword0; + HPTE hpte; + + HvCallHpt_get(&hpte, slot); + dword0 = hpte.dw0.dword0; + + return dword0; +} + +static long iSeries_hpte_remove(unsigned long hpte_group) +{ + unsigned long slot_offset; + int i; + HPTE lhpte; + + /* Pick a random slot to start at */ + slot_offset = mftb() & 0x7; + + for (i = 0; i < HPTES_PER_GROUP; i++) { + lhpte.dw0.dword0 = + iSeries_hpte_getword0(hpte_group + slot_offset); + + if (!lhpte.dw0.dw0.bolted) { + HvCallHpt_invalidateSetSwBitsGet(hpte_group + + slot_offset, 0, 0); + return i; + } + + slot_offset++; + slot_offset &= 0x7; + } + + return -1; +} + +static long iSeries_hpte_updatepp(unsigned long slot, unsigned long newpp, + unsigned long va, int large, int local) +{ + HPTE hpte; + unsigned long avpn = va >> 23; + + HvCallHpt_get(&hpte, slot); + if ((hpte.dw0.dw0.avpn == avpn) && (hpte.dw0.dw0.v)) { + HvCallHpt_setPp(slot, newpp); + return 0; + } + return -1; +} + +/* + * Functions used to find the PTE for a particular virtual address. + * Only used during boot when bolting pages. + * + * Input : vpn : virtual page number + * Output: PTE index within the page table of the entry + * -1 on failure + */ +static long iSeries_hpte_find(unsigned long vpn) +{ + HPTE hpte; + long slot; + + /* + * The HvCallHpt_findValid interface is as follows: + * 0xffffffffffffffff : No entry found. + * 0x00000000xxxxxxxx : Entry found in primary group, slot x + * 0x80000000xxxxxxxx : Entry found in secondary group, slot x + */ + slot = HvCallHpt_findValid(&hpte, vpn); + if (hpte.dw0.dw0.v) { + if (slot < 0) { + slot &= 0x7fffffffffffffff; + slot = -slot; + } + } else + slot = -1; + return slot; +} + +/* + * Update the page protection bits. Intended to be used to create + * guard pages for kernel data structures on pages which are bolted + * in the HPT. Assumes pages being operated on will not be stolen. + * Does not work on large pages. + * + * No need to lock here because we should be the only user. + */ +static void iSeries_hpte_updateboltedpp(unsigned long newpp, unsigned long ea) +{ + unsigned long vsid,va,vpn; + long slot; + + vsid = get_kernel_vsid(ea); + va = (vsid << 28) | (ea & 0x0fffffff); + vpn = va >> PAGE_SHIFT; + slot = iSeries_hpte_find(vpn); + if (slot == -1) + panic("updateboltedpp: Could not find page to bolt\n"); + HvCallHpt_setPp(slot, newpp); +} + +static void iSeries_hpte_invalidate(unsigned long slot, unsigned long va, + int large, int local) +{ + HPTE lhpte; + unsigned long avpn = va >> 23; + + lhpte.dw0.dword0 = iSeries_hpte_getword0(slot); + + if ((lhpte.dw0.dw0.avpn == avpn) && lhpte.dw0.dw0.v) + HvCallHpt_invalidateSetSwBitsGet(slot, 0, 0); +} + +void hpte_init_iSeries(void) +{ + ppc_md.hpte_invalidate = iSeries_hpte_invalidate; + ppc_md.hpte_updatepp = iSeries_hpte_updatepp; + ppc_md.hpte_updateboltedpp = iSeries_hpte_updateboltedpp; + ppc_md.hpte_insert = iSeries_hpte_insert; + ppc_md.hpte_remove = iSeries_hpte_remove; +} diff -puN arch/ppc64/kernel/iSeries_IoMmTable.c~linus arch/ppc64/kernel/iSeries_IoMmTable.c --- 25/arch/ppc64/kernel/iSeries_IoMmTable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_IoMmTable.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,3 +1,4 @@ +#define PCIFR(...) /************************************************************************/ /* This module supports the iSeries I/O Address translation mapping */ /* Copyright (C) 20yy */ @@ -30,134 +31,139 @@ #include #include #include -#include #include #include #include "iSeries_IoMmTable.h" #include "pci.h" -/*******************************************************************/ -/* Table defines */ -/* Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. */ -/*******************************************************************/ +/* + * Table defines + * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. + */ #define Max_Entries 1024 unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000; unsigned long iSeries_Base_Io_Memory = 0xE000000000000000; unsigned long iSeries_Max_Io_Memory = 0xE000000000000000; static long iSeries_CurrentIndex = 0; -/*******************************************************************/ -/* Lookup Tables. */ -/*******************************************************************/ -struct iSeries_Device_Node** iSeries_IoMmTable; -u8* iSeries_IoBarTable; - -/*******************************************************************/ -/* Static and Global variables */ -/*******************************************************************/ -static char* iSeriesPciIoText = "iSeries PCI I/O"; +/* + * Lookup Tables. + */ +struct iSeries_Device_Node **iSeries_IoMmTable; +u8 *iSeries_IoBarTable; + +/* + * Static and Global variables + */ +static char *iSeriesPciIoText = "iSeries PCI I/O"; static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED; -/*******************************************************************/ -/* iSeries_IoMmTable_Initialize */ -/*******************************************************************/ -/* Allocates and initalizes the Address Translation Table and Bar */ -/* Tables to get them ready for use. Must be called before any */ -/* I/O space is handed out to the device BARs. */ -/* A follow up method,iSeries_IoMmTable_Status can be called to */ -/* adjust the table after the device BARs have been assiged to */ -/* resize the table. */ -/*******************************************************************/ +/* + * iSeries_IoMmTable_Initialize + * + * Allocates and initalizes the Address Translation Table and Bar + * Tables to get them ready for use. Must be called before any + * I/O space is handed out to the device BARs. + * A follow up method,iSeries_IoMmTable_Status can be called to + * adjust the table after the device BARs have been assiged to + * resize the table. + */ void iSeries_IoMmTable_Initialize(void) { spin_lock(&iSeriesIoMmTableLock); - iSeries_IoMmTable = kmalloc(sizeof(void*)*Max_Entries,GFP_KERNEL); - iSeries_IoBarTable = kmalloc(sizeof(u8)*Max_Entries, GFP_KERNEL); + iSeries_IoMmTable = kmalloc(sizeof(void *) * Max_Entries, GFP_KERNEL); + iSeries_IoBarTable = kmalloc(sizeof(u8) * Max_Entries, GFP_KERNEL); spin_unlock(&iSeriesIoMmTableLock); - PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable); - if(iSeries_IoMmTable == NULL || iSeries_IoBarTable == NULL) { + PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable); + if ((iSeries_IoMmTable == NULL) || (iSeries_IoBarTable == NULL)) panic("PCI: I/O tables allocation failed.\n"); - } } -/*******************************************************************/ -/* iSeries_IoMmTable_AllocateEntry */ -/*******************************************************************/ -/* Adds pci_dev entry in address translation table */ -/*******************************************************************/ -/* - Allocates the number of entries required in table base on BAR */ -/* size. */ -/* - Allocates starting at iSeries_Base_Io_Memory and increases. */ -/* - The size is round up to be a multiple of entry size. */ -/* - CurrentIndex is incremented to keep track of the last entry. */ -/* - Builds the resource entry for allocated BARs. */ -/*******************************************************************/ -static void iSeries_IoMmTable_AllocateEntry(struct pci_dev* PciDev, int BarNumber) +/* + * iSeries_IoMmTable_AllocateEntry + * + * Adds pci_dev entry in address translation table + * + * - Allocates the number of entries required in table base on BAR + * size. + * - Allocates starting at iSeries_Base_Io_Memory and increases. + * - The size is round up to be a multiple of entry size. + * - CurrentIndex is incremented to keep track of the last entry. + * - Builds the resource entry for allocated BARs. + */ +static void iSeries_IoMmTable_AllocateEntry(struct pci_dev *PciDev, + int BarNumber) { - struct resource* BarResource = &PciDev->resource[BarNumber]; - long BarSize = pci_resource_len(PciDev,BarNumber); - /***********************************************************/ - /* No space to allocate, quick exit, skip Allocation. */ - /***********************************************************/ - if(BarSize == 0) return; - /***********************************************************/ - /* Set Resource values. */ - /***********************************************************/ + struct resource *BarResource = &PciDev->resource[BarNumber]; + long BarSize = pci_resource_len(PciDev, BarNumber); + + /* + * No space to allocate, quick exit, skip Allocation. + */ + if (BarSize == 0) + return; + /* + * Set Resource values. + */ spin_lock(&iSeriesIoMmTableLock); - BarResource->name = iSeriesPciIoText; - BarResource->start = iSeries_IoMmTable_Entry_Size*iSeries_CurrentIndex; - BarResource->start+= iSeries_Base_Io_Memory; - BarResource->end = BarResource->start+BarSize-1; - /***********************************************************/ - /* Allocate the number of table entries needed for BAR. */ - /***********************************************************/ + BarResource->name = iSeriesPciIoText; + BarResource->start = + iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex; + BarResource->start += iSeries_Base_Io_Memory; + BarResource->end = BarResource->start+BarSize-1; + /* + * Allocate the number of table entries needed for BAR. + */ while (BarSize > 0 ) { - *(iSeries_IoMmTable +iSeries_CurrentIndex) = (struct iSeries_Device_Node*)PciDev->sysdata; - *(iSeries_IoBarTable+iSeries_CurrentIndex) = BarNumber; + *(iSeries_IoMmTable + iSeries_CurrentIndex) = + (struct iSeries_Device_Node *)PciDev->sysdata; + *(iSeries_IoBarTable + iSeries_CurrentIndex) = BarNumber; BarSize -= iSeries_IoMmTable_Entry_Size; ++iSeries_CurrentIndex; } - iSeries_Max_Io_Memory = (iSeries_IoMmTable_Entry_Size*iSeries_CurrentIndex)+iSeries_Base_Io_Memory; + iSeries_Max_Io_Memory = iSeries_Base_Io_Memory + + (iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex); spin_unlock(&iSeriesIoMmTableLock); } -/*******************************************************************/ -/* iSeries_allocateDeviceBars */ -/*******************************************************************/ -/* - Allocates ALL pci_dev BAR's and updates the resources with the*/ -/* BAR value. BARS with zero length will have the resources */ -/* The HvCallPci_getBarParms is used to get the size of the BAR */ -/* space. It calls iSeries_IoMmTable_AllocateEntry to allocate */ -/* each entry. */ -/* - Loops through The Bar resources(0 - 5) including the ROM */ -/* is resource(6). */ -/*******************************************************************/ -void iSeries_allocateDeviceBars(struct pci_dev* PciDev) +/* + * iSeries_allocateDeviceBars + * + * - Allocates ALL pci_dev BAR's and updates the resources with the + * BAR value. BARS with zero length will have the resources + * The HvCallPci_getBarParms is used to get the size of the BAR + * space. It calls iSeries_IoMmTable_AllocateEntry to allocate + * each entry. + * - Loops through The Bar resources(0 - 5) including the ROM + * is resource(6). + */ +void iSeries_allocateDeviceBars(struct pci_dev *PciDev) { - struct resource* BarResource; - int BarNumber; - for(BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) { + struct resource *BarResource; + int BarNumber; + + for (BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) { BarResource = &PciDev->resource[BarNumber]; iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber); } } -/************************************************************************/ -/* Translates the IoAddress to the device that is mapped to IoSpace. */ -/* This code is inlined, see the iSeries_pci.c file for the replacement.*/ -/************************************************************************/ -struct iSeries_Device_Node* iSeries_xlateIoMmAddress(void* IoAddress) +/* + * Translates the IoAddress to the device that is mapped to IoSpace. + * This code is inlined, see the iSeries_pci.c file for the replacement. + */ +struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress) { return NULL; } -/************************************************************************ +/* * Status hook for IoMmTable - ************************************************************************/ -void iSeries_IoMmTable_Status(void) + */ +void iSeries_IoMmTable_Status(void) { - PCIFR("IoMmTable......: 0x%p",iSeries_IoMmTable); - PCIFR("IoMmTable Range: 0x%p to 0x%p",iSeries_Base_Io_Memory,iSeries_Max_Io_Memory); - return; + PCIFR("IoMmTable......: 0x%p", iSeries_IoMmTable); + PCIFR("IoMmTable Range: 0x%p to 0x%p", iSeries_Base_Io_Memory, + iSeries_Max_Io_Memory); } diff -puN arch/ppc64/kernel/iSeries_IoMmTable.h~linus arch/ppc64/kernel/iSeries_IoMmTable.h --- 25/arch/ppc64/kernel/iSeries_IoMmTable.h~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_IoMmTable.h 2004-01-19 22:17:21.000000000 -0800 @@ -31,55 +31,55 @@ struct pci_dev; struct iSeries_Device_Node; -extern struct iSeries_Device_Node** iSeries_IoMmTable; -extern u8* iSeries_IoBarTable; +extern struct iSeries_Device_Node **iSeries_IoMmTable; +extern u8 *iSeries_IoBarTable; extern unsigned long iSeries_Base_Io_Memory; extern unsigned long iSeries_Max_Io_Memory; extern unsigned long iSeries_Base_Io_Memory; extern unsigned long iSeries_IoMmTable_Entry_Size; -/************************************************************************/ -/* iSeries_IoMmTable_Initialize */ -/************************************************************************/ -/* - Initalizes the Address Translation Table and get it ready for use. */ -/* Must be called before any client calls any of the other methods. */ -/* */ -/* Parameters: None. */ -/* */ -/* Return: None. */ -/************************************************************************/ -extern void iSeries_IoMmTable_Initialize(void); -extern void iSeries_IoMmTable_Status(void); +/* + * iSeries_IoMmTable_Initialize + * + * - Initalizes the Address Translation Table and get it ready for use. + * Must be called before any client calls any of the other methods. + * + * Parameters: None. + * + * Return: None. + */ +extern void iSeries_IoMmTable_Initialize(void); +extern void iSeries_IoMmTable_Status(void); -/************************************************************************/ -/* iSeries_allocateDeviceBars */ -/************************************************************************/ -/* - Allocates ALL pci_dev BAR's and updates the resources with the BAR */ -/* value. BARS with zero length will not have the resources. The */ -/* HvCallPci_getBarParms is used to get the size of the BAR space. */ -/* It calls iSeries_IoMmTable_AllocateEntry to allocate each entry. */ -/* */ -/* Parameters: */ -/* pci_dev = Pointer to pci_dev structure that will be mapped to pseudo */ -/* I/O Address. */ -/* */ -/* Return: */ -/* The pci_dev I/O resources updated with pseudo I/O Addresses. */ -/************************************************************************/ -extern void iSeries_allocateDeviceBars(struct pci_dev* ); +/* + * iSeries_allocateDeviceBars + * + * - Allocates ALL pci_dev BAR's and updates the resources with the BAR + * value. BARS with zero length will not have the resources. The + * HvCallPci_getBarParms is used to get the size of the BAR space. + * It calls iSeries_IoMmTable_AllocateEntry to allocate each entry. + * + * Parameters: + * pci_dev = Pointer to pci_dev structure that will be mapped to pseudo + * I/O Address. + * + * Return: + * The pci_dev I/O resources updated with pseudo I/O Addresses. + */ +extern void iSeries_allocateDeviceBars(struct pci_dev *); -/************************************************************************/ -/* iSeries_xlateIoMmAddress */ -/************************************************************************/ -/* - Translates an I/O Memory address to Device Node that has been the */ -/* allocated the psuedo I/O Address. */ -/* */ -/* Parameters: */ -/* IoAddress = I/O Memory Address. */ -/* */ -/* Return: */ -/* An iSeries_Device_Node to the device mapped to the I/O address. The*/ -/* BarNumber and BarOffset are valid if the Device Node is returned. */ -/************************************************************************/ -extern struct iSeries_Device_Node* iSeries_xlateIoMmAddress(void* IoAddress); +/* + * iSeries_xlateIoMmAddress + * + * - Translates an I/O Memory address to Device Node that has been the + * allocated the psuedo I/O Address. + * + * Parameters: + * IoAddress = I/O Memory Address. + * + * Return: + * An iSeries_Device_Node to the device mapped to the I/O address. The + * BarNumber and BarOffset are valid if the Device Node is returned. + */ +extern struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress); #endif /* _ISERIES_IOMMTABLE_H */ diff -puN arch/ppc64/kernel/iSeries_irq.c~linus arch/ppc64/kernel/iSeries_irq.c --- 25/arch/ppc64/kernel/iSeries_irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -40,219 +40,177 @@ #include #include - -hw_irq_controller iSeries_IRQ_handler = { - "iSeries irq controller", - iSeries_startup_IRQ, /* startup */ - iSeries_shutdown_IRQ, /* shutdown */ - iSeries_enable_IRQ, /* enable */ - iSeries_disable_IRQ, /* disable */ - NULL, /* ack */ - iSeries_end_IRQ, /* end */ - NULL /* set_affinity */ -}; - - -struct iSeries_irqEntry { - u32 dsa; - struct iSeries_irqEntry* next; -}; - -struct iSeries_irqAnchor { - u8 valid : 1; - u8 reserved : 7; - u16 entryCount; - struct iSeries_irqEntry* head; +static unsigned int iSeries_startup_IRQ(unsigned int irq); +static void iSeries_shutdown_IRQ(unsigned int irq); +static void iSeries_enable_IRQ(unsigned int irq); +static void iSeries_disable_IRQ(unsigned int irq); +static void iSeries_end_IRQ(unsigned int irq); + +static hw_irq_controller iSeries_IRQ_handler = { + .typename = "iSeries irq controller", + .startup = iSeries_startup_IRQ, + .shutdown = iSeries_shutdown_IRQ, + .enable = iSeries_enable_IRQ, + .disable = iSeries_disable_IRQ, + .end = iSeries_end_IRQ }; -struct iSeries_irqAnchor iSeries_irqMap[NR_IRQS]; - -void iSeries_init_irqMap(int irq); +void iSeries_init_irq_desc(irq_desc_t *desc) +{ +} -/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ +/* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ void __init iSeries_init_IRQ(void) { - int i; - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = &iSeries_IRQ_handler; - irq_desc[i].status = 0; - irq_desc[i].status |= IRQ_DISABLED; - irq_desc[i].depth = 1; - iSeries_init_irqMap(i); - } /* Register PCI event handler and open an event path */ - PPCDBG(PPCDBG_BUSWALK,"Register PCI event handler and open an event path\n"); + PPCDBG(PPCDBG_BUSWALK, + "Register PCI event handler and open an event path\n"); XmPciLpEvent_init(); return; } -/********************************************************************** - * Called by iSeries_init_IRQ - * Prevent IRQs 0 and 255 from being used. IRQ 0 appears in - * uninitialized devices. IRQ 255 appears in the PCI interrupt - * line register if a PCI error occurs, - *********************************************************************/ -void __init iSeries_init_irqMap(int irq) -{ - iSeries_irqMap[irq].valid = (irq == 0 || irq == 255)? 0 : 1; - iSeries_irqMap[irq].entryCount = 0; - iSeries_irqMap[irq].head = NULL; -} - -/* This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot */ -/* It calculates the irq value for the slot. */ -int __init iSeries_allocate_IRQ(HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) +/* + * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot + * It calculates the irq value for the slot. + * Note that subBusNumber is always 0 (at the moment at least). + */ +int __init iSeries_allocate_IRQ(HvBusNumber busNumber, + HvSubBusNumber subBusNumber, HvAgentId deviceId) { u8 idsel = (deviceId >> 4); - u8 function = deviceId & 0x0F; - int irq = ((((busNumber-1)*16 + (idsel-1)*8 + function)*9/8) % 253) + 2; - return irq; + u8 function = deviceId & 7; + + return ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function + 1; } -/* This is called out of iSeries_scan_slot to assign the EADS slot to its IRQ number */ -int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, HvSubBusNumber subBusNumber, HvAgentId deviceId) +#define IRQ_TO_BUS(irq) (((((irq) - 1) >> 6) & 0xff) + 1) +#define IRQ_TO_IDSEL(irq) (((((irq) - 1) >> 3) & 7) + 1) +#define IRQ_TO_FUNC(irq) (((irq) - 1) & 7) + +/* + * This is called out of iSeries_scan_slot to assign the EADS slot + * to its IRQ number + */ +int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, + HvSubBusNumber subBusNumber, HvAgentId deviceId) { - int rc; - u32 dsa = (busNumber << 16) | (subBusNumber << 8) | deviceId; - struct iSeries_irqEntry* newEntry; - unsigned long flags; + irq_desc_t *desc = get_real_irq_desc(irq); - if (irq < 0 || irq >= NR_IRQS) { + if (desc == NULL) return -1; - } - newEntry = kmalloc(sizeof(*newEntry), GFP_KERNEL); - if (newEntry == NULL) { - return -ENOMEM; - } - newEntry->dsa = dsa; - newEntry->next = NULL; - /******************************************************************** - * Probably not necessary to lock the irq since allocation is only - * done during buswalk, but it should not hurt anything except a - * little performance to be smp safe. - *******************************************************************/ - spin_lock_irqsave(&irq_desc[irq].lock, flags); - - if (iSeries_irqMap[irq].valid) { - /* Push the new element onto the irq stack */ - newEntry->next = iSeries_irqMap[irq].head; - iSeries_irqMap[irq].head = newEntry; - ++iSeries_irqMap[irq].entryCount; - rc = 0; - PPCDBG(PPCDBG_BUSWALK,"iSeries_assign_IRQ 0x%04X.%02X.%02X = 0x%04X\n",busNumber, subBusNumber, deviceId, irq); - } - else { - printk("PCI: Something is wrong with the iSeries_irqMap. \n"); - kfree(newEntry); - rc = -1; - } - spin_unlock_irqrestore(&irq_desc[irq].lock, flags); - return rc; + desc->handler = &iSeries_IRQ_handler; + return 0; } /* This is called by iSeries_activate_IRQs */ -unsigned int iSeries_startup_IRQ(unsigned int irq) +static unsigned int iSeries_startup_IRQ(unsigned int irq) { - struct iSeries_irqEntry* entry; - u32 bus, subBus, deviceId, function, mask; - for(entry=iSeries_irqMap[irq].head; entry!=NULL; entry=entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - function = deviceId & 0x0F; - /* Link the IRQ number to the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); - /* Unmask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK,"iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n",bus,subBus,deviceId,irq); - } + u32 bus, deviceId, function, mask; + const u32 subBus = 0; + + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Link the IRQ number to the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, irq); + + /* Unmask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_unmaskFisr(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_activate_IRQ 0x%02X.%02X.%02X Irq:0x%02X\n", + bus, subBus, deviceId, irq); return 0; } -/* This is called out of iSeries_fixup to activate interrupt - * generation for usable slots */ +/* + * This is called out of iSeries_fixup to activate interrupt + * generation for usable slots + */ void __init iSeries_activate_IRQs() { int irq; unsigned long flags; - for (irq=0; irq < NR_IRQS; irq++) { - spin_lock_irqsave(&irq_desc[irq].lock, flags); - irq_desc[irq].handler->startup(irq); - spin_unlock_irqrestore(&irq_desc[irq].lock, flags); + + for (irq = 0; irq < NR_IRQS; irq++) { + irq_desc_t *desc = get_irq_desc(irq); + + if (desc && desc->handler && desc->handler->startup) { + spin_lock_irqsave(&desc->lock, flags); + desc->handler->startup(irq); + spin_unlock_irqrestore(&desc->lock, flags); + } } } /* this is not called anywhere currently */ -void iSeries_shutdown_IRQ(unsigned int irq) { - struct iSeries_irqEntry* entry; - u32 bus, subBus, deviceId, function, mask; +static void iSeries_shutdown_IRQ(unsigned int irq) +{ + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* irq should be locked by the caller */ + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; - for (entry=iSeries_irqMap[irq].head; entry; entry=entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - function = deviceId & 0x0F; - /* Invalidate the IRQ number in the bridge */ - HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); - /* Mask bridge interrupts in the FISR */ - mask = 0x01010000 << function; - HvCallPci_maskFisr(bus, subBus, deviceId, mask); - } + /* Invalidate the IRQ number in the bridge */ + HvCallXm_connectBusUnit(bus, subBus, deviceId, 0); + /* Mask bridge interrupts in the FISR */ + mask = 0x01010000 << function; + HvCallPci_maskFisr(bus, subBus, deviceId, mask); } -/*********************************************************** +/* * This will be called by device drivers (via disable_IRQ) * to disable INTA in the bridge interrupt status register. - ***********************************************************/ -void iSeries_disable_IRQ(unsigned int irq) + */ +static void iSeries_disable_IRQ(unsigned int irq) { - struct iSeries_irqEntry* entry; - u32 bus, subBus, deviceId, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* The IRQ has already been locked by the caller */ - - for (entry=iSeries_irqMap[irq].head; entry; entry=entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - /* Mask secondary INTA */ - mask = 0x80000000; - HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK,"iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",bus,subBus,deviceId,irq); - } + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Mask secondary INTA */ + mask = 0x80000000; + HvCallPci_maskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); } -/*********************************************************** +/* * This will be called by device drivers (via enable_IRQ) * to enable INTA in the bridge interrupt status register. - ***********************************************************/ -void iSeries_enable_IRQ(unsigned int irq) + */ +static void iSeries_enable_IRQ(unsigned int irq) { - struct iSeries_irqEntry* entry; - u32 bus, subBus, deviceId, mask; + u32 bus, deviceId, function, mask; + const u32 subBus = 0; /* The IRQ has already been locked by the caller */ - for (entry=iSeries_irqMap[irq].head; entry; entry=entry->next) { - bus = (entry->dsa >> 16) & 0xFFFF; - subBus = (entry->dsa >> 8) & 0xFF; - deviceId = entry->dsa & 0xFF; - /* Unmask secondary INTA */ - mask = 0x80000000; - HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); - PPCDBG(PPCDBG_BUSWALK,"iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",bus,subBus,deviceId,irq); - } -} - -/* Need to define this so ppc_irq_dispatch_handler will NOT call - enable_IRQ at the end of interrupt handling. However, this - does nothing because there is not enough information provided - to do the EOI HvCall. This is done by XmPciLpEvent.c */ -void iSeries_end_IRQ(unsigned int irq) + bus = IRQ_TO_BUS(irq); + function = IRQ_TO_FUNC(irq); + deviceId = (IRQ_TO_IDSEL(irq) << 4) + function; + + /* Unmask secondary INTA */ + mask = 0x80000000; + HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask); + PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n", + bus, subBus, deviceId, irq); +} + +/* + * Need to define this so ppc_irq_dispatch_handler will NOT call + * enable_IRQ at the end of interrupt handling. However, this does + * nothing because there is not enough information provided to do + * the EOI HvCall. This is done by XmPciLpEvent.c + */ +static void iSeries_end_IRQ(unsigned int irq) { } - diff -puN arch/ppc64/kernel/iSeries_pci.c~linus arch/ppc64/kernel/iSeries_pci.c --- 25/arch/ppc64/kernel/iSeries_pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,3 +1,4 @@ +#define PCIFR(...) /* * iSeries_pci.c * @@ -35,7 +36,6 @@ #include #include #include -#include #include #include @@ -49,856 +49,811 @@ #include "iSeries_IoMmTable.h" #include "pci.h" -extern struct pci_controller* hose_head; -extern struct pci_controller** hose_tail; -extern int global_phb_number; -extern int panic_timeout; +extern int panic_timeout; -extern struct device_node *allnodes; extern unsigned long iSeries_Base_Io_Memory; -extern struct pci_ops iSeries_pci_ops; -extern struct flightRecorder* PciFr; -extern struct TceTable* tceTables[256]; - -/******************************************************************* - * Counters and control flags. - *******************************************************************/ -extern long Pci_Io_Read_Count; -extern long Pci_Io_Write_Count; -extern long Pci_Cfg_Read_Count; -extern long Pci_Cfg_Write_Count; -extern long Pci_Error_Count; - -extern int Pci_Retry_Max; -extern int Pci_Error_Flag; -extern int Pci_Trace_Flag; +extern struct TceTable *tceTables[256]; extern void iSeries_MmIoTest(void); - -/******************************************************************* +/* * Forward declares of prototypes. - *******************************************************************/ -struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev); -struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev); - -unsigned long find_and_init_phbs(void); -struct pci_controller* alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) ; - -void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb); -void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel); -int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* Info); -void list_device_nodes(void); - -struct pci_dev; + */ +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn); +static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb); +static void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, + int IdSel); +static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, + struct HvCallPci_BridgeInfo *Info); LIST_HEAD(iSeries_Global_Device_List); -int DeviceCount = 0; - +static int DeviceCount; /* Counters and control flags. */ -static long Pci_Io_Read_Count = 0; -static long Pci_Io_Write_Count = 0; -static long Pci_Cfg_Read_Count = 0; -static long Pci_Cfg_Write_Count= 0; -static long Pci_Error_Count = 0; - -static int Pci_Retry_Max = 3; /* Only retry 3 times */ -static int Pci_Error_Flag = 1; /* Set Retry Error on. */ -static int Pci_Trace_Flag = 0; +static long Pci_Io_Read_Count; +static long Pci_Io_Write_Count; +#if 0 +static long Pci_Cfg_Read_Count; +static long Pci_Cfg_Write_Count; +#endif +static long Pci_Error_Count; + +static int Pci_Retry_Max = 3; /* Only retry 3 times */ +static int Pci_Error_Flag = 1; /* Set Retry Error on. */ +static struct pci_ops iSeries_pci_ops; -/********************************************************************************** +/* * Log Error infor in Flight Recorder to system Console. * Filter out the device not there errors. * PCI: EADs Connect Failed 0x18.58.10 Rc: 0x00xx * PCI: Read Vendor Failed 0x18.58.10 Rc: 0x00xx * PCI: Connect Bus Unit Failed 0x18.58.10 Rc: 0x00xx - **********************************************************************************/ -void pci_Log_Error(char* Error_Text, int Bus, int SubBus, int AgentId, int HvRc) + */ +static void pci_Log_Error(char *Error_Text, int Bus, int SubBus, + int AgentId, int HvRc) { - if( HvRc != 0x0302) { - char ErrorString[128]; - sprintf(ErrorString,"%s Failed: 0x%02X.%02X.%02X Rc: 0x%04X",Error_Text,Bus,SubBus,AgentId,HvRc); - PCIFR(ErrorString); - printk("PCI: %s\n",ErrorString); - } + if (HvRc == 0x0302) + return; + + printk(KERN_ERR "PCI: %s Failed: 0x%02X.%02X.%02X Rc: 0x%04X", + Error_Text, Bus, SubBus, AgentId, HvRc); } -/********************************************************************************** +#if 0 +/* * Dump the iSeries Temp Device Node - *<4>buswalk [swapper : - DeviceNode: 0xC000000000634300 - *<4>00. Device Node = 0xC000000000634300 - *<4> - PciDev = 0x0000000000000000 - *<4> - tDevice = 0x 17:01.00 0x1022 00 - *<4> 4. Device Node = 0xC000000000634480 - *<4> - PciDev = 0x0000000000000000 - *<4> - Device = 0x 18:38.16 Irq:0xA7 Vendor:0x1014 Flags:0x00 - *<4> - Devfn = 0xB0: 22.18 - **********************************************************************************/ -void dumpDevice_Node(struct iSeries_Device_Node* DevNode) + * <4>buswalk [swapper : - DeviceNode: 0xC000000000634300 + * <4>00. Device Node = 0xC000000000634300 + * <4> - PciDev = 0x0000000000000000 + * <4> - tDevice = 0x 17:01.00 0x1022 00 + * <4> 4. Device Node = 0xC000000000634480 + * <4> - PciDev = 0x0000000000000000 + * <4> - Device = 0x 18:38.16 Irq:0xA7 Vendor:0x1014 Flags:0x00 + * <4> - Devfn = 0xB0: 22.18 + */ +void dumpDevice_Node(struct iSeries_Device_Node *DevNode) { - udbg_printf("Device Node = 0x%p\n",DevNode); - udbg_printf(" - PciDev = 0x%p\n",DevNode->PciDev); + udbg_printf("Device Node = 0x%p\n", DevNode); + udbg_printf(" - PciDev = 0x%p\n", DevNode->PciDev); udbg_printf(" - Device = 0x%4X:%02X.%02X (0x%02X)\n", - ISERIES_BUS(DevNode), - ISERIES_SUBBUS(DevNode), - DevNode->AgentId, - DevNode->DevFn); - udbg_printf(" - LSlot = 0x%02X\n",DevNode->LogicalSlot); - udbg_printf(" - TceTable = 0x%p\n ",DevNode->DevTceTable); - - udbg_printf(" - DSA = 0x%04X\n",ISERIES_DSA(DevNode)>>32 ); - + ISERIES_BUS(DevNode), ISERIES_SUBBUS(DevNode), + DevNode->AgentId, DevNode->DevFn); + udbg_printf(" - LSlot = 0x%02X\n", DevNode->LogicalSlot); + udbg_printf(" - TceTable = 0x%p\n ", DevNode->DevTceTable); + udbg_printf(" - DSA = 0x%04X\n", ISERIES_DSA(DevNode) >> 32); udbg_printf(" = Irq:0x%02X Vendor:0x%04X Flags:0x%02X\n", - DevNode->Irq, - DevNode->Vendor, - DevNode->Flags ); - udbg_printf(" - Location = %s\n",DevNode->CardLocation); - - + DevNode->Irq, DevNode->Vendor, DevNode->Flags); + udbg_printf(" - Location = %s\n", DevNode->CardLocation); } -/********************************************************************************** + +/* * Walk down the device node chain - **********************************************************************************/ -void list_device_nodes(void) + */ +static void list_device_nodes(void) { - struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; - while(Device_Node_Ptr != &iSeries_Global_Device_List) { - dumpDevice_Node( (struct iSeries_Device_Node*)Device_Node_Ptr ); + struct list_head *Device_Node_Ptr = iSeries_Global_Device_List.next; + + while (Device_Node_Ptr != &iSeries_Global_Device_List) { + dumpDevice_Node((struct iSeries_Device_Node*)Device_Node_Ptr); Device_Node_Ptr = Device_Node_Ptr->next; } } - +#endif -/*********************************************************************** +/* * build_device_node(u16 Bus, int SubBus, u8 DevFn) - * - ***********************************************************************/ -struct iSeries_Device_Node* build_device_node(HvBusNumber Bus, HvSubBusNumber SubBus, int AgentId, int Function) + */ +static struct iSeries_Device_Node *build_device_node(HvBusNumber Bus, + HvSubBusNumber SubBus, int AgentId, int Function) { - struct iSeries_Device_Node* DeviceNode; - - PPCDBG(PPCDBG_BUSWALK,"-build_device_node 0x%02X.%02X.%02X Function: %02X\n",Bus,SubBus,AgentId, Function); + struct iSeries_Device_Node *node; - DeviceNode = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); - if(DeviceNode == NULL) return NULL; - - memset(DeviceNode,0,sizeof(struct iSeries_Device_Node) ); - list_add_tail(&DeviceNode->Device_List,&iSeries_Global_Device_List); - /*DeviceNode->DsaAddr = ((u64)Bus<<48)+((u64)SubBus<<40)+((u64)0x10<<32); */ - ISERIES_BUS(DeviceNode) = Bus; - ISERIES_SUBBUS(DeviceNode) = SubBus; - DeviceNode->DsaAddr.deviceId = 0x10; - DeviceNode->DsaAddr.barNumber = 0; - DeviceNode->AgentId = AgentId; - DeviceNode->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId),Function ); - DeviceNode->IoRetry = 0; - iSeries_Get_Location_Code(DeviceNode); - PCIFR("Device 0x%02X.%2X, Node:0x%p ",ISERIES_BUS(DeviceNode),ISERIES_DEVFUN(DeviceNode),DeviceNode); - return DeviceNode; -} -/**************************************************************************** -* -* Allocate pci_controller(phb) initialized common variables. -* -*****************************************************************************/ -struct pci_controller* pci_alloc_pci_controllerX(char *model, enum phb_types controller_type) -{ - struct pci_controller *hose; - hose = (struct pci_controller*)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); - if(hose == NULL) return NULL; - - memset(hose, 0, sizeof(struct pci_controller)); - if(strlen(model) < 8) strcpy(hose->what,model); - else memcpy(hose->what,model,7); - hose->type = controller_type; - hose->global_number = global_phb_number; - global_phb_number++; - - *hose_tail = hose; - hose_tail = &hose->next; - return hose; + PPCDBG(PPCDBG_BUSWALK, + "-build_device_node 0x%02X.%02X.%02X Function: %02X\n", + Bus, SubBus, AgentId, Function); + + node = kmalloc(sizeof(struct iSeries_Device_Node), GFP_KERNEL); + if (node == NULL) + return NULL; + + memset(node, 0, sizeof(struct iSeries_Device_Node)); + list_add_tail(&node->Device_List, &iSeries_Global_Device_List); +#if 0 + node->DsaAddr = ((u64)Bus << 48) + ((u64)SubBus << 40) + ((u64)0x10 << 32); +#endif + node->DsaAddr.DsaAddr = 0; + node->DsaAddr.Dsa.busNumber = Bus; + node->DsaAddr.Dsa.subBusNumber = SubBus; + node->DsaAddr.Dsa.deviceId = 0x10; + node->AgentId = AgentId; + node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function); + node->IoRetry = 0; + iSeries_Get_Location_Code(node); + PCIFR("Device 0x%02X.%2X, Node:0x%p ", ISERIES_BUS(node), + ISERIES_DEVFUN(node), node); + return node; } -/**************************************************************************** - * - * unsigned int __init find_and_init_phbs(void) +/* + * unsigned long __init find_and_init_phbs(void) * * Description: * This function checks for all possible system PCI host bridges that connect * PCI buses. The system hypervisor is queried as to the guest partition - * ownership status. A pci_controller is build for any bus which is partially + * ownership status. A pci_controller is built for any bus which is partially * owned or fully owned by this guest partition. - ****************************************************************************/ + */ unsigned long __init find_and_init_phbs(void) { - struct pci_controller* phb; - HvBusNumber BusNumber; + struct pci_controller *phb; + HvBusNumber bus; - PPCDBG(PPCDBG_BUSWALK,"find_and_init_phbs Entry\n"); + PPCDBG(PPCDBG_BUSWALK, "find_and_init_phbs Entry\n"); /* Check all possible buses. */ - for (BusNumber = 0; BusNumber < 256; BusNumber++) { - int RtnCode = HvCallXm_testBus(BusNumber); - if (RtnCode == 0) { - phb = pci_alloc_pci_controllerX("PHB HV", phb_type_hypervisor); - if(phb == NULL) { - printk("PCI: Allocate pci_controller failed.\n"); - PCIFR( "Allocate pci_controller failed."); + for (bus = 0; bus < 256; bus++) { + int ret = HvCallXm_testBus(bus); + if (ret == 0) { + printk("bus %d appears to exist\n", bus); + phb = pci_alloc_pci_controller(phb_type_hypervisor); + if (phb == NULL) { + PCIFR("Allocate pci_controller failed."); return -1; } - phb->pci_mem_offset = phb->local_number = BusNumber; - phb->first_busno = BusNumber; - phb->last_busno = BusNumber; - phb->ops = &iSeries_pci_ops; - - PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n",phb,BusNumber); - PCIFR("Create iSeries PHB controller: %04X",BusNumber); - - /***************************************************/ - /* Find and connect the devices. */ - /***************************************************/ + phb->pci_mem_offset = phb->local_number = bus; + phb->first_busno = bus; + phb->last_busno = bus; + phb->ops = &iSeries_pci_ops; + + PPCDBG(PPCDBG_BUSWALK, "PCI:Create iSeries pci_controller(%p), Bus: %04X\n", + phb, bus); + PCIFR("Create iSeries PHB controller: %04X", bus); + + /* Find and connect the devices. */ iSeries_Scan_PHBs_Slots(phb); } - /* Check for Unexpected Return code, a clue that something */ - /* has gone wrong. */ - else if(RtnCode != 0x0301) { - PCIFR("Unexpected Return on Probe(0x%04X): 0x%04X",BusNumber,RtnCode); - } - + /* + * Check for Unexpected Return code, a clue that something + * has gone wrong. + */ + else if (ret != 0x0301) + printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X", + bus, ret); } return 0; } -/*********************************************************************** + +/* * iSeries_pcibios_init * * Chance to initialize and structures or variable before PCI Bus walk. - * - *<4>buswalk [swapper : iSeries_pcibios_init Entry. - *<4>buswalk [swapper : IoMmTable Initialized 0xC00000000034BD30 - *<4>buswalk [swapper : find_and_init_phbs Entry - *<4>buswalk [swapper : Create iSeries pci_controller:(0xC00000001F5C7000), Bus 0x0017 - *<4>buswalk [swapper : Connect EADs: 0x17.00.12 = 0x00 - *<4>buswalk [swapper : iSeries_assign_IRQ 0x0017.00.12 = 0x0091 - *<4>buswalk [swapper : - allocate and assign IRQ 0x17.00.12 = 0x91 - *<4>buswalk [swapper : - FoundDevice: 0x17.28.10 = 0x12AE - *<4>buswalk [swapper : - build_device_node 0x17.28.12 - *<4>buswalk [swapper : iSeries_pcibios_init Exit. - ***********************************************************************/ + */ void iSeries_pcibios_init(void) { - PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Entry.\n"); - + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Entry.\n"); iSeries_IoMmTable_Initialize(); - find_and_init_phbs(); - - pci_assign_all_busses = 0; - PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_init Exit.\n"); + /* pci_assign_all_busses = 0; SFRXXX*/ + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_init Exit.\n"); } -/*********************************************************************** + +/* * pcibios_final_fixup(void) - ***********************************************************************/ + */ void __init pcibios_final_fixup(void) { - struct pci_dev* PciDev = NULL; - struct iSeries_Device_Node* DeviceNode; - char Buffer[256]; - int DeviceCount = 0; + struct pci_dev *pdev = NULL; + struct iSeries_Device_Node *node; + char Buffer[256]; + int DeviceCount = 0; + + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); - PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup Entry.\n"); - /******************************************************/ /* Fix up at the device node and pci_dev relationship */ - /******************************************************/ mf_displaySrc(0xC9000100); - while ((PciDev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, PciDev)) != NULL) { - DeviceNode = find_Device_Node(PciDev); - if(DeviceNode != NULL) { - ++DeviceCount; - PciDev->sysdata = (void*)DeviceNode; - DeviceNode->PciDev = PciDev; - - PPCDBG(PPCDBG_BUSWALK,"PciDev 0x%p <==> DevNode 0x%p\n",PciDev,DeviceNode ); - - iSeries_allocateDeviceBars(PciDev); - - iSeries_Device_Information(PciDev,Buffer, sizeof(Buffer) ); - printk("%d. %s\n",DeviceCount,Buffer); + printk("pcibios_final_fixup\n"); + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) + != NULL) { + node = find_Device_Node(pdev->bus->number, pdev->devfn); + printk("pci dev %p (%x.%x), node %p\n", pdev, + pdev->bus->number, pdev->devfn, node); - create_pci_bus_tce_table((unsigned long)DeviceNode); - } else { - printk("PCI: Device Tree not found for 0x%016lX\n",(unsigned long)PciDev); - } + if (node != NULL) { + ++DeviceCount; + pdev->sysdata = (void *)node; + node->PciDev = pdev; + PPCDBG(PPCDBG_BUSWALK, + "pdev 0x%p <==> DevNode 0x%p\n", + pdev, node); + iSeries_allocateDeviceBars(pdev); + iSeries_Device_Information(pdev, Buffer, + sizeof(Buffer)); + printk("%d. %s\n", DeviceCount, Buffer); + create_pci_bus_tce_table((unsigned long)node); + } else + printk("PCI: Device Tree not found for 0x%016lX\n", + (unsigned long)pdev); } iSeries_IoMmTable_Status(); - iSeries_activate_IRQs(); - mf_displaySrc(0xC9000200); } -void pcibios_fixup_bus(struct pci_bus* PciBus) +void pcibios_fixup_bus(struct pci_bus *PciBus) { - PPCDBG(PPCDBG_BUSWALK,"iSeries_pcibios_fixup_bus(0x%04X) Entry.\n",PciBus->number); - + PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup_bus(0x%04X) Entry.\n", + PciBus->number); } - -/*********************************************************************** - * pcibios_fixup_resources(struct pci_dev *dev) - * - ***********************************************************************/ -void pcibios_fixup_resources(struct pci_dev *PciDev) +void pcibios_fixup_resources(struct pci_dev *pdev) { - PPCDBG(PPCDBG_BUSWALK,"pcibios_fixup_resources PciDev %p\n",PciDev); + PPCDBG(PPCDBG_BUSWALK, "fixup_resources pdev %p\n", pdev); } +/* + * Loop through each node function to find usable EADs bridges. + */ +static void iSeries_Scan_PHBs_Slots(struct pci_controller *Phb) +{ + struct HvCallPci_DeviceInfo *DevInfo; + HvBusNumber bus = Phb->local_number; /* System Bus */ + const HvSubBusNumber SubBus = 0; /* EADs is always 0. */ + int HvRc = 0; + int IdSel; + const int MaxAgents = 8; + + DevInfo = (struct HvCallPci_DeviceInfo*) + kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); + if (DevInfo == NULL) + return; -/******************************************************************************** -* Loop through each node function to find usable EADs bridges. -*********************************************************************************/ -void iSeries_Scan_PHBs_Slots(struct pci_controller* Phb) -{ - struct HvCallPci_DeviceInfo* DevInfo; - HvBusNumber Bus = Phb->local_number; /* System Bus */ - HvSubBusNumber SubBus = 0; /* EADs is always 0. */ - int HvRc = 0; - int IdSel = 1; - int MaxAgents = 8; - - DevInfo = (struct HvCallPci_DeviceInfo*)kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL); - if(DevInfo == NULL) return; - - /******************************************************************************** + /* * Probe for EADs Bridges - ********************************************************************************/ - for (IdSel=1; IdSel < MaxAgents; ++IdSel) { - HvRc = HvCallPci_getDeviceInfo(Bus, SubBus, IdSel,REALADDR(DevInfo), sizeof(struct HvCallPci_DeviceInfo)); + */ + for (IdSel = 1; IdSel < MaxAgents; ++IdSel) { + HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel, + REALADDR(DevInfo), + sizeof(struct HvCallPci_DeviceInfo)); if (HvRc == 0) { - if(DevInfo->deviceType == HvCallPci_NodeDevice) { - iSeries_Scan_EADs_Bridge(Bus, SubBus, IdSel); - } - else printk("PCI: Invalid System Configuration(0x%02X.\n",DevInfo->deviceType); + if (DevInfo->deviceType == HvCallPci_NodeDevice) + iSeries_Scan_EADs_Bridge(bus, SubBus, IdSel); + else + printk("PCI: Invalid System Configuration(0x%02X)" + " for bus 0x%02x id 0x%02x.\n", + DevInfo->deviceType, bus, IdSel); } - else pci_Log_Error("getDeviceInfo",Bus, SubBus, IdSel,HvRc); + else + pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc); } kfree(DevInfo); } -/******************************************************************************** -* -*********************************************************************************/ -void iSeries_Scan_EADs_Bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel) -{ - struct HvCallPci_BridgeInfo* BridgeInfo; - HvAgentId AgentId; - int Function; - int HvRc; - - BridgeInfo = (struct HvCallPci_BridgeInfo*)kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); - if(BridgeInfo == NULL) return; - - /********************************************************************* - * Note: hvSubBus and irq is always be 0 at this level! - *********************************************************************/ - for (Function=0; Function < 8; ++Function) { +static void iSeries_Scan_EADs_Bridge(HvBusNumber bus, HvSubBusNumber SubBus, + int IdSel) +{ + struct HvCallPci_BridgeInfo *BridgeInfo; + HvAgentId AgentId; + int Function; + int HvRc; + + BridgeInfo = (struct HvCallPci_BridgeInfo *) + kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL); + if (BridgeInfo == NULL) + return; + + /* Note: hvSubBus and irq is always be 0 at this level! */ + for (Function = 0; Function < 8; ++Function) { AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, 0); + HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0); if (HvRc == 0) { + printk("found device at bus %d idsel %d func %d (AgentId %x)\n", + bus, IdSel, Function, AgentId); /* Connect EADs: 0x18.00.12 = 0x00 */ - PPCDBG(PPCDBG_BUSWALK,"PCI:Connect EADs: 0x%02X.%02X.%02X\n",Bus, SubBus, AgentId); - PCIFR( "Connect EADs: 0x%02X.%02X.%02X", Bus, SubBus, AgentId); - HvRc = HvCallPci_getBusUnitInfo(Bus, SubBus, AgentId, - REALADDR(BridgeInfo), sizeof(struct HvCallPci_BridgeInfo)); + PPCDBG(PPCDBG_BUSWALK, + "PCI:Connect EADs: 0x%02X.%02X.%02X\n", + bus, SubBus, AgentId); + HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId, + REALADDR(BridgeInfo), + sizeof(struct HvCallPci_BridgeInfo)); if (HvRc == 0) { - PPCDBG(PPCDBG_BUSWALK,"PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); - PCIFR( "BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X", - BridgeInfo->busUnitInfo.deviceType, - BridgeInfo->subBusNumber, - BridgeInfo->maxAgents, - BridgeInfo->maxSubBusNumber, - BridgeInfo->logicalSlotNumber); + printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n", + BridgeInfo->busUnitInfo.deviceType, + BridgeInfo->subBusNumber, + BridgeInfo->maxAgents, + BridgeInfo->maxSubBusNumber, + BridgeInfo->logicalSlotNumber); + PPCDBG(PPCDBG_BUSWALK, + "PCI: BridgeInfo, Type:0x%02X, SubBus:0x%02X, MaxAgents:0x%02X, MaxSubBus: 0x%02X, LSlot: 0x%02X\n", + BridgeInfo->busUnitInfo.deviceType, + BridgeInfo->subBusNumber, + BridgeInfo->maxAgents, + BridgeInfo->maxSubBusNumber, + BridgeInfo->logicalSlotNumber); - if (BridgeInfo->busUnitInfo.deviceType == HvCallPci_BridgeDevice) { + if (BridgeInfo->busUnitInfo.deviceType == + HvCallPci_BridgeDevice) { /* Scan_Bridge_Slot...: 0x18.00.12 */ - iSeries_Scan_Bridge_Slot(Bus,BridgeInfo); - } - else printk("PCI: Invalid Bridge Configuration(0x%02X)",BridgeInfo->busUnitInfo.deviceType); + iSeries_Scan_Bridge_Slot(bus, BridgeInfo); + } else + printk("PCI: Invalid Bridge Configuration(0x%02X)", + BridgeInfo->busUnitInfo.deviceType); } - } - else if(HvRc != 0x000B) pci_Log_Error("EADs Connect",Bus,SubBus,AgentId,HvRc); + } else if (HvRc != 0x000B) + pci_Log_Error("EADs Connect", + bus, SubBus, AgentId, HvRc); } kfree(BridgeInfo); } -/******************************************************************************** -* -* This assumes that the node slot is always on the primary bus! -* -*********************************************************************************/ -int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo* BridgeInfo) +/* + * This assumes that the node slot is always on the primary bus! + */ +static int iSeries_Scan_Bridge_Slot(HvBusNumber Bus, + struct HvCallPci_BridgeInfo *BridgeInfo) { - struct iSeries_Device_Node* DeviceNode; + struct iSeries_Device_Node *node; HvSubBusNumber SubBus = BridgeInfo->subBusNumber; - u16 VendorId = 0; - int HvRc = 0; - u8 Irq = 0; - int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); - int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); - HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); - int FirstSlotId = 0; - - /**********************************************************/ - /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ - /**********************************************************/ - Irq = iSeries_allocate_IRQ(Bus, 0, AgentId); - iSeries_assign_IRQ(Irq, Bus, 0, AgentId); - PPCDBG(PPCDBG_BUSWALK,"PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n",Bus, 0, AgentId, Irq ); + u16 VendorId = 0; + int HvRc = 0; + u8 Irq = 0; + int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus); + int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus); + HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function); + + /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ + Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); + iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel); + PPCDBG(PPCDBG_BUSWALK, + "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", + Bus, 0, EADsIdSel, Irq); - /**************************************************************************** + /* * Connect all functions of any device found. - ****************************************************************************/ + */ for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) { for (Function = 0; Function < 8; ++Function) { - AgentId = ISERIES_PCI_AGENTID(IdSel, Function); - HvRc = HvCallXm_connectBusUnit(Bus, SubBus, AgentId, Irq); - if( HvRc == 0) { - HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, PCI_VENDOR_ID, &VendorId); - if( HvRc == 0) { - /**********************************************************/ - /* FoundDevice: 0x18.28.10 = 0x12AE */ - /**********************************************************/ - PPCDBG(PPCDBG_BUSWALK,"PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", - Bus, SubBus, AgentId, VendorId); - - HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, PCI_INTERRUPT_LINE, Irq); - if( HvRc != 0) { - pci_Log_Error("PciCfgStore Irq Failed!",Bus,SubBus,AgentId,HvRc); - } - - ++DeviceCount; - DeviceNode = build_device_node(Bus, SubBus, EADsIdSel, Function); - DeviceNode->Vendor = VendorId; - DeviceNode->Irq = Irq; - DeviceNode->LogicalSlot = BridgeInfo->logicalSlotNumber; - PCIFR("Device(%4d): 0x%02X.%02X.%02X 0x%02X 0x%04X", - DeviceCount,Bus, SubBus, AgentId, - DeviceNode->LogicalSlot,DeviceNode->Vendor); - - /*********************************************************** - * On the first device/function, assign irq to slot - ***********************************************************/ - if(Function == 0) { - FirstSlotId = AgentId; - // AHT iSeries_assign_IRQ(Irq, Bus, SubBus, AgentId); - } - } - else pci_Log_Error("Read Vendor",Bus,SubBus,AgentId,HvRc); + HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function); + HvRc = HvCallXm_connectBusUnit(Bus, SubBus, + AgentId, Irq); + if (HvRc != 0) { + pci_Log_Error("Connect Bus Unit", + Bus, SubBus, AgentId, HvRc); + continue; + } + printk("connected bus unit at bus %d subbus 0x%x agentid 0x%x (idsel=%d func=%d)\n", + Bus, SubBus, AgentId, IdSel, Function); + + HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId, + PCI_VENDOR_ID, &VendorId); + if (HvRc != 0) { + pci_Log_Error("Read Vendor", + Bus, SubBus, AgentId, HvRc); + continue; } - else pci_Log_Error("Connect Bus Unit",Bus,SubBus, AgentId,HvRc); + printk("read vendor ID: %x\n", VendorId); + + /* FoundDevice: 0x18.28.10 = 0x12AE */ + PPCDBG(PPCDBG_BUSWALK, + "PCI:- FoundDevice: 0x%02X.%02X.%02X = 0x%04X\n", + Bus, SubBus, AgentId, VendorId); + HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId, + PCI_INTERRUPT_LINE, Irq); + if (HvRc != 0) + pci_Log_Error("PciCfgStore Irq Failed!", + Bus, SubBus, AgentId, HvRc); + + ++DeviceCount; + node = build_device_node(Bus, SubBus, EADsIdSel, Function); + node->Vendor = VendorId; + node->Irq = Irq; + node->LogicalSlot = BridgeInfo->logicalSlotNumber; + } /* for (Function = 0; Function < 8; ++Function) */ } /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */ return HvRc; } -/************************************************************************/ -/* I/0 Memory copy MUST use mmio commands on iSeries */ -/* To do; For performance, include the hv call directly */ -/************************************************************************/ -void* iSeries_memset_io(void* dest, char c, size_t Count) -{ - u8 ByteValue = c; - long NumberOfBytes = Count; - char* IoBuffer = dest; - while(NumberOfBytes > 0) { - iSeries_Write_Byte( ByteValue, (void*)IoBuffer ); + +/* + * I/0 Memory copy MUST use mmio commands on iSeries + * To do; For performance, include the hv call directly + */ +void *iSeries_memset_io(void *dest, char c, size_t Count) +{ + u8 ByteValue = c; + long NumberOfBytes = Count; + char *IoBuffer = dest; + + while (NumberOfBytes > 0) { + iSeries_Write_Byte(ByteValue, (void *)IoBuffer); ++IoBuffer; -- NumberOfBytes; } return dest; -} -void* iSeries_memcpy_toio(void *dest, void *source, size_t count) +} + +void *iSeries_memcpy_toio(void *dest, void *source, size_t count) { - char *dst = dest; - char *src = source; - long NumberOfBytes = count; - while(NumberOfBytes > 0) { - iSeries_Write_Byte(*src++, (void*)dst++); + char *dst = dest; + char *src = source; + long NumberOfBytes = count; + + while (NumberOfBytes > 0) { + iSeries_Write_Byte(*src++, (void *)dst++); -- NumberOfBytes; } return dest; } -void* iSeries_memcpy_fromio(void *dest, void *source, size_t count) + +void *iSeries_memcpy_fromio(void *dest, void *source, size_t count) { char *dst = dest; char *src = source; - long NumberOfBytes = count; - while(NumberOfBytes > 0) { - *dst++ = iSeries_Read_Byte( (void*)src++); + long NumberOfBytes = count; + + while (NumberOfBytes > 0) { + *dst++ = iSeries_Read_Byte((void *)src++); -- NumberOfBytes; } return dest; } -/********************************************************************************** + +/* * Look down the chain to find the matching Device Device - **********************************************************************************/ -struct iSeries_Device_Node* find_Device_Node(struct pci_dev* PciDev) + */ +static struct iSeries_Device_Node *find_Device_Node(int bus, int devfn) { - struct list_head* Device_Node_Ptr = iSeries_Global_Device_List.next; - int Bus = PciDev->bus->number; - int DevFn = PciDev->devfn; - - while(Device_Node_Ptr != &iSeries_Global_Device_List) { - struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)Device_Node_Ptr; - if(Bus == ISERIES_BUS(DevNode) && DevFn == DevNode->DevFn) { - return DevNode; - } - Device_Node_Ptr = Device_Node_Ptr->next; + struct list_head *pos; + + list_for_each(pos, &iSeries_Global_Device_List) { + struct iSeries_Device_Node *node = + list_entry(pos, struct iSeries_Device_Node, Device_List); + + if ((bus == ISERIES_BUS(node)) && (devfn == node->DevFn)) + return node; } return NULL; } -/******************************************************************/ -/* Returns the device node for the passed pci_dev */ -/* Sanity Check Node PciDev to passed pci_dev */ -/* If none is found, returns a NULL which the client must handle. */ -/******************************************************************/ -struct iSeries_Device_Node* get_Device_Node(struct pci_dev* PciDev) -{ - struct iSeries_Device_Node* Node; - Node = (struct iSeries_Device_Node*)PciDev->sysdata; - if(Node == NULL ) { - Node = find_Device_Node(PciDev); - } - else if(Node->PciDev != PciDev) { - Node = find_Device_Node(PciDev); + +#if 0 +/* + * Returns the device node for the passed pci_dev + * Sanity Check Node PciDev to passed pci_dev + * If none is found, returns a NULL which the client must handle. + */ +static struct iSeries_Device_Node *get_Device_Node(struct pci_dev *pdev) +{ + struct iSeries_Device_Node *node; + + node = pdev->sysdata; + if (node == NULL || node->PciDev != pdev) + node = find_Device_Node(pdev->bus->number, pdev->devfn); + return node; +} +#endif + +/* + * Config space read and write functions. + * For now at least, we look for the device node for the bus and devfn + * that we are asked to access. It may be possible to translate the devfn + * to a subbus and deviceid more directly. + */ +static u64 hv_cfg_read_func[4] = { + HvCallPciConfigLoad8, HvCallPciConfigLoad16, + HvCallPciConfigLoad32, HvCallPciConfigLoad32 +}; + +static u64 hv_cfg_write_func[4] = { + HvCallPciConfigStore8, HvCallPciConfigStore16, + HvCallPciConfigStore32, HvCallPciConfigStore32 +}; + +/* + * Read PCI config space + */ +static int iSeries_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 *val) +{ + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + struct HvCallPci_LoadReturn ret; + + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + fn = hv_cfg_read_func[(size - 1) & 3]; + HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0); + + if (ret.rc != 0) { + *val = ~0; + return PCIBIOS_DEVICE_NOT_FOUND; /* or something */ } - return Node; + + *val = ret.value; + return 0; } -/********************************************************************************** - * - * Read PCI Config Space Code - * - **********************************************************************************/ -/** BYTE *************************************************************************/ -int iSeries_Node_read_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8* ReadValue) -{ - u8 ReadData; - if(DevNode == NULL) { return 0x301; } - ++Pci_Cfg_Read_Count; - DevNode->ReturnCode = HvCallPci_configLoad8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,&ReadData); - if(Pci_Trace_Flag == 1) { - PCIFR("RCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: RCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "RCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - *ReadValue = ReadData; - return DevNode->ReturnCode; -} -/** WORD *************************************************************************/ -int iSeries_Node_read_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16* ReadValue) -{ - u16 ReadData; - if(DevNode == NULL) { return 0x301; } - ++Pci_Cfg_Read_Count; - DevNode->ReturnCode = HvCallPci_configLoad16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,&ReadData); - if(Pci_Trace_Flag == 1) { - PCIFR("RCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: RCW: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "RCW: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - - } - *ReadValue = ReadData; - return DevNode->ReturnCode; -} -/** DWORD *************************************************************************/ -int iSeries_Node_read_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32* ReadValue) -{ - u32 ReadData; - if(DevNode == NULL) { return 0x301; } - ++Pci_Cfg_Read_Count; - DevNode->ReturnCode = HvCallPci_configLoad32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,&ReadData); - if(Pci_Trace_Flag == 1) { - PCIFR("RCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,ReadData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: RCL: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "RCL: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - *ReadValue = ReadData; - return DevNode->ReturnCode; -} -int iSeries_pci_read_config_byte(struct pci_dev* PciDev, int Offset, u8* ReadValue) { - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_read_config_byte( DevNode ,Offset,ReadValue); -} -int iSeries_pci_read_config_word(struct pci_dev* PciDev, int Offset, u16* ReadValue) { - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_read_config_word( DevNode ,Offset,ReadValue ); -} -int iSeries_pci_read_config_dword(struct pci_dev* PciDev, int Offset, u32* ReadValue) { - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_read_config_dword(DevNode ,Offset,ReadValue ); -} -/**********************************************************************************/ -/* */ -/* Write PCI Config Space */ -/* */ -/** BYTE *************************************************************************/ -int iSeries_Node_write_config_byte(struct iSeries_Device_Node* DevNode, int Offset, u8 WriteData) -{ - ++Pci_Cfg_Write_Count; - DevNode->ReturnCode = HvCallPci_configStore8(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,WriteData); - if(Pci_Trace_Flag == 1) { - PCIFR("WCB: 0x%04X.%02X 0x%04X = 0x%02X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: WCB: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "WCB: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - return DevNode->ReturnCode; -} -/** WORD *************************************************************************/ -int iSeries_Node_write_config_word(struct iSeries_Device_Node* DevNode, int Offset, u16 WriteData) -{ - ++Pci_Cfg_Write_Count; - DevNode->ReturnCode = HvCallPci_configStore16(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,WriteData); - if(Pci_Trace_Flag == 1) { - PCIFR("WCW: 0x%04X.%02X 0x%04X = 0x%04X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: WCW: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "WCW: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - return DevNode->ReturnCode; -} -/** DWORD *************************************************************************/ -int iSeries_Node_write_config_dword(struct iSeries_Device_Node* DevNode, int Offset, u32 WriteData) -{ - ++Pci_Cfg_Write_Count; - DevNode->ReturnCode = HvCallPci_configStore32(ISERIES_BUS(DevNode),ISERIES_SUBBUS(DevNode),0x10, - Offset,WriteData); - if(Pci_Trace_Flag == 1) { - PCIFR("WCL: 0x%04X.%02X 0x%04X = 0x%08X",ISERIES_BUS(DevNode),DevNode->DevFn,Offset,WriteData); - } - if(DevNode->ReturnCode != 0 ) { - printk("PCI: WCL: 0x%04X.%02X Error: 0x%04X\n",ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - PCIFR( "WCL: 0x%04X.%02X Error: 0x%04X", ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->ReturnCode); - } - return DevNode->ReturnCode; -} -int iSeries_pci_write_config_byte( struct pci_dev* PciDev,int Offset, u8 WriteValue) -{ - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_write_config_byte( DevNode,Offset,WriteValue); -} -int iSeries_pci_write_config_word( struct pci_dev* PciDev,int Offset,u16 WriteValue) -{ - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_write_config_word( DevNode,Offset,WriteValue); -} -int iSeries_pci_write_config_dword(struct pci_dev* PciDev,int Offset,u32 WriteValue) -{ - struct iSeries_Device_Node* DevNode = get_Device_Node(PciDev); - if(DevNode == NULL) return 0x0301; - return iSeries_Node_write_config_dword(DevNode,Offset,WriteValue); -} - -/************************************************************************/ -/* Branch Table */ -/************************************************************************/ -struct pci_ops iSeries_pci_ops = { - iSeries_pci_read_config_byte, - iSeries_pci_read_config_word, - iSeries_pci_read_config_dword, - iSeries_pci_write_config_byte, - iSeries_pci_write_config_word, - iSeries_pci_write_config_dword + +/* + * Write PCI config space + */ + +static int iSeries_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 val) +{ + struct iSeries_Device_Node *node = find_Device_Node(bus->number, devfn); + u64 fn; + u64 ret; + + if (node == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + fn = hv_cfg_write_func[(size - 1) & 3]; + ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0); + + if (ret != 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + return 0; +} + +static struct pci_ops iSeries_pci_ops = { + .read = iSeries_pci_read_config, + .write = iSeries_pci_write_config }; -/************************************************************************ +/* * Check Return Code * -> On Failure, print and log information. * Increment Retry Count, if exceeds max, panic partition. * -> If in retry, print and log success - ************************************************************************ + * * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234 * PCI: Device 23.90 ReadL Retry( 1) * PCI: Device 23.90 ReadL Retry Successful(1) - ************************************************************************/ -int CheckReturnCode(char* TextHdr, struct iSeries_Device_Node* DevNode, u64 RtnCode) + */ +static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode, + u64 ret) { - if(RtnCode != 0) { + if (ret != 0) { ++Pci_Error_Count; ++DevNode->IoRetry; - PCIFR( "%s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X", - TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry,(int)RtnCode); printk("PCI: %s: Device 0x%04X:%02X I/O Error(%2d): 0x%04X\n", - TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry,(int)RtnCode); - /*******************************************************/ - /* Bump the retry and check for retry count exceeded. */ - /* If, Exceeded, panic the system. */ - /*******************************************************/ - if(DevNode->IoRetry > Pci_Retry_Max && Pci_Error_Flag > 0 ) { + TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, + DevNode->IoRetry, (int)ret); + /* + * Bump the retry and check for retry count exceeded. + * If, Exceeded, panic the system. + */ + if ((DevNode->IoRetry > Pci_Retry_Max) && + (Pci_Error_Flag > 0)) { mf_displaySrc(0xB6000103); panic_timeout = 0; - panic("PCI: Hardware I/O Error, SRC B6000103, Automatic Reboot Disabled.\n"); + panic("PCI: Hardware I/O Error, SRC B6000103, " + "Automatic Reboot Disabled.\n"); } return -1; /* Retry Try */ } - /******************************************************************** - * If retry was in progress, log success and rest retry count * - *********************************************************************/ - else if(DevNode->IoRetry > 0) { + /* If retry was in progress, log success and rest retry count */ + if (DevNode->IoRetry > 0) { PCIFR("%s: Device 0x%04X:%02X Retry Successful(%2d).", - TextHdr,ISERIES_BUS(DevNode),DevNode->DevFn,DevNode->IoRetry); + TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn, + DevNode->IoRetry); DevNode->IoRetry = 0; - return 0; } return 0; } -/************************************************************************/ -/* Translate the I/O Address into a device node, bar, and bar offset. */ -/* Note: Make sure the passed variable end up on the stack to avoid */ -/* the exposure of being device global. */ -/************************************************************************/ -static inline struct iSeries_Device_Node* xlateIoMmAddress(void* IoAddress, - union HvDsaMap* DsaPtr, - u64* BarOffsetPtr) { - - unsigned long BaseIoAddr = (unsigned long)IoAddress-iSeries_Base_Io_Memory; - long TableIndex = BaseIoAddr/iSeries_IoMmTable_Entry_Size; - struct iSeries_Device_Node* DevNode = *(iSeries_IoMmTable +TableIndex); - if(DevNode != NULL) { - DsaPtr->DsaAddr = ISERIES_DSA(DevNode); - DsaPtr->Dsa.barNumber = *(iSeries_IoBarTable+TableIndex); - *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; - } - else { + +/* + * Translate the I/O Address into a device node, bar, and bar offset. + * Note: Make sure the passed variable end up on the stack to avoid + * the exposure of being device global. + */ +static inline struct iSeries_Device_Node *xlateIoMmAddress(void *IoAddress, + u64 *dsaptr, u64 *BarOffsetPtr) +{ + unsigned long BaseIoAddr; + unsigned long TableIndex; + struct iSeries_Device_Node *DevNode; + + if (((unsigned long)IoAddress < iSeries_Base_Io_Memory) || + ((unsigned long)IoAddress >= iSeries_Max_Io_Memory)) + return NULL; + BaseIoAddr = (unsigned long)IoAddress - iSeries_Base_Io_Memory; + TableIndex = BaseIoAddr / iSeries_IoMmTable_Entry_Size; + DevNode = iSeries_IoMmTable[TableIndex]; + + if (DevNode != NULL) { + int barnum = iSeries_IoBarTable[TableIndex]; + *dsaptr = DevNode->DsaAddr.DsaAddr | (barnum << 24); + *BarOffsetPtr = BaseIoAddr % iSeries_IoMmTable_Entry_Size; + } else panic("PCI: Invalid PCI IoAddress detected!\n"); - } return DevNode; } -/************************************************************************/ -/* Read MM I/O Instructions for the iSeries */ -/* On MM I/O error, all ones are returned and iSeries_pci_IoError is cal*/ -/* else, data is returned in big Endian format. */ -/************************************************************************/ -/* iSeries_Read_Byte = Read Byte ( 8 bit) */ -/* iSeries_Read_Word = Read Word (16 bit) */ -/* iSeries_Read_Long = Read Long (32 bit) */ -/************************************************************************/ -u8 iSeries_Read_Byte(void* IoAddress) -{ - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); - +/* + * Read MM I/O Instructions for the iSeries + * On MM I/O error, all ones are returned and iSeries_pci_IoError is cal + * else, data is returned in big Endian format. + * + * iSeries_Read_Byte = Read Byte ( 8 bit) + * iSeries_Read_Word = Read Word (16 bit) + * iSeries_Read_Long = Read Long (32 bit) + */ +u8 iSeries_Read_Byte(void *IoAddress) +{ + u64 BarOffset; + u64 dsa; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Byte: invalid access at IO address %p\n", IoAddress); + return 0xff; + } do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad8, &Return, DsaData.DsaAddr,BarOffset, 0); - } while (CheckReturnCode("RDB",DevNode, Return.rc) != 0); + HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0); + } while (CheckReturnCode("RDB", DevNode, ret.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("RDB: IoAddress 0x%p = 0x%02X",IoAddress, (u8)Return.value); - return (u8)Return.value; + return (u8)ret.value; } -u16 iSeries_Read_Word(void* IoAddress) + +u16 iSeries_Read_Word(void *IoAddress) { - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); + u64 BarOffset; + u64 dsa; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Word: invalid access at IO address %p\n", IoAddress); + return 0xffff; + } do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad16,&Return, DsaData.DsaAddr,BarOffset, 0); - } while (CheckReturnCode("RDW",DevNode, Return.rc) != 0); + HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa, + BarOffset, 0); + } while (CheckReturnCode("RDW", DevNode, ret.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("RDW: IoAddress 0x%p = 0x%04X",IoAddress, swab16((u16)Return.value)); - return swab16((u16)Return.value); + return swab16((u16)ret.value); } -u32 iSeries_Read_Long(void* IoAddress) + +u32 iSeries_Read_Long(void *IoAddress) { - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); + u64 BarOffset; + u64 dsa; + struct HvCallPci_LoadReturn ret; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Read_Long: invalid access at IO address %p\n", IoAddress); + return 0xffffffff; + } do { ++Pci_Io_Read_Count; - HvCall3Ret16(HvCallPciBarLoad32,&Return, DsaData.DsaAddr,BarOffset, 0); - } while (CheckReturnCode("RDL",DevNode, Return.rc) != 0); + HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa, + BarOffset, 0); + } while (CheckReturnCode("RDL", DevNode, ret.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("RDL: IoAddress 0x%p = 0x%04X",IoAddress, swab32((u32)Return.value)); - return swab32((u32)Return.value); + return swab32((u32)ret.value); } -/************************************************************************/ -/* Write MM I/O Instructions for the iSeries */ -/************************************************************************/ -/* iSeries_Write_Byte = Write Byte (8 bit) */ -/* iSeries_Write_Word = Write Word(16 bit) */ -/* iSeries_Write_Long = Write Long(32 bit) */ -/************************************************************************/ -void iSeries_Write_Byte(u8 Data, void* IoAddress) -{ - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); +/* + * Write MM I/O Instructions for the iSeries + * + * iSeries_Write_Byte = Write Byte (8 bit) + * iSeries_Write_Word = Write Word(16 bit) + * iSeries_Write_Long = Write Long(32 bit) + */ +void iSeries_Write_Byte(u8 data, void *IoAddress) +{ + u64 BarOffset; + u64 dsa; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Byte: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore8, DsaData.DsaAddr,BarOffset, Data, 0); - } while (CheckReturnCode("WWB",DevNode, Return.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("WWB: IoAddress 0x%p = 0x%02X",IoAddress,Data); -} -void iSeries_Write_Word(u16 Data, void* IoAddress) -{ - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); + rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0); + } while (CheckReturnCode("WWB", DevNode, rc) != 0); +} + +void iSeries_Write_Word(u16 data, void *IoAddress) +{ + u64 BarOffset; + u64 dsa; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Word: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore16,DsaData.DsaAddr,BarOffset, swab16(Data), 0); - } while (CheckReturnCode("WWW",DevNode, Return.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("WWW: IoAddress 0x%p = 0x%04X",IoAddress,Data); -} -void iSeries_Write_Long(u32 Data, void* IoAddress) -{ - u64 BarOffset; - union HvDsaMap DsaData; - struct HvCallPci_LoadReturn Return; - struct iSeries_Device_Node* DevNode = xlateIoMmAddress(IoAddress,&DsaData,&BarOffset); + rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0); + } while (CheckReturnCode("WWW", DevNode, rc) != 0); +} + +void iSeries_Write_Long(u32 data, void *IoAddress) +{ + u64 BarOffset; + u64 dsa; + u64 rc; + struct iSeries_Device_Node *DevNode = + xlateIoMmAddress(IoAddress, &dsa, &BarOffset); + + if (DevNode == NULL) { + static unsigned long last_jiffies; + static int num_printed; + if ((jiffies - last_jiffies) > 60 * HZ) { + last_jiffies = jiffies; + num_printed = 0; + } + if (num_printed++ < 10) + printk(KERN_ERR "iSeries_Write_Long: invalid access at IO address %p\n", IoAddress); + return; + } do { ++Pci_Io_Write_Count; - Return.rc = HvCall4(HvCallPciBarStore32,DsaData.DsaAddr,BarOffset, swab32(Data), 0); - } while (CheckReturnCode("WWL",DevNode, Return.rc) != 0); - if(Pci_Trace_Flag == 1) PCIFR("WWL: IoAddress 0x%p = 0x%08X",IoAddress, Data); + rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0); + } while (CheckReturnCode("WWL", DevNode, rc) != 0); +} + +void pcibios_name_device(struct pci_dev *dev) +{ } diff -puN arch/ppc64/kernel/iSeries_pci_reset.c~linus arch/ppc64/kernel/iSeries_pci_reset.c --- 25/arch/ppc64/kernel/iSeries_pci_reset.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_pci_reset.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,3 +1,4 @@ +#define PCIFR(...) /************************************************************************/ /* File iSeries_pci_reset.c created by Allan Trautman on Mar 21 2001. */ /************************************************************************/ @@ -35,53 +36,67 @@ #include #include #include -#include #include #include #include "pci.h" -/************************************************************************/ -/* Interface to toggle the reset line */ -/* Time is in .1 seconds, need for seconds. */ -/************************************************************************/ -int iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime) +/* + * Interface to toggle the reset line + * Time is in .1 seconds, need for seconds. + */ +int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime, + int DelayTime) { unsigned long AssertDelay, WaitDelay; - struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)PciDev->sysdata; + struct iSeries_Device_Node *DeviceNode = + (struct iSeries_Device_Node *)PciDev->sysdata; + if (DeviceNode == NULL) { - printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",PciDev); + printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n", + PciDev); return -1; } - /******************************************************************** + /* * Set defaults, Assert is .5 second, Wait is 3 seconds. - ********************************************************************/ - if (AssertTime == 0) AssertDelay = ( 5 * HZ)/10; - else AssertDelay = (AssertTime*HZ)/10; - if (WaitDelay == 0) WaitDelay = (30 * HZ)/10; - else WaitDelay = (DelayTime* HZ)/10; + */ + if (AssertTime == 0) + AssertDelay = (5 * HZ) / 10; + else + AssertDelay = (AssertTime * HZ) / 10; + if (WaitDelay == 0) + WaitDelay = (30 * HZ) / 10; + else + WaitDelay = (DelayTime * HZ) / 10; - /******************************************************************** + /* * Assert reset - ********************************************************************/ - DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId,1); + */ + DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode), + 0x00, DeviceNode->AgentId, 1); if (DeviceNode->ReturnCode == 0) { set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(AssertDelay); /* Sleep for the time */ - DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId, 0); + schedule_timeout(AssertDelay); /* Sleep for the time */ + DeviceNode->ReturnCode = + HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode), + 0x00, DeviceNode->AgentId, 0); - /*************************************************************** + /* * Wait for device to reset - ***************************************************************/ + */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(WaitDelay); } - if (DeviceNode->ReturnCode == 0) { - PCIFR("Slot 0x%04X.%02 Reset\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId ); - } + if (DeviceNode->ReturnCode == 0) + PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode), + DeviceNode->AgentId); else { - printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId,DeviceNode->ReturnCode); - PCIFR( "Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId,DeviceNode->ReturnCode); + printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n", + ISERIES_BUS(DeviceNode), DeviceNode->AgentId, + DeviceNode->ReturnCode); + PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n", + ISERIES_BUS(DeviceNode), DeviceNode->AgentId, + DeviceNode->ReturnCode); } return DeviceNode->ReturnCode; } diff -puN arch/ppc64/kernel/iSeries_proc.c~linus arch/ppc64/kernel/iSeries_proc.c --- 25/arch/ppc64/kernel/iSeries_proc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_proc.c 2004-01-19 22:17:21.000000000 -0800 @@ -16,30 +16,22 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -/* Change Activity: */ -/* End Change Activity */ - #include #include -#ifndef _ISERIES_PROC_H +#include #include -#endif - -static struct proc_dir_entry * iSeries_proc_root = NULL; -static int iSeries_proc_initializationDone = 0; +static struct proc_dir_entry *iSeries_proc_root; +static int iSeries_proc_initializationDone; static spinlock_t iSeries_proc_lock; -struct iSeries_proc_registration -{ +struct iSeries_proc_registration { struct iSeries_proc_registration *next; iSeriesProcFunction functionMember; }; - struct iSeries_proc_registration preallocated[16]; + #define MYQUEUETYPE(T) struct MYQueue##T #define MYQUEUE(T) \ MYQUEUETYPE(T) \ @@ -69,74 +61,71 @@ do { \ if ((q)->tail == NULL) \ (q)->head = NULL; \ } while(0) + MYQUEUE(iSeries_proc_registration); typedef MYQUEUETYPE(iSeries_proc_registration) aQueue; - -aQueue iSeries_free; -aQueue iSeries_queued; +static aQueue iSeries_free; +static aQueue iSeries_queued; void iSeries_proc_early_init(void) { int i = 0; unsigned long flags; + iSeries_proc_initializationDone = 0; spin_lock_init(&iSeries_proc_lock); MYQUEUECTOR(&iSeries_free); MYQUEUECTOR(&iSeries_queued); spin_lock_irqsave(&iSeries_proc_lock, flags); - for (i = 0; i < 16; ++i) { - MYQUEUEENQ(&iSeries_free, preallocated+i); - } + for (i = 0; i < 16; ++i) + MYQUEUEENQ(&iSeries_free, preallocated + i); spin_unlock_irqrestore(&iSeries_proc_lock, flags); } -void iSeries_proc_create(void) +static int iSeries_proc_create(void) { unsigned long flags; - struct iSeries_proc_registration *reg = NULL; - spin_lock_irqsave(&iSeries_proc_lock, flags); + struct iSeries_proc_registration *reg; + printk("iSeries_proc: Creating /proc/iSeries\n"); + spin_lock_irqsave(&iSeries_proc_lock, flags); iSeries_proc_root = proc_mkdir("iSeries", 0); - if (!iSeries_proc_root) return; + if (!iSeries_proc_root) + goto out; MYQUEUEDEQ(&iSeries_queued, reg); - while (reg != NULL) { (*(reg->functionMember))(iSeries_proc_root); - MYQUEUEDEQ(&iSeries_queued, reg); } iSeries_proc_initializationDone = 1; +out: spin_unlock_irqrestore(&iSeries_proc_lock, flags); + return 0; } +arch_initcall(iSeries_proc_create); + void iSeries_proc_callback(iSeriesProcFunction initFunction) { unsigned long flags; - spin_lock_irqsave(&iSeries_proc_lock, flags); - if (iSeries_proc_initializationDone) { + spin_lock_irqsave(&iSeries_proc_lock, flags); + if (iSeries_proc_initializationDone) (*initFunction)(iSeries_proc_root); - } else { + else { struct iSeries_proc_registration *reg = NULL; MYQUEUEDEQ(&iSeries_free, reg); - if (reg != NULL) { - /* printk("Registering %p in reg %p\n", initFunction, reg); */ reg->functionMember = initFunction; - MYQUEUEENQ(&iSeries_queued, reg); - } else { + } else printk("Couldn't get a queue entry\n"); - } } - spin_unlock_irqrestore(&iSeries_proc_lock, flags); } - - diff -puN arch/ppc64/kernel/iSeries_setup.c~linus arch/ppc64/kernel/iSeries_setup.c --- 25/arch/ppc64/kernel/iSeries_setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/iSeries_setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -53,34 +55,35 @@ #include /* Function Prototypes */ - extern void abort(void); -#ifdef CONFIG_PPC_ISERIES -static void build_iSeries_Memory_Map( void ); -static void setup_iSeries_cache_sizes( void ); -static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); -#endif -void build_valid_hpte( unsigned long vsid, unsigned long ea, unsigned long pa, - pte_t * ptep, unsigned hpteflags, unsigned bolted ); extern void ppcdbg_initialize(void); extern void iSeries_pcibios_init(void); +extern void tce_init_iSeries(void); + +static void build_iSeries_Memory_Map(void); +static void setup_iSeries_cache_sizes(void); +static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); +void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, + pte_t *ptep, unsigned hpteflags, unsigned bolted); static void iSeries_setup_dprofile(void); +void iSeries_setup_arch(void); /* Global Variables */ +static unsigned long procFreqHz; +static unsigned long procFreqMhz; +static unsigned long procFreqMhzHundreths; + +static unsigned long tbFreqHz; +static unsigned long tbFreqMhz; +static unsigned long tbFreqMhzHundreths; -static unsigned long procFreqHz = 0; -static unsigned long procFreqMhz = 0; -static unsigned long procFreqMhzHundreths = 0; - -static unsigned long tbFreqHz = 0; -static unsigned long tbFreqMhz = 0; -static unsigned long tbFreqMhzHundreths = 0; - -unsigned long dprof_shift = 0; -unsigned long dprof_len = 0; -unsigned int * dprof_buffer = NULL; +unsigned long dprof_shift; +unsigned long dprof_len; +unsigned int *dprof_buffer; -int piranha_simulator = 0; +int piranha_simulator; + +int boot_cpuid; extern char _end[]; @@ -92,7 +95,7 @@ extern unsigned long embedded_sysmap_end extern unsigned long iSeries_recal_tb; extern unsigned long iSeries_recal_titan; -static int mf_initialized = 0; +static int mf_initialized; struct MemoryBlock { unsigned long absStart; @@ -106,30 +109,30 @@ struct MemoryBlock { * and return the number of physical blocks and fill in the array of * block data. */ - -unsigned long iSeries_process_Condor_mainstore_vpd( struct MemoryBlock *mb_array, unsigned long max_entries ) +unsigned long iSeries_process_Condor_mainstore_vpd(struct MemoryBlock *mb_array, + unsigned long max_entries) { - /* Determine if absolute memory has any - * holes so that we can interpret the - * access map we get back from the hypervisor - * correctly. - */ - unsigned long holeFirstChunk, holeSizeChunks; unsigned long numMemoryBlocks = 1; - struct IoHriMainStoreSegment4 * msVpd = (struct IoHriMainStoreSegment4 *)xMsVpd; + struct IoHriMainStoreSegment4 *msVpd = + (struct IoHriMainStoreSegment4 *)xMsVpd; unsigned long holeStart = msVpd->nonInterleavedBlocksStartAdr; - unsigned long holeEnd = msVpd->nonInterleavedBlocksEndAdr; + unsigned long holeEnd = msVpd->nonInterleavedBlocksEndAdr; unsigned long holeSize = holeEnd - holeStart; printk("Mainstore_VPD: Condor\n"); - + /* + * Determine if absolute memory has any + * holes so that we can interpret the + * access map we get back from the hypervisor + * correctly. + */ mb_array[0].logicalStart = 0; - mb_array[0].logicalEnd = 0x100000000; - mb_array[0].absStart = 0; - mb_array[0].absEnd = 0x100000000; + mb_array[0].logicalEnd = 0x100000000; + mb_array[0].absStart = 0; + mb_array[0].absEnd = 0x100000000; - if ( holeSize ) { + if (holeSize) { numMemoryBlocks = 2; holeStart = holeStart & 0x000fffffffffffff; holeStart = addr_to_chunk(holeStart); @@ -138,275 +141,264 @@ unsigned long iSeries_process_Condor_mai holeSizeChunks = holeSize; printk( "Main store hole: start chunk = %0lx, size = %0lx chunks\n", holeFirstChunk, holeSizeChunks ); - mb_array[0].logicalEnd = holeFirstChunk; - mb_array[0].absEnd = holeFirstChunk; + mb_array[0].logicalEnd = holeFirstChunk; + mb_array[0].absEnd = holeFirstChunk; mb_array[1].logicalStart = holeFirstChunk; - mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks; - mb_array[1].absStart = holeFirstChunk + holeSizeChunks; - mb_array[1].absEnd = 0x100000000; + mb_array[1].logicalEnd = 0x100000000 - holeSizeChunks; + mb_array[1].absStart = holeFirstChunk + holeSizeChunks; + mb_array[1].absEnd = 0x100000000; } - - return numMemoryBlocks; } -#define MaxSegmentAreas 32 -#define MaxSegmentAdrRangeBlocks 128 -#define MaxAreaRangeBlocks 4 -unsigned long iSeries_process_Regatta_mainstore_vpd( struct MemoryBlock *mb_array, unsigned long max_entries ) +#define MaxSegmentAreas 32 +#define MaxSegmentAdrRangeBlocks 128 +#define MaxAreaRangeBlocks 4 + +unsigned long iSeries_process_Regatta_mainstore_vpd( + struct MemoryBlock *mb_array, unsigned long max_entries) { - struct IoHriMainStoreSegment5 * msVpdP = (struct IoHriMainStoreSegment5 *)xMsVpd; + struct IoHriMainStoreSegment5 *msVpdP = + (struct IoHriMainStoreSegment5 *)xMsVpd; unsigned long numSegmentBlocks = 0; u32 existsBits = msVpdP->msAreaExists; unsigned long area_num; printk("Mainstore_VPD: Regatta\n"); - for ( area_num = 0; area_num < MaxSegmentAreas; ++area_num ) { + for (area_num = 0; area_num < MaxSegmentAreas; ++area_num ) { unsigned long numAreaBlocks; - struct IoHriMainStoreArea4 * currentArea; + struct IoHriMainStoreArea4 *currentArea; - if ( existsBits & 0x80000000 ) { + if (existsBits & 0x80000000) { unsigned long block_num; currentArea = &msVpdP->msAreaArray[area_num]; numAreaBlocks = currentArea->numAdrRangeBlocks; - - printk("ms_vpd: processing area %2ld blocks=%ld", area_num, numAreaBlocks); - - for ( block_num = 0; block_num < numAreaBlocks; ++block_num ) { + printk("ms_vpd: processing area %2ld blocks=%ld", + area_num, numAreaBlocks); + for (block_num = 0; block_num < numAreaBlocks; + ++block_num ) { /* Process an address range block */ struct MemoryBlock tempBlock; unsigned long i; - tempBlock.absStart = (unsigned long)currentArea->xAdrRangeBlock[block_num].blockStart; - tempBlock.absEnd = (unsigned long)currentArea->xAdrRangeBlock[block_num].blockEnd; + tempBlock.absStart = + (unsigned long)currentArea->xAdrRangeBlock[block_num].blockStart; + tempBlock.absEnd = + (unsigned long)currentArea->xAdrRangeBlock[block_num].blockEnd; tempBlock.logicalStart = 0; tempBlock.logicalEnd = 0; - - printk("\n block %ld absStart=%016lx absEnd=%016lx", block_num, - tempBlock.absStart, tempBlock.absEnd); - - for ( i=0; i 1 ) { + if (numSegmentBlocks > 1) { unsigned long m, n; - for ( m=0; mcpu_features & CPU_FTR_SLB) - mem_blocks = iSeries_process_Regatta_mainstore_vpd( mb_array, max_entries ); + mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array, + max_entries); else - mem_blocks = iSeries_process_Condor_mainstore_vpd( mb_array, max_entries ); + mem_blocks = iSeries_process_Condor_mainstore_vpd(mb_array, + max_entries); printk("Mainstore_VPD: numMemoryBlocks = %ld \n", mem_blocks); - for ( i=0; ixRamDisk ) { + if (naca->xRamDisk) { initrd_start = (unsigned long)__va(naca->xRamDisk); - initrd_end = initrd_start + naca->xRamDiskSize * PAGE_SIZE; + initrd_end = initrd_start + naca->xRamDiskSize * PAGE_SIZE; initrd_below_start_ok = 1; // ramdisk in kernel space ROOT_DEV = Root_RAM0; - - if ( ((rd_size*1024)/PAGE_SIZE) < naca->xRamDiskSize ) - rd_size = (naca->xRamDiskSize*PAGE_SIZE)/1024; + if (((rd_size * 1024) / PAGE_SIZE) < naca->xRamDiskSize) + rd_size = (naca->xRamDiskSize * PAGE_SIZE) / 1024; } else - #endif /* CONFIG_BLK_DEV_INITRD */ - { - - /* ROOT_DEV = MKDEV( VIODASD_MAJOR, 1 ); */ - } + { + /* ROOT_DEV = MKDEV(VIODASD_MAJOR, 1); */ + } iSeries_recal_tb = get_tb(); iSeries_recal_titan = HvCallXm_loadTod(); - ppc_md.setup_arch = iSeries_setup_arch; - ppc_md.setup_residual = iSeries_setup_residual; - ppc_md.get_cpuinfo = iSeries_get_cpuinfo; - ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.get_irq = iSeries_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = iSeries_restart; - ppc_md.power_off = iSeries_power_off; - ppc_md.halt = iSeries_halt; - - ppc_md.get_boot_time = iSeries_get_boot_time; - ppc_md.set_rtc_time = iSeries_set_rtc_time; - ppc_md.get_rtc_time = iSeries_get_rtc_time; - ppc_md.calibrate_decr = iSeries_calibrate_decr; - ppc_md.progress = iSeries_progress; + ppc_md.setup_arch = iSeries_setup_arch; + ppc_md.setup_residual = iSeries_setup_residual; + ppc_md.get_cpuinfo = iSeries_get_cpuinfo; + ppc_md.init_IRQ = iSeries_init_IRQ; + ppc_md.init_irq_desc = iSeries_init_irq_desc; + ppc_md.get_irq = iSeries_get_irq; + ppc_md.init = NULL; + + ppc_md.restart = iSeries_restart; + ppc_md.power_off = iSeries_power_off; + ppc_md.halt = iSeries_halt; + + ppc_md.get_boot_time = iSeries_get_boot_time; + ppc_md.set_rtc_time = iSeries_set_rtc_time; + ppc_md.get_rtc_time = iSeries_get_rtc_time; + ppc_md.calibrate_decr = iSeries_calibrate_decr; + ppc_md.progress = iSeries_progress; hpte_init_iSeries(); tce_init_iSeries(); - /* Initialize the table which translate Linux physical addresses to + /* + * Initialize the table which translate Linux physical addresses to * AS/400 absolute addresses */ - build_iSeries_Memory_Map(); - setup_iSeries_cache_sizes(); - /* Initialize machine-dependency vectors */ - - #ifdef CONFIG_SMP smp_init_iSeries(); #endif - - if ( itLpNaca.xPirEnvironMode == 0 ) + if (itLpNaca.xPirEnvironMode == 0) piranha_simulator = 1; -#endif } -/* - * void __init iSeries_init() - */ - -void __init -iSeries_init(unsigned long r3, unsigned long r4, unsigned long r5, +void __init iSeries_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { + char *p, *q; + /* Associate Lp Event Queue 0 with processor 0 */ - HvCallEvent_setLpEventQueueInterruptProc( 0, 0 ); + HvCallEvent_setLpEventQueueInterruptProc(0, 0); - { - /* copy the command line parameter from the primary VSP */ - char *p, *q; - HvCallEvent_dmaToSp( cmd_line, - 2*64*1024, - 256, - HvLpDma_Direction_RemoteToLocal ); - - p = q = cmd_line + 255; - while( p > cmd_line ) { - if ((*p == 0) || (*p == ' ') || (*p == '\n')) - --p; - else - break; - } - if ( p < q ) - *(p+1) = 0; + /* copy the command line parameter from the primary VSP */ + HvCallEvent_dmaToSp(cmd_line, 2 * 64* 1024, 256, + HvLpDma_Direction_RemoteToLocal); + + p = q = cmd_line + 255; + while (p > cmd_line) { + if ((*p == 0) || (*p == ' ') || (*p == '\n')) + --p; + else + break; } + if (p < q) + *(p + 1) = 0; if (strstr(cmd_line, "dprofile=")) { - char *p, *q; - for (q = cmd_line; (p = strstr(q, "dprofile=")) != 0; ) { unsigned long size, new_klimit; + q = p + 9; - if (p > cmd_line && p[-1] != ' ') + if ((p > cmd_line) && (p[-1] != ' ')) continue; dprof_shift = simple_strtoul(q, &q, 0); - dprof_len = (unsigned long)_etext - (unsigned long)_stext; + dprof_len = (unsigned long)_etext - + (unsigned long)_stext; dprof_len >>= dprof_shift; - size = ((dprof_len * sizeof(unsigned int)) + (PAGE_SIZE-1)) & PAGE_MASK; - dprof_buffer = (unsigned int *)((klimit + (PAGE_SIZE-1)) & PAGE_MASK); + size = ((dprof_len * sizeof(unsigned int)) + + (PAGE_SIZE-1)) & PAGE_MASK; + dprof_buffer = (unsigned int *)((klimit + + (PAGE_SIZE-1)) & PAGE_MASK); new_klimit = ((unsigned long)dprof_buffer) + size; - lmb_reserve( __pa(klimit), (new_klimit-klimit)); + lmb_reserve(__pa(klimit), (new_klimit-klimit)); klimit = new_klimit; - memset( dprof_buffer, 0, size ); + memset(dprof_buffer, 0, size); } } iSeries_setup_dprofile(); - iSeries_proc_early_init(); + iSeries_proc_early_init(); mf_init(); mf_initialized = 1; mb(); - iSeries_proc_callback( &pmc_proc_init ); + iSeries_proc_callback(&pmc_proc_init); } -#ifdef CONFIG_PPC_ISERIES /* * The iSeries may have very large memories ( > 128 GB ) and a partition * may get memory in "chunks" that may be anywhere in the 2**52 real @@ -444,9 +436,10 @@ static void __init build_iSeries_Memory_ /* Chunk size on iSeries is 256K bytes */ totalChunks = (u32)HvLpConfig_getMsChunks(); - klimit = msChunks_alloc(klimit, totalChunks, 1UL<<18); + klimit = msChunks_alloc(klimit, totalChunks, 1UL << 18); - /* Get absolute address of our load area + /* + * Get absolute address of our load area * and map it to physical address 0 * This guarantees that the loadarea ends up at physical 0 * otherwise, it might not be returned by PLIC as the first @@ -456,63 +449,68 @@ static void __init build_iSeries_Memory_ loadAreaFirstChunk = (u32)addr_to_chunk(itLpNaca.xLoadAreaAddr); loadAreaSize = itLpNaca.xLoadAreaChunks; - /* Only add the pages already mapped here. + /* + * Only add the pages already mapped here. * Otherwise we might add the hpt pages * The rest of the pages of the load area * aren't in the HPT yet and can still * be assigned an arbitrary physical address */ - if ( (loadAreaSize * 64) > HvPagesToMap ) + if ((loadAreaSize * 64) > HvPagesToMap) loadAreaSize = HvPagesToMap / 64; loadAreaLastChunk = loadAreaFirstChunk + loadAreaSize - 1; - /* TODO Do we need to do something if the HPT is in the 64MB load area? + /* + * TODO Do we need to do something if the HPT is in the 64MB load area? * This would be required if the itLpNaca.xLoadAreaChunks includes * the HPT size */ - printk( "Mapping load area - physical addr = 0000000000000000\n" - " absolute addr = %016lx\n", - chunk_to_addr(loadAreaFirstChunk) ); - printk( "Load area size %dK\n", loadAreaSize*256 ); + printk("Mapping load area - physical addr = 0000000000000000\n" + " absolute addr = %016lx\n", + chunk_to_addr(loadAreaFirstChunk)); + printk("Load area size %dK\n", loadAreaSize * 256); + + for (nextPhysChunk = 0; nextPhysChunk < loadAreaSize; ++nextPhysChunk) + msChunks.abs[nextPhysChunk] = + loadAreaFirstChunk + nextPhysChunk; - for ( nextPhysChunk = 0; - nextPhysChunk < loadAreaSize; - ++nextPhysChunk ) { - msChunks.abs[nextPhysChunk] = loadAreaFirstChunk+nextPhysChunk; - } - - /* Get absolute address of our HPT and remember it so + /* + * Get absolute address of our HPT and remember it so * we won't map it to any physical address */ - hptFirstChunk = (u32)addr_to_chunk(HvCallHpt_getHptAddress()); - hptSizePages = (u32)(HvCallHpt_getHptPages()); - hptSizeChunks = hptSizePages >> (msChunks.chunk_shift-PAGE_SHIFT); + hptSizePages = (u32)HvCallHpt_getHptPages(); + hptSizeChunks = hptSizePages >> (msChunks.chunk_shift - PAGE_SHIFT); hptLastChunk = hptFirstChunk + hptSizeChunks - 1; - - printk( "HPT absolute addr = %016lx, size = %dK\n", - chunk_to_addr(hptFirstChunk), hptSizeChunks*256 ); + + printk("HPT absolute addr = %016lx, size = %dK\n", + chunk_to_addr(hptFirstChunk), hptSizeChunks * 256); /* Fill in the htab_data structure */ - /* Fill in size of hashed page table */ - num_ptegs = hptSizePages * (PAGE_SIZE/(sizeof(HPTE)*HPTES_PER_GROUP)); + num_ptegs = hptSizePages * + (PAGE_SIZE / (sizeof(HPTE) * HPTES_PER_GROUP)); htab_data.htab_num_ptegs = num_ptegs; htab_data.htab_hash_mask = num_ptegs - 1; - /* The actual hashed page table is in the hypervisor, we have no direct access */ + /* + * The actual hashed page table is in the hypervisor, + * we have no direct access + */ htab_data.htab = NULL; - /* Determine if absolute memory has any + /* + * Determine if absolute memory has any * holes so that we can interpret the * access map we get back from the hypervisor * correctly. */ - numMemoryBlocks = iSeries_process_mainstore_vpd( mb, 32 ); + numMemoryBlocks = iSeries_process_mainstore_vpd(mb, 32); - /* Process the main store access map from the hypervisor + /* + * Process the main store access map from the hypervisor * to build up our physical -> absolute translation table */ curBlock = 0; @@ -520,30 +518,29 @@ static void __init build_iSeries_Memory_ currDword = 0; moreChunks = totalChunks; - while ( moreChunks ) { - map = HvCallSm_get64BitsOfAccessMap( itLpNaca.xLpIndex, - currDword ); + while (moreChunks) { + map = HvCallSm_get64BitsOfAccessMap(itLpNaca.xLpIndex, + currDword); thisChunk = currChunk; - while ( map ) { + while (map) { chunkBit = map >> 63; map <<= 1; - if ( chunkBit ) { + if (chunkBit) { --moreChunks; - - while ( thisChunk >= mb[curBlock].logicalEnd ) { + while (thisChunk >= mb[curBlock].logicalEnd) { ++curBlock; - if ( curBlock >= numMemoryBlocks ) + if (curBlock >= numMemoryBlocks) panic("out of memory blocks"); } - if ( thisChunk < mb[curBlock].logicalStart ) + if (thisChunk < mb[curBlock].logicalStart) panic("memory block error"); - absChunk = mb[curBlock].absStart + ( thisChunk - mb[curBlock].logicalStart ); - - if ( ( ( absChunk < hptFirstChunk ) || - ( absChunk > hptLastChunk ) ) && - ( ( absChunk < loadAreaFirstChunk ) || - ( absChunk > loadAreaLastChunk ) ) ) { + absChunk = mb[curBlock].absStart + + (thisChunk - mb[curBlock].logicalStart); + if (((absChunk < hptFirstChunk) || + (absChunk > hptLastChunk)) && + ((absChunk < loadAreaFirstChunk) || + (absChunk > loadAreaLastChunk))) { msChunks.abs[nextPhysChunk] = absChunk; ++nextPhysChunk; } @@ -553,8 +550,9 @@ static void __init build_iSeries_Memory_ ++currDword; currChunk += 64; } - - /* main store size (in chunks) is + + /* + * main store size (in chunks) is * totalChunks - hptSizeChunks * which should be equal to * nextPhysChunk @@ -562,12 +560,12 @@ static void __init build_iSeries_Memory_ systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk); /* Bolt kernel mappings for all of memory */ - iSeries_bolt_kernel( 0, systemcfg->physicalMemorySize ); + iSeries_bolt_kernel(0, systemcfg->physicalMemorySize); lmb_init(); - lmb_add( 0, systemcfg->physicalMemorySize ); + lmb_add(0, systemcfg->physicalMemorySize); lmb_analyze(); /* ?? */ - lmb_reserve( 0, __pa(klimit)); + lmb_reserve(0, __pa(klimit)); /* * Hardcode to GP size. I am not sure where to get this info. DRENG @@ -579,59 +577,94 @@ static void __init build_iSeries_Memory_ * Set up the variables that describe the cache line sizes * for this machine. */ - static void __init setup_iSeries_cache_sizes(void) { unsigned int i, n; unsigned int procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; - systemcfg->iCacheL1Size = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024; - systemcfg->iCacheL1LineSize = xIoHriProcessorVpd[procIx].xInstCacheOperandSize; - systemcfg->dCacheL1Size = xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024; - systemcfg->dCacheL1LineSize = xIoHriProcessorVpd[procIx].xDataCacheOperandSize; + systemcfg->iCacheL1Size = + xIoHriProcessorVpd[procIx].xInstCacheSize * 1024; + systemcfg->iCacheL1LineSize = + xIoHriProcessorVpd[procIx].xInstCacheOperandSize; + systemcfg->dCacheL1Size = + xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024; + systemcfg->dCacheL1LineSize = + xIoHriProcessorVpd[procIx].xDataCacheOperandSize; naca->iCacheL1LinesPerPage = PAGE_SIZE / systemcfg->iCacheL1LineSize; naca->dCacheL1LinesPerPage = PAGE_SIZE / systemcfg->dCacheL1LineSize; i = systemcfg->iCacheL1LineSize; n = 0; - while ((i=(i/2))) ++n; + while ((i = (i / 2))) + ++n; naca->iCacheL1LogLineSize = n; i = systemcfg->dCacheL1LineSize; n = 0; - while ((i=(i/2))) ++n; + while ((i = (i / 2))) + ++n; naca->dCacheL1LogLineSize = n; - printk( "D-cache line size = %d\n", (unsigned int)systemcfg->dCacheL1LineSize); - printk( "I-cache line size = %d\n", (unsigned int)systemcfg->iCacheL1LineSize); + printk("D-cache line size = %d\n", + (unsigned int)systemcfg->dCacheL1LineSize); + printk("I-cache line size = %d\n", + (unsigned int)systemcfg->iCacheL1LineSize); } /* - * Bolt the kernel addr space into the HPT + * Create a pte. Used during initialization only. */ +static void iSeries_make_pte(unsigned long va, unsigned long pa, + int mode) +{ + HPTE local_hpte, rhpte; + unsigned long hash, vpn; + long slot; + + vpn = va >> PAGE_SHIFT; + hash = hpt_hash(vpn, 0); + + local_hpte.dw1.dword1 = pa | mode; + local_hpte.dw0.dword0 = 0; + local_hpte.dw0.dw0.avpn = va >> 23; + local_hpte.dw0.dw0.bolted = 1; /* bolted */ + local_hpte.dw0.dw0.v = 1; + + slot = HvCallHpt_findValid(&rhpte, vpn); + if (slot < 0) { + /* Must find space in primary group */ + panic("hash_page: hpte already exists\n"); + } + HvCallHpt_addValidate(slot, 0, (HPTE *)&local_hpte ); +} +/* + * Bolt the kernel addr space into the HPT + */ static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr) { unsigned long pa; unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; HPTE hpte; - for (pa=saddr; pa < eaddr ;pa+=PAGE_SIZE) { + for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) { unsigned long ea = (unsigned long)__va(pa); - unsigned long vsid = get_kernel_vsid( ea ); - unsigned long va = ( vsid << 28 ) | ( pa & 0xfffffff ); + unsigned long vsid = get_kernel_vsid(ea); + unsigned long va = (vsid << 28) | (pa & 0xfffffff); unsigned long vpn = va >> PAGE_SHIFT; - unsigned long slot = HvCallHpt_findValid( &hpte, vpn ); - if ( hpte.dw0.dw0.v ) { + unsigned long slot = HvCallHpt_findValid(&hpte, vpn); + + if (hpte.dw0.dw0.v) { /* HPTE exists, so just bolt it */ - HvCallHpt_setSwBits( slot, 0x10, 0 ); - } else { + HvCallHpt_setSwBits(slot, 0x10, 0); + /* And make sure the pp bits are correct */ + HvCallHpt_setPp(slot, PP_RWXX); + } else /* No HPTE exists, so create a new bolted one */ - build_valid_hpte(vsid, ea, pa, NULL, mode_rw, 1); - } + iSeries_make_pte(va, (unsigned long)__v2a(ea), + mode_rw); } } -#endif /* CONFIG_PPC_ISERIES */ extern unsigned long ppc_proc_freq; extern unsigned long ppc_tb_freq; @@ -639,10 +672,9 @@ extern unsigned long ppc_tb_freq; /* * Document me. */ -void __init -iSeries_setup_arch(void) +void __init iSeries_setup_arch(void) { - void * eventStack; + void *eventStack; unsigned procIx = get_paca()->xLpPaca.xDynHvPhysicalProcIndex; /* Add an eye catcher and the systemcfg layout version number */ @@ -657,50 +689,43 @@ iSeries_setup_arch(void) * we subtract out the KERNELBASE and add in the * absolute real address of the kernel load area */ - - eventStack = alloc_bootmem_pages( LpEventStackSize ); - - memset( eventStack, 0, LpEventStackSize ); + eventStack = alloc_bootmem_pages(LpEventStackSize); + memset(eventStack, 0, LpEventStackSize); /* Invoke the hypervisor to initialize the event stack */ - - HvCallEvent_setLpEventStack( 0, eventStack, LpEventStackSize ); - + HvCallEvent_setLpEventStack(0, eventStack, LpEventStackSize); + /* Initialize fields in our Lp Event Queue */ - xItLpQueue.xSlicEventStackPtr = (char *)eventStack; xItLpQueue.xSlicCurEventPtr = (char *)eventStack; xItLpQueue.xSlicLastValidEventPtr = (char *)eventStack + (LpEventStackSize - LpEventMaxSize); xItLpQueue.xIndex = 0; - + /* Compute processor frequency */ - procFreqHz = (((1UL<<34) * 1000000) / xIoHriProcessorVpd[procIx].xProcFreq ); + procFreqHz = ((1UL << 34) * 1000000) / + xIoHriProcessorVpd[procIx].xProcFreq; procFreqMhz = procFreqHz / 1000000; - procFreqMhzHundreths = (procFreqHz/10000) - (procFreqMhz*100); - + procFreqMhzHundreths = (procFreqHz / 10000) - (procFreqMhz * 100); ppc_proc_freq = procFreqHz; /* Compute time base frequency */ - tbFreqHz = (((1UL<<32) * 1000000) / xIoHriProcessorVpd[procIx].xTimeBaseFreq ); + tbFreqHz = ((1UL << 32) * 1000000) / + xIoHriProcessorVpd[procIx].xTimeBaseFreq; tbFreqMhz = tbFreqHz / 1000000; - tbFreqMhzHundreths = (tbFreqHz/10000) - (tbFreqMhz*100); - + tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100); ppc_tb_freq = tbFreqHz; printk("Max logical processors = %d\n", - itVpdAreas.xSlicMaxLogicalProcs ); + itVpdAreas.xSlicMaxLogicalProcs); printk("Max physical processors = %d\n", - itVpdAreas.xSlicMaxPhysicalProcs ); - printk("Processor frequency = %lu.%02lu\n", - procFreqMhz, - procFreqMhzHundreths ); - printk("Time base frequency = %lu.%02lu\n", - tbFreqMhz, - tbFreqMhzHundreths ); + itVpdAreas.xSlicMaxPhysicalProcs); + printk("Processor frequency = %lu.%02lu\n", procFreqMhz, + procFreqMhzHundreths); + printk("Time base frequency = %lu.%02lu\n", tbFreqMhz, + tbFreqMhzHundreths); systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; printk("Processor version = %x\n", systemcfg->processor); - } /* @@ -715,38 +740,27 @@ iSeries_setup_arch(void) * * Output(s): * *buffer - Buffer with CPU data. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. */ -void iSeries_setup_residual(struct seq_file *m) +void iSeries_setup_residual(struct seq_file *m, int cpu_id) { - - seq_printf(m,"clock\t\t: %lu.%02luMhz\n", - procFreqMhz, procFreqMhzHundreths ); - seq_printf(m,"time base\t: %lu.%02luMHz\n", - tbFreqMhz, tbFreqMhzHundreths ); - seq_printf(m,"i-cache\t\t: %d\n", - systemcfg->iCacheL1LineSize); - seq_printf(m,"d-cache\t\t: %d\n", - systemcfg->dCacheL1LineSize); - + seq_printf(m, "clock\t\t: %lu.%02luMhz\n", procFreqMhz, + procFreqMhzHundreths); + seq_printf(m, "time base\t: %lu.%02luMHz\n", tbFreqMhz, + tbFreqMhzHundreths); + seq_printf(m, "i-cache\t\t: %d\n", systemcfg->iCacheL1LineSize); + seq_printf(m, "d-cache\t\t: %d\n", systemcfg->dCacheL1LineSize); } void iSeries_get_cpuinfo(struct seq_file *m) { - - seq_printf(m,"machine\t\t: 64-bit iSeries Logical Partition\n"); - + seq_printf(m, "machine\t\t: 64-bit iSeries Logical Partition\n"); } /* * Document me. * and Implement me. */ -int -iSeries_get_irq(struct pt_regs *regs) +int iSeries_get_irq(struct pt_regs *regs) { /* -2 means ignore this interrupt */ return -2; @@ -755,8 +769,7 @@ iSeries_get_irq(struct pt_regs *regs) /* * Document me. */ -void -iSeries_restart(char *cmd) +void iSeries_restart(char *cmd) { mf_reboot(); } @@ -764,8 +777,7 @@ iSeries_restart(char *cmd) /* * Document me. */ -void -iSeries_power_off(void) +void iSeries_power_off(void) { mf_powerOff(); } @@ -773,8 +785,7 @@ iSeries_power_off(void) /* * Document me. */ -void -iSeries_halt(void) +void iSeries_halt(void) { mf_powerOff(); } @@ -792,24 +803,19 @@ extern void setup_default_decr(void); * and sets up the kernel timer decrementer based on that value. * */ -void __init -iSeries_calibrate_decr(void) +void __init iSeries_calibrate_decr(void) { unsigned long cyclesPerUsec; - struct div_result divres; - /* Compute decrementer (and TB) frequency - * in cycles/sec - */ + /* Compute decrementer (and TB) frequency in cycles/sec */ + cyclesPerUsec = ppc_tb_freq / 1000000; - cyclesPerUsec = ppc_tb_freq / 1000000; /* cycles / usec */ - - /* Set the amount to refresh the decrementer by. This + /* + * Set the amount to refresh the decrementer by. This * is the number of decrementer ticks it takes for * 1/HZ seconds. */ - tb_ticks_per_jiffy = ppc_tb_freq / HZ; #if 0 @@ -824,47 +830,54 @@ iSeries_calibrate_decr(void) * that jiffies (and xtime) will match the time returned * by do_gettimeofday. */ - tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; + tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; tb_ticks_per_usec = cyclesPerUsec; tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); - div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); + div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres); tb_to_xs = divres.result_low; setup_default_decr(); } -void __init -iSeries_progress( char * st, unsigned short code ) +void __init iSeries_progress(char * st, unsigned short code) { - printk( "Progress: [%04x] - %s\n", (unsigned)code, st ); - if ( !piranha_simulator && mf_initialized ) { - if (code != 0xffff) - mf_displayProgress( code ); - else - mf_clearSrc(); + printk("Progress: [%04x] - %s\n", (unsigned)code, st); + if (!piranha_simulator && mf_initialized) { + if (code != 0xffff) + mf_displayProgress(code); + else + mf_clearSrc(); } } - void iSeries_fixup_klimit(void) { - /* Change klimit to take into account any ram disk that may be included */ + /* + * Change klimit to take into account any ram disk + * that may be included + */ if (naca->xRamDisk) - klimit = KERNELBASE + (u64)naca->xRamDisk + (naca->xRamDiskSize * PAGE_SIZE); + klimit = KERNELBASE + (u64)naca->xRamDisk + + (naca->xRamDiskSize * PAGE_SIZE); else { - /* No ram disk was included - check and see if there was an embedded system map */ - /* Change klimit to take into account any embedded system map */ + /* + * No ram disk was included - check and see if there + * was an embedded system map. Change klimit to take + * into account any embedded system map + */ if (embedded_sysmap_end) - klimit = KERNELBASE + ((embedded_sysmap_end+4095) & 0xfffffffffffff000); + klimit = KERNELBASE + ((embedded_sysmap_end + 4095) & + 0xfffffffffffff000); } } static void iSeries_setup_dprofile(void) { - if ( dprof_buffer ) { + if (dprof_buffer) { unsigned i; - for (i=0; i #include "pci.h" -/************************************************/ -/* Size of Bus VPD data */ -/************************************************/ +/* + * Size of Bus VPD data + */ #define BUS_VPDSIZE 1024 -/************************************************/ -/* Bus Vpd Tags */ -/************************************************/ +/* + * Bus Vpd Tags + */ #define VpdEndOfDataTag 0x78 #define VpdEndOfAreaTag 0x79 #define VpdIdStringTag 0x82 #define VpdVendorAreaTag 0x84 -/************************************************/ -/* Mfg Area Tags */ -/************************************************/ +/* + * Mfg Area Tags + */ #define VpdFruFlag 0x4647 // "FG" #define VpdFruFrameId 0x4649 // "FI" #define VpdSlotMapFormat 0x4D46 // "MF" @@ -59,9 +59,9 @@ #define VpdFruSerial 0x534E // "SN" #define VpdSlotMap 0x534D // "SM" -/************************************************/ -/* Structures of the areas */ -/************************************************/ +/* + * Structures of the areas + */ struct MfgVpdAreaStruct { u16 Tag; u8 TagLength; @@ -82,168 +82,172 @@ struct SlotMapStruct { typedef struct SlotMapStruct SlotMap; #define SLOT_ENTRY_SIZE 16 -/**************************************************************** - * * - * Bus, Card, Board, FrameId, CardLocation. * - ****************************************************************/ -LocationData* iSeries_GetLocationData(struct pci_dev* PciDev) +/* + * Bus, Card, Board, FrameId, CardLocation. + */ +LocationData* iSeries_GetLocationData(struct pci_dev *PciDev) { - struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; - LocationData* LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL); + struct iSeries_Device_Node *DevNode = + (struct iSeries_Device_Node *)PciDev->sysdata; + LocationData *LocationPtr = + (LocationData *)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL); + if (LocationPtr == NULL) { printk("PCI: LocationData area allocation failed!\n"); return NULL; } - memset(LocationPtr,0,LOCATION_DATA_SIZE); - LocationPtr->Bus = ISERIES_BUS(DevNode); - LocationPtr->Board = DevNode->Board; - LocationPtr->FrameId = DevNode->FrameId; - LocationPtr->Card = PCI_SLOT(DevNode->DevFn); - strcpy(&LocationPtr->CardLocation[0],&DevNode->CardLocation[0]); + memset(LocationPtr, 0, LOCATION_DATA_SIZE); + LocationPtr->Bus = ISERIES_BUS(DevNode); + LocationPtr->Board = DevNode->Board; + LocationPtr->FrameId = DevNode->FrameId; + LocationPtr->Card = PCI_SLOT(DevNode->DevFn); + strcpy(&LocationPtr->CardLocation[0], &DevNode->CardLocation[0]); return LocationPtr; } -/************************************************************************/ -/* Formats the device information. */ -/* - Pass in pci_dev* pointer to the device. */ -/* - Pass in buffer to place the data. Danger here is the buffer must */ -/* be as big as the client says it is. Should be at least 128 bytes.*/ -/* Return will the length of the string data put in the buffer. */ -/* Format: */ -/* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet */ -/* controller */ -/************************************************************************/ -int iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize) +/* + * Formats the device information. + * - Pass in pci_dev* pointer to the device. + * - Pass in buffer to place the data. Danger here is the buffer must + * be as big as the client says it is. Should be at least 128 bytes. + * Return will the length of the string data put in the buffer. + * Format: + * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet + * controller + */ +int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer, + int BufferSize) { - struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; - char* BufPtr = Buffer; - int LineLen = 0; - - if (DevNode == NULL) { - LineLen = sprintf(BufPtr+LineLen, "PCI: iSeries_Device_Information DevNode is NULL"); - return LineLen; - } - - if (BufferSize >= 128) { - LineLen = sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ", - ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),PciDev->vendor); - - LineLen += sprintf(BufPtr+LineLen,"Frame%3d, Card %4s ", DevNode->FrameId,DevNode->CardLocation); - - if (pci_class_name(PciDev->class >> 8) == 0) { - LineLen += sprintf(BufPtr+LineLen,"0x%04X ",(int)(PciDev->class >> 8)); - } - else { - LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) ); - } - } - return LineLen; + struct iSeries_Device_Node *DevNode = + (struct iSeries_Device_Node *)PciDev->sysdata; + int len; + + if (DevNode == NULL) + return sprintf(buffer, + "PCI: iSeries_Device_Information DevNode is NULL"); + + if (BufferSize < 128) + return 0; + + len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ", + ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn), + PciDev->vendor); + len += sprintf(buffer + len, "Frame%3d, Card %4s ", + DevNode->FrameId, DevNode->CardLocation); +#ifdef CONFIG_PCI + if (pci_class_name(PciDev->class >> 8) == 0) + len += sprintf(buffer + len, "0x%04X ", + (int)(PciDev->class >> 8)); + else + len += sprintf(buffer + len, "%s", + pci_class_name(PciDev->class >> 8)); +#endif + return len; } -/************************************************************************/ -/* Build a character string of the device location, Frame 1, Card C10 */ -/************************************************************************/ -int device_Location(struct pci_dev* PciDev,char* BufPtr) + +/* + * Build a character string of the device location, Frame 1, Card C10 + */ +int device_Location(struct pci_dev *PciDev, char *BufPtr) { - struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; - return sprintf(BufPtr,"PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s", - DevNode->DsaAddr.busNumber, - DevNode->AgentId, - DevNode->Vendor, - DevNode->Location); + struct iSeries_Device_Node *DevNode = + (struct iSeries_Device_Node *)PciDev->sysdata; + return sprintf(BufPtr, "PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s", + DevNode->DsaAddr.Dsa.busNumber, DevNode->AgentId, + DevNode->Vendor, DevNode->Location); } -/*****************************************************************/ -/* Parse the Slot Area */ -/*****************************************************************/ -void iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, struct iSeries_Device_Node* DevNode) +/* + * Parse the Slot Area + */ +void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen, + struct iSeries_Device_Node *DevNode) { - int SlotMapLen = MapLen; - SlotMap* SlotMapPtr = MapPtr; - /*************************************************************/ - /* Parse Slot label until we find the one requrested */ - /*************************************************************/ + int SlotMapLen = MapLen; + SlotMap *SlotMapPtr = MapPtr; + + /* + * Parse Slot label until we find the one requrested + */ while (SlotMapLen > 0) { if (SlotMapPtr->AgentId == DevNode->AgentId ) { - /*******************************************************/ - /* If Phb wasn't found, grab the entry first one found.*/ - /*******************************************************/ - if (DevNode->PhbId == 0xff) { + /* + * If Phb wasn't found, grab the entry first one found. + */ + if (DevNode->PhbId == 0xff) DevNode->PhbId = SlotMapPtr->PhbId; - } - /**************************************************/ - /* Found it, extract the data. */ - /**************************************************/ + /* Found it, extract the data. */ if (SlotMapPtr->PhbId == DevNode->PhbId ) { - memcpy(&DevNode->CardLocation,&SlotMapPtr->CardLocation,3); + memcpy(&DevNode->CardLocation, + &SlotMapPtr->CardLocation, 3); DevNode->CardLocation[3] = 0; break; } } - /*********************************************************/ - /* Point to the next Slot */ - /*********************************************************/ - SlotMapPtr = (SlotMap*)((char*)SlotMapPtr+SLOT_ENTRY_SIZE); + /* Point to the next Slot */ + SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE); SlotMapLen -= SLOT_ENTRY_SIZE; } } -/*****************************************************************/ -/* Parse the Mfg Area */ -/*****************************************************************/ -static void iSeries_Parse_MfgArea(u8* AreaData,int AreaLen, struct iSeries_Device_Node* DevNode) +/* + * Parse the Mfg Area + */ +static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen, + struct iSeries_Device_Node *DevNode) { - MfgArea* MfgAreaPtr = (MfgArea*)AreaData; - int MfgAreaLen = AreaLen; - u16 SlotMapFmt = 0; - - /*************************************************************/ - /* Parse Mfg Data */ - /*************************************************************/ + MfgArea *MfgAreaPtr = (MfgArea *)AreaData; + int MfgAreaLen = AreaLen; + u16 SlotMapFmt = 0; + + /* Parse Mfg Data */ while (MfgAreaLen > 0) { - int MfgTagLen = MfgAreaPtr->TagLength; - /*******************************************************/ - /* Frame ID (FI 4649020310 ) */ - /*******************************************************/ - if (MfgAreaPtr->Tag == VpdFruFrameId) { /* FI */ + int MfgTagLen = MfgAreaPtr->TagLength; + /* Frame ID (FI 4649020310 ) */ + if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */ DevNode->FrameId = MfgAreaPtr->AreaData1; + /* Slot Map Format (MF 4D46020004 ) */ + else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */ + SlotMapFmt = (MfgAreaPtr->AreaData1 * 256) + + MfgAreaPtr->AreaData2; + /* Slot Map (SM 534D90 */ + else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */ + SlotMap *SlotMapPtr; + + if (SlotMapFmt == 0x1004) + SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr + + MFG_ENTRY_SIZE + 1); + else + SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr + + MFG_ENTRY_SIZE); + iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode); } - /*******************************************************/ - /* Slot Map Format (MF 4D46020004 ) */ - /*******************************************************/ - else if (MfgAreaPtr->Tag == VpdSlotMapFormat){ /* MF */ - SlotMapFmt = (MfgAreaPtr->AreaData1*256)+(MfgAreaPtr->AreaData2); - } - /*******************************************************/ - /* Slot Map (SM 534D90 */ - /*******************************************************/ - else if (MfgAreaPtr->Tag == VpdSlotMap){ /* SM */ - SlotMap* SlotMapPtr; - if (SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE+1); - else SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE); - iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, DevNode); - } - /*********************************************************/ - /* Point to the next Mfg Area */ - /* Use defined size, sizeof give wrong answer */ - /*********************************************************/ - MfgAreaPtr = (MfgArea*)((char*)MfgAreaPtr + MfgTagLen + MFG_ENTRY_SIZE); + /* + * Point to the next Mfg Area + * Use defined size, sizeof give wrong answer + */ + MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen + + MFG_ENTRY_SIZE); MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); } } -/*****************************************************************/ -/* Look for "BUS".. Data is not Null terminated. */ -/* PHBID of 0xFF indicates PHB was not found in VPD Data. */ -/*****************************************************************/ -static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength) +/* + * Look for "BUS".. Data is not Null terminated. + * PHBID of 0xFF indicates PHB was not found in VPD Data. + */ +static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength) { - u8* PhbPtr = AreaPtr; - int DataLen = AreaLength; - char PhbId = 0xFF; + u8 *PhbPtr = AreaPtr; + int DataLen = AreaLength; + char PhbId = 0xFF; + while (DataLen > 0) { - if (*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') { + if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U') + && (*(PhbPtr + 2) == 'S')) { PhbPtr += 3; - while(*PhbPtr == ' ') ++PhbPtr; + while (*PhbPtr == ' ') + ++PhbPtr; PhbId = (*PhbPtr & 0x0F); break; } @@ -253,64 +257,54 @@ static int iSeries_Parse_PhbId(u8* AreaP return PhbId; } -/****************************************************************/ -/* Parse out the VPD Areas */ -/****************************************************************/ -static void iSeries_Parse_Vpd(u8* VpdData, int VpdDataLen, struct iSeries_Device_Node* DevNode) +/* + * Parse out the VPD Areas + */ +static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen, + struct iSeries_Device_Node *DevNode) { - u8* TagPtr = VpdData; - int DataLen = VpdDataLen-3; - /*************************************************************/ - /* Parse the Areas */ - /*************************************************************/ - while (*TagPtr != VpdEndOfAreaTag && DataLen > 0) { - int AreaLen = *(TagPtr+1) + (*(TagPtr+2)*256); - u8* AreaData = TagPtr+3; + u8 *TagPtr = VpdData; + int DataLen = VpdDataLen - 3; - if (*TagPtr == VpdIdStringTag) { - DevNode->PhbId = iSeries_Parse_PhbId(AreaData,AreaLen); - } - else if (*TagPtr == VpdVendorAreaTag) { - iSeries_Parse_MfgArea(AreaData,AreaLen,DevNode); - } - /********************************************************* - * Point to next Area. - *********************************************************/ + while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) { + int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256); + u8 *AreaData = TagPtr + 3; + + if (*TagPtr == VpdIdStringTag) + DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen); + else if (*TagPtr == VpdVendorAreaTag) + iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode); + /* Point to next Area. */ TagPtr = AreaData + AreaLen; DataLen -= AreaLen; } } -/**************************************************************** - * iSeries_Get_Location_Code(struct iSeries_Device_Node*) * - * - ****************************************************************/ -void iSeries_Get_Location_Code(struct iSeries_Device_Node* DevNode) +void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode) { - int BusVpdLen = 0; - u8* BusVpdPtr = (u8*)kmalloc(BUS_VPDSIZE, GFP_KERNEL); + int BusVpdLen = 0; + u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL); + if (BusVpdPtr == NULL) { printk("PCI: Bus VPD Buffer allocation failure.\n"); return; } - BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),REALADDR(BusVpdPtr),BUS_VPDSIZE); + BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode), + REALADDR(BusVpdPtr), BUS_VPDSIZE); if (BusVpdLen == 0) { kfree(BusVpdPtr); printk("PCI: Bus VPD Buffer zero length.\n"); return; } - //printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); - /*************************************************************/ - /* Make sure this is what I think it is */ - /*************************************************************/ - if (*BusVpdPtr != VpdIdStringTag) { /*0x82 */ + /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */ + /* Make sure this is what I think it is */ + if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */ printk("PCI: Bus VPD Buffer missing starting tag.\n"); kfree(BusVpdPtr); return; } - /***************************************************************/ - /***************************************************************/ iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode); - sprintf(DevNode->Location,"Frame%3d, Card %-4s",DevNode->FrameId,DevNode->CardLocation); + sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId, + DevNode->CardLocation); kfree(BusVpdPtr); } diff -puN arch/ppc64/kernel/ItLpQueue.c~linus arch/ppc64/kernel/ItLpQueue.c --- 25/arch/ppc64/kernel/ItLpQueue.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/ItLpQueue.c 2004-01-19 22:17:21.000000000 -0800 @@ -147,17 +147,14 @@ unsigned ItLpQueue_process( struct ItLpQ printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType ); ItLpQueue_clearValid( nextLpEvent ); - } - else /* No more valid events - * If overflow events are pending - * process them + } else if ( lpQueue->xPlicOverflowIntPending ) + /* + * No more valid events. If overflow events are + * pending process them */ - if ( lpQueue->xPlicOverflowIntPending ) { - HvCallEvent_getOverflowLpEvents( - lpQueue->xIndex); - } - else /* If nothing left then we are done */ - break; + HvCallEvent_getOverflowLpEvents( lpQueue->xIndex); + else + break; } ItLpQueueInProcess = 0; diff -puN /dev/null arch/ppc64/kernel/lparcfg.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/kernel/lparcfg.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,478 @@ +/* + * PowerPC64 LPAR Configuration Information Driver + * + * Dave Engebretsen engebret@us.ibm.com + * Copyright (c) 2003 Dave Engebretsen + * Will Schmidt willschm@us.ibm.com + * SPLPAR updates, Copyright (c) 2003 Will Schmidt IBM Corporation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This driver creates a proc file at /proc/ppc64/lparcfg which contains + * keyword - value pairs that specify the configuration of the partition. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MODULE_VERSION "1.0" +#define MODULE_NAME "lparcfg" + +static struct proc_dir_entry *proc_ppc64_lparcfg; +#define LPARCFG_BUFF_SIZE 4096 + +#ifdef CONFIG_PPC_ISERIES +static unsigned char e2a(unsigned char x) +{ + switch (x) { + case 0xF0: + return '0'; + case 0xF1: + return '1'; + case 0xF2: + return '2'; + case 0xF3: + return '3'; + case 0xF4: + return '4'; + case 0xF5: + return '5'; + case 0xF6: + return '6'; + case 0xF7: + return '7'; + case 0xF8: + return '8'; + case 0xF9: + return '9'; + case 0xC1: + return 'A'; + case 0xC2: + return 'B'; + case 0xC3: + return 'C'; + case 0xC4: + return 'D'; + case 0xC5: + return 'E'; + case 0xC6: + return 'F'; + case 0xC7: + return 'G'; + case 0xC8: + return 'H'; + case 0xC9: + return 'I'; + case 0xD1: + return 'J'; + case 0xD2: + return 'K'; + case 0xD3: + return 'L'; + case 0xD4: + return 'M'; + case 0xD5: + return 'N'; + case 0xD6: + return 'O'; + case 0xD7: + return 'P'; + case 0xD8: + return 'Q'; + case 0xD9: + return 'R'; + case 0xE2: + return 'S'; + case 0xE3: + return 'T'; + case 0xE4: + return 'U'; + case 0xE5: + return 'V'; + case 0xE6: + return 'W'; + case 0xE7: + return 'X'; + case 0xE8: + return 'Y'; + case 0xE9: + return 'Z'; + } + return ' '; +} + +/* + * Methods used to fetch LPAR data when running on an iSeries platform. + */ +static int lparcfg_data(unsigned char *buf, unsigned long size) +{ + unsigned long n = 0, pool_id, lp_index; + int shared, entitled_capacity, max_entitled_capacity; + int processors, max_processors; + struct paca_struct *lpaca = get_paca(); + + if((buf == NULL) || (size > LPARCFG_BUFF_SIZE)) { + return -EFAULT; + } + memset(buf, 0, size); + + shared = (int)(lpaca->xLpPacaPtr->xSharedProc); + n += snprintf(buf, LPARCFG_BUFF_SIZE - n, + "serial_number=%c%c%c%c%c%c%c\n", + e2a(xItExtVpdPanel.mfgID[2]), + e2a(xItExtVpdPanel.mfgID[3]), + e2a(xItExtVpdPanel.systemSerial[1]), + e2a(xItExtVpdPanel.systemSerial[2]), + e2a(xItExtVpdPanel.systemSerial[3]), + e2a(xItExtVpdPanel.systemSerial[4]), + e2a(xItExtVpdPanel.systemSerial[5])); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_type=%c%c%c%c\n", + e2a(xItExtVpdPanel.machineType[0]), + e2a(xItExtVpdPanel.machineType[1]), + e2a(xItExtVpdPanel.machineType[2]), + e2a(xItExtVpdPanel.machineType[3])); + + lp_index = HvLpConfig_getLpIndex(); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_id=%d\n", (int)lp_index); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_active_processors=%d\n", + (int)HvLpConfig_getSystemPhysicalProcessors()); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_potential_processors=%d\n", + (int)HvLpConfig_getSystemPhysicalProcessors()); + + processors = (int)HvLpConfig_getPhysicalProcessors(); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_active_processors=%d\n", processors); + + max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_potential_processors=%d\n", max_processors); + + if(shared) { + entitled_capacity = HvLpConfig_getSharedProcUnits(); + max_entitled_capacity = HvLpConfig_getMaxSharedProcUnits(); + } else { + entitled_capacity = processors * 100; + max_entitled_capacity = max_processors * 100; + } + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_entitled_capacity=%d\n", entitled_capacity); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_max_entitled_capacity=%d\n", + max_entitled_capacity); + + if(shared) { + pool_id = HvLpConfig_getSharedPoolIndex(); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", + (int)pool_id); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "pool_capacity=%d\n", (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100)); + } + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "shared_processor_mode=%d\n", shared); + + return 0; +} +#endif /* CONFIG_PPC_ISERIES */ + +#ifdef CONFIG_PPC_PSERIES +/* + * Methods used to fetch LPAR data when running on a pSeries platform. + */ + +/* + * H_GET_PPP hcall returns info in 4 parms. + * entitled_capacity,unallocated_capacity, + * aggregation, resource_capability). + * + * R4 = Entitled Processor Capacity Percentage. + * R5 = Unallocated Processor Capacity Percentage. + * R6 (AABBCCDDEEFFGGHH). + * XXXX - reserved (0) + * XXXX - reserved (0) + * XXXX - Group Number + * XXXX - Pool Number. + * R7 (PPOONNMMLLKKJJII) + * XX - reserved. (0) + * XX - bit 0-6 reserved (0). bit 7 is Capped indicator. + * XX - variable processor Capacity Weight + * XX - Unallocated Variable Processor Capacity Weight. + * XXXX - Active processors in Physical Processor Pool. + * XXXX - Processors active on platform. + */ +unsigned int h_get_ppp(unsigned long *entitled,unsigned long *unallocated,unsigned long *aggregation,unsigned long *resource) +{ + unsigned long rc; + rc = plpar_hcall_4out(H_GET_PPP,0,0,0,0,entitled,unallocated,aggregation,resource); + return 0; +} + +/* + * get_splpar_potential_characteristics(). + * Retrieve the potential_processors and max_entitled_capacity values + * through the get-system-parameter rtas call. + */ +#define SPLPAR_CHARACTERISTICS_TOKEN 20 +#define SPLPAR_MAXLENGTH 1026*(sizeof(char)) +unsigned int get_splpar_potential_characteristics(void) +{ + /* return 0 for now. Underlying rtas functionality is not yet complete. 12/01/2003*/ + return 0; +#if 0 + long call_status; + unsigned long ret[2]; + + char * buffer = kmalloc(SPLPAR_MAXLENGTH, GFP_KERNEL); + + printk("token for ibm,get-system-parameter (0x%x)\n",rtas_token("ibm,get-system-parameter")); + + call_status = rtas_call(rtas_token("ibm,get-system-parameter"), 3, 1, + NULL, + SPLPAR_CHARACTERISTICS_TOKEN, + &buffer, + SPLPAR_MAXLENGTH, + (void *)&ret); + + if (call_status!=0) { + printk("Error calling get-system-parameter (0x%lx)\n",call_status); + kfree(buffer); + return -1; + } else { + printk("get-system-parameter (%s)\n",buffer); + kfree(buffer); + /* TODO: Add code here to parse out value for system_potential_processors and partition_max_entitled_capacity */ + return 1; + } +#endif +} + +static int lparcfg_data(unsigned char *buf, unsigned long size) +{ + unsigned long n = 0; + int shared, max_entitled_capacity; + int processors, system_active_processors, system_potential_processors; + struct device_node *root; + const char *model = ""; + const char *system_id = ""; + unsigned int *lp_index_ptr, lp_index = 0; + struct device_node *rtas_node; + int *ip; + unsigned long h_entitled,h_unallocated,h_aggregation,h_resource; + + if((buf == NULL) || (size > LPARCFG_BUFF_SIZE)) { + return -EFAULT; + } + memset(buf, 0, size); + + root = find_path_device("/"); + if (root) { + model = get_property(root, "model", NULL); + system_id = get_property(root, "system-id", NULL); + lp_index_ptr = (unsigned int *)get_property(root, "ibm,partition-no", NULL); + if(lp_index_ptr) lp_index = *lp_index_ptr; + } + + n = snprintf(buf, LPARCFG_BUFF_SIZE - n, + "serial_number=%s\n", system_id); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_type=%s\n", model); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_id=%d\n", (int)lp_index); + + rtas_node = find_path_device("/rtas"); + ip = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); + if (ip == NULL) { + system_active_processors = systemcfg->processorCount; + } else { + system_active_processors = *(ip + 4); + } + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource); +#ifdef DEBUG + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "R4=0x%lx\n", h_entitled); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "R5=0x%lx\n", h_unallocated); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "R6=0x%lx\n", h_aggregation); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "R7=0x%lx\n", h_resource); +#endif /* DEBUG */ + } + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + system_potential_processors = get_splpar_potential_characteristics(); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_active_processors=%d\n", + (h_resource >> 2*8) && 0xffff); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_potential_processors=%d\n", + system_potential_processors); + } else { + system_potential_processors = system_active_processors; + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_active_processors=%d\n", + system_active_processors); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "system_potential_processors=%d\n", + system_potential_processors); + } + + processors = systemcfg->processorCount; + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_active_processors=%d\n", processors); + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_potential_processors=%d\n", + system_active_processors); + + /* max_entitled_capacity will come out of get_splpar_potential_characteristics() when that function is complete */ + max_entitled_capacity = system_active_processors * 100; + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_entitled_capacity=%ld\n", h_entitled); + } else { + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_entitled_capacity=%d\n", system_active_processors*100); + } + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "partition_max_entitled_capacity=%d\n", + max_entitled_capacity); + + shared = 0; + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "shared_processor_mode=%d\n", shared); + + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "pool=%d\n", (h_aggregation >> 0*8)&&0xffff); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "pool_capacity=%d\n", (h_resource >> 3*8) &&0xffff); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "group=%d\n", (h_aggregation >> 2*8)&&0xffff); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "capped=%d\n", (h_resource >> 6*8)&&0x40); + + n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF); + } + return 0; +} +#endif /* CONFIG_PPC_PSERIES */ + + +static ssize_t lparcfg_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + unsigned long *data = (unsigned long *)dp->data; + unsigned long p; + ssize_t read; + char * pnt; + + if (!data) { + printk(KERN_ERR "lparcfg: read failed no data\n"); + return -EIO; + } + + if(ppos) { + p = *ppos; + } else { + return -EFAULT; + } + + if (p >= LPARCFG_BUFF_SIZE) return 0; + + lparcfg_data((unsigned char *)data, LPARCFG_BUFF_SIZE); + if (count > (strlen((char *)data) - p)) + count = (strlen((char *)data)) - p; + read = 0; + + pnt = (char *)(data) + p; + copy_to_user(buf, (void *)pnt, count); + read += count; + *ppos += read; + return read; +} + +static int lparcfg_open(struct inode * inode, struct file * file) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + unsigned int *data = (unsigned int *)dp->data; + + if (!data) { + printk(KERN_ERR "lparcfg: open failed no data\n"); + return -EIO; + } + + return 0; +} + +struct file_operations lparcfg_fops = { + owner: THIS_MODULE, + read: lparcfg_read, + open: lparcfg_open, +}; + +int __init lparcfg_init(void) +{ + struct proc_dir_entry *ent; + + ent = create_proc_entry("ppc64/lparcfg", S_IRUSR, NULL); + if (ent) { + ent->proc_fops = &lparcfg_fops; + ent->data = kmalloc(LPARCFG_BUFF_SIZE, GFP_KERNEL); + if (!ent->data) { + printk(KERN_ERR "Failed to allocate buffer for lparcfg\n"); + remove_proc_entry("lparcfg", ent->parent); + return -ENOMEM; + } + } else { + printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); + return -EIO; + } + + proc_ppc64_lparcfg = ent; + return 0; +} + +void __exit lparcfg_cleanup(void) +{ + if (proc_ppc64_lparcfg) { + if (proc_ppc64_lparcfg->data) { + kfree(proc_ppc64_lparcfg->data); + } + remove_proc_entry("lparcfg", proc_ppc64_lparcfg->parent); + } +} + +module_init(lparcfg_init); +module_exit(lparcfg_cleanup); +MODULE_DESCRIPTION("Interface for LPAR configuration data"); +MODULE_AUTHOR("Dave Engebretsen"); +MODULE_LICENSE("GPL"); diff -puN arch/ppc64/kernel/LparData.c~linus arch/ppc64/kernel/LparData.c --- 25/arch/ppc64/kernel/LparData.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/LparData.c 2004-01-19 22:17:21.000000000 -0800 @@ -28,29 +28,12 @@ #include #include -extern char _start_boltedStacks[]; - -/* The LparMap data is now located at offset 0x6000 in head.S - * It was put there so that the HvReleaseData could address it - * with a 32-bit offset as required by the iSeries hypervisor - * - * The Naca has a pointer to the ItVpdAreas. The hypervisor finds - * the Naca via the HvReleaseData area. The HvReleaseData has the - * offset into the Naca of the pointer to the ItVpdAreas. - */ - -extern struct ItVpdAreas itVpdAreas; - /* The LpQueue is used to pass event data from the hypervisor to * the partition. This is where I/O interrupt events are communicated. - * The ItLpQueue must be initialized (even though only to all zeros) - * If it were uninitialized (in .bss) it would get zeroed after the - * kernel gets control. The hypervisor will have filled in some fields - * before the kernel gets control. By initializing it we keep it out - * of the .bss */ -struct ItLpQueue xItLpQueue = {}; +/* May be filled in by the hypervisor so cannot end up in the BSS */ +struct ItLpQueue xItLpQueue __attribute__((__section__(".data"))); /* The HvReleaseData is the root of the information shared between @@ -71,7 +54,7 @@ struct HvReleaseData hvReleaseData = { 6, /* TEMP: This allows non-GA driver */ 4, /* We are v5r2m0 */ 3, /* Min supported PLIC = v5r1m0 */ - 3, /* Min usuable PLIC = v5r1m0 */ + 3, /* Min usable PLIC = v5r1m0 */ { 0xd3, 0x89, 0x95, 0xa4, /* "Linux 2.4 "*/ 0xa7, 0x40, 0xf2, 0x4b, 0xf4, 0x4b, 0xf6, 0xf4 }, @@ -141,9 +124,11 @@ struct ItLpNaca itLpNaca = { } }; -struct ItIplParmsReal xItIplParmsReal = {}; +/* May be filled in by the hypervisor so cannot end up in the BSS */ +struct ItIplParmsReal xItIplParmsReal __attribute__((__section__(".data"))); -struct ItExtVpdPanel xItExtVpdPanel = {}; +/* May be filled in by the hypervisor so cannot end up in the BSS */ +struct ItExtVpdPanel xItExtVpdPanel __attribute__((__section__(".data"))); #define maxPhysicalProcessors 32 @@ -157,10 +142,13 @@ struct IoHriProcessorVpd xIoHriProcessor } }; - -u64 xMsVpd[3400] = {}; /* Space for Main Store Vpd 27,200 bytes */ - -u64 xRecoveryLogBuffer[32] = {}; /* Space for Recovery Log Buffer */ +/* Space for Main Store Vpd 27,200 bytes */ +/* May be filled in by the hypervisor so cannot end up in the BSS */ +u64 xMsVpd[3400] __attribute__((__section__(".data"))); + +/* Space for Recovery Log Buffer */ +/* May be filled in by the hypervisor so cannot end up in the BSS */ +u64 xRecoveryLogBuffer[32] __attribute__((__section__(".data"))); struct SpCommArea xSpCommArea = { 0xE2D7C3C2, @@ -169,13 +157,21 @@ struct SpCommArea xSpCommArea = { 0, 0, 0, 0, {0} }; +/* The LparMap data is now located at offset 0x6000 in head.S + * It was put there so that the HvReleaseData could address it + * with a 32-bit offset as required by the iSeries hypervisor + * + * The Naca has a pointer to the ItVpdAreas. The hypervisor finds + * the Naca via the HvReleaseData area. The HvReleaseData has the + * offset into the Naca of the pointer to the ItVpdAreas. + */ struct ItVpdAreas itVpdAreas = { 0xc9a3e5c1, /* "ItVA" */ sizeof( struct ItVpdAreas ), 0, 0, 26, /* # VPD array entries */ 10, /* # DMA array entries */ - MAX_PROCESSORS*2, maxPhysicalProcessors, /* Max logical, physical procs */ + NR_CPUS*2, maxPhysicalProcessors, /* Max logical, physical procs */ offsetof(struct ItVpdAreas,xPlicDmaToks),/* offset to DMA toks */ offsetof(struct ItVpdAreas,xSlicVpdAdrs),/* offset to VPD addrs */ offsetof(struct ItVpdAreas,xPlicDmaLens),/* offset to DMA lens */ @@ -223,7 +219,7 @@ struct ItVpdAreas itVpdAreas = { } }; -struct msChunks msChunks = {0, 0, 0, 0, NULL}; +struct msChunks msChunks; /* Depending on whether this is called from iSeries or pSeries setup * code, the location of the msChunks struct may or may not have diff -puN arch/ppc64/kernel/Makefile~linus arch/ppc64/kernel/Makefile --- 25/arch/ppc64/kernel/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -7,24 +7,29 @@ extra-y := head.o vmlinux.lds.s obj-y := setup.o entry.o traps.o irq.o idle.o \ time.o process.o signal.o syscalls.o misc.o ptrace.o \ - align.o semaphore.o bitops.o stab.o htab.o pacaData.o \ + align.o semaphore.o bitops.o stab.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o pci.o pci_dn.o pci_dma.o cputable.o + lmb.o cputable.o -obj-$(CONFIG_PPC_ISERIES) += iSeries_pci.o iSeries_pci_reset.o \ - iSeries_IoMmTable.o iSeries_irq.o \ - iSeries_VpdInfo.o XmPciLpEvent.o \ +obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o + +ifdef CONFIG_PPC_ISERIES +obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ + iSeries_IoMmTable.o +endif + +obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \ + iSeries_VpdInfo.o XmPciLpEvent.o \ HvCall.o HvLpConfig.o LparData.o mf_proc.o \ iSeries_setup.o ItLpQueue.o hvCall.o \ - mf.o HvLpEvent.o iSeries_proc.o + mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ + proc_pmc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o rtasd.o nvram.o ras.o - -# Change this to pSeries only once we've got iSeries up to date -obj-y += open_pic.o xics.o pSeries_htab.o rtas.o \ - chrp_setup.o i8259.o prom.o + eeh.o nvram.o rtasd.o ras.o \ + open_pic.o xics.o pSeries_htab.o rtas.o \ + chrp_setup.o i8259.o prom.o vio.o obj-$(CONFIG_PROC_FS) += proc_ppc64.o obj-$(CONFIG_RTAS_FLASH) += rtas_flash.o @@ -32,5 +37,8 @@ obj-$(CONFIG_SMP) += smp.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_PPC_RTAS) += rtas-proc.o obj-$(CONFIG_SCANLOG) += scanlog.o +obj-$(CONFIG_VIOPATH) += viopath.o +obj-$(CONFIG_LPARCFG) += lparcfg.o + CFLAGS_ioctl32.o += -Ifs/ diff -puN arch/ppc64/kernel/mf.c~linus arch/ppc64/kernel/mf.c --- 25/arch/ppc64/kernel/mf.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/mf.c 2004-01-19 22:17:21.000000000 -0800 @@ -36,166 +36,125 @@ #include #include #include -#include #include #include #include #include -extern struct pci_dev * iSeries_vio_dev; +extern struct pci_dev *iSeries_vio_dev; /* * This is the structure layout for the Machine Facilites LPAR event * flows. */ -struct VspCmdData; -struct CeMsgData; -union SafeCast -{ - u64 ptrAsU64; +union safe_cast { + u64 ptr_as_u64; void *ptr; }; +struct VspCmdData { + union safe_cast token; + u16 cmd; + HvLpIndex lp_index; + u8 result_code; + u32 reserved; + union { + u64 state; /* GetStateOut */ + u64 ipl_type; /* GetIplTypeOut, Function02SelectIplTypeIn */ + u64 ipl_mode; /* GetIplModeOut, Function02SelectIplModeIn */ + u64 page[4]; /* GetSrcHistoryIn */ + u64 flag; /* GetAutoIplWhenPrimaryIplsOut, + SetAutoIplWhenPrimaryIplsIn, + WhiteButtonPowerOffIn, + Function08FastPowerOffIn, + IsSpcnRackPowerIncompleteOut */ + struct { + u64 token; + u64 address_type; + u64 side; + u32 length; + u32 offset; + } kern; /* SetKernelImageIn, GetKernelImageIn, + SetKernelCmdLineIn, GetKernelCmdLineIn */ + u32 length_out; /* GetKernelImageOut, GetKernelCmdLineOut */ + u8 reserved[80]; + } sub_data; +}; -typedef void (*CeMsgCompleteHandler)( void *token, struct CeMsgData *vspCmdRsp ); - -struct CeMsgCompleteData -{ - CeMsgCompleteHandler xHdlr; - void *xToken; +struct VspRspData { + struct semaphore *sem; + struct VspCmdData *response; }; -struct VspRspData -{ - struct semaphore *xSemaphore; - struct VspCmdData *xResponse; +struct AllocData { + u16 size; + u16 type; + u32 count; + u16 reserved1; + u8 reserved2; + HvLpIndex target_lp; }; -struct IoMFLpEvent -{ - struct HvLpEvent xHvLpEvent; +struct CeMsgData; - u16 xSubtypeRc; - u16 xRsvd1; - u32 xRsvd2; - - union - { - - struct AllocData - { - u16 xSize; - u16 xType; - u32 xCount; - u16 xRsvd3; - u8 xRsvd4; - HvLpIndex xTargetLp; - } xAllocData; - - struct CeMsgData - { - u8 xCEMsg[12]; - char xReserved[4]; - struct CeMsgCompleteData *xToken; - } xCEMsgData; - - struct VspCmdData - { - union SafeCast xTokenUnion; - u16 xCmd; - HvLpIndex xLpIndex; - u8 xRc; - u32 xReserved1; +typedef void (*CeMsgCompleteHandler)(void *token, struct CeMsgData *vspCmdRsp); - union VspCmdSubData - { - struct - { - u64 xState; - } xGetStateOut; - - struct - { - u64 xIplType; - } xGetIplTypeOut, xFunction02SelectIplTypeIn; - - struct - { - u64 xIplMode; - } xGetIplModeOut, xFunction02SelectIplModeIn; - - struct - { - u64 xPage[4]; - } xGetSrcHistoryIn; - - struct - { - u64 xFlag; - } xGetAutoIplWhenPrimaryIplsOut, - xSetAutoIplWhenPrimaryIplsIn, - xWhiteButtonPowerOffIn, - xFunction08FastPowerOffIn, - xIsSpcnRackPowerIncompleteOut; - - struct - { - u64 xToken; - u64 xAddressType; - u64 xSide; - u32 xTransferLength; - u32 xOffset; - } xSetKernelImageIn, - xGetKernelImageIn, - xSetKernelCmdLineIn, - xGetKernelCmdLineIn; - - struct - { - u32 xTransferLength; - } xGetKernelImageOut,xGetKernelCmdLineOut; - - - u8 xReserved2[80]; - - } xSubData; - } xVspCmd; - } xUnion; +struct CeMsgCompleteData { + CeMsgCompleteHandler handler; + void *token; }; +struct CeMsgData { + u8 ce_msg[12]; + char reserved[4]; + struct CeMsgCompleteData *completion; +}; + +struct IoMFLpEvent { + struct HvLpEvent hp_lp_event; + u16 subtype_result_code; + u16 reserved1; + u32 reserved2; + union { + struct AllocData alloc; + struct CeMsgData ce_msg; + struct VspCmdData vsp_cmd; + } data; +}; + +#define subtype_data(a, b, c, d) \ + (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) /* * All outgoing event traffic is kept on a FIFO queue. The first * pointer points to the one that is outstanding, and all new * requests get stuck on the end. Also, we keep a certain number of - * preallocated stack elements so that we can operate very early in + * preallocated pending events so that we can operate very early in * the boot up sequence (before kmalloc is ready). */ -struct StackElement -{ - struct StackElement * next; +struct pending_event { + struct pending_event *next; struct IoMFLpEvent event; MFCompleteHandler hdlr; - char dmaData[72]; - unsigned dmaDataLength; - unsigned remoteAddress; + char dma_data[72]; + unsigned dma_data_length; + unsigned remote_address; }; -static spinlock_t spinlock; -static struct StackElement * head = NULL; -static struct StackElement * tail = NULL; -static struct StackElement * avail = NULL; -static struct StackElement prealloc[16]; +static spinlock_t pending_event_spinlock; +static struct pending_event *pending_event_head; +static struct pending_event *pending_event_tail; +static struct pending_event *pending_event_avail; +static struct pending_event pending_event_prealloc[16]; /* - * Put a stack element onto the available queue, so it can get reused. - * Attention! You must have the spinlock before calling! + * Put a pending event onto the available queue, so it can get reused. + * Attention! You must have the pending_event_spinlock before calling! */ -void free( struct StackElement * element ) +static void free_pending_event(struct pending_event *ev) { - if ( element != NULL ) - { - element->next = avail; - avail = element; + if (ev != NULL) { + ev->next = pending_event_avail; + pending_event_avail = ev; } } @@ -203,68 +162,68 @@ void free( struct StackElement * element * Enqueue the outbound event onto the stack. If the queue was * empty to begin with, we must also issue it via the Hypervisor * interface. There is a section of code below that will touch - * the first stack pointer without the protection of the spinlock. + * the first stack pointer without the protection of the pending_event_spinlock. * This is OK, because we know that nobody else will be modifying * the first pointer when we do this. */ -static int signalEvent( struct StackElement * newElement ) +static int signal_event(struct pending_event *ev) { int rc = 0; unsigned long flags; int go = 1; - struct StackElement * element; + struct pending_event *ev1; HvLpEvent_Rc hvRc; /* enqueue the event */ - if ( newElement != NULL ) - { - spin_lock_irqsave( &spinlock, flags ); - if ( head == NULL ) - head = newElement; + if (ev != NULL) { + ev->next = NULL; + spin_lock_irqsave(&pending_event_spinlock, flags); + if (pending_event_head == NULL) + pending_event_head = ev; else { go = 0; - tail->next = newElement; + pending_event_tail->next = ev; } - newElement->next = NULL; - tail = newElement; - spin_unlock_irqrestore( &spinlock, flags ); + pending_event_tail = ev; + spin_unlock_irqrestore(&pending_event_spinlock, flags); } /* send the event */ - while ( go ) - { + while (go) { go = 0; /* any DMA data to send beforehand? */ - if ( head->dmaDataLength > 0 ) - HvCallEvent_dmaToSp( head->dmaData, head->remoteAddress, head->dmaDataLength, HvLpDma_Direction_LocalToRemote ); - - hvRc = HvCallEvent_signalLpEvent(&head->event.xHvLpEvent); - if ( hvRc != HvLpEvent_Rc_Good ) - { - printk( KERN_ERR "mf.c: HvCallEvent_signalLpEvent() failed with %d\n", (int)hvRc ); - - spin_lock_irqsave( &spinlock, flags ); - element = head; - head = head->next; - if ( head != NULL ) + if (pending_event_head->dma_data_length > 0) + HvCallEvent_dmaToSp(pending_event_head->dma_data, + pending_event_head->remote_address, + pending_event_head->dma_data_length, + HvLpDma_Direction_LocalToRemote); + + hvRc = HvCallEvent_signalLpEvent( + &pending_event_head->event.hp_lp_event); + if (hvRc != HvLpEvent_Rc_Good) { + printk(KERN_ERR "mf.c: HvCallEvent_signalLpEvent() failed with %d\n", + (int)hvRc); + + spin_lock_irqsave(&pending_event_spinlock, flags); + ev1 = pending_event_head; + pending_event_head = pending_event_head->next; + if (pending_event_head != NULL) go = 1; - spin_unlock_irqrestore( &spinlock, flags ); + spin_unlock_irqrestore(&pending_event_spinlock, flags); - if ( element == newElement ) + if (ev1 == ev) rc = -EIO; - else { - if ( element->hdlr != NULL ) - { - union SafeCast mySafeCast; - mySafeCast.ptrAsU64 = element->event.xHvLpEvent.xCorrelationToken; - (*element->hdlr)( mySafeCast.ptr, -EIO ); - } + else if (ev1->hdlr != NULL) { + union safe_cast mySafeCast; + + mySafeCast.ptr_as_u64 = ev1->event.hp_lp_event.xCorrelationToken; + (*ev1->hdlr)(mySafeCast.ptr, -EIO); } - spin_lock_irqsave( &spinlock, flags ); - free( element ); - spin_unlock_irqrestore( &spinlock, flags ); + spin_lock_irqsave(&pending_event_spinlock, flags); + free_pending_event(ev1); + spin_unlock_irqrestore(&pending_event_spinlock, flags); } } @@ -272,80 +231,74 @@ static int signalEvent( struct StackElem } /* - * Allocate a new StackElement structure, and initialize it. + * Allocate a new pending_event structure, and initialize it. */ -static struct StackElement * newStackElement( void ) +static struct pending_event *new_pending_event(void) { - struct StackElement * newElement = NULL; + struct pending_event *ev = NULL; HvLpIndex primaryLp = HvLpConfig_getPrimaryLpIndex(); unsigned long flags; + struct HvLpEvent *hev; - if ( newElement == NULL ) - { - spin_lock_irqsave( &spinlock, flags ); - if ( avail != NULL ) - { - newElement = avail; - avail = avail->next; - } - spin_unlock_irqrestore( &spinlock, flags ); - } - - if ( newElement == NULL ) - newElement = kmalloc(sizeof(struct StackElement),GFP_ATOMIC); - - if ( newElement == NULL ) - { - printk( KERN_ERR "mf.c: unable to kmalloc %ld bytes\n", sizeof(struct StackElement) ); + spin_lock_irqsave(&pending_event_spinlock, flags); + if (pending_event_avail != NULL) { + ev = pending_event_avail; + pending_event_avail = pending_event_avail->next; + } + spin_unlock_irqrestore(&pending_event_spinlock, flags); + if (ev == NULL) + ev = kmalloc(sizeof(struct pending_event),GFP_ATOMIC); + if (ev == NULL) { + printk(KERN_ERR "mf.c: unable to kmalloc %ld bytes\n", + sizeof(struct pending_event)); return NULL; } + memset(ev, 0, sizeof(struct pending_event)); + hev = &ev->event.hp_lp_event; + hev->xFlags.xValid = 1; + hev->xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; + hev->xFlags.xAckInd = HvLpEvent_AckInd_DoAck; + hev->xFlags.xFunction = HvLpEvent_Function_Int; + hev->xType = HvLpEvent_Type_MachineFac; + hev->xSourceLp = HvLpConfig_getLpIndex(); + hev->xTargetLp = primaryLp; + hev->xSizeMinus1 = sizeof(ev->event)-1; + hev->xRc = HvLpEvent_Rc_Good; + hev->xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primaryLp, + HvLpEvent_Type_MachineFac); + hev->xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primaryLp, + HvLpEvent_Type_MachineFac); - memset( newElement, 0, sizeof(struct StackElement) ); - newElement->event.xHvLpEvent.xFlags.xValid = 1; - newElement->event.xHvLpEvent.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; - newElement->event.xHvLpEvent.xFlags.xAckInd = HvLpEvent_AckInd_DoAck; - newElement->event.xHvLpEvent.xFlags.xFunction = HvLpEvent_Function_Int; - newElement->event.xHvLpEvent.xType = HvLpEvent_Type_MachineFac; - newElement->event.xHvLpEvent.xSourceLp = HvLpConfig_getLpIndex(); - newElement->event.xHvLpEvent.xTargetLp = primaryLp; - newElement->event.xHvLpEvent.xSizeMinus1 = sizeof(newElement->event)-1; - newElement->event.xHvLpEvent.xRc = HvLpEvent_Rc_Good; - newElement->event.xHvLpEvent.xSourceInstanceId = HvCallEvent_getSourceLpInstanceId(primaryLp,HvLpEvent_Type_MachineFac); - newElement->event.xHvLpEvent.xTargetInstanceId = HvCallEvent_getTargetLpInstanceId(primaryLp,HvLpEvent_Type_MachineFac); - - return newElement; + return ev; } -static int signalVspInstruction( struct VspCmdData *vspCmd ) +static int signal_vsp_instruction(struct VspCmdData *vspCmd) { - struct StackElement * newElement = newStackElement(); - int rc = 0; + struct pending_event *ev = new_pending_event(); + int rc; struct VspRspData response; DECLARE_MUTEX_LOCKED(Semaphore); - response.xSemaphore = &Semaphore; - response.xResponse = vspCmd; - if ( newElement == NULL ) - rc = -ENOMEM; - else { - newElement->event.xHvLpEvent.xSubtype = 6; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('V'<<8)+('I'<<0); - newElement->event.xUnion.xVspCmd.xTokenUnion.ptr = &response; - newElement->event.xUnion.xVspCmd.xCmd = vspCmd->xCmd; - newElement->event.xUnion.xVspCmd.xLpIndex = HvLpConfig_getLpIndex(); - newElement->event.xUnion.xVspCmd.xRc = 0xFF; - newElement->event.xUnion.xVspCmd.xReserved1 = 0; - memcpy(&(newElement->event.xUnion.xVspCmd.xSubData),&(vspCmd->xSubData), sizeof(vspCmd->xSubData)); - mb(); + if (ev == NULL) + return -ENOMEM; - rc = signalEvent(newElement); - } + response.sem = &Semaphore; + response.response = vspCmd; + ev->event.hp_lp_event.xSubtype = 6; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'V', 'I'); + ev->event.data.vsp_cmd.token.ptr = &response; + ev->event.data.vsp_cmd.cmd = vspCmd->cmd; + ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); + ev->event.data.vsp_cmd.result_code = 0xFF; + ev->event.data.vsp_cmd.reserved = 0; + memcpy(&(ev->event.data.vsp_cmd.sub_data), + &(vspCmd->sub_data), sizeof(vspCmd->sub_data)); + mb(); + rc = signal_event(ev); if (rc == 0) - { down(&Semaphore); - } - return rc; } @@ -353,46 +306,42 @@ static int signalVspInstruction( struct /* * Send a 12-byte CE message to the primary partition VSP object */ -static int signalCEMsg( char * ceMsg, void * token ) +static int signal_ce_msg(char *ce_msg, struct CeMsgCompleteData *completion) { - struct StackElement * newElement = newStackElement(); - int rc = 0; + struct pending_event *ev = new_pending_event(); - if ( newElement == NULL ) - rc = -ENOMEM; - else { - newElement->event.xHvLpEvent.xSubtype = 0; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('C'<<8)+('E'<<0); - memcpy( newElement->event.xUnion.xCEMsgData.xCEMsg, ceMsg, 12 ); - newElement->event.xUnion.xCEMsgData.xToken = token; - rc = signalEvent(newElement); - } + if (ev == NULL) + return -ENOMEM; - return rc; + ev->event.hp_lp_event.xSubtype = 0; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'C', 'E'); + memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12); + ev->event.data.ce_msg.completion = completion; + return signal_event(ev); } /* * Send a 12-byte CE message and DMA data to the primary partition VSP object */ -static int dmaAndSignalCEMsg( char * ceMsg, void * token, void * dmaData, unsigned dmaDataLength, unsigned remoteAddress ) +static int dma_and_signal_ce_msg(char *ce_msg, + struct CeMsgCompleteData *completion, void *dma_data, + unsigned dma_data_length, unsigned remote_address) { - struct StackElement * newElement = newStackElement(); - int rc = 0; + struct pending_event *ev = new_pending_event(); - if ( newElement == NULL ) - rc = -ENOMEM; - else { - newElement->event.xHvLpEvent.xSubtype = 0; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('C'<<8)+('E'<<0); - memcpy( newElement->event.xUnion.xCEMsgData.xCEMsg, ceMsg, 12 ); - newElement->event.xUnion.xCEMsgData.xToken = token; - memcpy( newElement->dmaData, dmaData, dmaDataLength ); - newElement->dmaDataLength = dmaDataLength; - newElement->remoteAddress = remoteAddress; - rc = signalEvent(newElement); - } + if (ev == NULL) + return -ENOMEM; - return rc; + ev->event.hp_lp_event.xSubtype = 0; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'C', 'E'); + memcpy(ev->event.data.ce_msg.ce_msg, ce_msg, 12); + ev->event.data.ce_msg.completion = completion; + memcpy(ev->dma_data, dma_data, dma_data_length); + ev->dma_data_length = dma_data_length; + ev->remote_address = remote_address; + return signal_event(ev); } /* @@ -401,18 +350,17 @@ static int dmaAndSignalCEMsg( char * ceM * this fails (why?), we'll simply force it off in a not-so-nice * manner. */ -static int shutdown( void ) +static int shutdown(void) { - int rc = kill_proc(1,SIGINT,1); + int rc = kill_proc(1, SIGINT, 1); - if ( rc ) - { - printk( KERN_ALERT "mf.c: SIGINT to init failed (%d), hard shutdown commencing\n", rc ); + if (rc) { + printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), " + "hard shutdown commencing\n", rc); mf_powerOff(); - } - else - printk( KERN_INFO "mf.c: init has been successfully notified to proceed with shutdown\n" ); - + } else + printk(KERN_INFO "mf.c: init has been successfully notified " + "to proceed with shutdown\n"); return rc; } @@ -420,67 +368,64 @@ static int shutdown( void ) * The primary partition VSP object is sending us a new * event flow. Handle it... */ -static void intReceived( struct IoMFLpEvent * event ) +static void intReceived(struct IoMFLpEvent *event) { int freeIt = 0; - struct StackElement * two = NULL; + struct pending_event *two = NULL; + /* ack the interrupt */ - event->xHvLpEvent.xRc = HvLpEvent_Rc_Good; - HvCallEvent_ackLpEvent( &event->xHvLpEvent ); + event->hp_lp_event.xRc = HvLpEvent_Rc_Good; + HvCallEvent_ackLpEvent(&event->hp_lp_event); - /* process interrupt */ - switch( event->xHvLpEvent.xSubtype ) - { + /* process interrupt */ + switch (event->hp_lp_event.xSubtype) { case 0: /* CE message */ - switch( event->xUnion.xCEMsgData.xCEMsg[3] ) - { + switch (event->data.ce_msg.ce_msg[3]) { case 0x5B: /* power control notification */ - if ( (event->xUnion.xCEMsgData.xCEMsg[5]&0x20) != 0 ) - { - printk( KERN_INFO "mf.c: Commencing partition shutdown\n" ); - if ( shutdown() == 0 ) - signalCEMsg( "\x00\x00\x00\xDB\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); + if ((event->data.ce_msg.ce_msg[5] & 0x20) != 0) { + printk(KERN_INFO "mf.c: Commencing partition shutdown\n"); + if (shutdown() == 0) + signal_ce_msg("\x00\x00\x00\xDB\x00\x00\x00\x00\x00\x00\x00\x00", NULL); } break; case 0xC0: /* get time */ - { - if ( (head != NULL) && ( head->event.xUnion.xCEMsgData.xCEMsg[3] == 0x40 ) ) - { - freeIt = 1; - if ( head->event.xUnion.xCEMsgData.xToken != 0 ) - { - CeMsgCompleteHandler xHdlr = head->event.xUnion.xCEMsgData.xToken->xHdlr; - void * token = head->event.xUnion.xCEMsgData.xToken->xToken; + if ((pending_event_head == NULL) || + (pending_event_head->event.data.ce_msg.ce_msg[3] + != 0x40)) + break; + freeIt = 1; + if (pending_event_head->event.data.ce_msg.completion != 0) { + CeMsgCompleteHandler handler = pending_event_head->event.data.ce_msg.completion->handler; + void *token = pending_event_head->event.data.ce_msg.completion->token; - if (xHdlr != NULL) - (*xHdlr)( token, &(event->xUnion.xCEMsgData) ); - } - } + if (handler != NULL) + (*handler)(token, &(event->data.ce_msg)); } break; } /* remove from queue */ - if ( freeIt == 1 ) - { + if (freeIt == 1) { unsigned long flags; - spin_lock_irqsave( &spinlock, flags ); - if ( head != NULL ) - { - struct StackElement *oldHead = head; - head = head->next; - two = head; - free( oldHead ); + + spin_lock_irqsave(&pending_event_spinlock, flags); + if (pending_event_head != NULL) { + struct pending_event *oldHead = + pending_event_head; + + pending_event_head = pending_event_head->next; + two = pending_event_head; + free_pending_event(oldHead); } - spin_unlock_irqrestore( &spinlock, flags ); + spin_unlock_irqrestore(&pending_event_spinlock, flags); } /* send next waiting event */ - if ( two != NULL ) - signalEvent( NULL ); + if (two != NULL) + signal_event(NULL); break; case 1: /* IT sys shutdown */ - printk( KERN_INFO "mf.c: Commencing system shutdown\n" ); + printk(KERN_INFO "mf.c: Commencing system shutdown\n"); shutdown(); break; } @@ -491,81 +436,74 @@ static void intReceived( struct IoMFLpEv * of a flow we sent to them. If there are other flows queued * up, we must send another one now... */ -static void ackReceived( struct IoMFLpEvent * event ) +static void ackReceived(struct IoMFLpEvent *event) { unsigned long flags; - struct StackElement * two = NULL; + struct pending_event * two = NULL; unsigned long freeIt = 0; - /* handle current event */ - if ( head != NULL ) - { - switch( event->xHvLpEvent.xSubtype ) - { + /* handle current event */ + if (pending_event_head != NULL) { + switch (event->hp_lp_event.xSubtype) { case 0: /* CE msg */ - if ( event->xUnion.xCEMsgData.xCEMsg[3] == 0x40 ) - { - if ( event->xUnion.xCEMsgData.xCEMsg[2] != 0 ) - { + if (event->data.ce_msg.ce_msg[3] == 0x40) { + if (event->data.ce_msg.ce_msg[2] != 0) { freeIt = 1; - if ( head->event.xUnion.xCEMsgData.xToken != 0 ) - { - CeMsgCompleteHandler xHdlr = head->event.xUnion.xCEMsgData.xToken->xHdlr; - void * token = head->event.xUnion.xCEMsgData.xToken->xToken; + if (pending_event_head->event.data.ce_msg.completion + != 0) { + CeMsgCompleteHandler handler = pending_event_head->event.data.ce_msg.completion->handler; + void *token = pending_event_head->event.data.ce_msg.completion->token; - if (xHdlr != NULL) - (*xHdlr)( token, &(event->xUnion.xCEMsgData) ); + if (handler != NULL) + (*handler)(token, &(event->data.ce_msg)); } } - } else { + } else freeIt = 1; - } break; case 4: /* allocate */ case 5: /* deallocate */ - if ( head->hdlr != NULL ) - { - union SafeCast mySafeCast; - mySafeCast.ptrAsU64 = event->xHvLpEvent.xCorrelationToken; - (*head->hdlr)( mySafeCast.ptr, event->xUnion.xAllocData.xCount ); + if (pending_event_head->hdlr != NULL) { + union safe_cast mySafeCast; + + mySafeCast.ptr_as_u64 = event->hp_lp_event.xCorrelationToken; + (*pending_event_head->hdlr)(mySafeCast.ptr, event->data.alloc.count); } freeIt = 1; break; case 6: { - struct VspRspData *rsp = (struct VspRspData *)event->xUnion.xVspCmd.xTokenUnion.ptr; + struct VspRspData *rsp = (struct VspRspData *)event->data.vsp_cmd.token.ptr; - if (rsp != NULL) - { - if (rsp->xResponse != NULL) - memcpy(rsp->xResponse, &(event->xUnion.xVspCmd), sizeof(event->xUnion.xVspCmd)); - if (rsp->xSemaphore != NULL) - up(rsp->xSemaphore); - } else { - printk( KERN_ERR "mf.c: no rsp\n"); - } + if (rsp != NULL) { + if (rsp->response != NULL) + memcpy(rsp->response, &(event->data.vsp_cmd), sizeof(event->data.vsp_cmd)); + if (rsp->sem != NULL) + up(rsp->sem); + } else + printk(KERN_ERR "mf.c: no rsp\n"); freeIt = 1; } break; } } else - printk( KERN_ERR "mf.c: stack empty for receiving ack\n" ); + printk(KERN_ERR "mf.c: stack empty for receiving ack\n"); - /* remove from queue */ - spin_lock_irqsave( &spinlock, flags ); - if (( head != NULL ) && ( freeIt == 1 )) - { - struct StackElement *oldHead = head; - head = head->next; - two = head; - free( oldHead ); + /* remove from queue */ + spin_lock_irqsave(&pending_event_spinlock, flags); + if ((pending_event_head != NULL) && (freeIt == 1)) { + struct pending_event *oldHead = pending_event_head; + + pending_event_head = pending_event_head->next; + two = pending_event_head; + free_pending_event(oldHead); } - spin_unlock_irqrestore( &spinlock, flags ); + spin_unlock_irqrestore(&pending_event_spinlock, flags); - /* send next waiting event */ - if ( two != NULL ) - signalEvent( NULL ); + /* send next waiting event */ + if (two != NULL) + signal_event(NULL); } /* @@ -574,101 +512,94 @@ static void ackReceived( struct IoMFLpEv * parse it enough to know if it is an interrupt or an * acknowledge. */ -static void hvHandler( struct HvLpEvent * event, struct pt_regs * regs ) +static void hvHandler(struct HvLpEvent *event, struct pt_regs *regs) { - if ( (event != NULL) && (event->xType == HvLpEvent_Type_MachineFac) ) - { - switch( event->xFlags.xFunction ) - { + if ((event != NULL) && (event->xType == HvLpEvent_Type_MachineFac)) { + switch(event->xFlags.xFunction) { case HvLpEvent_Function_Ack: - ackReceived( (struct IoMFLpEvent *)event ); + ackReceived((struct IoMFLpEvent *)event); break; case HvLpEvent_Function_Int: - intReceived( (struct IoMFLpEvent *)event ); + intReceived((struct IoMFLpEvent *)event); break; default: - printk( KERN_ERR "mf.c: non ack/int event received\n" ); + printk(KERN_ERR "mf.c: non ack/int event received\n"); break; } - } - else - printk( KERN_ERR "mf.c: alien event received\n" ); + } else + printk(KERN_ERR "mf.c: alien event received\n"); } /* * Global kernel interface to allocate and seed events into the * Hypervisor. */ -void mf_allocateLpEvents( HvLpIndex targetLp, - HvLpEvent_Type type, - unsigned size, - unsigned count, - MFCompleteHandler hdlr, - void * userToken ) +void mf_allocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned size, unsigned count, MFCompleteHandler hdlr, + void *userToken) { - struct StackElement * newElement = newStackElement(); - int rc = 0; + struct pending_event *ev = new_pending_event(); + int rc; - if ( newElement == NULL ) + if (ev == NULL) { rc = -ENOMEM; - else { - union SafeCast mine; + } else { + union safe_cast mine; + mine.ptr = userToken; - newElement->event.xHvLpEvent.xSubtype = 4; - newElement->event.xHvLpEvent.xCorrelationToken = mine.ptrAsU64; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('M'<<8)+('A'<<0); - newElement->event.xUnion.xAllocData.xTargetLp = targetLp; - newElement->event.xUnion.xAllocData.xType = type; - newElement->event.xUnion.xAllocData.xSize = size; - newElement->event.xUnion.xAllocData.xCount = count; - newElement->hdlr = hdlr; - rc = signalEvent(newElement); + ev->event.hp_lp_event.xSubtype = 4; + ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'M', 'A'); + ev->event.data.alloc.target_lp = targetLp; + ev->event.data.alloc.type = type; + ev->event.data.alloc.size = size; + ev->event.data.alloc.count = count; + ev->hdlr = hdlr; + rc = signal_event(ev); } - - if ( (rc != 0) && (hdlr != NULL) ) - (*hdlr)( userToken, rc ); + if ((rc != 0) && (hdlr != NULL)) + (*hdlr)(userToken, rc); } /* * Global kernel interface to unseed and deallocate events already in * Hypervisor. */ -void mf_deallocateLpEvents( HvLpIndex targetLp, - HvLpEvent_Type type, - unsigned count, - MFCompleteHandler hdlr, - void * userToken ) +void mf_deallocateLpEvents(HvLpIndex targetLp, HvLpEvent_Type type, + unsigned count, MFCompleteHandler hdlr, void *userToken) { - struct StackElement * newElement = newStackElement(); - int rc = 0; + struct pending_event *ev = new_pending_event(); + int rc; - if ( newElement == NULL ) + if (ev == NULL) rc = -ENOMEM; else { - union SafeCast mine; + union safe_cast mine; + mine.ptr = userToken; - newElement->event.xHvLpEvent.xSubtype = 5; - newElement->event.xHvLpEvent.xCorrelationToken = mine.ptrAsU64; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('M'<<8)+('D'<<0); - newElement->event.xUnion.xAllocData.xTargetLp = targetLp; - newElement->event.xUnion.xAllocData.xType = type; - newElement->event.xUnion.xAllocData.xCount = count; - newElement->hdlr = hdlr; - rc = signalEvent(newElement); + ev->event.hp_lp_event.xSubtype = 5; + ev->event.hp_lp_event.xCorrelationToken = mine.ptr_as_u64; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'M', 'D'); + ev->event.data.alloc.target_lp = targetLp; + ev->event.data.alloc.type = type; + ev->event.data.alloc.count = count; + ev->hdlr = hdlr; + rc = signal_event(ev); } - - if ( (rc != 0) && (hdlr != NULL) ) - (*hdlr)( userToken, rc ); + if ((rc != 0) && (hdlr != NULL)) + (*hdlr)(userToken, rc); } /* * Global kernel interface to tell the VSP object in the primary * partition to power this partition off. */ -void mf_powerOff( void ) +void mf_powerOff(void) { - printk( KERN_INFO "mf.c: Down it goes...\n" ); - signalCEMsg( "\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); + printk(KERN_INFO "mf.c: Down it goes...\n"); + signal_ce_msg("\x00\x00\x00\x4D\x00\x00\x00\x00\x00\x00\x00\x00", NULL); for (;;); } @@ -676,111 +607,104 @@ void mf_powerOff( void ) * Global kernel interface to tell the VSP object in the primary * partition to reboot this partition. */ -void mf_reboot( void ) +void mf_reboot(void) { - printk( KERN_INFO "mf.c: Preparing to bounce...\n" ); - signalCEMsg( "\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); + printk(KERN_INFO "mf.c: Preparing to bounce...\n"); + signal_ce_msg("\x00\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x00", NULL); for (;;); } /* * Display a single word SRC onto the VSP control panel. */ -void mf_displaySrc( u32 word ) +void mf_displaySrc(u32 word) { u8 ce[12]; - memcpy( ce, "\x00\x00\x00\x4A\x00\x00\x00\x01\x00\x00\x00\x00", 12 ); - ce[8] = word>>24; - ce[9] = word>>16; - ce[10] = word>>8; + memcpy(ce, "\x00\x00\x00\x4A\x00\x00\x00\x01\x00\x00\x00\x00", 12); + ce[8] = word >> 24; + ce[9] = word >> 16; + ce[10] = word >> 8; ce[11] = word; - signalCEMsg( ce, NULL ); + signal_ce_msg(ce, NULL); } /* * Display a single word SRC of the form "PROGXXXX" on the VSP control panel. */ -void mf_displayProgress( u16 value ) +void mf_displayProgress(u16 value) { u8 ce[12]; u8 src[72]; - memcpy( ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12 ); - memcpy( src, - "\x01\x00\x00\x01" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "\x00\x00\x00\x00" - "PROGxxxx" - " ", - 72 ); - src[6] = value>>8; - src[7] = value&255; - src[44] = "0123456789ABCDEF"[(value>>12)&15]; - src[45] = "0123456789ABCDEF"[(value>>8)&15]; - src[46] = "0123456789ABCDEF"[(value>>4)&15]; - src[47] = "0123456789ABCDEF"[value&15]; - dmaAndSignalCEMsg( ce, NULL, src, sizeof(src), 9*64*1024 ); + memcpy(ce, "\x00\x00\x04\x4A\x00\x00\x00\x48\x00\x00\x00\x00", 12); + memcpy(src, "\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + "\x00\x00\x00\x00PROGxxxx ", + 72); + src[6] = value >> 8; + src[7] = value & 255; + src[44] = "0123456789ABCDEF"[(value >> 12) & 15]; + src[45] = "0123456789ABCDEF"[(value >> 8) & 15]; + src[46] = "0123456789ABCDEF"[(value >> 4) & 15]; + src[47] = "0123456789ABCDEF"[value & 15]; + dma_and_signal_ce_msg(ce, NULL, src, sizeof(src), 9 * 64 * 1024); } /* * Clear the VSP control panel. Used to "erase" an SRC that was * previously displayed. */ -void mf_clearSrc( void ) +void mf_clearSrc(void) { - signalCEMsg( "\x00\x00\x00\x4B\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); + signal_ce_msg("\x00\x00\x00\x4B\x00\x00\x00\x00\x00\x00\x00\x00", NULL); } /* * Initialization code here. */ -void mf_init( void ) +void mf_init(void) { int i; - /* initialize */ - spin_lock_init( &spinlock ); - for ( i = 0; i < sizeof(prealloc)/sizeof(*prealloc); ++i ) - free( &prealloc[i] ); - HvLpEvent_registerHandler( HvLpEvent_Type_MachineFac, &hvHandler ); + /* initialize */ + spin_lock_init(&pending_event_spinlock); + for (i = 0; + i < sizeof(pending_event_prealloc) / sizeof(*pending_event_prealloc); + ++i) + free_pending_event(&pending_event_prealloc[i]); + HvLpEvent_registerHandler(HvLpEvent_Type_MachineFac, &hvHandler); /* virtual continue ack */ - signalCEMsg( "\x00\x00\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00", NULL ); + signal_ce_msg("\x00\x00\x00\x57\x00\x00\x00\x00\x00\x00\x00\x00", NULL); /* initialization complete */ - printk( KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities initialized\n" ); + printk(KERN_NOTICE "mf.c: iSeries Linux LPAR Machine Facilities initialized\n"); iSeries_proc_callback(&mf_proc_init); } void mf_setSide(char side) { - int rc = 0; - u64 newSide = 0; + u64 newSide; struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); - if (side == 'A') - newSide = 0; - else if (side == 'B') - newSide = 1; - else if (side == 'C') - newSide = 2; - else - newSide = 3; - - myVspCmd.xSubData.xFunction02SelectIplTypeIn.xIplType = newSide; - myVspCmd.xCmd = 10; + switch (side) { + case 'A': newSide = 0; + break; + case 'B': newSide = 1; + break; + case 'C': newSide = 2; + break; + default: newSide = 3; + break; + } + myVspCmd.sub_data.ipl_type = newSide; + myVspCmd.cmd = 10; - rc = signalVspInstruction(&myVspCmd); + (void)signal_vsp_instruction(&myVspCmd); } char mf_getSide(void) @@ -790,91 +714,82 @@ char mf_getSide(void) struct VspCmdData myVspCmd; memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.xCmd = 2; - myVspCmd.xSubData.xFunction02SelectIplTypeIn.xIplType = 0; + myVspCmd.cmd = 2; + myVspCmd.sub_data.ipl_type = 0; mb(); - rc = signalVspInstruction(&myVspCmd); + rc = signal_vsp_instruction(&myVspCmd); if (rc != 0) - { return returnValue; - } else { - if (myVspCmd.xRc == 0) - { - if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 0) - returnValue = 'A'; - else if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 1) - returnValue = 'B'; - else if (myVspCmd.xSubData.xGetIplTypeOut.xIplType == 2) - returnValue = 'C'; - else - returnValue = 'D'; + + if (myVspCmd.result_code == 0) { + switch (myVspCmd.sub_data.ipl_type) { + case 0: returnValue = 'A'; + break; + case 1: returnValue = 'B'; + break; + case 2: returnValue = 'C'; + break; + default: returnValue = 'D'; + break; } } - return returnValue; } void mf_getSrcHistory(char *buffer, int size) { - /* struct IplTypeReturnStuff returnStuff; - struct StackElement * newElement = newStackElement(); - int rc = 0; - char *pages[4]; - - pages[0] = kmalloc(4096, GFP_ATOMIC); - pages[1] = kmalloc(4096, GFP_ATOMIC); - pages[2] = kmalloc(4096, GFP_ATOMIC); - pages[3] = kmalloc(4096, GFP_ATOMIC); - if (( newElement == NULL ) || (pages[0] == NULL) || (pages[1] == NULL) || (pages[2] == NULL) || (pages[3] == NULL)) - rc = -ENOMEM; - else - { - returnStuff.xType = 0; - returnStuff.xRc = 0; - returnStuff.xDone = 0; - newElement->event.xHvLpEvent.xSubtype = 6; - newElement->event.xHvLpEvent.x.xSubtypeData = ('M'<<24)+('F'<<16)+('V'<<8)+('I'<<0); - newElement->event.xUnion.xVspCmd.xEvent = &returnStuff; - newElement->event.xUnion.xVspCmd.xCmd = 4; - newElement->event.xUnion.xVspCmd.xLpIndex = HvLpConfig_getLpIndex(); - newElement->event.xUnion.xVspCmd.xRc = 0xFF; - newElement->event.xUnion.xVspCmd.xReserved1 = 0; - newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[0] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[0])); - newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[1] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[1])); - newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[2] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[2])); - newElement->event.xUnion.xVspCmd.xSubData.xGetSrcHistoryIn.xPage[3] = (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[3])); - mb(); - rc = signalEvent(newElement); - } - - if (rc != 0) - { - return; - } - else - { - while (returnStuff.xDone != 1) - { - udelay(10); - } - - if (returnStuff.xRc == 0) - { - memcpy(buffer, pages[0], size); - } - } - - kfree(pages[0]); - kfree(pages[1]); - kfree(pages[2]); - kfree(pages[3]);*/ +#if 0 + struct IplTypeReturnStuff returnStuff; + struct pending_event *ev = new_pending_event(); + int rc = 0; + char *pages[4]; + + pages[0] = kmalloc(4096, GFP_ATOMIC); + pages[1] = kmalloc(4096, GFP_ATOMIC); + pages[2] = kmalloc(4096, GFP_ATOMIC); + pages[3] = kmalloc(4096, GFP_ATOMIC); + if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL) + || (pages[2] == NULL) || (pages[3] == NULL)) + return -ENOMEM; + + returnStuff.xType = 0; + returnStuff.xRc = 0; + returnStuff.xDone = 0; + ev->event.hp_lp_event.xSubtype = 6; + ev->event.hp_lp_event.x.xSubtypeData = + subtype_data('M', 'F', 'V', 'I'); + ev->event.data.vsp_cmd.xEvent = &returnStuff; + ev->event.data.vsp_cmd.cmd = 4; + ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex(); + ev->event.data.vsp_cmd.result_code = 0xFF; + ev->event.data.vsp_cmd.reserved = 0; + ev->event.data.vsp_cmd.sub_data.page[0] = + (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[0])); + ev->event.data.vsp_cmd.sub_data.page[1] = + (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[1])); + ev->event.data.vsp_cmd.sub_data.page[2] = + (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[2])); + ev->event.data.vsp_cmd.sub_data.page[3] = + (0x8000000000000000ULL | virt_to_absolute((unsigned long)pages[3])); + mb(); + if (signal_event(ev) != 0) + return; + + while (returnStuff.xDone != 1) + udelay(10); + if (returnStuff.xRc == 0) + memcpy(buffer, pages[0], size); + kfree(pages[0]); + kfree(pages[1]); + kfree(pages[2]); + kfree(pages[3]); +#endif } void mf_setCmdLine(const char *cmdline, int size, u64 side) { struct VspCmdData myVspCmd; - int rc = 0; dma_addr_t dma_addr = 0; char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); @@ -886,13 +801,13 @@ void mf_setCmdLine(const char *cmdline, copy_from_user(page, cmdline, size); memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.xCmd = 31; - myVspCmd.xSubData.xSetKernelCmdLineIn.xToken = dma_addr; - myVspCmd.xSubData.xSetKernelCmdLineIn.xAddressType = HvLpDma_AddressType_TceIndex; - myVspCmd.xSubData.xSetKernelCmdLineIn.xSide = side; - myVspCmd.xSubData.xSetKernelCmdLineIn.xTransferLength = size; + myVspCmd.cmd = 31; + myVspCmd.sub_data.kern.token = dma_addr; + myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + myVspCmd.sub_data.kern.side = side; + myVspCmd.sub_data.kern.length = size; mb(); - rc = signalVspInstruction(&myVspCmd); + (void)signal_vsp_instruction(&myVspCmd); pci_free_consistent(iSeries_vio_dev, size, page, dma_addr); } @@ -900,31 +815,29 @@ void mf_setCmdLine(const char *cmdline, int mf_getCmdLine(char *cmdline, int *size, u64 side) { struct VspCmdData myVspCmd; - int rc = 0; + int rc; int len = *size; - dma_addr_t dma_addr = pci_map_single(iSeries_vio_dev, cmdline, *size, PCI_DMA_FROMDEVICE); + dma_addr_t dma_addr; - memset(cmdline, 0, *size); + dma_addr = pci_map_single(iSeries_vio_dev, cmdline, len, + PCI_DMA_FROMDEVICE); + memset(cmdline, 0, len); memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.xCmd = 33; - myVspCmd.xSubData.xGetKernelCmdLineIn.xToken = dma_addr; - myVspCmd.xSubData.xGetKernelCmdLineIn.xAddressType = HvLpDma_AddressType_TceIndex; - myVspCmd.xSubData.xGetKernelCmdLineIn.xSide = side; - myVspCmd.xSubData.xGetKernelCmdLineIn.xTransferLength = *size; + myVspCmd.cmd = 33; + myVspCmd.sub_data.kern.token = dma_addr; + myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + myVspCmd.sub_data.kern.side = side; + myVspCmd.sub_data.kern.length = len; mb(); - rc = signalVspInstruction(&myVspCmd); - - if ( ! rc ) { + rc = signal_vsp_instruction(&myVspCmd); - if (myVspCmd.xRc == 0) - { - len = myVspCmd.xSubData.xGetKernelCmdLineOut.xTransferLength; - } - /* else - { + if (rc == 0) { + if (myVspCmd.result_code == 0) + len = myVspCmd.sub_data.length_out; +#if 0 + else memcpy(cmdline, "Bad cmdline", 11); - } - */ +#endif } pci_unmap_single(iSeries_vio_dev, dma_addr, *size, PCI_DMA_FROMDEVICE); @@ -936,10 +849,8 @@ int mf_getCmdLine(char *cmdline, int *si int mf_setVmlinuxChunk(const char *buffer, int size, int offset, u64 side) { struct VspCmdData myVspCmd; - int rc = 0; - + int rc; dma_addr_t dma_addr = 0; - char *page = pci_alloc_consistent(iSeries_vio_dev, size, &dma_addr); if (page == NULL) { @@ -950,23 +861,19 @@ int mf_setVmlinuxChunk(const char *buffe copy_from_user(page, buffer, size); memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.xCmd = 30; - myVspCmd.xSubData.xGetKernelImageIn.xToken = dma_addr; - myVspCmd.xSubData.xGetKernelImageIn.xAddressType = HvLpDma_AddressType_TceIndex; - myVspCmd.xSubData.xGetKernelImageIn.xSide = side; - myVspCmd.xSubData.xGetKernelImageIn.xOffset = offset; - myVspCmd.xSubData.xGetKernelImageIn.xTransferLength = size; + myVspCmd.cmd = 30; + myVspCmd.sub_data.kern.token = dma_addr; + myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + myVspCmd.sub_data.kern.side = side; + myVspCmd.sub_data.kern.offset = offset; + myVspCmd.sub_data.kern.length = size; mb(); - rc = signalVspInstruction(&myVspCmd); - - if (rc == 0) - { - if (myVspCmd.xRc == 0) - { + rc = signal_vsp_instruction(&myVspCmd); + if (rc == 0) { + if (myVspCmd.result_code == 0) rc = 0; - } else { + else rc = -ENOMEM; - } } pci_free_consistent(iSeries_vio_dev, size, page, dma_addr); @@ -977,31 +884,27 @@ int mf_setVmlinuxChunk(const char *buffe int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side) { struct VspCmdData myVspCmd; - int rc = 0; + int rc; int len = *size; + dma_addr_t dma_addr; - dma_addr_t dma_addr = pci_map_single(iSeries_vio_dev, buffer, *size, PCI_DMA_FROMDEVICE); - + dma_addr = pci_map_single(iSeries_vio_dev, buffer, len, + PCI_DMA_FROMDEVICE); memset(buffer, 0, len); - memset(&myVspCmd, 0, sizeof(myVspCmd)); - myVspCmd.xCmd = 32; - myVspCmd.xSubData.xGetKernelImageIn.xToken = dma_addr; - myVspCmd.xSubData.xGetKernelImageIn.xAddressType = HvLpDma_AddressType_TceIndex; - myVspCmd.xSubData.xGetKernelImageIn.xSide = side; - myVspCmd.xSubData.xGetKernelImageIn.xOffset = offset; - myVspCmd.xSubData.xGetKernelImageIn.xTransferLength = len; + myVspCmd.cmd = 32; + myVspCmd.sub_data.kern.token = dma_addr; + myVspCmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex; + myVspCmd.sub_data.kern.side = side; + myVspCmd.sub_data.kern.offset = offset; + myVspCmd.sub_data.kern.length = len; mb(); - rc = signalVspInstruction(&myVspCmd); - - if (rc == 0) - { - if (myVspCmd.xRc == 0) - { - *size = myVspCmd.xSubData.xGetKernelImageOut.xTransferLength; - } else { + rc = signal_vsp_instruction(&myVspCmd); + if (rc == 0) { + if (myVspCmd.result_code == 0) + *size = myVspCmd.sub_data.length_out; + else rc = -ENOMEM; - } } pci_unmap_single(iSeries_vio_dev, dma_addr, len, PCI_DMA_FROMDEVICE); @@ -1015,12 +918,11 @@ int mf_setRtcTime(unsigned long time) to_tm(time, &tm); - return mf_setRtc( &tm ); + return mf_setRtc(&tm); } -struct RtcTimeData -{ - struct semaphore *xSemaphore; +struct RtcTimeData { + struct semaphore *sem; struct CeMsgData xCeMsg; int xRc; }; @@ -1030,26 +932,23 @@ void getRtcTimeComplete(void * token, st struct RtcTimeData *rtc = (struct RtcTimeData *)token; memcpy(&(rtc->xCeMsg), ceMsg, sizeof(rtc->xCeMsg)); - rtc->xRc = 0; - up(rtc->xSemaphore); + up(rtc->sem); } static unsigned long lastsec = 1; int mf_getRtcTime(unsigned long *time) { -/* unsigned long usec, tsec; */ - u32 dataWord1 = *((u32 *)(&xSpCommArea.xBcdTimeAtIplStart)); u32 dataWord2 = *(((u32 *)&(xSpCommArea.xBcdTimeAtIplStart)) + 1); int year = 1970; - int year1 = ( dataWord1 >> 24 ) & 0x000000FF; - int year2 = ( dataWord1 >> 16 ) & 0x000000FF; - int sec = ( dataWord1 >> 8 ) & 0x000000FF; + int year1 = (dataWord1 >> 24) & 0x000000FF; + int year2 = (dataWord1 >> 16) & 0x000000FF; + int sec = (dataWord1 >> 8) & 0x000000FF; int min = dataWord1 & 0x000000FF; - int hour = ( dataWord2 >> 24 ) & 0x000000FF; - int day = ( dataWord2 >> 8 ) & 0x000000FF; + int hour = (dataWord2 >> 24) & 0x000000FF; + int day = (dataWord2 >> 8) & 0x000000FF; int mon = dataWord2 & 0x000000FF; BCD_TO_BIN(sec); @@ -1062,49 +961,41 @@ int mf_getRtcTime(unsigned long *time) year = year1 * 100 + year2; *time = mktime(year, mon, day, hour, min, sec); - - *time += ( jiffies / HZ ); + *time += (jiffies / HZ); - /* Now THIS is a nasty hack! + /* + * Now THIS is a nasty hack! * It ensures that the first two calls to mf_getRtcTime get different * answers. That way the loop in init_time (time.c) will not think * the clock is stuck. */ - if ( lastsec ) { + if (lastsec) { *time -= lastsec; --lastsec; } - return 0; - } -int mf_getRtc( struct rtc_time * tm ) +int mf_getRtc(struct rtc_time *tm) { - struct CeMsgCompleteData ceComplete; struct RtcTimeData rtcData; - int rc = 0; + int rc; DECLARE_MUTEX_LOCKED(Semaphore); memset(&ceComplete, 0, sizeof(ceComplete)); memset(&rtcData, 0, sizeof(rtcData)); - - rtcData.xSemaphore = &Semaphore; - - ceComplete.xHdlr = &getRtcTimeComplete; - ceComplete.xToken = (void *)&rtcData; - - rc = signalCEMsg( "\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", &ceComplete ); - - if ( rc == 0 ) - { + rtcData.sem = &Semaphore; + ceComplete.handler = &getRtcTimeComplete; + ceComplete.token = (void *)&rtcData; + rc = signal_ce_msg("\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00", + &ceComplete); + if (rc == 0) { down(&Semaphore); - if ( rtcData.xRc == 0) - { - if ( ( rtcData.xCeMsg.xCEMsg[2] == 0xa9 ) || - ( rtcData.xCeMsg.xCEMsg[2] == 0xaf ) ) { + if (rtcData.xRc == 0) { + if ((rtcData.xCeMsg.ce_msg[2] == 0xa9) || + (rtcData.xCeMsg.ce_msg[2] == 0xaf)) { /* TOD clock is not set */ tm->tm_sec = 1; tm->tm_min = 1; @@ -1112,16 +1003,16 @@ int mf_getRtc( struct rtc_time * tm ) tm->tm_mday = 10; tm->tm_mon = 8; tm->tm_year = 71; - mf_setRtc( tm ); + mf_setRtc(tm); } { - u32 dataWord1 = *((u32 *)(rtcData.xCeMsg.xCEMsg+4)); - u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.xCEMsg+8)); - u8 year = (dataWord1 >> 16 ) & 0x000000FF; - u8 sec = ( dataWord1 >> 8 ) & 0x000000FF; + u32 dataWord1 = *((u32 *)(rtcData.xCeMsg.ce_msg+4)); + u32 dataWord2 = *((u32 *)(rtcData.xCeMsg.ce_msg+8)); + u8 year = (dataWord1 >> 16) & 0x000000FF; + u8 sec = (dataWord1 >> 8) & 0x000000FF; u8 min = dataWord1 & 0x000000FF; - u8 hour = ( dataWord2 >> 24 ) & 0x000000FF; - u8 day = ( dataWord2 >> 8 ) & 0x000000FF; + u8 hour = (dataWord2 >> 24) & 0x000000FF; + u8 day = (dataWord2 >> 8) & 0x000000FF; u8 mon = dataWord2 & 0x000000FF; BCD_TO_BIN(sec); @@ -1131,7 +1022,7 @@ int mf_getRtc( struct rtc_time * tm ) BCD_TO_BIN(mon); BCD_TO_BIN(year); - if ( year <= 69 ) + if (year <= 69) year += 100; tm->tm_sec = sec; @@ -1154,17 +1045,14 @@ int mf_getRtc( struct rtc_time * tm ) tm->tm_wday = 0; tm->tm_yday = 0; tm->tm_isdst = 0; - } return rc; - } int mf_setRtc(struct rtc_time * tm) { char ceTime[12] = "\x00\x00\x00\x41\x00\x00\x00\x00\x00\x00\x00\x00"; - int rc = 0; u8 day, mon, hour, min, sec, y1, y2; unsigned year; @@ -1194,10 +1082,5 @@ int mf_setRtc(struct rtc_time * tm) ceTime[10] = day; ceTime[11] = mon; - rc = signalCEMsg( ceTime, NULL ); - - return rc; + return signal_ce_msg(ceTime, NULL); } - - - diff -puN arch/ppc64/kernel/mf_proc.c~linus arch/ppc64/kernel/mf_proc.c --- 25/arch/ppc64/kernel/mf_proc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/mf_proc.c 2004-01-19 22:17:21.000000000 -0800 @@ -16,151 +16,27 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -/* Change Activity: */ -/* End Change Activity */ - -#ifndef _MF_PROC_H -#include -#endif -#ifndef MF_H_INCLUDED -#include -#endif #include +#include static struct proc_dir_entry *mf_proc_root = NULL; -int proc_mf_dump_cmdline -(char *page, char **start, off_t off, int count, int *eof, void *data); - -int proc_mf_dump_vmlinux -(char *page, char **start, off_t off, int count, int *eof, void *data); - -int proc_mf_dump_side -(char *page, char **start, off_t off, int count, int *eof, void *data); - -int proc_mf_change_side -(struct file *file, const char *buffer, unsigned long count, void *data); - -int proc_mf_dump_src -(char *page, char **start, off_t off, int count, int *eof, void *data); -int proc_mf_change_src (struct file *file, const char *buffer, unsigned long count, void *data); -int proc_mf_change_cmdline(struct file *file, const char *buffer, unsigned long count, void *data); -int proc_mf_change_vmlinux(struct file *file, const char *buffer, unsigned long count, void *data); - - -void mf_proc_init(struct proc_dir_entry *iSeries_proc) +static int proc_mf_dump_cmdline(char *page, char **start, off_t off, + int count, int *eof, void *data) { - struct proc_dir_entry *ent = NULL; - struct proc_dir_entry *mf_a = NULL; - struct proc_dir_entry *mf_b = NULL; - struct proc_dir_entry *mf_c = NULL; - struct proc_dir_entry *mf_d = NULL; - - mf_proc_root = proc_mkdir("mf", iSeries_proc); - if (!mf_proc_root) return; - - mf_a = proc_mkdir("A", mf_proc_root); - if (!mf_a) return; - - ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_a); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_mf_dump_cmdline; - ent->write_proc = proc_mf_change_cmdline; - - ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_a); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->write_proc = proc_mf_change_vmlinux; - ent->read_proc = NULL; - - mf_b = proc_mkdir("B", mf_proc_root); - if (!mf_b) return; - - ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_b); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)1; - ent->read_proc = proc_mf_dump_cmdline; - ent->write_proc = proc_mf_change_cmdline; - - ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_b); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)1; - ent->write_proc = proc_mf_change_vmlinux; - ent->read_proc = NULL; - - mf_c = proc_mkdir("C", mf_proc_root); - if (!mf_c) return; - - ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_c); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)2; - ent->read_proc = proc_mf_dump_cmdline; - ent->write_proc = proc_mf_change_cmdline; - - ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_c); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)2; - ent->write_proc = proc_mf_change_vmlinux; - ent->read_proc = NULL; - - mf_d = proc_mkdir("D", mf_proc_root); - if (!mf_d) return; - - - ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_d); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)3; - ent->read_proc = proc_mf_dump_cmdline; - ent->write_proc = proc_mf_change_cmdline; -#if 0 - ent = create_proc_entry("vmlinux", S_IFREG|S_IRUSR, mf_d); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)3; - ent->read_proc = proc_mf_dump_vmlinux; - ent->write_proc = NULL; -#endif - ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_mf_dump_side; - ent->write_proc = proc_mf_change_side; - - ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); - if (!ent) return; - ent->nlink = 1; - ent->data = (void *)0; - ent->read_proc = proc_mf_dump_src; - ent->write_proc = proc_mf_change_src; -} - -int proc_mf_dump_cmdline -(char *page, char **start, off_t off, int count, int *eof, void *data) -{ - int len = count; + int len = count; char *p; len = mf_getCmdLine(page, &len, (u64)data); p = page + len - 1; - while ( p > page ) { - if ( (*p == 0) || (*p == ' ') ) + while (p > page) { + if ((*p == 0) || (*p == ' ')) --p; else break; } - if ( *p != '\n' ) { + if (*p != '\n') { ++p; *p = '\n'; } @@ -179,74 +55,76 @@ int proc_mf_dump_cmdline return len; } -int proc_mf_dump_vmlinux -(char *page, char **start, off_t off, int count, int *eof, void *data) +#if 0 +static int proc_mf_dump_vmlinux(char *page, char **start, off_t off, + int count, int *eof, void *data) { int sizeToGet = count; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) - { - if (sizeToGet != 0) - { + if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) { + if (sizeToGet != 0) { *start = page + off; return sizeToGet; - } else { - *eof = 1; - return 0; } - } else { *eof = 1; return 0; } + *eof = 1; + return 0; } +#endif -int proc_mf_dump_side -(char *page, char **start, off_t off, int count, int *eof, void *data) +static int proc_mf_dump_side(char *page, char **start, off_t off, + int count, int *eof, void *data) { - int len = 0; - + int len; char mf_current_side = mf_getSide(); + len = sprintf(page, "%c\n", mf_current_side); - if (len <= off+count) *eof = 1; + if (len <= (off + count)) + *eof = 1; *start = page + off; len -= off; - if (len>count) len = count; - if (len<0) len = 0; + if (len > count) + len = count; + if (len < 0) + len = 0; return len; } -int proc_mf_change_side(struct file *file, const char *buffer, unsigned long count, void *data) +static int proc_mf_change_side(struct file *file, const char __user *buffer, + unsigned long count, void *data) { char stkbuf[10]; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (count > 9) count = 9; - if (copy_from_user (stkbuf, buffer, count)) { + if (count > (sizeof(stkbuf) - 1)) + count = sizeof(stkbuf) - 1; + if (copy_from_user(stkbuf, buffer, count)) return -EFAULT; - } stkbuf[count] = 0; - if ((*stkbuf != 'A') && - (*stkbuf != 'B') && - (*stkbuf != 'C') && - (*stkbuf != 'D')) - { + if ((*stkbuf != 'A') && (*stkbuf != 'B') && + (*stkbuf != 'C') && (*stkbuf != 'D')) { printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n"); return -EINVAL; } mf_setSide(*stkbuf); - return count; + return count; } -int proc_mf_dump_src -(char *page, char **start, off_t off, int count, int *eof, void *data) +static int proc_mf_dump_src(char *page, char **start, off_t off, + int count, int *eof, void *data) { - int len = 0; + int len; + mf_getSrcHistory(page, count); len = count; len -= off; @@ -260,34 +138,34 @@ int proc_mf_dump_src return len; } -int proc_mf_change_src(struct file *file, const char *buffer, unsigned long count, void *data) +static int proc_mf_change_src(struct file *file, const char __user *buffer, + unsigned long count, void *data) { char stkbuf[10]; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if ((count < 4) && (count != 1)) - { + if ((count < 4) && (count != 1)) { printk(KERN_ERR "mf_proc: invalid src\n"); return -EINVAL; } - if (count > 9) count = 9; - if (copy_from_user (stkbuf, buffer, count)) { + if (count > (sizeof(stkbuf) - 1)) + count = sizeof(stkbuf) - 1; + if (copy_from_user(stkbuf, buffer, count)) return -EFAULT; - } - if ((count == 1) && ((*stkbuf) == '\0')) - { + if ((count == 1) && (*stkbuf == '\0')) mf_clearSrc(); - } else { + else mf_displaySrc(*(u32 *)stkbuf); - } return count; } -int proc_mf_change_cmdline(struct file *file, const char *buffer, unsigned long count, void *data) +static int proc_mf_change_cmdline(struct file *file, const char *buffer, + unsigned long count, void *data) { if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -297,7 +175,8 @@ int proc_mf_change_cmdline(struct file * return count; } -int proc_mf_change_vmlinux(struct file *file, const char *buffer, unsigned long count, void *data) +static int proc_mf_change_vmlinux(struct file *file, const char *buffer, + unsigned long count, void *data) { if (!capable(CAP_SYS_ADMIN)) return -EACCES; @@ -307,3 +186,70 @@ int proc_mf_change_vmlinux(struct file * return count; } + +void mf_proc_init(struct proc_dir_entry *iSeries_proc) +{ + struct proc_dir_entry *ent; + struct proc_dir_entry *mf; + char name[2]; + int i; + + mf_proc_root = proc_mkdir("mf", iSeries_proc); + if (!mf_proc_root) + return; + + name[1] = '\0'; + for (i = 0; i < 4; i++) { + name[0] = 'A' + i; + mf = proc_mkdir(name, mf_proc_root); + if (!mf) + return; + + ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf); + if (!ent) + return; + ent->nlink = 1; + ent->data = (void *)(long)i; + ent->read_proc = proc_mf_dump_cmdline; + ent->write_proc = proc_mf_change_cmdline; + + if (i == 3) /* no vmlinux entry for 'D' */ + continue; + + ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf); + if (!ent) + return; + ent->nlink = 1; + ent->data = (void *)(long)i; +#if 0 + if (i == 3) { + /* + * if we had a 'D' vmlinux entry, it would only + * be readable. + */ + ent->read_proc = proc_mf_dump_vmlinux; + ent->write_proc = NULL; + } else +#endif + { + ent->write_proc = proc_mf_change_vmlinux; + ent->read_proc = NULL; + } + } + + ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + if (!ent) + return; + ent->nlink = 1; + ent->data = (void *)0; + ent->read_proc = proc_mf_dump_side; + ent->write_proc = proc_mf_change_side; + + ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); + if (!ent) + return; + ent->nlink = 1; + ent->data = (void *)0; + ent->read_proc = proc_mf_dump_src; + ent->write_proc = proc_mf_change_src; +} diff -puN arch/ppc64/kernel/misc.S~linus arch/ppc64/kernel/misc.S --- 25/arch/ppc64/kernel/misc.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/misc.S 2004-01-19 22:17:21.000000000 -0800 @@ -66,32 +66,31 @@ _GLOBAL(get_sp) blr #ifdef CONFIG_PPC_ISERIES -/* unsigned long __no_use_save_flags(void) */ -_GLOBAL(__no_use_save_flags) -#warning FIX ISERIES - mfspr r4,SPRG3 - lbz r3,PACAPROCENABLED(r4) +/* unsigned long local_save_flags(void) */ +_GLOBAL(local_get_flags) + lbz r3,PACAPROCENABLED(r13) blr -/* void __no_use_restore_flags(unsigned long flags) */ -_GLOBAL(__no_use_restore_flags) -/* - * Just set/clear the MSR_EE bit through restore/flags but do not - * change anything else. This is needed by the RT system and makes - * sense anyway. - * -- Cort - */ -#warning FIX ISERIES - mfspr r6,SPRG3 - lbz r5,PACAPROCENABLED(r6) +/* unsigned long local_irq_disable(void) */ +_GLOBAL(local_irq_disable) + lbz r3,PACAPROCENABLED(r13) + li r4,0 + stb r4,PACAPROCENABLED(r13) + blr /* Done */ + +/* void local_irq_restore(unsigned long flags) */ +_GLOBAL(local_irq_restore) + lbz r5,PACAPROCENABLED(r13) /* Check if things are setup the way we want _already_. */ cmpw 0,r3,r5 beqlr /* are we enabling interrupts? */ cmpi 0,r3,0 - stb r3,PACAPROCENABLED(r6) + stb r3,PACAPROCENABLED(r13) beqlr /* Check pending interrupts */ + /* A decrementer, IPI or PMC interrupt may have occurred + * while we were in the hypervisor (which enables) */ CHECKANYINT(r4,r5) beqlr @@ -101,35 +100,8 @@ _GLOBAL(__no_use_restore_flags) li r0,0x5555 sc blr +#endif /* CONFIG_PPC_ISERIES */ -_GLOBAL(__no_use_cli) -#warning FIX ISERIES - mfspr r5,SPRG3 - lbz r3,PACAPROCENABLED(r5) - li r4,0 - stb r4,PACAPROCENABLED(r5) - blr /* Done */ - -_GLOBAL(__no_use_sti) -#warning FIX ISERIES - mfspr r6,SPRG3 - li r3,1 - stb r3,PACAPROCENABLED(r6) - - /* Check for pending interrupts - * A decrementer, IPI or PMC interrupt may have occurred - * while we were in the hypervisor (which enables) - */ - CHECKANYINT(r4,r5) - beqlr - - /* - * Handle pending interrupts in interrupt context - */ - li r0,0x5555 - sc - blr -#endif /* * Flush instruction cache. */ @@ -446,7 +418,7 @@ _GLOBAL(cvt_df) blr /* - * identify_cpu, + * identify_cpu and calls setup_cpu * In: r3 = base of the cpu_specs array * r4 = address of cur_cpu_spec * r5 = relocation offset @@ -462,9 +434,17 @@ _GLOBAL(identify_cpu) addi r3,r3,CPU_SPEC_ENTRY_SIZE b 1b 1: - add r3,r3,r5 - std r3,0(r4) - blr + add r0,r3,r5 + std r0,0(r4) + ld r4,CPU_SPEC_SETUP(r3) + sub r4,r4,r5 + ld r4,0(r4) + sub r4,r4,r5 + mtctr r4 + /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ + mr r4,r3 + mr r3,r5 + bctr /* * do_cpu_ftr_fixups - goes through the list of CPU feature fixups @@ -514,25 +494,6 @@ _GLOBAL(do_cpu_ftr_fixups) isync b 1b -/* - * call_setup_cpu - call the setup_cpu function for this cpu - * r3 = data offset - * - * Setup function is called with: - * r3 = data offset - * r4 = ptr to CPU spec (relocated) - */ -_GLOBAL(call_setup_cpu) - LOADADDR(r4, cur_cpu_spec) - sub r4,r4,r3 - lwz r4,0(r4) # load pointer to cpu_spec - sub r4,r4,r3 # relocate - lwz r6,CPU_SPEC_SETUP(r4) # load function pointer - sub r6,r6,r3 - mtctr r6 - bctr - - /* * Create a kernel thread @@ -595,6 +556,10 @@ SYSCALL(dup) SYSCALL(execve) SYSCALL(waitpid) +#ifdef CONFIG_PPC_ISERIES /* hack hack hack */ +#define ppc_rtas sys_ni_syscall +#endif + /* Why isn't this a) automatic, b) written in 'C'? */ .balign 8 _GLOBAL(sys_call_table32) @@ -825,10 +790,10 @@ _GLOBAL(sys_call_table32) .llong .sys_ni_syscall .llong .sys_ni_syscall /* 225 - reserved for tux */ .llong .sys32_sendfile64 - .llong .sys32_io_setup + .llong .compat_sys_io_setup .llong .sys_io_destroy - .llong .sys32_io_getevents - .llong .sys32_io_submit + .llong .compat_sys_io_getevents + .llong .compat_sys_io_submit .llong .sys_io_cancel .llong .sys_set_tid_address .llong .ppc32_fadvise64 @@ -838,20 +803,22 @@ _GLOBAL(sys_call_table32) .llong .sys_epoll_ctl .llong .sys_epoll_wait .llong .sys_remap_file_pages - .llong .sys_ni_syscall /* 240 */ - .llong .sys_ni_syscall - .llong .sys_ni_syscall - .llong .sys_ni_syscall - .llong .sys_ni_syscall - .llong .sys_ni_syscall /* 245 */ - .llong .sys_ni_syscall - .llong .sys_ni_syscall - .llong .sys_ni_syscall - .llong .sys_ni_syscall + .llong .ppc32_timer_create /* 240 */ + .llong .compat_timer_settime + .llong .compat_timer_gettime + .llong .sys_timer_getoverrun + .llong .sys_timer_delete + .llong .compat_clock_settime /* 245 */ + .llong .compat_clock_gettime + .llong .compat_clock_getres + .llong .compat_clock_nanosleep + .llong .ppc32_swapcontext .llong .sys32_tgkill /* 250 */ .llong .sys32_utimes - .llong .sys_statfs64 - .llong .sys_fstatfs64 + .llong .compat_statfs64 + .llong .compat_fstatfs64 + .llong .ppc32_fadvise64_64 /* 32bit only fadvise64_64 */ + .llong .ppc_rtas /* 255 */ .balign 8 _GLOBAL(sys_call_table) @@ -1104,8 +1071,10 @@ _GLOBAL(sys_call_table) .llong .sys_clock_gettime .llong .sys_clock_getres .llong .sys_clock_nanosleep - .llong .sys_ni_syscall + .llong .ppc64_swapcontext .llong .sys_tgkill /* 250 */ .llong .sys_utimes .llong .sys_statfs64 .llong .sys_fstatfs64 + .llong .sys_ni_syscall /* 32bit only fadvise64_64 */ + .llong .ppc_rtas /* 255 */ diff -puN arch/ppc64/kernel/module.c~linus arch/ppc64/kernel/module.c --- 25/arch/ppc64/kernel/module.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/module.c 2004-01-19 22:17:21.000000000 -0800 @@ -404,10 +404,6 @@ int module_finalize(const Elf_Ehdr *hdr, */ list_add(&me->arch.bug_list, &module_bug_list); - sort_ex_table((struct exception_table_entry *)me->extable, - (struct exception_table_entry *)me->extable + - me->num_exentries); - return 0; } diff -puN arch/ppc64/kernel/nvram.c~linus arch/ppc64/kernel/nvram.c --- 25/arch/ppc64/kernel/nvram.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/nvram.c 2004-01-19 22:17:21.000000000 -0800 @@ -20,23 +20,50 @@ #include #include #include +#include +#include #include #include #include #include +#include -static unsigned int rtas_nvram_size; +#define DEBUG_NVRAM + +static int nvram_scan_partitions(void); +static int nvram_setup_partition(void); +static int nvram_create_os_partition(void); +static int nvram_remove_os_partition(void); +static unsigned char nvram_checksum(struct nvram_header *p); +static int nvram_write_header(struct nvram_partition * part); + +static unsigned int nvram_size; static unsigned int nvram_fetch, nvram_store; -static char nvram_buf[4]; /* assume this is in the first 4GB */ +static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ +static struct nvram_partition * nvram_part; +static long nvram_error_log_index = -1; +static long nvram_error_log_size = 0; +static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; + +volatile int no_more_logging = 1; /* Until we initialize everything, + * make sure we don't try logging + * anything */ + +extern volatile int error_log_cnt; + +struct err_log_info { + int error_type; + unsigned int seq_num; +}; -static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) +static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) { switch (origin) { case 1: offset += file->f_pos; break; case 2: - offset += rtas_nvram_size; + offset += nvram_size; break; } if (offset < 0) @@ -46,53 +73,76 @@ static loff_t nvram_llseek(struct file * } -static ssize_t read_nvram(struct file *file, char *buf, +static ssize_t dev_nvram_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - unsigned int i; - unsigned long len; - char *p = buf; + ssize_t len; + char *tmp_buffer; if (verify_area(VERIFY_WRITE, buf, count)) return -EFAULT; - if (*ppos >= rtas_nvram_size) + if (*ppos >= nvram_size) return 0; - for (i = *ppos; count > 0 && i < rtas_nvram_size; ++i, ++p, --count) { - if ((rtas_call(nvram_fetch, 3, 2, &len, i, __pa(nvram_buf), 1) != 0) || - len != 1) - return -EIO; - if (__put_user(nvram_buf[0], p)) - return -EFAULT; + if (count > nvram_size) + count = nvram_size; + + tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); + if (!tmp_buffer) { + printk(KERN_ERR "dev_read_nvram: kmalloc failed\n"); + return -ENOMEM; } - *ppos = i; - return p - buf; + + len = ppc_md.nvram_read(tmp_buffer, count, ppos); + if ((long)len <= 0) { + kfree(tmp_buffer); + return len; + } + + if (copy_to_user(buf, tmp_buffer, len)) { + kfree(tmp_buffer); + return -EFAULT; + } + + kfree(tmp_buffer); + return len; + } -static ssize_t write_nvram(struct file *file, const char *buf, +static ssize_t dev_nvram_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { - unsigned int i; - unsigned long len; - const char *p = buf; - char c; + ssize_t len; + char * tmp_buffer; if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; - if (*ppos >= rtas_nvram_size) + if (*ppos >= nvram_size) return 0; - for (i = *ppos; count > 0 && i < rtas_nvram_size; ++i, ++p, --count) { - if (__get_user(c, p)) - return -EFAULT; - nvram_buf[0] = c; - if ((rtas_call(nvram_store, 3, 2, &len, i, __pa(nvram_buf), 1) != 0) || - len != 1) - return -EIO; + if (count > nvram_size) + count = nvram_size; + + tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); + if (!tmp_buffer) { + printk(KERN_ERR "dev_nvram_write: kmalloc failed\n"); + return -ENOMEM; } - *ppos = i; - return p - buf; + + if (copy_from_user(tmp_buffer, buf, count)) { + kfree(tmp_buffer); + return -EFAULT; + } + + len = ppc_md.nvram_write(tmp_buffer, count, ppos); + if ((long)len <= 0) { + kfree(tmp_buffer); + return len; + } + + kfree(tmp_buffer); + return len; } -static int nvram_ioctl(struct inode *inode, struct file *file, +static int dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return -EINVAL; @@ -100,10 +150,10 @@ static int nvram_ioctl(struct inode *ino struct file_operations nvram_fops = { .owner = THIS_MODULE, - .llseek = nvram_llseek, - .read = read_nvram, - .write = write_nvram, - .ioctl = nvram_ioctl, + .llseek = dev_nvram_llseek, + .read = dev_nvram_read, + .write = dev_nvram_write, + .ioctl = dev_nvram_ioctl, }; static struct miscdevice nvram_dev = { @@ -112,21 +162,135 @@ static struct miscdevice nvram_dev = { &nvram_fops }; +ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + char *p = buf; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + memcpy(p, nvram_buf, len); + + p += len; + i += len; + } + + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + +ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + const char *p = buf; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + memcpy(nvram_buf, p, len); + + if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + p += len; + i += len; + } + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + int __init nvram_init(void) { struct device_node *nvram; unsigned int *nbytes_p, proplen; - if ((nvram = find_type_devices("nvram")) != NULL) { + int error; + int rc; + + if ((nvram = of_find_node_by_type(NULL, "nvram")) != NULL) { nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); if (nbytes_p && proplen == sizeof(unsigned int)) { - rtas_nvram_size = *nbytes_p; + nvram_size = *nbytes_p; + } else { + return -EIO; } } nvram_fetch = rtas_token("nvram-fetch"); nvram_store = rtas_token("nvram-store"); - printk(KERN_INFO "PPC64 nvram contains %d bytes\n", rtas_nvram_size); + printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); + of_node_put(nvram); + + rc = misc_register(&nvram_dev); + + /* If we don't know how big NVRAM is then we shouldn't touch + the nvram partitions */ + if (nvram == NULL) { + return rc; + } + + /* initialize our anchor for the nvram partition list */ + nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!nvram_part) { + printk(KERN_ERR "nvram_init: Failed kmalloc\n"); + return -ENOMEM; + } + INIT_LIST_HEAD(&nvram_part->partition); + + /* Get all the NVRAM partitions */ + error = nvram_scan_partitions(); + if (error) { + printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); + return error; + } + + if(nvram_setup_partition()) + printk(KERN_WARNING "nvram_init: Could not find nvram partition" + " for nvram buffered error logging.\n"); + +#ifdef DEBUG_NVRAM + nvram_print_partitions("NVRAM Partitions"); +#endif - return misc_register(&nvram_dev); + return rc; } void __exit nvram_cleanup(void) @@ -134,6 +298,444 @@ void __exit nvram_cleanup(void) misc_deregister( &nvram_dev ); } +static int nvram_scan_partitions(void) +{ + loff_t cur_index = 0; + struct nvram_header phead; + struct nvram_partition * tmp_part; + unsigned char c_sum; + char * header; + long size; + + header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); + if (!header) { + printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); + return -ENOMEM; + } + + while (cur_index < nvram_size) { + + size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); + if (size != NVRAM_HEADER_LEN) { + printk(KERN_ERR "nvram_scan_partitions: Error parsing " + "nvram partitions\n"); + kfree(header); + return size; + } + + cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ + + memcpy(&phead, header, NVRAM_HEADER_LEN); + + c_sum = nvram_checksum(&phead); + if (c_sum != phead.checksum) + printk(KERN_WARNING "WARNING: nvram partition checksum " + "was %02x, should be %02x!\n", phead.checksum, c_sum); + + tmp_part = (struct nvram_partition *) + kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!tmp_part) { + printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); + kfree(header); + return -ENOMEM; + } + + memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); + tmp_part->index = cur_index; + list_add_tail(&tmp_part->partition, &nvram_part->partition); + + cur_index += phead.length * NVRAM_BLOCK_LEN; + } + + kfree(header); + return 0; +} + +/* nvram_setup_partition + * + * This will setup the partition we need for buffering the + * error logs and cleanup partitions if needed. + * + * The general strategy is the following: + * 1.) If there is ppc64,linux partition large enough then use it. + * 2.) If there is not a ppc64,linux partition large enough, search + * for a free partition that is large enough. + * 3.) If there is not a free partition large enough remove + * _all_ OS partitions and consolidate the space. + * 4.) Will first try getting a chunk that will satisfy the maximum + * error log size (NVRAM_MAX_REQ). + * 5.) If the max chunk cannot be allocated then try finding a chunk + * that will satisfy the minum needed (NVRAM_MIN_REQ). + */ +static int nvram_setup_partition(void) +{ + struct list_head * p; + struct nvram_partition * part; + int rc; + + /* see if we have an OS partition that meets our needs. + will try getting the max we need. If not we'll delete + partitions and try again. */ + list_for_each(p, &nvram_part->partition) { + part = list_entry(p, struct nvram_partition, partition); + if (part->header.signature != NVRAM_SIG_OS) + continue; + + if (strcmp(part->header.name, "ppc64,linux")) + continue; + + if (part->header.length >= NVRAM_MIN_REQ) { + /* found our partition */ + nvram_error_log_index = part->index + NVRAM_HEADER_LEN; + nvram_error_log_size = ((part->header.length - 1) * + NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); + return 0; + } + } + + /* try creating a partition with the free space we have */ + rc = nvram_create_os_partition(); + if (!rc) { + return 0; + } + + /* need to free up some space */ + rc = nvram_remove_os_partition(); + if (rc) { + return rc; + } + + /* create a partition in this new space */ + rc = nvram_create_os_partition(); + if (rc) { + printk(KERN_ERR "nvram_create_os_partition: Could not find a " + "NVRAM partition large enough\n"); + return rc; + } + + return 0; +} + +static int nvram_remove_os_partition(void) +{ + struct list_head *i; + struct list_head *j; + struct nvram_partition * part; + struct nvram_partition * cur_part; + int rc; + + list_for_each(i, &nvram_part->partition) { + part = list_entry(i, struct nvram_partition, partition); + if (part->header.signature != NVRAM_SIG_OS) + continue; + + /* Make os partition a free partition */ + part->header.signature = NVRAM_SIG_FREE; + sprintf(part->header.name, "wwwwwwwwwwww"); + part->header.checksum = nvram_checksum(&part->header); + + /* Merge contiguous free partitions backwards */ + list_for_each_prev(j, &part->partition) { + cur_part = list_entry(j, struct nvram_partition, partition); + if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { + break; + } + + part->header.length += cur_part->header.length; + part->header.checksum = nvram_checksum(&part->header); + part->index = cur_part->index; + + list_del(&cur_part->partition); + kfree(cur_part); + j = &part->partition; /* fixup our loop */ + } + + /* Merge contiguous free partitions forwards */ + list_for_each(j, &part->partition) { + cur_part = list_entry(j, struct nvram_partition, partition); + if (cur_part == nvram_part || cur_part->header.signature != NVRAM_SIG_FREE) { + break; + } + + part->header.length += cur_part->header.length; + part->header.checksum = nvram_checksum(&part->header); + + list_del(&cur_part->partition); + kfree(cur_part); + j = &part->partition; /* fixup our loop */ + } + + rc = nvram_write_header(part); + if (rc <= 0) { + printk(KERN_ERR "nvram_remove_os_partition: nvram_write failed (%d)\n", rc); + return rc; + } + + } + + return 0; +} + +/* nvram_create_os_partition + * + * Create a OS linux partition to buffer error logs. + * Will create a partition starting at the first free + * space found if space has enough room. + */ +static int nvram_create_os_partition(void) +{ + struct list_head * p; + struct nvram_partition * part; + struct nvram_partition * new_part = NULL; + struct nvram_partition * free_part; + int seq_init[2] = { 0, 0 }; + loff_t tmp_index; + long size = 0; + int rc; + + /* Find a free partition that will give us the maximum needed size + If can't find one that will give us the minimum size needed */ + list_for_each(p, &nvram_part->partition) { + part = list_entry(p, struct nvram_partition, partition); + if (part->header.signature != NVRAM_SIG_FREE) + continue; + + if (part->header.length >= NVRAM_MAX_REQ) { + size = NVRAM_MAX_REQ; + free_part = part; + break; + } + if (!size && part->header.length >= NVRAM_MIN_REQ) { + size = NVRAM_MIN_REQ; + free_part = part; + } + } + if (!size) { + return -ENOSPC; + } + + /* Create our OS partition */ + new_part = (struct nvram_partition *) + kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!new_part) { + printk(KERN_ERR "nvram_create_os_partition: kmalloc failed\n"); + return -ENOMEM; + } + + new_part->index = free_part->index; + new_part->header.signature = NVRAM_SIG_OS; + new_part->header.length = size; + sprintf(new_part->header.name, "ppc64,linux"); + new_part->header.checksum = nvram_checksum(&new_part->header); + + rc = nvram_write_header(new_part); + if (rc <= 0) { + printk(KERN_ERR "nvram_create_os_partition: nvram_write_header \ + failed (%d)\n", rc); + return rc; + } + + /* make sure and initialize to zero the sequence number and the error + type logged */ + tmp_index = new_part->index + NVRAM_HEADER_LEN; + rc = ppc_md.nvram_write((char *)&seq_init, sizeof(seq_init), &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_create_os_partition: nvram_write failed (%d)\n", rc); + return rc; + } + + nvram_error_log_index = new_part->index + NVRAM_HEADER_LEN; + nvram_error_log_size = ((part->header.length - 1) * + NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); + + list_add_tail(&new_part->partition, &free_part->partition); + + if (free_part->header.length <= size) { + list_del(&free_part->partition); + kfree(free_part); + return 0; + } + + /* Adjust the partition we stole the space from */ + free_part->index += size * NVRAM_BLOCK_LEN; + free_part->header.length -= size; + free_part->header.checksum = nvram_checksum(&free_part->header); + + rc = nvram_write_header(free_part); + if (rc <= 0) { + printk(KERN_ERR "nvram_create_os_partition: nvram_write_header " + "failed (%d)\n", rc); + return rc; + } + + return 0; +} + + +void nvram_print_partitions(char * label) +{ + struct list_head * p; + struct nvram_partition * tmp_part; + + printk(KERN_WARNING "--------%s---------\n", label); + printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); + list_for_each(p, &nvram_part->partition) { + tmp_part = list_entry(p, struct nvram_partition, partition); + printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", + tmp_part->index, tmp_part->header.signature, + tmp_part->header.checksum, tmp_part->header.length, + tmp_part->header.name); + } +} + +/* nvram_write_error_log + * + * We need to buffer the error logs into nvram to ensure that we have + * the failure information to decode. If we have a severe error there + * is no way to guarantee that the OS or the machine is in a state to + * get back to user land and write the error to disk. For example if + * the SCSI device driver causes a Machine Check by writing to a bad + * IO address, there is no way of guaranteeing that the device driver + * is in any state that is would also be able to write the error data + * captured to disk, thus we buffer it in NVRAM for analysis on the + * next boot. + * + * In NVRAM the partition containing the error log buffer will looks like: + * Header (in bytes): + * +-----------+----------+--------+------------+------------------+ + * | signature | checksum | length | name | data | + * |0 |1 |2 3|4 15|16 length-1| + * +-----------+----------+--------+------------+------------------+ + * + * The 'data' section would look like (in bytes): + * +--------------+------------+-----------------------------------+ + * | event_logged | sequence # | error log | + * |0 3|4 7|8 nvram_error_log_size-1| + * +--------------+------------+-----------------------------------+ + * + * event_logged: 0 if event has not been logged to syslog, 1 if it has + * sequence #: The unique sequence # for each event. (until it wraps) + * error log: The error log from event_scan + */ +int nvram_write_error_log(char * buff, int length, unsigned int err_type) +{ + int rc; + loff_t tmp_index; + struct err_log_info info; + + if (no_more_logging) { + return -EPERM; + } + + if (nvram_error_log_index == -1) { + return -ESPIPE; + } + + if (length > nvram_error_log_size) { + length = nvram_error_log_size; + } + + info.error_type = err_type; + info.seq_num = error_log_cnt; + + tmp_index = nvram_error_log_index; + + rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); + return rc; + } + + rc = ppc_md.nvram_write(buff, length, &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc); + return rc; + } + + return 0; +} + +/* nvram_read_error_log + * + * Reads nvram for error log for at most 'length' + */ +int nvram_read_error_log(char * buff, int length, unsigned int * err_type) +{ + int rc; + loff_t tmp_index; + struct err_log_info info; + + if (nvram_error_log_index == -1) + return -1; + + if (length > nvram_error_log_size) + length = nvram_error_log_size; + + tmp_index = nvram_error_log_index; + + rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); + return rc; + } + + rc = ppc_md.nvram_read(buff, length, &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); + return rc; + } + + error_log_cnt = info.seq_num; + *err_type = info.error_type; + + return 0; +} + +/* This doesn't actually zero anything, but it sets the event_logged + * word to tell that this event is safely in syslog. + */ +int nvram_clear_error_log() +{ + loff_t tmp_index; + int clear_word = ERR_FLAG_ALREADY_LOGGED; + int rc; + + tmp_index = nvram_error_log_index; + + rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index); + if (rc <= 0) { + printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc); + return rc; + } + + return 0; +} + +static int nvram_write_header(struct nvram_partition * part) +{ + loff_t tmp_index; + int rc; + + tmp_index = part->index; + rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); + + return rc; +} + +static unsigned char nvram_checksum(struct nvram_header *p) +{ + unsigned int c_sum, c_sum2; + unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ + c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; + + /* The sum may have spilled into the 3rd byte. Fold it back. */ + c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; + /* The sum cannot exceed 2 bytes. Fold it into a checksum */ + c_sum2 = (c_sum >> 8) + (c_sum << 8); + c_sum = ((c_sum + c_sum2) >> 8) & 0xff; + return c_sum; +} + module_init(nvram_init); module_exit(nvram_cleanup); MODULE_LICENSE("GPL"); diff -puN arch/ppc64/kernel/open_pic.c~linus arch/ppc64/kernel/open_pic.c --- 25/arch/ppc64/kernel/open_pic.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/open_pic.c 2004-01-19 22:17:21.000000000 -0800 @@ -85,10 +85,10 @@ unsigned int openpic_vec_spurious; */ #ifdef CONFIG_SMP #define THIS_CPU Processor[cpu] -#define DECL_THIS_CPU int cpu = smp_processor_id() +#define DECL_THIS_CPU int cpu = hard_smp_processor_id() #define CHECK_THIS_CPU check_arg_cpu(cpu) #else -#define THIS_CPU Processor[smp_processor_id()] +#define THIS_CPU Processor[hard_smp_processor_id()] #define DECL_THIS_CPU #define CHECK_THIS_CPU #endif /* CONFIG_SMP */ @@ -142,7 +142,7 @@ void __init openpic_init_IRQ(void) struct device_node *kbd; #endif - if (!(np = find_devices("pci")) + if (!(np = of_find_node_by_name(NULL, "pci")) || !(addrp = (unsigned int *) get_property(np, "8259-interrupt-acknowledge", NULL))) printk(KERN_ERR "Cannot find pci to get ack address\n"); @@ -158,6 +158,7 @@ void __init openpic_init_IRQ(void) openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq); for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ ) irq_desc[i].handler = &i8259_pic; + of_node_put(np); } static inline u_int openpic_read(volatile u_int *addr) @@ -354,7 +355,7 @@ void __init openpic_init(int main_pic, i /* SIOint (8259 cascade) is special */ if (offset) { openpic_initirq(0, 8, offset, 1, 1); - openpic_mapirq(0, 1 << boot_cpuid); + openpic_mapirq(0, 1 << get_hard_smp_processor_id(boot_cpuid)); } /* Init all external sources */ @@ -372,7 +373,7 @@ void __init openpic_init(int main_pic, i /* Enabled, Priority 8 or 9 */ openpic_initirq(i, pri, i+offset, !sense, sense); /* Processor 0 */ - openpic_mapirq(i, 1 << boot_cpuid); + openpic_mapirq(i, 1 << get_hard_smp_processor_id(boot_cpuid)); } /* Init descriptors */ @@ -513,10 +514,23 @@ static void openpic_set_spurious(u_int v vec); } +/* + * Convert a cpu mask from logical to physical cpu numbers. + */ +static inline u32 physmask(u32 cpumask) +{ + int i; + u32 mask = 0; + + for (i = 0; i < NR_CPUS; ++i, cpumask >>= 1) + mask |= (cpumask & 1) << get_hard_smp_processor_id(i); + return mask; +} + void openpic_init_processor(u_int cpumask) { openpic_write(&OpenPIC->Global.Processor_Initialization, - cpumask & cpus_coerce(cpu_online_map)); + physmask(cpumask & cpus_coerce(cpu_online_map))); } #ifdef CONFIG_SMP @@ -550,7 +564,7 @@ void openpic_cause_IPI(u_int ipi, u_int CHECK_THIS_CPU; check_arg_ipi(ipi); openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), - cpumask & cpus_coerce(cpu_online_map)); + physmask(cpumask & cpus_coerce(cpu_online_map))); } void openpic_request_IPIs(void) @@ -591,7 +605,7 @@ void __devinit do_openpic_setup_cpu(void { #ifdef CONFIG_IRQ_ALL_CPUS int i; - u32 msk = 1 << smp_processor_id(); + u32 msk = 1 << hard_smp_processor_id(); #endif spin_lock(&openpic_setup_lock); @@ -636,7 +650,7 @@ static void __init openpic_maptimer(u_in { check_arg_timer(timer); openpic_write(&OpenPIC->Global.Timer[timer].Destination, - cpumask & cpus_coerce(cpu_online_map)); + physmask(cpumask & cpus_coerce(cpu_online_map))); } @@ -762,7 +776,7 @@ static void openpic_set_affinity(unsigne cpumask_t tmp; cpus_and(tmp, cpumask, cpu_online_map); - openpic_mapirq(irq_nr - open_pic_irq_offset, cpus_coerce(tmp)); + openpic_mapirq(irq_nr - open_pic_irq_offset, physmask(cpus_coerce(tmp))); } #ifdef CONFIG_SMP diff -puN arch/ppc64/kernel/pci.c~linus arch/ppc64/kernel/pci.c --- 25/arch/ppc64/kernel/pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -144,7 +144,7 @@ struct pci_dev *pci_find_dev_by_addr(uns return NULL; } -void __devinit +void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, struct resource *res) { @@ -224,7 +224,11 @@ pci_alloc_pci_controller(enum phb_types struct pci_controller *hose; char *model; +#ifdef CONFIG_PPC_ISERIES + hose = (struct pci_controller *)kmalloc(sizeof(struct pci_controller), GFP_KERNEL); +#else hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); +#endif if(hose == NULL) { printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); return NULL; @@ -232,6 +236,11 @@ pci_alloc_pci_controller(enum phb_types memset(hose, 0, sizeof(struct pci_controller)); switch(controller_type) { +#ifdef CONFIG_PPC_ISERIES + case phb_type_hypervisor: + model = "PHB HV"; + break; +#endif case phb_type_python: model = "PHB PY"; break; @@ -280,6 +289,7 @@ static void __init pcibios_claim_one_bus pcibios_claim_one_bus(child_bus); } +#ifndef CONFIG_PPC_ISERIES static void __init pcibios_claim_of_setup(void) { struct list_head *lb; @@ -289,6 +299,7 @@ static void __init pcibios_claim_of_setu pcibios_claim_one_bus(b); } } +#endif static int __init pcibios_init(void) { @@ -311,6 +322,7 @@ static int __init pcibios_init(void) hose->last_busno = bus->subordinate; } +#ifndef CONFIG_PPC_ISERIES if (pci_probe_only) pcibios_claim_of_setup(); else @@ -318,6 +330,7 @@ static int __init pcibios_init(void) pci_assign_unassigned_resources() is able to work correctly with [partially] allocated PCI tree. */ pci_assign_unassigned_resources(); +#endif /* Call machine dependent fixup */ pcibios_final_fixup(); @@ -375,19 +388,27 @@ int pcibios_enable_device(struct pci_dev */ int pci_domain_nr(struct pci_bus *bus) { +#ifdef CONFIG_PPC_ISERIES + return 0; +#else struct pci_controller *hose = PCI_GET_PHB_PTR(bus); return hose->global_number; +#endif } +EXPORT_SYMBOL(pci_domain_nr); + /* Set the name of the bus as it appears in /proc/bus/pci */ int pci_name_bus(char *name, struct pci_bus *bus) { +#ifndef CONFIG_PPC_ISERIES struct pci_controller *hose = PCI_GET_PHB_PTR(bus); if (hose->buid) sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); else +#endif sprintf(name, "%02x", bus->number); return 0; diff -puN arch/ppc64/kernel/pci_dma.c~linus arch/ppc64/kernel/pci_dma.c --- 25/arch/ppc64/kernel/pci_dma.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pci_dma.c 2004-01-19 22:17:21.000000000 -0800 @@ -48,11 +48,13 @@ /* #define MONITOR_TCE 1 */ /* Turn on to sanity check TCE generation. */ +#ifdef CONFIG_PPC_PSERIES /* Initialize so this guy does not end up in the BSS section. * Only used to pass OF initialization data set in prom.c into the main * kernel code -- data ultimately copied into tceTables[]. */ extern struct _of_tce_table of_tce_table[]; +#endif extern struct pci_controller* hose_head; extern struct pci_controller** hose_tail; @@ -553,7 +555,7 @@ inline dma_addr_t get_tces( struct TceTa } #ifdef CONFIG_PPC_ISERIES -static void tce_free_one_iSeries( struct TceTable *tbl, long tcenum ) +void tce_free_one_iSeries( struct TceTable *tbl, long tcenum ) { u64 set_tce_rc; union Tce tce; @@ -701,6 +703,7 @@ void create_tce_tables_for_buses(struct } } +#ifdef CONFIG_PPC_PSERIES void create_tce_tables_for_busesLP(struct list_head *bus_list) { struct list_head *ln; @@ -722,15 +725,19 @@ void create_tce_tables_for_busesLP(struc create_tce_tables_for_busesLP(&bus->children); } } +#endif void create_tce_tables(void) { struct pci_dev *dev = NULL; struct device_node *dn, *mydn; +#ifdef CONFIG_PPC_PSERIES if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { create_tce_tables_for_busesLP(&pci_root_buses); } - else { + else +#endif + { create_tce_tables_for_buses(&pci_root_buses); } /* Now copy the tce_table ptr from the bus devices down to every @@ -884,6 +891,7 @@ static void getTceTableParmsiSeries(stru static void getTceTableParmsPSeries(struct pci_controller *phb, struct device_node *dn, struct TceTable *newTceTable ) { +#ifdef CONFIG_PPC_PSERIES phandle node; unsigned long i; @@ -953,6 +961,7 @@ static void getTceTableParmsPSeries(stru } i++; } +#endif } /* @@ -970,6 +979,7 @@ static void getTceTableParmsPSeries(stru static void getTceTableParmsPSeriesLP(struct pci_controller *phb, struct device_node *dn, struct TceTable *newTceTable ) { +#ifdef CONFIG_PPC_PSERIES u32 *dma_window = (u32 *)get_property(dn, "ibm,dma-window", 0); if (!dma_window) { panic("PCI_DMA: getTceTableParmsPSeriesLP: device %s has no ibm,dma-window property!\n", dn->full_name); @@ -985,6 +995,7 @@ static void getTceTableParmsPSeriesLP(st PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->index = 0x%lx\n", newTceTable->index); PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->startOffset = 0x%lx\n", newTceTable->startOffset); PPCDBG(PPCDBG_TCEINIT, "\tnewTceTable->size = 0x%lx\n", newTceTable->size); +#endif } /* Allocates a contiguous real buffer and creates TCEs over it. diff -puN arch/ppc64/kernel/pci_dn.c~linus arch/ppc64/kernel/pci_dn.c --- 25/arch/ppc64/kernel/pci_dn.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pci_dn.c 2004-01-19 22:17:21.000000000 -0800 @@ -46,6 +46,7 @@ static void * __init update_dn_pci_info(struct device_node *dn, void *data) { +#ifdef CONFIG_PPC_PSERIES struct pci_controller *phb = (struct pci_controller *)data; u32 *regs; char *device_type = get_property(dn, "device_type", 0); @@ -64,6 +65,7 @@ update_dn_pci_info(struct device_node *d dn->devfn = (regs[0] >> 8) & 0xff; } } +#endif return NULL; } @@ -97,6 +99,7 @@ void *traverse_pci_devices(struct device return ret; for (dn = start->child; dn; dn = nextdn) { nextdn = NULL; +#ifdef CONFIG_PPC_PSERIES if (get_property(dn, "class-code", 0)) { if (pre && (ret = pre(dn, data)) != NULL) return ret; @@ -112,6 +115,7 @@ void *traverse_pci_devices(struct device post(dn, data); } } +#endif if (!nextdn) { /* Walk up to next valid sibling. */ do { diff -puN arch/ppc64/kernel/ppc_ksyms.c~linus arch/ppc64/kernel/ppc_ksyms.c --- 25/arch/ppc64/kernel/ppc_ksyms.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/ppc_ksyms.c 2004-01-19 22:17:21.000000000 -0800 @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #include #include @@ -163,21 +164,23 @@ EXPORT_SYMBOL(kernel_thread); EXPORT_SYMBOL(flush_instruction_cache); EXPORT_SYMBOL(_get_PVR); EXPORT_SYMBOL(giveup_fpu); -EXPORT_SYMBOL(enable_kernel_fp); +#ifdef CONFIG_ALTIVEC +EXPORT_SYMBOL(giveup_altivec); +#endif EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(flush_icache_user_range); EXPORT_SYMBOL(flush_dcache_page); #ifdef CONFIG_SMP #ifdef CONFIG_PPC_ISERIES -EXPORT_SYMBOL(__no_use_restore_flags); -EXPORT_SYMBOL(__no_use_save_flags); -EXPORT_SYMBOL(__no_use_sti); -EXPORT_SYMBOL(__no_use_cli); +EXPORT_SYMBOL(local_get_flags); +EXPORT_SYMBOL(local_irq_disable); +EXPORT_SYMBOL(local_irq_restore); #endif #endif EXPORT_SYMBOL(ppc_md); +#ifdef CONFIG_PPC_PSERIES EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); EXPORT_SYMBOL(find_compatible_devices); @@ -186,6 +189,7 @@ EXPORT_SYMBOL(device_is_compatible); EXPORT_SYMBOL(machine_is_compatible); EXPORT_SYMBOL(find_all_nodes); EXPORT_SYMBOL(get_property); +#endif EXPORT_SYMBOL_NOVERS(memcpy); @@ -222,3 +226,4 @@ EXPORT_SYMBOL(debugger_fault_handler); EXPORT_SYMBOL(tb_ticks_per_usec); EXPORT_SYMBOL(paca); +EXPORT_SYMBOL(proc_ppc64); diff -puN arch/ppc64/kernel/process.c~linus arch/ppc64/kernel/process.c --- 25/arch/ppc64/kernel/process.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/process.c 2004-01-19 22:17:21.000000000 -0800 @@ -50,7 +50,10 @@ #include #include +#ifndef CONFIG_SMP struct task_struct *last_task_used_math = NULL; +struct task_struct *last_task_used_altivec = NULL; +#endif struct mm_struct ioremap_mm = { pgd : ioremap_dir ,page_table_lock : SPIN_LOCK_UNLOCKED }; @@ -58,8 +61,7 @@ struct mm_struct ioremap_mm = { pgd char *sysmap = NULL; unsigned long sysmap_size = 0; -void -enable_kernel_fp(void) +void enable_kernel_fp(void) { #ifdef CONFIG_SMP if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) @@ -70,6 +72,7 @@ enable_kernel_fp(void) giveup_fpu(last_task_used_math); #endif /* CONFIG_SMP */ } +EXPORT_SYMBOL(enable_kernel_fp); int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) { @@ -85,6 +88,31 @@ int dump_task_fpu(struct task_struct *ts return 1; } +#ifdef CONFIG_ALTIVEC + +void enable_kernel_altivec(void) +{ +#ifdef CONFIG_SMP + if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) + giveup_altivec(current); + else + giveup_altivec(NULL); /* just enables FP for kernel */ +#else + giveup_altivec(last_task_used_altivec); +#endif /* CONFIG_SMP */ +} +EXPORT_SYMBOL(enable_kernel_altivec); + +int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) +{ + if (regs->msr & MSR_VEC) + giveup_altivec(current); + memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); + return 1; +} + +#endif /* CONFIG_ALTIVEC */ + struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *new) { @@ -104,8 +132,20 @@ struct task_struct *__switch_to(struct t */ if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) giveup_fpu(prev); +#ifdef CONFIG_ALTIVEC + if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) + giveup_altivec(prev); +#endif /* CONFIG_ALTIVEC */ #endif /* CONFIG_SMP */ +#if defined(CONFIG_ALTIVEC) && !defined(CONFIG_SMP) + /* Avoid the trap. On smp this this never happens since + * we don't set last_task_used_altivec -- Cort + */ + if (new->thread.regs && last_task_used_altivec == new) + new->thread.regs->msr |= MSR_VEC; +#endif /* CONFIG_ALTIVEC */ + new_thread = &new->thread; old_thread = ¤t->thread; @@ -158,8 +198,14 @@ void show_regs(struct pt_regs * regs) void exit_thread(void) { +#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = NULL; +#ifdef CONFIG_ALTIVEC + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; +#endif /* CONFIG_ALTIVEC */ +#endif /* CONFIG_SMP */ } void flush_thread(void) @@ -169,8 +215,14 @@ void flush_thread(void) if (t->flags & _TIF_ABI_PENDING) t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); +#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = NULL; +#ifdef CONFIG_ALTIVEC + if (last_task_used_altivec == current) + last_task_used_altivec = NULL; +#endif /* CONFIG_ALTIVEC */ +#endif /* CONFIG_SMP */ } void @@ -178,6 +230,25 @@ release_thread(struct task_struct *t) { } + +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + struct pt_regs *regs = tsk->thread.regs; + + if (regs == NULL) + return; + if (regs->msr & MSR_FP) + giveup_fpu(current); +#ifdef CONFIG_ALTIVEC + if (regs->msr & MSR_VEC) + giveup_altivec(current); +#endif /* CONFIG_ALTIVEC */ +} + /* * Copy a thread.. */ @@ -268,9 +339,25 @@ void start_thread(struct pt_regs *regs, regs->gpr[1] = sp; regs->gpr[2] = toc; regs->msr = MSR_USER64; +#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = 0; +#endif /* CONFIG_SMP */ + memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); current->thread.fpscr = 0; +#ifdef CONFIG_ALTIVEC +#ifndef CONFIG_SMP + if (last_task_used_altivec == current) + last_task_used_altivec = 0; +#endif /* CONFIG_SMP */ + memset(current->thread.vr, 0, sizeof(current->thread.vr)); + current->thread.vscr.u[0] = 0; + current->thread.vscr.u[1] = 0; + current->thread.vscr.u[2] = 0; + current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ + current->thread.vrsave = 0; + current->thread.used_vr = 0; +#endif /* CONFIG_ALTIVEC */ } int set_fpexc_mode(struct task_struct *tsk, unsigned int val) @@ -314,9 +401,6 @@ int sys_clone(unsigned long clone_flags, } } - if (regs->msr & MSR_FP) - giveup_fpu(current); - return do_fork(clone_flags & ~CLONE_IDLETASK, p2, regs, 0, (int *)parent_tidptr, (int *)child_tidptr); } @@ -325,9 +409,6 @@ int sys_fork(unsigned long p1, unsigned unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - if (regs->msr & MSR_FP) - giveup_fpu(current); - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } @@ -335,9 +416,6 @@ int sys_vfork(unsigned long p1, unsigned unsigned long p4, unsigned long p5, unsigned long p6, struct pt_regs *regs) { - if (regs->msr & MSR_FP) - giveup_fpu(current); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); } @@ -355,7 +433,10 @@ int sys_execve(unsigned long a0, unsigne goto out; if (regs->msr & MSR_FP) giveup_fpu(current); - +#ifdef CONFIG_ALTIVEC + if (regs->msr & MSR_VEC) + giveup_altivec(current); +#endif /* CONFIG_ALTIVEC */ error = do_execve(filename, (char **) a1, (char **) a2, regs); if (error == 0) diff -puN arch/ppc64/kernel/proc_pmc.c~linus arch/ppc64/kernel/proc_pmc.c --- 25/arch/ppc64/kernel/proc_pmc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/proc_pmc.c 2004-01-19 22:17:21.000000000 -0800 @@ -44,8 +44,6 @@ static int proc_pmc_control_mode = 0; -static struct proc_dir_entry *proc_ppc64_root = NULL; -static struct proc_dir_entry *proc_ppc64_pmc_root = NULL; static struct proc_dir_entry *proc_ppc64_pmc_system_root = NULL; static struct proc_dir_entry *proc_ppc64_pmc_cpu_root[NR_CPUS] = {NULL, }; @@ -82,8 +80,8 @@ int proc_pmc_set_pmc6( struct file *fil int proc_pmc_set_pmc7( struct file *file, const char *buffer, unsigned long count, void *data); int proc_pmc_set_pmc8( struct file *file, const char *buffer, unsigned long count, void *data); - -void proc_ppc64_init(void) +#if 0 +int proc_ppc64_init(void) { unsigned long i; struct proc_dir_entry *ent = NULL; @@ -97,15 +95,21 @@ void proc_ppc64_init(void) * /proc/ppc64/pmc/cpu0 */ spin_lock(&proc_ppc64_lock); - proc_ppc64_root = proc_mkdir("ppc64", 0); - if (!proc_ppc64_root) return; + if (proc_ppc64.root == NULL) { + proc_ppc64_init(); + if (!proc_ppc64.root) { + spin_unlock(&proc_ppc64_lock); + return; + } + } spin_unlock(&proc_ppc64_lock); /* Placeholder for rtas interfaces. */ - rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root); - + if (proc_ppc64.rtas == NULL) { + return; + } - proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root); + proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64.root); proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root); for (i = 0; i < NR_CPUS; i++) { @@ -116,7 +120,6 @@ void proc_ppc64_init(void) } } - /* Create directories for the software counters. */ for (i = 0; i < NR_CPUS; i++) { if (!cpu_online(i)) @@ -181,6 +184,7 @@ void proc_ppc64_init(void) ent->write_proc = NULL; } } +#endif /* * Find the requested 'file' given a proc token. diff -puN arch/ppc64/kernel/proc_ppc64.c~linus arch/ppc64/kernel/proc_ppc64.c --- 25/arch/ppc64/kernel/proc_ppc64.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/proc_ppc64.c 2004-01-19 22:17:21.000000000 -0800 @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -37,6 +39,7 @@ #include #include #include +#include struct proc_ppc64_t proc_ppc64; @@ -52,15 +55,32 @@ static struct file_operations page_map_f .mmap = page_map_mmap }; +#ifdef CONFIG_PPC_PSERIES +/* routines for /proc/ppc64/ofdt */ +static ssize_t ofdt_write(struct file *, const char __user *, size_t, loff_t *); +static void proc_ppc64_create_ofdt(struct proc_dir_entry *); +static int do_remove_node(char *); +static int do_add_node(char *, size_t); +static void release_prop_list(const struct property *); +static struct property *new_property(const char *, const int, const unsigned char *, struct property *); +static char * parse_next_property(char *, char *, char **, int *, unsigned char**); +static struct file_operations ofdt_fops = { + .write = ofdt_write +}; +#endif -static int __init proc_ppc64_init(void) +int __init proc_ppc64_init(void) { - printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n"); - proc_ppc64.root = proc_mkdir("ppc64", 0); - if (!proc_ppc64.root) + if (proc_ppc64.root == NULL) { + printk(KERN_INFO "proc_ppc64: Creating /proc/ppc64/\n"); + proc_ppc64.root = proc_mkdir("ppc64", 0); + if (!proc_ppc64.root) + return 0; + } else { return 0; + } proc_ppc64.naca = create_proc_entry("naca", S_IRUSR, proc_ppc64.root); if ( proc_ppc64.naca ) { @@ -90,8 +110,16 @@ static int __init proc_ppc64_init(void) } } +#ifdef CONFIG_PPC_PSERIES /* Placeholder for rtas interfaces. */ - proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root); + if (proc_ppc64.rtas == NULL) + proc_ppc64.rtas = proc_mkdir("rtas", proc_ppc64.root); + + if (proc_ppc64.rtas) + proc_symlink("rtas", 0, "ppc64/rtas"); + + proc_ppc64_create_ofdt(proc_ppc64.root); +#endif return 0; } @@ -173,5 +201,228 @@ static int page_map_mmap( struct file *f return 0; } -fs_initcall(proc_ppc64_init); +#ifdef CONFIG_PPC_PSERIES +/* create /proc/ppc64/ofdt write-only by root */ +static void proc_ppc64_create_ofdt(struct proc_dir_entry *parent) +{ + struct proc_dir_entry *ent; + + ent = create_proc_entry("ofdt", S_IWUSR, parent); + if (ent) { + ent->nlink = 1; + ent->data = NULL; + ent->size = 0; + ent->proc_fops = &ofdt_fops; + } +} + +/** + * ofdt_write - perform operations on the Open Firmware device tree + * + * @file: not used + * @buf: command and arguments + * @count: size of the command buffer + * @off: not used + * + * Operations supported at this time are addition and removal of + * whole nodes along with their properties. Operations on individual + * properties are not implemented (yet). + */ +static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count, loff_t *off) +{ + int rv = 0; + char *kbuf; + char *tmp; + + if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) { + rv = -ENOMEM; + goto out; + } + if (copy_from_user(kbuf, buf, count)) { + rv = -EFAULT; + goto out; + } + + kbuf[count] = '\0'; + + tmp = strchr(kbuf, ' '); + if (!tmp) { + rv = -EINVAL; + goto out; + } + *tmp = '\0'; + tmp++; + + if (!strcmp(kbuf, "add_node")) + rv = do_add_node(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "remove_node")) + rv = do_remove_node(tmp); + else + rv = -EINVAL; +out: + kfree(kbuf); + return rv ? rv : count; +} + +static int do_remove_node(char *buf) +{ + struct device_node *node; + int rv = 0; + + if ((node = of_find_node_by_path(buf))) + of_remove_node(node); + else + rv = -ENODEV; + + of_node_put(node); + return rv; +} + +static int do_add_node(char *buf, size_t bufsize) +{ + char *path, *end, *name; + struct device_node *np; + struct property *prop = NULL; + unsigned char* value; + int length, rv = 0; + + end = buf + bufsize; + path = buf; + buf = strchr(buf, ' '); + if (!buf) + return -EINVAL; + *buf = '\0'; + buf++; + + if ((np = of_find_node_by_path(path))) { + of_node_put(np); + return -EINVAL; + } + /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */ + while (buf < end && + (buf = parse_next_property(buf, end, &name, &length, &value))) { + struct property *last = prop; + + prop = new_property(name, length, value, last); + if (!prop) { + rv = -ENOMEM; + prop = last; + goto out; + } + } + if (!buf) { + rv = -EINVAL; + goto out; + } + + rv = of_add_node(path, prop); + +out: + if (rv) + release_prop_list(prop); + return rv; +} + +static struct property *new_property(const char *name, const int length, const unsigned char *value, struct property *last) +{ + struct property *new = kmalloc(sizeof(*new), GFP_KERNEL); + + if (!new) + return NULL; + memset(new, 0, sizeof(*new)); + + if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL))) + goto cleanup; + if (!(new->value = kmalloc(length + 1, GFP_KERNEL))) + goto cleanup; + + strcpy(new->name, name); + memcpy(new->value, value, length); + *(((char *)new->value) + length) = 0; + new->length = length; + new->next = last; + return new; + +cleanup: + if (new->name) + kfree(new->name); + if (new->value) + kfree(new->value); + kfree(new); + return NULL; +} + +/** + * parse_next_property - process the next property from raw input buffer + * @buf: input buffer, must be nul-terminated + * @end: end of the input buffer + 1, for validation + * @name: return value; set to property name in buf + * @length: return value; set to length of value + * @value: return value; set to the property value in buf + * + * Note that the caller must make copies of the name and value returned, + * this function does no allocation or copying of the data. Return value + * is set to the next name in buf, or NULL on error. + */ +static char * parse_next_property(char *buf, char *end, char **name, int *length, unsigned char **value) +{ + char *tmp; + + *name = buf; + + tmp = strchr(buf, ' '); + if (!tmp) { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + *tmp = '\0'; + + if (++tmp >= end) { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + + /* now we're on the length */ + *length = -1; + *length = simple_strtoul(tmp, &tmp, 10); + if (*length == -1) { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + if (*tmp != ' ' || ++tmp >= end) { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + + /* now we're on the value */ + *value = tmp; + tmp += *length; + if (tmp > end) { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + else if (tmp < end && *tmp != ' ' && *tmp != '\0') { + printk(KERN_ERR "property parse failed in %s at line %d\n", __FUNCTION__, __LINE__); + return NULL; + } + tmp++; + + /* and now we should be on the next name, or the end */ + return tmp; +} + +static void release_prop_list(const struct property *prop) +{ + struct property *next; + for (; prop; prop = next) { + next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + } + +} +#endif /* defined(CONFIG_PPC_PSERIES) */ + +fs_initcall(proc_ppc64_init); diff -puN arch/ppc64/kernel/prom.c~linus arch/ppc64/kernel/prom.c --- 25/arch/ppc64/kernel/prom.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/prom.c 2004-01-19 22:17:21.000000000 -0800 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,10 @@ #include #include #include +#include #include #include +#include #include "open_pic.h" #ifdef CONFIG_LOGO_LINUX_CLUT224 @@ -147,8 +150,13 @@ char *bootpath = 0; char *bootdevice = 0; int boot_cpuid = 0; +#define MAX_CPU_THREADS 2 struct device_node *allnodes = 0; +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +static rwlock_t devtree_lock = RW_LOCK_UNLOCKED; #define UNDEFINED_IRQ 0xffff unsigned short real_irq_to_virt_map[NR_HW_IRQS]; @@ -156,7 +164,7 @@ unsigned short virt_irq_to_real_map[NR_I int last_virt_irq = 2; /* index of last virt_irq. Skip through IPI */ static unsigned long call_prom(const char *service, int nargs, int nret, ...); -static void prom_exit(void); +static void prom_panic(const char *reason); static unsigned long copy_device_tree(unsigned long); static unsigned long inspect_node(phandle, struct device_node *, unsigned long, unsigned long, struct device_node ***); @@ -168,6 +176,11 @@ static int prom_next_node(phandle *); static struct bi_record * prom_bi_rec_verify(struct bi_record *); static unsigned long prom_bi_rec_reserve(unsigned long); static struct device_node *find_phandle(phandle); +static void of_node_cleanup(struct device_node *); +static struct device_node *derive_parent(const char *); +static void add_node_proc_entries(struct device_node *); +static void remove_node_proc_entries(struct device_node *); +static int of_finish_dynamic_node(struct device_node *); #ifdef DEBUG_PROM void prom_dump_lmb(void); @@ -223,10 +236,12 @@ call_prom(const char *service, int nargs static void __init -prom_exit() +prom_panic(const char *reason) { unsigned long offset = reloc_offset(); + prom_print(reason); + /* ToDo: should put up an SRC here */ call_prom(RELOC("exit"), 0, 0); for (;;) /* should never get here */ @@ -602,6 +617,9 @@ prom_instantiate_rtas(void) _rtas->base) >= 0) { _rtas->entry = (long)_prom->args.rets[1]; } + RELOC(rtas_rmo_buf) + = lmb_alloc_base(RTAS_RMOBUF_MAX, PAGE_SIZE, + rtas_region); } if (_rtas->entry <= 0) { @@ -785,8 +803,7 @@ prom_initialize_tce_table(void) base = lmb_alloc(minsize, align); if ( !base ) { - prom_print(RELOC("ERROR, cannot find space for TCE table.\n")); - prom_exit(); + prom_panic(RELOC("ERROR, cannot find space for TCE table.\n")); } vbase = absolute_to_virt(base); @@ -884,16 +901,21 @@ static void prom_hold_cpus(unsigned long mem) { unsigned long i; - unsigned int cpuid; + unsigned int reg; phandle node; unsigned long offset = reloc_offset(); char type[64], *path; + int cpuid = 0; + unsigned int interrupt_server[MAX_CPU_THREADS]; + unsigned int cpu_threads, hw_cpu_num; + int propsize; extern void __secondary_hold(void); extern unsigned long __secondary_hold_spinloop; extern unsigned long __secondary_hold_acknowledge; unsigned long *spinloop = __v2a(&__secondary_hold_spinloop); unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge); unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold)); + struct naca_struct *_naca = RELOC(naca); struct systemcfg *_systemcfg = RELOC(systemcfg); struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); @@ -946,13 +968,9 @@ prom_hold_cpus(unsigned long mem) if (strcmp(type, RELOC("okay")) != 0) continue; - cpuid = -1; + reg = -1; call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), - &cpuid, sizeof(cpuid)); - - /* Only need to start secondary procs, not ourself. */ - if ( cpuid == _prom->cpu ) - continue; + ®, sizeof(reg)); path = (char *) mem; memset(path, 0, 256); @@ -962,12 +980,14 @@ prom_hold_cpus(unsigned long mem) #ifdef DEBUG_PROM prom_print_nl(); - prom_print(RELOC("cpu hw idx = 0x")); + prom_print(RELOC("cpuid = 0x")); prom_print_hex(cpuid); prom_print_nl(); + prom_print(RELOC("cpu hw idx = 0x")); + prom_print_hex(reg); + prom_print_nl(); #endif - prom_print(RELOC("starting cpu ")); - prom_print(path); + _xPaca[cpuid].xHwProcNum = reg; /* Init the acknowledge var which will be reset by * the secondary cpu when it awakens from its OF @@ -975,45 +995,85 @@ prom_hold_cpus(unsigned long mem) */ *acknowledge = (unsigned long)-1; -#ifdef DEBUG_PROM - prom_print(RELOC(" 3) spinloop = 0x")); - prom_print_hex(spinloop); - prom_print_nl(); - prom_print(RELOC(" 3) *spinloop = 0x")); - prom_print_hex(*spinloop); - prom_print_nl(); - prom_print(RELOC(" 3) acknowledge = 0x")); - prom_print_hex(acknowledge); - prom_print_nl(); - prom_print(RELOC(" 3) *acknowledge = 0x")); - prom_print_hex(*acknowledge); - prom_print_nl(); - prom_print(RELOC(" 3) secondary_hold = 0x")); - prom_print_hex(secondary_hold); - prom_print_nl(); -#endif - call_prom(RELOC("start-cpu"), 3, 0, node, secondary_hold, cpuid); - prom_print(RELOC("...")); - for ( i = 0 ; (i < 100000000) && - (*acknowledge == ((unsigned long)-1)); i++ ) ; -#ifdef DEBUG_PROM - { - unsigned long *p = 0x0; - prom_print(RELOC(" 4) 0x0 = 0x")); - prom_print_hex(*p); - prom_print_nl(); + propsize = call_prom(RELOC("getprop"), 4, 1, node, + RELOC("ibm,ppc-interrupt-server#s"), + &interrupt_server, + sizeof(interrupt_server)); + if (propsize < 0) { + /* no property. old hardware has no SMT */ + cpu_threads = 1; + interrupt_server[0] = reg; /* fake it with phys id */ + } else { + /* We have a threaded processor */ + cpu_threads = propsize / sizeof(u32); + if (cpu_threads > MAX_CPU_THREADS) { + prom_print(RELOC("SMT: too many threads!\nSMT: found ")); + prom_print_hex(cpu_threads); + prom_print(RELOC(", max is ")); + prom_print_hex(MAX_CPU_THREADS); + prom_print_nl(); + cpu_threads = 1; /* ToDo: panic? */ + } } + + hw_cpu_num = interrupt_server[0]; + if (hw_cpu_num != _prom->cpu) { + /* Primary Thread of non-boot cpu */ + prom_print_hex(cpuid); + prom_print(RELOC(" : starting cpu ")); + prom_print(path); + prom_print(RELOC("...")); + call_prom(RELOC("start-cpu"), 3, 0, node, + secondary_hold, cpuid); + + for ( i = 0 ; (i < 100000000) && + (*acknowledge == ((unsigned long)-1)); i++ ) ; + + if (*acknowledge == cpuid) { + prom_print(RELOC("ok\n")); +#ifdef CONFIG_SMP + /* Set the number of active processors. */ + _systemcfg->processorCount++; + cpu_set(cpuid, RELOC(cpu_available_map)); + cpu_set(cpuid, RELOC(cpu_possible_map)); + cpu_set(cpuid, RELOC(cpu_present_at_boot)); #endif - if (*acknowledge == cpuid) { - prom_print(RELOC("ok\n")); - /* Set the number of active processors. */ - _systemcfg->processorCount++; - _xPaca[cpuid].active = 1; - } else { - prom_print(RELOC("failed: ")); - prom_print_hex(*acknowledge); + } else { + prom_print(RELOC("failed: ")); + prom_print_hex(*acknowledge); + prom_print_nl(); + /* prom_panic(RELOC("cpu failed to start")); */ + } + } +#ifdef CONFIG_SMP + else { + prom_print_hex(cpuid); + prom_print(RELOC(" : booting cpu ")); + prom_print(path); + prom_print_nl(); + cpu_set(cpuid, RELOC(cpu_available_map)); + cpu_set(cpuid, RELOC(cpu_possible_map)); + cpu_set(cpuid, RELOC(cpu_online_map)); + cpu_set(cpuid, RELOC(cpu_present_at_boot)); + } + + /* Init paca for secondary threads. They start later. */ + for (i=1; i < cpu_threads; i++) { + cpuid++; + _xPaca[cpuid].xHwProcNum = interrupt_server[i]; + prom_print_hex(interrupt_server[i]); + prom_print(RELOC(" : preparing thread ... ")); + if (_naca->smt_state) { + cpu_set(cpuid, RELOC(cpu_available_map)); + cpu_set(cpuid, RELOC(cpu_present_at_boot)); + prom_print(RELOC("available")); + } else { + prom_print(RELOC("not available")); + } prom_print_nl(); } +#endif + cpuid++; } #ifdef CONFIG_HMT /* Only enable HMT on processors that provide support. */ @@ -1023,10 +1083,10 @@ prom_hold_cpus(unsigned long mem) prom_print(RELOC(" starting secondary threads\n")); for (i = 0; i < NR_CPUS; i += 2) { - if (!_xPaca[i].active) + if (!cpu_online(i)) continue; - if (i == boot_cpuid) { + if (i == 0) { unsigned long pir = _get_PIR(); if (__is_processor(PV_PULSAR)) { RELOC(hmt_thread_data)[i].pir = @@ -1036,7 +1096,8 @@ prom_hold_cpus(unsigned long mem) pir & 0x3ff; } } - _xPaca[i+1].active = 1; +/* cpu_set(i+1, cpu_online_map); */ + cpu_set(i+1, RELOC(cpu_possible_map)); } _systemcfg->processorCount *= 2; } else { @@ -1049,6 +1110,105 @@ prom_hold_cpus(unsigned long mem) #endif } +static void +smt_setup(void) +{ + char *p, *q; + char my_smt_enabled = SMT_DYNAMIC; + unsigned long my_smt_snooze_delay; + ihandle prom_options = NULL; + char option[9]; + unsigned long offset = reloc_offset(); + struct naca_struct *_naca = RELOC(naca); + char found = 0; + + if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) { + for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) { + q = p + 12; + if (p > RELOC(cmd_line) && p[-1] != ' ') + continue; + found = 1; + if (q[0] == 'o' && q[1] == 'f' && + q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) { + my_smt_enabled = SMT_OFF; + } else if (q[0]=='o' && q[1] == 'n' && + (q[2] == ' ' || q[2] == '\0')) { + my_smt_enabled = SMT_ON; + } else { + my_smt_enabled = SMT_DYNAMIC; + } + } + } + if (!found) { + prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options")); + if (prom_options != (ihandle) -1) { + call_prom(RELOC("getprop"), + 4, 1, prom_options, + RELOC("ibm,smt-enabled"), + option, + sizeof(option)); + if (option[0] != 0) { + found = 1; + if (!strcmp(option, "off")) + my_smt_enabled = SMT_OFF; + else if (!strcmp(option, "on")) + my_smt_enabled = SMT_ON; + else + my_smt_enabled = SMT_DYNAMIC; + } + } + } + + if (!found ) + my_smt_enabled = SMT_DYNAMIC; /* default to on */ + + found = 0; + if (my_smt_enabled) { + if (strstr(RELOC(cmd_line), RELOC("smt-snooze-delay="))) { + for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-snooze-delay="))) != 0; ) { + q = p + 17; + if (p > RELOC(cmd_line) && p[-1] != ' ') + continue; + found = 1; + /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */ + my_smt_snooze_delay = 0; + while (*q >= '0' && *q <= '9') { + my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0'; + q++; + } + } + } + + if (!found) { + prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options")); + if (prom_options != (ihandle) -1) { + call_prom(RELOC("getprop"), + 4, 1, prom_options, + RELOC("ibm,smt-snooze-delay"), + option, + sizeof(option)); + if (option[0] != 0) { + found = 1; + /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */ + my_smt_snooze_delay = 0; + q = option; + while (*q >= '0' && *q <= '9') { + my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0'; + q++; + } + } + } + } + + if (!found) { + my_smt_snooze_delay = 30000; /* default value */ + } + } else { + my_smt_snooze_delay = 0; /* default value */ + } + _naca->smt_snooze_delay = my_smt_snooze_delay; + _naca->smt_state = my_smt_enabled; +} /* * We enter here early on, when the Open Firmware prom is still @@ -1065,12 +1225,20 @@ prom_init(unsigned long r3, unsigned lon unsigned long offset = reloc_offset(); long l; char *p, *d; - unsigned long phys; - u32 getprop_rval; - struct systemcfg *_systemcfg = RELOC(systemcfg); + unsigned long phys; + u32 getprop_rval; + struct systemcfg *_systemcfg; struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* First zero the BSS -- use memset, some arches don't have + * caches on yet */ + memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start); + + /* Setup systemcfg and NACA pointers now */ + RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset); + RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset); + /* Default machine type. */ _systemcfg->platform = PLATFORM_PSERIES; @@ -1092,12 +1260,12 @@ prom_init(unsigned long r3, unsigned lon RELOC("/chosen")); if ((long)_prom->chosen <= 0) - prom_exit(); + prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */ if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("stdout"), &getprop_rval, sizeof(getprop_rval)) <= 0) - prom_exit(); + prom_panic(RELOC("cannot find stdout")); _prom->stdout = (ihandle)(unsigned long)getprop_rval; @@ -1123,7 +1291,7 @@ prom_init(unsigned long r3, unsigned lon if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, RELOC("cpu"), &getprop_rval, sizeof(getprop_rval)) <= 0) - prom_exit(); + prom_panic(RELOC("cannot find boot cpu")); prom_cpu = (ihandle)(unsigned long)getprop_rval; cpu_pkg = call_prom(RELOC("instance-to-package"), 1, 1, prom_cpu); @@ -1131,11 +1299,9 @@ prom_init(unsigned long r3, unsigned lon cpu_pkg, RELOC("reg"), &getprop_rval, sizeof(getprop_rval)); _prom->cpu = (int)(unsigned long)getprop_rval; - _xPaca[_prom->cpu].active = 1; -#ifdef CONFIG_SMP - cpu_set(_prom->cpu, RELOC(cpu_online_map)); -#endif - RELOC(boot_cpuid) = _prom->cpu; + _xPaca[0].xHwProcNum = _prom->cpu; + + RELOC(boot_cpuid) = 0; #ifdef DEBUG_PROM prom_print(RELOC("Booting CPU hw index = 0x")); @@ -1169,11 +1335,12 @@ prom_init(unsigned long r3, unsigned lon /* Initialize some system info into the Naca early... */ mem = prom_initialize_naca(mem); + smt_setup(); + /* If we are on an SMP machine, then we *MUST* do the * following, regardless of whether we have an SMP * kernel or not. */ - if (_systemcfg->processorCount > 1) prom_hold_cpus(mem); #ifdef DEBUG_PROM @@ -1381,8 +1548,7 @@ copy_device_tree(unsigned long mem_start root = call_prom(RELOC("peer"), 1, 1, (phandle)0); if (root == (phandle)0) { - prom_print(RELOC("couldn't get device tree root\n")); - prom_exit(); + prom_panic(RELOC("couldn't get device tree root\n")); } allnextp = &RELOC(allnodes); mem_start = DOUBLEWORD_ALIGN(mem_start); @@ -1444,6 +1610,23 @@ inspect_node(phandle node, struct device *prev_propp = PTRUNRELOC(pp); prev_propp = &pp->next; } + + /* Add a "linux_phandle" value */ + if (np->node) { + u32 ibm_phandle = 0; + int len; + + /* First see if "ibm,phandle" exists and use its value */ + len = (int) + call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,phandle"), + &ibm_phandle, sizeof(ibm_phandle)); + if (len < 0) { + np->linux_phandle = np->node; + } else { + np->linux_phandle = ibm_phandle; + } + } + *prev_propp = 0; /* get the node's full name */ @@ -1487,7 +1670,7 @@ finish_device_tree(void) klimit = mem; - rtas.dev = find_devices("rtas"); + rtas.dev = of_find_node_by_name(NULL, "rtas"); } static unsigned long __init @@ -1540,7 +1723,7 @@ finish_node(struct device_node *np, unsi /* * Find the interrupt parent of a node. */ -static struct device_node * __init +static struct device_node * __devinit intr_parent(struct device_node *p) { phandle *parp; @@ -1555,7 +1738,7 @@ intr_parent(struct device_node *p) * Find out the size of each entry of the interrupts property * for a node. */ -static int __init +static int __devinit prom_n_intr_cells(struct device_node *np) { struct device_node *p; @@ -1583,7 +1766,7 @@ prom_n_intr_cells(struct device_node *np * Map an interrupt from a device up to the platform interrupt * descriptor. */ -static int __init +static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, struct device_node *np, unsigned int *ints, int nintrc) { @@ -1939,11 +2122,14 @@ int machine_is_compatible(const char *compat) { struct device_node *root; - - root = find_path_device("/"); - if (root == 0) - return 0; - return device_is_compatible(root, compat); + int rc = 0; + + root = of_find_node_by_path("/"); + if (root) { + rc = device_is_compatible(root, compat); + of_node_put(root); + } + return rc; } /* @@ -1983,16 +2169,560 @@ find_path_device(const char *path) return NULL; } +/******* + * + * New implementation of the OF "find" APIs, return a refcounted + * object, call of_node_put() when done. The device tree and list + * are protected by a rw_lock. + * + * Note that property management will need some locking as well, + * this isn't dealt with yet. + * + *******/ + +/** + * of_find_node_by_name - Find a node by its "name" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @name: The name string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->name != 0 && strcasecmp(np->name, name) == 0 + && of_node_get(np)) + break; + if (from) + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} + +/** + * of_find_node_by_type - Find a node by its "device_type" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @name: The type string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (np->type != 0 && strcasecmp(np->type, type) == 0 + && of_node_get(np)) + break; + if (from) + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +/** + * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @type: The type string to match "device_type" or NULL to ignore + * @compatible: The string to match to one of the tokens in the device + * "compatible" list. + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np != 0; np = np->allnext) { + if (type != NULL + && !(np->type != 0 && strcasecmp(np->type, type) == 0)) + continue; + if (device_is_compatible(np, compatible) && of_node_get(np)) + break; + } + if (from) + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} + +/** + * of_find_node_by_path - Find a node matching a full OF path + * @path: The full path to match + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + read_lock(&devtree_lock); + for (; np != 0; np = np->allnext) + if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 + && of_node_get(np)) + break; + read_unlock(&devtree_lock); + return np; +} + +/** + * of_find_all_nodes - Get next node in global list + * @prev: Previous node or NULL to start iteration + * of_node_put() will be called on it + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_all_nodes(struct device_node *prev) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = prev ? prev->allnext : allnodes; + for (; np != 0; np = np->allnext) + if (of_node_get(np)) + break; + if (prev) + of_node_put(prev); + read_unlock(&devtree_lock); + return np; +} + +/** + * of_get_parent - Get a node's parent if any + * @node: Node to get parent + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + read_lock(&devtree_lock); + np = of_node_get(node->parent); + read_unlock(&devtree_lock); + return np; +} + +/** + * of_get_next_child - Iterate a node childs + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + read_lock(&devtree_lock); + next = prev ? prev->sibling : node->child; + for (; next != 0; next = next->sibling) + if (of_node_get(next)) + break; + if (prev) + of_node_put(prev); + read_unlock(&devtree_lock); + return next; +} + +/** + * of_node_get - Increment refcount of a node + * @node: Node to inc refcount, NULL is supported to + * simplify writing of callers + * + * Returns the node itself or NULL if gone. + */ +struct device_node *of_node_get(struct device_node *node) +{ + if (node && !OF_IS_STALE(node)) { + atomic_inc(&node->_users); + return node; + } + return NULL; +} + +/** + * of_node_put - Decrement refcount of a node + * @node: Node to dec refcount, NULL is supported to + * simplify writing of callers + * + */ +void of_node_put(struct device_node *node) +{ + if (!node) + return; + + WARN_ON(0 == atomic_read(&node->_users)); + + if (OF_IS_STALE(node)) { + if (atomic_dec_and_test(&node->_users)) { + of_node_cleanup(node); + return; + } + } + else + atomic_dec(&node->_users); +} + +/** + * of_node_cleanup - release a dynamically allocated node + * @arg: Node to be released + */ +static void of_node_cleanup(struct device_node *node) +{ + struct property *prop = node->properties; + + if (!OF_IS_DYNAMIC(node)) + return; + while (prop) { + struct property *next = prop->next; + kfree(prop->name); + kfree(prop->value); + kfree(prop); + prop = next; + } + kfree(node->intrs); + kfree(node->addrs); + kfree(node->full_name); + kfree(node); +} + +/** + * derive_parent - basically like dirname(1) + * @path: the full_name of a node to be added to the tree + * + * Returns the node which should be the parent of the node + * described by path. E.g., for path = "/foo/bar", returns + * the node with full_name = "/foo". + */ +static struct device_node *derive_parent(const char *path) +{ + struct device_node *parent = NULL; + char *parent_path = "/"; + size_t parent_path_len = strrchr(path, '/') - path + 1; + + /* reject if path is "/" */ + if (!strcmp(path, "/")) + return NULL; + + if (strrchr(path, '/') != path) { + parent_path = kmalloc(parent_path_len, GFP_KERNEL); + if (!parent_path) + return NULL; + strlcpy(parent_path, path, parent_path_len); + } + parent = of_find_node_by_path(parent_path); + if (strcmp(parent_path, "/")) + kfree(parent_path); + return parent; +} + +/* + * Routines for "runtime" addition and removal of device tree nodes. + */ + +/* + * Given a path and a property list, construct an OF device node, add + * it to the device tree and global list, and place it in + * /proc/device-tree. This function may sleep. + */ +int of_add_node(const char *path, struct property *proplist) +{ + struct device_node *np; + int err = 0; + + np = kmalloc(sizeof(struct device_node), GFP_KERNEL); + if (!np) + return -ENOMEM; + + memset(np, 0, sizeof(*np)); + + np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL); + if (!np->full_name) { + kfree(np); + return -ENOMEM; + } + strcpy(np->full_name, path); + + np->properties = proplist; + OF_MARK_DYNAMIC(np); + of_node_get(np); + np->parent = derive_parent(path); + if (!np->parent) { + kfree(np); + return -EINVAL; /* could also be ENOMEM, though */ + } + + if (0 != (err = of_finish_dynamic_node(np))) { + kfree(np); + return err; + } + + write_lock(&devtree_lock); + np->sibling = np->parent->child; + np->allnext = allnodes; + np->parent->child = np; + allnodes = np; + write_unlock(&devtree_lock); + + add_node_proc_entries(np); + + of_node_put(np->parent); + of_node_put(np); + return 0; +} + +/* + * Remove an OF device node from the system. + */ +int of_remove_node(struct device_node *np) +{ + struct device_node *parent, *child; + + parent = of_get_parent(np); + child = of_get_next_child(np, NULL); + if (child && !child->child && !child->sibling) { + /* For now, we will allow removal of a + * node with one and only one child, so + * that we can support removing a slot with + * an IOA in it. More general support for + * subtree removal to be implemented later, if + * necessary. + */ + of_remove_node(child); + } + else if (child) { + of_node_put(child); + of_node_put(parent); + return -EINVAL; + } + of_node_put(child); + + write_lock(&devtree_lock); + OF_MARK_STALE(np); + remove_node_proc_entries(np); + if (allnodes == np) + allnodes = np->allnext; + else { + struct device_node *prev; + for (prev = allnodes; + prev->allnext != np; + prev = prev->allnext) + ; + prev->allnext = np->allnext; + } + + if (np->parent->child == np) + np->parent->child = np->sibling; + else { + struct device_node *prevsib; + for (prevsib = np->parent->child; + prevsib->sibling != np; + prevsib = prevsib->sibling) + ; + prevsib->sibling = np->sibling; + } + write_unlock(&devtree_lock); + of_node_put(parent); + return 0; +} + +/* + * Add a node to /proc/device-tree. + */ +static void add_node_proc_entries(struct device_node *np) +{ + struct proc_dir_entry *ent; + + ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde); + if (ent) + proc_device_tree_add_node(np, ent); +} + +static void remove_node_proc_entries(struct device_node *np) +{ + struct property *pp = np->properties; + struct device_node *parent = np->parent; + + while (pp) { + remove_proc_entry(pp->name, np->pde); + pp = pp->next; + } + + /* Assuming that symlinks have the same parent directory as + * np->pde. + */ + if (np->name_link) + remove_proc_entry(np->name_link->name, parent->pde); + if (np->addr_link) + remove_proc_entry(np->addr_link->name, parent->pde); + if (np->pde) + remove_proc_entry(np->pde->name, parent->pde); +} + +/* + * Fix up the uninitialized fields in a new device node: + * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields + * + * A lot of boot-time code is duplicated here, because functions such + * as finish_node_interrupts, interpret_pci_props, etc. cannot use the + * slab allocator. + * + * This should probably be split up into smaller chunks. + */ + +static int of_finish_dynamic_node(struct device_node *node) +{ + struct device_node *parent = of_get_parent(node); + u32 *regs; + unsigned int *ints; + int intlen, intrcells; + int i, j, n, err = 0; + unsigned int *irq; + struct device_node *ic; + + node->name = get_property(node, "name", 0); + node->type = get_property(node, "device_type", 0); + + if (!parent) { + err = -ENODEV; + goto out; + } + + /* do the work of interpret_pci_props */ + if (parent->type && !strcmp(parent->type, "pci")) { + struct address_range *adr; + struct pci_reg_property *pci_addrs; + int i, l; + + pci_addrs = (struct pci_reg_property *) + get_property(node, "assigned-addresses", &l); + if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) { + i = 0; + adr = kmalloc(sizeof(struct address_range) * + (l / sizeof(struct pci_reg_property)), + GFP_KERNEL); + if (!adr) { + err = -ENOMEM; + goto out; + } + while ((l -= sizeof(struct pci_reg_property)) >= 0) { + adr[i].space = pci_addrs[i].addr.a_hi; + adr[i].address = pci_addrs[i].addr.a_lo; + adr[i].size = pci_addrs[i].size_lo; + ++i; + } + node->addrs = adr; + node->n_addrs = i; + } + } + + /* now do the work of finish_node_interrupts */ + + ints = (unsigned int *) get_property(node, "interrupts", &intlen); + if (!ints) + goto out; + + intrcells = prom_n_intr_cells(node); + intlen /= intrcells * sizeof(unsigned int); + node->n_intrs = intlen; + node->intrs = kmalloc(sizeof(struct interrupt_info) * intlen, + GFP_KERNEL); + if (!node->intrs) { + err = -ENOMEM; + goto out; + } + + for (i = 0; i < intlen; ++i) { + node->intrs[i].line = 0; + node->intrs[i].sense = 1; + n = map_interrupt(&irq, &ic, node, ints, intrcells); + if (n <= 0) + continue; + node->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + if (n > 1) + node->intrs[i].sense = irq[1]; + if (n > 2) { + printk(KERN_DEBUG "hmmm, got %d intr cells for %s:", n, + node->full_name); + for (j = 0; j < n; ++j) + printk(" %d", irq[j]); + printk("\n"); + } + ints += intrcells; + } + + /* now do the rough equivalent of update_dn_pci_info, this + * probably is not correct for phb's, but should work for + * IOAs and slots. + */ + + node->phb = parent->phb; + + regs = (u32 *)get_property(node, "reg", 0); + if (regs) { + node->busno = (regs[0] >> 16) & 0xff; + node->devfn = (regs[0] >> 8) & 0xff; + } + + /* fixing up tce_table */ + + if(strcmp(node->name, "pci") == 0 && + get_property(node, "ibm,dma-window", NULL)) { + node->bussubno = node->busno; + create_pci_bus_tce_table((unsigned long)node); + } + else + node->tce_table = parent->tce_table; + +out: + of_node_put(parent); + return err; +} + /* * Find the device_node with a given phandle. */ -static struct device_node * __init +static struct device_node * __devinit find_phandle(phandle ph) { struct device_node *np; for (np = allnodes; np != 0; np = np->allnext) - if (np->node == ph) + if (np->linux_phandle == ph) return np; return NULL; } @@ -2082,17 +2812,6 @@ print_properties(struct device_node *np) #endif -void __init -abort() -{ -#ifdef CONFIG_XMON - xmon(NULL); -#endif - for (;;) - prom_exit(); -} - - /* Verify bi_recs are good */ static struct bi_record * prom_bi_rec_verify(struct bi_record *bi_recs) diff -puN arch/ppc64/kernel/pSeries_htab.c~linus arch/ppc64/kernel/pSeries_htab.c --- 25/arch/ppc64/kernel/pSeries_htab.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_htab.c 2004-01-19 22:17:21.000000000 -0800 @@ -219,10 +219,10 @@ static long pSeries_hpte_updatepp(unsign /* Ensure it is out of the tlb too */ if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { - _tlbiel(va); + tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); - _tlbie(va, large); + tlbie(va, large); spin_unlock_irqrestore(&pSeries_tlbie_lock, flags); } @@ -256,7 +256,7 @@ static void pSeries_hpte_updateboltedpp( /* Ensure it is out of the tlb too */ spin_lock_irqsave(&pSeries_tlbie_lock, flags); - _tlbie(va, 0); + tlbie(va, 0); spin_unlock_irqrestore(&pSeries_tlbie_lock, flags); } @@ -285,10 +285,10 @@ static void pSeries_hpte_invalidate(unsi /* Invalidate the tlb */ if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { - _tlbiel(va); + tlbiel(va); } else { spin_lock_irqsave(&pSeries_tlbie_lock, flags); - _tlbie(va, large); + tlbie(va, large); spin_unlock_irqrestore(&pSeries_tlbie_lock, flags); } } @@ -350,12 +350,8 @@ static void pSeries_flush_hash_range(uns if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) { asm volatile("ptesync":::"memory"); - for (i = 0; i < j; i++) { - asm volatile("\n\ - clrldi %0,%0,16\n\ - tlbiel %0" - : : "r" (batch->vaddr[i]) : "memory" ); - } + for (i = 0; i < j; i++) + __tlbiel(batch->vaddr[i]); asm volatile("ptesync":::"memory"); } else { @@ -364,12 +360,8 @@ static void pSeries_flush_hash_range(uns asm volatile("ptesync":::"memory"); - for (i = 0; i < j; i++) { - asm volatile("\n\ - clrldi %0,%0,16\n\ - tlbie %0" - : : "r" (batch->vaddr[i]) : "memory" ); - } + for (i = 0; i < j; i++) + __tlbie(batch->vaddr[i], 0); asm volatile("eieio; tlbsync; ptesync":::"memory"); @@ -389,10 +381,11 @@ void hpte_init_pSeries(void) ppc_md.hpte_remove = pSeries_hpte_remove; /* Disable TLB batching on nighthawk */ - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) { model = get_property(root, "model", NULL); if (strcmp(model, "CHRP IBM,9076-N81")) ppc_md.flush_hash_range = pSeries_flush_hash_range; + of_node_put(root); } } diff -puN arch/ppc64/kernel/pSeries_hvCall.S~linus arch/ppc64/kernel/pSeries_hvCall.S --- 25/arch/ppc64/kernel/pSeries_hvCall.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_hvCall.S 2004-01-19 22:17:21.000000000 -0800 @@ -67,3 +67,77 @@ _GLOBAL(plpar_hcall_norets) ld r0,-8(r1) mtcrf 0xff,r0 blr /* return r3 = status */ + + +/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3 + unsigned long arg1, R4 + unsigned long arg2, R5 + unsigned long arg3, R6 + unsigned long arg4, R7 + unsigned long arg5, R8 + unsigned long arg6, R9 + unsigned long arg7, R10 + unsigned long arg8, 112(R1) + unsigned long *out1); 120(R1) + + */ + + .text +_GLOBAL(plpar_hcall_8arg_2ret) + mfcr r0 + + ld r11, 112(r1) /* put arg8 and out1 in R11 and R12 */ + ld r12, 120(r1) + + std r0,-8(r1) + stdu r1,-32(r1) + + std r12,-8(r1) /* Save out ptr */ + + HSC /* invoke the hypervisor */ + + ld r10,-8(r1) /* Fetch r4 ret arg */ + std r4,0(r10) + + ld r1,0(r1) + ld r0,-8(r1) + mtcrf 0xff,r0 + blr /* return r3 = status */ + + +/* long plpar_hcall_4out(unsigned long opcode, R3 + unsigned long arg1, R4 + unsigned long arg2, R5 + unsigned long arg3, R6 + unsigned long arg4, R7 + unsigned long *out1, (r4) R8 + unsigned long *out2, (r5) R9 + unsigned long *out3, (r6) R10 + unsigned long *out4); (r7) 112(R1). From Parameter save area. + */ +_GLOBAL(plpar_hcall_4out) + mfcr r0 + std r0,-8(r1) + ld r14,112(r1) + stdu r1,-48(r1) + + std r8,32(r1) /* Save out ptrs. */ + std r9,24(r1) + std r10,16(r1) + std r14,8(r1) + + HSC /* invoke the hypervisor */ + + ld r14,32(r1) /* Fetch r4-r7 ret args. */ + std r4,0(r14) + ld r14,24(r1) + std r5,0(r14) + ld r14,16(r1) + std r6,0(r14) + ld r14,8(r1) + std r7,0(r14) + + ld r1,0(r1) + ld r0,-8(r1) + mtcrf 0xff,r0 + blr /* return r3 = status */ diff -puN arch/ppc64/kernel/pSeries_lpar.c~linus arch/ppc64/kernel/pSeries_lpar.c --- 25/arch/ppc64/kernel/pSeries_lpar.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_lpar.c 2004-01-19 22:17:21.000000000 -0800 @@ -35,6 +35,32 @@ #include #include #include +#include + +long poll_pending(void) +{ + unsigned long dummy; + return plpar_hcall(H_POLL_PENDING, 0, 0, 0, 0, + &dummy, &dummy, &dummy); +} + +long prod_processor(void) +{ + plpar_hcall_norets(H_PROD); + return(0); +} + +long cede_processor(void) +{ + plpar_hcall_norets(H_CEDE); + return(0); +} + +long register_vpa(unsigned long flags, unsigned long proc, unsigned long vpa) +{ + plpar_hcall_norets(H_REGISTER_VPA, flags, proc, vpa); + return(0); +} long plpar_pte_remove(unsigned long flags, unsigned long ptex, @@ -206,6 +232,61 @@ static unsigned char udbg_getcLP(void) } } +/* returns 0 if couldn't find or use /chosen/stdout as console */ +static int find_udbg_vterm(void) +{ + struct device_node *stdout_node; + u32 *termno; + char *name; + int found = 0; + + /* find the boot console from /chosen/stdout */ + if (!of_stdout_device) { + printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n"); + return found; + } + stdout_node = of_find_node_by_path(of_stdout_device); + if (!stdout_node) { + printk(KERN_WARNING "couldn't find node from /chosen/stdout\n"); + return found; + } + + /* now we have the stdout node; figure out what type of device it is. */ + name = (char *)get_property(stdout_node, "name", 0); + if (!name) { + printk(KERN_WARNING "stdout node missing 'name' property!\n"); + goto out; + } + + if (strncmp(name, "vty", 3) == 0) { + if (device_is_compatible(stdout_node, "hvterm1")) { + termno = (u32 *)get_property(stdout_node, "reg", 0); + if (termno) { + vtermno = termno[0]; + ppc_md.udbg_putc = udbg_putcLP; + ppc_md.udbg_getc = udbg_getcLP; + ppc_md.udbg_getc_poll = udbg_getc_pollLP; + found = 1; + } + } else { + /* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */ + printk(KERN_WARNING "%s doesn't speak hvterm1; " + "can't print udbg messages\n", of_stdout_device); + } + } else if (strncmp(name, "serial", 6)) { + /* XXX fix ISA serial console */ + printk(KERN_WARNING "serial stdout on LPAR ('%s')! " + "can't print udbg messages\n", of_stdout_device); + } else { + printk(KERN_WARNING "don't know how to print to stdout '%s'\n", + of_stdout_device); + } + +out: + of_node_put(stdout_node); + return found; +} + void pSeries_lpar_mm_init(void); /* This is called early in setup.c. @@ -213,8 +294,6 @@ void pSeries_lpar_mm_init(void); */ void pSeriesLP_init_early(void) { - struct device_node *np; - pSeries_lpar_mm_init(); ppc_md.tce_build = tce_build_pSeriesLP; @@ -225,24 +304,13 @@ void pSeriesLP_init_early(void) #endif /* The keyboard is not useful in the LPAR environment. - * Leave all the interfaces NULL. + * Leave all the ppc_md keyboard interfaces NULL. */ - /* lookup the first virtual terminal number in case we don't have a - * com port. Zero is probably correct in case someone calls udbg - * before the init. The property is a pair of numbers. The first - * is the starting termno (the one we use) and the second is the - * number of terminals. - */ - np = find_path_device("/rtas"); - if (np) { - u32 *termno = (u32 *)get_property(np, "ibm,termno", 0); - if (termno) - vtermno = termno[0]; - } - ppc_md.udbg_putc = udbg_putcLP; - ppc_md.udbg_getc = udbg_getcLP; - ppc_md.udbg_getc_poll = udbg_getc_pollLP; + if (0 == find_udbg_vterm()) { + printk(KERN_WARNING + "can't use stdout; can't print early debug messages.\n"); + } } int hvc_get_chars(int index, char *buf, int count) @@ -285,23 +353,28 @@ int hvc_put_chars(int index, const char return -1; } +/* return the number of client vterms present */ +/* XXX this requires an interface change to handle multiple discontiguous + * vterms */ int hvc_count(int *start_termno) { - u32 *termno; - struct device_node *dn; + struct device_node *vty; + int num_found = 0; - if ((dn = find_path_device("/rtas")) != NULL) { - if ((termno = (u32 *)get_property(dn, "ibm,termno", 0)) != NULL) { - if (start_termno) - *start_termno = termno[0]; - return termno[1]; - } + /* consider only the first vty node. + * we should _always_ be able to find one. */ + vty = of_find_node_by_name(NULL, "vty"); + if (vty && device_is_compatible(vty, "hvterm1")) { + u32 *termno = (u32 *)get_property(vty, "reg", 0); + + if (termno && start_termno) + *start_termno = *termno; + num_found = 1; + of_node_put(vty); } - return 0; -} - - + return num_found; +} long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, diff -puN arch/ppc64/kernel/pSeries_pci.c~linus arch/ppc64/kernel/pSeries_pci.c --- 25/arch/ppc64/kernel/pSeries_pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -176,6 +176,55 @@ int pci_read_irq_line(struct pci_dev *pc pci_name(pci_dev), pci_dev->irq); return 0; } +EXPORT_SYMBOL(pci_read_irq_line); + +#define ISA_SPACE_MASK 0x1 +#define ISA_SPACE_IO 0x1 + +static void pci_process_ISA_OF_ranges(struct device_node *isa_node, + unsigned long phb_io_base_phys, + void * phb_io_base_virt) +{ + struct isa_range *range; + unsigned long pci_addr; + unsigned int isa_addr; + unsigned int size; + int rlen = 0; + + range = (struct isa_range *) get_property(isa_node, "ranges", &rlen); + if (rlen < sizeof(struct isa_range)) { + printk(KERN_ERR "unexpected isa range size: %s\n", + __FUNCTION__); + return; + } + + /* From "ISA Binding to 1275" + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 1: an ISA address + * cells 2 - 4: a PCI address + * (size depending on dev->n_addr_cells) + * cell 5: the size of the range + */ + if ((range->isa_addr.a_hi && ISA_SPACE_MASK) == ISA_SPACE_IO) { + isa_addr = range->isa_addr.a_lo; + pci_addr = (unsigned long) range->pci_addr.a_mid << 32 | + range->pci_addr.a_lo; + + /* Assume these are both zero */ + if ((pci_addr != 0) || (isa_addr != 0)) { + printk(KERN_ERR "unexpected isa to pci mapping: %s\n", + __FUNCTION__); + return; + } + + size = PAGE_ALIGN(range->size); + + __ioremap_explicit(phb_io_base_phys, + (unsigned long) phb_io_base_virt, + size, _PAGE_NO_CACHE); + } +} static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose, struct device_node *dev, @@ -188,10 +237,11 @@ static void __init pci_process_bridge_OF struct resource *res; int np, na = prom_n_addr_cells(dev); unsigned long pci_addr, cpu_phys_addr; + struct device_node *isa_dn; np = na + 5; - /* + /* From "PCI Binding to 1275" * The ranges property is laid out as an array of elements, * each of which comprises: * cells 0 - 2: a PCI address @@ -215,12 +265,22 @@ static void __init pci_process_bridge_OF switch (ranges[0] >> 24) { case 1: /* I/O space */ hose->io_base_phys = cpu_phys_addr; - hose->io_base_virt = __ioremap(hose->io_base_phys, - size, _PAGE_NO_CACHE); + hose->io_base_virt = reserve_phb_iospace(size); + PPCDBG(PPCDBG_PHBINIT, + "phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n", + hose->global_number, hose->io_base_phys, + (unsigned long) hose->io_base_virt); + if (primary) { pci_io_base = (unsigned long)hose->io_base_virt; - if (find_type_devices("isa")) + isa_dn = of_find_node_by_type(NULL, "isa"); + if (isa_dn) { isa_io_base = pci_io_base; + of_node_put(isa_dn); + pci_process_ISA_OF_ranges(isa_dn, + hose->io_base_phys, + hose->io_base_virt); + } } res = &hose->io_resource; @@ -386,7 +446,7 @@ unsigned long __init find_and_init_phbs( unsigned int root_size_cells = 0; unsigned int index; unsigned int *opprop; - struct device_node *root = find_path_device("/"); + struct device_node *root = of_find_node_by_path("/"); read_pci_config = rtas_token("read-pci-config"); write_pci_config = rtas_token("write-pci-config"); @@ -402,7 +462,9 @@ unsigned long __init find_and_init_phbs( index = 0; - for (node = root->child; node != NULL; node = node->sibling) { + for (node = of_get_next_child(root, NULL); + node != NULL; + node = of_get_next_child(root, node)) { if (node->type == NULL || strcmp(node->type, "pci") != 0) continue; @@ -420,6 +482,7 @@ unsigned long __init find_and_init_phbs( index++; } + of_node_put(root); pci_devs_phb_init(); return 0; @@ -450,7 +513,7 @@ void pcibios_name_device(struct pci_dev #endif } -void __init pcibios_fixup_device_resources(struct pci_dev *dev, +void __devinit pcibios_fixup_device_resources(struct pci_dev *dev, struct pci_bus *bus) { /* Update device resources. */ @@ -469,8 +532,9 @@ void __init pcibios_fixup_device_resourc } } } +EXPORT_SYMBOL(pcibios_fixup_device_resources); -void __init pcibios_fixup_bus(struct pci_bus *bus) +void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = PCI_GET_PHB_PTR(bus); struct list_head *ln; @@ -519,18 +583,106 @@ void __init pcibios_fixup_bus(struct pci pcibios_fixup_device_resources(dev, bus); } } +EXPORT_SYMBOL(pcibios_fixup_bus); static void check_s7a(void) { struct device_node *root; char *model; - root = find_path_device("/"); + root = of_find_node_by_path("/"); if (root) { model = get_property(root, "model", NULL); if (model && !strcmp(model, "IBM,7013-S7A")) s7a_workaround = 1; + of_node_put(root); + } +} + +static int get_bus_io_range(struct pci_bus *bus, unsigned long *start_phys, + unsigned long *start_virt, unsigned long *size) +{ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + struct pci_bus_region region; + struct resource *res; + + if (bus->self) { + res = bus->resource[0]; + pcibios_resource_to_bus(bus->self, ®ion, res); + *start_phys = hose->io_base_phys + region.start; + *start_virt = (unsigned long) hose->io_base_virt + + region.start; + if (region.end > region.start) + *size = region.end - region.start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, region.start, region.end); + return 1; + } + + } else { + /* Root Bus */ + res = &hose->io_resource; + *start_phys = hose->io_base_phys; + *start_virt = (unsigned long) hose->io_base_virt; + if (res->end > res->start) + *size = res->end - res->start + 1; + else { + printk("%s(): unexpected region 0x%lx->0x%lx\n", + __FUNCTION__, res->start, res->end); + return 1; + } } + + return 0; +} + +int unmap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; + + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + if (iounmap_explicit((void *) start_virt, size)) + return 1; + + return 0; +} +EXPORT_SYMBOL(unmap_bus_range); + +int remap_bus_range(struct pci_bus *bus) +{ + unsigned long start_phys; + unsigned long start_virt; + unsigned long size; + + if (!bus) { + printk(KERN_ERR "%s() expected bus\n", __FUNCTION__); + return 1; + } + + if (get_bus_io_range(bus, &start_phys, &start_virt, &size)) + return 1; + if (__ioremap_explicit(start_phys, start_virt, size, _PAGE_NO_CACHE)) + return 1; + + return 0; +} +EXPORT_SYMBOL(remap_bus_range); + +static void phbs_fixup_io(void) +{ + struct pci_controller *hose; + + for (hose=hose_head;hose;hose=hose->next) + remap_bus_range(hose->bus); } extern void chrp_request_regions(void); @@ -544,6 +696,7 @@ void __init pcibios_final_fixup(void) while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) pci_read_irq_line(dev); + phbs_fixup_io(); chrp_request_regions(); pci_fix_bus_sysdata(); create_tce_tables(); diff -puN arch/ppc64/kernel/ras.c~linus arch/ppc64/kernel/ras.c --- 25/arch/ppc64/kernel/ras.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/ras.c 2004-01-19 22:17:21.000000000 -0800 @@ -70,27 +70,29 @@ static int __init init_ras_IRQ(void) struct device_node *np; unsigned int *ireg, len, i; - if((np = find_path_device("/event-sources/internal-errors")) && - (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", - &len))) { - for(i=0; i<(len / sizeof(*ireg)); i++) { + if ((np = of_find_node_by_path("/event-sources/internal-errors")) && + (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", + &len))) { + for (i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, ras_error_interrupt, 0, "RAS_ERROR", NULL); ireg++; } } + of_node_put(np); - if((np = find_path_device("/event-sources/epow-events")) && - (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", - &len))) { - for(i=0; i<(len / sizeof(*ireg)); i++) { + if ((np = of_find_node_by_path("/event-sources/epow-events")) && + (ireg = (unsigned int *)get_property(np, "open-pic-interrupt", + &len))) { + for (i=0; i<(len / sizeof(*ireg)); i++) { request_irq(virt_irq_create_mapping(*(ireg)) + NUM_8259_INTERRUPTS, ras_epow_interrupt, 0, "RAS_EPOW", NULL); ireg++; } } + of_node_put(np); return 1; } @@ -112,7 +114,7 @@ ras_epow_interrupt(int irq, void *dev_id status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, 0x500, irq, - EPOW_WARNING | POWERMGM_EVENTS, + RTAS_EPOW_WARNING | RTAS_POWERMGM_EVENTS, 1, /* Time Critical */ __pa(&log_entry), size); @@ -120,6 +122,10 @@ ras_epow_interrupt(int irq, void *dev_id *((unsigned long *)&log_entry), status); printk(KERN_WARNING "EPOW <0x%lx 0x%lx>\n",*((unsigned long *)&log_entry), status); + + /* format and print the extended information */ + log_error((char *)&log_entry, ERR_TYPE_RTAS_LOG, 0); + return IRQ_HANDLED; } @@ -137,15 +143,23 @@ ras_error_interrupt(int irq, void *dev_i struct rtas_error_log log_entry; unsigned int size = sizeof(log_entry); long status = 0xdeadbeef; + int fatal; status = rtas_call(rtas_token("check-exception"), 6, 1, NULL, 0x500, irq, - INTERNAL_ERROR, + RTAS_INTERNAL_ERROR, 1, /* Time Critical */ __pa(&log_entry), size); - if((status != 1) && - (log_entry.severity >= SEVERITY_ERROR_SYNC)) { + if ((status == 0) && (log_entry.severity >= SEVERITY_ERROR_SYNC)) + fatal = 1; + else + fatal = 0; + + /* format and print the extended information */ + log_error((char *)&log_entry, ERR_TYPE_RTAS_LOG, fatal); + + if (fatal) { udbg_printf("HW Error <0x%lx 0x%lx>\n", *((unsigned long *)&log_entry), status); printk(KERN_EMERG @@ -155,6 +169,7 @@ ras_error_interrupt(int irq, void *dev_i #ifndef DEBUG /* Don't actually power off when debugging so we can test * without actually failing while injecting errors. + * Error data will not be logged to syslog. */ ppc_md.power_off(); #endif diff -puN arch/ppc64/kernel/rtas.c~linus arch/ppc64/kernel/rtas.c --- 25/arch/ppc64/kernel/rtas.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtas.c 2004-01-19 22:17:21.000000000 -0800 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,8 @@ #include #include #include +#include +#include struct flash_block_list_header rtas_firmware_flash_list = {0, 0}; @@ -59,7 +62,7 @@ struct rtas_t rtas = { extern unsigned long reloc_offset(void); spinlock_t rtas_data_buf_lock = SPIN_LOCK_UNLOCKED; -char rtas_data_buf[RTAS_DATA_BUF_SIZE]; +char rtas_data_buf[RTAS_DATA_BUF_SIZE]__page_aligned; void phys_call_rtas(int token, int nargs, int nret, ...) @@ -180,23 +183,98 @@ rtas_call(int token, int nargs, int nret } /* Given an RTAS status code of 990n compute the hinted delay of 10^n - * (last digit) milliseconds. For now we bound at n=3 (1 sec). + * (last digit) milliseconds. For now we bound at n=5 (100 sec). */ unsigned int rtas_extended_busy_delay_time(int status) { int order = status - 9900; - unsigned int ms; + unsigned long ms; if (order < 0) order = 0; /* RTC depends on this for -2 clock busy */ - else if (order > 3) - order = 3; /* bound */ + else if (order > 5) + order = 5; /* bound */ /* Use microseconds for reasonable accuracy */ - for (ms = 1000; order > 0; order--) - ms = ms * 10; - return ms / (1000000/HZ); /* round down is fine */ + for (ms=1; order > 0; order--) + ms *= 10; + + return ms; +} + +int +rtas_get_power_level(int powerdomain, int *level) +{ + int token = rtas_token("get-power-level"); + long powerlevel; + int rc; + + if (token == RTAS_UNKNOWN_SERVICE) + return RTAS_UNKNOWN_OP; + + while(1) { + rc = (int) rtas_call(token, 1, 2, &powerlevel, powerdomain); + if (rc == RTAS_BUSY) + udelay(1); + else + break; + } + *level = (int) powerlevel; + return rc; +} + +int +rtas_get_sensor(int sensor, int index, int *state) +{ + int token = rtas_token("get-sensor-state"); + unsigned int wait_time; + long returned_state; + int rc; + + if (token == RTAS_UNKNOWN_SERVICE) + return RTAS_UNKNOWN_OP; + + while (1) { + rc = (int) rtas_call(token, 2, 2, &returned_state, sensor, + index); + if (rc == RTAS_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } + else + break; + } + *state = (int) returned_state; + return rc; +} + +int +rtas_set_indicator(int indicator, int index, int new_value) +{ + int token = rtas_token("set-indicator"); + unsigned int wait_time; + int rc; + + if (token == RTAS_UNKNOWN_SERVICE) + return RTAS_UNKNOWN_OP; + + while (1) { + rc = (int) rtas_call(token, 3, 1, NULL, indicator, index, + new_value); + if (rc == RTAS_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } + else + break; + } + + return rc; } #define FLASH_BLOCK_LIST_VERSION (1UL) @@ -308,9 +386,51 @@ rtas_halt(void) rtas_power_off(); } -EXPORT_SYMBOL(proc_ppc64); +unsigned long rtas_rmo_buf = 0; + +asmlinkage int ppc_rtas(struct rtas_args __user *uargs) +{ + struct rtas_args args; + unsigned long flags; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) + return -EFAULT; + + if (args.nargs > ARRAY_SIZE(args.args) + || args.nret > ARRAY_SIZE(args.args) + || args.nargs + args.nret > ARRAY_SIZE(args.args)) + return -EINVAL; + + /* Copy in args. */ + if (copy_from_user(args.args, uargs->args, + args.nargs * sizeof(rtas_arg_t)) != 0) + return -EFAULT; + + spin_lock_irqsave(&rtas.lock, flags); + get_paca()->xRtas = args; + enter_rtas((void *)__pa((unsigned long)&get_paca()->xRtas)); + args = get_paca()->xRtas; + spin_unlock_irqrestore(&rtas.lock, flags); + + /* Copy out args. */ + if (copy_to_user(uargs->args + args.nargs, + args.args + args.nargs, + args.nret * sizeof(rtas_arg_t)) != 0) + return -EFAULT; + + return 0; +} + + EXPORT_SYMBOL(rtas_firmware_flash_list); EXPORT_SYMBOL(rtas_token); EXPORT_SYMBOL(rtas_call); EXPORT_SYMBOL(rtas_data_buf); EXPORT_SYMBOL(rtas_data_buf_lock); +EXPORT_SYMBOL(rtas_extended_busy_delay_time); +EXPORT_SYMBOL(rtas_get_sensor); +EXPORT_SYMBOL(rtas_get_power_level); +EXPORT_SYMBOL(rtas_set_indicator); diff -puN arch/ppc64/kernel/rtasd.c~linus arch/ppc64/kernel/rtasd.c --- 25/arch/ppc64/kernel/rtasd.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtasd.c 2004-01-19 22:17:21.000000000 -0800 @@ -17,11 +17,15 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #if 0 #define DEBUG(A...) printk(KERN_ERR A) @@ -29,36 +33,184 @@ #define DEBUG(A...) #endif -static spinlock_t rtas_log_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t log_lock = SPIN_LOCK_UNLOCKED; DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); -#define LOG_NUMBER 64 /* must be a power of two */ -#define LOG_NUMBER_MASK (LOG_NUMBER-1) - static char *rtas_log_buf; static unsigned long rtas_log_start; static unsigned long rtas_log_size; -static int surveillance_requested; +static int surveillance_timeout = -1; static unsigned int rtas_event_scan_rate; static unsigned int rtas_error_log_max; +static unsigned int rtas_error_log_buffer_max; -#define EVENT_SCAN_ALL_EVENTS 0xf0000000 -#define SURVEILLANCE_TOKEN 9000 -#define SURVEILLANCE_TIMEOUT 1 -#define SURVEILLANCE_SCANRATE 1 +extern spinlock_t proc_ppc64_lock; +extern volatile int no_more_logging; -struct proc_dir_entry *proc_rtas; +volatile int error_log_cnt = 0; /* * Since we use 32 bit RTAS, the physical address of this must be below * 4G or else bad things happen. Allocate this in the kernel data and * make it big enough. */ -#define RTAS_ERROR_LOG_MAX 1024 static unsigned char logdata[RTAS_ERROR_LOG_MAX]; +/* To see this info, grep RTAS /var/log/messages and each entry + * will be collected together with obvious begin/end. + * There will be a unique identifier on the begin and end lines. + * This will persist across reboots. + * + * format of error logs returned from RTAS: + * bytes (size) : contents + * -------------------------------------------------------- + * 0-7 (8) : rtas_error_log + * 8-47 (40) : extended info + * 48-51 (4) : vendor id + * 52-1023 (vendor specific) : location code and debug data + */ +static void printk_log_rtas(char *buf, int len) +{ + + int i,j,n; + int perline = 16; + char buffer[64]; + char * str = "RTAS event"; + + printk(RTAS_ERR "%d -------- %s begin --------\n", error_log_cnt, str); + + /* + * Print perline bytes on each line, each line will start + * with RTAS and a changing number, so syslogd will + * print lines that are otherwise the same. Separate every + * 4 bytes with a space. + */ + for (i=0; i < len; i++) { + j = i % perline; + if (j == 0) { + memset(buffer, 0, sizeof(buffer)); + n = sprintf(buffer, "RTAS %d:", i/perline); + } + + if ((i % 4) == 0) + n += sprintf(buffer+n, " "); + + n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]); + + if (j == (perline-1)) + printk(KERN_ERR "%s\n", buffer); + } + if ((i % perline) != 0) + printk(KERN_ERR "%s\n", buffer); + + printk(RTAS_ERR "%d -------- %s end ----------\n", error_log_cnt, str); +} + +static int log_rtas_len(char * buf) +{ + int len; + struct rtas_error_log *err; + + /* rtas fixed header */ + len = 8; + err = (struct rtas_error_log *)buf; + if (err->extended_log_length) { + + /* extended header */ + len += err->extended_log_length; + + if (len > RTAS_ERROR_LOG_MAX) + len = RTAS_ERROR_LOG_MAX; + } + return len; +} + +/* + * First write to nvram, if fatal error, that is the only + * place we log the info. The error will be picked up + * on the next reboot by rtasd. If not fatal, run the + * method for the type of error. Currently, only RTAS + * errors have methods implemented, but in the future + * there might be a need to store data in nvram before a + * call to panic(). + * + * XXX We write to nvram periodically, to indicate error has + * been written and sync'd, but there is a possibility + * that if we don't shutdown correctly, a duplicate error + * record will be created on next reboot. + */ +void pSeries_log_error(char *buf, unsigned int err_type, int fatal) +{ + unsigned long offset; + unsigned long s; + int len = 0; + + DEBUG("logging event\n"); + + if (buf == NULL) + return; + + spin_lock_irqsave(&log_lock, s); + + /* get length and increase count */ + switch (err_type & ERR_TYPE_MASK) { + case ERR_TYPE_RTAS_LOG: + len = log_rtas_len(buf); + if (!(err_type & ERR_FLAG_BOOT)) + error_log_cnt++; + break; + case ERR_TYPE_KERNEL_PANIC: + default: + spin_unlock_irqrestore(&log_lock, s); + return; + } + + /* Write error to NVRAM */ + if (!no_more_logging && !(err_type & ERR_FLAG_BOOT)) + nvram_write_error_log(buf, len, err_type); + + /* Check to see if we need to or have stopped logging */ + if (fatal || no_more_logging) { + no_more_logging = 1; + spin_unlock_irqrestore(&log_lock, s); + return; + } + + /* call type specific method for error */ + switch (err_type & ERR_TYPE_MASK) { + case ERR_TYPE_RTAS_LOG: + /* put into syslog and error_log file */ + printk_log_rtas(buf, len); + + offset = rtas_error_log_buffer_max * + ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); + + /* First copy over sequence number */ + memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int)); + + /* Second copy over error log data */ + offset += sizeof(int); + memcpy(&rtas_log_buf[offset], buf, len); + + if (rtas_log_size < LOG_NUMBER) + rtas_log_size += 1; + else + rtas_log_start += 1; + + spin_unlock_irqrestore(&log_lock, s); + wake_up_interruptible(&rtas_log_wait); + break; + case ERR_TYPE_KERNEL_PANIC: + default: + spin_unlock_irqrestore(&log_lock, s); + return; + } + +} + + static int rtas_log_open(struct inode * inode, struct file * file) { return 0; @@ -69,36 +221,50 @@ static int rtas_log_release(struct inode return 0; } +/* This will check if all events are logged, if they are then, we + * know that we can safely clear the events in NVRAM. + * Next we'll sit and wait for something else to log. + */ static ssize_t rtas_log_read(struct file * file, char * buf, size_t count, loff_t *ppos) { int error; char *tmp; + unsigned long s; unsigned long offset; - if (!buf || count < rtas_error_log_max) + if (!buf || count < rtas_error_log_buffer_max) return -EINVAL; - count = rtas_error_log_max; + count = rtas_error_log_buffer_max; error = verify_area(VERIFY_WRITE, buf, count); if (error) - return -EINVAL; + return -EFAULT; - tmp = kmalloc(rtas_error_log_max, GFP_KERNEL); + tmp = kmalloc(count, GFP_KERNEL); if (!tmp) return -ENOMEM; + + spin_lock_irqsave(&log_lock, s); + /* if it's 0, then we know we got the last one (the one in NVRAM) */ + if (rtas_log_size == 0 && !no_more_logging) + nvram_clear_error_log(); + spin_unlock_irqrestore(&log_lock, s); + + error = wait_event_interruptible(rtas_log_wait, rtas_log_size); if (error) goto out; - spin_lock(&rtas_log_lock); - offset = rtas_error_log_max * (rtas_log_start & LOG_NUMBER_MASK); + spin_lock_irqsave(&log_lock, s); + offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK); memcpy(tmp, &rtas_log_buf[offset], count); + rtas_log_start += 1; rtas_log_size -= 1; - spin_unlock(&rtas_log_lock); + spin_unlock_irqrestore(&log_lock, s); error = copy_to_user(buf, tmp, count) ? -EFAULT : count; out: @@ -121,42 +287,18 @@ struct file_operations proc_rtas_log_ope .release = rtas_log_release, }; -static void log_rtas(char *buf) -{ - unsigned long offset; - - DEBUG("logging rtas event\n"); - - spin_lock(&rtas_log_lock); - - offset = rtas_error_log_max * - ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK); - - memcpy(&rtas_log_buf[offset], buf, rtas_error_log_max); - - if (rtas_log_size < LOG_NUMBER) - rtas_log_size += 1; - else - rtas_log_start += 1; - - spin_unlock(&rtas_log_lock); - wake_up_interruptible(&rtas_log_wait); -} - -static int enable_surveillance(void) +static int enable_surveillance(int timeout) { int error; error = rtas_call(rtas_token("set-indicator"), 3, 1, NULL, - SURVEILLANCE_TOKEN, 0, SURVEILLANCE_TIMEOUT); + SURVEILLANCE_TOKEN, 0, timeout); if (error) { printk(KERN_ERR "rtasd: could not enable surveillance\n"); return -1; } - rtas_event_scan_rate = SURVEILLANCE_SCANRATE; - return 0; } @@ -165,11 +307,12 @@ static int get_eventscan_parms(void) struct device_node *node; int *ip; - node = find_path_device("/rtas"); + node = of_find_node_by_path("/rtas"); ip = (int *)get_property(node, "rtas-event-scan-rate", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-event-scan-rate\n"); + of_node_put(node); return -1; } rtas_event_scan_rate = *ip; @@ -178,6 +321,7 @@ static int get_eventscan_parms(void) ip = (int *)get_property(node, "rtas-error-log-max", NULL); if (ip == NULL) { printk(KERN_ERR "rtasd: no rtas-error-log-max\n"); + of_node_put(node); return -1; } rtas_error_log_max = *ip; @@ -187,6 +331,7 @@ static int get_eventscan_parms(void) printk(KERN_ERR "rtasd: truncated error log from %d to %d bytes\n", rtas_error_log_max, RTAS_ERROR_LOG_MAX); rtas_error_log_max = RTAS_ERROR_LOG_MAX; } + of_node_put(node); return 0; } @@ -195,10 +340,12 @@ extern long sys_sched_get_priority_max(i static int rtasd(void *unused) { + unsigned int err_type; int cpu = 0; int error; int first_pass = 1; int event_scan = rtas_token("event-scan"); + int rc; if (event_scan == RTAS_UNKNOWN_SERVICE || get_eventscan_parms() == -1) goto error; @@ -209,6 +356,9 @@ static int rtasd(void *unused) goto error; } + /* We can use rtas_log_buf now */ + no_more_logging = 0; + DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2); daemonize("rtasd"); @@ -219,6 +369,16 @@ static int rtasd(void *unused) current->nice = sys_sched_get_priority_max(SCHED_FIFO) + 1; #endif + /* See if we have any error stored in NVRAM */ + memset(logdata, 0, rtas_error_log_max); + + rc = nvram_read_error_log(logdata, rtas_error_log_max, &err_type); + if (!rc) { + if (err_type != ERR_FLAG_ALREADY_LOGGED) { + pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0); + } + } + repeat: for (cpu = 0; cpu < NR_CPUS; cpu++) { if (!cpu_online(cpu)) @@ -231,7 +391,7 @@ repeat: do { memset(logdata, 0, rtas_error_log_max); error = rtas_call(event_scan, 4, 1, NULL, - EVENT_SCAN_ALL_EVENTS, 0, + RTAS_EVENT_SCAN_ALL_EVENTS, 0, __pa(logdata), rtas_error_log_max); if (error == -1) { printk(KERN_ERR "event-scan failed\n"); @@ -239,7 +399,7 @@ repeat: } if (error == 0) - log_rtas(logdata); + pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG, 0); } while(error == 0); @@ -252,9 +412,9 @@ repeat: schedule_timeout(first_pass ? HZ : (HZ*60/rtas_event_scan_rate) / 2); } - if (first_pass && surveillance_requested) { + if (first_pass && (surveillance_timeout != -1)) { DEBUG("enabling surveillance\n"); - if (enable_surveillance()) + if (enable_surveillance(surveillance_timeout)) goto error_vfree; DEBUG("surveillance enabled\n"); } @@ -273,25 +433,29 @@ static int __init rtas_init(void) { struct proc_dir_entry *entry; - if (proc_rtas == NULL) { - proc_rtas = proc_mkdir("rtas", 0); + if (proc_ppc64.rtas == NULL) { + proc_ppc64_init(); } - if (proc_rtas == NULL) { - printk(KERN_ERR "Failed to create /proc/rtas in rtas_init\n"); - } else { - entry = create_proc_entry("error_log", S_IRUSR, proc_rtas); - if (entry) - entry->proc_fops = &proc_rtas_log_operations; - else - printk(KERN_ERR "Failed to create rtas/error_log proc entry\n"); + if (proc_ppc64.rtas == NULL) { + printk(KERN_ERR "rtas_init: /proc/ppc64/rtas does not exist."); + return -EIO; } + entry = create_proc_entry("error_log", S_IRUSR, proc_ppc64.rtas); + if (entry) + entry->proc_fops = &proc_rtas_log_operations; + else + printk(KERN_ERR "Failed to create rtas/error_log proc entry\n"); + if (kernel_thread(rtasd, 0, CLONE_FS) < 0) printk(KERN_ERR "Failed to start RTAS daemon\n"); printk(KERN_ERR "RTAS daemon started\n"); + /* Make room for the sequence number */ + rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int); + return 0; } @@ -300,8 +464,8 @@ static int __init surveillance_setup(cha int i; if (get_option(&str,&i)) { - if (i == 1) - surveillance_requested = 1; + if (i >= 0 && i <= 255) + surveillance_timeout = i; } return 1; diff -puN arch/ppc64/kernel/rtas_flash.c~linus arch/ppc64/kernel/rtas_flash.c --- 25/arch/ppc64/kernel/rtas_flash.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtas_flash.c 2004-01-19 22:17:21.000000000 -0800 @@ -14,15 +14,64 @@ */ #include -#include + +#include #include +#include +#include #include #include #define MODULE_VERSION "1.0" #define MODULE_NAME "rtas_flash" -#define FIRMWARE_FLASH_NAME "firmware_flash" +#define FIRMWARE_FLASH_NAME "firmware_flash" +#define FIRMWARE_UPDATE_NAME "firmware_update" +#define MANAGE_FLASH_NAME "manage_flash" +#define VALIDATE_FLASH_NAME "validate_flash" + +/* General RTAS Status Codes */ +#define RTAS_RC_SUCCESS 0 +#define RTAS_RC_HW_ERR -1 +#define RTAS_RC_BUSY -2 + +/* Flash image status values */ +#define FLASH_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define FLASH_NO_OP -1099 /* No operation initiated by user */ +#define FLASH_IMG_SHORT -1005 /* Flash image shorter than expected */ +#define FLASH_IMG_BAD_LEN -1004 /* Bad length value in flash list block */ +#define FLASH_IMG_NULL_DATA -1003 /* Bad data value in flash list block */ +#define FLASH_IMG_READY 0 /* Firmware img ready for flash on reboot */ + +/* Manage image status values */ +#define MANAGE_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define MANAGE_ACTIVE_ERR -9001 /* RTAS Cannot Overwrite Active Img */ +#define MANAGE_NO_OP -1099 /* No operation initiated by user */ +#define MANAGE_PARAM_ERR -3 /* RTAS Parameter Error */ +#define MANAGE_HW_ERR -1 /* RTAS Hardware Error */ + +/* Validate image status values */ +#define VALIDATE_AUTH -9002 /* RTAS Not Service Authority Partition */ +#define VALIDATE_NO_OP -1099 /* No operation initiated by the user */ +#define VALIDATE_INCOMPLETE -1002 /* User copied < VALIDATE_BUF_SIZE */ +#define VALIDATE_READY -1001 /* Firmware image ready for validation */ +#define VALIDATE_PARAM_ERR -3 /* RTAS Parameter Error */ +#define VALIDATE_HW_ERR -1 /* RTAS Hardware Error */ +#define VALIDATE_TMP_UPDATE 0 /* Validate Return Status */ +#define VALIDATE_FLASH_AUTH 1 /* Validate Return Status */ +#define VALIDATE_INVALID_IMG 2 /* Validate Return Status */ +#define VALIDATE_CUR_UNKNOWN 3 /* Validate Return Status */ +#define VALIDATE_TMP_COMMIT_DL 4 /* Validate Return Status */ +#define VALIDATE_TMP_COMMIT 5 /* Validate Return Status */ +#define VALIDATE_TMP_UPDATE_DL 6 /* Validate Return Status */ + +/* ibm,manage-flash-image operation tokens */ +#define RTAS_REJECT_TMP_IMG 0 +#define RTAS_COMMIT_TMP_IMG 1 + +/* Array sizes */ +#define VALIDATE_BUF_SIZE 4096 +#define RTAS_MSG_MAXLEN 64 /* Local copy of the flash block list. * We only allow one open of the flash proc file and create this @@ -34,21 +83,35 @@ * is treated as the number of entries currently in the block * (i.e. not a byte count). This is all fixed on release. */ -static struct flash_block_list *flist; -static char *flash_msg; -static int flash_possible; - -static int rtas_flash_open(struct inode *inode, struct file *file) -{ - if ((file->f_mode & FMODE_WRITE) && flash_possible) { - if (flist) - return -EBUSY; - flist = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); - if (!flist) - return -ENOMEM; - } - return 0; -} + +/* Status int must be first member of struct */ +struct rtas_update_flash_t +{ + int status; /* Flash update status */ + struct flash_block_list *flist; /* Local copy of flash block list */ +}; + +/* Status int must be first member of struct */ +struct rtas_manage_flash_t +{ + int status; /* Returned status */ + unsigned int op; /* Reject or commit image */ +}; + +/* Status int must be first member of struct */ +struct rtas_validate_flash_t +{ + int status; /* Returned status */ + char buf[VALIDATE_BUF_SIZE]; /* Candidate image buffer */ + unsigned int buf_size; /* Size of image buf */ + unsigned int update_results; /* Update results token */ +}; + +static spinlock_t flash_file_open_lock = SPIN_LOCK_UNLOCKED; +static struct proc_dir_entry *firmware_flash_pde = NULL; +static struct proc_dir_entry *firmware_update_pde = NULL; +static struct proc_dir_entry *validate_pde = NULL; +static struct proc_dir_entry *manage_pde = NULL; /* Do simple sanity checks on the flash image. */ static int flash_list_valid(struct flash_block_list *flist) @@ -57,32 +120,29 @@ static int flash_list_valid(struct flash int i; unsigned long block_size, image_size; - flash_msg = NULL; /* Paranoid self test here. We also collect the image size. */ image_size = 0; for (f = flist; f; f = f->next) { for (i = 0; i < f->num_blocks; i++) { if (f->blocks[i].data == NULL) { - flash_msg = "error: internal error null data\n"; - return 0; + return FLASH_IMG_NULL_DATA; } block_size = f->blocks[i].length; if (block_size <= 0 || block_size > PAGE_SIZE) { - flash_msg = "error: internal error bad length\n"; - return 0; + return FLASH_IMG_BAD_LEN; } image_size += block_size; } } + if (image_size < (256 << 10)) { - if (image_size < 2) - flash_msg = NULL; /* allow "clear" of image */ - else - flash_msg = "error: flash image short\n"; - return 0; + if (image_size < 2) + return FLASH_NO_OP; } + printk(KERN_INFO "FLASH: flash image with %ld bytes stored for hardware flash on reboot\n", image_size); - return 1; + + return FLASH_IMG_READY; } static void free_flash_list(struct flash_block_list *f) @@ -101,40 +161,80 @@ static void free_flash_list(struct flash static int rtas_flash_release(struct inode *inode, struct file *file) { - if (flist) { - /* Always clear saved list on a new attempt. */ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; + + uf = (struct rtas_update_flash_t *) dp->data; + if (uf->flist) { + /* File was opened in write mode for a new flash attempt */ + /* Clear saved list */ if (rtas_firmware_flash_list.next) { free_flash_list(rtas_firmware_flash_list.next); rtas_firmware_flash_list.next = NULL; } - if (flash_list_valid(flist)) - rtas_firmware_flash_list.next = flist; + if (uf->status != FLASH_AUTH) + uf->status = flash_list_valid(uf->flist); + + if (uf->status == FLASH_IMG_READY) + rtas_firmware_flash_list.next = uf->flist; else - free_flash_list(flist); - flist = NULL; + free_flash_list(uf->flist); + + uf->flist = NULL; } + + atomic_dec(&dp->count); return 0; } +static void get_flash_status_msg(int status, char *buf) +{ + char *msg; + + switch (status) { + case FLASH_AUTH: + msg = "error: this partition does not have service authority\n"; + break; + case FLASH_NO_OP: + msg = "info: no firmware image for flash\n"; + break; + case FLASH_IMG_SHORT: + msg = "error: flash image short\n"; + break; + case FLASH_IMG_BAD_LEN: + msg = "error: internal error bad length\n"; + break; + case FLASH_IMG_NULL_DATA: + msg = "error: internal error null data\n"; + break; + case FLASH_IMG_READY: + msg = "ready: firmware image ready for flash on reboot\n"; + break; + default: + sprintf(buf, "error: unexpected status value %d\n", status); + return; + } + + strcpy(buf, msg); +} + /* Reading the proc file will show status (not the firmware contents) */ static ssize_t rtas_flash_read(struct file *file, char *buf, size_t count, loff_t *ppos) { + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; + char msg[RTAS_MSG_MAXLEN]; int error; - char *msg; int msglen; - if (!flash_possible) { - msg = "error: this partition does not have service authority\n"; - } else if (flist) { - msg = "info: this file is busy for write by some process\n"; - } else if (flash_msg) { - msg = flash_msg; /* message from last flash attempt */ - } else if (rtas_firmware_flash_list.next) { - msg = "ready: firmware image ready for flash on reboot\n"; - } else { - msg = "info: no firmware image for flash\n"; + uf = (struct rtas_update_flash_t *) dp->data; + + if (!strcmp(dp->name, FIRMWARE_FLASH_NAME)) { + get_flash_status_msg(uf->status, msg); + } else { /* FIRMWARE_UPDATE_NAME */ + sprintf(msg, "%d\n", uf->status); } msglen = strlen(msg); if (msglen > count) @@ -147,7 +247,8 @@ static ssize_t rtas_flash_read(struct fi if (error) return -EINVAL; - copy_to_user(buf, msg, msglen); + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; if (ppos) *ppos = msglen; @@ -162,14 +263,28 @@ static ssize_t rtas_flash_read(struct fi static ssize_t rtas_flash_write(struct file *file, const char *buffer, size_t count, loff_t *off) { - size_t len = count; + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_update_flash_t *uf; char *p; int next_free; - struct flash_block_list *fl = flist; + struct flash_block_list *fl; + + uf = (struct rtas_update_flash_t *) dp->data; - if (!flash_possible || len == 0) - return len; /* discard data */ + if (uf->status == FLASH_AUTH || count == 0) + return count; /* discard data */ + /* In the case that the image is not ready for flashing, the memory + * allocated for the block list will be freed upon the release of the + * proc file + */ + if (uf->flist == NULL) { + uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); + if (!uf->flist) + return -ENOMEM; + } + + fl = uf->flist; while (fl->next) fl = fl->next; /* seek to last block_list for append */ next_free = fl->num_blocks; @@ -182,47 +297,392 @@ static ssize_t rtas_flash_write(struct f next_free = 0; } - if (len > PAGE_SIZE) - len = PAGE_SIZE; + if (count > PAGE_SIZE) + count = PAGE_SIZE; p = (char *)get_zeroed_page(GFP_KERNEL); if (!p) return -ENOMEM; - if(copy_from_user(p, buffer, len)) { + + if(copy_from_user(p, buffer, count)) { free_page((unsigned long)p); return -EFAULT; } fl->blocks[next_free].data = p; - fl->blocks[next_free].length = len; + fl->blocks[next_free].length = count; fl->num_blocks++; - return len; + return count; +} + +static int rtas_excl_open(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(inode); + + /* Enforce exclusive open with use count of PDE */ + spin_lock(&flash_file_open_lock); + if (atomic_read(&dp->count) > 1) { + spin_unlock(&flash_file_open_lock); + return -EBUSY; + } + + atomic_inc(&dp->count); + spin_unlock(&flash_file_open_lock); + + return 0; +} + +static int rtas_excl_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(inode); + + atomic_dec(&dp->count); + + return 0; +} + +static void manage_flash(struct rtas_manage_flash_t *args_buf) +{ + unsigned int wait_time; + s32 rc; + + while (1) { + rc = (s32) rtas_call(rtas_token("ibm,manage-flash-image"), 1, + 1, NULL, (long) args_buf->op); + if (rc == RTAS_RC_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } + + args_buf->status = rc; +} + +static ssize_t manage_flash_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_manage_flash_t *args_buf; + char msg[RTAS_MSG_MAXLEN]; + int msglen; + int error; + + args_buf = (struct rtas_manage_flash_t *) dp->data; + if (args_buf == NULL) + return 0; + + msglen = sprintf(msg, "%d\n", args_buf->status); + if (msglen > count) + msglen = count; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + error = verify_area(VERIFY_WRITE, buf, msglen); + if (error) + return -EINVAL; + + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; + + if (ppos) + *ppos = msglen; + return msglen; +} + +static ssize_t manage_flash_write(struct file *file, const char *buf, + size_t count, loff_t *off) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_manage_flash_t *args_buf; + const char reject_str[] = "0"; + const char commit_str[] = "1"; + char stkbuf[10]; + int op; + + args_buf = (struct rtas_manage_flash_t *) dp->data; + if ((args_buf->status == MANAGE_AUTH) || (count == 0)) + return count; + + op = -1; + if (buf) { + if (count > 9) count = 9; + if (copy_from_user (stkbuf, buf, count)) { + return -EFAULT; + } + if (strncmp(stkbuf, reject_str, strlen(reject_str)) == 0) + op = RTAS_REJECT_TMP_IMG; + else if (strncmp(stkbuf, commit_str, strlen(commit_str)) == 0) + op = RTAS_COMMIT_TMP_IMG; + } + + if (op == -1) /* buf is empty, or contains invalid string */ + return -EINVAL; + + args_buf->op = op; + manage_flash(args_buf); + + return count; +} + +static void validate_flash(struct rtas_validate_flash_t *args_buf) +{ + int token = rtas_token("ibm,validate-flash-image"); + unsigned int wait_time; + long update_results; + s32 rc; + + rc = 0; + while(1) { + spin_lock(&rtas_data_buf_lock); + memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); + rc = (s32) rtas_call(token, 2, 2, &update_results, + __pa(rtas_data_buf), args_buf->buf_size); + memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); + spin_unlock(&rtas_data_buf_lock); + + if (rc == RTAS_RC_BUSY) + udelay(1); + else if (rtas_is_extended_busy(rc)) { + wait_time = rtas_extended_busy_delay_time(rc); + udelay(wait_time * 1000); + } else + break; + } + + args_buf->status = rc; + args_buf->update_results = (u32) update_results; +} + +static int get_validate_flash_msg(struct rtas_validate_flash_t *args_buf, + char *msg) +{ + int n; + + if (args_buf->status >= VALIDATE_TMP_UPDATE) { + n = sprintf(msg, "%d\n", args_buf->update_results); + if ((args_buf->update_results >= VALIDATE_CUR_UNKNOWN) || + (args_buf->update_results == VALIDATE_TMP_UPDATE)) + n += sprintf(msg + n, "%s\n", args_buf->buf); + } else { + n = sprintf(msg, "%d\n", args_buf->status); + } + return n; +} + +static ssize_t validate_flash_read(struct file *file, char *buf, + size_t count, loff_t *ppos) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + char msg[RTAS_MSG_MAXLEN]; + int msglen; + int error; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (ppos && *ppos != 0) + return 0; /* be cheap */ + + msglen = get_validate_flash_msg(args_buf, msg); + if (msglen > count) + msglen = count; + + error = verify_area(VERIFY_WRITE, buf, msglen); + if (error) + return -EINVAL; + + if (copy_to_user(buf, msg, msglen)) + return -EFAULT; + + if (ppos) + *ppos = msglen; + return msglen; +} + +static ssize_t validate_flash_write(struct file *file, const char *buf, + size_t count, loff_t *off) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + int rc; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (dp->data == NULL) { + dp->data = kmalloc(sizeof(struct rtas_validate_flash_t), + GFP_KERNEL); + if (dp->data == NULL) + return -ENOMEM; + } + + /* We are only interested in the first 4K of the + * candidate image */ + if ((*off >= VALIDATE_BUF_SIZE) || + (args_buf->status == VALIDATE_AUTH)) { + *off += count; + return count; + } + + if (*off + count >= VALIDATE_BUF_SIZE) { + count = VALIDATE_BUF_SIZE - *off; + args_buf->status = VALIDATE_READY; + } else { + args_buf->status = VALIDATE_INCOMPLETE; + } + + if (verify_area(VERIFY_READ, buf, count)) { + rc = -EFAULT; + goto done; + } + if (copy_from_user(args_buf->buf + *off, buf, count)) { + rc = -EFAULT; + goto done; + } + + *off += count; + rc = count; +done: + if (rc < 0) { + kfree(dp->data); + dp->data = NULL; + } + return rc; +} + +static int validate_flash_release(struct inode *inode, struct file *file) +{ + struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode); + struct rtas_validate_flash_t *args_buf; + + args_buf = (struct rtas_validate_flash_t *) dp->data; + + if (args_buf->status == VALIDATE_READY) { + args_buf->buf_size = VALIDATE_BUF_SIZE; + validate_flash(args_buf); + } + + atomic_dec(&dp->count); + + return 0; +} + +static inline void remove_flash_pde(struct proc_dir_entry *dp) +{ + if (dp) { + if (dp->data != NULL) + kfree(dp->data); + remove_proc_entry(dp->name, proc_ppc64.rtas); + } +} + +static inline int initialize_flash_pde_data(const char *rtas_call_name, + size_t buf_size, + struct proc_dir_entry *dp) +{ + int *status; + int token; + + dp->data = kmalloc(buf_size, GFP_KERNEL); + if (dp->data == NULL) { + remove_flash_pde(dp); + return -ENOMEM; + } + + memset(dp->data, 0, buf_size); + + /* This code assumes that the status int is the first member of the + * struct + */ + status = (int *) dp->data; + token = rtas_token(rtas_call_name); + if (token == RTAS_UNKNOWN_SERVICE) + *status = FLASH_AUTH; + else + *status = FLASH_NO_OP; + + return 0; +} + +static inline struct proc_dir_entry * create_flash_pde(const char *filename, + struct file_operations *fops) +{ + struct proc_dir_entry *ent = NULL; + + ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, proc_ppc64.rtas); + if (ent != NULL) { + ent->nlink = 1; + ent->proc_fops = fops; + ent->owner = THIS_MODULE; + } + + return ent; } static struct file_operations rtas_flash_operations = { .read = rtas_flash_read, .write = rtas_flash_write, - .open = rtas_flash_open, + .open = rtas_excl_open, .release = rtas_flash_release, }; +static struct file_operations manage_flash_operations = { + .read = manage_flash_read, + .write = manage_flash_write, + .open = rtas_excl_open, + .release = rtas_excl_release, +}; + +static struct file_operations validate_flash_operations = { + .read = validate_flash_read, + .write = validate_flash_write, + .open = rtas_excl_open, + .release = validate_flash_release, +}; int __init rtas_flash_init(void) { - struct proc_dir_entry *ent = NULL; + int rc; if (!proc_ppc64.rtas) { printk(KERN_WARNING "rtas proc dir does not already exist"); return -ENOENT; } - if (rtas_token("ibm,update-flash-64-and-reboot") != RTAS_UNKNOWN_SERVICE) - flash_possible = 1; - - if ((ent = create_proc_entry(FIRMWARE_FLASH_NAME, S_IRUSR | S_IWUSR, proc_ppc64.rtas)) != NULL) { - ent->nlink = 1; - ent->proc_fops = &rtas_flash_operations; - ent->owner = THIS_MODULE; - } + firmware_flash_pde = create_flash_pde(FIRMWARE_FLASH_NAME, + &rtas_flash_operations); + rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", + sizeof(struct rtas_update_flash_t), + firmware_flash_pde); + if (rc != 0) + return rc; + + firmware_update_pde = create_flash_pde(FIRMWARE_UPDATE_NAME, + &rtas_flash_operations); + rc = initialize_flash_pde_data("ibm,update-flash-64-and-reboot", + sizeof(struct rtas_update_flash_t), + firmware_update_pde); + if (rc != 0) + return rc; + + validate_pde = create_flash_pde(VALIDATE_FLASH_NAME, + &validate_flash_operations); + rc = initialize_flash_pde_data("ibm,validate-flash-image", + sizeof(struct rtas_validate_flash_t), + validate_pde); + if (rc != 0) + return rc; + + manage_pde = create_flash_pde(MANAGE_FLASH_NAME, + &manage_flash_operations); + rc = initialize_flash_pde_data("ibm,manage-flash-image", + sizeof(struct rtas_manage_flash_t), + manage_pde); + if (rc != 0) + return rc; + return 0; } @@ -230,7 +690,10 @@ void __exit rtas_flash_cleanup(void) { if (!proc_ppc64.rtas) return; - remove_proc_entry(FIRMWARE_FLASH_NAME, proc_ppc64.rtas); + remove_flash_pde(firmware_flash_pde); + remove_flash_pde(firmware_update_pde); + remove_flash_pde(validate_pde); + remove_flash_pde(manage_pde); } module_init(rtas_flash_init); diff -puN arch/ppc64/kernel/rtas-proc.c~linus arch/ppc64/kernel/rtas-proc.c --- 25/arch/ppc64/kernel/rtas-proc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtas-proc.c 2004-01-19 22:17:21.000000000 -0800 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,7 @@ #include #include #include +#include #include /* for ppc_md */ #include @@ -161,6 +163,8 @@ static ssize_t ppc_rtas_tone_volume_writ size_t count, loff_t *ppos); static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf, size_t count, loff_t *ppos); +static ssize_t ppc_rtas_rmo_buf_read(struct file *file, char *buf, + size_t count, loff_t *ppos); struct file_operations ppc_rtas_poweron_operations = { .read = ppc_rtas_poweron_read, @@ -185,6 +189,10 @@ struct file_operations ppc_rtas_tone_vol .write = ppc_rtas_tone_volume_write }; +static struct file_operations ppc_rtas_rmo_buf_ops = { + .read = ppc_rtas_rmo_buf_read, +}; + int ppc_rtas_find_all_sensors (void); int ppc_rtas_process_sensor(struct individual_sensor s, int state, int error, char * buf); @@ -200,39 +208,42 @@ void proc_rtas_init(void) { struct proc_dir_entry *entry; - rtas_node = find_devices("rtas"); + rtas_node = of_find_node_by_name(NULL, "rtas"); if ((rtas_node == NULL) || (systemcfg->platform == PLATFORM_ISERIES_LPAR)) { return; } - if (proc_rtas == NULL) { - proc_rtas = proc_mkdir("rtas", 0); + if (proc_ppc64.rtas == NULL) { + proc_ppc64_init(); } - if (proc_rtas == NULL) { + if (proc_ppc64.rtas == NULL) { printk(KERN_ERR "Failed to create /proc/rtas in proc_rtas_init\n"); return; } /* /proc/rtas entries */ - entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas); + entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_ppc64.rtas); if (entry) entry->proc_fops = &ppc_rtas_progress_operations; - entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); + entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_ppc64.rtas); if (entry) entry->proc_fops = &ppc_rtas_clock_operations; - entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); + entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_ppc64.rtas); if (entry) entry->proc_fops = &ppc_rtas_poweron_operations; - create_proc_read_entry("sensors", S_IRUGO, proc_rtas, + create_proc_read_entry("sensors", S_IRUGO, proc_ppc64.rtas, ppc_rtas_sensor_read, NULL); - entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); + entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_ppc64.rtas); if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations; - entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); + entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_ppc64.rtas); if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations; + + entry = create_proc_entry("rmo_buffer", S_IRUSR, proc_ppc64.rtas); + if (entry) entry->proc_fops = &ppc_rtas_rmo_buf_ops; } /* ****************************************************************** */ @@ -919,3 +930,28 @@ static ssize_t ppc_rtas_tone_volume_read *ppos += n; return n; } + +#define RMO_READ_BUF_MAX 30 + +/* RTAS Userspace access */ +static ssize_t ppc_rtas_rmo_buf_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + char kbuf[RMO_READ_BUF_MAX]; + int n; + + n = sprintf(kbuf, "%016lx %x\n", rtas_rmo_buf, RTAS_RMOBUF_MAX); + if (n > count) + n = count; + + if (ppos && *ppos != 0) + return 0; + + if (copy_to_user(buf, kbuf, n)) + return -EFAULT; + + if (ppos) + *ppos = n; + + return n; +} diff -puN arch/ppc64/kernel/rtc.c~linus arch/ppc64/kernel/rtc.c --- 25/arch/ppc64/kernel/rtc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/rtc.c 2004-01-19 22:17:21.000000000 -0800 @@ -99,6 +99,7 @@ static int rtc_ioctl(struct inode *inode switch (cmd) { case RTC_RD_TIME: /* Read the time/date from RTC */ { + memset(&wtime, 0, sizeof(struct rtc_time)); ppc_md.get_rtc_time(&wtime); break; } diff -puN arch/ppc64/kernel/scanlog.c~linus arch/ppc64/kernel/scanlog.c --- 25/arch/ppc64/kernel/scanlog.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/scanlog.c 2004-01-19 22:17:21.000000000 -0800 @@ -28,6 +28,7 @@ #include #include #include +#include #define MODULE_VERSION "1.0" #define MODULE_NAME "scanlog" @@ -43,9 +44,6 @@ static int scanlog_debug; static unsigned int ibm_scan_log_dump; /* RTAS token */ static struct proc_dir_entry *proc_ppc64_scan_log_dump; /* The proc file */ -extern struct proc_dir_entry *proc_rtas; - - static ssize_t scanlog_read(struct file *file, char *buf, size_t count, loff_t *ppos) { @@ -214,15 +212,16 @@ int __init scanlog_init(void) return -EIO; } - if (proc_rtas == NULL) - proc_rtas = proc_mkdir("rtas", 0); + if (proc_ppc64.rtas == NULL) { + proc_ppc64_init(); + } - if (proc_rtas == NULL) { + if (proc_ppc64.rtas == NULL) { printk(KERN_ERR "Failed to create /proc/rtas in scanlog_init\n"); return -EIO; } - ent = create_proc_entry("scan-log-dump", S_IRUSR, proc_rtas); + ent = create_proc_entry("scan-log-dump", S_IRUSR, proc_ppc64.rtas); if (ent) { ent->proc_fops = &scanlog_fops; /* Ideally we could allocate a buffer < 4G */ diff -puN arch/ppc64/kernel/setup.c~linus arch/ppc64/kernel/setup.c --- 25/arch/ppc64/kernel/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -58,6 +58,9 @@ extern void iSeries_init_early( void ); extern void pSeries_init_early( void ); extern void pSeriesLP_init_early(void); extern void mm_init_ppc64( void ); +extern void pseries_secondary_smp_init(unsigned long); +extern int idle_setup(void); +extern void vpa_init(int cpu); unsigned long decr_overclock = 1; unsigned long decr_overclock_proc0 = 1; @@ -137,12 +140,16 @@ void __init disable_early_printk(void) } /* - * Do some initial setup of the system. The paramters are those which + * Do some initial setup of the system. The parameters are those which * were passed in from the bootloader. */ void setup_system(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { +#ifdef CONFIG_PPC_PSERIES + unsigned int ret, i; +#endif + #ifdef CONFIG_XMON_DEFAULT debugger = xmon; debugger_bpt = xmon_bpt; @@ -183,10 +190,33 @@ void setup_system(unsigned long r3, unsi #endif } +#ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; register_console(&udbg_console); + finish_device_tree(); + chrp_init(r3, r4, r5, r6, r7); + +#ifdef CONFIG_SMP + /* Start secondary threads on SMT systems */ + for (i = 0; i < NR_CPUS; i++) { + if(cpu_available(i) && !cpu_possible(i)) { + printk("%16.16x : starting thread\n", i); + rtas_call(rtas_token("start-cpu"), 3, 1, + (void *)&ret, + get_hard_smp_processor_id(i), + *((unsigned long *)pseries_secondary_smp_init), i); + cpu_set(i, cpu_possible_map); + systemcfg->processorCount++; + } + } +#endif } +#endif + /* Finish initializing the hash table (do the dynamic + * patching for the fast-path hashtable.S code) + */ + htab_finish_init(); printk("Starting Linux PPC64 %s\n", UTS_RELEASE); @@ -204,12 +234,16 @@ void setup_system(unsigned long r3, unsi printk("htab_data.num_ptegs = 0x%lx\n", htab_data.htab_num_ptegs); printk("-----------------------------------------------------\n"); - if (systemcfg->platform & PLATFORM_PSERIES) { - finish_device_tree(); - chrp_init(r3, r4, r5, r6, r7); + mm_init_ppc64(); + +#if defined(CONFIG_SMP) && defined(CONFIG_PPC_PSERIES) + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + vpa_init(boot_cpuid); } +#endif - mm_init_ppc64(); + /* Select the correct idle loop for the platform. */ + idle_setup(); switch (systemcfg->platform) { #ifdef CONFIG_PPC_ISERIES @@ -277,36 +311,19 @@ static int show_cpuinfo(struct seq_file seq_printf(m, "processor\t: %lu\n", cpu_id); seq_printf(m, "cpu\t\t: "); - switch (PVR_VER(pvr)) { - case PV_NORTHSTAR: - seq_printf(m, "RS64-II (northstar)\n"); - break; - case PV_PULSAR: - seq_printf(m, "RS64-III (pulsar)\n"); - break; - case PV_POWER4: - seq_printf(m, "POWER4 (gp)\n"); - break; - case PV_ICESTAR: - seq_printf(m, "RS64-III (icestar)\n"); - break; - case PV_SSTAR: - seq_printf(m, "RS64-IV (sstar)\n"); - break; - case PV_POWER4p: - seq_printf(m, "POWER4+ (gq)\n"); - break; - case PV_630: - seq_printf(m, "POWER3 (630)\n"); - break; - case PV_630p: - seq_printf(m, "POWER3 (630+)\n"); - break; - default: - seq_printf(m, "Unknown (%08x)\n", pvr); - break; - } + if (cur_cpu_spec->pvr_mask) + seq_printf(m, "%s", cur_cpu_spec->cpu_name); + else + seq_printf(m, "unknown (%08x)", pvr); + +#ifdef CONFIG_ALTIVEC + if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC) + seq_printf(m, ", altivec supported"); +#endif /* CONFIG_ALTIVEC */ + seq_printf(m, "\n"); + +#ifdef CONFIG_PPC_PSERIES /* * Assume here that all clock rates are the same in a * smp system. -- Cort @@ -315,15 +332,17 @@ static int show_cpuinfo(struct seq_file struct device_node *cpu_node; int *fp; - cpu_node = find_type_devices("cpu"); + cpu_node = of_find_node_by_type(NULL, "cpu"); if (cpu_node) { fp = (int *) get_property(cpu_node, "clock-frequency", NULL); if (fp) seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000); + of_node_put(cpu_node); } } +#endif if (ppc_md.setup_residual != NULL) ppc_md.setup_residual(m, cpu_id); @@ -353,13 +372,11 @@ struct seq_operations cpuinfo_op = { }; /* - * Fetch the cmd_line from open firmware. */ + * Fetch the cmd_line from open firmware. + */ void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { - struct device_node *chosen; - char *p; - #ifdef CONFIG_BLK_DEV_INITRD if ((initrd_start == 0) && r3 && r4 && r4 != 0xdeadbeef) { initrd_start = (r3 >= KERNELBASE) ? r3 : (unsigned long)__va(r3); @@ -375,12 +392,20 @@ void parse_cmd_line(unsigned long r3, un strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ - chosen = find_devices("chosen"); +#ifdef CONFIG_PPC_PSERIES + { + struct device_node *chosen; + + chosen = of_find_node_by_name(NULL, "chosen"); if (chosen != NULL) { + char *p; p = get_property(chosen, "bootargs", NULL); if (p != NULL && p[0] != 0) strlcpy(cmd_line, p, sizeof(cmd_line)); + of_node_put(chosen); } + } +#endif /* Look for mem= option on command line */ if (strstr(cmd_line, "mem=")) { @@ -406,28 +431,7 @@ void parse_cmd_line(unsigned long r3, un } -char *bi_tag2str(unsigned long tag) -{ - switch (tag) { - case BI_FIRST: - return "BI_FIRST"; - case BI_LAST: - return "BI_LAST"; - case BI_CMD_LINE: - return "BI_CMD_LINE"; - case BI_BOOTLOADER_ID: - return "BI_BOOTLOADER_ID"; - case BI_INITRD: - return "BI_INITRD"; - case BI_SYSMAP: - return "BI_SYSMAP"; - case BI_MACHTYPE: - return "BI_MACHTYPE"; - default: - return "BI_UNKNOWN"; - } -} - +#ifdef CONFIG_PPC_PSERIES int parse_bootinfo(void) { struct bi_record *rec; @@ -445,8 +449,7 @@ int parse_bootinfo(void) memcpy(cmd_line, (void *)rec->data, rec->size); break; case BI_SYSMAP: - sysmap = (char *)((rec->data[0] >= (KERNELBASE)) - ? rec->data[0] : (unsigned long)__va(rec->data[0])); + sysmap = __va(rec->data[0]); sysmap_size = rec->data[1]; break; #ifdef CONFIG_BLK_DEV_INITRD @@ -462,6 +465,7 @@ int parse_bootinfo(void) return 0; } +#endif int __init ppc_init(void) { @@ -486,7 +490,6 @@ void __init ppc64_calibrate_delay(void) } extern void (*calibrate_delay)(void); -extern void sort_exception_table(void); /* * Called into from start_kernel, after lock_kernel has been called. @@ -534,7 +537,6 @@ void __init setup_arch(char **cmdline_p) ppc_md.setup_arch(); paging_init(); - sort_exception_table(); ppc64_boot_msg(0x15, "Setup Done"); } diff -puN arch/ppc64/kernel/signal32.c~linus arch/ppc64/kernel/signal32.c --- 25/arch/ppc64/kernel/signal32.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/signal32.c 2004-01-19 22:17:21.000000000 -0800 @@ -32,71 +32,207 @@ #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -/* - * These are the flags in the MSR that the user is allowed to change - * by modifying the saved value of the MSR on the stack. SE and BE - * should not be in this list since gdb may want to change these. I.e, - * you should be able to step out of a signal handler to see what - * instruction executes next after the signal handler completes. - * Alternately, if you stepped into a signal handler, you should be - * able to continue 'til the next breakpoint from within the signal - * handler, even if the handler returns. - */ -#if 0 -#define MSR_USERCHANGE (MSR_FE0 | MSR_FE1) -#else + +#define GP_REGS_SIZE32 min(sizeof(elf_gregset_t32), sizeof(struct pt_regs32)) + /* - * glibc tries to set FE0/FE1 via a signal handler. Since it only ever - * sets both bits and this is the default setting we now disable this - * behaviour. This is done to insure the new prctl which alters FE0/FE1 does - * not get overriden by glibc. Setting and clearing FE0/FE1 via signal - * handler has always been bogus since load_up_fpu used to set FE0/FE1 - * unconditionally. + * When we have signals to deliver, we set up on the + * user stack, going down from the original stack pointer: + * a sigregs32 struct + * a sigcontext32 struct + * a gap of __SIGNAL_FRAMESIZE32 bytes + * + * Each of these things must be a multiple of 16 bytes in size. + * */ -#define MSR_USERCHANGE 0 -#endif - struct sigregs32 { - /* - * the gp_regs array is 32 bit representation of the pt_regs - * structure that was stored on the kernel stack during the - * system call that was interrupted for the signal. - * - * Note that the entire pt_regs regs structure will fit in - * the gp_regs structure because the ELF_NREG value is 48 for - * PPC and the pt_regs structure contains 44 registers - */ - elf_gregset_t32 gp_regs; - double fp_regs[ELF_NFPREG]; - unsigned int tramp[2]; + struct mcontext32 mctx; /* all the register values */ /* * Programs using the rs6000/xcoff abi can save up to 19 gp * regs and 18 fp regs below sp before decrementing it. */ - int abigap[56]; + int abigap[56]; }; +/* We use the mc_pad field for the signal return trampoline. */ +#define tramp mc_pad -struct rt_sigframe_32 { - /* - * Unused space at start of frame to allow for storing of - * stack pointers - */ - unsigned long _unused; +/* + * When we have rt signals to deliver, we set up on the + * user stack, going down from the original stack pointer: + * one rt_sigframe32 struct (siginfo + ucontext + ABI gap) + * a gap of __SIGNAL_FRAMESIZE32+16 bytes + * (the +16 is to get the siginfo and ucontext32 in the same + * positions as in older kernels). + * + * Each of these things must be a multiple of 16 bytes in size. + * + */ +struct rt_sigframe32 { + struct compat_siginfo info; + struct ucontext32 uc; /* - * This is a 32 bit pointer in user address space - * it is a pointer to the siginfo stucture in the rt stack frame + * Programs using the rs6000/xcoff abi can save up to 19 gp + * regs and 18 fp regs below sp before decrementing it. */ - u32 pinfo; + int abigap[56]; +}; + + +/* + * Common utility functions used by signal and context support + * + */ + +/* + * Restore the user process's signal mask + * (implemented in signal.c) + */ +extern void restore_sigmask(sigset_t *set); + +/* + * Functions for flipping sigsets (thanks to brain dead generic + * implementation that makes things simple for little endian only + */ +static inline void compat_from_sigset(compat_sigset_t *compat, sigset_t *set) +{ + switch (_NSIG_WORDS) { + case 4: compat->sig[5] = set->sig[3] & 0xffffffffull ; + compat->sig[7] = set->sig[3] >> 32; + case 3: compat->sig[4] = set->sig[2] & 0xffffffffull ; + compat->sig[5] = set->sig[2] >> 32; + case 2: compat->sig[2] = set->sig[1] & 0xffffffffull ; + compat->sig[3] = set->sig[1] >> 32; + case 1: compat->sig[0] = set->sig[0] & 0xffffffffull ; + compat->sig[1] = set->sig[0] >> 32; + } +} + +static inline void sigset_from_compat(sigset_t *set, compat_sigset_t *compat) +{ + switch (_NSIG_WORDS) { + case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32); + case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32); + case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32); + case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32); + } +} + + +/* + * Save the current user registers on the user stack. + * We only save the altivec registers if the process has used + * altivec instructions at some point. + */ +static int save_user_regs(struct pt_regs *regs, struct mcontext32 *frame, int sigret) +{ + elf_greg_t64 *gregs = (elf_greg_t64 *)regs; + int i, err = 0; + + /* Make sure floating point registers are stored in regs */ + if (regs->msr & MSR_FP) + giveup_fpu(current); + + /* save general and floating-point registers */ + for (i = 0; i <= PT_RESULT; i ++) + err |= __put_user((unsigned int)gregs[i], &frame->mc_gregs[i]); + err |= __copy_to_user(&frame->mc_fregs, current->thread.fpr, + ELF_NFPREG * sizeof(double)); + if (err) + return 1; + + current->thread.fpscr = 0; /* turn off all fp exceptions */ + +#ifdef CONFIG_ALTIVEC + /* save altivec registers */ + if (current->thread.used_vr) { + if (regs->msr & MSR_VEC) + giveup_altivec(current); + if (__copy_to_user(&frame->mc_vregs, current->thread.vr, + ELF_NVRREG32 * sizeof(vector128))) + return 1; + /* set MSR_VEC in the saved MSR value to indicate that + frame->mc_vregs contains valid data */ + if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR])) + return 1; + } + /* else assert((regs->msr & MSR_VEC) == 0) */ + + /* We always copy to/from vrsave, it's 0 if we don't have or don't + * use altivec. Since VSCR only contains 32 bits saved in the least + * significant bits of a vector, we "cheat" and stuff VRSAVE in the + * most significant bits of that same vector. --BenH + */ + if (__put_user(current->thread.vrsave, (u32 *)&frame->mc_vregs[32])) + return 1; +#endif /* CONFIG_ALTIVEC */ + + if (sigret) { + /* Set up the sigreturn trampoline: li r0,sigret; sc */ + if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) + || __put_user(0x44000002UL, &frame->tramp[1])) + return 1; + flush_icache_range((unsigned long) &frame->tramp[0], + (unsigned long) &frame->tramp[2]); + } + + return 0; +} + +/* + * Restore the current user register values from the user stack, + * (except for MSR). + */ +static int restore_user_regs(struct pt_regs *regs, struct mcontext32 __user *sr, int sig) +{ + elf_greg_t64 *gregs = (elf_greg_t64 *)regs; + int i, err = 0; + unsigned int save_r2; +#ifdef CONFIG_ALTIVEC + unsigned long msr; +#endif + /* - * This is a 32 bit pointer in user address space - * it is a pointer to the user context in the rt stack frame + * restore general registers but not including MSR. Also take + * care of keeping r2 (TLS) intact if not a signal */ - u32 puc; - struct siginfo32 info; - struct ucontext32 uc; -}; + if (!sig) + save_r2 = (unsigned int)regs->gpr[2]; + for (i = 0; i < PT_MSR; i ++) + err |= __get_user(gregs[i], &sr->mc_gregs[i]); + for (i ++; i <= PT_RESULT; i ++) + err |= __get_user(gregs[i], &sr->mc_gregs[i]); + if (!sig) + regs->gpr[2] = (unsigned long) save_r2; + if (err) + return 1; + + /* force the process to reload the FP registers from + current->thread when it next does FP instructions */ + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); + if (__copy_from_user(current->thread.fpr, &sr->mc_fregs, + sizeof(sr->mc_fregs))) + return 1; + +#ifdef CONFIG_ALTIVEC + /* force the process to reload the altivec registers from + current->thread when it next does altivec instructions */ + regs->msr &= ~MSR_VEC; + if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { + /* restore altivec registers from the stack */ + if (__copy_from_user(current->thread.vr, &sr->mc_vregs, + sizeof(sr->mc_vregs))) + return 1; + } else if (current->thread.used_vr) + memset(¤t->thread.vr, 0, ELF_NVRREG32 * sizeof(vector128)); + + /* Always get VRSAVE back */ + if (__get_user(current->thread.vrsave, (u32 *)&sr->mc_vregs[32])) + return 1; +#endif /* CONFIG_ALTIVEC */ + return 0; +} /* @@ -181,209 +317,6 @@ long sys32_sigaction(int sig, struct old } -/* - * When we have signals to deliver, we set up on the - * user stack, going down from the original stack pointer: - * a sigregs struct - * one or more sigcontext structs - * a gap of __SIGNAL_FRAMESIZE32 bytes - * - * Each of these things must be a multiple of 16 bytes in size. - * - */ - - -/* - * Do a signal return; undo the signal stack. - */ -long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs *regs) -{ - struct sigcontext32 *sc, sigctx; - struct sigregs32 *sr; - int ret; - elf_gregset_t32 saved_regs; /* an array of ELF_NGREG unsigned ints (32 bits) */ - sigset_t set; - int i; - - sc = (struct sigcontext32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); - if (copy_from_user(&sigctx, sc, sizeof(sigctx))) - goto badframe; - - /* - * Note that PPC32 puts the upper 32 bits of the sigmask in the - * unused part of the signal stackframe - */ - set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32); - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - if (regs->msr & MSR_FP ) - giveup_fpu(current); - /* Last stacked signal - restore registers */ - sr = (struct sigregs32*)(u64)sigctx.regs; - /* - * copy the 32 bit register values off the user stack - * into the 32 bit register area - */ - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - /* - * The saved reg structure in the frame is an elf_grepset_t32, - * it is a 32 bit register save of the registers in the - * pt_regs structure that was stored on the kernel stack - * during the system call when the system call was interrupted - * for the signal. Only 32 bits are saved because the - * sigcontext contains a pointer to the regs and the sig - * context address is passed as a pointer to the signal - * handler. - * - * The entries in the elf_grepset have the same index as the - * elements in the pt_regs structure. - */ - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - /* - * Register 2 is the kernel toc - should be reset on - * any calls into the kernel - */ - for (i = 0; i < 32; i++) - regs->gpr[i] = (u64)(saved_regs[i]) & 0xFFFFFFFF; - - /* - * restore the non gpr registers - */ - regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; - /* - * Insure that the interrupt mode is 64 bit, during 32 bit - * execution. (This is necessary because we only saved - * lower 32 bits of msr.) - */ - regs->msr = regs->msr | MSR_ISF; /* When this thread is interrupted it should run in 64 bit mode. */ - - regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; - regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; - regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; - regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; - regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; - regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; - /* regs->softe is left unchanged (like the MSR.EE bit) */ - /******************************************************/ - /* the DAR and the DSISR are only relevant during a */ - /* data or instruction storage interrupt. The value */ - /* will be set to zero. */ - /******************************************************/ - regs->dar = 0; - regs->dsisr = 0; - regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; - - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - - ret = regs->result; - return ret; - -badframe: - do_exit(SIGSEGV); -} - -/* - * Set up a signal frame. - */ -static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, - unsigned int newsp) -{ - struct sigcontext32 *sc = (struct sigcontext32 *)(u64)newsp; - int i; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); - - /* - * Copy the register contents for the pt_regs structure on the - * kernel stack to the elf_gregset_t32 structure on the user - * stack. This is a copy of 64 bit register values to 32 bit - * register values. The high order 32 bits of the 64 bit - * registers are not needed since a 32 bit application is - * running and the saved registers are the contents of the - * user registers at the time of a system call. - * - * The values saved on the user stack will be restored into - * the registers during the signal return processing - */ - for (i = 0; i < 32; i++) { - if (__put_user((u32)regs->gpr[i], &frame->gp_regs[i])) - goto badframe; - } - - /* - * Copy the non gpr registers to the user stack - */ - if (__put_user((u32)regs->gpr[PT_NIP], &frame->gp_regs[PT_NIP]) - || __put_user((u32)regs->gpr[PT_MSR], &frame->gp_regs[PT_MSR]) - || __put_user((u32)regs->gpr[PT_ORIG_R3], &frame->gp_regs[PT_ORIG_R3]) - || __put_user((u32)regs->gpr[PT_CTR], &frame->gp_regs[PT_CTR]) - || __put_user((u32)regs->gpr[PT_LNK], &frame->gp_regs[PT_LNK]) - || __put_user((u32)regs->gpr[PT_XER], &frame->gp_regs[PT_XER]) - || __put_user((u32)regs->gpr[PT_CCR], &frame->gp_regs[PT_CCR]) -#if 0 - || __put_user((u32)regs->gpr[PT_MQ], &frame->gp_regs[PT_MQ]) -#endif - || __put_user((u32)regs->gpr[PT_RESULT], &frame->gp_regs[PT_RESULT])) - goto badframe; - - - /* - * Now copy the floating point registers onto the user stack - * - * Also set up so on the completion of the signal handler, the - * sys_sigreturn will get control to reset the stack - */ - if (__copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - /* li r0, __NR_sigreturn */ - || __put_user(0x38000000U + __NR_sigreturn, &frame->tramp[0]) - /* sc */ - || __put_user(0x44000002U, &frame->tramp[1])) - goto badframe; - flush_icache_range((unsigned long)&frame->tramp[0], - (unsigned long)&frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ - - newsp -= __SIGNAL_FRAMESIZE32; - if (put_user(regs->gpr[1], (u32*)(u64)newsp) - || get_user(regs->nip, &sc->handler) - || get_user(regs->gpr[3], &sc->signal)) - goto badframe; - - regs->gpr[1] = newsp & 0xFFFFFFFF; - /* - * first parameter to the signal handler is the signal number - * - the value is in gpr3 - * second parameter to the signal handler is the sigcontext - * - set the value into gpr4 - */ - regs->gpr[4] = (unsigned long) sc; - regs->link = (unsigned long) frame->tramp; - return; - -badframe: -#if DEBUG_SIG - printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", - regs, frame, newsp); -#endif - do_exit(SIGSEGV); -} - /* * Start of RT signal support @@ -405,115 +338,6 @@ badframe: * siginfo32to64 */ -/* - * This code executes after the rt signal handler in 32 bit mode has - * completed and returned - */ -long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, unsigned long r8, - struct pt_regs * regs) -{ - struct rt_sigframe_32 *rt_sf; - struct sigcontext32 sigctx; - struct sigregs32 *sr; - int ret; - elf_gregset_t32 saved_regs; /* an array of 32 bit register values */ - sigset_t set; - stack_t st; - int i; - mm_segment_t old_fs; - - /* Always make any pending restarted system calls return -EINTR */ - current_thread_info()->restart_block.fn = do_no_restart_syscall; - - /* Adjust the inputted reg1 to point to the first rt signal frame */ - rt_sf = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); - /* Copy the information from the user stack */ - if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)) - || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set)) - || copy_from_user(&st,&rt_sf->uc.uc_stack, sizeof(st))) - goto badframe; - - /* - * Unblock the signal that was processed - * After a signal handler runs - - * if the signal is blockable - the signal will be unblocked - * (sigkill and sigstop are not blockable) - */ - sigdelsetmask(&set, ~_BLOCKABLE); - /* update the current based on the sigmask found in the rt_stackframe */ - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - /* If currently owning the floating point - give them up */ - if (regs->msr & MSR_FP) - giveup_fpu(current); - /* - * Set to point to the next rt_sigframe - this is used to - * determine whether this is the last signal to process - */ - sr = (struct sigregs32 *)(u64)sigctx.regs; - if (copy_from_user(saved_regs, &sr->gp_regs, sizeof(sr->gp_regs))) - goto badframe; - /* - * The saved reg structure in the frame is an elf_grepset_t32, - * it is a 32 bit register save of the registers in the - * pt_regs structure that was stored on the kernel stack - * during the system call when the system call was interrupted - * for the signal. Only 32 bits are saved because the - * sigcontext contains a pointer to the regs and the sig - * context address is passed as a pointer to the signal handler - * - * The entries in the elf_grepset have the same index as - * the elements in the pt_regs structure. - */ - saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) - | (saved_regs[PT_MSR] & MSR_USERCHANGE); - /* - * Register 2 is the kernel toc - should be reset on any - * calls into the kernel - */ - for (i = 0; i < 32; i++) - regs->gpr[i] = (u64)(saved_regs[i]) & 0xFFFFFFFF; - /* - * restore the non gpr registers - */ - regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; - regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; - regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; - regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; - regs->link = (u64)(saved_regs[PT_LNK]) & 0xFFFFFFFF; - regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; - regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; - /* regs->softe is left unchanged (like MSR.EE) */ - /* - * the DAR and the DSISR are only relevant during a - * data or instruction storage interrupt. The value - * will be set to zero. - */ - regs->dar = 0; - regs->dsisr = 0; - regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; - if (copy_from_user(current->thread.fpr, &sr->fp_regs, - sizeof(sr->fp_regs))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack(&st, NULL, regs->gpr[1]); - set_fs(old_fs); - - ret = regs->result; - return ret; - - badframe: - do_exit(SIGSEGV); -} - - long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, size_t sigsetsize) @@ -530,16 +354,7 @@ long sys32_rt_sigaction(int sig, const s ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); ret |= __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); - switch (_NSIG_WORDS) { - case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] - | (((long)set32.sig[7]) << 32); - case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] - | (((long)set32.sig[5]) << 32); - case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] - | (((long)set32.sig[3]) << 32); - case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] - | (((long)set32.sig[1]) << 32); - } + sigset_from_compat(&new_ka.sa.sa_mask, &set32); ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); if (ret) return -EFAULT; @@ -547,20 +362,7 @@ long sys32_rt_sigaction(int sig, const s ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { - switch (_NSIG_WORDS) { - case 4: - set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); - set32.sig[6] = old_ka.sa.sa_mask.sig[3]; - case 3: - set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); - set32.sig[4] = old_ka.sa.sa_mask.sig[2]; - case 2: - set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); - set32.sig[2] = old_ka.sa.sa_mask.sig[1]; - case 1: - set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); - set32.sig[0] = old_ka.sa.sa_mask.sig[0]; - } + compat_from_sigset(&set32, &old_ka.sa.sa_mask); ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)); @@ -586,14 +388,8 @@ long sys32_rt_sigprocmask(u32 how, compa if (set) { if (copy_from_user (&s32, set, sizeof(compat_sigset_t))) - return -EFAULT; - - switch (_NSIG_WORDS) { - case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - } + return -EFAULT; + sigset_from_compat(&s, &s32); } set_fs(KERNEL_DS); @@ -603,12 +399,7 @@ long sys32_rt_sigprocmask(u32 how, compa if (ret) return ret; if (oset) { - switch (_NSIG_WORDS) { - case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; - case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; - case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; - case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; - } + compat_from_sigset(&s32, &s); if (copy_to_user (oset, &s32, sizeof(compat_sigset_t))) return -EFAULT; } @@ -626,12 +417,7 @@ long sys32_rt_sigpending(compat_sigset_t ret = sys_rt_sigpending(&s, sigsetsize); set_fs(old_fs); if (!ret) { - switch (_NSIG_WORDS) { - case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; - case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; - case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; - case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; - } + compat_from_sigset(&s32, &s); if (copy_to_user (set, &s32, sizeof(compat_sigset_t))) return -EFAULT; } @@ -639,7 +425,7 @@ long sys32_rt_sigpending(compat_sigset_t } -static int copy_siginfo_to_user32(siginfo_t32 *d, siginfo_t *s) +static int copy_siginfo_to_user32(compat_siginfo_t *d, siginfo_t *s) { int err; @@ -681,7 +467,7 @@ static int copy_siginfo_to_user32(siginf return err; } -long sys32_rt_sigtimedwait(compat_sigset_t *uthese, siginfo_t32 *uinfo, +long sys32_rt_sigtimedwait(compat_sigset_t *uthese, compat_siginfo_t *uinfo, struct compat_timespec *uts, compat_size_t sigsetsize) { sigset_t s; @@ -693,12 +479,7 @@ long sys32_rt_sigtimedwait(compat_sigset if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) return -EFAULT; - switch (_NSIG_WORDS) { - case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - } + sigset_from_compat(&s, &s32); if (uts && get_compat_timespec(&t, uts)) return -EFAULT; set_fs(KERNEL_DS); @@ -714,7 +495,7 @@ long sys32_rt_sigtimedwait(compat_sigset -static siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s) +static siginfo_t * siginfo32to64(siginfo_t *d, compat_siginfo_t *s) { d->si_signo = s->si_signo; d->si_errno = s->si_errno; @@ -758,14 +539,14 @@ static siginfo_t * siginfo32to64(siginfo * (msr in 32-bit mode) and the register representation of a signed int * (msr in 64-bit mode) is performed. */ -long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) +long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t *uinfo) { siginfo_t info; - siginfo_t32 info32; + compat_siginfo_t info32; int ret; mm_segment_t old_fs = get_fs(); - if (copy_from_user (&info32, uinfo, sizeof(siginfo_t32))) + if (copy_from_user (&info32, uinfo, sizeof(compat_siginfo_t))) return -EFAULT; /* XXX: Is this correct? */ siginfo32to64(&info, &info32); @@ -793,15 +574,9 @@ int sys32_rt_sigsuspend(compat_sigset_t* * Swap the 2 words of the 64-bit sigset_t (they are stored * in the "wrong" endian in 32-bit user storage). */ - switch (_NSIG_WORDS) { - case 4: newset.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); - case 3: newset.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); - case 2: newset.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); - case 1: newset.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); - } + sigset_from_compat(&newset, &s32); sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; @@ -827,237 +602,324 @@ int sys32_rt_sigsuspend(compat_sigset_t* } } - /* - * Set up a rt signal frame. + * Start Alternate signal stack support + * + * System Calls + * sigaltatck sys32_sigaltstack */ -static void setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, - unsigned int newsp) + +int sys32_sigaltstack(u32 newstack, u32 oldstack, int r5, + int r6, int r7, int r8, struct pt_regs *regs) { - unsigned int copyreg4, copyreg5; - struct rt_sigframe_32 * rt_sf = (struct rt_sigframe_32 *) (u64)newsp; - int i; - - if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) - goto badframe; - if (regs->msr & MSR_FP) - giveup_fpu(current); + stack_t uss, uoss; + int ret; + mm_segment_t old_fs; + unsigned long sp; /* - * Copy the register contents for the pt_regs structure on the - * kernel stack to the elf_gregset_t32 structure on the user - * stack. This is a copy of 64 bit register values to 32 bit - * register values. The high order 32 bits of the 64 bit - * registers are not needed since a 32 bit application is - * running and the saved registers are the contents of the - * user registers at the time of a system call. - * - * The values saved on the user stack will be restored into - * the registers during the signal return processing + * set sp to the user stack on entry to the system call + * the system call router sets R9 to the saved registers */ - for (i = 0; i < 32; i++) { - if (__put_user((u32)regs->gpr[i], &frame->gp_regs[i])) - goto badframe; - } + sp = regs->gpr[1]; - /* - * Copy the non gpr registers to the user stack - */ - if (__put_user((u32)regs->gpr[PT_NIP], &frame->gp_regs[PT_NIP]) - || __put_user((u32)regs->gpr[PT_MSR], &frame->gp_regs[PT_MSR]) - || __put_user((u32)regs->gpr[PT_ORIG_R3], &frame->gp_regs[PT_ORIG_R3]) - || __put_user((u32)regs->gpr[PT_CTR], &frame->gp_regs[PT_CTR]) - || __put_user((u32)regs->gpr[PT_LNK], &frame->gp_regs[PT_LNK]) - || __put_user((u32)regs->gpr[PT_XER], &frame->gp_regs[PT_XER]) - || __put_user((u32)regs->gpr[PT_CCR], &frame->gp_regs[PT_CCR]) - || __put_user((u32)regs->gpr[PT_RESULT], &frame->gp_regs[PT_RESULT])) - goto badframe; + /* Put new stack info in local 64 bit stack struct */ + if (newstack && + (get_user((long)uss.ss_sp, + &((stack_32_t *)(long)newstack)->ss_sp) || + __get_user(uss.ss_flags, + &((stack_32_t *)(long)newstack)->ss_flags) || + __get_user(uss.ss_size, + &((stack_32_t *)(long)newstack)->ss_size))) + return -EFAULT; + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL, + sp); + set_fs(old_fs); + /* Copy the stack information to the user output buffer */ + if (!ret && oldstack && + (put_user((long)uoss.ss_sp, + &((stack_32_t *)(long)oldstack)->ss_sp) || + __put_user(uoss.ss_flags, + &((stack_32_t *)(long)oldstack)->ss_flags) || + __put_user(uoss.ss_size, + &((stack_32_t *)(long)oldstack)->ss_size))) + return -EFAULT; + return ret; +} - /* - * Now copy the floating point registers onto the user stack - * - * Also set up so on the completion of the signal handler, the - * sys_sigreturn will get control to reset the stack - */ - if (__copy_to_user(&frame->fp_regs, current->thread.fpr, - ELF_NFPREG * sizeof(double)) - || __put_user(0x38000000U + __NR_rt_sigreturn, &frame->tramp[0]) /* li r0, __NR_rt_sigreturn */ - || __put_user(0x44000002U, &frame->tramp[1])) /* sc */ + +/* + * Set up a signal frame for a "real-time" signal handler + * (one which gets siginfo). + */ +static void handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, unsigned long newsp) +{ + struct rt_sigframe32 __user *rt_sf; + struct mcontext32 __user *frame; + unsigned long origsp = newsp; + compat_sigset_t c_oldset; + + /* Set up Signal Frame */ + /* Put a Real Time Context onto stack */ + newsp -= sizeof(*rt_sf); + rt_sf = (struct rt_sigframe32 __user *)newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE32 + 16; + + if (verify_area(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) goto badframe; - flush_icache_range((unsigned long) &frame->tramp[0], - (unsigned long) &frame->tramp[2]); - current->thread.fpscr = 0; /* turn off all fp exceptions */ + compat_from_sigset(&c_oldset, oldset); - /* - * Retrieve rt_sigframe from stack and - * set up registers for signal handler - */ - newsp -= __SIGNAL_FRAMESIZE32; - + /* Put the siginfo & fill in most of the ucontext */ + if (copy_siginfo_to_user32(&rt_sf->info, info) + || __put_user(0, &rt_sf->uc.uc_flags) + || __put_user(0, &rt_sf->uc.uc_link) + || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) + || __put_user(sas_ss_flags(regs->gpr[1]), + &rt_sf->uc.uc_stack.ss_flags) + || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size) + || __put_user((u32)(u64)&rt_sf->uc.uc_mcontext, &rt_sf->uc.uc_regs) + || __copy_to_user(&rt_sf->uc.uc_sigmask, &c_oldset, sizeof(c_oldset))) + goto badframe; - if (put_user((u32)(regs->gpr[1]), (unsigned int *)(u64)newsp) - || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler) - || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal) - || get_user(copyreg4, &rt_sf->pinfo) - || get_user(copyreg5, &rt_sf->puc)) + /* Save user registers on the stack */ + frame = &rt_sf->uc.uc_mcontext; + if (save_user_regs(regs, frame, __NR_rt_sigreturn)) goto badframe; - regs->gpr[4] = copyreg4; - regs->gpr[5] = copyreg5; - regs->gpr[1] = newsp; + if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + goto badframe; + regs->gpr[1] = (unsigned long) newsp; + regs->gpr[3] = sig; + regs->gpr[4] = (unsigned long) &rt_sf->info; + regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[6] = (unsigned long) rt_sf; + regs->nip = (unsigned long) ka->sa.sa_handler; regs->link = (unsigned long) frame->tramp; + regs->trap = 0; return; badframe: #if DEBUG_SIG - printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", + printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } +static long do_setcontext32(struct ucontext32 __user *ucp, struct pt_regs *regs, int sig) +{ + compat_sigset_t c_set; + sigset_t set; + u32 mcp; + + if (__copy_from_user(&c_set, &ucp->uc_sigmask, sizeof(c_set)) + || __get_user(mcp, &ucp->uc_regs)) + return -EFAULT; + sigset_from_compat(&set, &c_set); + restore_sigmask(&set); + if (restore_user_regs(regs, (struct mcontext32 *)(u64)mcp, sig)) + return -EFAULT; + + return 0; +} /* - * OK, we're invoking a handler + * Handle {get,set,swap}_context operations for 32 bits processes */ -static void handle_signal32(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs * regs, unsigned int *newspp, - unsigned int frame) -{ - struct sigcontext32 *sc; - struct rt_sigframe_32 *rt_sf; - struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - - if (regs->trap == 0x0C00 /* System Call! */ - && ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTART_RESTARTBLOCK || - ((int)regs->result == -ERESTARTSYS && - !(ka->sa.sa_flags & SA_RESTART)))) { - if ((int)regs->result == -ERESTART_RESTARTBLOCK) - current_thread_info()->restart_block.fn - = do_no_restart_syscall; - regs->result = -EINTR; + +long sys32_swapcontext(struct ucontext32 __user *old_ctx, + struct ucontext32 __user *new_ctx, + int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) +{ + unsigned char tmp; + compat_sigset_t c_set; + + /* Context size is for future use. Right now, we only make sure + * we are passed something we understand + */ + if (ctx_size < sizeof(struct ucontext32)) + return -EINVAL; + + if (old_ctx != NULL) { + compat_from_sigset(&c_set, ¤t->blocked); + if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) + || save_user_regs(regs, &old_ctx->uc_mcontext, 0) + || __copy_to_user(&old_ctx->uc_sigmask, &c_set, sizeof(c_set)) + || __put_user((u32)(u64)&old_ctx->uc_mcontext, &old_ctx->uc_regs)) + return -EFAULT; } + if (new_ctx == NULL) + return 0; + if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx)) + || __get_user(tmp, (u8 *) new_ctx) + || __get_user(tmp, (u8 *) (new_ctx + 1) - 1)) + return -EFAULT; /* - * Set up the signal frame - * Determine if a real time frame and a siginfo is required + * If we get a fault copying the context into the kernel's + * image of the user's registers, we can't just return -EFAULT + * because the user's registers will be corrupted. For instance + * the NIP value may have been updated but not some of the + * other registers. Given that we have done the verify_area + * and successfully read the first and last bytes of the region + * above, this should only happen in an out-of-memory situation + * or if another thread unmaps the region containing the context. + * We kill the task with a SIGSEGV in this situation. */ - if (ka->sa.sa_flags & SA_SIGINFO) { - *newspp -= sizeof(*rt_sf); - rt_sf = (struct rt_sigframe_32 *)(u64)(*newspp); - if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf))) - goto badframe; - if (__put_user((u32)(u64)ka->sa.sa_handler, - &rt_sf->uc.uc_mcontext.handler) - || __put_user((u32)(u64)&rt_sf->info, &rt_sf->pinfo) - || __put_user((u32)(u64)&rt_sf->uc, &rt_sf->puc) - /* put the siginfo on the user stack */ - || copy_siginfo_to_user32(&rt_sf->info, info) - /* set the ucontext on the user stack */ - || __put_user(0, &rt_sf->uc.uc_flags) - || __put_user(0, &rt_sf->uc.uc_link) - || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp) - || __put_user(sas_ss_flags(regs->gpr[1]), - &rt_sf->uc.uc_stack.ss_flags) - || __put_user(current->sas_ss_size, - &rt_sf->uc.uc_stack.ss_size) - || __copy_to_user(&rt_sf->uc.uc_sigmask, - oldset, sizeof(*oldset)) - /* point the mcontext.regs to the pramble register frame */ - || __put_user(frame, &rt_sf->uc.uc_mcontext.regs) - || __put_user(sig,&rt_sf->uc.uc_mcontext.signal)) - goto badframe; - } else { - /* Put a sigcontext on the stack */ - *newspp -= sizeof(*sc); - sc = (struct sigcontext32 *)(u64)*newspp; - if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) - goto badframe; - /* - * Note the upper 32 bits of the signal mask are stored - * in the unused part of the signal stack frame - */ - if (__put_user((u32)(u64)ka->sa.sa_handler, &sc->handler) - || __put_user(oldset->sig[0], &sc->oldmask) - || __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) - || __put_user((unsigned int)frame, &sc->regs) - || __put_user(sig, &sc->signal)) - goto badframe; - } + if (do_setcontext32(new_ctx, regs, 0)) + do_exit(SIGSEGV); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; + return 0; +} + +long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, + struct pt_regs *regs) +{ + struct rt_sigframe32 __user *rt_sf; + int ret; + + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + rt_sf = (struct rt_sigframe32 __user *) + (regs->gpr[1] + __SIGNAL_FRAMESIZE32 + 16); + if (verify_area(VERIFY_READ, rt_sf, sizeof(*rt_sf))) + goto bad; + if (do_setcontext32(&rt_sf->uc, regs, 1)) + goto bad; + + /* + * It's not clear whether or why it is desirable to save the + * sigaltstack setting on signal delivery and restore it on + * signal return. But other architectures do this and we have + * always done it up until now so it is probably better not to + * change it. -- paulus + * We use the sys32_ version that does the 32/64 bits conversion + * and takes userland pointer directly. What about error checking ? + * nobody does any... + */ + sys32_sigaltstack((u32)(u64)&rt_sf->uc.uc_stack, 0, 0, 0, 0, 0, regs); + + regs->result &= 0xFFFFFFFF; + ret = regs->result; + + return ret; + + bad: + force_sig(SIGSEGV, current); + return 0; +} + + +/* + * OK, we're invoking a handler + */ +static void handle_signal32(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs * regs, unsigned long newsp) +{ + struct sigcontext32 __user *sc; + struct sigregs32 __user *frame; + unsigned long origsp = newsp; + + /* Set up Signal Frame */ + newsp -= sizeof(struct sigregs32); + frame = (struct sigregs32 __user *) newsp; + + /* Put a sigcontext on the stack */ + newsp -= sizeof(*sc); + sc = (struct sigcontext32 __user *) newsp; + + /* create a stack frame for the caller of the handler */ + newsp -= __SIGNAL_FRAMESIZE32; + + if (verify_area(VERIFY_WRITE, (void *) newsp, origsp - newsp)) + goto badframe; + +#if _NSIG != 64 +#error "Please adjust handle_signal32()" +#endif + if (__put_user((u32)(u64)ka->sa.sa_handler, &sc->handler) + || __put_user(oldset->sig[0], &sc->oldmask) + || __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) + || __put_user((u32)(u64)frame, &sc->regs) + || __put_user(sig, &sc->signal)) + goto badframe; + + if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) + goto badframe; + + if (put_user(regs->gpr[1], (unsigned long __user *)newsp)) + goto badframe; + regs->gpr[1] = (unsigned long) newsp; + regs->gpr[3] = sig; + regs->gpr[4] = (unsigned long) sc; + regs->nip = (unsigned long) ka->sa.sa_handler; + regs->link = (unsigned long) frame->mctx.tramp; + regs->trap = 0; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } return; badframe: #if DEBUG_SIG - printk("badframe in handle_signal32, regs=%p frame=%lx newsp=%lx\n", + printk("badframe in handle_signal, regs=%p frame=%x newsp=%x\n", regs, frame, *newspp); - printk("sc=%p sig=%d ka=%p info=%p oldset=%p\n", sc, sig, ka, info, oldset); #endif - do_exit(SIGSEGV); + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); } - /* - * Start Alternate signal stack support - * - * System Calls - * sigaltatck sys32_sigaltstack + * Do a signal return; undo the signal stack. */ - -int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, - int p4, int p6, int p7, struct pt_regs *regs) +long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, + struct pt_regs *regs) { - stack_t uss, uoss; + struct sigcontext32 __user *sc; + struct sigcontext32 sigctx; + struct mcontext32 __user *sr; + sigset_t set; int ret; - mm_segment_t old_fs; - unsigned long sp; + + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + + sc = (struct sigcontext32 __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); + if (copy_from_user(&sigctx, sc, sizeof(sigctx))) + goto badframe; /* - * set sp to the user stack on entry to the system call - * the system call router sets R9 to the saved registers + * Note that PPC32 puts the upper 32 bits of the sigmask in the + * unused part of the signal stackframe */ - sp = regs->gpr[1]; + set.sig[0] = sigctx.oldmask + ((long)(sigctx._unused[3]) << 32); + restore_sigmask(&set); - /* Put new stack info in local 64 bit stack struct */ - if (newstack && - (get_user((long)uss.ss_sp, - &((stack_32_t *)(long)newstack)->ss_sp) || - __get_user(uss.ss_flags, - &((stack_32_t *)(long)newstack)->ss_flags) || - __get_user(uss.ss_size, - &((stack_32_t *)(long)newstack)->ss_size))) - return -EFAULT; + sr = (struct mcontext32 *)(u64)sigctx.regs; + if (verify_area(VERIFY_READ, sr, sizeof(*sr)) + || restore_user_regs(regs, sr, 1)) + goto badframe; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL, - sp); - set_fs(old_fs); - /* Copy the stack information to the user output buffer */ - if (!ret && oldstack && - (put_user((long)uoss.ss_sp, - &((stack_32_t *)(long)oldstack)->ss_sp) || - __put_user(uoss.ss_flags, - &((stack_32_t *)(long)oldstack)->ss_flags) || - __put_user(uoss.ss_size, - &((stack_32_t *)(long)oldstack)->ss_size))) - return -EFAULT; + regs->result &= 0xFFFFFFFF; + ret = regs->result; return ret; + +badframe: + force_sig(SIGSEGV, current); + return 0; } @@ -1082,7 +944,7 @@ int do_signal32(sigset_t *oldset, struct siginfo_t info; struct k_sigaction *ka; unsigned int frame, newsp; - int signr; + int signr, ret; if (!oldset) oldset = ¤t->blocked; @@ -1090,40 +952,60 @@ int do_signal32(sigset_t *oldset, struct newsp = frame = 0; signr = get_signal_to_deliver(&info, regs, NULL); - if (signr > 0) { - ka = ¤t->sighand->action[signr-1]; - if ((ka->sa.sa_flags & SA_ONSTACK) - && (!on_sig_stack(regs->gpr[1]))) - newsp = (current->sas_ss_sp + current->sas_ss_size); - else - newsp = regs->gpr[1]; - newsp = frame = newsp - sizeof(struct sigregs32); - /* Whee! Actually deliver the signal. */ - handle_signal32(signr, &info, oldset, regs, &newsp, frame); - } + ka = (signr == 0)? NULL: ¤t->sighand->action[signr-1]; - if (regs->trap == 0x0C00) { /* System Call! */ - if ((int)regs->result == -ERESTARTNOHAND || - (int)regs->result == -ERESTARTSYS || - (int)regs->result == -ERESTARTNOINTR) { - regs->gpr[3] = regs->orig_gpr3; - regs->nip -= 4; /* Back up & retry system call */ - regs->result = 0; - } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) { - regs->gpr[0] = __NR_restart_syscall; - regs->nip -= 4; + if (regs->trap == 0x0C00 /* System Call! */ + && regs->ccr & 0x10000000 /* error signalled */ + && ((ret = regs->gpr[3]) == ERESTARTSYS + || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR + || ret == ERESTART_RESTARTBLOCK)) { + + if (signr > 0 + && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK + || (ret == ERESTARTSYS + && !(ka->sa.sa_flags & SA_RESTART)))) { + /* make the system call return an EINTR error */ + regs->result = -EINTR; + regs->gpr[3] = EINTR; + /* note that the cr0.SO bit is already set */ + } else { + regs->nip -= 4; /* Back up & retry system call */ regs->result = 0; + regs->trap = 0; + if (ret == ERESTART_RESTARTBLOCK) + regs->gpr[0] = __NR_restart_syscall; + else + regs->gpr[3] = regs->orig_gpr3; } } - if (newsp == frame) + if (signr == 0) return 0; /* no signals delivered */ - /* Invoke correct stack setup routine */ + if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size + && (!on_sig_stack(regs->gpr[1]))) + newsp = (current->sas_ss_sp + current->sas_ss_size); + else + newsp = regs->gpr[1]; + newsp &= ~0xfUL; + + /* Whee! Actually deliver the signal. */ if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); + handle_rt_signal32(signr, ka, &info, oldset, regs, newsp); else - setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp); + handle_signal32(signr, ka, &info, oldset, regs, newsp); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked, signr); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } + return 1; } diff -puN arch/ppc64/kernel/signal.c~linus arch/ppc64/kernel/signal.c --- 25/arch/ppc64/kernel/signal.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/signal.c 2004-01-19 22:17:21.000000000 -0800 @@ -114,19 +114,49 @@ long sys_sigaltstack(const stack_t *uss, * Set up the sigcontext for the signal frame. */ -static int -setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, +static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int signr, sigset_t *set, unsigned long handler) { + /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the + * process never used altivec yet (MSR_VEC is zero in pt_regs of + * the context). This is very important because we must ensure we + * don't lose the VRSAVE content that may have been set prior to + * the process doing its first vector operation + * Userland shall check AT_HWCAP to know wether it can rely on the + * v_regs pointer or not + */ +#ifdef CONFIG_ALTIVEC + elf_vrreg_t *v_regs = (elf_vrreg_t *)(((unsigned long)sc->vmx_reserve) & ~0xful); +#endif int err = 0; if (regs->msr & MSR_FP) giveup_fpu(current); - current->thread.saved_msr = regs->msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); - regs->msr = current->thread.saved_msr | current->thread.fpexc_mode; - current->thread.saved_softe = regs->softe; + /* Make sure signal doesn't get spurrious FP exceptions */ + current->thread.fpscr = 0; + +#ifdef CONFIG_ALTIVEC + err |= __put_user(v_regs, &sc->v_regs); + /* save altivec registers */ + if (current->thread.used_vr) { + if (regs->msr & MSR_VEC) + giveup_altivec(current); + /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ + err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); + /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) + * contains valid data. + */ + regs->msr |= MSR_VEC; + } + /* We always copy to/from vrsave, it's 0 if we don't have or don't + * use altivec. + */ + err |= __put_user(current->thread.vrsave, (u32 *)&v_regs[33]); +#else /* CONFIG_ALTIVEC */ + err |= __put_user(0, &sc->v_regs); +#endif /* CONFIG_ALTIVEC */ err |= __put_user(&sc->gp_regs, &sc->regs); err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); err |= __copy_to_user(&sc->fp_regs, ¤t->thread.fpr, FP_REGS_SIZE); @@ -135,9 +165,6 @@ setup_sigcontext(struct sigcontext *sc, if (set != NULL) err |= __put_user(set->sig[0], &sc->oldmask); - regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); - current->thread.fpscr = 0; - return err; } @@ -145,23 +172,42 @@ setup_sigcontext(struct sigcontext *sc, * Restore the sigcontext from the signal frame. */ -static int -restore_sigcontext(struct pt_regs *regs, sigset_t *set, struct sigcontext *sc) +static int restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, struct sigcontext *sc) { +#ifdef CONFIG_ALTIVEC + elf_vrreg_t *v_regs; +#endif unsigned int err = 0; + unsigned long save_r13; - if (regs->msr & MSR_FP) - giveup_fpu(current); - + /* If this is not a signal return, we preserve the TLS in r13 */ + if (!sig) + save_r13 = regs->gpr[13]; err |= __copy_from_user(regs, &sc->gp_regs, GP_REGS_SIZE); + if (!sig) + regs->gpr[13] = save_r13; err |= __copy_from_user(¤t->thread.fpr, &sc->fp_regs, FP_REGS_SIZE); - current->thread.fpexc_mode = regs->msr & (MSR_FE0 | MSR_FE1); if (set != NULL) err |= __get_user(set->sig[0], &sc->oldmask); - /* Don't allow the signal handler to change these modulo FE{0,1} */ - regs->msr = current->thread.saved_msr & ~(MSR_FP | MSR_FE0 | MSR_FE1); - regs->softe = current->thread.saved_softe; +#ifdef CONFIG_ALTIVEC + err |= __get_user(v_regs, &sc->v_regs); + if (err) + return err; + /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ + if (v_regs != 0 && (regs->msr & MSR_VEC) != 0) + err |= __copy_from_user(current->thread.vr, v_regs, 33 * sizeof(vector128)); + else if (current->thread.used_vr) + memset(¤t->thread.vr, 0, 33); + /* Always get VRSAVE back */ + if (v_regs != 0) + err |= __get_user(current->thread.vrsave, (u32 *)&v_regs[33]); + else + current->thread.vrsave = 0; +#endif /* CONFIG_ALTIVEC */ + + /* Force reload of FP/VEC */ + regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC); return err; } @@ -169,8 +215,8 @@ restore_sigcontext(struct pt_regs *regs, /* * Allocate space for the signal frame */ -static inline void * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) { unsigned long newsp; @@ -185,8 +231,10 @@ get_sigframe(struct k_sigaction *ka, str return (void *)((newsp - frame_size) & -8ul); } -static int -setup_trampoline(unsigned int syscall, unsigned int *tramp) +/* + * Setup the trampoline code on the stack + */ +static int setup_trampoline(unsigned int syscall, unsigned int *tramp) { int i, err = 0; @@ -209,6 +257,72 @@ setup_trampoline(unsigned int syscall, u } /* + * Restore the user process's signal mask (also used by signal32.c) + */ +void restore_sigmask(sigset_t *set) +{ + sigdelsetmask(set, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + current->blocked = *set; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); +} + + +/* + * Handle {get,set,swap}_context operations + */ +int sys_swapcontext(struct ucontext __user *old_ctx, + struct ucontext __user *new_ctx, + long ctx_size, long r6, long r7, long r8, struct pt_regs *regs) +{ + unsigned char tmp; + sigset_t set; + + /* Context size is for future use. Right now, we only make sure + * we are passed something we understand + */ + if (ctx_size < sizeof(struct ucontext)) + return -EINVAL; + + if (old_ctx != NULL) { + if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx)) + || setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0) + || __copy_to_user(&old_ctx->uc_sigmask, + ¤t->blocked, sizeof(sigset_t))) + return -EFAULT; + } + if (new_ctx == NULL) + return 0; + if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx)) + || __get_user(tmp, (u8 *) new_ctx) + || __get_user(tmp, (u8 *) (new_ctx + 1) - 1)) + return -EFAULT; + + /* + * If we get a fault copying the context into the kernel's + * image of the user's registers, we can't just return -EFAULT + * because the user's registers will be corrupted. For instance + * the NIP value may have been updated but not some of the + * other registers. Given that we have done the verify_area + * and successfully read the first and last bytes of the region + * above, this should only happen in an out-of-memory situation + * or if another thread unmaps the region containing the context. + * We kill the task with a SIGSEGV in this situation. + */ + + if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set))) + do_exit(SIGSEGV); + restore_sigmask(&set); + if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext)) + do_exit(SIGSEGV); + + /* This returns like rt_sigreturn */ + return 0; +} + + +/* * Do a signal return; undo the signal stack. */ @@ -218,7 +332,6 @@ int sys_rt_sigreturn(unsigned long r3, u { struct ucontext *uc = (struct ucontext *)regs->gpr[1]; sigset_t set; - stack_t st; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; @@ -228,20 +341,14 @@ int sys_rt_sigreturn(unsigned long r3, u if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) goto badframe; - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - if (restore_sigcontext(regs, NULL, &uc->uc_mcontext)) + restore_sigmask(&set); + if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) goto badframe; - if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) - goto badframe; - /* This function sets back the stack flags into - the current task structure. */ - sys_sigaltstack(&st, NULL, 0, 0, 0, 0, regs); + /* do_sigaltstack expects a __user pointer and won't modify + * what's in there anyway + */ + do_sigaltstack(&uc->uc_stack, NULL, regs->gpr[1]); return regs->result; @@ -253,8 +360,7 @@ badframe: do_exit(SIGSEGV); } -static void -setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, +static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for @@ -332,9 +438,8 @@ badframe: /* * OK, we're invoking a handler */ -static void -handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) +static void handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { /* Set up Signal Frame */ setup_rt_frame(sig, ka, info, oldset, regs); @@ -352,8 +457,7 @@ handle_signal(unsigned long sig, struct return; } -static inline void -syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) +static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) { switch ((int)regs->result) { case -ERESTART_RESTARTBLOCK: diff -puN arch/ppc64/kernel/smp.c~linus arch/ppc64/kernel/smp.c --- 25/arch/ppc64/kernel/smp.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/smp.c 2004-01-19 22:17:21.000000000 -0800 @@ -53,10 +53,14 @@ int smp_threads_ready; unsigned long cache_decay_ticks; -/* initialised so it doesn't end up in bss */ +/* Initialised so it doesn't end up in bss */ +cpumask_t cpu_possible_map = CPU_MASK_NONE; cpumask_t cpu_online_map = CPU_MASK_NONE; +cpumask_t cpu_available_map = CPU_MASK_NONE; +cpumask_t cpu_present_at_boot = CPU_MASK_NONE; EXPORT_SYMBOL(cpu_online_map); +EXPORT_SYMBOL(cpu_possible_map); static struct smp_ops_t *smp_ops; @@ -67,6 +71,8 @@ extern unsigned char stab_array[]; extern int cpu_idle(void *unused); void smp_call_function_interrupt(void); void smp_message_pass(int target, int msg, unsigned long data, int wait); +extern long register_vpa(unsigned long flags, unsigned long proc, + unsigned long vpa); #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) @@ -120,6 +126,9 @@ static int smp_iSeries_numProcs(void) for (i=0; i < NR_CPUS; ++i) { lpPaca = paca[i].xLpPacaPtr; if ( lpPaca->xDynProcStatus < 2 ) { + cpu_set(i, cpu_available_map); + cpu_set(i, cpu_possible_map); + cpu_set(i, cpu_present_at_boot); ++np; } } @@ -135,7 +144,7 @@ static int smp_iSeries_probe(void) for (i=0; i < NR_CPUS; ++i) { lpPaca = paca[i].xLpPacaPtr; if (lpPaca->xDynProcStatus < 2) { - paca[i].active = 1; + /*paca[i].active = 1;*/ ++np; } } @@ -181,7 +190,6 @@ void __init smp_init_iSeries(void) smp_ops->probe = smp_iSeries_probe; smp_ops->kick_cpu = smp_iSeries_kick_cpu; smp_ops->setup_cpu = smp_iSeries_setup_cpu; -#warning fix for iseries systemcfg->processorCount = smp_iSeries_numProcs(); } #endif @@ -227,6 +235,11 @@ static int __init smp_openpic_probe(void return nr_cpus; } +static void __devinit smp_openpic_setup_cpu(int cpu) +{ + do_openpic_setup_cpu(); +} + static void smp_kick_cpu(int nr) { @@ -266,14 +279,15 @@ static void __init smp_space_timers(unsi } #ifdef CONFIG_PPC_PSERIES -static void __devinit pSeries_setup_cpu(int cpu) +void vpa_init(int cpu) { - if (OpenPIC_Addr) { - do_openpic_setup_cpu(); - } else { - if (cpu != boot_cpuid) - xics_setup_cpu(); - } + unsigned long flags; + + /* Register the Virtual Processor Area (VPA) */ + printk(KERN_INFO "register_vpa: cpu 0x%x\n", cpu); + flags = 1UL << (63 - 18); + paca[cpu].xLpPaca.xSLBCount = 64; /* SLB restore highwater mark */ + register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); } static void @@ -295,6 +309,8 @@ smp_xics_message_pass(int target, int ms } } +extern void xics_request_IPIs(void); + static int __init smp_xics_probe(void) { int i; @@ -305,13 +321,18 @@ static int __init smp_xics_probe(void) nr_cpus++; } #ifdef CONFIG_SMP - extern void xics_request_IPIs(void); xics_request_IPIs(); #endif return nr_cpus; } +static void __devinit smp_xics_setup_cpu(int cpu) +{ + if (cpu != boot_cpuid) + xics_setup_cpu(); +} + static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; static unsigned long timebase = 0; @@ -345,9 +366,11 @@ void __init smp_init_pSeries(void) if (naca->interrupt_controller == IC_OPEN_PIC) { smp_ops->message_pass = smp_openpic_message_pass; smp_ops->probe = smp_openpic_probe; + smp_ops->setup_cpu = smp_openpic_setup_cpu; } else { smp_ops->message_pass = smp_xics_message_pass; smp_ops->probe = smp_xics_probe; + smp_ops->setup_cpu = smp_xics_setup_cpu; } if (systemcfg->platform == PLATFORM_PSERIES) { @@ -356,7 +379,6 @@ void __init smp_init_pSeries(void) } smp_ops->kick_cpu = smp_kick_cpu; - smp_ops->setup_cpu = pSeries_setup_cpu; } #endif @@ -480,13 +502,13 @@ int smp_call_function (void (*func) (voi while (atomic_read(&data.started) != cpus) { HMT_low(); if (--timeout == 0) { + printk("smp_call_function on cpu %d: other cpus not " + "responding (%d)\n", smp_processor_id(), + atomic_read(&data.started)); #ifdef CONFIG_DEBUG_KERNEL if (debugger) debugger(0); #endif - printk("smp_call_function on cpu %d: other cpus not " - "responding (%d)\n", smp_processor_id(), - atomic_read(&data.started)); goto out; } } @@ -496,15 +518,15 @@ int smp_call_function (void (*func) (voi while (atomic_read(&data.finished) != cpus) { HMT_low(); if (--timeout == 0) { -#ifdef CONFIG_DEBUG_KERNEL - if (debugger) - debugger(0); -#endif printk("smp_call_function on cpu %d: other " "cpus not finishing (%d/%d)\n", smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started)); +#ifdef CONFIG_DEBUG_KERNEL + if (debugger) + debugger(0); +#endif goto out; } } @@ -513,6 +535,7 @@ int smp_call_function (void (*func) (voi ret = 0; out: + call_data = NULL; HMT_medium(); spin_unlock(&call_lock); return ret; @@ -520,9 +543,19 @@ out: void smp_call_function_interrupt(void) { - void (*func) (void *info) = call_data->func; - void *info = call_data->info; - int wait = call_data->wait; + void (*func) (void *info); + void *info; + int wait; + + /* call_data will be NULL if the sender timed out while + * waiting on us to receive the call. + */ + if (!call_data) + return; + + func = call_data->func; + info = call_data->info; + wait = call_data->wait; /* * Notify initiating CPU that I've grabbed the data and am @@ -549,11 +582,17 @@ static void __devinit smp_store_cpu_info void __init smp_prepare_cpus(unsigned int max_cpus) { + /* + * setup_cpu may need to be called on the boot cpu. We havent + * spun any cpus up but lets be paranoid. + */ + BUG_ON(boot_cpuid != smp_processor_id()); + /* Fixup boot cpu */ - smp_store_cpu_info(smp_processor_id()); - cpu_callin_map[smp_processor_id()] = 1; - paca[smp_processor_id()].prof_counter = 1; - paca[smp_processor_id()].prof_multiplier = 1; + smp_store_cpu_info(boot_cpuid); + cpu_callin_map[boot_cpuid] = 1; + paca[boot_cpuid].prof_counter = 1; + paca[boot_cpuid].prof_multiplier = 1; /* * XXX very rough. @@ -658,6 +697,14 @@ int __devinit start_secondary(void *unus if (smp_ops->take_timebase) smp_ops->take_timebase(); + get_paca()->yielded = 0; + +#ifdef CONFIG_PPC_PSERIES + if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { + vpa_init(cpu); + } +#endif + local_irq_enable(); return cpu_idle(NULL); @@ -670,8 +717,19 @@ int setup_profiling_timer(unsigned int m void __init smp_cpus_done(unsigned int max_cpus) { + cpumask_t old_mask; + + /* We want the setup_cpu() here to be called from CPU 0, but our + * init thread may have been "borrowed" by another CPU in the meantime + * se we pin us down to CPU 0 for a short while + */ + old_mask = current->cpus_allowed; + set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); + smp_ops->setup_cpu(boot_cpuid); /* XXX fix this, xics currently relies on it - Anton */ smp_threads_ready = 1; + + set_cpus_allowed(current, old_mask); } diff -puN arch/ppc64/kernel/syscalls.c~linus arch/ppc64/kernel/syscalls.c --- 25/arch/ppc64/kernel/syscalls.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/syscalls.c 2004-01-19 22:17:21.000000000 -0800 @@ -41,6 +41,7 @@ #include #include #include +#include extern unsigned long wall_jiffies; @@ -234,3 +235,6 @@ asmlinkage time_t sys64_time(time_t* tlo return secs; } + +/* Only exists on P-series. */ +cond_syscall(ppc_rtas); diff -puN arch/ppc64/kernel/sys_ppc32.c~linus arch/ppc64/kernel/sys_ppc32.c --- 25/arch/ppc64/kernel/sys_ppc32.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/sys_ppc32.c 2004-01-19 22:17:21.000000000 -0800 @@ -746,30 +746,31 @@ int ppc32_select(u32 n, u32* inp, u32* o int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { - int err; + long err; if (stat->size > MAX_NON_LFS || !new_valid_dev(stat->dev) || !new_valid_dev(stat->rdev)) return -EOVERFLOW; - err = put_user(new_encode_dev(stat->dev), &statbuf->st_dev); - err |= put_user(stat->ino, &statbuf->st_ino); - err |= put_user(stat->mode, &statbuf->st_mode); - err |= put_user(stat->nlink, &statbuf->st_nlink); - err |= put_user(stat->uid, &statbuf->st_uid); - err |= put_user(stat->gid, &statbuf->st_gid); - err |= put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); - err |= put_user(stat->size, &statbuf->st_size); - err |= put_user(stat->atime.tv_sec, &statbuf->st_atime); - err |= put_user(0, &statbuf->__unused1); - err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime); - err |= put_user(0, &statbuf->__unused2); - err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime); - err |= put_user(0, &statbuf->__unused3); - err |= put_user(stat->blksize, &statbuf->st_blksize); - err |= put_user(stat->blocks, &statbuf->st_blocks); - err |= put_user(0, &statbuf->__unused4[0]); - err |= put_user(0, &statbuf->__unused4[1]); + err = verify_area(VERIFY_WRITE, statbuf, sizeof(*statbuf)); + err |= __put_user(new_encode_dev(stat->dev), &statbuf->st_dev); + err |= __put_user(stat->ino, &statbuf->st_ino); + err |= __put_user(stat->mode, &statbuf->st_mode); + err |= __put_user(stat->nlink, &statbuf->st_nlink); + err |= __put_user(stat->uid, &statbuf->st_uid); + err |= __put_user(stat->gid, &statbuf->st_gid); + err |= __put_user(new_encode_dev(stat->rdev), &statbuf->st_rdev); + err |= __put_user(stat->size, &statbuf->st_size); + err |= __put_user(stat->atime.tv_sec, &statbuf->st_atime); + err |= __put_user(stat->atime.tv_nsec, &statbuf->st_atime_nsec); + err |= __put_user(stat->mtime.tv_sec, &statbuf->st_mtime); + err |= __put_user(stat->mtime.tv_nsec, &statbuf->st_mtime_nsec); + err |= __put_user(stat->ctime.tv_sec, &statbuf->st_ctime); + err |= __put_user(stat->ctime.tv_nsec, &statbuf->st_ctime_nsec); + err |= __put_user(stat->blksize, &statbuf->st_blksize); + err |= __put_user(stat->blocks, &statbuf->st_blocks); + err |= __put_user(0, &statbuf->__unused4[0]); + err |= __put_user(0, &statbuf->__unused4[1]); return err; } @@ -2106,6 +2107,10 @@ long sys32_execve(unsigned long a0, unsi goto out; if (regs->msr & MSR_FP) giveup_fpu(current); +#ifdef CONFIG_ALTIVEC + if (regs->msr & MSR_VEC) + giveup_altivec(current); +#endif /* CONFIG_ALTIVEC */ error = do_execve32(filename, (u32*) a1, (u32*) a2, regs); @@ -2126,9 +2131,25 @@ void start_thread32(struct pt_regs* regs regs->nip = nip; regs->gpr[1] = sp; regs->msr = MSR_USER32; +#ifndef CONFIG_SMP if (last_task_used_math == current) last_task_used_math = 0; +#endif /* CONFIG_SMP */ current->thread.fpscr = 0; + memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); +#ifdef CONFIG_ALTIVEC +#ifndef CONFIG_SMP + if (last_task_used_altivec == current) + last_task_used_altivec = 0; +#endif /* CONFIG_SMP */ + memset(current->thread.vr, 0, sizeof(current->thread.vr)); + current->thread.vscr.u[0] = 0; + current->thread.vscr.u[1] = 0; + current->thread.vscr.u[2] = 0; + current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ + current->thread.vrsave = 0; + current->thread.used_vr = 0; +#endif /* CONFIG_ALTIVEC */ } extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3, @@ -2683,98 +2704,6 @@ unsigned long sys32_mmap2(unsigned long return sys_mmap(addr, len, prot, flags, fd, pgoff << 12); } -extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx); - -long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) -{ - long ret; - aio_context_t ctx64; - mm_segment_t oldfs = get_fs(); - - if (get_user((u32)ctx64, ctx32p)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_io_setup(nr_reqs, &ctx64); - set_fs(oldfs); - - /* truncating is ok because it's a user address */ - if (!ret) - ret = put_user((u32)ctx64, ctx32p); - - return ret; -} - -long sys_io_getevents(aio_context_t ctx_id, long min_nr, long nr, - struct io_event *events, struct timespec *timeout); - -long sys32_io_getevents(aio_context_t ctx_id, u32 min_nr, u32 nr, - struct io_event *events, struct compat_timespec *t32) -{ - struct timespec t; - long ret; - mm_segment_t oldfs = get_fs(); - - if (t32) { - if (get_user(t.tv_sec, &t32->tv_sec) || - __get_user(t.tv_nsec, &t32->tv_nsec)) - return -EFAULT; - } - - if (verify_area(VERIFY_WRITE, events, nr * sizeof(*events))) - return -EFAULT; - - set_fs(KERNEL_DS); - /* sign extend min_nr and nr */ - ret = sys_io_getevents(ctx_id, (int)min_nr, (int)nr, events, - t32 ? &t : NULL); - set_fs(oldfs); - - return ret; -} - -long sys32_io_submit(aio_context_t ctx_id, u32 number, u32 *iocbpp) -{ - struct kioctx *ctx; - long ret = 0; - int i; - int nr = (int)number; /* sign extend */ - - if (unlikely(nr < 0)) - return -EINVAL; - - if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(u32))))) - return -EFAULT; - - ctx = lookup_ioctx(ctx_id); - if (unlikely(!ctx)) { - pr_debug("EINVAL: io_submit: invalid context id\n"); - return -EINVAL; - } - - for (i=0; isigev_value.sival_int) + || __get_user(event.sigev_signo, &ev32->sigev_signo) + || __get_user(event.sigev_notify, &ev32->sigev_notify) + || __get_user(event.sigev_notify_thread_id, + &ev32->sigev_notify_thread_id)) + return -EFAULT; + + if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t))) + return -EFAULT; + + savefs = get_fs(); + err = sys_timer_create(clock, &event, &t); + set_fs(savefs); + + if (err == 0) + err = __put_user(t, timer_id); + + return err; +} diff -puN arch/ppc64/kernel/time.c~linus arch/ppc64/kernel/time.c --- 25/arch/ppc64/kernel/time.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/time.c 2004-01-19 22:17:21.000000000 -0800 @@ -91,6 +91,9 @@ unsigned tb_to_us; unsigned long processor_freq; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; +unsigned long tb_to_ns_scale; +unsigned long tb_to_ns_shift; + struct gettimeofday_struct do_gtod; extern unsigned long wall_jiffies; @@ -313,11 +316,13 @@ int timer_interrupt(struct pt_regs * reg /* * Scheduler clock - returns current time in nanosec units. * - * This is wrong, but my CPUs run at 1GHz, so nyer nyer. + * Note: mulhdu(a, b) (multiply high double unsigned) returns + * the high 64 bits of a * b, i.e. (a * b) >> 64, where a and b + * are 64-bit unsigned numbers. */ unsigned long long sched_clock(void) { - return get_tb(); + return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; } /* @@ -473,9 +478,30 @@ void __init time_init(void) /* This function is only called on the boot processor */ unsigned long flags; struct rtc_time tm; + struct div_result res; + unsigned long scale, shift; ppc_md.calibrate_decr(); + /* + * Compute scale factor for sched_clock. + * The calibrate_decr() function has set tb_ticks_per_sec, + * which is the timebase frequency. + * We compute 1e9 * 2^64 / tb_ticks_per_sec and interpret + * the 128-bit result as a 64.64 fixed-point number. + * We then shift that number right until it is less than 1.0, + * giving us the scale factor and shift count to use in + * sched_clock(). + */ + div128_by_32(1000000000, 0, tb_ticks_per_sec, &res); + scale = res.result_low; + for (shift = 0; res.result_high != 0; ++shift) { + scale = (scale >> 1) | (res.result_high << 63); + res.result_high >>= 1; + } + tb_to_ns_scale = scale; + tb_to_ns_shift = shift; + #ifdef CONFIG_PPC_ISERIES if (!piranha_simulator) #endif diff -puN arch/ppc64/kernel/traps.c~linus arch/ppc64/kernel/traps.c --- 25/arch/ppc64/kernel/traps.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/traps.c 2004-01-19 22:17:21.000000000 -0800 @@ -16,6 +16,7 @@ * This file handles the architecture-dependent parts of hardware exceptions */ +#include #include #include #include @@ -26,7 +27,6 @@ #include #include #include -#include #include #include @@ -40,8 +40,10 @@ extern int fix_alignment(struct pt_regs *); extern void bad_page_fault(struct pt_regs *, unsigned long, int); +#ifdef CONFIG_PPC_PSERIES /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; +#endif #ifdef CONFIG_DEBUG_KERNEL void (*debugger)(struct pt_regs *regs); @@ -96,6 +98,7 @@ _exception(int signr, siginfo_t *info, s force_sig_info(signr, info, current); } +#ifdef CONFIG_PPC_PSERIES /* Get the error information for errors coming through the * FWNMI vectors. The pt_regs' r3 will be updated to reflect * the actual r3 if possible, and a ptr to the error log entry @@ -128,10 +131,12 @@ static void FWNMI_release_errinfo(void) if (ret != 0) printk("FWNMI: nmi-interlock failed: %ld\n", ret); } +#endif void SystemResetException(struct pt_regs *regs) { +#ifdef CONFIG_PPC_PSERIES if (fwnmi_active) { struct rtas_error_log *errhdr = FWNMI_get_errinfo(regs); if (errhdr) { @@ -139,6 +144,7 @@ SystemResetException(struct pt_regs *reg } FWNMI_release_errinfo(); } +#endif #ifdef CONFIG_DEBUG_KERNEL if (debugger) @@ -154,6 +160,7 @@ SystemResetException(struct pt_regs *reg /* What should we do here? We could issue a shutdown or hard reset. */ } +#ifdef CONFIG_PPC_PSERIES /* * See if we can recover from a machine check exception. * This is only called on power4 (or above) and only via @@ -190,6 +197,7 @@ static int recover_mce(struct pt_regs *r } return 0; } +#endif /* * Handle a machine check. @@ -207,6 +215,7 @@ static int recover_mce(struct pt_regs *r void MachineCheckException(struct pt_regs *regs) { +#ifdef CONFIG_PPC_PSERIES struct rtas_error_log err, *errp; if (fwnmi_active) { @@ -217,6 +226,7 @@ MachineCheckException(struct pt_regs *re if (errp && recover_mce(regs, err)) return; } +#endif #ifdef CONFIG_DEBUG_KERNEL if (debugger_fault_handler) { @@ -349,7 +359,7 @@ check_bug_trap(struct pt_regs *regs) printk(KERN_ERR "Badness in %s at %s:%d\n", bug->function, bug->file, (unsigned int)bug->line & ~BUG_WARNING_TRAP); - dump_stack(); + show_stack(current, (void *)regs->gpr[1]); return 1; } printk(KERN_CRIT "kernel BUG in %s at %s:%d!\n", @@ -410,6 +420,14 @@ KernelFPUnavailableException(struct pt_r } void +KernelAltivecUnavailableException(struct pt_regs *regs) +{ + printk("Illegal VMX/Altivec used in kernel (task=0x%p, " + "pc=0x%016lx, trap=0x%lx)\n", current, regs->nip, regs->trap); + panic("Unrecoverable VMX/Altivec Unavailable Exception in Kernel"); +} + +void SingleStepException(struct pt_regs *regs) { siginfo_t info; @@ -478,6 +496,17 @@ AlignmentException(struct pt_regs *regs) _exception(SIGBUS, &info, regs); } +#ifdef CONFIG_ALTIVEC +void +AltivecAssistException(struct pt_regs *regs) +{ + if (regs->msr & MSR_VEC) + giveup_altivec(current); + /* XXX quick hack for now: set the non-Java bit in the VSCR */ + current->thread.vscr.u[3] |= 0x10000; +} +#endif /* CONFIG_ALTIVEC */ + void __init trap_init(void) { } diff -puN arch/ppc64/kernel/udbg.c~linus arch/ppc64/kernel/udbg.c --- 25/arch/ppc64/kernel/udbg.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/udbg.c 2004-01-19 22:17:21.000000000 -0800 @@ -127,8 +127,10 @@ udbg_write(const char *s, int n) { int remain = n; char c; + if (!ppc_md.udbg_putc) - for (;;); /* stop here for cpuctl */ + return 0; + if ( s && *s != '\0' ) { while ( (( c = *s++ ) != '\0') && (remain-- > 0)) { ppc_md.udbg_putc(c); diff -puN /dev/null arch/ppc64/kernel/vio.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/kernel/vio.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,536 @@ +/* + * IBM PowerPC Virtual I/O Infrastructure Support. + * + * Copyright (c) 2003 IBM Corp. + * Dave Engebretsen engebret@us.ibm.com + * Santiago Leon santil@us.ibm.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "open_pic.h" /* temporary, until we merge large irq support */ + +extern struct TceTable *build_tce_table(struct TceTable *tbl); + +extern dma_addr_t get_tces(struct TceTable *, unsigned order, + void *page, unsigned numPages, int direction); +extern void tce_free(struct TceTable *tbl, dma_addr_t dma_addr, + unsigned order, unsigned num_pages); + + +static struct vio_bus vio_bus; +static LIST_HEAD(registered_vio_drivers); +int vio_num_address_cells; +EXPORT_SYMBOL(vio_num_address_cells); + +/* TODO: + * really fit into driver model (see include/linux/device.h) + * locking around list accesses + */ + +/** + * vio_register_driver: - Register a new vio driver + * @drv: The vio_driver structure to be registered. + * + * Adds the driver structure to the list of registered drivers + * Returns the number of vio devices which were claimed by the driver + * during registration. The driver remains registered even if the + * return value is zero. + */ +int vio_register_driver(struct vio_driver *drv) +{ + int count = 0; + struct vio_dev *dev; + + printk(KERN_DEBUG "%s: driver %s/%s registering\n", __FUNCTION__, + drv->id_table[0].type, drv->id_table[0].type); + + /* find matching devices not already claimed by other drivers and pass + * them to probe() */ + list_for_each_entry(dev, &vio_bus.devices, devices_list) { + const struct vio_device_id* id; + + if (dev->driver) + continue; /* this device is already owned */ + + id = vio_match_device(drv->id_table, dev); + if (drv && id) { + if (0 == drv->probe(dev, id)) { + printk(KERN_DEBUG " took device %p\n", dev); + dev->driver = drv; + count++; + } + } + } + + list_add_tail(&drv->node, ®istered_vio_drivers); + + return count; +} +EXPORT_SYMBOL(vio_register_driver); + +/** + * vio_unregister_driver - Remove registration of vio driver. + * @driver: The vio_driver struct to be removed form registration + * + * Searches for devices that are assigned to the driver and calls + * driver->remove() for each one. Removes the driver from the list + * of registered drivers. Returns the number of devices that were + * assigned to that driver. + */ +int vio_unregister_driver(struct vio_driver *driver) +{ + struct vio_dev *dev; + int devices_found = 0; + + list_for_each_entry(dev, &vio_bus.devices, devices_list) { + if (dev->driver == driver) { + driver->remove(dev); + dev->driver = NULL; + devices_found++; + } + } + + list_del(&driver->node); + + return devices_found; +} +EXPORT_SYMBOL(vio_unregister_driver); + +/** + * vio_match_device: - Tell if a VIO device has a matching VIO device id structure. + * @ids: array of VIO device id structures to search in + * @dev: the VIO device structure to match against + * + * Used by a driver to check whether a VIO device present in the + * system is in its list of supported devices. Returns the matching + * vio_device_id structure or NULL if there is no match. + */ +const struct vio_device_id * +vio_match_device(const struct vio_device_id *ids, const struct vio_dev *dev) +{ + while (ids->type) { + if ((strncmp(dev->archdata->type, ids->type, strlen(ids->type)) == 0) && + device_is_compatible((struct device_node*)dev->archdata, ids->compat)) + return ids; + ids++; + } + return NULL; +} + +/** + * vio_bus_init: - Initialize the virtual IO bus + */ +int __init +vio_bus_init(void) +{ + struct device_node *node_vroot, *node_vdev; + + INIT_LIST_HEAD(&vio_bus.devices); + + /* + * Create device node entries for each virtual device + * identified in the device tree. + * Functionally takes the place of pci_scan_bus + */ + node_vroot = find_devices("vdevice"); + if ((node_vroot == NULL) || (node_vroot->child == NULL)) { + printk(KERN_INFO "VIO: missing or empty /vdevice node; no virtual IO" + " devices present.\n"); + return 0; + } + + vio_num_address_cells = prom_n_addr_cells(node_vroot->child); + + for (node_vdev = node_vroot->child; + node_vdev != NULL; + node_vdev = node_vdev->sibling) { + printk(KERN_DEBUG "%s: processing %p\n", __FUNCTION__, node_vdev); + + vio_register_device(node_vdev); + } + + return 0; +} + +__initcall(vio_bus_init); + + +/** + * vio_probe_device - attach dev to appropriate driver + * @dev: device to find a driver for + * + * Walks the list of registered VIO drivers looking for one to take this + * device. + * + * Returns a pointer to the matched driver or NULL if driver is not + * found. + */ +struct vio_driver * __devinit vio_probe_device(struct vio_dev* dev) +{ + struct vio_driver *driver; + + list_for_each_entry(driver, ®istered_vio_drivers, node) { + const struct vio_device_id* id; + + id = vio_match_device(driver->id_table, dev); + if (id && (0 < driver->probe(dev, id))) { + printk(KERN_DEBUG "%s: driver %s/%s took device %p\n", + __FUNCTION__, id->type, id->compat, dev); + dev->driver = driver; + return driver; + } + } + + printk(KERN_DEBUG "%s: device %p found no driver\n", __FUNCTION__, dev); + return NULL; +} + +/** + * vio_register_device: - Register a new vio device. + * @archdata: The OF node for this device. + * + * Creates and initializes a vio_dev structure from the data in + * node_vdev (archdata) and adds it to the list of virtual devices. + * Returns a pointer to the created vio_dev or NULL if node has + * NULL device_type or compatible fields. + */ +struct vio_dev * __devinit vio_register_device(struct device_node *node_vdev) +{ + struct vio_dev *dev; + unsigned int *unit_address; + unsigned int *irq_p; + + /* guarantee all vio_devs have 'device_type' field*/ + if ((NULL == node_vdev->type)) { + printk(KERN_WARNING + "%s: node %s missing 'device_type'\n", __FUNCTION__, + node_vdev->name ? node_vdev->name : ""); + return NULL; + } + + unit_address = (unsigned int *)get_property(node_vdev, "reg", NULL); + if (!unit_address) { + printk(KERN_WARNING "%s: node %s missing 'reg'\n", __FUNCTION__, + node_vdev->name ? node_vdev->name : ""); + return NULL; + } + + /* allocate a vio_dev for this node */ + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->archdata = (void*)of_node_get(node_vdev); + dev->bus = &vio_bus; + dev->unit_address = *unit_address; + dev->tce_table = vio_build_tce_table(dev); + + irq_p = (unsigned int *) get_property(node_vdev, "interrupts", 0); + if(irq_p) { + dev->irq = openpic_to_irq(virt_irq_create_mapping(*irq_p)); + } else { + dev->irq = (unsigned int) -1; + } + + list_add_tail(&dev->devices_list, &vio_bus.devices); + + vio_probe_device(dev); /* finally, assign it to a driver */ + + return dev; +} +EXPORT_SYMBOL(vio_register_device); + +int __devinit vio_unregister_device(struct vio_dev *dev) +{ + list_del(&dev->devices_list); + of_node_put(dev->archdata); + + return 0; +} +EXPORT_SYMBOL(vio_unregister_device); + +/** + * vio_get_attribute: - get attribute for virtual device + * @vdev: The vio device to get property. + * @which: The property/attribute to be extracted. + * @length: Pointer to length of returned data size (unused if NULL). + * + * Calls prom.c's get_property() to return the value of the + * attribute specified by the preprocessor constant @which +*/ +const void * vio_get_attribute(struct vio_dev *vdev, void* which, int* length) +{ + return get_property((struct device_node *)vdev->archdata, (char*)which, length); +} +EXPORT_SYMBOL(vio_get_attribute); + +/** + * vio_build_tce_table: - gets the dma information from OF and builds the TCE tree. + * @dev: the virtual device. + * + * Returns a pointer to the built tce tree, or NULL if it can't + * find property. +*/ +struct TceTable * vio_build_tce_table(struct vio_dev *dev) +{ + unsigned int *dma_window; + struct TceTable *newTceTable; + unsigned long offset; + unsigned long size; + int dma_window_property_size; + + dma_window = (unsigned int *) get_property((struct device_node *)dev->archdata, "ibm,my-dma-window", &dma_window_property_size); + if(!dma_window) { + return NULL; + } + + newTceTable = (struct TceTable *) kmalloc(sizeof(struct TceTable), GFP_KERNEL); + + /* RPA docs say that #address-cells is always 1 for virtual + devices, but some older boxes' OF returns 2. This should + be removed by GA, unless there is legacy OFs that still + have 2 for #address-cells */ + size = ((dma_window[1+vio_num_address_cells] + >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; + + /* This is just an ugly kludge. Remove as soon as the OF for all + machines actually follow the spec and encodes the offset field + as phys-encode (that is, #address-cells wide)*/ + if (dma_window_property_size == 12) { + size = ((dma_window[1] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; + } else if (dma_window_property_size == 20) { + size = ((dma_window[4] >> PAGE_SHIFT) << 3) >> PAGE_SHIFT; + } else { + printk(KERN_WARNING "vio_build_tce_table: Invalid size of ibm,my-dma-window=%i, using 0x80 for size\n", dma_window_property_size); + size = 0x80; + } + + /* There should be some code to extract the phys-encoded offset + using prom_n_addr_cells(). However, according to a comment + on earlier versions, it's always zero, so we don't bother */ + offset = dma_window[1] >> PAGE_SHIFT; + + /* TCE table size - measured in units of pages of tce table */ + newTceTable->size = size; + /* offset for VIO should always be 0 */ + newTceTable->startOffset = offset; + newTceTable->busNumber = 0; + newTceTable->index = (unsigned long)dma_window[0]; + newTceTable->tceType = TCE_VB; + + return build_tce_table(newTceTable); +} + +int vio_enable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); + if (rc != H_Success) { + printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); + } + return rc; +} +EXPORT_SYMBOL(vio_enable_interrupts); + +int vio_disable_interrupts(struct vio_dev *dev) +{ + int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); + if (rc != H_Success) { + printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); + } + return rc; +} +EXPORT_SYMBOL(vio_disable_interrupts); + + +dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr, + size_t size, int direction ) +{ + struct TceTable * tbl; + dma_addr_t dma_handle = NO_TCE; + unsigned long uaddr; + unsigned order, nPages; + + if(direction == PCI_DMA_NONE) BUG(); + + uaddr = (unsigned long)vaddr; + nPages = PAGE_ALIGN( uaddr + size ) - ( uaddr & PAGE_MASK ); + order = get_order( nPages & PAGE_MASK ); + nPages >>= PAGE_SHIFT; + + /* Client asked for way to much space. This is checked later anyway */ + /* It is easier to debug here for the drivers than in the tce tables.*/ + if(order >= NUM_TCE_LEVELS) { + printk("VIO_DMA: vio_map_single size to large: 0x%lx \n",size); + return NO_TCE; + } + + tbl = dev->tce_table; + + if(tbl) { + dma_handle = get_tces(tbl, order, vaddr, nPages, direction); + dma_handle |= (uaddr & ~PAGE_MASK); + } + + return dma_handle; +} +EXPORT_SYMBOL(vio_map_single); + +void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle, + size_t size, int direction) +{ + struct TceTable * tbl; + unsigned order, nPages; + + if (direction == PCI_DMA_NONE) BUG(); + + nPages = PAGE_ALIGN( dma_handle + size ) - ( dma_handle & PAGE_MASK ); + order = get_order( nPages & PAGE_MASK ); + nPages >>= PAGE_SHIFT; + + /* Client asked for way to much space. This is checked later anyway */ + /* It is easier to debug here for the drivers than in the tce tables.*/ + if(order >= NUM_TCE_LEVELS) { + printk("VIO_DMA: vio_unmap_single 0x%lx size to large: 0x%lx \n",(unsigned long)dma_handle,(unsigned long)size); + return; + } + + tbl = dev->tce_table; + if(tbl) tce_free(tbl, dma_handle, order, nPages); +} +EXPORT_SYMBOL(vio_unmap_single); + +int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems, + int direction) +{ + int i; + + for (i = 0; i < nelems; i++) { + + /* 2.4 scsi scatterlists use address field. + Not sure about other subsystems. */ + void *vaddr; +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0) + if (sglist->address) + vaddr = sglist->address; + else +#endif + vaddr = page_address(sglist->page) + sglist->offset; + + sglist->dma_address = vio_map_single(vdev, vaddr, + sglist->length, + direction); + sglist->dma_length = sglist->length; + sglist++; + } + + return nelems; +} +EXPORT_SYMBOL(vio_map_sg); + +void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems, + int direction) +{ + while (nelems--) { + vio_unmap_single(vdev, sglist->dma_address, + sglist->dma_length, direction); + sglist++; + } +} + +void *vio_alloc_consistent(struct vio_dev *dev, size_t size, + dma_addr_t *dma_handle) +{ + struct TceTable * tbl; + void *ret = NULL; + unsigned order, nPages; + dma_addr_t tce; + + size = PAGE_ALIGN(size); + order = get_order(size); + nPages = 1 << order; + + /* Client asked for way to much space. This is checked later anyway */ + /* It is easier to debug here for the drivers than in the tce tables.*/ + if(order >= NUM_TCE_LEVELS) { + printk("VIO_DMA: vio_alloc_consistent size to large: 0x%lx \n",size); + return (void *)NO_TCE; + } + + tbl = dev->tce_table; + + if ( tbl ) { + /* Alloc enough pages (and possibly more) */ + ret = (void *)__get_free_pages( GFP_ATOMIC, order ); + if ( ret ) { + /* Page allocation succeeded */ + memset(ret, 0, nPages << PAGE_SHIFT); + /* Set up tces to cover the allocated range */ + tce = get_tces( tbl, order, ret, nPages, PCI_DMA_BIDIRECTIONAL ); + if ( tce == NO_TCE ) { + PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: get_tces failed\n" ); + free_pages( (unsigned long)ret, order ); + ret = NULL; + } + else + { + *dma_handle = tce; + } + } + else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: __get_free_pages failed for order = %d\n", order); + } + else PPCDBG(PPCDBG_TCE, "vio_alloc_consistent: get_tce_table failed for 0x%016lx\n", dev); + + PPCDBG(PPCDBG_TCE, "\tvio_alloc_consistent: dma_handle = 0x%16.16lx\n", *dma_handle); + PPCDBG(PPCDBG_TCE, "\tvio_alloc_consistent: return = 0x%16.16lx\n", ret); + return ret; +} +EXPORT_SYMBOL(vio_alloc_consistent); + +void vio_free_consistent(struct vio_dev *dev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + struct TceTable * tbl; + unsigned order, nPages; + + PPCDBG(PPCDBG_TCE, "vio_free_consistent:\n"); + PPCDBG(PPCDBG_TCE, "\tdev = 0x%16.16lx, size = 0x%16.16lx, dma_handle = 0x%16.16lx, vaddr = 0x%16.16lx\n", dev, size, dma_handle, vaddr); + + size = PAGE_ALIGN(size); + order = get_order(size); + nPages = 1 << order; + + /* Client asked for way to much space. This is checked later anyway */ + /* It is easier to debug here for the drivers than in the tce tables.*/ + if(order >= NUM_TCE_LEVELS) { + printk("PCI_DMA: pci_free_consistent size to large: 0x%lx \n",size); + return; + } + + tbl = dev->tce_table; + + if ( tbl ) { + tce_free(tbl, dma_handle, order, nPages); + free_pages( (unsigned long)vaddr, order ); + } +} +EXPORT_SYMBOL(vio_free_consistent); + +EXPORT_SYMBOL(plpar_hcall_norets); +EXPORT_SYMBOL(plpar_hcall_8arg_2ret); diff -puN /dev/null arch/ppc64/kernel/viopath.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/kernel/viopath.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,757 @@ +/* -*- linux-c -*- + * arch/ppc64/kernel/viopath.c + * + * iSeries Virtual I/O Message Path code + * + * Authors: Dave Boutcher + * Ryan Arnold + * Colin Devilbiss + * + * (C) Copyright 2000-2003 IBM Corporation + * + * This code is used by the iSeries virtual disk, cd, + * tape, and console to communicate with OS/400 in another + * partition. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) anyu later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for is_atomic */ + +#include +#include +#include +#include +#include +#include +#include + +extern struct pci_dev *iSeries_vio_dev; + +/* Status of the path to each other partition in the system. + * This is overkill, since we will only ever establish connections + * to our hosting partition and the primary partition on the system. + * But this allows for other support in the future. + */ +static struct viopathStatus { + int isOpen:1; /* Did we open the path? */ + int isActive:1; /* Do we have a mon msg outstanding */ + int users[VIO_MAX_SUBTYPES]; + HvLpInstanceId mSourceInst; + HvLpInstanceId mTargetInst; + int numberAllocated; +} viopathStatus[HVMAXARCHITECTEDLPS]; + +static spinlock_t statuslock = SPIN_LOCK_UNLOCKED; + +/* + * For each kind of event we allocate a buffer that is + * guaranteed not to cross a page boundary + */ +static unsigned char event_buffer[VIO_MAX_SUBTYPES * 256] __page_aligned; +static atomic_t event_buffer_available[VIO_MAX_SUBTYPES]; +static int event_buffer_initialised; + +static void handleMonitorEvent(struct HvLpEvent *event); + +/* + * We use this structure to handle asynchronous responses. The caller + * blocks on the semaphore and the handler posts the semaphore. However, + * if in_atomic() is true in the caller, then wait_atomic is used ... + */ +struct doneAllocParms_t { + struct semaphore *sem; + int number; + atomic_t *wait_atomic; + int used_wait_atomic; +}; + +/* Put a sequence number in each mon msg. The value is not + * important. Start at something other than 0 just for + * readability. wrapping this is ok. + */ +static u8 viomonseq = 22; + +/* Our hosting logical partition. We get this at startup + * time, and different modules access this variable directly. + */ +HvLpIndex viopath_hostLp = 0xff; /* HvLpIndexInvalid */ +EXPORT_SYMBOL(viopath_hostLp); +HvLpIndex viopath_ourLp = 0xff; +EXPORT_SYMBOL(viopath_ourLp); + +/* For each kind of incoming event we set a pointer to a + * routine to call. + */ +static vio_event_handler_t *vio_handler[VIO_MAX_SUBTYPES]; + +static unsigned char e2a(unsigned char x) +{ + switch (x) { + case 0xF0: + return '0'; + case 0xF1: + return '1'; + case 0xF2: + return '2'; + case 0xF3: + return '3'; + case 0xF4: + return '4'; + case 0xF5: + return '5'; + case 0xF6: + return '6'; + case 0xF7: + return '7'; + case 0xF8: + return '8'; + case 0xF9: + return '9'; + case 0xC1: + return 'A'; + case 0xC2: + return 'B'; + case 0xC3: + return 'C'; + case 0xC4: + return 'D'; + case 0xC5: + return 'E'; + case 0xC6: + return 'F'; + case 0xC7: + return 'G'; + case 0xC8: + return 'H'; + case 0xC9: + return 'I'; + case 0xD1: + return 'J'; + case 0xD2: + return 'K'; + case 0xD3: + return 'L'; + case 0xD4: + return 'M'; + case 0xD5: + return 'N'; + case 0xD6: + return 'O'; + case 0xD7: + return 'P'; + case 0xD8: + return 'Q'; + case 0xD9: + return 'R'; + case 0xE2: + return 'S'; + case 0xE3: + return 'T'; + case 0xE4: + return 'U'; + case 0xE5: + return 'V'; + case 0xE6: + return 'W'; + case 0xE7: + return 'X'; + case 0xE8: + return 'Y'; + case 0xE9: + return 'Z'; + } + return ' '; +} + +/* Handle reads from the proc file system + */ +static int proc_read(char *buf, char **start, off_t offset, + int blen, int *eof, void *data) +{ + HvLpEvent_Rc hvrc; + DECLARE_MUTEX_LOCKED(Semaphore); + dma_addr_t dmaa = + pci_map_single(iSeries_vio_dev, buf, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + int len = PAGE_SIZE; + + if (len > blen) + len = blen; + + memset(buf, 0x00, len); + hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp, + HvLpEvent_Type_VirtualIo, + viomajorsubtype_config | vioconfigget, + HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, + viopath_sourceinst(viopath_hostLp), + viopath_targetinst(viopath_hostLp), + (u64)(unsigned long)&Semaphore, VIOVERSION << 16, + ((u64)dmaa) << 32, len, 0, 0); + if (hvrc != HvLpEvent_Rc_Good) + printk("viopath hv error on op %d\n", (int) hvrc); + + down(&Semaphore); + + pci_unmap_single(iSeries_vio_dev, dmaa, PAGE_SIZE, + PCI_DMA_FROMDEVICE); + + sprintf(buf + strlen(buf), "SRLNBR="); + buf[strlen(buf)] = e2a(xItExtVpdPanel.mfgID[2]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.mfgID[3]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[1]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[2]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[3]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[4]); + buf[strlen(buf)] = e2a(xItExtVpdPanel.systemSerial[5]); + buf[strlen(buf)] = '\n'; + *eof = 1; + return strlen(buf); +} + +/* Handle writes to our proc file system + */ +static int proc_write(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + /* Doesn't do anything today!!! + */ + return count; +} + +/* setup our proc file system entries + */ +static void vio_proc_init(struct proc_dir_entry *iSeries_proc) +{ + struct proc_dir_entry *ent; + ent = create_proc_entry("config", S_IFREG | S_IRUSR, iSeries_proc); + if (!ent) + return; + ent->nlink = 1; + ent->data = NULL; + ent->read_proc = proc_read; + ent->write_proc = proc_write; +} + +/* See if a given LP is active. Allow for invalid lps to be passed in + * and just return invalid + */ +int viopath_isactive(HvLpIndex lp) +{ + if (lp == HvLpIndexInvalid) + return 0; + if (lp < HVMAXARCHITECTEDLPS) + return viopathStatus[lp].isActive; + else + return 0; +} +EXPORT_SYMBOL(viopath_isactive); + +/* + * We cache the source and target instance ids for each + * partition. + */ +HvLpInstanceId viopath_sourceinst(HvLpIndex lp) +{ + return viopathStatus[lp].mSourceInst; +} +EXPORT_SYMBOL(viopath_sourceinst); + +HvLpInstanceId viopath_targetinst(HvLpIndex lp) +{ + return viopathStatus[lp].mTargetInst; +} +EXPORT_SYMBOL(viopath_targetinst); + +/* + * Send a monitor message. This is a message with the acknowledge + * bit on that the other side will NOT explicitly acknowledge. When + * the other side goes down, the hypervisor will acknowledge any + * outstanding messages....so we will know when the other side dies. + */ +static void sendMonMsg(HvLpIndex remoteLp) +{ + HvLpEvent_Rc hvrc; + + viopathStatus[remoteLp].mSourceInst = + HvCallEvent_getSourceLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].mTargetInst = + HvCallEvent_getTargetLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + + /* + * Deliberately ignore the return code here. if we call this + * more than once, we don't care. + */ + vio_setHandler(viomajorsubtype_monitor, handleMonitorEvent); + + hvrc = HvCallEvent_signalLpEventFast(remoteLp, HvLpEvent_Type_VirtualIo, + viomajorsubtype_monitor, HvLpEvent_AckInd_DoAck, + HvLpEvent_AckType_DeferredAck, + viopathStatus[remoteLp].mSourceInst, + viopathStatus[remoteLp].mTargetInst, + viomonseq++, 0, 0, 0, 0, 0); + + if (hvrc == HvLpEvent_Rc_Good) + viopathStatus[remoteLp].isActive = 1; + else { + printk(KERN_WARNING_VIO "could not connect to partition %d\n", + remoteLp); + viopathStatus[remoteLp].isActive = 0; + } +} + +static void handleMonitorEvent(struct HvLpEvent *event) +{ + HvLpIndex remoteLp; + int i; + + /* + * This handler is _also_ called as part of the loop + * at the end of this routine, so it must be able to + * ignore NULL events... + */ + if (!event) + return; + + /* + * First see if this is just a normal monitor message from the + * other partition + */ + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + remoteLp = event->xSourceLp; + if (!viopathStatus[remoteLp].isActive) + sendMonMsg(remoteLp); + return; + } + + /* + * This path is for an acknowledgement; the other partition + * died + */ + remoteLp = event->xTargetLp; + if ((event->xSourceInstanceId != viopathStatus[remoteLp].mSourceInst) || + (event->xTargetInstanceId != viopathStatus[remoteLp].mTargetInst)) { + printk(KERN_WARNING_VIO "ignoring ack....mismatched instances\n"); + return; + } + + printk(KERN_WARNING_VIO "partition %d ended\n", remoteLp); + + viopathStatus[remoteLp].isActive = 0; + + /* + * For each active handler, pass them a NULL + * message to indicate that the other partition + * died + */ + for (i = 0; i < VIO_MAX_SUBTYPES; i++) { + if (vio_handler[i] != NULL) + (*vio_handler[i])(NULL); + } +} + +int vio_setHandler(int subtype, vio_event_handler_t *beh) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + if (vio_handler[subtype] != NULL) + return -EBUSY; + vio_handler[subtype] = beh; + return 0; +} +EXPORT_SYMBOL(vio_setHandler); + +int vio_clearHandler(int subtype) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + if (vio_handler[subtype] == NULL) + return -EAGAIN; + vio_handler[subtype] = NULL; + return 0; +} +EXPORT_SYMBOL(vio_clearHandler); + +static void handleConfig(struct HvLpEvent *event) +{ + if (!event) + return; + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + printk(KERN_WARNING_VIO + "unexpected config request from partition %d", + event->xSourceLp); + + if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && + (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + up((struct semaphore *)event->xCorrelationToken); +} + +/* + * Initialization of the hosting partition + */ +void vio_set_hostlp(void) +{ + /* + * If this has already been set then we DON'T want to either change + * it or re-register the proc file system + */ + if (viopath_hostLp != HvLpIndexInvalid) + return; + + /* + * Figure out our hosting partition. This isn't allowed to change + * while we're active + */ + viopath_ourLp = HvLpConfig_getLpIndex(); + viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp); + + /* If we have a valid hosting LP, create a proc file system entry + * for config information + */ + if (viopath_hostLp != HvLpIndexInvalid) { + iSeries_proc_callback(&vio_proc_init); + vio_setHandler(viomajorsubtype_config, handleConfig); + } +} +EXPORT_SYMBOL(vio_set_hostlp); + +static void vio_handleEvent(struct HvLpEvent *event, struct pt_regs *regs) +{ + HvLpIndex remoteLp; + int subtype = (event->xSubtype & VIOMAJOR_SUBTYPE_MASK) + >> VIOMAJOR_SUBTYPE_SHIFT; + + if (event->xFlags.xFunction == HvLpEvent_Function_Int) { + remoteLp = event->xSourceLp; + /* + * The isActive is checked because if the hosting partition + * went down and came back up it would not be active but it + * would have different source and target instances, in which + * case we'd want to reset them. This case really protects + * against an unauthorized active partition sending interrupts + * or acks to this linux partition. + */ + if (viopathStatus[remoteLp].isActive + && (event->xSourceInstanceId != + viopathStatus[remoteLp].mTargetInst)) { + printk(KERN_WARNING_VIO + "message from invalid partition. " + "int msg rcvd, source inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mTargetInst, + event->xSourceInstanceId); + return; + } + + if (viopathStatus[remoteLp].isActive + && (event->xTargetInstanceId != + viopathStatus[remoteLp].mSourceInst)) { + printk(KERN_WARNING_VIO + "message from invalid partition. " + "int msg rcvd, target inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mSourceInst, + event->xTargetInstanceId); + return; + } + } else { + remoteLp = event->xTargetLp; + if (event->xSourceInstanceId != + viopathStatus[remoteLp].mSourceInst) { + printk(KERN_WARNING_VIO + "message from invalid partition. " + "ack msg rcvd, source inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mSourceInst, + event->xSourceInstanceId); + return; + } + + if (event->xTargetInstanceId != + viopathStatus[remoteLp].mTargetInst) { + printk(KERN_WARNING_VIO + "message from invalid partition. " + "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n", + viopathStatus[remoteLp].mTargetInst, + event->xTargetInstanceId); + return; + } + } + + if (vio_handler[subtype] == NULL) { + printk(KERN_WARNING_VIO + "unexpected virtual io event subtype %d from partition %d\n", + event->xSubtype, remoteLp); + /* No handler. Ack if necessary */ + if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && + (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { + event->xRc = HvLpEvent_Rc_InvalidSubtype; + HvCallEvent_ackLpEvent(event); + } + return; + } + + /* This innocuous little line is where all the real work happens */ + (*vio_handler[subtype])(event); +} + +static void viopath_donealloc(void *parm, int number) +{ + struct doneAllocParms_t *parmsp = (struct doneAllocParms_t *)parm; + + parmsp->number = number; + if (parmsp->used_wait_atomic) + atomic_set(parmsp->wait_atomic, 0); + else + up(parmsp->sem); +} + +static int allocateEvents(HvLpIndex remoteLp, int numEvents) +{ + struct doneAllocParms_t parms; + DECLARE_MUTEX_LOCKED(Semaphore); + atomic_t wait_atomic; + + if (in_atomic()) { + parms.used_wait_atomic = 1; + atomic_set(&wait_atomic, 1); + parms.wait_atomic = &wait_atomic; + } else { + parms.used_wait_atomic = 0; + parms.sem = &Semaphore; + } + mf_allocateLpEvents(remoteLp, HvLpEvent_Type_VirtualIo, 250, /* It would be nice to put a real number here! */ + numEvents, &viopath_donealloc, &parms); + if (in_atomic()) { + while (atomic_read(&wait_atomic)) + mb(); + } else + down(&Semaphore); + return parms.number; +} + +int viopath_open(HvLpIndex remoteLp, int subtype, int numReq) +{ + int i; + unsigned long flags; + int tempNumAllocated; + + if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid)) + return -EINVAL; + + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + + spin_lock_irqsave(&statuslock, flags); + + if (!event_buffer_initialised) { + for (i = 0; i < VIO_MAX_SUBTYPES; i++) + atomic_set(&event_buffer_available[i], 1); + event_buffer_initialised = 1; + } + + viopathStatus[remoteLp].users[subtype]++; + + if (!viopathStatus[remoteLp].isOpen) { + viopathStatus[remoteLp].isOpen = 1; + HvCallEvent_openLpEventPath(remoteLp, HvLpEvent_Type_VirtualIo); + + /* + * Don't hold the spinlock during an operation that + * can sleep. + */ + spin_unlock_irqrestore(&statuslock, flags); + tempNumAllocated = allocateEvents(remoteLp, 1); + spin_lock_irqsave(&statuslock, flags); + + viopathStatus[remoteLp].numberAllocated += tempNumAllocated; + + if (viopathStatus[remoteLp].numberAllocated == 0) { + HvCallEvent_closeLpEventPath(remoteLp, + HvLpEvent_Type_VirtualIo); + + spin_unlock_irqrestore(&statuslock, flags); + return -ENOMEM; + } + + viopathStatus[remoteLp].mSourceInst = + HvCallEvent_getSourceLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].mTargetInst = + HvCallEvent_getTargetLpInstanceId(remoteLp, + HvLpEvent_Type_VirtualIo); + HvLpEvent_registerHandler(HvLpEvent_Type_VirtualIo, + &vio_handleEvent); + sendMonMsg(remoteLp); + printk(KERN_INFO_VIO + "Opening connection to partition %d, setting sinst %d, tinst %d\n", + remoteLp, viopathStatus[remoteLp].mSourceInst, + viopathStatus[remoteLp].mTargetInst); + } + + spin_unlock_irqrestore(&statuslock, flags); + tempNumAllocated = allocateEvents(remoteLp, numReq); + spin_lock_irqsave(&statuslock, flags); + viopathStatus[remoteLp].numberAllocated += tempNumAllocated; + spin_unlock_irqrestore(&statuslock, flags); + + return 0; +} +EXPORT_SYMBOL(viopath_open); + +int viopath_close(HvLpIndex remoteLp, int subtype, int numReq) +{ + unsigned long flags; + int i; + int numOpen; + struct doneAllocParms_t doneAllocParms; + DECLARE_MUTEX_LOCKED(Semaphore); + + if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid)) + return -EINVAL; + + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return -EINVAL; + + spin_lock_irqsave(&statuslock, flags); + /* + * If the viopath_close somehow gets called before a + * viopath_open it could decrement to -1 which is a non + * recoverable state so we'll prevent this from + * happening. + */ + if (viopathStatus[remoteLp].users[subtype] > 0) + viopathStatus[remoteLp].users[subtype]--; + + spin_unlock_irqrestore(&statuslock, flags); + + doneAllocParms.used_wait_atomic = 0; + doneAllocParms.sem = &Semaphore; + mf_deallocateLpEvents(remoteLp, HvLpEvent_Type_VirtualIo, + numReq, &viopath_donealloc, &doneAllocParms); + down(&Semaphore); + + spin_lock_irqsave(&statuslock, flags); + for (i = 0, numOpen = 0; i < VIO_MAX_SUBTYPES; i++) + numOpen += viopathStatus[remoteLp].users[i]; + + if ((viopathStatus[remoteLp].isOpen) && (numOpen == 0)) { + printk(KERN_INFO_VIO "Closing connection to partition %d", + remoteLp); + + HvCallEvent_closeLpEventPath(remoteLp, + HvLpEvent_Type_VirtualIo); + viopathStatus[remoteLp].isOpen = 0; + viopathStatus[remoteLp].isActive = 0; + + for (i = 0; i < VIO_MAX_SUBTYPES; i++) + atomic_set(&event_buffer_available[i], 0); + event_buffer_initialised = 0; + } + spin_unlock_irqrestore(&statuslock, flags); + return 0; +} +EXPORT_SYMBOL(viopath_close); + +void *vio_get_event_buffer(int subtype) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) + return NULL; + + if (atomic_dec_if_positive(&event_buffer_available[subtype]) == 0) + return &event_buffer[subtype * 256]; + else + return NULL; +} +EXPORT_SYMBOL(vio_get_event_buffer); + +void vio_free_event_buffer(int subtype, void *buffer) +{ + subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT; + if ((subtype < 0) || (subtype >= VIO_MAX_SUBTYPES)) { + printk(KERN_WARNING_VIO + "unexpected subtype %d freeing event buffer\n", + subtype); + return; + } + + if (atomic_read(&event_buffer_available[subtype]) != 0) { + printk(KERN_WARNING_VIO + "freeing unallocated event buffer, subtype %d\n", + subtype); + return; + } + + if (buffer != &event_buffer[subtype * 256]) { + printk(KERN_WARNING_VIO + "freeing invalid event buffer, subtype %d\n", + subtype); + } + + atomic_set(&event_buffer_available[subtype], 1); +} +EXPORT_SYMBOL(vio_free_event_buffer); + +static const struct vio_error_entry vio_no_error = + { 0, 0, "Non-VIO Error" }; +static const struct vio_error_entry vio_unknown_error = + { 0, EIO, "Unknown Error" }; + +static const struct vio_error_entry vio_default_errors[] = { + {0x0001, EIO, "No Connection"}, + {0x0002, EIO, "No Receiver"}, + {0x0003, EIO, "No Buffer Available"}, + {0x0004, EBADRQC, "Invalid Message Type"}, + {0x0000, 0, NULL}, +}; + +const struct vio_error_entry *vio_lookup_rc( + const struct vio_error_entry *local_table, u16 rc) +{ + const struct vio_error_entry *cur; + + if (!rc) + return &vio_no_error; + if (local_table) + for (cur = local_table; cur->rc; ++cur) + if (cur->rc == rc) + return cur; + for (cur = vio_default_errors; cur->rc; ++cur) + if (cur->rc == rc) + return cur; + return &vio_unknown_error; +} +EXPORT_SYMBOL(vio_lookup_rc); diff -puN arch/ppc64/kernel/vmlinux.lds.S~linus arch/ppc64/kernel/vmlinux.lds.S --- 25/arch/ppc64/kernel/vmlinux.lds.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/vmlinux.lds.S 2004-01-19 22:17:21.000000000 -0800 @@ -1,145 +1,146 @@ #include OUTPUT_ARCH(powerpc:common64) -/* Do we need any of these for elf? - __DYNAMIC = 0; */ jiffies = jiffies_64; SECTIONS { - /* Read-only sections, merged into text segment: */ - . = + SIZEOF_HEADERS; - .interp : { *(.interp) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .rel.text : { *(.rel.text) } - .rela.text : { *(.rela.text) } - .rel.data : { *(.rel.data) } - .rela.data : { *(.rela.data) } - .rel.rodata : { *(.rel.rodata) } - .rela.rodata : { *(.rela.rodata) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.bss : { *(.rel.bss) } - .rela.bss : { *(.rela.bss) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } -/* .init : { *(.init) } =0*/ - .plt : { *(.plt) } - .text : - { - *(.text) - *(.fixup) - *(.got1) - } - . = ALIGN(4096); - _etext = .; - PROVIDE (etext = .); - - RODATA - - .fini : { *(.fini) } =0 - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - /* Read-write section, merged into data segment: */ - . = (. + 0x0FFF) & 0xFFFFFFFFFFFFF000; - .data : - { - *(.data) - *(.data1) - *(.sdata) - *(.sdata2) - *(.got.plt) *(.got) - *(.dynamic) - CONSTRUCTORS - } - . = ALIGN(4096); - _edata = .; - PROVIDE (edata = .); + /* Sections to be discarded. */ + /DISCARD/ : { + *(.exitcall.exit) + } - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - __start___bug_table = .; - __bug_table : { *(__bug_table) } - __stop___bug_table = .; - - __start___ftr_fixup = .; - __ftr_fixup : { *(__ftr_fixup) } - __stop___ftr_fixup = .; - . = ALIGN(16384); /* init_task */ - .data.init_task : { *(.data.init_task) } + /* Read-only sections, merged into text segment: */ + .text : { + *(.text .text.*) + *(.fixup) + . = ALIGN(4096); + _etext = .; + } + + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } + + __bug_table : { + __start___bug_table = .; + *(__bug_table) + __stop___bug_table = .; + } + + __ftr_fixup : { + __start___ftr_fixup = .; + *(__ftr_fixup) + __stop___ftr_fixup = .; + } - . = ALIGN(4096); - .data.page_aligned : { *(.data.page_aligned) } + RODATA - . = ALIGN(128); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } /* will be freed after init */ . = ALIGN(4096); __init_begin = .; - .init.text : { + + .init.text : { _sinittext = .; *(.init.text) _einittext = .; - } - .init.data : { *(.init.data) } + } + + .init.data : { + *(.init.data) + } + . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - __start___param = .; - __param : { *(__param) } - __stop___param = .; - __initcall_start = .; + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + + __param : { + __start___param = .; + *(__param) + __stop___param = .; + } + .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) + __initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) *(.initcall7.init) - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; + __initcall_end = .; + } + + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + SECURITY_INIT + . = ALIGN(4096); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; - . = ALIGN(32); - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; - . = ALIGN(4096); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } + + .data.percpu : { + __per_cpu_start = .; + *(.data.percpu) + __per_cpu_end = .; + } + + . = ALIGN(16384); __init_end = .; /* freed after init ends here */ - __toc_start = .; - .toc : { *(.toc) } - . = ALIGN(4096); - __toc_end = .; - __bss_start = .; - .bss : { *(.bss) } - __bss_stop = .; + /* Read/write sections */ + . = ALIGN(16384); + /* The initial task and kernel stack */ + .data.init_task : { + *(.data.init_task) + } + + .data.page_aligned : { + *(.data.page_aligned) + } + + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } + + .data : { + *(.data .data.rel* .toc1) + *(.opd) + *(.branch_lt) + } + + .got : { + __toc_start = .; + *(.got) + *(.toc) + . = ALIGN(4096); + _edata = .; + } + . = ALIGN(4096); - _end = . ; - PROVIDE (end = .); + .bss : { + __bss_start = .; + *(.bss) + __bss_stop = .; + } - /* Sections to be discarded. */ - /DISCARD/ : { - *(.exitcall.exit) - } + . = ALIGN(4096); + _end = . ; } diff -puN arch/ppc64/kernel/xics.c~linus arch/ppc64/kernel/xics.c --- 25/arch/ppc64/kernel/xics.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/xics.c 2004-01-19 22:17:21.000000000 -0800 @@ -202,7 +202,7 @@ static void pSeriesLP_qirr_info(int n_cp { unsigned long lpar_rc; - lpar_rc = plpar_ipi(n_cpu, value); + lpar_rc = plpar_ipi(get_hard_smp_processor_id(n_cpu), value); if (lpar_rc != H_Success) panic("bad return code qirr - rc = %lx\n", lpar_rc); } @@ -398,7 +398,7 @@ void xics_init_IRQ(void) ibm_int_on = rtas_token("ibm,int-on"); ibm_int_off = rtas_token("ibm,int-off"); - np = find_type_devices("PowerPC-External-Interrupt-Presentation"); + np = of_find_node_by_type(NULL, "PowerPC-External-Interrupt-Presentation"); if (!np) { printk(KERN_WARNING "Can't find Interrupt Presentation\n"); udbg_printf("Can't find Interrupt Presentation\n"); @@ -433,13 +433,15 @@ nextnode: if (indx >= NR_CPUS) break; } - np = np->next; + np = of_find_node_by_type(np, "PowerPC-External-Interrupt-Presentation"); if ((indx < NR_CPUS) && np) goto nextnode; /* Find the server numbers for the boot cpu. */ - for (np = find_type_devices("cpu"); np; np = np->next) { + for (np = of_find_node_by_type(NULL, "cpu"); + np; + np = of_find_node_by_type(np, "cpu")) { ireg = (uint *)get_property(np, "reg", &ilen); - if (ireg && ireg[0] == smp_processor_id()) { + if (ireg && ireg[0] == hard_smp_processor_id()) { ireg = (uint *)get_property(np, "ibm,ppc-interrupt-gserver#s", &ilen); i = ilen / sizeof(int); if (ireg && i > 0) { @@ -449,11 +451,12 @@ nextnode: break; } } + of_node_put(np); intr_base = inodes[0].addr; intr_size = (ulong)inodes[0].size; - np = find_type_devices("interrupt-controller"); + np = of_find_node_by_type(NULL, "interrupt-controller"); if (!np) { printk(KERN_WARNING "xics: no ISA Interrupt Controller\n"); xics_irq_8259_cascade_real = -1; @@ -467,6 +470,7 @@ nextnode: } xics_irq_8259_cascade_real = *ireg; xics_irq_8259_cascade = virt_irq_create_mapping(xics_irq_8259_cascade_real); + of_node_put(np); } if (systemcfg->platform == PLATFORM_PSERIES) { @@ -474,8 +478,8 @@ nextnode: for (i = 0; i < NR_CPUS; ++i) { if (!cpu_possible(i)) continue; - xics_per_cpu[i] = __ioremap((ulong)inodes[i].addr, - (ulong)inodes[i].size, + xics_per_cpu[i] = __ioremap((ulong)inodes[get_hard_smp_processor_id(i)].addr, + (ulong)inodes[get_hard_smp_processor_id(i)].size, _PAGE_NO_CACHE); } #else @@ -566,7 +570,7 @@ void xics_set_affinity(unsigned int virq cpus_and(tmp, cpu_online_map, cpumask); if (cpus_empty(tmp)) goto out; - newmask = first_cpu(cpumask); + newmask = get_hard_smp_processor_id(first_cpu(cpumask)); } status = rtas_call(ibm_set_xive, 3, 1, NULL, diff -puN arch/ppc64/kernel/XmPciLpEvent.c~linus arch/ppc64/kernel/XmPciLpEvent.c --- 25/arch/ppc64/kernel/XmPciLpEvent.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/XmPciLpEvent.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,10 +1,10 @@ /* - * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001. - * - * This module handles PCI interrupt events sent by the iSeries Hypervisor. + * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001. + * + * This module handles PCI interrupt events sent by the iSeries Hypervisor. */ - +#include #include #include #include @@ -20,13 +20,13 @@ #include #include -long Pci_Interrupt_Count = 0; -long Pci_Event_Count = 0; +static long Pci_Interrupt_Count; +static long Pci_Event_Count; enum XmPciLpEvent_Subtype { XmPciLpEvent_BusCreated = 0, // PHB has been created XmPciLpEvent_BusError = 1, // PHB has failed - XmPciLpEvent_BusFailed = 2, // Msg to Seconday, Primary failed bus + XmPciLpEvent_BusFailed = 2, // Msg to Secondary, Primary failed bus XmPciLpEvent_NodeFailed = 4, // Multi-adapter bridge has failed XmPciLpEvent_NodeRecovered = 5, // Multi-adapter bridge has recovered XmPciLpEvent_BusRecovered = 12, // PHB has been recovered @@ -36,14 +36,14 @@ enum XmPciLpEvent_Subtype { }; struct XmPciLpEvent_BusInterrupt { - HvBusNumber busNumber; + HvBusNumber busNumber; HvSubBusNumber subBusNumber; }; struct XmPciLpEvent_NodeInterrupt { - HvBusNumber busNumber; + HvBusNumber busNumber; HvSubBusNumber subBusNumber; - HvAgentId deviceId; + HvAgentId deviceId; }; struct XmPciLpEvent { @@ -53,10 +53,10 @@ struct XmPciLpEvent { u64 alignData; // Align on an 8-byte boundary struct { - u32 fisr; + u32 fisr; HvBusNumber busNumber; HvSubBusNumber subBusNumber; - HvAgentId deviceId; + HvAgentId deviceId; } slotInterrupt; struct XmPciLpEvent_BusInterrupt busFailed; @@ -70,40 +70,52 @@ struct XmPciLpEvent { }; -static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm); +static void intReceived(struct XmPciLpEvent *eventParm, + struct pt_regs *regsParm); -static void XmPciLpEvent_handler( struct HvLpEvent* eventParm, struct pt_regs* regsParm) +static void XmPciLpEvent_handler(struct HvLpEvent *eventParm, + struct pt_regs *regsParm) { - //PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_handler, type 0x%x\n",eventParm->xType ); +#ifdef CONFIG_PCI +#if 0 + PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n", + eventParm->xType); +#endif ++Pci_Event_Count; - if (eventParm && eventParm->xType == HvLpEvent_Type_PciIo) { - switch( eventParm->xFlags.xFunction ) { + if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) { + switch (eventParm->xFlags.xFunction) { case HvLpEvent_Function_Int: - intReceived( (struct XmPciLpEvent*)eventParm, regsParm ); + intReceived((struct XmPciLpEvent *)eventParm, regsParm); break; case HvLpEvent_Function_Ack: - printk(KERN_ERR "XmPciLpEvent.c: unexpected ack received\n"); + printk(KERN_ERR + "XmPciLpEvent.c: unexpected ack received\n"); break; default: - printk(KERN_ERR "XmPciLpEvent.c: unexpected event function %d\n",(int)eventParm->xFlags.xFunction); + printk(KERN_ERR + "XmPciLpEvent.c: unexpected event function %d\n", + (int)eventParm->xFlags.xFunction); break; } - } - else if (event) { - printk(KERN_ERR "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",(int)eventParm->xType); - } - else { + } else if (eventParm) + printk(KERN_ERR + "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n", + (int)eventParm->xType); + else printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n"); - } +#endif } -static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm) +static void intReceived(struct XmPciLpEvent *eventParm, + struct pt_regs *regsParm) { int irq; ++Pci_Interrupt_Count; - //PPCDBG(PPCDBG_BUSWALK,"PCI: XmPciLpEvent.c: intReceived\n"); +#if 0 + PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n"); +#endif switch (eventParm->hvLpEvent.xSubtype) { case XmPciLpEvent_SlotInterrupt: @@ -111,33 +123,45 @@ static void intReceived(struct XmPciLpEv /* Dispatch the interrupt handlers for this irq */ ppc_irq_dispatch_handler(regsParm, irq); HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber, - eventParm->eventData.slotInterrupt.subBusNumber, - eventParm->eventData.slotInterrupt.deviceId); + eventParm->eventData.slotInterrupt.subBusNumber, + eventParm->eventData.slotInterrupt.deviceId); break; /* Ignore error recovery events for now */ case XmPciLpEvent_BusCreated: - printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber); + printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", + eventParm->eventData.busCreated.busNumber); break; case XmPciLpEvent_BusError: case XmPciLpEvent_BusFailed: - printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber); + printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", + eventParm->eventData.busFailed.busNumber); break; case XmPciLpEvent_BusRecovered: case XmPciLpEvent_UnQuiesceBus: - printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber); + printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", + eventParm->eventData.busRecovered.busNumber); break; case XmPciLpEvent_NodeFailed: case XmPciLpEvent_BridgeError: - printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId); + printk(KERN_INFO + "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", + eventParm->eventData.nodeFailed.busNumber, + eventParm->eventData.nodeFailed.subBusNumber, + eventParm->eventData.nodeFailed.deviceId); break; case XmPciLpEvent_NodeRecovered: - printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", eventParm->eventData.nodeRecovered.busNumber, eventParm->eventData.nodeRecovered.subBusNumber, eventParm->eventData.nodeRecovered.deviceId); + printk(KERN_INFO + "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", + eventParm->eventData.nodeRecovered.busNumber, + eventParm->eventData.nodeRecovered.subBusNumber, + eventParm->eventData.nodeRecovered.deviceId); break; default: - printk(KERN_ERR "XmPciLpEvent.c: unrecognized event subtype 0x%x\n", - eventParm->hvLpEvent.xSubtype); + printk(KERN_ERR + "XmPciLpEvent.c: unrecognized event subtype 0x%x\n", + eventParm->hvLpEvent.xSubtype); break; - }; + } } @@ -145,18 +169,22 @@ static void intReceived(struct XmPciLpEv int XmPciLpEvent_init() { int xRc; - PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_init, Register Event type 0x%04X\n",HvLpEvent_Type_PciIo); - xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, &XmPciLpEvent_handler); + PPCDBG(PPCDBG_BUSWALK, + "XmPciLpEvent_init, Register Event type 0x%04X\n", + HvLpEvent_Type_PciIo); + + xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, + &XmPciLpEvent_handler); if (xRc == 0) { xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); - if (xRc != 0) { - printk(KERN_ERR "XmPciLpEvent.c: open event path failed with rc 0x%x\n", xRc); - } - } - else { - printk(KERN_ERR "XmPciLpEvent.c: register handler failed with rc 0x%x\n", xRc); - } - return xRc; + if (xRc != 0) + printk(KERN_ERR + "XmPciLpEvent.c: open event path failed with rc 0x%x\n", + xRc); + } else + printk(KERN_ERR + "XmPciLpEvent.c: register handler failed with rc 0x%x\n", + xRc); + return xRc; } - diff -puN arch/ppc64/Makefile~linus arch/ppc64/Makefile --- 25/arch/ppc64/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -15,15 +15,25 @@ KERNELLOAD := 0xc000000000000000 +HAS_BIARCH := $(shell if $(CC) -m64 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;) +ifeq ($(HAS_BIARCH),y) +AS := $(AS) -64 +LD := $(LD) -m elf64ppc +CC := $(CC) -m64 +endif + LDFLAGS := -m elf64ppc LDFLAGS_vmlinux := -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ - -mcpu=power4 - -have_zero_bss := $(shell if $(CC) -fno-zero-initialized-in-bss -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi) + -mtraceback=none -ifeq ($(have_zero_bss),y) -CFLAGS += -fno-zero-initialized-in-bss +HAS_POWER4 := $(shell if $(CC) -mcpu=power4 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi;) +ifeq ($(HAS_POWER4),y) +ifeq ($(CONFIG_POWER4_ONLY),y) +CFLAGS += -mcpu=power4 +else +CFLAGS += -mtune=power4 +endif endif head-y := arch/ppc64/kernel/head.o @@ -47,6 +57,8 @@ BOOTIMAGE := $(bootimage-y) install: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ +all: $(BOOTIMAGE) + archclean: $(Q)$(MAKE) $(clean)=$(boot) diff -puN -L arch/ppc64/mm/extable.c arch/ppc64/mm/extable.c~linus /dev/null --- 25/arch/ppc64/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,74 +0,0 @@ -/* - * arch/ppc64/mm/extable.c - * - * from arch/i386/mm/extable.c - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include -#include -#include - -extern struct exception_table_entry __start___ex_table[]; -extern struct exception_table_entry __stop___ex_table[]; - -/* - * The exception table needs to be sorted because we use the macros - * which put things into the exception table in a variety of segments - * as well as the init segment and the main kernel text segment. - * - * Also used for modules. - */ -void __init_or_module sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish) -{ - struct exception_table_entry el, *p, *q; - - /* insertion sort */ - for (p = start + 1; p < finish; ++p) { - /* start .. p-1 is sorted */ - if (p[0].insn < p[-1].insn) { - /* move element p down to its right place */ - el = *p; - q = p; - do { - /* el comes before q[-1], move q[-1] up one */ - q[0] = q[-1]; - --q; - } while (q > start && el.insn < q[-1].insn); - *q = el; - } - } -} - -void __init -sort_exception_table(void) -{ - sort_ex_table(__start___ex_table, __stop___ex_table); -} - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN /dev/null arch/ppc64/mm/hash_low.S --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/mm/hash_low.S 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,283 @@ +/* + * ppc64 MMU hashtable management routines + * + * (c) Copyright IBM Corp. 2003 + * + * Maintained by: Benjamin Herrenschmidt + * + * + * This file is covered by the GNU Public Licence v2 as + * described in the kernel's COPYING file. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .text + +/* + * Stackframe: + * + * +-> Back chain (SP + 256) + * | General register save area (SP + 112) + * | Parameter save area (SP + 48) + * | TOC save area (SP + 40) + * | link editor doubleword (SP + 32) + * | compiler doubleword (SP + 24) + * | LR save area (SP + 16) + * | CR save area (SP + 8) + * SP ---> +-- Back chain (SP + 0) + */ +#define STACKFRAMESIZE 256 + +/* Save parameters offsets */ +#define STK_PARM(i) (STACKFRAMESIZE + 48 + ((i)-3)*8) + +/* Save non-volatile offsets */ +#define STK_REG(i) (112 + ((i)-14)*8) + +/* + * _hash_page(unsigned long ea, unsigned long access, unsigned long vsid, + * pte_t *ptep, unsigned long trap, int local) + * + * Adds a page to the hash table. This is the non-LPAR version for now + */ + +_GLOBAL(__hash_page) + mflr r0 + std r0,16(r1) + stdu r1,-STACKFRAMESIZE(r1) + /* Save all params that we need after a function call */ + std r6,STK_PARM(r6)(r1) + std r8,STK_PARM(r8)(r1) + + /* Add _PAGE_PRESENT to access */ + ori r4,r4,_PAGE_PRESENT + + /* Save non-volatile registers. + * r31 will hold "old PTE" + * r30 is "new PTE" + * r29 is "va" + * r28 is a hash value + * r27 is hashtab mask (maybe dynamic patched instead ?) + */ + std r27,STK_REG(r27)(r1) + std r28,STK_REG(r28)(r1) + std r29,STK_REG(r29)(r1) + std r30,STK_REG(r30)(r1) + std r31,STK_REG(r31)(r1) + + /* Step 1: + * + * Check permissions, atomically mark the linux PTE busy + * and hashed. + */ +1: + ldarx r31,0,r6 + /* Check access rights (access & ~(pte_val(*ptep))) */ + andc. r0,r4,r31 + bne- htab_wrong_access + /* Check if PTE is busy */ + andi. r0,r31,_PAGE_BUSY + bne- 1b + /* Prepare new PTE value (turn access RW into DIRTY, then + * add BUSY,HASHPTE and ACCESSED) + */ + rlwinm r30,r4,5,24,24 /* _PAGE_RW -> _PAGE_DIRTY */ + or r30,r30,r31 + ori r30,r30,_PAGE_BUSY | _PAGE_ACCESSED | _PAGE_HASHPTE + /* Write the linux PTE atomically (setting busy) */ + stdcx. r30,0,r6 + bne- 1b + + + /* Step 2: + * + * Insert/Update the HPTE in the hash table. At this point, + * r4 (access) is re-useable, we use it for the new HPTE flags + */ + + /* Calc va and put it in r29 */ + rldicr r29,r5,28,63-28 + rldicl r3,r3,0,36 + or r29,r3,r29 + + /* Calculate hash value for primary slot and store it in r28 */ + rldicl r5,r5,0,25 /* vsid & 0x0000007fffffffff */ + rldicl r0,r3,64-12,48 /* (ea >> 12) & 0xffff */ + xor r28,r5,r0 + + /* Convert linux PTE bits into HW equivalents + */ + andi. r3,r30,0x1fa /* Get basic set of flags */ + rlwinm r0,r30,32-2+1,30,30 /* _PAGE_RW -> _PAGE_USER (r0) */ + rlwinm r4,r30,32-7+1,30,30 /* _PAGE_DIRTY -> _PAGE_USER (r4) */ + and r0,r0,r4 /* _PAGE_RW & _PAGE_DIRTY -> r0 bit 30 */ + andc r0,r30,r0 /* r0 = pte & ~r0 */ + rlwimi r3,r0,32-1,31,31 /* Insert result into PP lsb */ + + /* We eventually do the icache sync here (maybe inline that + * code rather than call a C function...) + */ +BEGIN_FTR_SECTION + mr r4,r30 + mr r5,r7 + bl .hash_page_do_lazy_icache +END_FTR_SECTION_IFSET(CPU_FTR_NOEXECUTE) + + /* At this point, r3 contains new PP bits, save them in + * place of "access" in the param area (sic) + */ + std r3,STK_PARM(r4)(r1) + + /* Get htab_hash_mask */ + ld r4,htab_data@got(2) + ld r27,16(r4) /* htab_data.htab_hash_mask -> r27 */ + + /* Check if we may already be in the hashtable, in this case, we + * go to out-of-line code to try to modify the HPTE + */ + andi. r0,r31,_PAGE_HASHPTE + bne htab_modify_pte + +htab_insert_pte: + /* Clear hpte bits in new pte (we also clear BUSY btw) and + * add _PAGE_HASHPTE + */ + lis r0,_PAGE_HPTEFLAGS@h + ori r0,r0,_PAGE_HPTEFLAGS@l + andc r30,r30,r0 + ori r30,r30,_PAGE_HASHPTE + + /* page number in r5 */ + rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + + /* Calculate primary group hash */ + and r0,r28,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r6,0 /* primary slot */ + li r8,0 /* not bolted and not large */ + li r9,0 +_GLOBAL(htab_call_hpte_insert1) + bl . /* Will be patched by htab_finish_init() */ + cmpi 0,r3,0 + bge htab_pte_insert_ok /* Insertion successful */ + cmpi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Now try secondary slot */ + ori r30,r30,_PAGE_SECONDARY + + /* page number in r5 */ + rldicl r5,r31,64-PTE_SHIFT,PTE_SHIFT + + /* Calculate secondary group hash */ + andc r0,r27,r28 + rldicr r3,r0,3,63-3 /* r0 = (~hash & mask) << 3 */ + + /* Call ppc_md.hpte_insert */ + ld r7,STK_PARM(r4)(r1) /* Retreive new pp bits */ + mr r4,r29 /* Retreive va */ + li r6,1 /* secondary slot */ + li r8,0 /* not bolted and not large */ + li r9,0 +_GLOBAL(htab_call_hpte_insert2) + bl . /* Will be patched by htab_finish_init() */ + cmpi 0,r3,0 + bge+ htab_pte_insert_ok /* Insertion successful */ + cmpi 0,r3,-2 /* Critical failure */ + beq- htab_pte_insert_failure + + /* Both are full, we need to evict something */ + mftb r0 + /* Pick a random group based on TB */ + andi. r0,r0,1 + mr r5,r28 + bne 2f + not r5,r5 +2: and r0,r5,r27 + rldicr r3,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + /* Call ppc_md.hpte_remove */ +_GLOBAL(htab_call_hpte_remove) + bl . /* Will be patched by htab_finish_init() */ + + /* Try all again */ + b htab_insert_pte + +htab_pte_insert_ok: + /* Insert slot number in PTE */ + rldimi r30,r3,12,63-14 + + /* Write out the PTE with a normal write + * (maybe add eieio may be good still ?) + */ +htab_write_out_pte: + ld r6,STK_PARM(r6)(r1) + std r30,0(r6) + li r3, 0 +bail: + ld r27,STK_REG(r27)(r1) + ld r28,STK_REG(r28)(r1) + ld r29,STK_REG(r29)(r1) + ld r30,STK_REG(r30)(r1) + ld r31,STK_REG(r31)(r1) + addi r1,r1,STACKFRAMESIZE + ld r0,16(r1) + mtlr r0 + blr + +htab_modify_pte: + /* Keep PP bits in r4 and slot idx from the PTE around in r3 */ + mr r4,r3 + rlwinm r3,r31,32-12,29,31 + + /* Secondary group ? if yes, get a inverted hash value */ + mr r5,r28 + andi. r0,r31,_PAGE_SECONDARY + beq 1f + not r5,r5 +1: + /* Calculate proper slot value for ppc_md.hpte_updatepp */ + and r0,r5,r27 + rldicr r0,r0,3,63-3 /* r0 = (hash & mask) << 3 */ + add r3,r0,r3 /* add slot idx */ + + /* Call ppc_md.hpte_updatepp */ + mr r5,r29 /* va */ + li r6,0 /* large is 0 */ + ld r7,STK_PARM(r8)(r1) /* get "local" param */ +_GLOBAL(htab_call_hpte_updatepp) + bl . /* Will be patched by htab_finish_init() */ + + /* if we failed because typically the HPTE wasn't really here + * we try an insertion. + */ + cmpi 0,r3,-1 + beq- htab_insert_pte + + /* Clear the BUSY bit and Write out the PTE */ + li r0,_PAGE_BUSY + andc r30,r30,r0 + b htab_write_out_pte + +htab_wrong_access: + /* Bail out clearing reservation */ + stdcx. r31,0,r6 + li r3,1 + b bail + +htab_pte_insert_failure: + b .htab_insert_failure + + diff -puN /dev/null arch/ppc64/mm/hash_utils.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/ppc64/mm/hash_utils.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,358 @@ +/* + * PowerPC64 port by Mike Corrigan and Dave Engebretsen + * {mikejc|engebret}@us.ibm.com + * + * Copyright (c) 2000 Mike Corrigan + * + * SMP scalability work: + * Copyright (C) 2001 Anton Blanchard , IBM + * + * Module name: htab.c + * + * Description: + * PowerPC Hashed Page Table functions + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + * Note: pte --> Linux PTE + * HPTE --> PowerPC Hashed Page Table Entry + * + * Execution context: + * htab_initialize is called with the MMU off (of course), but + * the kernel has been copied down to zero so it can directly + * reference global data. At this point it is very difficult + * to print debug info. + * + */ + +HTAB htab_data = {NULL, 0, 0, 0, 0}; + +extern unsigned long _SDR1; + +#define KB (1024) +#define MB (1024*KB) + +static inline void loop_forever(void) +{ + volatile unsigned long x = 1; + for(;x;x|=1) + ; +} + +#ifdef CONFIG_PPC_PSERIES +static inline void create_pte_mapping(unsigned long start, unsigned long end, + unsigned long mode, int large) +{ + unsigned long addr; + unsigned int step; + + if (large) + step = 16*MB; + else + step = 4*KB; + + for (addr = start; addr < end; addr += step) { + unsigned long vpn, hash, hpteg; + unsigned long vsid = get_kernel_vsid(addr); + unsigned long va = (vsid << 28) | (addr & 0xfffffff); + int ret; + + if (large) + vpn = va >> LARGE_PAGE_SHIFT; + else + vpn = va >> PAGE_SHIFT; + + hash = hpt_hash(vpn, large); + + hpteg = ((hash & htab_data.htab_hash_mask)*HPTES_PER_GROUP); + + if (systemcfg->platform == PLATFORM_PSERIES_LPAR) + ret = pSeries_lpar_hpte_insert(hpteg, va, + (unsigned long)__v2a(addr) >> PAGE_SHIFT, + 0, mode, 1, large); + else + ret = pSeries_hpte_insert(hpteg, va, + (unsigned long)__v2a(addr) >> PAGE_SHIFT, + 0, mode, 1, large); + + if (ret == -1) { + ppc64_terminate_msg(0x20, "create_pte_mapping"); + loop_forever(); + } + } +} + +void __init htab_initialize(void) +{ + unsigned long table, htab_size_bytes; + unsigned long pteg_count; + unsigned long mode_rw; + + /* + * Calculate the required size of the htab. We want the number of + * PTEGs to equal one half the number of real pages. + */ + htab_size_bytes = 1UL << naca->pftSize; + pteg_count = htab_size_bytes >> 7; + + /* For debug, make the HTAB 1/8 as big as it normally would be. */ + ifppcdebug(PPCDBG_HTABSIZE) { + pteg_count >>= 3; + htab_size_bytes = pteg_count << 7; + } + + htab_data.htab_num_ptegs = pteg_count; + htab_data.htab_hash_mask = pteg_count - 1; + + if (systemcfg->platform == PLATFORM_PSERIES) { + /* Find storage for the HPT. Must be contiguous in + * the absolute address space. + */ + table = lmb_alloc(htab_size_bytes, htab_size_bytes); + if ( !table ) { + ppc64_terminate_msg(0x20, "hpt space"); + loop_forever(); + } + htab_data.htab = (HPTE *)__a2v(table); + + /* htab absolute addr + encoded htabsize */ + _SDR1 = table + __ilog2(pteg_count) - 11; + + /* Initialize the HPT with no entries */ + memset((void *)table, 0, htab_size_bytes); + } else { + /* Using a hypervisor which owns the htab */ + htab_data.htab = NULL; + _SDR1 = 0; + } + + mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX; + + /* XXX we currently map kernel text rw, should fix this */ + if ((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) + && systemcfg->physicalMemorySize > 256*MB) { + create_pte_mapping((unsigned long)KERNELBASE, + KERNELBASE + 256*MB, mode_rw, 0); + create_pte_mapping((unsigned long)KERNELBASE + 256*MB, + KERNELBASE + (systemcfg->physicalMemorySize), + mode_rw, 1); + } else { + create_pte_mapping((unsigned long)KERNELBASE, + KERNELBASE+(systemcfg->physicalMemorySize), + mode_rw, 0); + } +} +#undef KB +#undef MB +#endif + +/* + * Called by asm hashtable.S for doing lazy icache flush + */ +unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap) +{ + struct page *page; + +#define PPC64_HWNOEXEC (1 << 2) + + if (!pfn_valid(pte_pfn(pte))) + return pp; + + page = pte_page(pte); + + /* page is dirty */ + if (!test_bit(PG_arch_1, &page->flags) && !PageReserved(page)) { + if (trap == 0x400) { + __flush_dcache_icache(page_address(page)); + set_bit(PG_arch_1, &page->flags); + } else + pp |= PPC64_HWNOEXEC; + } + return pp; +} + +/* + * Called by asm hashtable.S in case of critical insert failure + */ +void htab_insert_failure(void) +{ + panic("hash_page: pte_insert failed\n"); +} + +int hash_page(unsigned long ea, unsigned long access, unsigned long trap) +{ + void *pgdir; + unsigned long vsid; + struct mm_struct *mm; + pte_t *ptep; + int ret; + int user_region = 0; + int local = 0; + cpumask_t tmp; + + /* Check for invalid addresses. */ + if (!IS_VALID_EA(ea)) + return 1; + + switch (REGION_ID(ea)) { + case USER_REGION_ID: + user_region = 1; + mm = current->mm; + if (mm == NULL) + return 1; + + vsid = get_vsid(mm->context, ea); + break; + case IO_REGION_ID: + mm = &ioremap_mm; + vsid = get_kernel_vsid(ea); + break; + case VMALLOC_REGION_ID: + mm = &init_mm; + vsid = get_kernel_vsid(ea); + break; +#if 0 + case EEH_REGION_ID: + /* + * Should only be hit if there is an access to MMIO space + * which is protected by EEH. + * Send the problem up to do_page_fault + */ + case KERNEL_REGION_ID: + /* + * Should never get here - entire 0xC0... region is bolted. + * Send the problem up to do_page_fault + */ +#endif + default: + /* Not a valid range + * Send the problem up to do_page_fault + */ + return 1; + break; + } + + pgdir = mm->pgd; + + if (pgdir == NULL) + return 1; + + tmp = cpumask_of_cpu(smp_processor_id()); + if (user_region && cpus_equal(mm->cpu_vm_mask, tmp)) + local = 1; + + /* Is this a huge page ? */ + if (unlikely(in_hugepage_area(mm->context, ea))) + ret = hash_huge_page(mm, access, ea, vsid, local); + else { + ptep = find_linux_pte(pgdir, ea); + if (ptep == NULL) + return 1; + ret = __hash_page(ea, access, vsid, ptep, trap, local); + } + + + return ret; +} + +void flush_hash_page(unsigned long context, unsigned long ea, pte_t pte, + int local) +{ + unsigned long vsid, vpn, va, hash, secondary, slot; + + /* XXX fix for large ptes */ + unsigned long large = 0; + + if ((ea >= USER_START) && (ea <= USER_END)) + vsid = get_vsid(context, ea); + else + vsid = get_kernel_vsid(ea); + + va = (vsid << 28) | (ea & 0x0fffffff); + if (large) + vpn = va >> LARGE_PAGE_SHIFT; + else + vpn = va >> PAGE_SHIFT; + hash = hpt_hash(vpn, large); + secondary = (pte_val(pte) & _PAGE_SECONDARY) >> 15; + if (secondary) + hash = ~hash; + slot = (hash & htab_data.htab_hash_mask) * HPTES_PER_GROUP; + slot += (pte_val(pte) & _PAGE_GROUP_IX) >> 12; + + ppc_md.hpte_invalidate(slot, va, large, local); +} + +void flush_hash_range(unsigned long context, unsigned long number, int local) +{ + if (ppc_md.flush_hash_range) { + ppc_md.flush_hash_range(context, number, local); + } else { + int i; + struct ppc64_tlb_batch *batch = + &ppc64_tlb_batch[smp_processor_id()]; + + for (i = 0; i < number; i++) + flush_hash_page(context, batch->addr[i], batch->pte[i], + local); + } +} + +static inline void make_bl(unsigned int *insn_addr, void *func) +{ + unsigned long funcp = *((unsigned long *)func); + int offset = funcp - (unsigned long)insn_addr; + + *insn_addr = (unsigned int)(0x48000001 | (offset & 0x03fffffc)); + flush_icache_range((unsigned long)insn_addr, 4+ + (unsigned long)insn_addr); +} + +void __init htab_finish_init(void) +{ + extern unsigned int *htab_call_hpte_insert1; + extern unsigned int *htab_call_hpte_insert2; + extern unsigned int *htab_call_hpte_remove; + extern unsigned int *htab_call_hpte_updatepp; + + make_bl(htab_call_hpte_insert1, ppc_md.hpte_insert); + make_bl(htab_call_hpte_insert2, ppc_md.hpte_insert); + make_bl(htab_call_hpte_remove, ppc_md.hpte_remove); + make_bl(htab_call_hpte_updatepp, ppc_md.hpte_updatepp); +} diff -puN arch/ppc64/mm/hugetlbpage.c~linus arch/ppc64/mm/hugetlbpage.c --- 25/arch/ppc64/mm/hugetlbpage.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/hugetlbpage.c 2004-01-19 22:17:21.000000000 -0800 @@ -652,13 +652,9 @@ int hash_huge_page(struct mm_struct *mm, unsigned long va, vpn; int is_write; hugepte_t old_pte, new_pte; - unsigned long hpteflags, prpn; + unsigned long hpteflags, prpn, flags; long slot; - /* Is this for us? */ - if (!in_hugepage_area(mm->context, ea)) - return -1; - ea &= ~(HPAGE_SIZE-1); /* We have to find the first hugepte in the batch, since @@ -698,6 +694,8 @@ int hash_huge_page(struct mm_struct *mm, * page is currently not DIRTY. */ + spin_lock_irqsave(&mm->page_table_lock, flags); + old_pte = *ptep; new_pte = old_pte; @@ -769,6 +767,8 @@ repeat: *ptep = new_pte; } + spin_unlock_irqrestore(&mm->page_table_lock, flags); + return 0; } diff -puN arch/ppc64/mm/imalloc.c~linus arch/ppc64/mm/imalloc.c --- 25/arch/ppc64/mm/imalloc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/imalloc.c 2004-01-19 22:17:21.000000000 -0800 @@ -18,55 +18,264 @@ rwlock_t imlist_lock = RW_LOCK_UNLOCKED; struct vm_struct * imlist = NULL; -struct vm_struct *get_im_area(unsigned long size) +static int get_free_im_addr(unsigned long size, unsigned long *im_addr) { unsigned long addr; - struct vm_struct **p, *tmp, *area; - - area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); - if (!area) - return NULL; + struct vm_struct **p, *tmp; + addr = IMALLOC_START; - write_lock(&imlist_lock); for (p = &imlist; (tmp = *p) ; p = &tmp->next) { if (size + addr < (unsigned long) tmp->addr) break; - addr = tmp->size + (unsigned long) tmp->addr; - if (addr > IMALLOC_END-size) { - write_unlock(&imlist_lock); - kfree(area); + if ((unsigned long)tmp->addr >= IMALLOC_START) + addr = tmp->size + (unsigned long) tmp->addr; + if (addr > IMALLOC_END-size) + return 1; + } + *im_addr = addr; + + return 0; +} + +/* Return whether the region described by v_addr and size overlaps + * the region described by vm. Overlapping regions meet the + * following conditions: + * 1) The regions share some part of the address space + * 2) The regions aren't identical + * 3) The first region is not a subset of the second + */ +static inline int im_region_overlaps(unsigned long v_addr, unsigned long size, + struct vm_struct *vm) +{ + return (v_addr + size > (unsigned long) vm->addr + vm->size && + v_addr < (unsigned long) vm->addr + vm->size) || + (v_addr < (unsigned long) vm->addr && + v_addr + size > (unsigned long) vm->addr); +} + +/* Return whether the region described by v_addr and size is a subset + * of the region described by vm + */ +static inline int im_region_is_subset(unsigned long v_addr, unsigned long size, + struct vm_struct *vm) +{ + return (int) (v_addr >= (unsigned long) vm->addr && + v_addr < (unsigned long) vm->addr + vm->size && + size < vm->size); +} + +/* Determine imalloc status of region described by v_addr and size. + * Can return one of the following: + * IM_REGION_UNUSED - Entire region is unallocated in imalloc space. + * IM_REGION_SUBSET - Region is a subset of a region that is already + * allocated in imalloc space. + * vm will be assigned to a ptr to the parent region. + * IM_REGION_EXISTS - Exact region already allocated in imalloc space. + * vm will be assigned to a ptr to the existing imlist + * member. + * IM_REGION_OVERLAPS - A portion of the region is already allocated in + * imalloc space. + */ +static int im_region_status(unsigned long v_addr, unsigned long size, + struct vm_struct **vm) +{ + struct vm_struct *tmp; + + for (tmp = imlist; tmp; tmp = tmp->next) + if (v_addr < (unsigned long) tmp->addr + tmp->size) + break; + + if (tmp) { + if (im_region_overlaps(v_addr, size, tmp)) + return IM_REGION_OVERLAP; + + *vm = tmp; + if (im_region_is_subset(v_addr, size, tmp)) + return IM_REGION_SUBSET; + else if (v_addr == (unsigned long) tmp->addr && + size == tmp->size) + return IM_REGION_EXISTS; + } + + *vm = NULL; + return IM_REGION_UNUSED; +} + +static struct vm_struct * split_im_region(unsigned long v_addr, + unsigned long size, struct vm_struct *parent) +{ + struct vm_struct *vm1 = NULL; + struct vm_struct *vm2 = NULL; + struct vm_struct *new_vm = NULL; + + vm1 = (struct vm_struct *) kmalloc(sizeof(*vm1), GFP_KERNEL); + if (vm1 == NULL) { + printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); + return NULL; + } + + if (v_addr == (unsigned long) parent->addr) { + /* Use existing parent vm_struct to represent child, allocate + * new one for the remainder of parent range + */ + vm1->size = parent->size - size; + vm1->addr = (void *) (v_addr + size); + vm1->next = parent->next; + + parent->size = size; + parent->next = vm1; + new_vm = parent; + } else if (v_addr + size == (unsigned long) parent->addr + + parent->size) { + /* Allocate new vm_struct to represent child, use existing + * parent one for remainder of parent range + */ + vm1->size = size; + vm1->addr = (void *) v_addr; + vm1->next = parent->next; + new_vm = vm1; + + parent->size -= size; + parent->next = vm1; + } else { + /* Allocate two new vm_structs for the new child and + * uppermost remainder, and use existing parent one for the + * lower remainder of parent range + */ + vm2 = (struct vm_struct *) kmalloc(sizeof(*vm2), GFP_KERNEL); + if (vm2 == NULL) { + printk(KERN_ERR "%s() out of memory\n", __FUNCTION__); + kfree(vm1); return NULL; } + + vm1->size = size; + vm1->addr = (void *) v_addr; + vm1->next = vm2; + new_vm = vm1; + + vm2->size = ((unsigned long) parent->addr + parent->size) - + (v_addr + size); + vm2->addr = (void *) v_addr + size; + vm2->next = parent->next; + + parent->size = v_addr - (unsigned long) parent->addr; + parent->next = vm1; } + + return new_vm; +} + +static struct vm_struct * __add_new_im_area(unsigned long req_addr, + unsigned long size) +{ + struct vm_struct **p, *tmp, *area; + + for (p = &imlist; (tmp = *p) ; p = &tmp->next) { + if (req_addr + size <= (unsigned long)tmp->addr) + break; + } + + area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; area->flags = 0; - area->addr = (void *)addr; + area->addr = (void *)req_addr; area->size = size; area->next = *p; *p = area; + + return area; +} + +static struct vm_struct * __im_get_area(unsigned long req_addr, + unsigned long size, + int criteria) +{ + struct vm_struct *tmp; + int status; + + status = im_region_status(req_addr, size, &tmp); + if ((criteria & status) == 0) { + return NULL; + } + + switch (status) { + case IM_REGION_UNUSED: + tmp = __add_new_im_area(req_addr, size); + break; + case IM_REGION_SUBSET: + tmp = split_im_region(req_addr, size, tmp); + break; + case IM_REGION_EXISTS: + break; + default: + printk(KERN_ERR "%s() unexpected imalloc region status\n", + __FUNCTION__); + tmp = NULL; + } + + return tmp; +} + +struct vm_struct * im_get_free_area(unsigned long size) +{ + struct vm_struct *area; + unsigned long addr; + + write_lock(&imlist_lock); + if (get_free_im_addr(size, &addr)) { + printk(KERN_ERR "%s() cannot obtain addr for size 0x%lx\n", + __FUNCTION__, size); + area = NULL; + goto next_im_done; + } + + area = __im_get_area(addr, size, IM_REGION_UNUSED); + if (area == NULL) { + printk(KERN_ERR + "%s() cannot obtain area for addr 0x%lx size 0x%lx\n", + __FUNCTION__, addr, size); + } +next_im_done: write_unlock(&imlist_lock); return area; } -void ifree(void * addr) +struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size, + int criteria) +{ + struct vm_struct *area; + + write_lock(&imlist_lock); + area = __im_get_area(v_addr, size, criteria); + write_unlock(&imlist_lock); + return area; +} + +unsigned long im_free(void * addr) { struct vm_struct **p, *tmp; + unsigned long ret_size = 0; if (!addr) - return; + return ret_size; if ((PAGE_SIZE-1) & (unsigned long) addr) { - printk(KERN_ERR "Trying to ifree() bad address (%p)\n", addr); - return; + printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__, addr); + return ret_size; } write_lock(&imlist_lock); for (p = &imlist ; (tmp = *p) ; p = &tmp->next) { if (tmp->addr == addr) { + ret_size = tmp->size; *p = tmp->next; kfree(tmp); write_unlock(&imlist_lock); - return; + return ret_size; } } write_unlock(&imlist_lock); - printk(KERN_ERR "Trying to ifree() nonexistent area (%p)\n", addr); + printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__, + addr); + return ret_size; } - diff -puN arch/ppc64/mm/init.c~linus arch/ppc64/mm/init.c --- 25/arch/ppc64/mm/init.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/init.c 2004-01-19 22:17:21.000000000 -0800 @@ -67,6 +67,7 @@ struct mmu_context_queue_t mmu_context_queue; int mem_init_done; unsigned long ioremap_bot = IMALLOC_BASE; +static unsigned long phbs_io_bot = PHBS_IO_BASE; extern pgd_t swapper_pg_dir[]; extern struct task_struct *current_set[NR_CPUS]; @@ -74,6 +75,9 @@ extern struct task_struct *current_set[N extern pgd_t ioremap_dir[]; pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir; +static void * __ioremap_com(unsigned long addr, unsigned long pa, + unsigned long ea, unsigned long size, + unsigned long flags); static void map_io_page(unsigned long va, unsigned long pa, int flags); unsigned long klimit = (unsigned long)_end; @@ -90,6 +94,52 @@ unsigned long __max_memory; * include/asm-ppc64/tlb.h file -- tgall */ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +DEFINE_PER_CPU(struct pte_freelist_batch *, pte_freelist_cur); +unsigned long pte_freelist_forced_free; + +static void pte_free_smp_sync(void *arg) +{ + /* Do nothing, just ensure we sync with all CPUs */ +} + +/* This is only called when we are critically out of memory + * (and fail to get a page in pte_free_tlb). + */ +void pte_free_now(struct page *ptepage) +{ + pte_freelist_forced_free++; + + smp_call_function(pte_free_smp_sync, NULL, 0, 1); + + pte_free(ptepage); +} + +static void pte_free_rcu_callback(void *arg) +{ + struct pte_freelist_batch *batch = arg; + unsigned int i; + + for (i = 0; i < batch->index; i++) + pte_free(batch->pages[i]); + free_page((unsigned long)batch); +} + +void pte_free_submit(struct pte_freelist_batch *batch) +{ + INIT_RCU_HEAD(&batch->rcu); + call_rcu(&batch->rcu, pte_free_rcu_callback, batch); +} + +void pte_free_finish(void) +{ + /* This is safe as we are holding page_table_lock */ + struct pte_freelist_batch **batchp = &__get_cpu_var(pte_freelist_cur); + + if (*batchp == NULL) + return; + pte_free_submit(*batchp); + *batchp = NULL; +} void show_mem(void) { @@ -133,12 +183,10 @@ ioremap(unsigned long addr, unsigned lon #endif } -extern struct vm_struct * get_im_area( unsigned long size ); - void * __ioremap(unsigned long addr, unsigned long size, unsigned long flags) { - unsigned long pa, ea, i; + unsigned long pa, ea; /* * Choose an address to map it to. @@ -157,26 +205,163 @@ __ioremap(unsigned long addr, unsigned l if (mem_init_done) { struct vm_struct *area; - area = get_im_area(size); - if (area == 0) + area = im_get_free_area(size); + if (area == NULL) return NULL; ea = (unsigned long)(area->addr); - } - else { + } else { ea = ioremap_bot; ioremap_bot += size; } - if ((flags & _PAGE_PRESENT) == 0) - flags |= pgprot_val(PAGE_KERNEL); - if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) - flags |= _PAGE_GUARDED; + return __ioremap_com(addr, pa, ea, size, flags); +} - for (i = 0; i < size; i += PAGE_SIZE) { - map_io_page(ea+i, pa+i, flags); +#define IS_PAGE_ALIGNED(_val) ((_val) == ((_val) & PAGE_MASK)) + +int __ioremap_explicit(unsigned long pa, unsigned long ea, + unsigned long size, unsigned long flags) +{ + struct vm_struct *area; + + /* For now, require page-aligned values for pa, ea, and size */ + if (!IS_PAGE_ALIGNED(pa) || !IS_PAGE_ALIGNED(ea) || + !IS_PAGE_ALIGNED(size)) { + printk(KERN_ERR "unaligned value in %s\n", __FUNCTION__); + return 1; + } + + if (!mem_init_done) { + /* Two things to consider in this case: + * 1) No records will be kept (imalloc, etc) that the region + * has been remapped + * 2) It won't be easy to iounmap() the region later (because + * of 1) + */ + ; + } else { + area = im_get_area(ea, size, IM_REGION_UNUSED|IM_REGION_SUBSET); + if (area == NULL) { + printk(KERN_ERR "could not obtain imalloc area for ea 0x%lx\n", ea); + return 1; + } + if (ea != (unsigned long) area->addr) { + printk(KERN_ERR "unexpected addr return from im_get_area\n"); + return 1; + } + } + + if (__ioremap_com(pa, pa, ea, size, flags) != (void *) ea) { + printk(KERN_ERR "__ioremap_com() returned unexpected addr\n"); + return 1; } - return (void *) (ea + (addr & ~PAGE_MASK)); + return 0; +} + +static void unmap_im_area_pte(pmd_t *pmd, unsigned long address, + unsigned long size) +{ + unsigned long end; + pte_t *pte; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + + pte = pte_offset_kernel(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + + do { + pte_t page; + page = ptep_get_and_clear(pte); + address += PAGE_SIZE; + pte++; + if (pte_none(page)) + continue; + if (pte_present(page)) + continue; + printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n"); + } while (address < end); +} + +static void unmap_im_area_pmd(pgd_t *dir, unsigned long address, + unsigned long size) +{ + unsigned long end; + pmd_t *pmd; + + if (pgd_none(*dir)) + return; + if (pgd_bad(*dir)) { + pgd_ERROR(*dir); + pgd_clear(dir); + return; + } + + pmd = pmd_offset(dir, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + + do { + unmap_im_area_pte(pmd, address, end - address); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +/* + * Unmap an IO region and remove it from imalloc'd list. + * Access to IO memory should be serialized by driver. + * This code is modeled after vmalloc code - unmap_vm_area() + * + * XXX what about calls before mem_init_done (ie python_countermeasures()) + */ +void pSeries_iounmap(void *addr) +{ + unsigned long address, start, end, size; + struct mm_struct *mm; + pgd_t *dir; + + if (!mem_init_done) { + return; + } + + /* addr could be in EEH or IO region, map it to IO region regardless. + */ + addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK); + + if ((size = im_free(addr)) == 0) { + return; + } + + address = (unsigned long)addr; + start = address; + end = address + size; + + mm = &ioremap_mm; + spin_lock(&mm->page_table_lock); + + dir = pgd_offset_i(address); + flush_cache_all(); + do { + unmap_im_area_pmd(dir, address, end - address); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + __flush_tlb_range(mm, start, end); + + spin_unlock(&mm->page_table_lock); + return; } void iounmap(void *addr) @@ -186,10 +371,52 @@ void iounmap(void *addr) return; #else /* DRENG / PPPBBB todo */ - return; + return pSeries_iounmap(addr); #endif } +int iounmap_explicit(void *addr, unsigned long size) +{ + struct vm_struct *area; + + /* addr could be in EEH or IO region, map it to IO region regardless. + */ + addr = (void *) (IO_TOKEN_TO_ADDR(addr) & PAGE_MASK); + + /* Verify that the region either exists or is a subset of an existing + * region. In the latter case, split the parent region to create + * the exact region + */ + area = im_get_area((unsigned long) addr, size, + IM_REGION_EXISTS | IM_REGION_SUBSET); + if (area == NULL) { + printk(KERN_ERR "%s() cannot unmap nonexistant range 0x%lx\n", + __FUNCTION__, (unsigned long) addr); + return 1; + } + + iounmap(area->addr); + return 0; +} + +static void * __ioremap_com(unsigned long addr, unsigned long pa, + unsigned long ea, unsigned long size, + unsigned long flags) +{ + unsigned long i; + + if ((flags & _PAGE_PRESENT) == 0) + flags |= pgprot_val(PAGE_KERNEL); + if (flags & (_PAGE_NO_CACHE | _PAGE_WRITETHRU)) + flags |= _PAGE_GUARDED; + + for (i = 0; i < size; i += PAGE_SIZE) { + map_io_page(ea+i, pa+i, flags); + } + + return (void *) (ea + (addr & ~PAGE_MASK)); +} + /* * map_io_page currently only called by __ioremap * map_io_page adds an entry to the ioremap page table @@ -674,10 +901,6 @@ void flush_icache_user_range(struct vm_a flush_icache_range(maddr, maddr + len); } -extern pte_t *find_linux_pte(pgd_t *pgdir, unsigned long ea); -int __hash_page(unsigned long ea, unsigned long access, unsigned long vsid, - pte_t *ptep, unsigned long trap, int local); - /* * This is called at the end of handling a user page fault, when the * fault has been handled by updating a PTE in the linux page tables. @@ -717,6 +940,9 @@ void update_mmu_cache(struct vm_area_str return; ptep = find_linux_pte(pgdir, ea); + if (!ptep) + return; + vsid = get_vsid(vma->vm_mm->context, ea); tmp = cpumask_of_cpu(smp_processor_id()); @@ -727,6 +953,19 @@ void update_mmu_cache(struct vm_area_str 0x300, local); } +void * reserve_phb_iospace(unsigned long size) +{ + void *virt_addr; + + if (phbs_io_bot >= IMALLOC_BASE) + panic("reserve_phb_iospace(): phb io space overflow\n"); + + virt_addr = (void *) phbs_io_bot; + phbs_io_bot += size; + + return virt_addr; +} + kmem_cache_t *zero_cache; static void zero_ctor(void *pte, kmem_cache_t *cache, unsigned long flags) diff -puN arch/ppc64/mm/Makefile~linus arch/ppc64/mm/Makefile --- 25/arch/ppc64/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -4,6 +4,6 @@ EXTRA_CFLAGS += -mno-minimal-toc -obj-y := fault.o init.o extable.o imalloc.o +obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o obj-$(CONFIG_DISCONTIGMEM) += numa.o obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o diff -puN arch/ppc64/mm/numa.c~linus arch/ppc64/mm/numa.c --- 25/arch/ppc64/mm/numa.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/mm/numa.c 2004-01-19 22:17:21.000000000 -0800 @@ -46,29 +46,29 @@ static inline void map_cpu_to_node(int c static int __init parse_numa_properties(void) { - struct device_node *cpu; - struct device_node *memory; + struct device_node *cpu = NULL; + struct device_node *memory = NULL; int *cpu_associativity; int *memory_associativity; int depth; int max_domain = 0; - cpu = find_type_devices("cpu"); + cpu = of_find_node_by_type(NULL, "cpu"); if (!cpu) - return -1; + goto err; - memory = find_type_devices("memory"); + memory = of_find_node_by_type(NULL, "memory"); if (!memory) - return -1; + goto err; cpu_associativity = (int *)get_property(cpu, "ibm,associativity", NULL); if (!cpu_associativity) - return -1; + goto err; memory_associativity = (int *)get_property(memory, "ibm,associativity", NULL); if (!memory_associativity) - return -1; + goto err; /* find common depth */ if (cpu_associativity[0] < memory_associativity[0]) @@ -76,7 +76,7 @@ static int __init parse_numa_properties( else depth = memory_associativity[0]; - for (cpu = find_type_devices("cpu"); cpu; cpu = cpu->next) { + for (; cpu; cpu = of_find_node_by_type(cpu, "cpu")) { int *tmp; int cpu_nr, numa_domain; @@ -106,9 +106,8 @@ static int __init parse_numa_properties( map_cpu_to_node(cpu_nr, numa_domain); } - for (memory = find_type_devices("memory"); memory; - memory = memory->next) { - int *tmp1, *tmp2; + for (; memory; memory = of_find_node_by_type(memory, "memory")) { + unsigned int *tmp1, *tmp2; unsigned long i; unsigned long start = 0; unsigned long size = 0; @@ -196,6 +195,10 @@ new_range: numnodes = max_domain + 1; return 0; +err: + of_node_put(cpu); + of_node_put(memory); + return -1; } void setup_nonnuma(void) diff -puN arch/ppc64/xmon/xmon.c~linus arch/ppc64/xmon/xmon.c --- 25/arch/ppc64/xmon/xmon.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc64/xmon/xmon.c 2004-01-19 22:17:21.000000000 -0800 @@ -37,9 +37,10 @@ #define skipbl xmon_skipbl #ifdef CONFIG_SMP -unsigned long cpus_in_xmon = 0; +volatile unsigned long cpus_in_xmon = 0; static unsigned long got_xmon = 0; static volatile int take_xmon = -1; +static volatile int leaving_xmon = 0; #endif /* CONFIG_SMP */ static unsigned long adrs; @@ -162,7 +163,6 @@ Commands:\n\ mz zero a block of memory\n\ mx translation information for an effective address\n\ mi show information about memory allocation\n\ - M print System.map\n\ p show the task list\n\ r print registers\n\ s single step\n\ @@ -227,7 +227,7 @@ void xmon(struct pt_regs *excp) { struct pt_regs regs; - int cmd; + int cmd = 0; unsigned long msr; if (excp == NULL) { @@ -285,9 +285,15 @@ xmon(struct pt_regs *excp) xmon_regs[smp_processor_id()] = excp; excprint(excp); #ifdef CONFIG_SMP - if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) + leaving_xmon = 0; + /* possible race condition here if a CPU is held up and gets + * here while we are exiting */ + if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon)) { + /* xmon probably caused an exception itself */ + printf("We are already in xmon\n"); for (;;) ; + } while (test_and_set_bit(0, &got_xmon)) { if (take_xmon == smp_processor_id()) { take_xmon = -1; @@ -304,6 +310,9 @@ xmon(struct pt_regs *excp) if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; excp->msr |= MSR_SE; +#ifdef CONFIG_SMP + take_xmon = smp_processor_id(); +#endif } else if (at_breakpoint(excp->nip)) { xmon_trace[smp_processor_id()] = BRSTEP; excp->msr |= MSR_SE; @@ -313,7 +322,9 @@ xmon(struct pt_regs *excp) } xmon_regs[smp_processor_id()] = 0; #ifdef CONFIG_SMP - clear_bit(0, &got_xmon); + leaving_xmon = 1; + if (cmd != 's') + clear_bit(0, &got_xmon); clear_bit(smp_processor_id(), &cpus_in_xmon); #endif /* CONFIG_SMP */ set_msrd(msr); /* restore interrupt enable */ @@ -421,8 +432,6 @@ insert_bpts() int i; struct bpt *bp; - if (systemcfg->platform != PLATFORM_PSERIES) - return; bp = bpts; for (i = 0; i < NBPTS; ++i, ++bp) { if (!bp->enabled) @@ -450,9 +459,6 @@ remove_bpts() struct bpt *bp; unsigned instr; - if (systemcfg->platform != PLATFORM_PSERIES) - return; - if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR)) set_dabr(0); if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR)) @@ -478,11 +484,15 @@ static char *last_cmd; static int cmds(struct pt_regs *excp) { - int cmd; + int cmd = 0; last_cmd = NULL; for(;;) { #ifdef CONFIG_SMP + /* Need to check if we should take any commands on + this CPU. */ + if (leaving_xmon) + return cmd; printf("%d:", smp_processor_id()); #endif /* CONFIG_SMP */ printf("mon> "); @@ -832,6 +842,12 @@ bpt_cmds(void) } break; } + + if (!(systemcfg->platform & PLATFORM_PSERIES)) { + printf("Not supported for this platform\n"); + break; + } + bp = at_breakpoint(a); if (bp == 0) { for (bp = bpts; bp < &bpts[NBPTS]; ++bp) diff -puN arch/ppc/boot/prep/head.S~linus arch/ppc/boot/prep/head.S --- 25/arch/ppc/boot/prep/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/boot/prep/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -35,9 +35,28 @@ start_: mr r11,r3 /* Save pointer to residual/board data */ - /* Establish default MSR value */ - li r3,MSR_IP|MSR_FP - mtmsr r3 +/* + * Save the OF pointer to r25, but only if the entry point is in a sane + * location; if not we store 0. If there is no entry point, or it is + * invalid, we establish the default MSR value immediately. Otherwise, + * we defer doing that, to allow OF functions to be called, until we + * begin uncompressing the kernel. + */ + lis r3,0x0fff /* r3 = 0x0fffffff */ + ori r3,r3,0xffff + + subc r3,r3,r5 /* r3 = (r5 <= r3) ? ~0 : 0 */ + subfe r3,r3,r3 + nand r3,r3,r3 + + and. r5,r5,r3 /* r5 will be cleared if (r5 > r3) */ + bne+ haveOF + + li r3,MSR_IP|MSR_FP /* Not OF: set MSR immediately */ + mtmsr r3 + isync +haveOF: + mr r25,r5 /* compute the size of the whole image in words. */ lis r4,start@h @@ -111,6 +130,7 @@ start_ldr: mr r4,r7 /* Program length */ mr r5,r6 /* Checksum */ mr r6,r11 /* Residual data */ + mr r7,r25 /* Validated OFW interface */ bl decompress_kernel /* diff -puN arch/ppc/boot/prep/Makefile~linus arch/ppc/boot/prep/Makefile --- 25/arch/ppc/boot/prep/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/boot/prep/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -27,9 +27,10 @@ utils := $(boot)/utils bootlib := $(boot)/lib images := $(boot)/images simple := $(boot)/simple +of1275 := $(boot)/of1275 OBJCOPYFLAGS := -O elf32-powerpc -LIBS := $(common)/lib.a $(bootlib)/lib.a +LIBS := $(common)/lib.a $(bootlib)/lib.a $(of1275)/lib.a targets := $(boot-y) dummy.o ../simple/legacy.o OBJS := $(addprefix $(obj)/,$(boot-y)) $(simple)/legacy.o diff -puN arch/ppc/boot/prep/misc.c~linus arch/ppc/boot/prep/misc.c --- 25/arch/ppc/boot/prep/misc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/boot/prep/misc.c 2004-01-19 22:17:21.000000000 -0800 @@ -19,7 +19,7 @@ #include #include #include - +#include "of1275.h" #include "nonstdio.h" #include "zlib.h" @@ -114,17 +114,19 @@ scroll(void) unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, - RESIDUAL *residual) + RESIDUAL *residual, void *OFW_interface) { int timer = 0; extern unsigned long start; char *cp, ch; unsigned long TotalMemory; - unsigned char board_type; - unsigned char base_mod; int start_multi = 0; unsigned int pci_viddid, pci_did, tulip_pci_base, tulip_base; + /* If we have Open Firmware, initialise it immediately */ + if (OFW_interface) + ofinit(OFW_interface); + serial_fixups(); #if defined(CONFIG_SERIAL_8250_CONSOLE) com_port = serial_init(0, NULL); @@ -163,7 +165,8 @@ decompress_kernel(unsigned long load_add /* Is this Motorola PPCBug? */ if ((1 & residual->VitalProductData.FirmwareSupports) && (1 == residual->VitalProductData.FirmwareSupplier)) { - board_type = inb(0x800) & 0xF0; + unsigned char base_mod; + unsigned char board_type = inb(0x800) & 0xF0; /* * Reset the onboard 21x4x Ethernet @@ -229,8 +232,31 @@ decompress_kernel(unsigned long load_add /* If it's not, see if we have anything in the residual data. */ else if (residual && residual->TotalMemory) TotalMemory = residual->TotalMemory; - /* Fall back to hard-coding 32MB. */ - else + else if (OFW_interface) { + /* + * This is a 'best guess' check. We want to make sure + * we don't try this on a PReP box without OF + * -- Cort + */ + while (OFW_interface) + { + phandle dev_handle; + int mem_info[2]; + + /* get handle to memory description */ + if (!(dev_handle = finddevice("/memory@0"))) + break; + + /* get the info */ + if (getprop(dev_handle, "reg", mem_info, + sizeof(mem_info)) != 8) + break; + + TotalMemory = mem_info[1]; + break; + } + } else + /* Fall back to hard-coding 32MB. */ TotalMemory = 32*1024*1024; @@ -304,6 +330,18 @@ decompress_kernel(unsigned long load_add *cp = 0; puts("\nUncompressing Linux..."); + /* + * If we have OF, then we have deferred setting the MSR. + * We must set it now because we are about to overwrite + * the exception table. The new MSR value will disable + * machine check exceptions and point the exception table + * to the ROM. + */ + if (OFW_interface) { + mtmsr(MSR_IP | MSR_FP); + asm volatile("isync"); + } + gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); diff -puN arch/ppc/Kconfig~linus arch/ppc/Kconfig --- 25/arch/ppc/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -681,6 +681,7 @@ config IRQ_ALL_CPUS config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "4" diff -puN arch/ppc/kernel/Makefile~linus arch/ppc/kernel/Makefile --- 25/arch/ppc/kernel/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -9,8 +9,7 @@ ifdef CONFIG_4xx EXTRA_AFLAGS := -Wa,-m405 endif -# Start off with 'head.o', change as needed. -extra-y := head.o +extra-$(CONFIG_PPC_STD_MMU) := head.o extra-$(CONFIG_40x) := head_4xx.o extra-$(CONFIG_44x) := head_44x.o extra-$(CONFIG_8xx) := head_8xx.o diff -puN arch/ppc/kernel/misc.S~linus arch/ppc/kernel/misc.S --- 25/arch/ppc/kernel/misc.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/misc.S 2004-01-19 22:17:21.000000000 -0800 @@ -1385,3 +1385,4 @@ _GLOBAL(sys_call_table) .long sys_statfs64 .long sys_fstatfs64 .long ppc_fadvise64_64 + .long sys_ni_syscall /* 255 - rtas (used on ppc64) */ diff -puN arch/ppc/kernel/module.c~linus arch/ppc/kernel/module.c --- 25/arch/ppc/kernel/module.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/module.c 2004-01-19 22:17:21.000000000 -0800 @@ -88,6 +88,10 @@ static unsigned long get_plt_size(const != is_init) continue; + /* We don't want to look at debug sections. */ + if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) + continue; + if (sechdrs[i].sh_type == SHT_RELA) { DEBUGP("Found relocations in section %u\n", i); DEBUGP("Ptr: %p. Number: %u\n", @@ -265,7 +269,6 @@ int apply_relocate_add(Elf32_Shdr *sechd return 0; } -/* FIXME: Sort exception table --RR */ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) diff -puN arch/ppc/kernel/ppc_ksyms.c~linus arch/ppc/kernel/ppc_ksyms.c --- 25/arch/ppc/kernel/ppc_ksyms.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/ppc_ksyms.c 2004-01-19 22:17:21.000000000 -0800 @@ -92,7 +92,7 @@ EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(probe_irq_mask); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); -EXPORT_SYMBOL_NOVERS(DMA_MODE_READ); +EXPORT_SYMBOL(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); #if defined(CONFIG_PPC_PREP) EXPORT_SYMBOL(_prep_type); @@ -167,9 +167,9 @@ EXPORT_SYMBOL(ppc_ide_md); #endif #ifdef CONFIG_PCI -EXPORT_SYMBOL_NOVERS(isa_io_base); -EXPORT_SYMBOL_NOVERS(isa_mem_base); -EXPORT_SYMBOL_NOVERS(pci_dram_offset); +EXPORT_SYMBOL(isa_io_base); +EXPORT_SYMBOL(isa_mem_base); +EXPORT_SYMBOL(pci_dram_offset); EXPORT_SYMBOL(pci_alloc_consistent); EXPORT_SYMBOL(pci_free_consistent); EXPORT_SYMBOL(pci_bus_io_base); @@ -246,7 +246,7 @@ EXPORT_SYMBOL(register_backlight_control EXPORT_SYMBOL(_machine); #endif #ifdef CONFIG_PPC_PMAC -EXPORT_SYMBOL_NOVERS(sys_ctrler); +EXPORT_SYMBOL(sys_ctrler); EXPORT_SYMBOL(pmac_newworld); #endif #ifdef CONFIG_PPC_OF @@ -294,15 +294,15 @@ EXPORT_SYMBOL(to_tm); EXPORT_SYMBOL(pm_power_off); -EXPORT_SYMBOL_NOVERS(__ashrdi3); -EXPORT_SYMBOL_NOVERS(__ashldi3); -EXPORT_SYMBOL_NOVERS(__lshrdi3); -EXPORT_SYMBOL_NOVERS(memcpy); -EXPORT_SYMBOL_NOVERS(memset); -EXPORT_SYMBOL_NOVERS(memmove); -EXPORT_SYMBOL_NOVERS(memscan); -EXPORT_SYMBOL_NOVERS(memcmp); -EXPORT_SYMBOL_NOVERS(memchr); +EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__ashldi3); +EXPORT_SYMBOL(__lshrdi3); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(memscan); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(abs); @@ -366,7 +366,7 @@ EXPORT_SYMBOL(request_8xxirq); EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); EXPORT_SYMBOL(handle_mm_fault); /* For MOL */ -EXPORT_SYMBOL_NOVERS(disarm_decr); +EXPORT_SYMBOL(disarm_decr); #ifdef CONFIG_PPC_STD_MMU extern long mol_trampoline; EXPORT_SYMBOL(mol_trampoline); /* For MOL */ @@ -381,5 +381,5 @@ EXPORT_SYMBOL(intercept_table); EXPORT_SYMBOL(cur_cpu_spec); #ifdef CONFIG_PPC_PMAC extern unsigned long agp_special_page; -EXPORT_SYMBOL_NOVERS(agp_special_page); +EXPORT_SYMBOL(agp_special_page); #endif diff -puN arch/ppc/kernel/syscalls.c~linus arch/ppc/kernel/syscalls.c --- 25/arch/ppc/kernel/syscalls.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/kernel/syscalls.c 2004-01-19 22:17:21.000000000 -0800 @@ -271,5 +271,3 @@ long ppc_fadvise64_64(int fd, int advice { return sys_fadvise64_64(fd, offset, len, advice); } - -cond_syscall(sys_pciconfig_iobase); diff -puN arch/ppc/mm/cachemap.c~linus arch/ppc/mm/cachemap.c --- 25/arch/ppc/mm/cachemap.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/mm/cachemap.c 2004-01-19 22:17:21.000000000 -0800 @@ -170,3 +170,5 @@ void consistent_sync_page(struct page *p start = (unsigned long)page_address(page) + offset; consistent_sync((void *)start, size, direction); } + +EXPORT_SYMBOL(consistent_sync_page); diff -puN -L arch/ppc/mm/extable.c arch/ppc/mm/extable.c~linus /dev/null --- 25/arch/ppc/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,70 +0,0 @@ -/* - * arch/ppc/mm/extable.c - * - * from arch/i386/mm/extable.c - */ - -#include -#include -#include -#include - -extern struct exception_table_entry __start___ex_table[]; -extern struct exception_table_entry __stop___ex_table[]; - -/* - * The exception table needs to be sorted because we use the macros - * which put things into the exception table in a variety of segments - * such as the prep, pmac, chrp, etc. segments as well as the init - * segment and the main kernel text segment. - */ -static inline void -sort_ex_table(struct exception_table_entry *start, - struct exception_table_entry *finish) -{ - struct exception_table_entry el, *p, *q; - - /* insertion sort */ - for (p = start + 1; p < finish; ++p) { - /* start .. p-1 is sorted */ - if (p[0].insn < p[-1].insn) { - /* move element p down to its right place */ - el = *p; - q = p; - do { - /* el comes before q[-1], move q[-1] up one */ - q[0] = q[-1]; - --q; - } while (q > start && el.insn < q[-1].insn); - *q = el; - } - } -} - -void __init -sort_exception_table(void) -{ - sort_ex_table(__start___ex_table, __stop___ex_table); -} - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN arch/ppc/mm/Makefile~linus arch/ppc/mm/Makefile --- 25/arch/ppc/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/ppc/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,7 +6,7 @@ ifdef CONFIG_PPC64BRIDGE EXTRA_AFLAGS := -Wa,-mppc64bridge endif -obj-y := fault.o init.o mem_pieces.o extable.o \ +obj-y := fault.o init.o mem_pieces.o \ mmu_context.o pgtable.o obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o diff -puN -L arch/ppc/platforms/mpc82xx.h arch/ppc/platforms/mpc82xx.h~linus /dev/null --- 25/arch/ppc/platforms/mpc82xx.h +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,42 +0,0 @@ -/* - * arch/ppc/platforms/mpc82xx.h - * - * Board specific support for various 82xx platforms. - * - * Author: Allen Curtis - * - * Copyright 2002 Ones and Zeros, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#ifndef __CONFIG_82XX_PLATFORMS -#define __CONFIG_82XX_PLATFORMS - -#ifdef CONFIG_8260 - -#ifdef CONFIG_EST8260 -#include -#endif - -#ifdef CONFIG_SBS8260 -#include -#endif - -#ifdef CONFIG_RPX6 -#include -#endif - -#ifdef CONFIG_WILLOW -#include -#endif - -#ifdef CONFIG_TQM8260 -#include -#endif - -#endif /* CONFIG_8260 */ - -#endif diff -puN arch/s390/defconfig~linus arch/s390/defconfig --- 25/arch/s390/defconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/defconfig 2004-01-19 22:17:21.000000000 -0800 @@ -29,6 +29,7 @@ CONFIG_EPOLL=y CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -109,8 +110,8 @@ CONFIG_SCSI_LOGGING=y # # SCSI low-level drivers # -# CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_SATA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_DEBUG is not set CONFIG_ZFCP=y @@ -158,7 +159,8 @@ CONFIG_UNIX98_PTY_COUNT=2048 # # S/390 character device drivers # -# CONFIG_TN3270 is not set +CONFIG_TN3270=y +CONFIG_TN3270_CONSOLE=y CONFIG_TN3215=y CONFIG_TN3215_CONSOLE=y CONFIG_CCW_CONSOLE=y @@ -318,6 +320,21 @@ CONFIG_QETH=y CONFIG_CCWGROUP=y # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -358,8 +375,7 @@ CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set -# CONFIG_HUGETLBFS is not set +CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y @@ -385,6 +401,7 @@ CONFIG_RAMFS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set CONFIG_NFSD=y CONFIG_NFSD_V3=y # CONFIG_NFSD_V4 is not set @@ -424,6 +441,11 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_EFI_PARTITION is not set # +# Native Language Support +# +# CONFIG_NLS is not set + +# # Kernel hacking # CONFIG_DEBUG_KERNEL=y diff -puN arch/s390/Kconfig~linus arch/s390/Kconfig --- 25/arch/s390/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -97,6 +97,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP && ARCH_S390X = 'n' default "32" help @@ -109,6 +110,7 @@ config NR_CPUS config NR_CPUS int "Maximum number of CPUs (2-64)" + range 2 64 depends on SMP && ARCH_S390X default "64" help diff -puN arch/s390/kernel/compat_ioctl.c~linus arch/s390/kernel/compat_ioctl.c --- 25/arch/s390/kernel/compat_ioctl.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_ioctl.c 2004-01-19 22:17:21.000000000 -0800 @@ -2,818 +2,46 @@ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * S390 version - * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Copyright (C) 2000-2003 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Gerhard Tonn (ton@de.ibm.com) + * Arnd Bergmann (arndb@de.ibm.com) * - * Heavily inspired by the 32-bit Sparc compat code which is + * Original implementation from 32-bit Sparc compat code which is * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) - * */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - +#include "compat_linux.h" +#define INCLUDES +#define CODE +#include "../../../fs/compat_ioctl.c" #include -#include #include -#include "compat_linux.h" - -long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); - -struct hd_geometry32 { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - __u32 start; -}; - -static inline int hd_geometry_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *f) -{ - struct hd_geometry32 *hg32 = (struct hd_geometry32 *) A(arg); - struct hd_geometry hg; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_ioctl (fd, cmd, (long)&hg); - set_fs (old_fs); - - if (ret) - return ret; - - ret = put_user (hg.heads, &(hg32->heads)); - ret |= __put_user (hg.sectors, &(hg32->sectors)); - ret |= __put_user (hg.cylinders, &(hg32->cylinders)); - ret |= __put_user (hg.start, &(hg32->start)); - - return ret; -} - -#define EXT2_IOC32_GETFLAGS _IOR('f', 1, int) -#define EXT2_IOC32_SETFLAGS _IOW('f', 2, int) -#define EXT2_IOC32_GETVERSION _IOR('v', 1, int) -#define EXT2_IOC32_SETVERSION _IOW('v', 2, int) - -struct ifmap32 { - unsigned int mem_start; - unsigned int mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct ifreq32 { -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - char ifru_newname[IFNAMSIZ]; - __u32 ifru_data; - } ifr_ifru; -}; - -struct ifconf32 { - int ifc_len; /* size of buffer */ - __u32 ifcbuf; -}; - -static int dev_ifname32(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - struct ireq32 *uir32 = (struct ireq32 *) A(arg); - struct net_device *dev; - struct ifreq32 ifr32; - - if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32))) - return -EFAULT; - - read_lock(&dev_base_lock); - dev = __dev_get_by_index(ifr32.ifr_ifindex); - if (!dev) { - read_unlock(&dev_base_lock); - return -ENODEV; - } - - strcpy(ifr32.ifr_name, dev->name); - read_unlock(&dev_base_lock); - - if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32))) - return -EFAULT; - - return 0; -} - -static int dev_ifconf(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - struct ioconf32 *uifc32 = (struct ioconf32 *) A(arg); - struct ifconf32 ifc32; - struct ifconf ifc; - struct ifreq32 *ifr32; - struct ifreq *ifr; - mm_segment_t old_fs; - int len; - int err; - - if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32))) - return -EFAULT; - - if(ifc32.ifcbuf == 0) { - ifc32.ifc_len = 0; - ifc.ifc_len = 0; - ifc.ifc_buf = NULL; - } else { - ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) * - sizeof (struct ifreq); - ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL); - if (!ifc.ifc_buf) - return -ENOMEM; - } - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf); - len = ifc32.ifc_len / sizeof (struct ifreq32); - while (len--) { - if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) { - err = -EFAULT; - goto out; - } - } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); - set_fs (old_fs); - if (err) - goto out; - - ifr = ifc.ifc_req; - ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf); - len = ifc.ifc_len / sizeof (struct ifreq); - ifc32.ifc_len = len * sizeof (struct ifreq32); - - while (len--) { - if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) { - err = -EFAULT; - goto out; - } - } - - if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) { - err = -EFAULT; - goto out; - } -out: - if(ifc.ifc_buf != NULL) - kfree (ifc.ifc_buf); - return err; -} - -static int bond_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - struct ifreq ifr; - mm_segment_t old_fs; - int err, len; - u32 data; - - if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) - return -EFAULT; - ifr.ifr_data = (__kernel_caddr_t)get_zeroed_page(GFP_KERNEL); - if (!ifr.ifr_data) - return -EAGAIN; - - switch (cmd) { - case SIOCBONDENSLAVE: - case SIOCBONDRELEASE: - case SIOCBONDSETHWADDR: - case SIOCBONDCHANGEACTIVE: - len = IFNAMSIZ * sizeof(char); - break; - case SIOCBONDSLAVEINFOQUERY: - len = sizeof(struct ifslave); - break; - case SIOCBONDINFOQUERY: - len = sizeof(struct ifbond); - break; - default: - err = -EINVAL; - goto out; - }; - - __get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data)); - if (copy_from_user(ifr.ifr_data, (char *)A(data), len)) { - err = -EFAULT; - goto out; - } - - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - len = copy_to_user((char *)A(data), ifr.ifr_data, len); - if (len) - err = -EFAULT; - } - -out: - free_page((unsigned long)ifr.ifr_data); - return err; -} - -static int dev_ifsioc(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) +static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file *f) { - struct ifreq32 *uifr = (struct ifreq32 *) A(arg); - struct ifreq ifr; - mm_segment_t old_fs; - int err; - - switch (cmd) { - case SIOCSIFMAP: - err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name)); - err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); - err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); - err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); - err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); - err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); - err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); - if (err) - return -EFAULT; - break; - default: - if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32))) - return -EFAULT; - break; - } - old_fs = get_fs(); - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&ifr); - set_fs (old_fs); - if (!err) { - switch (cmd) { - case SIOCGIFFLAGS: - case SIOCGIFMETRIC: - case SIOCGIFMTU: - case SIOCGIFMEM: - case SIOCGIFHWADDR: - case SIOCGIFINDEX: - case SIOCGIFADDR: - case SIOCGIFBRDADDR: - case SIOCGIFDSTADDR: - case SIOCGIFNETMASK: - case SIOCGIFTXQLEN: - if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32))) - return -EFAULT; - break; - case SIOCGIFMAP: - err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name)); - err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); - err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); - err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); - err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); - err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); - err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); - if (err) - err = -EFAULT; - break; - } - } - return err; + return sys_ioctl(fd, cmd, (unsigned long)compat_ptr(arg)); } -struct rtentry32 -{ - unsigned int rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - unsigned int rt_pad3; - unsigned int rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - unsigned int rt_dev; /* forcing the device at add */ - unsigned int rt_mtu; /* per route MTU/Window */ -#ifndef __KERNEL__ -#define rt_mss rt_mtu /* Compatibility :-( */ -#endif - unsigned int rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ -}; - -static int routing_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) +static int do_ioctl32_ulong(unsigned int fd, unsigned int cmd, + unsigned long arg, struct file *f) { - struct rtentry32 *ur = (struct rtentry32 *) A(arg); - struct rtentry r; - char devname[16]; - u32 rtdev; - int ret; - mm_segment_t old_fs = get_fs(); - - ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr)); - ret |= __get_user (r.rt_flags, &(ur->rt_flags)); - ret |= __get_user (r.rt_metric, &(ur->rt_metric)); - ret |= __get_user (r.rt_mtu, &(ur->rt_mtu)); - ret |= __get_user (r.rt_window, &(ur->rt_window)); - ret |= __get_user (r.rt_irtt, &(ur->rt_irtt)); - ret |= __get_user (rtdev, &(ur->rt_dev)); - if (rtdev) { - ret |= copy_from_user (devname, (char *) A(rtdev), 15); - r.rt_dev = devname; devname[15] = 0; - } else - r.rt_dev = 0; - if (ret) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_ioctl (fd, cmd, (long)&r); - set_fs (old_fs); - return ret; -} - -static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - /* These are just misnamed, they actually get/put from/to user an int */ - switch (cmd) { - case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break; - case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break; - case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break; - case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break; - } return sys_ioctl(fd, cmd, arg); } +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_pointer) +#define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)do_ioctl32_ulong) +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl_trans_handler_t)(handler), NULL }, -struct loop_info32 { - int lo_number; /* ioctl r/o */ - compat_dev_t lo_device; /* ioctl r/o */ - unsigned int lo_inode; /* ioctl r/o */ - compat_dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned int lo_init[2]; - char reserved[4]; -}; - -static int loop_status(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - mm_segment_t old_fs = get_fs(); - struct loop_info l; - int err = -EINVAL; - - switch(cmd) { - case LOOP_SET_STATUS: - err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset, - 8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) { - err = -EFAULT; - } else { - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - } - break; - case LOOP_GET_STATUS: - set_fs (KERNEL_DS); - err = sys_ioctl (fd, cmd, (unsigned long)&l); - set_fs (old_fs); - if (!err) { - err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number); - err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device); - err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode); - err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice); - err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset, - (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset); - if (err) - err = -EFAULT; - } - break; - default: { - static int count = 0; - if (++count <= 20) - printk("%s: Unknown loop ioctl cmd, fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } - } - return err; -} - - -struct blkpg_ioctl_arg32 { - int op; - int flags; - int datalen; - u32 data; -}; - -static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, - unsigned long uarg, struct file *f) -{ - struct blkpg_ioctl_arg a; - struct blkpg_partition p; - struct blkpg_ioctl_arg32 *arg = (void*)A(uarg); - int err; - mm_segment_t old_fs = get_fs(); - - err = get_user(a.op, &arg->op); - err |= __get_user(a.flags, &arg->flags); - err |= __get_user(a.datalen, &arg->datalen); - err |= __get_user((long)a.data, &arg->data); - if (err) return err; - switch (a.op) { - case BLKPG_ADD_PARTITION: - case BLKPG_DEL_PARTITION: - if (a.datalen < sizeof(struct blkpg_partition)) - return -EINVAL; - if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) - return -EFAULT; - a.data = &p; - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&a); - set_fs (old_fs); - default: - return -EINVAL; - } - return err; -} - - -typedef struct ica_z90_status_t { - int totalcount; - int leedslitecount; - int leeds2count; - int requestqWaitCount; - int pendingqWaitCount; - int totalOpenCount; - int cryptoDomain; - unsigned char status[64]; - unsigned char qdepth[64]; -} ica_z90_status; - -typedef struct _ica_rsa_modexpo { - char *inputdata; - unsigned int inputdatalength; - char *outputdata; - unsigned int outputdatalength; - char *b_key; - char *n_modulus; -} ica_rsa_modexpo_t; - -typedef struct _ica_rsa_modexpo_32 { - u32 inputdata; - u32 inputdatalength; - u32 outputdata; - u32 outputdatalength; - u32 b_key; - u32 n_modulus; -} ica_rsa_modexpo_32_t; - -typedef struct _ica_rsa_modexpo_crt { - char *inputdata; - unsigned int inputdatalength; - char *outputdata; - unsigned int outputdatalength; - char *bp_key; - char *bq_key; - char *np_prime; - char *nq_prime; - char *u_mult_inv; -} ica_rsa_modexpo_crt_t; - -typedef struct _ica_rsa_modexpo_crt_32 { - u32 inputdata; - u32 inputdatalength; - u32 outputdata; - u32 outputdatalength; - u32 bp_key; - u32 bq_key; - u32 np_prime; - u32 nq_prime; - u32 u_mult_inv; -} ica_rsa_modexpo_crt_32_t; - -#define ICA_IOCTL_MAGIC 'z' -#define ICARSAMODEXPO _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x05, 0) -#define ICARSACRT _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x06, 0) -#define ICARSAMODMULT _IOC(_IOC_READ|_IOC_WRITE, ICA_IOCTL_MAGIC, 0x07, 0) -#define ICAZ90STATUS _IOC(_IOC_READ, ICA_IOCTL_MAGIC, 0x10, sizeof(ica_z90_status)) -#define ICAZ90QUIESCE _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x11, 0) -#define ICAZ90HARDRESET _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x12, 0) -#define ICAZ90HARDERROR _IOC(_IOC_NONE, ICA_IOCTL_MAGIC, 0x13, 0) - -static int do_rsa_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *f) -{ - mm_segment_t old_fs = get_fs(); - int err = 0; - ica_rsa_modexpo_t rsa; - ica_rsa_modexpo_32_t *rsa32 = (ica_rsa_modexpo_32_t *)arg; - u32 inputdata, outputdata, b_key, n_modulus; - - memset (&rsa, 0, sizeof(rsa)); - - err |= __get_user (inputdata, &rsa32->inputdata); - err |= __get_user (rsa.inputdatalength, &rsa32->inputdatalength); - err |= __get_user (outputdata, &rsa32->outputdata); - err |= __get_user (rsa.outputdatalength, &rsa32->outputdatalength); - err |= __get_user (b_key, &rsa32->b_key); - err |= __get_user (n_modulus, &rsa32->n_modulus); - if (err) - return -EFAULT; - - rsa.inputdata = (char *)kmalloc(rsa.inputdatalength, GFP_KERNEL); - if (!rsa.inputdata) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.inputdata, (char *)(u64)(inputdata & 0x7fffffff), - rsa.inputdatalength)) { - err = -EFAULT; - goto cleanup; - } - - rsa.outputdata = (char *)kmalloc(rsa.outputdatalength, GFP_KERNEL); - if (!rsa.outputdata) { - err = -ENOMEM; - goto cleanup; - } - - rsa.b_key = (char *)kmalloc(rsa.inputdatalength, GFP_KERNEL); - if (!rsa.b_key) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.b_key, (char *)(u64)(b_key & 0x7fffffff), - rsa.inputdatalength)) { - err = -EFAULT; - goto cleanup; - } - - rsa.n_modulus = (char *)kmalloc(rsa.inputdatalength, GFP_KERNEL); - if (!rsa.n_modulus) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.n_modulus, (char *)(u64)(n_modulus & 0x7fffffff), - rsa.inputdatalength)) { - err = -EFAULT; - goto cleanup; - } - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&rsa); - set_fs(old_fs); - if (err < 0) - goto cleanup; - - if (copy_to_user((char *)(u64)(outputdata & 0x7fffffff), rsa.outputdata, - rsa.outputdatalength)) - err = -EFAULT; - -cleanup: - if (rsa.inputdata) - kfree(rsa.inputdata); - if (rsa.outputdata) - kfree(rsa.outputdata); - if (rsa.b_key) - kfree(rsa.b_key); - if (rsa.n_modulus) - kfree(rsa.n_modulus); - - return err; -} - -static int do_rsa_crt_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - mm_segment_t old_fs = get_fs(); - int err = 0; - ica_rsa_modexpo_crt_t rsa; - ica_rsa_modexpo_crt_32_t *rsa32 = (ica_rsa_modexpo_crt_32_t *)arg; - u32 inputdata, outputdata, bp_key, bq_key, np_prime, nq_prime, u_mult_inv; - - memset (&rsa, 0, sizeof(rsa)); - - err |= __get_user (inputdata, &rsa32->inputdata); - err |= __get_user (rsa.inputdatalength, &rsa32->inputdatalength); - err |= __get_user (outputdata, &rsa32->outputdata); - err |= __get_user (rsa.outputdatalength, &rsa32->outputdatalength); - err |= __get_user (bp_key, &rsa32->bp_key); - err |= __get_user (bq_key, &rsa32->bq_key); - err |= __get_user (np_prime, &rsa32->np_prime); - err |= __get_user (nq_prime, &rsa32->nq_prime); - err |= __get_user (u_mult_inv, &rsa32->u_mult_inv); - if (err) - return -EFAULT; - - rsa.inputdata = (char *)kmalloc(rsa.inputdatalength, GFP_KERNEL); - if (!rsa.inputdata) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.inputdata, (char *)(u64)(inputdata & 0x7fffffff), - rsa.inputdatalength)) { - err = -EFAULT; - goto cleanup; - } - - rsa.outputdata = (char *)kmalloc(rsa.outputdatalength, GFP_KERNEL); - if (!rsa.outputdata) { - err = -ENOMEM; - goto cleanup; - } - - rsa.bp_key = (char *)kmalloc(rsa.inputdatalength/2 + 8, GFP_KERNEL); - if (!rsa.bp_key) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.bp_key, (char *)(u64)(bp_key & 0x7fffffff), - rsa.inputdatalength/2 + 8)) { - err = -EFAULT; - goto cleanup; - } - - rsa.bq_key = (char *)kmalloc(rsa.inputdatalength/2, GFP_KERNEL); - if (!rsa.bq_key) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.bq_key, (char *)(u64)(bq_key & 0x7fffffff), - rsa.inputdatalength/2)) { - err = -EFAULT; - goto cleanup; - } - - rsa.np_prime = (char *)kmalloc(rsa.inputdatalength/2 + 8, GFP_KERNEL); - if (!rsa.np_prime) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.np_prime, (char *)(u64)(np_prime & 0x7fffffff), - rsa.inputdatalength/2 + 8)) { - err = -EFAULT; - goto cleanup; - } - - rsa.nq_prime = (char *)kmalloc(rsa.inputdatalength/2, GFP_KERNEL); - if (!rsa.nq_prime) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.nq_prime, (char *)(u64)(nq_prime & 0x7fffffff), - rsa.inputdatalength/2)) { - err = -EFAULT; - goto cleanup; - } - - rsa.u_mult_inv = (char *)kmalloc(rsa.inputdatalength/2 + 8, GFP_KERNEL); - if (!rsa.u_mult_inv) { - err = -ENOMEM; - goto cleanup; - } - if (copy_from_user(rsa.u_mult_inv, (char *)(u64)(u_mult_inv & 0x7fffffff), - rsa.inputdatalength/2 + 8)) { - err = -EFAULT; - goto cleanup; - } - - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&rsa); - set_fs(old_fs); - if (err < 0) - goto cleanup; - - if (copy_to_user((char *)(u64)(outputdata & 0x7fffffff), rsa.outputdata, - rsa.outputdatalength)) - err = -EFAULT; - -cleanup: - if (rsa.inputdata) - kfree(rsa.inputdata); - if (rsa.outputdata) - kfree(rsa.outputdata); - if (rsa.bp_key) - kfree(rsa.bp_key); - if (rsa.bq_key) - kfree(rsa.bq_key); - if (rsa.np_prime) - kfree(rsa.np_prime); - if (rsa.nq_prime) - kfree(rsa.nq_prime); - if (rsa.u_mult_inv) - kfree(rsa.u_mult_inv); - - return err; -} - -static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg, - struct file *f) -{ - mm_segment_t old_fs = get_fs(); - int err; - unsigned long val; - - set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); - set_fs (old_fs); - if (!err && put_user((unsigned int) val, (u32 *)arg)) - return -EFAULT; - return err; -} - -int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, - unsigned long arg, struct file *f) -{ - /* siocdevprivate cannot be emulated properly */ - return -EINVAL; -} - -#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd), NULL) -#define HANDLE_IOCTL(cmd,handler) { (cmd), (handler), NULL }, -#define IOCTL_TABLE_START \ - struct ioctl_trans ioctl_start[] = { -#define IOCTL_TABLE_END \ - }; - -IOCTL_TABLE_START +struct ioctl_trans ioctl_start[] = { +/* architecture independent ioctls */ #include +#define DECLARES +#include "../../../fs/compat_ioctl.c" +/* s390 only ioctls */ +#if defined(CONFIG_DASD) || defined(CONFIG_DASD_MODULE) COMPATIBLE_IOCTL(DASDAPIVER) COMPATIBLE_IOCTL(BIODASDDISABLE) COMPATIBLE_IOCTL(BIODASDENABLE) @@ -822,83 +50,18 @@ COMPATIBLE_IOCTL(BIODASDRLSE) COMPATIBLE_IOCTL(BIODASDSLCK) COMPATIBLE_IOCTL(BIODASDINFO) COMPATIBLE_IOCTL(BIODASDFMT) +#endif +#if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE) COMPATIBLE_IOCTL(TAPE390_DISPLAY) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(BLKFRASET) -COMPATIBLE_IOCTL(BLKBSZGET) -COMPATIBLE_IOCTL(BLKGETSIZE64) - -HANDLE_IOCTL(HDIO_GETGEO, hd_geometry_ioctl) +#endif +/* This one should be architecture independent */ COMPATIBLE_IOCTL(TCSBRKP) +/* s390 doesn't need handlers here */ COMPATIBLE_IOCTL(TIOCGSERIAL) COMPATIBLE_IOCTL(TIOCSSERIAL) - -COMPATIBLE_IOCTL(SIOCGSTAMP) - -HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) -HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) -HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) -HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) -HANDLE_IOCTL(SIOCADDRT, routing_ioctl) -HANDLE_IOCTL(SIOCDELRT, routing_ioctl) -HANDLE_IOCTL(SIOCBONDENSLAVE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDRELEASE, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSETHWADDR, bond_ioctl) -HANDLE_IOCTL(SIOCBONDSLAVEINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDINFOQUERY, bond_ioctl) -HANDLE_IOCTL(SIOCBONDCHANGEACTIVE, bond_ioctl) - -HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) -HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) - -HANDLE_IOCTL(LOOP_SET_STATUS, loop_status) -HANDLE_IOCTL(LOOP_GET_STATUS, loop_status) - -HANDLE_IOCTL(ICARSAMODEXPO, do_rsa_ioctl) -HANDLE_IOCTL(ICARSACRT, do_rsa_crt_ioctl) -HANDLE_IOCTL(ICARSAMODMULT, do_rsa_ioctl) - -COMPATIBLE_IOCTL(ICAZ90STATUS) -COMPATIBLE_IOCTL(ICAZ90QUIESCE) -COMPATIBLE_IOCTL(ICAZ90HARDRESET) -COMPATIBLE_IOCTL(ICAZ90HARDERROR) - -HANDLE_IOCTL(BLKRAGET, w_long) -HANDLE_IOCTL(BLKGETSIZE, w_long) -HANDLE_IOCTL(BLKFRAGET, w_long) -HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) - -IOCTL_TABLE_END +}; int ioctl_table_size = ARRAY_SIZE(ioctl_start); diff -puN arch/s390/kernel/compat_linux.c~linus arch/s390/kernel/compat_linux.c --- 25/arch/s390/kernel/compat_linux.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.c 2004-01-19 22:17:21.000000000 -0800 @@ -5,6 +5,7 @@ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), * Gerhard Tonn (ton@de.ibm.com) + * Thomas Spatzier (tspat@de.ibm.com) * * Conversion between 31bit and 64bit native syscalls. * @@ -934,19 +935,32 @@ static long do_readv_writev32(int type, tot_len = 0; i = count; ivp = iov; + retval = -EINVAL; while(i > 0) { - u32 len; + compat_ssize_t tmp = tot_len; + compat_ssize_t len; u32 buf; - __get_user(len, &vector->iov_len); - __get_user(buf, &vector->iov_base); + if (__get_user(len, &vector->iov_len) || + __get_user(buf, &vector->iov_base)) { + retval = -EFAULT; + goto out; + } + if (len < 0) /* size_t not fitting an ssize_t32 .. */ + goto out; tot_len += len; + if (tot_len < tmp) /* maths overflow on the compat_ssize_t */ + goto out; ivp->iov_base = (void *)A(buf); ivp->iov_len = (__kernel_size_t) len; vector++; ivp++; i--; } + if (tot_len == 0) { + retval = 0; + goto out; + } inode = file->f_dentry->d_inode; /* VERIFY_WRITE actually means a read, as we write to user space */ @@ -1500,50 +1514,6 @@ out: return err; } -struct rusage32 { - struct compat_timeval ru_utime; - struct compat_timeval ru_stime; - s32 ru_maxrss; - s32 ru_ixrss; - s32 ru_idrss; - s32 ru_isrss; - s32 ru_minflt; - s32 ru_majflt; - s32 ru_nswap; - s32 ru_inblock; - s32 ru_oublock; - s32 ru_msgsnd; - s32 ru_msgrcv; - s32 ru_nsignals; - s32 ru_nvcsw; - s32 ru_nivcsw; -}; - -static int put_rusage (struct rusage32 *ru, struct rusage *r) -{ - int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); - err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); - err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); - err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); - err |= __put_user (r->ru_maxrss, &ru->ru_maxrss); - err |= __put_user (r->ru_ixrss, &ru->ru_ixrss); - err |= __put_user (r->ru_idrss, &ru->ru_idrss); - err |= __put_user (r->ru_isrss, &ru->ru_isrss); - err |= __put_user (r->ru_minflt, &ru->ru_minflt); - err |= __put_user (r->ru_majflt, &ru->ru_majflt); - err |= __put_user (r->ru_nswap, &ru->ru_nswap); - err |= __put_user (r->ru_inblock, &ru->ru_inblock); - err |= __put_user (r->ru_oublock, &ru->ru_oublock); - err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd); - err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv); - err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); - err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); - err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); - return err; -} - struct sysinfo32 { s32 uptime; u32 loads[3]; @@ -2706,56 +2676,6 @@ out: return error; } -extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_setaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - if (get_user(kernel_mask, user_mask_ptr)) - return -EFAULT; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_setaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - return ret; -} - -extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, - unsigned long *user_mask_ptr); - -asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len, - u32 *user_mask_ptr) -{ - unsigned long kernel_mask; - mm_segment_t old_fs; - int ret; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_sched_getaffinity(pid, - /* XXX Nice api... */ - sizeof(kernel_mask), - &kernel_mask); - set_fs(old_fs); - - if (ret == 0) { - if (put_user(kernel_mask, user_mask_ptr)) - ret = -EFAULT; - } - - return ret; -} - asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count) @@ -2792,4 +2712,43 @@ asmlinkage int sys32_clone(struct pt_reg parent_tidptr, child_tidptr); } +/* + * Wrapper function for sys_timer_create. + */ +extern asmlinkage long +sys_timer_create(clockid_t, struct sigevent *, timer_t *); + +asmlinkage long +sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32, + timer_t *timer_id) +{ + struct sigevent se; + timer_t ktimer_id; + mm_segment_t old_fs; + long ret; + + if (se32 == NULL) + return sys_timer_create(which_clock, NULL, timer_id); + /* XXX: converting se32 to se is filthy because of the + * two union members. For now it is ok, because the pointers + * are not touched in kernel. + */ + memset(&se, 0, sizeof(se)); + if (get_user(se.sigev_value.sival_int, &se32->sigev_value.sival_int) || + get_user(se.sigev_signo, &se32->sigev_signo) || + get_user(se.sigev_notify, &se32->sigev_notify) || + copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad, + sizeof(se._sigev_un._pad))) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_timer_create(which_clock, &se, &ktimer_id); + set_fs(old_fs); + + if (!ret) + ret = put_user (ktimer_id, timer_id); + + return ret; +} diff -puN arch/s390/kernel/compat_linux.h~linus arch/s390/kernel/compat_linux.h --- 25/arch/s390/kernel/compat_linux.h~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_linux.h 2004-01-19 22:17:21.000000000 -0800 @@ -190,4 +190,22 @@ struct ucontext32 { compat_sigset_t uc_sigmask; /* mask last for extensibility */ }; +#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3) +struct sigevent32 { + union { + int sival_int; + u32 sival_ptr; + } sigev_value; + int sigev_signo; + int sigev_notify; + union { + int _pad[SIGEV_PAD_SIZE32]; + int _tid; + struct { + u32 *_function; + u32 *_attribute; + } _sigev_thread; + } _sigev_un; +}; + #endif /* _ASM_S390X_S390_H */ diff -puN arch/s390/kernel/compat_signal.c~linus arch/s390/kernel/compat_signal.c --- 25/arch/s390/kernel/compat_signal.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_signal.c 2004-01-19 22:17:21.000000000 -0800 @@ -314,6 +314,9 @@ static int restore_sigregs32(struct pt_r _s390_regs_common32 regs32; int err, i; + /* Alwys make any pending restarted system call return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); if (err) return err; diff -puN arch/s390/kernel/compat_wrapper.S~linus arch/s390/kernel/compat_wrapper.S --- 25/arch/s390/kernel/compat_wrapper.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/compat_wrapper.S 2004-01-19 22:17:21.000000000 -0800 @@ -135,7 +135,7 @@ sys32_alarm_wrapper: compat_sys_utime_wrapper: llgtr %r2,%r2 # char * llgtr %r3,%r3 # struct compat_utimbuf * - jg compat_sys_utime # branch to system call + jg compat_sys_utime # branch to system call .globl sys32_access_wrapper sys32_access_wrapper: @@ -1192,14 +1192,14 @@ sys32_sched_setaffinity_wrapper: lgfr %r2,%r2 # int llgfr %r3,%r3 # unsigned int llgtr %r4,%r4 # unsigned long * - jg sys32_sched_setaffinity + jg compat_sys_sched_setaffinity .globl sys32_sched_getaffinity_wrapper sys32_sched_getaffinity_wrapper: lgfr %r2,%r2 # int llgfr %r3,%r3 # unsigned int llgtr %r4,%r4 # unsigned long * - jg sys32_sched_getaffinity + jg compat_sys_sched_getaffinity .globl sys32_exit_group_wrapper sys32_exit_group_wrapper: @@ -1232,6 +1232,77 @@ sys_epoll_wait_wrapper: lgfr %r5,%r5 # int jg sys_epoll_wait # branch to system call + .globl sys32_fadvise64_wrapper +sys32_fadvise64_wrapper: + lgfr %r2,%r2 # int + sllg %r3,%r3,32 # get high word of 64bit loff_t + or %r3,%r4 # get low word of 64bit loff_t + llgfr %r4,%r5 # size_t (unsigned long) + lgfr %r5,%r6 # int + jg sys_fadvise64 + + .globl sys32_fadvise64_64_wrapper +sys32_fadvise64_64_wrapper: + llgtr %r2,%r2 # struct fadvise64_64_args * + jg s390_fadvise64_64 + + .globl sys32_clock_settime_wrapper +sys32_clock_settime_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_settime + + .globl sys32_clock_gettime_wrapper +sys32_clock_gettime_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_gettime + + .globl sys32_clock_getres_wrapper +sys32_clock_getres_wrapper: + lgfr %r2,%r2 # clockid_t (int) + llgtr %r3,%r3 # struct compat_timespec * + jg compat_clock_getres + + .globl sys32_clock_nanosleep_wrapper +sys32_clock_nanosleep_wrapper: + lgfr %r2,%r2 # clockid_t (int) + lgfr %r3,%r3 # int + llgtr %r4,%r4 # struct compat_timespec * + llgtr %r5,%r5 # struct compat_timespec * + jg compat_clock_nanosleep + + .globl sys32_timer_create_wrapper +sys32_timer_create_wrapper: + lgfr %r2,%r2 # timer_t (int) + llgtr %r3,%r3 # struct compat_sigevent * + llgtr %r4,%r4 # timer_t * + jg sys32_timer_create + + .globl sys32_timer_settime_wrapper +sys32_timer_settime_wrapper: + lgfr %r2,%r2 # timer_t (int) + lgfr %r3,%r3 # int + llgtr %r4,%r4 # struct compat_itimerspec * + llgtr %r5,%r5 # struct compat_itimerspec * + jg compat_timer_settime + + .globl sys32_timer_gettime_wrapper +sys32_timer_gettime_wrapper: + lgfr %r2,%r2 # timer_t (int) + llgtr %r3,%r3 # struct compat_itimerspec * + jg compat_timer_gettime + + .globl sys32_timer_getoverrun_wrapper +sys32_timer_getoverrun_wrapper: + lgfr %r2,%r2 # timer_t (int) + jg sys_timer_getoverrun + + .globl sys32_timer_delete_wrapper +sys32_timer_delete_wrapper: + lgfr %r2,%r2 # timer_t (int) + jg sys_timer_delete + .globl sys32_io_setup_wrapper sys32_io_setup_wrapper: llgfr %r2,%r2 # unsigned int diff -puN arch/s390/kernel/entry64.S~linus arch/s390/kernel/entry64.S --- 25/arch/s390/kernel/entry64.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/entry64.S 2004-01-19 22:17:21.000000000 -0800 @@ -169,9 +169,10 @@ system_call: slag %r7,%r7,2 # *4 and test for svc 0 jnz sysc_do_restart # svc 0: system call number in %r1 - clg %r1,.Lnr_syscalls-.Lconst(%r14) + cl %r1,.Lnr_syscalls-.Lconst(%r14) jnl sysc_do_restart - slag %r7,%r1,2 # svc 0: system call number in %r1 + lgfr %r7,%r1 # clear high word in r1 + slag %r7,%r7,2 # svc 0: system call number in %r1 sysc_do_restart: larl %r10,sys_call_table #ifdef CONFIG_S390_SUPPORT @@ -235,16 +236,18 @@ sysc_sigpending: sgr %r3,%r3 # clear *oldset brasl %r14,do_signal # call do_signal stnsm 48(%r15),0xfc # disable I/O and ext. interrupts + tm __TI_flags+7(%r9),_TIF_RESTART_SVC + jo sysc_restart j sysc_leave # out of here, do NOT recheck # # _TIF_RESTART_SVC is set, set up registers and restart svc # sysc_restart: - ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC + ni __TI_flags+7(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC stosm 48(%r15),0x03 # reenable interrupts lg %r7,SP_R2(%r15) # load new svc number - slag %r7,%r7,3 # *8 + slag %r7,%r7,2 # *4 mvc SP_R2(8,%r15),SP_ORIG_R2(%r15) # restore first argument lmg %r2,%r6,SP_R2(%r15) # load svc arguments j sysc_do_restart # restart svc @@ -503,7 +506,7 @@ pgm_svcstd: larl %r10,sys_call_table_emu # use 31 bit emulation system calls pgm_svcper_noemu: #endif - tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE + tm __TI_flags+7(%r9),_TIF_SYSCALL_TRACE lgf %r8,0(%r7,%r10) # load address of system call routine jo pgm_tracesys basr %r14,%r8 # call sys_xxxx @@ -512,7 +515,7 @@ pgm_svcper_noemu: # changing anything here !! pgm_svcret: - tm __TI_flags+3(%r9),_TIF_SIGPENDING + tm __TI_flags+7(%r9),_TIF_SIGPENDING jo pgm_svcper_nosig la %r2,SP_PTREGS(%r15) # load pt_regs sgr %r3,%r3 # clear *oldset diff -puN arch/s390/kernel/entry.S~linus arch/s390/kernel/entry.S --- 25/arch/s390/kernel/entry.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/entry.S 2004-01-19 22:17:21.000000000 -0800 @@ -249,6 +249,8 @@ sysc_sigpending: l %r1,BASED(.Ldo_signal) basr %r14,%r1 # call do_signal stnsm 24(%r15),0xfc # disable I/O and ext. interrupts + tm __TI_flags+3(%r9),_TIF_RESTART_SVC + bo BASED(sysc_restart) b BASED(sysc_leave) # out of here, do NOT recheck # @@ -258,7 +260,7 @@ sysc_restart: ni __TI_flags+3(%r9),255-_TIF_RESTART_SVC # clear TIF_RESTART_SVC stosm 24(%r15),0x03 # reenable interrupts l %r7,SP_R2(%r15) # load new svc number - sla %r2,2 + sla %r7,2 mvc SP_R2(4,%r15),SP_ORIG_R2(%r15) # restore first argument lm %r2,%r6,SP_R2(%r15) # load svc arguments b BASED(sysc_do_restart) # restart svc @@ -541,7 +543,7 @@ io_preempt: io_resume_loop: tm __TI_flags+3(%r9),_TIF_NEED_RESCHED bno BASED(io_leave) - mvc __TI_precount(4,%r9),.Lc_pactive + mvc __TI_precount(4,%r9),BASED(.Lc_pactive) # hmpf, we are on the async. stack but to call schedule # we have to move the interrupt frame to the process stack l %r1,SP_R15(%r15) diff -puN arch/s390/kernel/head64.S~linus arch/s390/kernel/head64.S --- 25/arch/s390/kernel/head64.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/head64.S 2004-01-19 22:17:21.000000000 -0800 @@ -582,6 +582,20 @@ startup:basr %r13,0 mvc __LC_DIAG44_OPCODE(8),.Ldiag44-.LPG1(%r13) 0: +# +# find out if we have the IDTE instruction +# + la %r1,0f-.LPG1(%r13) # set program check address + stg %r1,__LC_PGM_NEW_PSW+8 + .long 0xb2b10000 # store facility list + tm 0xc8,0x08 # check bit for clearing-by-ASCE + bno 0f-.LPG1(%r13) + lhi %r1,2094 + lhi %r2,0 + .long 0xb98e2001 + oi 7(%r12),0x80 # set IDTE flag +0: + lpswe .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 16 diff -puN arch/s390/kernel/head.S~linus arch/s390/kernel/head.S --- 25/arch/s390/kernel/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -569,6 +569,19 @@ startup:basr %r13,0 oi 3(%r12),16 # set MVPG flag .Lchkmvpg: +# +# find out if we have the IDTE instruction +# + mvc __LC_PGM_NEW_PSW(8),.Lpcidte-.LPG1(%r13) + .long 0xb2b10000 # store facility list + tm 0xc8,0x08 # check bit for clearing-by-ASCE + bno .Lchkidte-.LPG1(%r13) + lhi %r1,2094 + lhi %r2,0 + .long 0xb98e2001 + oi 3(%r12),0x80 # set IDTE flag +.Lchkidte: + lpsw .Lentry-.LPG1(13) # jump to _stext in primary-space, # virtual and never return ... .align 8 @@ -593,6 +606,7 @@ startup:basr %r13,0 .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp .Lpcmvpg:.long 0x00080000,0x80000000 + .Lchkmvpg +.Lpcidte:.long 0x00080000,0x80000000 + .Lchkidte .Lmemsize:.long memory_size .Lmchunk:.long memory_chunk .Lmflags:.long machine_flags diff -puN arch/s390/kernel/ptrace.c~linus arch/s390/kernel/ptrace.c --- 25/arch/s390/kernel/ptrace.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/ptrace.c 2004-01-19 22:17:21.000000000 -0800 @@ -130,7 +130,11 @@ peek_user(struct task_struct *child, add struct user *dummy = NULL; addr_t offset, tmp; - if ((addr & __ADDR_MASK) || addr > sizeof(struct user) - __ADDR_MASK) + /* + * Stupid gdb peeks/pokes the access registers in 64 bit with + * an alignment of 4. Programmers from hell... + */ + if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK) return -EIO; if (addr <= (addr_t) &dummy->regs.orig_gpr2) { @@ -138,6 +142,9 @@ peek_user(struct task_struct *child, add * psw, gprs, acrs and orig_gpr2 are stored on the stack */ tmp = *(addr_t *)((addr_t) __KSTK_PTREGS(child) + addr); + if (addr == (addr_t) &dummy->regs.psw.mask) + /* Remove per bit from user psw. */ + tmp &= ~PSW_MASK_PER; } else if (addr >= (addr_t) &dummy->regs.fp_regs && addr < (addr_t) (&dummy->regs.fp_regs + 1)) { @@ -173,7 +180,11 @@ poke_user(struct task_struct *child, add struct user *dummy = NULL; addr_t offset; - if ((addr & __ADDR_MASK) || addr > sizeof(struct user) - __ADDR_MASK) + /* + * Stupid gdb peeks/pokes the access registers in 64 bit with + * an alignment of 4. Programmers from hell indeed... + */ + if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK) return -EIO; if (addr <= (addr_t) &dummy->regs.orig_gpr2) { @@ -258,7 +269,7 @@ do_ptrace_normal(struct task_struct *chi case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: - if (!copy_from_user(&parea, (void *) addr, sizeof(parea))) + if (copy_from_user(&parea, (void *) addr, sizeof(parea))) return -EFAULT; addr = parea.kernel_addr; data = parea.process_addr; @@ -266,8 +277,12 @@ do_ptrace_normal(struct task_struct *chi while (copied < parea.len) { if (request == PTRACE_PEEKUSR_AREA) ret = peek_user(child, addr, data); - else - ret = poke_user(child, addr, data); + else { + addr_t tmp; + if (get_user (tmp, (addr_t *) data)) + return -EFAULT; + ret = poke_user(child, addr, tmp); + } if (ret) return ret; addr += sizeof(unsigned long); @@ -390,7 +405,7 @@ poke_user_emu31(struct task_struct *chil if ((tmp & ~PSW32_MASK_CC) != PSW32_USER_BITS) /* Invalid psw mask. */ return -EINVAL; - __KSTK_PTREGS(child)->psw.mask = PSW_USER_BITS | + __KSTK_PTREGS(child)->psw.mask = PSW_USER32_BITS | ((tmp & PSW32_MASK_CC) << 32); } else if (addr == (addr_t) &dummy32->regs.psw.addr) { /* Build a 64 bit psw address from 31 bit address. */ @@ -484,7 +499,7 @@ do_ptrace_emu31(struct task_struct *chil case PTRACE_PEEKUSR_AREA: case PTRACE_POKEUSR_AREA: - if (!copy_from_user(&parea, (void *) addr, sizeof(parea))) + if (copy_from_user(&parea, (void *) addr, sizeof(parea))) return -EFAULT; addr = parea.kernel_addr; data = parea.process_addr; @@ -492,8 +507,12 @@ do_ptrace_emu31(struct task_struct *chil while (copied < parea.len) { if (request == PTRACE_PEEKUSR_AREA) ret = peek_user_emu31(child, addr, data); - else - ret = poke_user_emu31(child, addr, data); + else { + __u32 tmp; + if (get_user (tmp, (__u32 *) data)) + return -EFAULT; + ret = poke_user_emu31(child, addr, tmp); + } if (ret) return ret; addr += sizeof(unsigned int); diff -puN arch/s390/kernel/semaphore.c~linus arch/s390/kernel/semaphore.c --- 25/arch/s390/kernel/semaphore.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/semaphore.c 2004-01-19 22:17:21.000000000 -0800 @@ -64,14 +64,14 @@ void __down(struct semaphore * sem) struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE; + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { schedule(); - tsk->state = TASK_UNINTERRUPTIBLE; + set_task_state(tsk, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + __set_task_state(tsk, TASK_RUNNING); wake_up(&sem->wait); } @@ -87,7 +87,7 @@ int __down_interruptible(struct semaphor struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE; + __set_task_state(tsk, TASK_INTERRUPTIBLE); add_wait_queue_exclusive(&sem->wait, &wait); while (__sem_update_count(sem, -1) <= 0) { if (signal_pending(current)) { @@ -96,10 +96,10 @@ int __down_interruptible(struct semaphor break; } schedule(); - tsk->state = TASK_INTERRUPTIBLE; + set_task_state(tsk, TASK_INTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + __set_task_state(tsk, TASK_RUNNING); wake_up(&sem->wait); return retval; } diff -puN arch/s390/kernel/setup.c~linus arch/s390/kernel/setup.c --- 25/arch/s390/kernel/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -158,8 +158,10 @@ static int __init condev_setup(char *str int vdev; vdev = simple_strtoul(str, &str, 0); - if (vdev >= 0 && vdev < 65536) + if (vdev >= 0 && vdev < 65536) { console_device = vdev; + console_irq = -1; + } return 1; } @@ -287,6 +289,7 @@ void (*_machine_power_off)(void) = do_ma void machine_restart(char *command) { + console_unblank(); _machine_restart(command); } @@ -294,6 +297,7 @@ EXPORT_SYMBOL(machine_restart); void machine_halt(void) { + console_unblank(); _machine_halt(); } @@ -301,6 +305,7 @@ EXPORT_SYMBOL(machine_halt); void machine_power_off(void) { + console_unblank(); _machine_power_off(); } diff -puN arch/s390/kernel/signal.c~linus arch/s390/kernel/signal.c --- 25/arch/s390/kernel/signal.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/signal.c 2004-01-19 22:17:21.000000000 -0800 @@ -167,6 +167,9 @@ static int restore_sigregs(struct pt_reg { int err; + /* Alwys make any pending restarted system call return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + err = __copy_from_user(regs, &sregs->regs, sizeof(_s390_regs_common)); regs->psw.mask = PSW_USER_BITS | (regs->psw.mask & PSW_MASK_CC); regs->psw.addr |= PSW_ADDR_AMODE; diff -puN arch/s390/kernel/syscalls.S~linus arch/s390/kernel/syscalls.S --- 25/arch/s390/kernel/syscalls.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/syscalls.S 2004-01-19 22:17:21.000000000 -0800 @@ -15,7 +15,7 @@ SYSCALL(sys_read,sys_read,sys32_read_wra SYSCALL(sys_write,sys_write,sys32_write_wrapper) SYSCALL(sys_open,sys_open,sys32_open_wrapper) /* 5 */ SYSCALL(sys_close,sys_close,sys32_close_wrapper) -SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_ni_syscall) +SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) SYSCALL(sys_link,sys_link,sys32_link_wrapper) SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ @@ -261,14 +261,15 @@ SYSCALL(sys_epoll_create,sys_epoll_creat SYSCALL(sys_epoll_ctl,sys_epoll_ctl,sys_epoll_ctl_wrapper) /* 250 */ SYSCALL(sys_epoll_wait,sys_epoll_wait,sys_epoll_wait_wrapper) SYSCALL(sys_set_tid_address,sys_set_tid_address,sys32_set_tid_address_wrapper) -SYSCALL(sys_fadvise64,sys_fadvise64,sys_ni_syscall) -SYSCALL(sys_timer_create,sys_timer_create,sys_ni_syscall) -SYSCALL(sys_timer_settime,sys_timer_settime,sys_ni_syscall) /* 255 */ -SYSCALL(sys_timer_gettime,sys_timer_gettime,sys_ni_syscall) -SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys_ni_syscall) -SYSCALL(sys_timer_delete,sys_timer_delete,sys_ni_syscall) -SYSCALL(sys_clock_settime,sys_clock_settime,sys_ni_syscall) -SYSCALL(sys_clock_gettime,sys_clock_gettime,sys_ni_syscall) /* 260 */ -SYSCALL(sys_clock_getres,sys_clock_getres,sys_ni_syscall) -SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys_ni_syscall) +SYSCALL(s390_fadvise64,sys_fadvise64_64,sys32_fadvise64_wrapper) +SYSCALL(sys_timer_create,sys_timer_create,sys32_timer_create_wrapper) +SYSCALL(sys_timer_settime,sys_timer_settime,sys32_timer_settime_wrapper) /* 255 */ +SYSCALL(sys_timer_gettime,sys_timer_gettime,sys32_timer_gettime_wrapper) +SYSCALL(sys_timer_getoverrun,sys_timer_getoverrun,sys32_timer_getoverrun_wrapper) +SYSCALL(sys_timer_delete,sys_timer_delete,sys32_timer_delete_wrapper) +SYSCALL(sys_clock_settime,sys_clock_settime,sys32_clock_settime_wrapper) +SYSCALL(sys_clock_gettime,sys_clock_gettime,sys32_clock_gettime_wrapper) /* 260 */ +SYSCALL(sys_clock_getres,sys_clock_getres,sys32_clock_getres_wrapper) +SYSCALL(sys_clock_nanosleep,sys_clock_nanosleep,sys32_clock_nanosleep_wrapper) NI_SYSCALL /* reserved for vserver */ +SYSCALL(s390_fadvise64_64,sys_ni_syscall,sys32_fadvise64_64_wrapper) diff -puN arch/s390/kernel/sys_s390.c~linus arch/s390/kernel/sys_s390.c --- 25/arch/s390/kernel/sys_s390.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/sys_s390.c 2004-01-19 22:17:21.000000000 -0800 @@ -325,3 +325,39 @@ asmlinkage int s390x_personality(unsigne return ret; } #endif /* CONFIG_ARCH_S390X */ + +/* + * Wrapper function for sys_fadvise64/fadvise64_64 + */ +#ifndef CONFIG_ARCH_S390X + +extern asmlinkage long sys_fadvise64(int, loff_t, size_t, int); + +asmlinkage long +s390_fadvise64(int fd, u32 offset_high, u32 offset_low, size_t len, int advice) +{ + return sys_fadvise64(fd, (u64) offset_high << 32 | offset_low, + len, advice); +} + +#endif + +extern asmlinkage long sys_fadvise64_64(int, loff_t, loff_t, int); + +struct fadvise64_64_args { + int fd; + long long offset; + long long len; + int advice; +}; + +asmlinkage long +s390_fadvise64_64(struct fadvise64_64_args *args) +{ + struct fadvise64_64_args a; + + if ( copy_from_user(&a, args, sizeof(a)) ) + return -EFAULT; + return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice); +} + diff -puN arch/s390/kernel/traps.c~linus arch/s390/kernel/traps.c --- 25/arch/s390/kernel/traps.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/traps.c 2004-01-19 22:17:21.000000000 -0800 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -156,9 +157,10 @@ void show_registers(struct pt_regs *regs int i; mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl"; - printk("%s PSW : %p %p\n", + printk("%s PSW : %p %p", mode, (void *) regs->psw.mask, (void *) regs->psw.addr); + print_symbol(" (%s)\n", regs->psw.addr & PSW_ADDR_INSN); printk("%s GPRS: " FOURLONG, mode, regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); printk(" " FOURLONG, @@ -250,6 +252,10 @@ void die(const char * str, struct pt_reg show_regs(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); + if (in_interrupt()) + panic("Fatal exception in interrupt"); + if (panic_on_oops) + panic("Fatal exception: panic_on_oops"); do_exit(SIGSEGV); } diff -puN arch/s390/kernel/vmlinux.lds.S~linus arch/s390/kernel/vmlinux.lds.S --- 25/arch/s390/kernel/vmlinux.lds.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/kernel/vmlinux.lds.S 2004-01-19 22:17:21.000000000 -0800 @@ -117,10 +117,7 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { - *(.exit.text) - *(.exit.data) *(.exitcall.exit) - *(.eh_frame) } /* Stabs debugging sections. */ diff -puN arch/s390/lib/uaccess64.S~linus arch/s390/lib/uaccess64.S --- 25/arch/s390/lib/uaccess64.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/lib/uaccess64.S 2004-01-19 22:17:21.000000000 -0800 @@ -73,6 +73,41 @@ __copy_to_user_asm: .align 4 .text + .globl __copy_in_user_asm +__copy_in_user_asm: + stmg %r6,%r15,48(%r15) + lgr %r5,%r3 + lgr %r7,%r5 + lgr %r6,%r2 + cpya 6,4 # ar6 = ar4 + sacf 512 +0: mvcle %r4,%r6,0 + jo 0b +1: sacf 0 + lgr %r2,%r7 + lmg %r6,%r15,48(%r15) + br %r14 +2: lghi %r1,-4096 + lgr %r5,%r4 + slgr %r5,%r1 # %r5 = %r4 + 4096 + ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slgr %r5,%r4 # %r5 = #bytes to next user page boundary + clgr %r7,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r6,0 + jo 3b + j 1b + .section __ex_table,"a" + .quad 0b,2b + .quad 3b,1b + .previous + + .align 4 + .text .globl __clear_user_asm __clear_user_asm: lgr %r4,%r2 diff -puN arch/s390/lib/uaccess.S~linus arch/s390/lib/uaccess.S --- 25/arch/s390/lib/uaccess.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/lib/uaccess.S 2004-01-19 22:17:21.000000000 -0800 @@ -73,6 +73,41 @@ __copy_to_user_asm: .align 4 .text + .globl __copy_in_user_asm +__copy_in_user_asm: + stm %r6,%r15,24(%r15) + lr %r5,%r3 + lr %r7,%r3 + lr %r6,%r2 + cpya 6,4 # ar6 = ar4 + sacf 512 +0: mvcle %r4,%r6,0 + jo 0b +1: sacf 0 + lr %r2,%r7 + lm %r6,%r15,24(%r15) + br %r14 +2: lhi %r1,-4096 + lr %r5,%r4 + slr %r5,%r1 # %r5 = %r4 + 4096 + nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096 + slr %r5,%r4 # %r5 = #bytes to next user page boundary + clr %r7,%r5 # copy crosses next page boundary ? + jnh 1b # no, the current page fauled + # The page after the current user page might have faulted. + # We cant't find out which page because the program check handler + # might have callled schedule, destroying all lowcore information. + # We retry with the shortened length. +3: mvcle %r4,%r6,0 + jo 3b + j 1b + .section __ex_table,"a" + .long 0b,2b + .long 3b,1b + .previous + + .align 4 + .text .globl __clear_user_asm __clear_user_asm: lr %r4,%r2 diff -puN -L arch/s390/mm/extable.c arch/s390/mm/extable.c~linus /dev/null --- 25/arch/s390/mm/extable.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,34 +0,0 @@ -/* - * arch/s390/mm/extable.c - * - * S390 version - * - * identical to arch/i386/mm/extable.c - */ - -#include -#include -#include -#include - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return NULL; -} diff -puN arch/s390/mm/fault.c~linus arch/s390/mm/fault.c --- 25/arch/s390/mm/fault.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/mm/fault.c 2004-01-19 22:17:21.000000000 -0800 @@ -538,8 +538,6 @@ asmlinkage void pfault_interrupt(struct pt_regs *regs, __u16 error_code) { struct task_struct *tsk; - wait_queue_head_t queue; - wait_queue_head_t *qp; __u16 subcode; /* @@ -553,46 +551,34 @@ pfault_interrupt(struct pt_regs *regs, _ return; /* - * Get the token (= address of kernel stack of affected task). + * Get the token (= address of the task structure of the affected task). */ tsk = *(struct task_struct **) __LC_PFAULT_INTPARM; - /* - * We got all needed information from the lowcore and can - * now safely switch on interrupts. - */ - if (regs->psw.mask & PSW_MASK_PSTATE) - local_irq_enable(); - if (subcode & 0x0080) { /* signal bit is set -> a page has been swapped in by VM */ - qp = (wait_queue_head_t *) - xchg(&tsk->thread.pfault_wait, -1); - if (qp != NULL) { + if (xchg(&tsk->thread.pfault_wait, -1) != 0) { /* Initial interrupt was faster than the completion * interrupt. pfault_wait is valid. Set pfault_wait * back to zero and wake up the process. This can * safely be done because the task is still sleeping * and can't procude new pfaults. */ - tsk->thread.pfault_wait = 0ULL; - wake_up(qp); + tsk->thread.pfault_wait = 0; + wake_up_process(tsk); } } else { /* signal bit not set -> a real page is missing. */ - init_waitqueue_head (&queue); - qp = (wait_queue_head_t *) - xchg(&tsk->thread.pfault_wait, (addr_t) &queue); - if (qp != NULL) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (xchg(&tsk->thread.pfault_wait, 1) != 0) { /* Completion interrupt was faster than the initial * interrupt (swapped in a -1 for pfault_wait). Set * pfault_wait back to zero and exit. This can be * done safely because tsk is running in kernel * mode and can't produce new pfaults. */ - tsk->thread.pfault_wait = 0ULL; - } - - /* go to sleep */ - wait_event(queue, tsk->thread.pfault_wait == 0ULL); + tsk->thread.pfault_wait = 0; + set_task_state(tsk, TASK_RUNNING); + } else + set_tsk_need_resched(tsk); } } #endif diff -puN arch/s390/mm/Makefile~linus arch/s390/mm/Makefile --- 25/arch/s390/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/s390/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,4 +2,4 @@ # Makefile for the linux s390-specific parts of the memory manager. # -obj-y := init.o fault.o ioremap.o extable.o +obj-y := init.o fault.o ioremap.o diff -puN -L arch/sh/boards/adx/io.c arch/sh/boards/adx/io.c~linus /dev/null --- 25/arch/sh/boards/adx/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,195 +0,0 @@ -/* - * linux/arch/sh/kernel/io_adx.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * I/O routine and setup routines for A&D ADX Board - * - * 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. - * - */ - -#include -#include -#include - -#define PORT2ADDR(x) (adx_isa_port2addr(x)) - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char adx_inb(unsigned long port) -{ - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned short adx_inw(unsigned long port) -{ - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int adx_inl(unsigned long port) -{ - return *(volatile unsigned long*)PORT2ADDR(port); -} - -unsigned char adx_inb_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned short adx_inw_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned int adx_inl_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); - - delay(); - return v; -} - -void adx_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf = buffer; - while(count--) *buf++ = inb(port); -} - -void adx_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf = buffer; - while(count--) *buf++ = inw(port); -} - -void adx_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf = buffer; - while(count--) *buf++ = inl(port); -} - -void adx_outb(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; -} - -void adx_outw(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void adx_outl(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; -} - -void adx_outb_p(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outw_p(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outl_p(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; - delay(); -} - -void adx_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf = buffer; - while(count--) outb(*buf++, port); -} - -void adx_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf = buffer; - while(count--) outw(*buf++, port); -} - -void adx_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf = buffer; - while(count--) outl(*buf++, port); -} - -unsigned char adx_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short adx_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int adx_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void adx_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void adx_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void adx_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -void *adx_ioremap(unsigned long offset, unsigned long size) -{ - return (void *)P2SEGADDR(offset); -} - -EXPORT_SYMBOL (adx_ioremap); - -void adx_iounmap(void *addr) -{ -} - -EXPORT_SYMBOL(adx_iounmap); - -#ifdef CONFIG_IDE -#include -extern void *cf_io_base; - -unsigned long adx_isa_port2addr(unsigned long offset) -{ - /* CompactFlash (IDE) */ - if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { - return (unsigned long)cf_io_base + offset; - } - - /* eth0 */ - if ((offset >= 0x300) && (offset <= 0x30f)) { - return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ - } - - return offset + 0xb0000000; /* IOBUS (AREA 4)*/ -} -#endif - diff -puN -L arch/sh/boards/adx/mach.c arch/sh/boards/adx/mach.c~linus /dev/null --- 25/arch/sh/boards/adx/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,64 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_adx.c - * - * Copyright (C) 2001 A&D Co., Ltd. - * - * This file may be copied or modified under the terms of the GNU - * General Public License. See linux/COPYING for more information. - * - * Machine vector for the A&D ADX Board - */ - -#include -#include - -#include -#include -#include -#include - -extern void init_adx_IRQ(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_adx __initmv = { - .mv_nr_irqs = 48, - - .mv_inb = adx_inb, - .mv_inw = adx_inw, - .mv_inl = adx_inl, - .mv_outb = adx_outb, - .mv_outw = adx_outw, - .mv_outl = adx_outl, - - .mv_inb_p = adx_inb_p, - .mv_inw_p = adx_inw, - .mv_inl_p = adx_inl, - .mv_outb_p = adx_outb_p, - .mv_outw_p = adx_outw, - .mv_outl_p = adx_outl, - - .mv_insb = adx_insb, - .mv_insw = adx_insw, - .mv_insl = adx_insl, - .mv_outsb = adx_outsb, - .mv_outsw = adx_outsw, - .mv_outsl = adx_outsl, - - .mv_readb = adx_readb, - .mv_readw = adx_readw, - .mv_readl = adx_readl, - .mv_writeb = adx_writeb, - .mv_writew = adx_writew, - .mv_writel = adx_writel, - - .mv_ioremap = adx_ioremap, - .mv_iounmap = adx_iounmap, - - .mv_isa_port2addr = adx_isa_port2addr, - - .mv_init_irq = init_adx_IRQ, -}; -ALIAS_MV(adx) diff -puN arch/sh/boards/adx/Makefile~linus arch/sh/boards/adx/Makefile --- 25/arch/sh/boards/adx/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/adx/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o irq_maskreq.o +obj-y := setup.o irq.o irq_maskreq.o diff -puN arch/sh/boards/adx/setup.c~linus arch/sh/boards/adx/setup.c --- 25/arch/sh/boards/adx/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/adx/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -14,11 +14,43 @@ #include #include +extern void init_adx_IRQ(void); +extern void *cf_io_base; + const char *get_system_type(void) { return "A&D ADX"; } -void platform_setup(void) +unsigned long adx_isa_port2addr(unsigned long offset) { + /* CompactFlash (IDE) */ + if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset == 0x3f6)) { + return (unsigned long)cf_io_base + offset; + } + + /* eth0 */ + if ((offset >= 0x300) && (offset <= 0x30f)) { + return 0xa5000000 + offset; /* COMM BOARD (AREA1) */ + } + + return offset + 0xb0000000; /* IOBUS (AREA 4)*/ } + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_adx __initmv = { + .mv_nr_irqs = 48, + .mv_isa_port2addr = adx_isa_port2addr, + .mv_init_irq = init_adx_IRQ, +}; +ALIAS_MV(adx) + +int __init platform_setup(void) +{ + /* Nothing to see here .. */ + return 0; +} + diff -puN arch/sh/boards/bigsur/io.c~linus arch/sh/boards/bigsur/io.c --- 25/arch/sh/boards/bigsur/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/bigsur/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -21,18 +21,6 @@ #include #include -//#define BIGSUR_DEBUG 2 -#undef BIGSUR_DEBUG - -#ifdef BIGSUR_DEBUG -#define DPRINTK(args...) printk(args) -#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) -#else -#define DPRINTK(args...) -#define DIPRINTK(n, args...) -#endif - - /* Low iomap maps port 0-1K to addresses in 8byte chunks */ #define BIGSUR_IOMAP_LO_THRESH 0x400 #define BIGSUR_IOMAP_LO_SHIFT 3 @@ -53,19 +41,17 @@ static u8 bigsur_iomap_hi_shift[BIGSUR_I #define MAX(a,b) ((a)>(b)?(a):(b)) #endif -#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x)) - void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift) { - u32 port, endport = baseport + nports; + u32 port, endport = baseport + nports; - DPRINTK("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n", - baseport, nports, addr); + pr_debug("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n", + baseport, nports, addr); for (port = baseport ; port < endport && port < BIGSUR_IOMAP_LO_THRESH ; port += (1<>BIGSUR_IOMAP_LO_SHIFT] = addr; bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift; addr += (1<<(BIGSUR_IOMAP_LO_SHIFT)); @@ -74,7 +60,7 @@ void bigsur_port_map(u32 baseport, u32 n for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; port < endport && port < BIGSUR_IOMAP_HI_THRESH ; port += (1<>BIGSUR_IOMAP_HI_SHIFT] = addr; bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift; addr += (1<<(BIGSUR_IOMAP_HI_SHIFT)); @@ -84,166 +70,56 @@ EXPORT_SYMBOL(bigsur_port_map); void bigsur_port_unmap(u32 baseport, u32 nports) { - u32 port, endport = baseport + nports; + u32 port, endport = baseport + nports; - DPRINTK("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports); + pr_debug("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports); for (port = baseport ; port < endport && port < BIGSUR_IOMAP_LO_THRESH ; port += (1<>BIGSUR_IOMAP_LO_SHIFT] = 0; + bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0; } for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ; port < endport && port < BIGSUR_IOMAP_HI_THRESH ; port += (1<>BIGSUR_IOMAP_HI_SHIFT] = 0; + bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0; } } EXPORT_SYMBOL(bigsur_port_unmap); unsigned long bigsur_isa_port2addr(unsigned long port) { - unsigned long addr = 0; + unsigned long addr = 0; unsigned char shift; /* Physical address not in P0, do nothing */ - if (PXSEG(port)) addr = port; + if (PXSEG(port)) { + addr = port; /* physical address in P0, map to P2 */ - else if (port >= 0x30000) - addr = P2SEGADDR(port); + } else if (port >= 0x30000) { + addr = P2SEGADDR(port); /* Big Sur I/O + HD64465 registers 0x10000-0x30000 */ - else if (port >= BIGSUR_IOMAP_HI_THRESH) - addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH); + } else if (port >= BIGSUR_IOMAP_HI_THRESH) { + addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH); /* Handle remapping of high IO/PCI IO ports */ - else if (port >= BIGSUR_IOMAP_LO_THRESH) { - addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT]; - shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT]; - if (addr != 0) - addr += (port & BIGSUR_IOMAP_HI_MASK) << shift; - } - /* Handle remapping of low IO ports */ - else { - addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT]; - shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT]; - if (addr != 0) - addr += (port & BIGSUR_IOMAP_LO_MASK) << shift; + } else if (port >= BIGSUR_IOMAP_LO_THRESH) { + addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT]; + shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT]; + + if (addr != 0) + addr += (port & BIGSUR_IOMAP_HI_MASK) << shift; + } else { + /* Handle remapping of low IO ports */ + addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT]; + shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT]; + + if (addr != 0) + addr += (port & BIGSUR_IOMAP_LO_MASK) << shift; } - DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr); + pr_debug("%s(0x%08lx) = 0x%08lx\n", __FUNCTION__, port, addr); return addr; } -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char bigsur_inb(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - - DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b); - return b; -} - -unsigned char bigsur_inb_p(unsigned long port) -{ - unsigned long v; - unsigned long addr = PORT2ADDR(port); - - v = (addr == 0 ? 0 : *(volatile unsigned char*)addr); - delay(); - DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v); - return v; -} - -unsigned short bigsur_inw(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr); - DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b); - return b; -} - -unsigned int bigsur_inl(unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr); - DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b); - return b; -} - -void bigsur_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void bigsur_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void bigsur_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - -void bigsur_outb(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; -} - -void bigsur_outb_p(unsigned char b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - - DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned char*)addr = b; - delay(); -} - -void bigsur_outw(unsigned short b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr); - if (addr != 0) - *(volatile unsigned short*)addr = b; -} - -void bigsur_outl(unsigned int b, unsigned long port) -{ - unsigned long addr = PORT2ADDR(port); - DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr); - if (addr != 0) - *(volatile unsigned long*)addr = b; -} - -void bigsur_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void bigsur_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void bigsur_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} - diff -puN -L arch/sh/boards/bigsur/mach.c arch/sh/boards/bigsur/mach.c~linus /dev/null --- 25/arch/sh/boards/bigsur/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,72 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_bigsur.c - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - * Derived from mach_se.h, which bore the message: - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the Hitachi Big Sur Evaluation Board - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -/* - * The Machine Vector - */ -extern void heartbeat_bigsur(void); -extern void init_bigsur_IRQ(void); - -struct sh_machine_vector mv_bigsur __initmv = { - .mv_nr_irqs = NR_IRQS, // Defined in - .mv_inb = bigsur_inb, - .mv_inw = bigsur_inw, - .mv_inl = bigsur_inl, - .mv_outb = bigsur_outb, - .mv_outw = bigsur_outw, - .mv_outl = bigsur_outl, - - .mv_inb_p = bigsur_inb_p, - .mv_inw_p = bigsur_inw, - .mv_inl_p = bigsur_inl, - .mv_outb_p = bigsur_outb_p, - .mv_outw_p = bigsur_outw, - .mv_outl_p = bigsur_outl, - - .mv_insb = bigsur_insb, - .mv_insw = bigsur_insw, - .mv_insl = bigsur_insl, - .mv_outsb = bigsur_outsb, - .mv_outsw = bigsur_outsw, - .mv_outsl = bigsur_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = bigsur_isa_port2addr, - .mv_irq_demux = bigsur_irq_demux, - - .mv_init_irq = init_bigsur_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_bigsur, -#endif - -}; -ALIAS_MV(bigsur) diff -puN arch/sh/boards/bigsur/Makefile~linus arch/sh/boards/bigsur/Makefile --- 25/arch/sh/boards/bigsur/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/bigsur/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,7 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o led.o - -obj-$(CONFIG_PCI) += pci.o +obj-y := setup.o io.o irq.o led.o diff -puN -L arch/sh/boards/bigsur/pci.c arch/sh/boards/bigsur/pci.c~linus /dev/null --- 25/arch/sh/boards/bigsur/pci.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,163 +0,0 @@ -/* - * linux/arch/sh/kernel/pci-bigsur.c - * - * By Dustin McIntire (dustin@sensoria.com) (c)2001 - - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * PCI initialization for the Hitachi Big Sur Evaluation Board - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) - -/* - * Initialize the Big Sur PCI interface - * Setup hardware to be Central Funtion - * Copy the BSR regs to the PCI interface - * Setup PCI windows into local RAM - */ -int __init pcibios_init_platform(void) { - u32 reg; - u32 word; - - PCIDBG(1,"PCI: bigsur_pci_init called\n"); - /* Set the BCR's to enable PCI access */ - reg = inl(SH7751_BCR1); - reg |= 0x80000; - outl(reg, SH7751_BCR1); - - /* Setup the host hardware */ - if(inl(PCI_REG(SH7751_PCICONF0)) != - (u32)((SH7751_DEVICE_ID <<16) | (SH7751_VENDOR_ID))) { - printk("PCI: Unkown PCI host bridge.\n"); - return 0; - } - printk("PCI: SH7751 PCI host bridge found.\n"); - - /* Turn the clocks back on (not done in reset)*/ - outl(0, PCI_REG(SH7751_PCICLKR)); - /* Clear Powerdown IRQ's (not done in reset) */ - word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; - outl(word, PCI_REG(SH7751_PCICLKR)); - - /* toggle PCI reset pin */ - word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; - outl(word,PCI_REG(SH7751_PCICR)); - /* Wait for a long time... not 1 sec. but long enough */ - mdelay(100); - word = SH7751_PCICR_PREFIX; - outl(word,PCI_REG(SH7751_PCICR)); - - /* set the command/status bits to: - * Wait Cycle Control + Parity Enable + Bus Master + - * Mem space enable - */ - word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | - SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; - outl(word, PCI_REG(SH7751_PCICONF1)); - - /* define this host as the host bridge */ - word = SH7751_PCI_HOST_BRIDGE << 24; - outl(word, PCI_REG(SH7751_PCICONF2)); - - /* Set IO and Mem windows to local address - * Make PCI and local address the same for easy 1 to 1 mapping - * Window0 = BIGSUR_LSR0_SIZE @ non-cached CS3 base = SDRAM - * Window1 = BIGSUR_LSR1_SIZE @ cached CS3 base = SDRAM - */ - word = BIGSUR_LSR0_SIZE - 1; - outl(word, PCI_REG(SH7751_PCILSR0)); - word = BIGSUR_LSR1_SIZE - 1; - outl(word, PCI_REG(SH7751_PCILSR1)); - /* Set the values on window 0 PCI config registers */ - word = P2SEGADDR(SH7751_CS3_BASE_ADDR); - outl(word, PCI_REG(SH7751_PCILAR0)); - outl(word, PCI_REG(SH7751_PCICONF5)); - /* Set the values on window 1 PCI config registers */ - word = PHYSADDR(SH7751_CS3_BASE_ADDR); - outl(word, PCI_REG(SH7751_PCILAR1)); - outl(word, PCI_REG(SH7751_PCICONF6)); - - /* Set the local 16MB PCI memory space window to - * the lowest PCI mapped address - */ - word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; - PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); - outl(word , PCI_REG(SH7751_PCIMBR)); - - /* Map IO space into PCI IO window - * The IO window is 64K-PCIBIOS_MIN_IO in size - * IO addresses will be translated to the - * PCI IO window base address - */ - PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, - (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); - bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0); - - /* Make sure the MSB's of IO window are set to access PCI space correctly */ - word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; - PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); - outl(word, PCI_REG(SH7751_PCIIOBR)); - - /* Set PCI WCRx, BCRx's, copy from BSC locations */ - word = inl(SH7751_BCR1); - /* check BCR for SDRAM in area 3 */ - if(((word >> 3) & 1) == 0) { - printk("PCI: Area 3 is not configured for SDRAM. BCR1=0x%x\n", word); - return 0; - } - outl(word, PCI_REG(SH7751_PCIBCR1)); - word = (u16)inw(SH7751_BCR2); - /* check BCR2 for 32bit SDRAM interface*/ - if(((word >> 6) & 0x3) != 0x3) { - printk("PCI: Area 3 is not 32 bit SDRAM. BCR2=0x%x\n", word); - return 0; - } - outl(word, PCI_REG(SH7751_PCIBCR2)); - /* configure the wait control registers */ - word = inl(SH7751_WCR1); - outl(word, PCI_REG(SH7751_PCIWCR1)); - word = inl(SH7751_WCR2); - outl(word, PCI_REG(SH7751_PCIWCR2)); - word = inl(SH7751_WCR3); - outl(word, PCI_REG(SH7751_PCIWCR3)); - word = inl(SH7751_MCR); - outl(word, PCI_REG(SH7751_PCIMCR)); - - /* NOTE: I'm ignoring the PCI error IRQs for now.. - * TODO: add support for the internal error interrupts and - * DMA interrupts... - */ - - /* SH7751 init done, set central function init complete */ - word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN; - outl(word,PCI_REG(SH7751_PCICR)); - PCIDBG(2,"PCI: bigsur_pci_init finished\n"); - - return 1; -} - -int pcibios_map_platform_irq(u8 slot, u8 pin) -{ - /* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI interface is on the - * wrong end of the board so that it can also support a V320 CPI interface chip... - * Therefor the IRQ mapping is somewhat use dependent... I'l assume a linear map for - * now, i.e. INTA=slot0,pin0... INTD=slot3,pin0... - */ - int irq = (slot + pin-1)%4 + BIGSUR_SH7751_PCI_IRQ_BASE; - PCIDBG(2,"PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", slot, pin-1+'A', irq); - return irq; - -} diff -puN arch/sh/boards/bigsur/setup.c~linus arch/sh/boards/bigsur/setup.c --- 25/arch/sh/boards/bigsur/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/bigsur/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -33,22 +33,11 @@ #include #include #include - +#include #include #include #include -//#define BIGSUR_DEBUG 3 -#undef BIGSUR_DEBUG - -#ifdef BIGSUR_DEBUG -#define DPRINTK(args...) printk(args) -#define DIPRINTK(n, args...) if (BIGSUR_DEBUG>(n)) printk(args) -#else -#define DPRINTK(args...) -#define DIPRINTK(n, args...) -#endif /* BIGSUR_DEBUG */ - /*===========================================================*/ // Big Sur Init Routines /*===========================================================*/ @@ -58,13 +47,27 @@ const char *get_system_type(void) return "Big Sur"; } +/* + * The Machine Vector + */ +extern void heartbeat_bigsur(void); +extern void init_bigsur_IRQ(void); + +struct sh_machine_vector mv_bigsur __initmv = { + .mv_nr_irqs = NR_IRQS, // Defined in + + .mv_isa_port2addr = bigsur_isa_port2addr, + .mv_irq_demux = bigsur_irq_demux, + + .mv_init_irq = init_bigsur_IRQ, +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_bigsur, +#endif +}; +ALIAS_MV(bigsur) + int __init platform_setup(void) { - static int done = 0; /* run this only once */ - - if (!MACH_BIGSUR || done) return 0; - done = 1; - /* Mask all 2nd level IRQ's */ outb(-1,BIGSUR_IMR0); outb(-1,BIGSUR_IMR1); @@ -88,7 +91,6 @@ int __init platform_setup(void) /* set the IO port to BIGSUR_ETHER_IOPORT */ outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2); - return 0; + return 0; } -module_init(setup_bigsur); diff -puN -L arch/sh/boards/cat68701/io.c arch/sh/boards/cat68701/io.c~linus /dev/null --- 25/arch/sh/boards/cat68701/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,207 +0,0 @@ -/* - * linux/arch/sh/boards/cat68701/io.c - * - * Copyright (C) 2000 Niibe Yutaka - * 2001 Yutaro Ebihara - * - * I/O routines for A-ONE Corp CAT-68701 SH7708 Board - * - * 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. - * - */ - -#include -#include -#include -#include - -#define SH3_PCMCIA_BUG_WORKAROUND 1 -#define DUMMY_READ_AREA6 0xba000000 - -#define PORT2ADDR(x) (cat68701_isa_port2addr(x)) - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -unsigned char cat68701_inb(unsigned long port) -{ - return *(volatile unsigned char*)PORT2ADDR(port); -} - -unsigned short cat68701_inw(unsigned long port) -{ - return *(volatile unsigned short*)PORT2ADDR(port); -} - -unsigned int cat68701_inl(unsigned long port) -{ - return *(volatile unsigned long*)PORT2ADDR(port); -} - -unsigned char cat68701_inb_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned char*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned short cat68701_inw_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned short*)PORT2ADDR(port); - - delay(); - return v; -} - -unsigned int cat68701_inl_p(unsigned long port) -{ - unsigned long v = *(volatile unsigned long*)PORT2ADDR(port); - - delay(); - return v; -} - -void cat68701_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void cat68701_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_outb(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; -} - -void cat68701_outw(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; -} - -void cat68701_outl(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; -} - -void cat68701_outb_p(unsigned char b, unsigned long port) -{ - *(volatile unsigned char*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outw_p(unsigned short b, unsigned long port) -{ - *(volatile unsigned short*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outl_p(unsigned int b, unsigned long port) -{ - *(volatile unsigned long*)PORT2ADDR(port) = b; - delay(); -} - -void cat68701_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void cat68701_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -void cat68701_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -#ifdef SH3_PCMCIA_BUG_WORKAROUND - ctrl_inb (DUMMY_READ_AREA6); -#endif -} - -unsigned char cat68701_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short cat68701_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int cat68701_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void cat68701_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void cat68701_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void cat68701_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - -void * cat68701_ioremap(unsigned long offset, unsigned long size) -{ - return (void *) P2SEGADDR(offset); -} -EXPORT_SYMBOL(cat68701_ioremap); - -void cat68701_iounmap(void *addr) -{ -} -EXPORT_SYMBOL(cat68701_iounmap); - -unsigned long cat68701_isa_port2addr(unsigned long offset) -{ - /* CompactFlash (IDE) */ - if(((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6)) - return 0xba000000 + offset; - - /* INPUT PORT */ - if((offset >= 0x3fc) && (offset <= 0x3fd)) - return 0xb4007000 + offset; - - /* OUTPUT PORT */ - if((offset >= 0x3fe) && (offset <= 0x3ff)) - return 0xb4007400 + offset; - - return offset + 0xb4000000; /* other I/O (EREA 5)*/ -} - diff -puN -L arch/sh/boards/cat68701/mach.c arch/sh/boards/cat68701/mach.c~linus /dev/null --- 25/arch/sh/boards/cat68701/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,66 +0,0 @@ -/* - * linux/arch/sh/boards/cat68701/mach.c - * - * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) - * 2001 Yutaro Ebihara (ebihara@si-linux.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine vector for the A-ONE corp. CAT-68701 SH7708 board - */ - -#include -#include - -#include -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_cat68701 __initmv = { - .mv_nr_irqs = 32, - .mv_inb = cat68701_inb, - .mv_inw = cat68701_inw, - .mv_inl = cat68701_inl, - .mv_outb = cat68701_outb, - .mv_outw = cat68701_outw, - .mv_outl = cat68701_outl, - - .mv_inb_p = cat68701_inb_p, - .mv_inw_p = cat68701_inw, - .mv_inl_p = cat68701_inl, - .mv_outb_p = cat68701_outb_p, - .mv_outw_p = cat68701_outw, - .mv_outl_p = cat68701_outl, - - .mv_insb = cat68701_insb, - .mv_insw = cat68701_insw, - .mv_insl = cat68701_insl, - .mv_outsb = cat68701_outsb, - .mv_outsw = cat68701_outsw, - .mv_outsl = cat68701_outsl, - - .mv_readb = cat68701_readb, - .mv_readw = cat68701_readw, - .mv_readl = cat68701_readl, - .mv_writeb = cat68701_writeb, - .mv_writew = cat68701_writew, - .mv_writel = cat68701_writel, - - .mv_ioremap = cat68701_ioremap, - .mv_iounmap = cat68701_iounmap, - - .mv_isa_port2addr = cat68701_isa_port2addr, - .mv_irq_demux = cat68701_irq_demux, - - .mv_init_irq = init_cat68701_IRQ, -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_cat68701, -#endif -}; -ALIAS_MV(cat68701) diff -puN arch/sh/boards/cat68701/Makefile~linus arch/sh/boards/cat68701/Makefile --- 25/arch/sh/boards/cat68701/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/cat68701/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o +obj-y := setup.o irq.o diff -puN arch/sh/boards/cat68701/setup.c~linus arch/sh/boards/cat68701/setup.c --- 25/arch/sh/boards/cat68701/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/cat68701/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -14,21 +14,18 @@ #include #include +#include #include #include +#include +#include const char *get_system_type(void) { return "CAT-68701"; } -void platform_setup() -{ - /* dummy read erea5 (CS8900A) */ -} - #ifdef CONFIG_HEARTBEAT -#include void heartbeat_cat68701() { static unsigned int cnt = 0, period = 0 , bit = 0; @@ -49,3 +46,41 @@ void heartbeat_cat68701() } #endif /* CONFIG_HEARTBEAT */ +unsigned long cat68701_isa_port2addr(unsigned long offset) +{ + /* CompactFlash (IDE) */ + if (((offset >= 0x1f0) && (offset <= 0x1f7)) || (offset==0x3f6)) + return 0xba000000 + offset; + + /* INPUT PORT */ + if ((offset >= 0x3fc) && (offset <= 0x3fd)) + return 0xb4007000 + offset; + + /* OUTPUT PORT */ + if ((offset >= 0x3fe) && (offset <= 0x3ff)) + return 0xb4007400 + offset; + + return offset + 0xb4000000; /* other I/O (EREA 5)*/ +} + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_cat68701 __initmv = { + .mv_nr_irqs = 32, + .mv_isa_port2addr = cat68701_isa_port2addr, + .mv_irq_demux = cat68701_irq_demux, + + .mv_init_irq = init_cat68701_IRQ, +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_cat68701, +#endif +}; +ALIAS_MV(cat68701) + +int __init platform_setup(void) +{ + /* dummy read erea5 (CS8900A) */ +} + diff -puN -L arch/sh/boards/cqreek/io.c arch/sh/boards/cqreek/io.c~linus /dev/null --- 25/arch/sh/boards/cqreek/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,14 +0,0 @@ -#define IDE_OFFSET 0xA4000000UL -#define ISA_OFFSET 0xA4A00000UL - -unsigned long cqreek_port2addr(unsigned long port) -{ - if (0x0000<=port && port<=0x0040) - return IDE_OFFSET + port; - if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) - return IDE_OFFSET + port; - - return ISA_OFFSET + port; -} - - diff -puN -L arch/sh/boards/cqreek/mach.c arch/sh/boards/cqreek/mach.c~linus /dev/null --- 25/arch/sh/boards/cqreek/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,66 +0,0 @@ -/* $Id: mach.c,v 1.1.2.4.2.1 2003/01/10 17:26:32 lethal Exp $ - * - * arch/sh/kernel/setup_cqreek.c - * - * Copyright (C) 2000 Niibe Yutaka - * - * CqREEK IDE/ISA Bridge Support. - * - */ - -#include -#include -#include -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_cqreek __initmv = { -#if defined(CONFIG_CPU_SH4) - .mv_nr_irqs = 48, -#elif defined(CONFIG_CPU_SUBTYPE_SH7708) - .mv_nr_irqs = 32, -#elif defined(CONFIG_CPU_SUBTYPE_SH7709) - .mv_nr_irqs = 61, -#endif - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw_p, - .mv_inl_p = generic_inl_p, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw_p, - .mv_outl_p = generic_outl_p, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_init_irq = init_cqreek_IRQ, - - .mv_isa_port2addr = cqreek_port2addr, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, -}; -ALIAS_MV(cqreek) diff -puN arch/sh/boards/cqreek/Makefile~linus arch/sh/boards/cqreek/Makefile --- 25/arch/sh/boards/cqreek/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/cqreek/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o +obj-y := setup.o irq.o diff -puN arch/sh/boards/cqreek/setup.c~linus arch/sh/boards/cqreek/setup.c --- 25/arch/sh/boards/cqreek/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/cqreek/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.1.2.5 2002/03/02 21:57:07 lethal Exp $ +/* $Id: setup.c,v 1.5 2003/08/04 01:51:58 lethal Exp $ * * arch/sh/kernel/setup_cqreek.c * @@ -13,17 +13,49 @@ #include #include -#include +#include +#include #include #include #include #include +#define IDE_OFFSET 0xA4000000UL +#define ISA_OFFSET 0xA4A00000UL + const char *get_system_type(void) { return "CqREEK"; } +static unsigned long cqreek_port2addr(unsigned long port) +{ + if (0x0000<=port && port<=0x0040) + return IDE_OFFSET + port; + if ((0x01f0<=port && port<=0x01f7) || port == 0x03f6) + return IDE_OFFSET + port; + + return ISA_OFFSET + port; +} + +/* + * The Machine Vector + */ +struct sh_machine_vector mv_cqreek __initmv = { +#if defined(CONFIG_CPU_SH4) + .mv_nr_irqs = 48, +#elif defined(CONFIG_CPU_SUBTYPE_SH7708) + .mv_nr_irqs = 32, +#elif defined(CONFIG_CPU_SUBTYPE_SH7709) + .mv_nr_irqs = 61, +#endif + + .mv_init_irq = init_cqreek_IRQ, + + .mv_isa_port2addr = cqreek_port2addr, +}; +ALIAS_MV(cqreek) + /* * Initialize the board */ diff -puN arch/sh/boards/dmida/mach.c~linus arch/sh/boards/dmida/mach.c --- 25/arch/sh/boards/dmida/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/dmida/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * linux/arch/sh/kernel/mach_dmida.c + * linux/arch/sh/boards/dmida/mach.c * * by Greg Banks * (c) 2000 PocketPenguins Inc @@ -30,8 +30,6 @@ */ struct sh_machine_vector mv_dmida __initmv = { - .mv_name = "DMIDA", - .mv_nr_irqs = HD64465_IRQ_BASE+HD64465_IRQ_NUM, .mv_inb = hd64465_inb, @@ -55,17 +53,7 @@ struct sh_machine_vector mv_dmida __init .mv_outsw = hd64465_outsw, .mv_outsl = hd64465_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - .mv_irq_demux = hd64465_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(dmida) diff -puN -L arch/sh/boards/dreamcast/io.c arch/sh/boards/dreamcast/io.c~linus /dev/null --- 25/arch/sh/boards/dreamcast/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,12 +0,0 @@ -/* - * $Id: io.c,v 1.1.2.1 2002/01/19 23:54:19 mrbrown Exp $ - * I/O routines for SEGA Dreamcast - */ - -#include -#include - -unsigned long dreamcast_isa_port2addr(unsigned long offset) -{ - return offset + 0xa0000000; -} diff -puN -L arch/sh/boards/dreamcast/mach.c arch/sh/boards/dreamcast/mach.c~linus /dev/null --- 25/arch/sh/boards/dreamcast/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,60 +0,0 @@ -/* - * $Id: mach.c,v 1.4 2003/05/20 03:04:36 lethal Exp $ - * SEGA Dreamcast machine vector - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -void __init dreamcast_pcibios_init(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_dreamcast __initmv = { - .mv_nr_irqs = NR_IRQS, - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw, - .mv_inl_p = generic_inl, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw, - .mv_outl_p = generic_outl, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = dreamcast_isa_port2addr, - .mv_irq_demux = systemasic_irq_demux, -}; -ALIAS_MV(dreamcast) diff -puN arch/sh/boards/dreamcast/Makefile~linus arch/sh/boards/dreamcast/Makefile --- 25/arch/sh/boards/dreamcast/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/dreamcast/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,7 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o rtc.o - -obj-$(CONFIG_PCI) += pci.o +obj-y := setup.o irq.o rtc.o diff -puN -L arch/sh/boards/dreamcast/pci.c arch/sh/boards/dreamcast/pci.c~linus /dev/null --- 25/arch/sh/boards/dreamcast/pci.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,214 +0,0 @@ -/* - $ $Id: pci.c,v 1.1.2.4.2.1 2003/03/31 14:33:18 lethal Exp $ - * Dreamcast PCI: Supports SEGA Broadband Adaptor only. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define GAPSPCI_REGS 0x01001400 -#define GAPSPCI_DMA_BASE 0x01840000 -#define GAPSPCI_DMA_SIZE 32768 -#define GAPSPCI_BBA_CONFIG 0x01001600 - -#define GAPSPCI_IRQ HW_EVENT_EXTERNAL - -static int gapspci_dma_used; - -/* XXX: Uh... */ -static struct resource gapspci_io_resource = { - "GAPSPCI IO", - 0x01001600, - 0x010016ff, - IORESOURCE_IO -}; - -static struct resource gapspci_mem_resource = { - "GAPSPCI mem", - 0x01840000, - 0x01847fff, - IORESOURCE_MEM -}; - -static struct pci_ops gapspci_pci_ops; -struct pci_channel board_pci_channels[] = { - {&gapspci_pci_ops, &gapspci_io_resource, &gapspci_mem_resource, 0, 1}, - {NULL, NULL, NULL, 0, 0}, -}; - -struct pci_fixup pcibios_fixups[] = { - {0, 0, 0, NULL} -}; - -#define BBA_SELECTED(bus,devfn) (bus->number==0 && devfn==0) - -static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - switch (size) { - case 1: - if (BBA_SELECTED(bus, devfn)) - *val = (u8)inb(GAPSPCI_BBA_CONFIG+where); - else - *val = (u8)0xff; - break; - case 2: - if (BBA_SELECTED(bus, devfn)) - *val = (u16)inw(GAPSPCI_BBA_CONFIG+where); - else - *val = (u16)0xffff; - break; - case 4: - if (BBA_SELECTED(bus, devfn)) - *val = inl(GAPSPCI_BBA_CONFIG+where); - else - *val = 0xffffffff; - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - if (BBA_SELECTED(bus, devfn)) { - switch (size) { - case 1: - if (BBA_SELECTED(bus, devfn)) - outb((u8)val, GAPSPCI_BBA_CONFIG+where); - break; - case 2: - if (BBA_SELECTED(bus, devfn)) - outw((u16)val, GAPSPCI_BBA_CONFIG+where); - break; - case 4: - if (BBA_SELECTED(bus, devfn)) - outl(val, GAPSPCI_BBA_CONFIG+where); - break; - } - } - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops gapspci_pci_ops = { - .read = gapspci_read, - .write = gapspci_write, -}; - - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - unsigned long buf; - - if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) - return NULL; - - buf = GAPSPCI_DMA_BASE+gapspci_dma_used; - - gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); - - printk("pci_alloc_consistent: %ld bytes at 0x%lx\n", (long)size, buf); - - *dma_handle = (dma_addr_t)buf; - - return (void *)P2SEGADDR(buf); -} - - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - /* XXX */ - gapspci_dma_used = 0; -} - - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - struct list_head *ln; - struct pci_dev *dev; - - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (!BBA_SELECTED(bus, dev->devfn)) continue; - - printk("PCI: MMIO fixup to %s\n", dev->dev.name); - dev->resource[1].start=0x01001700; - dev->resource[1].end=0x010017ff; - } -} - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - return PCI_SLOT(dev->devfn); -} - - -static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - return GAPSPCI_IRQ; -} - -void __init pcibios_fixup(void) { /* Do nothing. */ } - -void __init pcibios_fixup_irqs(void) -{ - pci_fixup_irqs(no_swizzle, map_dc_irq); -} - -int __init gapspci_init(void) -{ - int i; - char idbuf[16]; - - for(i=0; i<16; i++) - idbuf[i]=inb(GAPSPCI_REGS+i); - - if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) - return -1; - - outl(0x5a14a501, GAPSPCI_REGS+0x18); - - for(i=0; i<1000000; i++); - - if(inl(GAPSPCI_REGS+0x18)!=1) - return -1; - - outl(0x01000000, GAPSPCI_REGS+0x20); - outl(0x01000000, GAPSPCI_REGS+0x24); - - outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); - outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); - - outl(1, GAPSPCI_REGS+0x14); - outl(1, GAPSPCI_REGS+0x34); - - gapspci_dma_used=0; - - /* Setting Broadband Adapter */ - outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); - outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); - outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); - outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); - outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); - outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); - outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); - - return 0; -} - -/* Haven't done anything here as yet */ -char * __devinit pcibios_setup(char *str) -{ - return str; -} diff -puN arch/sh/boards/dreamcast/setup.c~linus arch/sh/boards/dreamcast/setup.c --- 25/arch/sh/boards/dreamcast/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/dreamcast/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,9 +1,10 @@ -/* arch/sh/kernel/setup_dc.c +/* + * arch/sh/boards/dreamcast/setup.c * * Hardware support for the Sega Dreamcast. * * Copyright (c) 2001, 2002 M. R. Brown - * Copyright (c) 2002 Paul Mundt + * Copyright (c) 2002, 2003 Paul Mundt * * This file is part of the LinuxDC project (www.linuxdc.org) * @@ -23,21 +24,27 @@ #include #include -#include +#include +#include +#include extern struct hw_interrupt_type systemasic_int; /* XXX: Move this into it's proper header. */ extern void (*board_time_init)(void); extern void aica_time_init(void); - +extern int gapspci_init(void); +extern int systemasic_irq_demux(int); const char *get_system_type(void) { return "Sega Dreamcast"; } -#ifdef CONFIG_PCI -extern int gapspci_init(void); -#endif +struct sh_machine_vector mv_dreamcast __initmv = { + .mv_nr_irqs = NR_IRQS, + + .mv_irq_demux = systemasic_irq_demux, +}; +ALIAS_MV(dreamcast) int __init platform_setup(void) { @@ -49,6 +56,8 @@ int __init platform_setup(void) /* Acknowledge any previous events */ /* XXX */ + __set_io_port_base(0xa0000000); + /* Assign all virtual IRQs to the System ASIC int. handler */ for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) irq_desc[i].handler = &systemasic_int; diff -puN -L arch/sh/boards/ec3104/mach.c arch/sh/boards/ec3104/mach.c~linus /dev/null --- 25/arch/sh/boards/ec3104/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,69 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_ec3104.c - * EC3104 companion chip support - * - * Copyright (C) 2000 Philipp Rumpf - * - */ -/* EC3104 note: - * This code was written without any documentation about the EC3104 chip. While - * I hope I got most of the basic functionality right, the register names I use - * are most likely completely different from those in the chip documentation. - * - * If you have any further information about the EC3104, please tell me - * (prumpf@tux.org). - */ - -#include - -#include -#include -#include - -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_ec3104 __initmv = { - .mv_name = "EC3104", - - .mv_nr_irqs = 96, - - .mv_inb = ec3104_inb, - .mv_inw = ec3104_inw, - .mv_inl = ec3104_inl, - .mv_outb = ec3104_outb, - .mv_outw = ec3104_outw, - .mv_outl = ec3104_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw, - .mv_inl_p = generic_inl, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw, - .mv_outl_p = generic_outl, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_irq_demux = ec3104_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, -}; - -ALIAS_MV(ec3104) diff -puN arch/sh/boards/ec3104/Makefile~linus arch/sh/boards/ec3104/Makefile --- 25/arch/sh/boards/ec3104/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/ec3104/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o +obj-y := setup.o io.o irq.o diff -puN arch/sh/boards/ec3104/setup.c~linus arch/sh/boards/ec3104/setup.c --- 25/arch/sh/boards/ec3104/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/ec3104/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -24,16 +24,38 @@ #include #include -#include +#include +#include -int __init setup_ec3104(void) +const char *get_system_type(void) +{ + return "EC3104"; +} + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_ec3104 __initmv = { + .mv_nr_irqs = 96, + + .mv_inb = ec3104_inb, + .mv_inw = ec3104_inw, + .mv_inl = ec3104_inl, + .mv_outb = ec3104_outb, + .mv_outw = ec3104_outw, + .mv_outl = ec3104_outl, + + .mv_irq_demux = ec3104_irq_demux, +}; + +ALIAS_MV(ec3104) + +int __init platform_setup(void) { char str[8]; int i; - if (!MACH_EC3104) - printk("!MACH_EC3104\n"); - if (0) return 0; @@ -54,4 +76,3 @@ int __init setup_ec3104(void) return 0; } -module_init(setup_ec3104); diff -puN arch/sh/boards/harp/mach.c~linus arch/sh/boards/harp/mach.c --- 25/arch/sh/boards/harp/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/harp/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * linux/arch/sh/stboards/mach.c + * linux/arch/sh/boards/harp/mach.c * * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com) * @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include void setup_harp(void); @@ -49,16 +49,6 @@ struct sh_machine_vector mv_harp __initm .mv_outsw = hd64465_outsw, .mv_outsl = hd64465_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - .mv_isa_port2addr = hd64465_isa_port2addr, #ifdef CONFIG_PCI diff -puN arch/sh/boards/hp6xx/hp620/mach.c~linus arch/sh/boards/hp6xx/hp620/mach.c --- 25/arch/sh/boards/hp6xx/hp620/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/hp6xx/hp620/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -24,8 +24,6 @@ */ struct sh_machine_vector mv_hp620 __initmv = { - .mv_name = "hp620", - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -49,16 +47,6 @@ struct sh_machine_vector mv_hp620 __init .mv_outsw = hd64461_outsw, .mv_outsl = hd64461_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(hp620) diff -puN arch/sh/boards/hp6xx/hp680/mach.c~linus arch/sh/boards/hp6xx/hp680/mach.c --- 25/arch/sh/boards/hp6xx/hp680/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/hp6xx/hp680/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -20,8 +20,6 @@ #include struct sh_machine_vector mv_hp680 __initmv = { - .mv_name = "hp680", - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -45,16 +43,6 @@ struct sh_machine_vector mv_hp680 __init .mv_outsw = hd64461_outsw, .mv_outsl = hd64461_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(hp680) diff -puN arch/sh/boards/hp6xx/hp690/mach.c~linus arch/sh/boards/hp6xx/hp690/mach.c --- 25/arch/sh/boards/hp6xx/hp690/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/hp6xx/hp690/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -20,8 +20,6 @@ #include struct sh_machine_vector mv_hp690 __initmv = { - .mv_name = "hp690", - .mv_nr_irqs = HD64461_IRQBASE+HD64461_IRQ_NUM, .mv_inb = hd64461_inb, @@ -45,16 +43,6 @@ struct sh_machine_vector mv_hp690 __init .mv_outsw = hd64461_outsw, .mv_outsl = hd64461_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - .mv_irq_demux = hd64461_irq_demux, - - .mv_rtc_gettimeofday = sh_rtc_gettimeofday, - .mv_rtc_settimeofday = sh_rtc_settimeofday, }; ALIAS_MV(hp690) diff -puN -L arch/sh/boards/mpc1211/io.c arch/sh/boards/mpc1211/io.c~linus /dev/null --- 25/arch/sh/boards/mpc1211/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,158 +0,0 @@ -/* - * linux/arch/sh/kernel/io_mpc1211.c - * - * Copyright (C) 2001 Saito.K & Jeanne - * - * I/O routine for Interface MPC-1211. - * - */ - -#include -#include -#include -#include -#include - -static inline void delay(void) -{ - ctrl_inw(0xa0000000); -} - -static inline unsigned long port2adr(unsigned long port) -{ - return port + PA_PCI_IO; -} - -unsigned char mpc1211_inb(unsigned long port) -{ - return *(__u8 *)port2adr(port); -} - -unsigned short mpc1211_inw(unsigned long port) -{ - return *(__u16 *)port2adr(port); -} - -unsigned int mpc1211_inl(unsigned long port) -{ - return *(__u32 *)port2adr(port); -} - -void mpc1211_outb(unsigned char value, unsigned long port) -{ - *(__u8 *)port2adr(port) = value; -} - -void mpc1211_outw(unsigned short value, unsigned long port) -{ - *(__u16 *)port2adr(port) = value; -} - -void mpc1211_outl(unsigned int value, unsigned long port) -{ - *(__u32 *)port2adr(port) = value; -} - -unsigned char mpc1211_inb_p(unsigned long port) -{ - unsigned char v; - - v = *(__u8 *)port2adr(port); - delay(); - return v; -} - -void mpc1211_outb_p(unsigned char value, unsigned long port) -{ - *(__u8 *)port2adr(port) = value; - delay(); -} - -void mpc1211_insb(unsigned long port, void *addr, unsigned long count) -{ - volatile __u8 *p = (__u8 *)port2adr(port); - - while (count--) { - *((__u8 *)addr)++ = *p; - } -} - -void mpc1211_insw(unsigned long port, void *addr, unsigned long count) -{ - volatile __u16 *p = (__u16 *)port2adr(port); - - while (count--) { - *((__u16 *)addr)++ = *p; - } -} - -void mpc1211_insl(unsigned long port, void *addr, unsigned long count) -{ - volatile __u32 *p = (__u32 *)port2adr(port); - - while (count--) { - *((__u32 *)addr)++ = *p; - } -} - -void mpc1211_outsb(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u8 *p = (__u8 *)port2adr(port); - - while (count--) { - *p = *((__u8 *)addr)++; - } -} - -void mpc1211_outsw(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u16 *p = (__u16 *)port2adr(port); - - while (count--) { - *p = *((__u16 *)addr)++; - } -} - -void mpc1211_outsl(unsigned long port, const void *addr, unsigned long count) -{ - volatile __u32 *p = (__u32 *)port2adr(port); - - while (count--) { - *p = *((__u32 *)addr)++; - } -} - -unsigned char mpc1211_readb(unsigned long addr) -{ - return *(volatile unsigned char *)addr; -} - -unsigned short mpc1211_readw(unsigned long addr) -{ - return *(volatile unsigned short *)addr; -} - -unsigned int mpc1211_readl(unsigned long addr) -{ - return *(volatile unsigned int *)addr; -} - -void mpc1211_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char *)addr = b; -} - -void mpc1211_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short *)addr = b; -} - -void mpc1211_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned int *)addr = b; -} - -unsigned long mpc1211_isa_port2addr(unsigned long offset) -{ - return port2adr(offset); -} diff -puN -L arch/sh/boards/mpc1211/mach.c arch/sh/boards/mpc1211/mach.c~linus /dev/null --- 25/arch/sh/boards/mpc1211/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,77 +0,0 @@ -/* - * linux/arch/sh/kernel/mach_mpc1211.c - * - * Copyright (C) 2001 Saito.K & Jeanne - * - * Machine vector for the Interface MPC-1211 - */ - -#include -#include - -#include -#include -#include - -#include - -void heartbeat_mpc1211(void); -void setup_mpc1211(void); -void init_mpc1211_IRQ(void); - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_mpc1211 __initmv = { - .mv_name = "MPC-1211", - - .mv_nr_irqs = 48, - - .mv_inb = mpc1211_inb, - .mv_inw = mpc1211_inw, - .mv_inl = mpc1211_inl, - .mv_outb = mpc1211_outb, - .mv_outw = mpc1211_outw, - .mv_outl = mpc1211_outl, - - .mv_inb_p = mpc1211_inb_p, - .mv_inw_p = mpc1211_inw, - .mv_inl_p = mpc1211_inl, - .mv_outb_p = mpc1211_outb_p, - .mv_outw_p = mpc1211_outw, - .mv_outl_p = mpc1211_outl, - - .mv_insb = mpc1211_insb, - .mv_insw = mpc1211_insw, - .mv_insl = mpc1211_insl, - .mv_outsb = mpc1211_outsb, - .mv_outsw = mpc1211_outsw, - .mv_outsl = mpc1211_outsl, - - .mv_readb = mpc1211_readb, - .mv_readw = mpc1211_readw, - .mv_readl = mpc1211_readl, - .mv_writeb = mpc1211_writeb, - .mv_writew = mpc1211_writew, - .mv_writel = mpc1211_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = mpc1211_isa_port2addr, - - .mv_irq_demux = mpc1211_irq_demux, - - .mv_init_arch = setup_mpc1211, - .mv_init_irq = init_mpc1211_IRQ, - // mv_init_pci = mpc1211_pcibios_init, - -#ifdef CONFIG_HEARTBEAT - .mv_heartbeat = heartbeat_mpc1211, -#endif - - .mv_rtc_gettimeofday = mpc1211_rtc_gettimeofday, - .mv_rtc_settimeofday = mpc1211_rtc_settimeofday, -}; -ALIAS_MV(mpc1211) diff -puN arch/sh/boards/mpc1211/Makefile~linus arch/sh/boards/mpc1211/Makefile --- 25/arch/sh/boards/mpc1211/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/mpc1211/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,7 +6,7 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o rtc.o led.o +obj-y := setup.o rtc.o led.o obj-$(CONFIG_PCI) += pci.o diff -puN arch/sh/boards/mpc1211/pci.c~linus arch/sh/boards/mpc1211/pci.c --- 25/arch/sh/boards/mpc1211/pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/mpc1211/pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -180,7 +180,8 @@ static void __devinit quirk_ali_ide_port /* Add future fixups here... */ struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, + PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports }, { 0 } }; @@ -273,8 +274,6 @@ static int __init map_mpc1211_irq(struct return irq; } -void __init pcibios_fixup(void) { /* Do nothing. */ } - void __init pcibios_fixup_irqs(void) { pci_fixup_irqs(mpc1211_swizzle, map_mpc1211_irq); diff -puN arch/sh/boards/mpc1211/rtc.c~linus arch/sh/boards/mpc1211/rtc.c --- 25/arch/sh/boards/mpc1211/rtc.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/mpc1211/rtc.c 2004-01-19 22:17:21.000000000 -0800 @@ -143,3 +143,10 @@ int mpc1211_rtc_settimeofday(const struc return set_rtc_mmss(nowtime); } + +void mpc1211_time_init(void) +{ + rtc_get_time = mpc1211_rtc_gettimeofday; + rtc_set_time = mpc1211_rtc_settimeofday; +} + diff -puN arch/sh/boards/mpc1211/setup.c~linus arch/sh/boards/mpc1211/setup.c --- 25/arch/sh/boards/mpc1211/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/mpc1211/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -13,7 +13,9 @@ #include #include +#include #include +#include #include @@ -54,10 +56,6 @@ const char *get_system_type(void) return "Interface MPC-1211(CTP/PCI/MPC-SH02)"; } -void platform_setup(void) -{ -} - static void __init pci_write_config(unsigned long busNo, unsigned long devNo, unsigned long fncNo, @@ -265,15 +263,16 @@ void __init init_mpc1211_IRQ(void) static void delay (void) { - volatile unsigned short tmp; - tmp = *(volatile unsigned short *) 0xa0000000; + volatile unsigned short tmp; + tmp = *(volatile unsigned short *) 0xa0000000; } static void delay1000 (void) { - int i; - for (i=0; i<1000; i++) - delay (); + int i; + + for (i=0; i<1000; i++) + delay (); } static int put_smb_blk(unsigned char *p, int address, int command, int no) @@ -316,21 +315,46 @@ static int put_smb_blk(unsigned char *p, return 0; } -void __init setup_mpc1211(void) +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_mpc1211 __initmv = { + .mv_nr_irqs = 48, + .mv_irq_demux = mpc1211_irq_demux, + .mv_init_irq = init_mpc1211_IRQ, + +#ifdef CONFIG_HEARTBEAT + .mv_heartbeat = heartbeat_mpc1211, +#endif +}; + +ALIAS_MV(mpc1211) + +/* arch/sh/boards/mpc1211/rtc.c */ +void mpc1211_time_init(void); + +int __init platform_setup(void) { - unsigned char spd_buf[128]; - pci_write_config(0,0,0,0x54, 0xb0b00000); + unsigned char spd_buf[128]; + + __set_io_port_base(PA_PCI_IO); + + pci_write_config(0,0,0,0x54, 0xb0b00000); -retry: - outb(ALI15X3_ABORT, SMBHSTCNT); - spd_buf[0] = 0x0c; - spd_buf[1] = 0x43; - spd_buf[2] = 0x7f; - spd_buf[3] = 0x03; - spd_buf[4] = 0x00; - spd_buf[5] = 0x03; - spd_buf[6] = 0x00; - if (put_smb_blk(spd_buf, 0x69, 0, 7) < 0) { - goto retry; - } + do { + outb(ALI15X3_ABORT, SMBHSTCNT); + spd_buf[0] = 0x0c; + spd_buf[1] = 0x43; + spd_buf[2] = 0x7f; + spd_buf[3] = 0x03; + spd_buf[4] = 0x00; + spd_buf[5] = 0x03; + spd_buf[6] = 0x00; + } while (put_smb_blk(spd_buf, 0x69, 0, 7) < 0); + + board_time_init = mpc1211_time_init; + + return 0; } + diff -puN arch/sh/boards/overdrive/mach.c~linus arch/sh/boards/overdrive/mach.c --- 25/arch/sh/boards/overdrive/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/overdrive/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -51,18 +51,6 @@ struct sh_machine_vector mv_od __initmv .mv_outsw = od_outsw, .mv_outsl = od_outsl, - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - - .mv_isa_port2addr = generic_isa_port2addr, - #ifdef CONFIG_PCI .mv_init_irq = init_overdrive_irq, #endif diff -puN arch/sh/boards/saturn/irq.c~linus arch/sh/boards/saturn/irq.c --- 25/arch/sh/boards/saturn/irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/saturn/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -7,8 +7,7 @@ */ #include #include -#include -#include +#include #include #include @@ -65,7 +64,7 @@ static inline void unmask_saturn_irq(uns mask = ctrl_inl(SATURN_IMR); mask &= ~saturn_irq_mask(irq_nr); - ctrl_outl(SATURN_IMR); + ctrl_outl(mask, SATURN_IMR); } static void disable_saturn_irq(unsigned int irq_nr) @@ -85,7 +84,7 @@ static void mask_and_ack_saturn_irq(unsi static void end_saturn_irq(unsigned int irq_nr) { - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) unmask_saturn_irq(irq_nr); } diff -puN -L arch/sh/boards/saturn/mach.c arch/sh/boards/saturn/mach.c~linus /dev/null --- 25/arch/sh/boards/saturn/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,59 +0,0 @@ -/* - * arch/sh/boards/saturn/mach.c - * - * machvec definitions for the Sega Saturn. - * - * Copyright (C) 2002 Paul Mundt - * - * Released under the terms of the GNU GPL v2.0. - */ -#include -#include -#include -#include -#include -#include - -/* - * The Machine Vector - */ -struct sh_machine_vector mv_saturn __initmv = { - .mv_nr_irqs = 80, /* Fix this later */ - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw_p, - .mv_inl_p = generic_inl_p, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw_p, - .mv_outl_p = generic_outl_p, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_isa_port2addr = saturn_isa_port2addr, - .mv_irq_demux = saturn_irq_demux, - - .mv_ioremap = saturn_ioremap, - .mv_iounmap = saturn_iounmap, -}; - -ALIAS_MV(saturn) - diff -puN arch/sh/boards/saturn/Makefile~linus arch/sh/boards/saturn/Makefile --- 25/arch/sh/boards/saturn/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/saturn/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,7 +6,7 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o irq.o +obj-y := setup.o io.o irq.o obj-$(CONFIG_SMP) += smp.o diff -puN arch/sh/boards/saturn/setup.c~linus arch/sh/boards/saturn/setup.c --- 25/arch/sh/boards/saturn/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/saturn/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -10,11 +10,32 @@ #include #include +#include +#include +#include + +extern int saturn_irq_demux(int irq_nr); + const char *get_system_type(void) { return "Sega Saturn"; } +/* + * The Machine Vector + */ +struct sh_machine_vector mv_saturn __initmv = { + .mv_nr_irqs = 80, /* Fix this later */ + + .mv_isa_port2addr = saturn_isa_port2addr, + .mv_irq_demux = saturn_irq_demux, + + .mv_ioremap = saturn_ioremap, + .mv_iounmap = saturn_iounmap, +}; + +ALIAS_MV(saturn) + int __init platform_setup(void) { return 0; diff -puN arch/sh/boards/saturn/smp.c~linus arch/sh/boards/saturn/smp.c --- 25/arch/sh/boards/saturn/smp.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/saturn/smp.c 2004-01-19 22:17:21.000000000 -0800 @@ -34,7 +34,7 @@ unsigned int __smp_probe_cpus(void) * addition to which, we treat them as write-only, since * reading from them will return undefined data. */ -static inline void smpc_slave_off(unsigned int cpu) +static inline void smpc_slave_stop(unsigned int cpu) { smpc_barrier(); ctrl_outb(1, SMPC_STATUS); @@ -43,7 +43,7 @@ static inline void smpc_slave_off(unsign smpc_barrier(); } -static inline void smpc_slave_on(unsigned int cpu) +static inline void smpc_slave_start(unsigned int cpu) { ctrl_outb(1, SMPC_STATUS); ctrl_outb(SMPC_CMD_SSHON, SMPC_COMMAND); diff -puN arch/sh/boards/se/770x/io.c~linus arch/sh/boards/se/770x/io.c --- 25/arch/sh/boards/se/770x/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/se/770x/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: io.c,v 1.1.2.2 2002/01/20 05:03:25 mrbrown Exp $ +/* $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ * * linux/arch/sh/kernel/io_se.c * @@ -189,36 +189,6 @@ void se_outsl(unsigned long port, const maybebadio(outsw, port); } -unsigned char se_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short se_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int se_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void se_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void se_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void se_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - /* Map ISA bus address to the real address. Only for PCMCIA. */ /* ISA page descriptor. */ diff -puN arch/sh/boards/se/770x/mach.c~linus arch/sh/boards/se/770x/mach.c --- 25/arch/sh/boards/se/770x/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/se/770x/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -56,16 +56,6 @@ struct sh_machine_vector mv_se __initmv .mv_outsw = se_outsw, .mv_outsl = se_outsl, - .mv_readb = se_readb, - .mv_readw = se_readw, - .mv_readl = se_readl, - .mv_writeb = se_writeb, - .mv_writew = se_writew, - .mv_writel = se_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - .mv_isa_port2addr = se_isa_port2addr, .mv_init_irq = init_se_IRQ, diff -puN arch/sh/boards/se/7751/io.c~linus arch/sh/boards/se/7751/io.c --- 25/arch/sh/boards/se/7751/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/se/7751/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -201,76 +201,16 @@ void sh7751se_outl(unsigned int value, u maybebadio(outl, port); } -void sh7751se_insb(unsigned long port, void *addr, unsigned long count) -{ - unsigned char *p = addr; - while (count--) *p++ = sh7751se_inb(port); -} - -void sh7751se_insw(unsigned long port, void *addr, unsigned long count) -{ - unsigned short *p = addr; - while (count--) *p++ = sh7751se_inw(port); -} - void sh7751se_insl(unsigned long port, void *addr, unsigned long count) { maybebadio(insl, port); } -void sh7751se_outsb(unsigned long port, const void *addr, unsigned long count) -{ - unsigned char *p = (unsigned char*)addr; - while (count--) sh7751se_outb(*p++, port); -} - -void sh7751se_outsw(unsigned long port, const void *addr, unsigned long count) -{ - unsigned short *p = (unsigned short*)addr; - while (count--) sh7751se_outw(*p++, port); -} - void sh7751se_outsl(unsigned long port, const void *addr, unsigned long count) { maybebadio(outsw, port); } -/* For read/write calls, just copy generic (pass-thru); PCIMBR is */ -/* already set up. For a larger memory space, these would need to */ -/* reset PCIMBR as needed on a per-call basis... */ - -unsigned char sh7751se_readb(unsigned long addr) -{ - return *(volatile unsigned char*)addr; -} - -unsigned short sh7751se_readw(unsigned long addr) -{ - return *(volatile unsigned short*)addr; -} - -unsigned int sh7751se_readl(unsigned long addr) -{ - return *(volatile unsigned long*)addr; -} - -void sh7751se_writeb(unsigned char b, unsigned long addr) -{ - *(volatile unsigned char*)addr = b; -} - -void sh7751se_writew(unsigned short b, unsigned long addr) -{ - *(volatile unsigned short*)addr = b; -} - -void sh7751se_writel(unsigned int b, unsigned long addr) -{ - *(volatile unsigned long*)addr = b; -} - - - /* Map ISA bus address to the real address. Only for PCMCIA. */ /* ISA page descriptor. */ diff -puN arch/sh/boards/se/7751/mach.c~linus arch/sh/boards/se/7751/mach.c --- 25/arch/sh/boards/se/7751/mach.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/se/7751/mach.c 2004-01-19 22:17:21.000000000 -0800 @@ -42,23 +42,9 @@ struct sh_machine_vector mv_7751se __ini .mv_outw_p = sh7751se_outw, .mv_outl_p = sh7751se_outl, - .mv_insb = sh7751se_insb, - .mv_insw = sh7751se_insw, .mv_insl = sh7751se_insl, - .mv_outsb = sh7751se_outsb, - .mv_outsw = sh7751se_outsw, .mv_outsl = sh7751se_outsl, - .mv_readb = sh7751se_readb, - .mv_readw = sh7751se_readw, - .mv_readl = sh7751se_readl, - .mv_writeb = sh7751se_writeb, - .mv_writew = sh7751se_writew, - .mv_writel = sh7751se_writel, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, - .mv_isa_port2addr = sh7751se_isa_port2addr, .mv_init_irq = init_7751se_IRQ, diff -puN arch/sh/boards/se/7751/pci.c~linus arch/sh/boards/se/7751/pci.c --- 25/arch/sh/boards/se/7751/pci.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/se/7751/pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -95,12 +95,11 @@ int __init pcibios_init_platform(void) /* * Set the MBR so PCI address is one-to-one with window, - * meaning all calls go straight through... use ifdef to + * meaning all calls go straight through... use BUG_ON to * catch erroneous assumption. */ -#if PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE -#error One-to-one assumption for PCI memory mapping is wrong!?!?!? -#endif + BUG_ON(PCIBIOS_MIN_MEM != SH7751_PCI_MEMORY_BASE); + PCIC_WRITE(SH7751_PCIMBR, PCIBIOS_MIN_MEM); /* Set IOBR for window containing area specified in pci.h */ @@ -125,3 +124,25 @@ int __init pcibios_map_platform_irq(u8 s return -1; } } + +static struct resource sh7751_io_resource = { + .name = "SH7751 IO", + .start = SH7751_PCI_IO_BASE, + .end = SH7751_PCI_IO_BASE + SH7751_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO +}; + +static struct resource sh7751_mem_resource = { + .name = "SH7751 mem", + .start = SH7751_PCI_MEMORY_BASE, + .end = SH7751_PCI_MEMORY_BASE + SH7751_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +extern struct pci_ops sh7751_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { NULL, NULL, NULL, 0, 0 }, +}; + diff -puN -L arch/sh/boards/sh2000/io.c arch/sh/boards/sh2000/io.c~linus /dev/null --- 25/arch/sh/boards/sh2000/io.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,19 +0,0 @@ -/* - * I/O routine for SH-2000 - */ -#include -#include -#include - -#define IDE_OFFSET 0xb6200000 -#define NIC_OFFSET 0xb6000000 -#define EXTBUS_OFFSET 0xba000000 - -unsigned long sh2000_isa_port2addr(unsigned long offset) -{ - if((offset & ~7) == 0x1f0 || offset == 0x3f6) - return IDE_OFFSET + offset; - else if((offset & ~0x1f) == 0x300) - return NIC_OFFSET + offset; - return EXTBUS_OFFSET + offset; -} diff -puN -L arch/sh/boards/sh2000/mach.c arch/sh/boards/sh2000/mach.c~linus /dev/null --- 25/arch/sh/boards/sh2000/mach.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,57 +0,0 @@ -/* - * linux/arch/sh/boards/sh2000/mach.c - * - * Original copyright message: - * Copyright (C) 2001 SUGIOKA Tochinobu - * - * Split into mach.c from setup.c by M. R. Brown - */ - -#include -#include -#include -#include -#include -#include - -/* - * The Machine Vector - */ - -struct sh_machine_vector mv_sh2000 __initmv = { - .mv_nr_irqs = 80, - - .mv_inb = generic_inb, - .mv_inw = generic_inw, - .mv_inl = generic_inl, - .mv_outb = generic_outb, - .mv_outw = generic_outw, - .mv_outl = generic_outl, - - .mv_inb_p = generic_inb_p, - .mv_inw_p = generic_inw_p, - .mv_inl_p = generic_inl_p, - .mv_outb_p = generic_outb_p, - .mv_outw_p = generic_outw_p, - .mv_outl_p = generic_outl_p, - - .mv_insb = generic_insb, - .mv_insw = generic_insw, - .mv_insl = generic_insl, - .mv_outsb = generic_outsb, - .mv_outsw = generic_outsw, - .mv_outsl = generic_outsl, - - .mv_readb = generic_readb, - .mv_readw = generic_readw, - .mv_readl = generic_readl, - .mv_writeb = generic_writeb, - .mv_writew = generic_writew, - .mv_writel = generic_writel, - - .mv_isa_port2addr = sh2000_isa_port2addr, - - .mv_ioremap = generic_ioremap, - .mv_iounmap = generic_iounmap, -}; -ALIAS_MV(sh2000) diff -puN arch/sh/boards/sh2000/Makefile~linus arch/sh/boards/sh2000/Makefile --- 25/arch/sh/boards/sh2000/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/sh2000/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o setup.o io.o +obj-y := setup.o diff -puN arch/sh/boards/sh2000/setup.c~linus arch/sh/boards/sh2000/setup.c --- 25/arch/sh/boards/sh2000/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boards/sh2000/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -12,6 +12,8 @@ #include #include +#include +#include #define CF_CIS_BASE 0xb4200000 @@ -20,11 +22,34 @@ #define PORT_ICR1 0xa4000010 #define PORT_IRR0 0xa4000004 +#define IDE_OFFSET 0xb6200000 +#define NIC_OFFSET 0xb6000000 +#define EXTBUS_OFFSET 0xba000000 + + const char *get_system_type(void) { return "sh2000"; } +static unsigned long sh2000_isa_port2addr(unsigned long offset) +{ + if((offset & ~7) == 0x1f0 || offset == 0x3f6) + return IDE_OFFSET + offset; + else if((offset & ~0x1f) == 0x300) + return NIC_OFFSET + offset; + return EXTBUS_OFFSET + offset; +} + +/* + * The Machine Vector + */ +struct sh_machine_vector mv_sh2000 __initmv = { + .mv_nr_irqs = 80, + .mv_isa_port2addr = sh2000_isa_port2addr, +}; +ALIAS_MV(sh2000) + /* * Initialize the board */ diff -puN /dev/null arch/sh/boards/snapgear/io.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/snapgear/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,226 @@ +/* + * linux/arch/sh/kernel/io_7751se.c + * + * Copyright (C) 2002 David McCullough + * Copyright (C) 2001 Ian da Silva, Jeremy Siegel + * Based largely on io_se.c. + * + * I/O routine for Hitachi 7751 SolutionEngine. + * + * Initial version only to support LAN access; some + * placeholder code from io_se.c left in with the + * expectation of later SuperIO and PCMCIA access. + */ + +#include +#include +#include +#include +#include + +#include +#include "../../drivers/pci/pci-sh7751.h" + +#ifdef CONFIG_SH_SECUREEDGE5410 +unsigned short secureedge5410_ioport; +#endif + +/* + * The SnapGear uses the built-in PCI controller (PCIC) + * of the 7751 processor + */ + +#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) +#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) +#define PCI_IO_AREA SH7751_PCI_IO_BASE +#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE + + +#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) + + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + + +static inline volatile __u16 *port2adr(unsigned int port) +{ +#if 0 + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); +#endif + maybebadio(name,(unsigned long)port); + return (volatile __u16*)port; +} + + +/* In case someone configures the kernel w/o PCI support: in that */ +/* scenario, don't ever bother to check for PCI-window addresses */ + +/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ +#if defined(CONFIG_PCI) +#define CHECK_SH7751_PCIIO(port) \ + ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) +#else +#define CHECK_SH7751_PCIIO(port) (0) +#endif + +/* + * General outline: remap really low stuff [eventually] to SuperIO, + * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) + * is mapped through the PCI IO window. Stuff with high bits (PXSEG) + * should be way beyond the window, and is used w/o translation for + * compatibility. + */ + +unsigned char snapgear_inb(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned char *)PCI_IOMAP(port); + else + return (*port2adr(port))&0xff; +} + + +unsigned char snapgear_inb_p(unsigned long port) +{ + unsigned char v; + + if (PXSEG(port)) + v = *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + v = *(volatile unsigned char *)PCI_IOMAP(port); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + + +unsigned short snapgear_inw(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned short *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned short *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inw, port); + return 0; +} + + +unsigned int snapgear_inl(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned long *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned int *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else + maybebadio(inl, port); + return 0; +} + + +void snapgear_outb(unsigned char value, unsigned long port) +{ + + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; +} + + +void snapgear_outb_p(unsigned char value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else + *(port2adr(port)) = value; + delay(); +} + + +void snapgear_outw(unsigned short value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned short *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned short *)PCI_IOMAP(port)) = value; + else if (port >= 0x2000) + *port2adr(port) = value; + else + maybebadio(outw, port); +} + + +void snapgear_outl(unsigned int value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned long *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned long*)PCI_IOMAP(port)) = value; + else + maybebadio(outl, port); +} + +void snapgear_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void snapgear_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + + +#if 0 +static int sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); +#if 0 + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); +#endif + return 0; +} +#endif + +unsigned long snapgear_isa_port2addr(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -puN /dev/null arch/sh/boards/snapgear/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/snapgear/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,10 @@ +# +# Makefile for the SnapGear specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := setup.o io.o rtc.o + diff -puN /dev/null arch/sh/boards/snapgear/rtc.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/snapgear/rtc.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,333 @@ +/****************************************************************************/ +/* + * linux/arch/sh/boards/snapgear/rtc.c -- Secureedge5410 RTC code + * + * Copyright (C) 2002 David McCullough + * Copyright (C) 2003 Paul Mundt + * + * The SecureEdge5410 can have one of 2 real time clocks, the SH + * built in version or the preferred external DS1302. Here we work out + * each to see what we have and then run with it. + */ +/****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/****************************************************************************/ + +static int use_ds1302 = 0; + +/****************************************************************************/ +/* + * we need to implement a DS1302 driver here that can operate in + * conjunction with the builtin rtc driver which is already quite friendly + */ +/*****************************************************************************/ + +#define RTC_CMD_READ 0x81 /* Read command */ +#define RTC_CMD_WRITE 0x80 /* Write command */ + +#define RTC_ADDR_YEAR 0x06 /* Address of year register */ +#define RTC_ADDR_DAY 0x05 /* Address of day of week register */ +#define RTC_ADDR_MON 0x04 /* Address of month register */ +#define RTC_ADDR_DATE 0x03 /* Address of day of month register */ +#define RTC_ADDR_HOUR 0x02 /* Address of hour register */ +#define RTC_ADDR_MIN 0x01 /* Address of minute register */ +#define RTC_ADDR_SEC 0x00 /* Address of second register */ + +#define RTC_RESET 0x1000 +#define RTC_IODATA 0x0800 +#define RTC_SCLK 0x0400 + +#define set_dirp(x) +#define get_dirp(x) 0 +#define set_dp(x) SECUREEDGE_WRITE_IOPORT(x, 0x1c00) +#define get_dp(x) SECUREEDGE_READ_IOPORT() + +static void ds1302_sendbits(unsigned int val) +{ + int i; + + for (i = 8; (i); i--, val >>= 1) { + set_dp((get_dp() & ~RTC_IODATA) | ((val & 0x1) ? RTC_IODATA : 0)); + set_dp(get_dp() | RTC_SCLK); // clock high + set_dp(get_dp() & ~RTC_SCLK); // clock low + } +} + +static unsigned int ds1302_recvbits(void) +{ + unsigned int val; + int i; + + for (i = 0, val = 0; (i < 8); i++) { + val |= (((get_dp() & RTC_IODATA) ? 1 : 0) << i); + set_dp(get_dp() | RTC_SCLK); // clock high + set_dp(get_dp() & ~RTC_SCLK); // clock low + } + return(val); +} + +static unsigned int ds1302_readbyte(unsigned int addr) +{ + unsigned int val; + unsigned long flags; + +#if 0 + printk("SnapGear RTC: ds1302_readbyte(addr=%x)\n", addr); +#endif + + local_irq_save(flags); + set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); + set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); + + set_dp(get_dp() | RTC_RESET); + ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_READ); + set_dirp(get_dirp() & ~RTC_IODATA); + val = ds1302_recvbits(); + set_dp(get_dp() & ~RTC_RESET); + local_irq_restore(flags); + + return(val); +} + +static void ds1302_writebyte(unsigned int addr, unsigned int val) +{ + unsigned long flags; + +#if 0 + printk("SnapGear RTC: ds1302_writebyte(addr=%x)\n", addr); +#endif + + local_irq_save(flags); + set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); + set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); + set_dp(get_dp() | RTC_RESET); + ds1302_sendbits(((addr & 0x3f) << 1) | RTC_CMD_WRITE); + ds1302_sendbits(val); + set_dp(get_dp() & ~RTC_RESET); + local_irq_restore(flags); +} + +static void ds1302_reset(void) +{ + unsigned long flags; + /* Hardware dependant reset/init */ + local_irq_save(flags); + set_dirp(get_dirp() | RTC_RESET | RTC_IODATA | RTC_SCLK); + set_dp(get_dp() & ~(RTC_RESET | RTC_IODATA | RTC_SCLK)); + local_irq_restore(flags); +} + +/*****************************************************************************/ + +static inline int bcd2int(int val) +{ + return((((val & 0xf0) >> 4) * 10) + (val & 0xf)); +} + +static inline int int2bcd(int val) +{ + return(((val / 10) << 4) + (val % 10)); +} + +/*****************************************************************************/ +/* + * Write and Read some RAM in the DS1302, if it works assume it's there + * Otherwise use the SH4 internal RTC + */ + +void snapgear_rtc_gettimeofday(struct timespec *); +int snapgear_rtc_settimeofday(const time_t); + +void __init secureedge5410_rtc_init(void) +{ + unsigned char *test = "snapgear"; + int i; + + ds1302_reset(); + + use_ds1302 = 1; + + for (i = 0; test[i]; i++) + ds1302_writebyte(32 + i, test[i]); + + for (i = 0; test[i]; i++) + if (ds1302_readbyte(32 + i) != test[i]) { + use_ds1302 = 0; + break; + } + + if (use_ds1302) { + rtc_get_time = snapgear_rtc_gettimeofday; + rtc_set_time = snapgear_rtc_settimeofday; + } else { + rtc_get_time = sh_rtc_gettimeofday; + rtc_set_time = sh_rtc_settimeofday; + } + + printk("SnapGear RTC: using %s rtc.\n", use_ds1302 ? "ds1302" : "internal"); +} + +/****************************************************************************/ +/* + * our generic interface that chooses the correct code to use + */ + +void snapgear_rtc_gettimeofday(struct timespec *ts) +{ + unsigned int sec, min, hr, day, mon, yr; + + if (!use_ds1302) { + sh_rtc_gettimeofday(ts); + return; + } + + sec = bcd2int(ds1302_readbyte(RTC_ADDR_SEC)); + min = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); + hr = bcd2int(ds1302_readbyte(RTC_ADDR_HOUR)); + day = bcd2int(ds1302_readbyte(RTC_ADDR_DATE)); + mon = bcd2int(ds1302_readbyte(RTC_ADDR_MON)); + yr = bcd2int(ds1302_readbyte(RTC_ADDR_YEAR)); + +bad_time: + if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || + hr > 23 || min > 59 || sec > 59) { + printk(KERN_ERR + "SnapGear RTC: invalid value, resetting to 1 Jan 2000\n"); + ds1302_writebyte(RTC_ADDR_MIN, min = 0); + ds1302_writebyte(RTC_ADDR_HOUR, hr = 0); + ds1302_writebyte(RTC_ADDR_DAY, 7); + ds1302_writebyte(RTC_ADDR_DATE, day = 1); + ds1302_writebyte(RTC_ADDR_MON, mon = 1); + ds1302_writebyte(RTC_ADDR_YEAR, yr = 0); + ds1302_writebyte(RTC_ADDR_SEC, sec = 0); + } + + ts->tv_sec = mktime(2000 + yr, mon, day, hr, min, sec); + if (ts->tv_sec < 0) { +#if 0 + printk("BAD TIME %d %d %d %d %d %d\n", yr, mon, day, hr, min, sec); +#endif + yr = 100; + goto bad_time; + } + ts->tv_nsec = 0; +} + +int snapgear_rtc_settimeofday(const time_t secs) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + unsigned long nowtime; + + if (!use_ds1302) + return sh_rtc_settimeofday(secs); + +/* + * This is called direct from the kernel timer handling code. + * It is supposed to synchronize the kernel clock to the RTC. + */ + + nowtime = secs; + +#if 1 + printk("SnapGear RTC: snapgear_rtc_settimeofday(nowtime=%ld)\n", nowtime); +#endif + + /* STOP RTC */ + ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80); + + cmos_minutes = bcd2int(ds1302_readbyte(RTC_ADDR_MIN)); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + ds1302_writebyte(RTC_ADDR_MIN, int2bcd(real_minutes)); + ds1302_writebyte(RTC_ADDR_SEC, int2bcd(real_seconds)); + } else { + printk(KERN_WARNING + "SnapGear RTC: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + /* START RTC */ + ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80); + return(0); +} + +unsigned char secureedge5410_cmos_read(int addr) +{ + unsigned char val = 0; + + if (!use_ds1302) + return(__CMOS_READ(addr, w)); + + switch(addr) { + case RTC_SECONDS: val = ds1302_readbyte(RTC_ADDR_SEC); break; + case RTC_SECONDS_ALARM: break; + case RTC_MINUTES: val = ds1302_readbyte(RTC_ADDR_MIN); break; + case RTC_MINUTES_ALARM: break; + case RTC_HOURS: val = ds1302_readbyte(RTC_ADDR_HOUR); break; + case RTC_HOURS_ALARM: break; + case RTC_DAY_OF_WEEK: val = ds1302_readbyte(RTC_ADDR_DAY); break; + case RTC_DAY_OF_MONTH: val = ds1302_readbyte(RTC_ADDR_DATE); break; + case RTC_MONTH: val = ds1302_readbyte(RTC_ADDR_MON); break; + case RTC_YEAR: val = ds1302_readbyte(RTC_ADDR_YEAR); break; + case RTC_REG_A: /* RTC_FREQ_SELECT */ break; + case RTC_REG_B: /* RTC_CONTROL */ break; + case RTC_REG_C: /* RTC_INTR_FLAGS */ break; + case RTC_REG_D: val = RTC_VRT /* RTC_VALID */; break; + default: break; + } + + return(val); +} + +void secureedge5410_cmos_write(unsigned char val, int addr) +{ + if (!use_ds1302) { + __CMOS_WRITE(val, addr, w); + return; + } + + switch(addr) { + case RTC_SECONDS: ds1302_writebyte(RTC_ADDR_SEC, val); break; + case RTC_SECONDS_ALARM: break; + case RTC_MINUTES: ds1302_writebyte(RTC_ADDR_MIN, val); break; + case RTC_MINUTES_ALARM: break; + case RTC_HOURS: ds1302_writebyte(RTC_ADDR_HOUR, val); break; + case RTC_HOURS_ALARM: break; + case RTC_DAY_OF_WEEK: ds1302_writebyte(RTC_ADDR_DAY, val); break; + case RTC_DAY_OF_MONTH: ds1302_writebyte(RTC_ADDR_DATE, val); break; + case RTC_MONTH: ds1302_writebyte(RTC_ADDR_MON, val); break; + case RTC_YEAR: ds1302_writebyte(RTC_ADDR_YEAR, val); break; + case RTC_REG_A: /* RTC_FREQ_SELECT */ break; + case RTC_REG_B: /* RTC_CONTROL */ break; + case RTC_REG_C: /* RTC_INTR_FLAGS */ break; + case RTC_REG_D: /* RTC_VALID */ break; + default: break; + } +} + +/****************************************************************************/ diff -puN /dev/null arch/sh/boards/snapgear/setup.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/snapgear/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,220 @@ +/****************************************************************************/ +/* + * linux/arch/sh/boards/snapgear/setup.c + * + * Copyright (C) 2002 David McCullough + * Copyright (C) 2003 Paul Mundt + * + * Based on files with the following comments: + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Modified for 7751 Solution Engine by + * Ian da Silva and Jeremy Siegel, 2001. + */ +/****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern void (*board_time_init)(void); +extern void secureedge5410_rtc_init(void); +extern void pcibios_init(void); + +/****************************************************************************/ +/* + * EraseConfig handling functions + */ + +static irqreturn_t eraseconfig_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile char dummy __attribute__((unused)) = * (volatile char *) 0xb8000000; + + printk("SnapGear: erase switch interrupt!\n"); + + return IRQ_HANDLED; +} + +static int __init eraseconfig_init(void) +{ + printk("SnapGear: EraseConfig init\n"); + /* Setup "EraseConfig" switch on external IRQ 0 */ + if (request_irq(IRL0_IRQ, eraseconfig_interrupt, SA_INTERRUPT, + "Erase Config", NULL)) + printk("SnapGear: failed to register IRQ%d for Reset witch\n", + IRL0_IRQ); + else + printk("SnapGear: registered EraseConfig switch on IRQ%d\n", + IRL0_IRQ); + return(0); +} + +module_init(eraseconfig_init); + +/****************************************************************************/ +/* + * Initialize IRQ setting + * + * IRL0 = erase switch + * IRL1 = eth0 + * IRL2 = eth1 + * IRL3 = crypto + */ + +static void __init init_snapgear_IRQ(void) +{ + /* enable individual interrupt mode for externals */ + ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR); + + printk("Setup SnapGear IRQ/IPR ...\n"); + + make_ipr_irq(IRL0_IRQ, IRL0_IPR_ADDR, IRL0_IPR_POS, IRL0_PRIORITY); + make_ipr_irq(IRL1_IRQ, IRL1_IPR_ADDR, IRL1_IPR_POS, IRL1_PRIORITY); + make_ipr_irq(IRL2_IRQ, IRL2_IPR_ADDR, IRL2_IPR_POS, IRL2_PRIORITY); + make_ipr_irq(IRL3_IRQ, IRL3_IPR_ADDR, IRL3_IPR_POS, IRL3_PRIORITY); +} + +/****************************************************************************/ +/* + * Fast poll interrupt simulator. + */ + +/* + * Leave all of the fast timer/fast poll stuff commented out for now, since + * it's not clear whether it actually works or not. Since it wasn't being used + * at all in 2.4, we'll assume it's not sane for 2.6 either.. -- PFM + */ +#if 0 +#define FAST_POLL 1000 +//#define FAST_POLL_INTR + +#define FASTTIMER_IRQ 17 +#define FASTTIMER_IPR_ADDR INTC_IPRA +#define FASTTIMER_IPR_POS 2 +#define FASTTIMER_PRIORITY 3 + +#ifdef FAST_POLL_INTR +#define TMU1_TCR_INIT 0x0020 +#else +#define TMU1_TCR_INIT 0 +#endif +#define TMU_TSTR_INIT 1 +#define TMU1_TCR_CALIB 0x0000 +#define TMU_TOCR 0xffd80000 /* Byte access */ +#define TMU_TSTR 0xffd80004 /* Byte access */ +#define TMU1_TCOR 0xffd80014 /* Long access */ +#define TMU1_TCNT 0xffd80018 /* Long access */ +#define TMU1_TCR 0xffd8001c /* Word access */ + + +#ifdef FAST_POLL_INTR +static void fast_timer_irq(int irq, void *dev_instance, struct pt_regs *regs) +{ + unsigned long timer_status; + timer_status = ctrl_inw(TMU1_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU1_TCR); +} +#endif + +/* + * return the current ticks on the fast timer + */ + +unsigned long fast_timer_count(void) +{ + return(ctrl_inl(TMU1_TCNT)); +} + +/* + * setup a fast timer for profiling etc etc + */ + +static void setup_fast_timer() +{ + unsigned long interval; + +#ifdef FAST_POLL_INTR + interval = (current_cpu_data.module_clock/4 + FAST_POLL/2) / FAST_POLL; + + make_ipr_irq(FASTTIMER_IRQ, FASTTIMER_IPR_ADDR, FASTTIMER_IPR_POS, + FASTTIMER_PRIORITY); + + printk("SnapGear: %dHz fast timer on IRQ %d\n",FAST_POLL,FASTTIMER_IRQ); + + if (request_irq(FASTTIMER_IRQ, fast_timer_irq, 0, "SnapGear fast timer", + NULL) != 0) + printk("%s(%d): request_irq() failed?\n", __FILE__, __LINE__); +#else + printk("SnapGear: fast timer running\n",FAST_POLL,FASTTIMER_IRQ); + interval = 0xffffffff; +#endif + + ctrl_outb(ctrl_inb(TMU_TSTR) & ~0x2, TMU_TSTR); /* disable timer 1 */ + ctrl_outw(TMU1_TCR_INIT, TMU1_TCR); + ctrl_outl(interval, TMU1_TCOR); + ctrl_outl(interval, TMU1_TCNT); + ctrl_outb(ctrl_inb(TMU_TSTR) | 0x2, TMU_TSTR); /* enable timer 1 */ + + printk("Timer count 1 = 0x%x\n", fast_timer_count()); + udelay(1000); + printk("Timer count 2 = 0x%x\n", fast_timer_count()); +} +#endif + +/****************************************************************************/ + +const char *get_system_type(void) +{ + return "SnapGear SecureEdge5410"; +} + +/* + * The Machine Vector + */ + +struct sh_machine_vector mv_snapgear __initmv = { + .mv_nr_irqs = 72, + + .mv_inb = snapgear_inb, + .mv_inw = snapgear_inw, + .mv_inl = snapgear_inl, + .mv_outb = snapgear_outb, + .mv_outw = snapgear_outw, + .mv_outl = snapgear_outl, + + .mv_inb_p = snapgear_inb_p, + .mv_inw_p = snapgear_inw, + .mv_inl_p = snapgear_inl, + .mv_outb_p = snapgear_outb_p, + .mv_outw_p = snapgear_outw, + .mv_outl_p = snapgear_outl, + + .mv_isa_port2addr = snapgear_isa_port2addr, + + .mv_init_irq = init_snapgear_IRQ, +}; +ALIAS_MV(snapgear) + +/* + * Initialize the board + */ + +int __init platform_setup(void) +{ + board_time_init = secureedge5410_rtc_init; + + return 0; +} + diff -puN /dev/null arch/sh/boards/systemh/io.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/systemh/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,283 @@ +/* + * linux/arch/sh/boards/systemh/io.c + * + * Copyright (C) 2001 Ian da Silva, Jeremy Siegel + * Based largely on io_se.c. + * + * I/O routine for Hitachi 7751 Systemh. + * + */ + +#include +#include +#include +#include +#include + +#include +#include "../../drivers/pci/pci-sh7751.h" + +/* + * The 7751 SystemH Engine uses the built-in PCI controller (PCIC) + * of the 7751 processor, and has a SuperIO accessible on its memory + * bus. + */ + +#define PCIIOBR (volatile long *)PCI_REG(SH7751_PCIIOBR) +#define PCIMBR (volatile long *)PCI_REG(SH7751_PCIMBR) +#define PCI_IO_AREA SH7751_PCI_IO_BASE +#define PCI_MEM_AREA SH7751_PCI_CONFIG_BASE + +#define PCI_IOMAP(adr) (PCI_IO_AREA + (adr & ~SH7751_PCIIOBR_MASK)) +#define ETHER_IOMAP(adr) (0xB3000000 + (adr)) /*map to 16bits access area + of smc lan chip*/ + +#define maybebadio(name,port) \ + printk("bad PC-like io %s for port 0x%lx at 0x%08x\n", \ + #name, (port), (__u32) __builtin_return_address(0)) + +static inline void delay(void) +{ + ctrl_inw(0xa0000000); +} + +static inline volatile __u16 * +port2adr(unsigned int port) +{ + if (port >= 0x2000) + return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000)); +#if 0 + else + return (volatile __u16 *) (PA_SUPERIO + (port << 1)); +#endif + maybebadio(name,(unsigned long)port); + return (volatile __u16*)port; +} + +/* In case someone configures the kernel w/o PCI support: in that */ +/* scenario, don't ever bother to check for PCI-window addresses */ + +/* NOTE: WINDOW CHECK MAY BE A BIT OFF, HIGH PCIBIOS_MIN_IO WRAPS? */ +#if defined(CONFIG_PCI) +#define CHECK_SH7751_PCIIO(port) \ + ((port >= PCIBIOS_MIN_IO) && (port < (PCIBIOS_MIN_IO + SH7751_PCI_IO_SIZE))) +#else +#define CHECK_SH7751_PCIIO(port) (0) +#endif + +/* + * General outline: remap really low stuff [eventually] to SuperIO, + * stuff in PCI IO space (at or above window at pci.h:PCIBIOS_MIN_IO) + * is mapped through the PCI IO window. Stuff with high bits (PXSEG) + * should be way beyond the window, and is used w/o translation for + * compatibility. + */ +unsigned char sh7751systemh_inb(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned char *)PCI_IOMAP(port); + else if (port <= 0x3F1) + return *(volatile unsigned char *)ETHER_IOMAP(port); + else + return (*port2adr(port))&0xff; +} + +unsigned char sh7751systemh_inb_p(unsigned long port) +{ + unsigned char v; + + if (PXSEG(port)) + v = *(volatile unsigned char *)port; + else if (CHECK_SH7751_PCIIO(port)) + v = *(volatile unsigned char *)PCI_IOMAP(port); + else if (port <= 0x3F1) + v = *(volatile unsigned char *)ETHER_IOMAP(port); + else + v = (*port2adr(port))&0xff; + delay(); + return v; +} + +unsigned short sh7751systemh_inw(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned short *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned short *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else if (port <= 0x3F1) + return *(volatile unsigned int *)ETHER_IOMAP(port); + else + maybebadio(inw, port); + return 0; +} + +unsigned int sh7751systemh_inl(unsigned long port) +{ + if (PXSEG(port)) + return *(volatile unsigned long *)port; + else if (CHECK_SH7751_PCIIO(port)) + return *(volatile unsigned int *)PCI_IOMAP(port); + else if (port >= 0x2000) + return *port2adr(port); + else if (port <= 0x3F1) + return *(volatile unsigned int *)ETHER_IOMAP(port); + else + maybebadio(inl, port); + return 0; +} + +void sh7751systemh_outb(unsigned char value, unsigned long port) +{ + + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else if (port <= 0x3F1) + *(volatile unsigned char *)ETHER_IOMAP(port) = value; + else + *(port2adr(port)) = value; +} + +void sh7751systemh_outb_p(unsigned char value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned char *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned char*)PCI_IOMAP(port)) = value; + else if (port <= 0x3F1) + *(volatile unsigned char *)ETHER_IOMAP(port) = value; + else + *(port2adr(port)) = value; + delay(); +} + +void sh7751systemh_outw(unsigned short value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned short *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned short *)PCI_IOMAP(port)) = value; + else if (port >= 0x2000) + *port2adr(port) = value; + else if (port <= 0x3F1) + *(volatile unsigned short *)ETHER_IOMAP(port) = value; + else + maybebadio(outw, port); +} + +void sh7751systemh_outl(unsigned int value, unsigned long port) +{ + if (PXSEG(port)) + *(volatile unsigned long *)port = value; + else if (CHECK_SH7751_PCIIO(port)) + *((unsigned long*)PCI_IOMAP(port)) = value; + else + maybebadio(outl, port); +} + +void sh7751systemh_insb(unsigned long port, void *addr, unsigned long count) +{ + unsigned char *p = addr; + while (count--) *p++ = sh7751systemh_inb(port); +} + +void sh7751systemh_insw(unsigned long port, void *addr, unsigned long count) +{ + unsigned short *p = addr; + while (count--) *p++ = sh7751systemh_inw(port); +} + +void sh7751systemh_insl(unsigned long port, void *addr, unsigned long count) +{ + maybebadio(insl, port); +} + +void sh7751systemh_outsb(unsigned long port, const void *addr, unsigned long count) +{ + unsigned char *p = (unsigned char*)addr; + while (count--) sh7751systemh_outb(*p++, port); +} + +void sh7751systemh_outsw(unsigned long port, const void *addr, unsigned long count) +{ + unsigned short *p = (unsigned short*)addr; + while (count--) sh7751systemh_outw(*p++, port); +} + +void sh7751systemh_outsl(unsigned long port, const void *addr, unsigned long count) +{ + maybebadio(outsw, port); +} + +/* For read/write calls, just copy generic (pass-thru); PCIMBR is */ +/* already set up. For a larger memory space, these would need to */ +/* reset PCIMBR as needed on a per-call basis... */ + +unsigned char sh7751systemh_readb(unsigned long addr) +{ + return *(volatile unsigned char*)addr; +} + +unsigned short sh7751systemh_readw(unsigned long addr) +{ + return *(volatile unsigned short*)addr; +} + +unsigned int sh7751systemh_readl(unsigned long addr) +{ + return *(volatile unsigned long*)addr; +} + +void sh7751systemh_writeb(unsigned char b, unsigned long addr) +{ + *(volatile unsigned char*)addr = b; +} + +void sh7751systemh_writew(unsigned short b, unsigned long addr) +{ + *(volatile unsigned short*)addr = b; +} + +void sh7751systemh_writel(unsigned int b, unsigned long addr) +{ + *(volatile unsigned long*)addr = b; +} + + + +/* Map ISA bus address to the real address. Only for PCMCIA. */ + +/* ISA page descriptor. */ +static __u32 sh_isa_memmap[256]; + +#if 0 +static int +sh_isa_mmap(__u32 start, __u32 length, __u32 offset) +{ + int idx; + + if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000)) + return -1; + + idx = start >> 12; + sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff); + printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n", + start, length, offset, idx, sh_isa_memmap[idx]); + return 0; +} +#endif + +unsigned long +sh7751systemh_isa_port2addr(unsigned long offset) +{ + int idx; + + idx = (offset >> 12) & 0xff; + offset &= 0xfff; + return sh_isa_memmap[idx] + offset; +} diff -puN /dev/null arch/sh/boards/systemh/irq.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/systemh/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,111 @@ +/* + * linux/arch/sh/boards/systemh/irq.c + * + * Copyright (C) 2000 Kazumoto Kojima + * + * Hitachi SystemH Support. + * + * Modified for 7751 SystemH by + * Jonathan Short. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* address of external interrupt mask register + * address must be set prior to use these (maybe in init_XXX_irq()) + * XXX : is it better to use .config than specifying it in code? */ +static unsigned long *systemh_irq_mask_register = (unsigned long *)0xB3F10004; +static unsigned long *systemh_irq_request_register = (unsigned long *)0xB3F10000; + +/* forward declaration */ +static unsigned int startup_systemh_irq(unsigned int irq); +static void shutdown_systemh_irq(unsigned int irq); +static void enable_systemh_irq(unsigned int irq); +static void disable_systemh_irq(unsigned int irq); +static void mask_and_ack_systemh(unsigned int); +static void end_systemh_irq(unsigned int irq); + +/* hw_interrupt_type */ +static struct hw_interrupt_type systemh_irq_type = { + " SystemH Register", + startup_systemh_irq, + shutdown_systemh_irq, + enable_systemh_irq, + disable_systemh_irq, + mask_and_ack_systemh, + end_systemh_irq +}; + +static unsigned int startup_systemh_irq(unsigned int irq) +{ + enable_systemh_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_systemh_irq(unsigned int irq) +{ + disable_systemh_irq(irq); +} + +static void disable_systemh_irq(unsigned int irq) +{ + if (systemh_irq_mask_register) { + unsigned long flags; + unsigned long val, mask = 0x01 << 1; + + /* Clear the "irq"th bit in the mask and set it in the request */ + local_irq_save(flags); + + val = ctrl_inl((unsigned long)systemh_irq_mask_register); + val &= ~mask; + ctrl_outl(val, (unsigned long)systemh_irq_mask_register); + + val = ctrl_inl((unsigned long)systemh_irq_request_register); + val |= mask; + ctrl_outl(val, (unsigned long)systemh_irq_request_register); + + local_irq_restore(flags); + } +} + +static void enable_systemh_irq(unsigned int irq) +{ + if (systemh_irq_mask_register) { + unsigned long flags; + unsigned long val, mask = 0x01 << 1; + + /* Set "irq"th bit in the mask register */ + local_irq_save(flags); + val = ctrl_inl((unsigned long)systemh_irq_mask_register); + val |= mask; + ctrl_outl(val, (unsigned long)systemh_irq_mask_register); + local_irq_restore(flags); + } +} + +static void mask_and_ack_systemh(unsigned int irq) +{ + disable_systemh_irq(irq); +} + +static void end_systemh_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_systemh_irq(irq); +} + +void make_systemh_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &systemh_irq_type; + disable_systemh_irq(irq); +} + diff -puN /dev/null arch/sh/boards/systemh/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/systemh/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,17 @@ +# +# Makefile for the SystemH specific parts of the kernel +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := setup.o irq.o io.o + +# XXX: This wants to be consolidated in arch/sh/drivers/pci, and more +# importantly, with the generic sh7751_pcic_init() code. For now, we'll +# just abuse the hell out of kbuild, because we can.. + +obj-$(CONFIG_PCI) += pci.o +pci-y := ../se/7751/pci.o + diff -puN /dev/null arch/sh/boards/systemh/setup.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boards/systemh/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,80 @@ +/* + * linux/arch/sh/boards/systemh/setup.c + * + * Copyright (C) 2000 Kazumoto Kojima + * Copyright (C) 2003 Paul Mundt + * + * Hitachi SystemH Support. + * + * Modified for 7751 SystemH by Jonathan Short. + * + * Rewritten for 2.6 by Paul Mundt. + * + * 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. + */ +#include +#include +#include +#include + +extern void make_systemh_irq(unsigned int irq); + +const char *get_system_type(void) +{ + return "7751 SystemH"; +} + +/* + * Initialize IRQ setting + */ +void __init init_7751systemh_IRQ(void) +{ +/* make_ipr_irq(10, BCR_ILCRD, 1, 0x0f-10); LAN */ +/* make_ipr_irq(14, BCR_ILCRA, 2, 0x0f-4); */ + make_systemh_irq(0xb); /* Ethernet interrupt */ +} + +struct sh_machine_vector mv_7751systemh __initmv = { + .mv_nr_irqs = 72, + + .mv_inb = sh7751systemh_inb, + .mv_inw = sh7751systemh_inw, + .mv_inl = sh7751systemh_inl, + .mv_outb = sh7751systemh_outb, + .mv_outw = sh7751systemh_outw, + .mv_outl = sh7751systemh_outl, + + .mv_inb_p = sh7751systemh_inb_p, + .mv_inw_p = sh7751systemh_inw, + .mv_inl_p = sh7751systemh_inl, + .mv_outb_p = sh7751systemh_outb_p, + .mv_outw_p = sh7751systemh_outw, + .mv_outl_p = sh7751systemh_outl, + + .mv_insb = sh7751systemh_insb, + .mv_insw = sh7751systemh_insw, + .mv_insl = sh7751systemh_insl, + .mv_outsb = sh7751systemh_outsb, + .mv_outsw = sh7751systemh_outsw, + .mv_outsl = sh7751systemh_outsl, + + .mv_readb = sh7751systemh_readb, + .mv_readw = sh7751systemh_readw, + .mv_readl = sh7751systemh_readl, + .mv_writeb = sh7751systemh_writeb, + .mv_writew = sh7751systemh_writew, + .mv_writel = sh7751systemh_writel, + + .mv_isa_port2addr = sh7751systemh_isa_port2addr, + + .mv_init_irq = init_7751systemh_IRQ, +}; +ALIAS_MV(7751systemh) + +int __init platform_setup(void) +{ + return 0; +} + diff -puN arch/sh/boot/compressed/head.S~linus arch/sh/boot/compressed/head.S --- 25/arch/sh/boot/compressed/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boot/compressed/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -2,10 +2,12 @@ * linux/arch/sh/boot/compressed/head.S * * Copyright (C) 1999 Stuart Menefy + * Copyright (C) 2003 SUGIOKA Toshinobu */ .text +#include #include .global startup @@ -14,7 +16,54 @@ startup: mov.l init_sr, r1 ldc r1, sr - /* First clear BSS */ + /* Move myself to proper location if necessary */ + mova 1f, r0 + mov.l 1f, r2 + cmp/eq r2, r0 + bt clear_bss + sub r0, r2 + mov.l bss_start_addr, r0 + mov #0xe0, r1 + and r1, r0 ! align cache line + mov.l text_start_addr, r3 + mov r0, r1 + sub r2, r1 +3: + mov.l @r1, r4 + mov.l @(4,r1), r5 + mov.l @(8,r1), r6 + mov.l @(12,r1), r7 + mov.l @(16,r1), r8 + mov.l @(20,r1), r9 + mov.l @(24,r1), r10 + mov.l @(28,r1), r11 + mov.l r4, @r0 + mov.l r5, @(4,r0) + mov.l r6, @(8,r0) + mov.l r7, @(12,r0) + mov.l r8, @(16,r0) + mov.l r9, @(20,r0) + mov.l r10, @(24,r0) + mov.l r11, @(28,r0) +#ifdef CONFIG_CPU_SH4 + ocbwb @r0 +#endif + cmp/hi r3, r0 + add #-32, r0 + bt/s 3b + add #-32, r1 + mov.l 2f, r0 + jmp @r0 + nop + + .align 2 +1: .long 1b +2: .long clear_bss +text_start_addr: + .long startup + + /* Clear BSS */ +clear_bss: mov.l end_addr, r1 mov.l bss_start_addr, r2 mov #0, r0 diff -puN arch/sh/boot/compressed/Makefile~linus arch/sh/boot/compressed/Makefile --- 25/arch/sh/boot/compressed/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/boot/compressed/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -16,9 +16,9 @@ endif # # IMAGE_OFFSET is the load offset of the compression loader # -IMAGE_OFFSET = $(shell printf "0x%8x" $$[0x80000000+0x$(CONFIG_MEMORY_START)+0x200000+0x10000]) +IMAGE_OFFSET := $(shell printf "0x%8x" $$[0x80000000+$(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)]) -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../vmlinux.lds.s +LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds.s $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE $(call if_changed,ld) diff -puN /dev/null arch/sh/boot/compressed/vmlinux.scr --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/boot/compressed/vmlinux.scr 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,9 @@ +SECTIONS +{ + .data : { + input_len = .; + LONG(input_data_end - input_data) input_data = .; + *(.data) + input_data_end = .; + } +} diff -puN arch/sh/cchips/hd6446x/hd64461/io.c~linus arch/sh/cchips/hd6446x/hd64461/io.c --- 25/arch/sh/cchips/hd6446x/hd64461/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/cchips/hd6446x/hd64461/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: io.c,v 1.1.2.2 2002/01/20 05:03:25 mrbrown Exp $ + * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ * Copyright (C) 2000 YAEGASHI Takeshi * Typical I/O routines for HD64461 system. */ @@ -78,24 +78,6 @@ unsigned int hd64461_inl(unsigned long p return *(volatile unsigned long*)PORT2ADDR(port); } -void hd64461_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void hd64461_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void hd64461_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - void hd64461_outb(unsigned char b, unsigned long port) { *(volatile unsigned char*)PORT2ADDR(port) = b; @@ -117,20 +99,3 @@ void hd64461_outl(unsigned int b, unsign *(volatile unsigned long*)PORT2ADDR(port) = b; } -void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} diff -puN arch/sh/cchips/hd6446x/hd64461/setup.c~linus arch/sh/cchips/hd6446x/hd64461/setup.c --- 25/arch/sh/cchips/hd6446x/hd64461/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/cchips/hd6446x/hd64461/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $ + * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ * Copyright (C) 2000 YAEGASHI Takeshi * Hitachi HD64461 companion chip support */ @@ -76,21 +76,23 @@ static void shutdown_hd64461_irq(unsigne static struct hw_interrupt_type hd64461_irq_type = { - "HD64461-IRQ", - startup_hd64461_irq, - shutdown_hd64461_irq, - enable_hd64461_irq, - disable_hd64461_irq, - mask_and_ack_hd64461, - end_hd64461_irq + .typename = "HD64461-IRQ", + .startup = startup_hd64461_irq, + .shutdown = shutdown_hd64461_irq, + .enable = enable_hd64461_irq, + .disable = disable_hd64461_irq, + .ack = mask_and_ack_hd64461, + .end = end_hd64461_irq, }; -static void hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t hd64461_interrupt(int irq, void *dev_id, struct pt_regs *regs) { printk(KERN_INFO "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", inw(HD64461_NIRR), inw(HD64461_NIMR)); + + return IRQ_NONE; } int hd64461_irq_demux(int irq) diff -puN arch/sh/cchips/hd6446x/hd64465/io.c~linus arch/sh/cchips/hd6446x/hd64465/io.c --- 25/arch/sh/cchips/hd6446x/hd64465/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/cchips/hd6446x/hd64465/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: io.c,v 1.1.2.2 2002/01/20 05:03:25 mrbrown Exp $ + * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ * by Greg Banks * (c) 2000 PocketPenguins Inc * @@ -179,24 +179,6 @@ unsigned int hd64465_inl(unsigned long p return b; } -void hd64465_insb(unsigned long port, void *buffer, unsigned long count) -{ - unsigned char *buf=buffer; - while(count--) *buf++=inb(port); -} - -void hd64465_insw(unsigned long port, void *buffer, unsigned long count) -{ - unsigned short *buf=buffer; - while(count--) *buf++=inw(port); -} - -void hd64465_insl(unsigned long port, void *buffer, unsigned long count) -{ - unsigned long *buf=buffer; - while(count--) *buf++=inl(port); -} - void hd64465_outb(unsigned char b, unsigned long port) { unsigned long addr = PORT2ADDR(port); @@ -232,20 +214,3 @@ void hd64465_outl(unsigned int b, unsign *(volatile unsigned long*)addr = b; } -void hd64465_outsb(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned char *buf=buffer; - while(count--) outb(*buf++, port); -} - -void hd64465_outsw(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned short *buf=buffer; - while(count--) outw(*buf++, port); -} - -void hd64465_outsl(unsigned long port, const void *buffer, unsigned long count) -{ - const unsigned long *buf=buffer; - while(count--) outl(*buf++, port); -} diff -puN arch/sh/cchips/hd6446x/hd64465/setup.c~linus arch/sh/cchips/hd6446x/hd64465/setup.c --- 25/arch/sh/cchips/hd6446x/hd64465/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/cchips/hd6446x/hd64465/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: setup.c,v 1.1.2.3 2002/11/04 20:33:57 lethal Exp $ + * $Id: setup.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ * * Setup and IRQ handling code for the HD64465 companion chip. * by Greg Banks @@ -24,21 +24,13 @@ #include -#undef HD64465_DEBUG - -#ifdef HD64465_DEBUG -#define DPRINTK(args...) printk(args) -#else -#define DPRINTK(args...) -#endif - static void disable_hd64465_irq(unsigned int irq) { unsigned long flags; unsigned short nimr; unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - DPRINTK("disable_hd64465_irq(%d): mask=%x\n", irq, mask); + pr_debug("disable_hd64465_irq(%d): mask=%x\n", irq, mask); local_irq_save(flags); nimr = inw(HD64465_REG_NIMR); nimr |= mask; @@ -53,7 +45,7 @@ static void enable_hd64465_irq(unsigned unsigned short nimr; unsigned short mask = 1 << (irq - HD64465_IRQ_BASE); - DPRINTK("enable_hd64465_irq(%d): mask=%x\n", irq, mask); + pr_debug("enable_hd64465_irq(%d): mask=%x\n", irq, mask); local_irq_save(flags); nimr = inw(HD64465_REG_NIMR); nimr &= ~mask; @@ -95,15 +87,17 @@ static struct hw_interrupt_type hd64465_ .enable = enable_hd64465_irq, .disable = disable_hd64465_irq, .ack = mask_and_ack_hd64465, - .end = end_hd64465_irq + .end = end_hd64465_irq, }; -static void hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) +static irqreturn_t hd64465_interrupt(int irq, void *dev_id, struct pt_regs *regs) { printk(KERN_INFO "HD64465: spurious interrupt, nirr: 0x%x nimr: 0x%x\n", inw(HD64465_REG_NIRR), inw(HD64465_REG_NIMR)); + + return IRQ_NONE; } @@ -145,7 +139,7 @@ int hd64465_irq_demux(int irq) unsigned short nirr = inw(HD64465_REG_NIRR); unsigned short nimr = inw(HD64465_REG_NIMR); - DPRINTK("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); + pr_debug("hd64465_irq_demux, nirr=%04x, nimr=%04x\n", nirr, nimr); nirr &= ~nimr; for (bit = 1, i = 0 ; i < HD64465_IRQ_NUM ; bit <<= 1, i++) if (nirr & bit) diff -puN /dev/null arch/sh/cchips/Kconfig --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/cchips/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,76 @@ +# A board must have defined HD6446X_SERIES in order to see these +choice + prompt "HD6446x options" + depends HD6446X_SERIES + default HD64461 + +config HD64461 + bool "Hitachi HD64461 companion chip support" + depends on CPU_SUBTYPE_SH7709 + ---help--- + The Hitachi HD64461 provides an interface for + the SH7709 CPU, supporting a LCD controller, + CRT color controller, IrDA up to 4 Mbps, and a + PCMCIA controller supporting 2 slots. + + More information is available at + . + + Say Y if you want support for the HD64461. + Otherwise, say N. + +config HD64465 + bool "Hitachi HD64465 companion chip support" + depends on CPU_SUBTYPE_SH7750 + ---help--- + The Hitachi HD64465 provides an interface for + the SH7750 CPU, supporting a LCD controller, + CRT color controller, IrDA, USB, PCMCIA, + keyboard controller, and a printer interface. + + More information is available at + . + + Say Y if you want support for the HD64465. + Otherwise, say N. + +endchoice + +# These will also be split into the Kconfig's below +config HD64461_IRQ + int "HD64461 IRQ" + depends on HD64461 + default "36" + help + The default setting of the HD64461 IRQ is 36. + + Do not change this unless you know what you are doing. + +config HD64461_ENABLER + bool "HD64461 PCMCIA enabler" + depends on HD64461 + help + Say Y here if you want to enable PCMCIA support + via the HD64461 companion chip. + Otherwise, say N. + + +config HD64465_IOBASE + hex "HD64465 start address" + depends on HD64465 + default "0xb0000000" + help + The default setting of the HD64465 IO base address is 0xb0000000. + + Do not change this unless you know what you are doing. + +config HD64465_IRQ + int "HD64465 IRQ" + depends on HD64465 + default "5" + help + The default setting of the HD64465 IRQ is 5. + + Do not change this unless you know what you are doing. + + diff -puN arch/sh/configs/defconfig-adx~linus arch/sh/configs/defconfig-adx --- 25/arch/sh/configs/defconfig-adx~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/configs/defconfig-adx 2004-01-19 22:17:21.000000000 -0800 @@ -45,8 +45,8 @@ CONFIG_CPU_SUBTYPE_SH7750=y # CONFIG_CPU_SH3 is not set CONFIG_CPU_SH4=y CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MEMORY_START=08000000 -CONFIG_MEMORY_SIZE=00400000 +CONFIG_MEMORY_START=0x08000000 +CONFIG_MEMORY_SIZE=0x00400000 CONFIG_MEMORY_SET=y # CONFIG_DISCONTIGMEM is not set @@ -61,7 +61,7 @@ CONFIG_ISA=y CONFIG_CF_ENABLER=y # CONFIG_CF_AREA5 is not set CONFIG_CF_AREA6=y -CONFIG_CF_BASE_ADDR=b8000000 +CONFIG_CF_BASE_ADDR=0xb8000000 # CONFIG_HD64461 is not set # CONFIG_HD64465 is not set # CONFIG_SH_DMA is not set diff -puN arch/sh/configs/defconfig-cqreek~linus arch/sh/configs/defconfig-cqreek --- 25/arch/sh/configs/defconfig-cqreek~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/configs/defconfig-cqreek 2004-01-19 22:17:21.000000000 -0800 @@ -45,8 +45,8 @@ CONFIG_CPU_SUBTYPE_SH7708=y CONFIG_CPU_SH3=y # CONFIG_CPU_SH4 is not set CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MEMORY_START=0c000000 -CONFIG_MEMORY_SIZE=00400000 +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x00400000 # CONFIG_DISCONTIGMEM is not set # @@ -59,7 +59,7 @@ CONFIG_ISA=y # CONFIG_NET is not set # CONFIG_CF_AREA5 is not set CONFIG_CF_AREA6=y -CONFIG_CF_BASE_ADDR=b8000000 +CONFIG_CF_BASE_ADDR=0xb8000000 # CONFIG_HD64461 is not set # CONFIG_HD64465 is not set # CONFIG_SH_DMA is not set diff -puN arch/sh/configs/defconfig-dreamcast~linus arch/sh/configs/defconfig-dreamcast --- 25/arch/sh/configs/defconfig-dreamcast~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/configs/defconfig-dreamcast 2004-01-19 22:17:21.000000000 -0800 @@ -1,23 +1,48 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_SUPERH=y CONFIG_UID16=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +# CONFIG_STANDALONE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y # # Loadable module support # -# CONFIG_MODULES is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set # -# Processor type and features +# System type # # CONFIG_SH_SOLUTION_ENGINE is not set # CONFIG_SH_7751_SOLUTION_ENGINE is not set @@ -29,60 +54,77 @@ CONFIG_EXPERIMENTAL=y # CONFIG_SH_CQREEK is not set # CONFIG_SH_DMIDA is not set # CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set CONFIG_SH_DREAMCAST=y # CONFIG_SH_CAT68701 is not set # CONFIG_SH_BIGSUR is not set # CONFIG_SH_SH2000 is not set # CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SECUREEDGE5410 is not set # CONFIG_SH_UNKNOWN is not set -# CONFIG_SH_RTC is not set +# CONFIG_CPU_SH2 is not set +# CONFIG_CPU_SH3 is not set +CONFIG_CPU_SH4=y +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set # CONFIG_CPU_SUBTYPE_SH7708 is not set # CONFIG_CPU_SUBTYPE_SH7709 is not set CONFIG_CPU_SUBTYPE_SH7750=y # CONFIG_CPU_SUBTYPE_SH7751 is not set # CONFIG_CPU_SUBTYPE_ST40STB1 is not set -# CONFIG_CPU_SH3 is not set -CONFIG_CPU_SH4=y -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MEMORY_START=0c000000 -CONFIG_MEMORY_SIZE=00400000 +CONFIG_MMU=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x01000000 CONFIG_MEMORY_SET=y -# CONFIG_DISCONTIGMEM is not set +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_PREEMPT=y +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +CONFIG_SH_STORE_QUEUES=y +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=49876504 +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_SH_CPU_FREQ=y +# CONFIG_CPU_FREQ_PROC_INTF is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_SH_DMA=y +CONFIG_NR_ONCHIP_DMA_CHANNELS=4 +CONFIG_NR_DMA_CHANNELS_BOOL=y +CONFIG_NR_DMA_CHANNELS=9 +CONFIG_DMA_PAGE_OPS=y # -# General setup +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) # -CONFIG_ISA=y -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_NET=y -# CONFIG_HD64461 is not set -# CONFIG_HD64465 is not set -# CONFIG_SH_DMA is not set CONFIG_PCI=y -# CONFIG_PCI_GOBIOS is not set -# CONFIG_PCI_GODIRECT is not set -CONFIG_PCI_GOANY=y -CONFIG_PCI_BIOS=y -CONFIG_PCI_DIRECT=y # CONFIG_SH_PCIDMA_NONCOHERENT is not set +CONFIG_PCI_AUTO=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set + +# +# Executable file formats +# CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_BINFMT_MISC is not set # -# Parallel port support +# Generic Driver Options # -# CONFIG_PARPORT is not set # # Memory Technology Devices (MTD) @@ -90,64 +132,89 @@ CONFIG_BINFMT_ELF=y # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Block devices # -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_CISS_SCSI_TAPE is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM 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_SIZE=4096 +CONFIG_BLK_DEV_RAM_SIZE=1024 CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set # # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set +# CONFIG_NETLINK_DEV 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=y -# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_DHCP=y # CONFIG_IP_PNP_BOOTP is not set # CONFIG_IP_PNP_RARP 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_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -160,24 +227,9 @@ CONFIG_IP_PNP=y # CONFIG_NET_SCHED is not set # -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# IEEE 1394 (FireWire) support (EXPERIMENTAL) -# -# CONFIG_IEEE1394 is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -193,65 +245,60 @@ CONFIG_NETDEVICES=y # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_MII=y # CONFIG_STNIC is not set -# CONFIG_SUNLANCE is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set +# CONFIG_B44 is not set # CONFIG_DGRS is not set -# CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set -# CONFIG_LNE390 is not set +# CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set # CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set # CONFIG_8139CP is not set CONFIG_8139TOO=y # CONFIG_8139TOO_PIO is not set # CONFIG_8139TOO_TUNE_TWISTER is not set # CONFIG_8139TOO_8129 is not set -CONFIG_8139TOO_DREAMCAST=y +# CONFIG_8139_OLD_RX_RESET is not set # CONFIG_SIS900 is not set # CONFIG_EPIC100 is not set # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_VIA_RHINE_MMIO is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -264,7 +311,6 @@ CONFIG_8139TOO_DREAMCAST=y # Token Ring devices # # CONFIG_TR is not set -# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -274,165 +320,186 @@ CONFIG_8139TOO_DREAMCAST=y # CONFIG_WAN is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_ISDN_BOOL is not set # -# Input core support +# Telephony Support # -CONFIG_INPUT=y -CONFIG_INPUT_KEYBDEV=y -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -CONFIG_INPUT_JOYDEV=y -# CONFIG_INPUT_EVDEV is not set +# CONFIG_PHONE is not set # -# Maple Bus support +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers # -CONFIG_MAPLE=y # # Character devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y +# CONFIG_VT is not set # CONFIG_SERIAL is not set CONFIG_SH_SCI=y CONFIG_SERIAL_CONSOLE=y -# CONFIG_UNIX98_PTYS is not set # -# Maple Bus input peripherals -# -CONFIG_MAPLE_KEYBOARD=y -CONFIG_MAPLE_MOUSE=y - +# Unix 98 PTY support # -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set -# CONFIG_INPUT_NS558 is not set -# CONFIG_INPUT_LIGHTNING is not set -# CONFIG_INPUT_PCIGAME is not set -# CONFIG_INPUT_CS461X is not set -# CONFIG_INPUT_EMU10K1 is not set -# CONFIG_INPUT_SERIO is not set -# CONFIG_INPUT_SERPORT is not set -# CONFIG_INPUT_ANALOG is not set -# CONFIG_INPUT_A3D is not set -# CONFIG_INPUT_ADI is not set -# CONFIG_INPUT_COBRA is not set -# CONFIG_INPUT_GF2K is not set -# CONFIG_INPUT_GRIP is not set -# CONFIG_INPUT_INTERACT is not set -# CONFIG_INPUT_TMDC is not set -# CONFIG_INPUT_SIDEWINDER is not set -# CONFIG_INPUT_IFORCE_USB is not set -# CONFIG_INPUT_IFORCE_232 is not set -# CONFIG_INPUT_WARRIOR is not set -# CONFIG_INPUT_MAGELLAN is not set -# CONFIG_INPUT_SPACEORB is not set -# CONFIG_INPUT_SPACEBALL is not set -# CONFIG_INPUT_STINGER is not set -# CONFIG_INPUT_DB9 is not set -# CONFIG_INPUT_GAMECON is not set -# CONFIG_INPUT_TURBOGRAFX is not set -CONFIG_INPUT_MAPLE_CONTROL=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # CONFIG_PSMOUSE is not set # # Watchdog Cards # -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -CONFIG_SH_WDT=y +# CONFIG_WATCHDOG is not set # CONFIG_RTC is not set # +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# # File systems # +# CONFIG_EXT2_FS 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_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_MINIX_FS is not set +CONFIG_CRAMFS=y # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -# CONFIG_EXT2_FS is not set # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set -# CONFIG_ZISOFS_FS is not set -# CONFIG_ZLIB_FS_INFLATE is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set # # Multimedia devices @@ -440,40 +507,39 @@ CONFIG_MSDOS_PARTITION=y # CONFIG_VIDEO_DEV is not set # -# Console drivers +# Digital Video Broadcasting Devices # -# CONFIG_VGA_CONSOLE is not set -# CONFIG_VIDEO_SELECT is not set -# CONFIG_MDA_CONSOLE is not set +# CONFIG_DVB is not set # -# Frame-buffer support +# Graphics support # CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set CONFIG_FB_PVR2=y -CONFIG_FB_PVR2_DEBUG=y +# CONFIG_FB_PVR2_DEBUG is not set # CONFIG_FB_E1355 is not set +# CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y + +# +# Logo configuration +# +# CONFIG_LOGO is not set # # Sound @@ -481,7 +547,38 @@ CONFIG_FONT_8x16=y # CONFIG_SOUND is not set # +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# # Kernel hacking # # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set # CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y diff -puN /dev/null arch/sh/configs/defconfig-se7751 --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/configs/defconfig-se7751 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,617 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_SUPERH=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODULE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +CONFIG_SH_7751_SOLUTION_ENGINE=y +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_STB1_HARP is not set +# CONFIG_SH_STB1_OVERDRIVE is not set +# CONFIG_SH_HP620 is not set +# CONFIG_SH_HP680 is not set +# CONFIG_SH_HP690 is not set +# CONFIG_SH_CQREEK is not set +# CONFIG_SH_DMIDA is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_CAT68701 is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_SH2000 is not set +# CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_UNKNOWN is not set +# CONFIG_CPU_SH2 is not set +# CONFIG_CPU_SH3 is not set +CONFIG_CPU_SH4=y +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +CONFIG_CPU_SUBTYPE_SH7751=y +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +CONFIG_MMU=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="console=ttySC1,38400" +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x04000000 +CONFIG_MEMORY_SET=y +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_SH_RTC=y +CONFIG_ZERO_PAGE_OFFSET=0x00010000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_PREEMPT is not set +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +# CONFIG_SH_STORE_QUEUES is not set +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=60013568 +# CONFIG_CPU_FREQ is not set +# CONFIG_SH_DMA is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_SH_PCIDMA_NONCOHERENT is not set +CONFIG_PCI_AUTO=y +CONFIG_PCI_AUTO_UPDATE_RESOURCES=y +CONFIG_PCI_DMA=y +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# + +# +# 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_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +# CONFIG_MTD_CHAR is not set +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=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA 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_PHYSMAP is not set +# CONFIG_MTD_MPC1211 is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM 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_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE 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_INET_IPCOMP is not set + +# +# IP: Virtual Server Configuration +# +# CONFIG_IP_VS is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +CONFIG_NETFILTER=y +CONFIG_NETFILTER_DEBUG=y + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +CONFIG_IP_NF_QUEUE=y +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q 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_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# 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=y +# CONFIG_STNIC is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set +# CONFIG_SERIO_I8042 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +CONFIG_SH_SCI=y +CONFIG_SERIAL_CONSOLE=y + +# +# Unix 98 PTY support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_HEARTBEAT=y +# CONFIG_PSMOUSE is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SH_WDT is not set +# CONFIG_RTC is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR 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_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# 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 + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -puN /dev/null arch/sh/configs/defconfig-snapgear --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/configs/defconfig-snapgear 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,540 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_SUPERH=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_STB1_HARP is not set +# CONFIG_SH_STB1_OVERDRIVE is not set +# CONFIG_SH_HP620 is not set +# CONFIG_SH_HP680 is not set +# CONFIG_SH_HP690 is not set +# CONFIG_SH_CQREEK is not set +# CONFIG_SH_DMIDA is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_CAT68701 is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_SH2000 is not set +# CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +CONFIG_SH_SECUREEDGE5410=y +# CONFIG_SH_UNKNOWN is not set +# CONFIG_CPU_SH2 is not set +# CONFIG_CPU_SH3 is not set +CONFIG_CPU_SH4=y +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +CONFIG_CPU_SUBTYPE_SH7751=y +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +CONFIG_MMU=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MEMORY_START=0x08000000 +CONFIG_MEMORY_SIZE=0x01000000 +CONFIG_MEMORY_SET=y +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_SH_RTC=y +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_PREEMPT is not set +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +# CONFIG_SH_STORE_QUEUES is not set +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=60013568 +# CONFIG_CPU_FREQ is not set +CONFIG_SH_DMA=y +CONFIG_NR_DMA_CHANNELS=8 +# CONFIG_DMA_PAGE_OPS is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_SH_PCIDMA_NONCOHERENT is not set +CONFIG_PCI_AUTO=y +CONFIG_PCI_AUTO_UPDATE_RESOURCES=y +CONFIG_PCI_DMA=y +# CONFIG_PCI_LEGACY_PROC is not set +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM 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_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV 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=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP 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_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +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_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_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_STNIC is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +# CONFIG_E100 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +CONFIG_8139TOO=y +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +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 + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +CONFIG_SH_SCI=y +CONFIG_SERIAL_CONSOLE=y + +# +# Unix 98 PTY support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_PSMOUSE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR 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_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS 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 + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y diff -puN /dev/null arch/sh/configs/defconfig-systemh --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/configs/defconfig-systemh 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,372 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_SUPERH=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +# CONFIG_STANDALONE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +CONFIG_SH_7751_SYSTEMH=y +# CONFIG_SH_STB1_HARP is not set +# CONFIG_SH_STB1_OVERDRIVE is not set +# CONFIG_SH_HP620 is not set +# CONFIG_SH_HP680 is not set +# CONFIG_SH_HP690 is not set +# CONFIG_SH_CQREEK is not set +# CONFIG_SH_DMIDA is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_CAT68701 is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_SH2000 is not set +# CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_UNKNOWN is not set +# CONFIG_CPU_SH2 is not set +# CONFIG_CPU_SH3 is not set +CONFIG_CPU_SH4=y +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +CONFIG_CPU_SUBTYPE_SH7751=y +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +CONFIG_MMU=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x00400000 +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_SH_RTC=y +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_PREEMPT=y +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +# CONFIG_SH_STORE_QUEUES is not set +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=49876504 +# CONFIG_CPU_FREQ is not set +# CONFIG_SH_DMA is not set + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +CONFIG_PCI=y +# CONFIG_SH_PCIDMA_NONCOHERENT is not set +CONFIG_PCI_AUTO=y +CONFIG_PCI_AUTO_UPDATE_RESOURCES=y +CONFIG_PCI_DMA=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=1024 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +# CONFIG_INPUT is not set + +# +# Userland interfaces +# + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL is not set +CONFIG_SH_SCI=y +CONFIG_SERIAL_CONSOLE=y + +# +# Unix 98 PTY support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_PSMOUSE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# File systems +# +# CONFIG_EXT2_FS 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_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# + +# +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y diff -puN /dev/null arch/sh/drivers/dma/dma-api.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-api.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,193 @@ +/* + * arch/sh/drivers/dma/dma-api.c + * + * SuperH-specific DMA management API + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include +#include +#include + +struct dma_info dma_info[MAX_DMA_CHANNELS] = { { 0, } }; +spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED; + +/* + * A brief note about the reasons for this API as it stands. + * + * For starters, the old ISA DMA API didn't work for us for a number of + * reasons, for one, the vast majority of channels on the SH DMAC are + * dual-address mode only, and both the new and the old DMA APIs are after the + * concept of managing a DMA buffer, which doesn't overly fit this model very + * well. In addition to which, the new API is largely geared at IOMMUs and + * GARTs, and doesn't even support the channel notion very well. + * + * The other thing that's a marginal issue, is the sheer number of random DMA + * engines that are present (ie, in boards like the Dreamcast), some of which + * cascade off of the SH DMAC, and others do not. As such, there was a real + * need for a scalable subsystem that could deal with both single and + * dual-address mode usage, in addition to interoperating with cascaded DMACs. + * + * There really isn't any reason why this needs to be SH specific, though I'm + * not aware of too many other processors (with the exception of some MIPS) + * that have the same concept of a dual address mode, or any real desire to + * actually make use of the DMAC even if such a subsystem were exposed + * elsewhere. + * + * The idea for this was derived from the ARM port, which acted as an excellent + * reference when trying to address these issues. + * + * It should also be noted that the decision to add Yet Another DMA API(tm) to + * the kernel wasn't made easily, and was only decided upon after conferring + * with jejb with regards to the state of the old and new APIs as they applied + * to these circumstances. Philip Blundell was also a great help in figuring + * out some single-address mode DMA semantics that were otherwise rather + * confusing. + */ + +struct dma_info *get_dma_info(unsigned int chan) +{ + return dma_info + chan; +} + +int get_dma_residue(unsigned int chan) +{ + struct dma_info *info = get_dma_info(chan); + + if (info->ops->get_residue) + return info->ops->get_residue(info); + + return 0; +} + +int request_dma(unsigned int chan, const char *dev_id) +{ + struct dma_info *info = get_dma_info(chan); + + down(&info->sem); + + if (!info->ops || chan >= MAX_DMA_CHANNELS) { + up(&info->sem); + return -EINVAL; + } + + atomic_set(&info->busy, 1); + + info->dev_id = dev_id; + + up(&info->sem); + + if (info->ops->request) + return info->ops->request(info); + + return 0; +} + +void free_dma(unsigned int chan) +{ + struct dma_info *info = get_dma_info(chan); + + if (info->ops->free) + info->ops->free(info); + + atomic_set(&info->busy, 0); +} + +void dma_wait_for_completion(unsigned int chan) +{ + struct dma_info *info = get_dma_info(chan); + + while (info->ops->get_residue(info)) + cpu_relax(); +} + +void dma_configure_channel(unsigned int chan, unsigned long flags) +{ + struct dma_info *info = get_dma_info(chan); + + if (info->ops->configure) + info->ops->configure(info, flags); +} + +int dma_xfer(unsigned int chan, unsigned long from, + unsigned long to, size_t size, unsigned int mode) +{ + struct dma_info *info = get_dma_info(chan); + + info->sar = from; + info->dar = to; + info->count = size; + info->mode = mode; + + return info->ops->xfer(info); +} + +#ifdef CONFIG_PROC_FS +static int dma_read_proc(char *buf, char **start, off_t off, + int len, int *eof, void *data) +{ + struct dma_info *info; + char *p = buf; + int i; + + for (i = 0, info = dma_info; i < MAX_DMA_CHANNELS; i++, info++) { + if (!atomic_read(&info->busy)) + continue; + + p += sprintf(p, "%2d: %14s %s\n", i, + info->ops->name, info->dev_id); + } + + return p - buf; +} +#endif + +int __init register_dmac(struct dma_ops *ops) +{ + int i; + + printk("DMA: Registering %s handler.\n", ops->name); + + for (i = 0; i < MAX_DMA_CHANNELS; i++) { + struct dma_info *info = get_dma_info(i); + + info->chan = i; + + init_MUTEX(&info->sem); + } + + return 0; +} + +static int __init dma_api_init(void) +{ + printk("DMA: Registering DMA API.\n"); + +#ifdef CONFIG_PROC_FS + create_proc_read_entry("dma", 0, 0, dma_read_proc, 0); +#endif + + return 0; +} + +subsys_initcall(dma_api_init); + +MODULE_AUTHOR("Paul Mundt "); +MODULE_DESCRIPTION("DMA API for SuperH"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(request_dma); +EXPORT_SYMBOL(free_dma); +EXPORT_SYMBOL(get_dma_residue); +EXPORT_SYMBOL(get_dma_info); +EXPORT_SYMBOL(dma_xfer); +EXPORT_SYMBOL(dma_wait_for_completion); +EXPORT_SYMBOL(dma_configure_channel); + diff -puN /dev/null arch/sh/drivers/dma/dma-g2.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-g2.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,173 @@ +/* + * arch/sh/drivers/dma/dma-g2.c + * + * G2 bus DMA support + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include + +#include +#include +#include + +struct g2_channel { + unsigned long g2_addr; /* G2 bus address */ + unsigned long root_addr; /* Root bus (SH-4) address */ + unsigned long size; /* Size (in bytes), 32-byte aligned */ + unsigned long direction; /* Transfer direction */ + unsigned long ctrl; /* Transfer control */ + unsigned long chan_enable; /* Channel enable */ + unsigned long xfer_enable; /* Transfer enable */ + unsigned long xfer_stat; /* Transfer status */ +} __attribute__ ((aligned(32))); + +struct g2_status { + unsigned long g2_addr; + unsigned long root_addr; + unsigned long size; + unsigned long status; +} __attribute__ ((aligned(16))); + +struct g2_dma_info { + struct g2_channel channel[G2_NR_DMA_CHANNELS]; + unsigned long pad1[G2_NR_DMA_CHANNELS]; + unsigned long wait_state; + unsigned long pad2[10]; + unsigned long magic; + struct g2_status status[G2_NR_DMA_CHANNELS]; +} __attribute__ ((aligned(256))); + +static volatile struct g2_dma_info *g2_dma = (volatile struct g2_dma_info *)0xa05f7800; + +static irqreturn_t g2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + /* FIXME: Do some meaningful completion work here.. */ + return IRQ_HANDLED; +} + +static struct irqaction g2_dma_irq = { + .name = "g2 DMA handler", + .handler = g2_dma_interrupt, + .flags = SA_INTERRUPT, +}; + +static int g2_enable_dma(struct dma_info *info) +{ + unsigned int chan = info->chan; + + g2_dma->channel[chan].chan_enable = 1; + g2_dma->channel[chan].xfer_enable = 1; + + return 0; +} + +static int g2_disable_dma(struct dma_info *info) +{ + unsigned int chan = info->chan; + + g2_dma->channel[chan].chan_enable = 0; + g2_dma->channel[chan].xfer_enable = 0; + + return 0; +} + +static int g2_xfer_dma(struct dma_info *info) +{ + unsigned int chan = info->chan; + + if (info->sar & 31) { + printk("g2dma: unaligned source 0x%lx\n", info->sar); + return -EINVAL; + } + + if (info->dar & 31) { + printk("g2dma: unaligned dest 0x%lx\n", info->dar); + return -EINVAL; + } + + /* Align the count */ + if (info->count & 31) + info->count = (info->count + (32 - 1)) & ~(32 - 1); + + /* Fixup destination */ + info->dar += 0xa0800000; + + /* Fixup direction */ + info->mode = !info->mode; + + flush_icache_range((unsigned long)info->sar, info->count); + + g2_disable_dma(info); + + g2_dma->channel[chan].g2_addr = info->dar & 0x1fffffe0; + g2_dma->channel[chan].root_addr = info->sar & 0x1fffffe0; + g2_dma->channel[chan].size = (info->count & ~31) | 0x80000000; + g2_dma->channel[chan].direction = info->mode; + + /* + * bit 0 - ??? + * bit 1 - if set, generate a hardware event on transfer completion + * bit 2 - ??? something to do with suspend? + */ + g2_dma->channel[chan].ctrl = 5; /* ?? */ + + g2_enable_dma(info); + + /* debug cruft */ + pr_debug("count, sar, dar, mode, ctrl, chan, xfer: %ld, 0x%08lx, " + "0x%08lx, %ld, %ld, %ld, %ld\n", + g2_dma->channel[chan].size, + g2_dma->channel[chan].root_addr, + g2_dma->channel[chan].g2_addr, + g2_dma->channel[chan].direction, + g2_dma->channel[chan].ctrl, + g2_dma->channel[chan].chan_enable, + g2_dma->channel[chan].xfer_enable); + + return 0; +} + +static struct dma_ops g2_dma_ops = { + .name = "G2 DMA", + .xfer = g2_xfer_dma, +}; + +static int __init g2_dma_init(void) +{ + int i, base; + + setup_irq(HW_EVENT_G2_DMA, &g2_dma_irq); + + /* Magic */ + g2_dma->wait_state = 27; + g2_dma->magic = 0x4659404f; + + /* G2 channels come after on-chip and pvr2 */ + base = ONCHIP_NR_DMA_CHANNELS + PVR2_NR_DMA_CHANNELS; + + for (i = 0; i < G2_NR_DMA_CHANNELS; i++) + dma_info[base + i].ops = &g2_dma_ops; + + return register_dmac(&g2_dma_ops); +} + +static void __exit g2_dma_exit(void) +{ + free_irq(HW_EVENT_G2_DMA, 0); +} + +subsys_initcall(g2_dma_init); +module_exit(g2_dma_exit); + +MODULE_AUTHOR("Paul Mundt "); +MODULE_DESCRIPTION("G2 bus DMA driver"); +MODULE_LICENSE("GPL"); + diff -puN /dev/null arch/sh/drivers/dma/dma-isa.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-isa.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,93 @@ +/* + * arch/sh/drivers/dma/dma-isa.c + * + * Generic ISA DMA wrapper for SH DMA API + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include + +/* + * This implements a small wrapper set to make code using the old ISA DMA API + * work with the SH DMA API. Since most of the work in the new API happens + * at ops->xfer() time, we simply use the various set_dma_xxx() routines to + * fill in per-channel info, and then hand hand this off to ops->xfer() at + * enable_dma() time. + * + * For channels that are doing on-demand data transfer via cascading, the + * channel itself will still need to be configured through the new API. As + * such, this code is meant for only the simplest of tasks (and shouldn't be + * used in any new drivers at all). + * + * It should also be noted that various functions here are labelled as + * being deprecated. This is due to the fact that the ops->xfer() method is + * the preferred way of doing things (as well as just grabbing the spinlock + * directly). As such, any users of this interface will be warned rather + * loudly. + */ + +unsigned long __deprecated claim_dma_lock(void) +{ + unsigned long flags; + + spin_lock_irqsave(&dma_spin_lock, flags); + + return flags; +} + +void __deprecated release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +void __deprecated disable_dma(unsigned int chan) +{ + /* Nothing */ +} + +void __deprecated enable_dma(unsigned int chan) +{ + struct dma_info *info = get_dma_info(chan); + + info->ops->xfer(info); +} + +void clear_dma_ff(unsigned int chan) +{ + /* Nothing */ +} + +void set_dma_mode(unsigned int chan, char mode) +{ + struct dma_info *info = get_dma_info(chan); + + info->mode = mode; +} + +void set_dma_addr(unsigned int chan, unsigned int addr) +{ + struct dma_info *info = get_dma_info(chan); + + /* + * Single address mode is the only thing supported through + * this interface. + */ + if ((info->mode & DMA_MODE_MASK) == DMA_MODE_READ) { + info->sar = addr; + } else { + info->dar = addr; + } +} + +void set_dma_count(unsigned int chan, unsigned int count) +{ + struct dma_info *info = get_dma_info(chan); + + info->count = count; +} + diff -puN /dev/null arch/sh/drivers/dma/dma-pvr2.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-pvr2.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,111 @@ +/* + * arch/sh/boards/dreamcast/dma-pvr2.c + * + * NEC PowerVR 2 (Dreamcast) DMA support + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int xfer_complete = 0; +static int count = 0; + +static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (get_dma_residue(PVR2_CASCADE_CHAN)) { + printk(KERN_WARNING "DMA: SH DMAC did not complete transfer " + "on channel %d, waiting..\n", PVR2_CASCADE_CHAN); + dma_wait_for_completion(PVR2_CASCADE_CHAN); + } + + if (count++ < 10) + pr_debug("Got a pvr2 dma interrupt for channel %d\n", + irq - HW_EVENT_PVR2_DMA); + + xfer_complete = 1; + + return IRQ_HANDLED; +} + +static int pvr2_request_dma(struct dma_info *info) +{ + if (ctrl_inl(PVR2_DMA_MODE) != 0) + return -EBUSY; + + ctrl_outl(0, PVR2_DMA_LMMODE0); + + return 0; +} + +static int pvr2_get_dma_residue(struct dma_info *info) +{ + return xfer_complete == 0; +} + +static int pvr2_xfer_dma(struct dma_info *info) +{ + if (info->sar || !info->dar) + return -EINVAL; + + xfer_complete = 0; + + ctrl_outl(info->dar, PVR2_DMA_ADDR); + ctrl_outl(info->count, PVR2_DMA_COUNT); + ctrl_outl(info->mode & DMA_MODE_MASK, PVR2_DMA_MODE); + + return 0; +} + +static struct irqaction pvr2_dma_irq = { + .name = "pvr2 DMA handler", + .handler = pvr2_dma_interrupt, + .flags = SA_INTERRUPT, +}; + +static struct dma_ops pvr2_dma_ops = { + .name = "PowerVR 2 DMA", + .request = pvr2_request_dma, + .get_residue = pvr2_get_dma_residue, + .xfer = pvr2_xfer_dma, +}; + +static int __init pvr2_dma_init(void) +{ + int i, base; + + setup_irq(HW_EVENT_PVR2_DMA, &pvr2_dma_irq); + request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade"); + + /* PVR2 cascade comes after on-chip DMAC */ + base = ONCHIP_NR_DMA_CHANNELS; + + for (i = 0; i < PVR2_NR_DMA_CHANNELS; i++) + dma_info[base + i].ops = &pvr2_dma_ops; + + return register_dmac(&pvr2_dma_ops); +} + +static void __exit pvr2_dma_exit(void) +{ + free_dma(PVR2_CASCADE_CHAN); + free_irq(HW_EVENT_PVR2_DMA, 0); +} + +subsys_initcall(pvr2_dma_init); +module_exit(pvr2_dma_exit); + +MODULE_AUTHOR("Paul Mundt "); +MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver"); +MODULE_LICENSE("GPL"); + diff -puN /dev/null arch/sh/drivers/dma/dma-sh.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-sh.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,271 @@ +/* + * arch/sh/kernel/cpu/dma.c + * + * Copyright (C) 2000 Takashi YOSHII + * Copyright (C) 2003 Paul Mundt + * + * PC like DMA API for SuperH's DMAC. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dma-sh.h" + +/* + * The SuperH DMAC supports a number of transmit sizes, we list them here, + * with their respective values as they appear in the CHCR registers. + * + * Defaults to a 64-bit transfer size. + */ +enum { + XMIT_SZ_64BIT = 0, + XMIT_SZ_8BIT = 1, + XMIT_SZ_16BIT = 2, + XMIT_SZ_32BIT = 3, + XMIT_SZ_256BIT = 4, +}; + +/* + * The DMA count is defined as the number of bytes to transfer. + */ +static unsigned int ts_shift[] = { + [XMIT_SZ_64BIT] 3, + [XMIT_SZ_8BIT] 0, + [XMIT_SZ_16BIT] 1, + [XMIT_SZ_32BIT] 2, + [XMIT_SZ_256BIT] 5, +}; + +struct sh_dmac_channel { + unsigned long sar; + unsigned long dar; + unsigned long dmatcr; + unsigned long chcr; +} __attribute__ ((aligned(16))); + +struct sh_dmac_info { + struct sh_dmac_channel channel[MAX_DMAC_CHANNELS]; + unsigned long dmaor; +} __attribute__ ((packed)); + +static volatile struct sh_dmac_info *sh_dmac = (volatile struct sh_dmac_info *)SH_DMAC_BASE; + +static inline unsigned int get_dmte_irq(unsigned int chan) +{ + unsigned int irq; + + /* + * Normally we could just do DMTE0_IRQ + chan outright, though in the + * case of the 7751R, the DMTE IRQs for channels > 4 start right above + * the SCIF + */ + + if (chan < 4) { + irq = DMTE0_IRQ + chan; + } else { + irq = DMTE4_IRQ + chan; + } + + return irq; +} + +static inline int get_dmte_chan(unsigned int irq) +{ + int chan; + + if ((irq - DMTE4_IRQ) < 0) { + chan = irq - DMTE0_IRQ; + } else { + chan = irq - DMTE4_IRQ + 4; + } + + return chan; +} + +/* + * We determine the correct shift size based off of the CHCR transmit size + * for the given channel. Since we know that it will take: + * + * info->count >> ts_shift[transmit_size] + * + * iterations to complete the transfer. + */ +static inline unsigned int calc_xmit_shift(struct dma_info *info) +{ + return ts_shift[(sh_dmac->channel[info->chan].chcr >> 4) & 0x0007]; +} + +static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) +{ + + int chan = get_dmte_chan(irq); + struct dma_info *info = get_dma_info(chan); + + if (info->sar) + sh_dmac->channel[info->chan].sar = info->sar; + if (info->dar) + sh_dmac->channel[info->chan].sar = info->dar; + + sh_dmac->channel[info->chan].dmatcr = info->count >> calc_xmit_shift(info); + sh_dmac->channel[info->chan].chcr &= ~CHCR_TE; + + disable_irq(irq); + + return IRQ_HANDLED; +} + +static struct irqaction irq_tei = { + .name = "DMAC Transfer End", + .handler = dma_tei, + .flags = SA_INTERRUPT, +}; + +static int sh_dmac_request_dma(struct dma_info *info) +{ + int irq = get_dmte_irq(info->chan); + char *p = (char *)((&irq_tei)->name); + + sprintf(p, "%s (Channel %d)", p, info->chan); + + make_ipr_irq(irq, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); + + return setup_irq(irq, &irq_tei); +} + +static void sh_dmac_free_dma(struct dma_info *info) +{ + free_irq(get_dmte_irq(info->chan), 0); +} + +static void sh_dmac_configure_channel(struct dma_info *info, unsigned long chcr) +{ + if (!chcr) { + chcr = sh_dmac->channel[info->chan].chcr; + chcr |= /* CHCR_IE | */ RS_DUAL; + } + + sh_dmac->channel[info->chan].chcr = chcr; + + info->configured = 1; +} + +static void sh_dmac_enable_dma(struct dma_info *info) +{ + sh_dmac->channel[info->chan].chcr |= CHCR_DE; +} + +static void sh_dmac_disable_dma(struct dma_info *info) +{ + sh_dmac->channel[info->chan].chcr &= ~(CHCR_DE | CHCR_TE); +} + +static int sh_dmac_xfer_dma(struct dma_info *info) +{ + /* + * If we haven't pre-configured the channel with special flags, use + * the defaults. + */ + if (!info->configured) + sh_dmac_configure_channel(info, 0); + + sh_dmac_disable_dma(info); + + /* + * Single-address mode usage note! + * + * It's important that we don't accidentally write any value to SAR/DAR + * (this includes 0) that hasn't been directly specified by the user if + * we're in single-address mode. + * + * In this case, only one address can be defined, anything else will + * result in a DMA address error interrupt (at least on the SH-4), + * which will subsequently halt the transfer. + */ + if (info->sar) + sh_dmac->channel[info->chan].sar = info->sar; + if (info->dar) + sh_dmac->channel[info->chan].dar = info->dar; + + sh_dmac->channel[info->chan].dmatcr = info->count >> calc_xmit_shift(info); + + sh_dmac_enable_dma(info); + + return 0; +} + +static int sh_dmac_get_dma_residue(struct dma_info *info) +{ + return sh_dmac->channel[info->chan].dmatcr << calc_xmit_shift(info); +} + +#if defined(CONFIG_CPU_SH4) +static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) +{ + printk("DMAE: DMAOR=%lx\n", sh_dmac->dmaor); + + sh_dmac->dmaor &= ~(DMAOR_NMIF | DMAOR_AE); + sh_dmac->dmaor |= DMAOR_DME; + + disable_irq(irq); + + return IRQ_HANDLED; +} + +static struct irqaction irq_err = { + .name = "DMAC Address Error", + .handler = dma_err, + .flags = SA_INTERRUPT, +}; +#endif + +static struct dma_ops sh_dmac_ops = { + .name = "SuperH DMAC", + .request = sh_dmac_request_dma, + .free = sh_dmac_free_dma, + .get_residue = sh_dmac_get_dma_residue, + .xfer = sh_dmac_xfer_dma, + .configure = sh_dmac_configure_channel, +}; + +static int __init sh_dmac_init(void) +{ + int i; + +#ifdef CONFIG_CPU_SH4 + make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); + setup_irq(DMAE_IRQ, &irq_err); +#endif + + /* Kick the DMAOR */ + sh_dmac->dmaor |= DMAOR_DME /* | 0x200 */ | 0x8000; /* DDT = 1, PR1 = 1, DME = 1 */ + sh_dmac->dmaor &= ~(DMAOR_NMIF | DMAOR_AE); + + for (i = 0; i < MAX_DMAC_CHANNELS; i++) + dma_info[i].ops = &sh_dmac_ops; + + return register_dmac(&sh_dmac_ops); +} + +static void __exit sh_dmac_exit(void) +{ +#ifdef CONFIG_CPU_SH4 + free_irq(DMAE_IRQ, 0); +#endif +} + +subsys_initcall(sh_dmac_init); +module_exit(sh_dmac_exit); + +MODULE_LICENSE("GPL"); + diff -puN /dev/null arch/sh/drivers/dma/dma-sh.h --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/dma-sh.h 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,48 @@ +/* + * arch/sh/drivers/dma/dma-sh.h + * + * Copyright (C) 2000 Takashi YOSHII + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#ifndef __DMA_SH_H +#define __DMA_SH_H + +/* Definitions for the SuperH DMAC */ +#define REQ_L 0x00000000 +#define REQ_E 0x00080000 +#define RACK_H 0x00000000 +#define RACK_L 0x00040000 +#define ACK_R 0x00000000 +#define ACK_W 0x00020000 +#define ACK_H 0x00000000 +#define ACK_L 0x00010000 +#define DM_INC 0x00004000 +#define DM_DEC 0x00008000 +#define SM_INC 0x00001000 +#define SM_DEC 0x00002000 +#define RS_DUAL 0x00000000 +#define RS_IN 0x00000200 +#define RS_OUT 0x00000300 +#define TM_BURST 0x0000080 +#define TS_8 0x00000010 +#define TS_16 0x00000020 +#define TS_32 0x00000030 +#define TS_64 0x00000000 +#define TS_BLK 0x00000040 +#define CHCR_DE 0x00000001 +#define CHCR_TE 0x00000002 +#define CHCR_IE 0x00000004 + +#define DMAOR_COD 0x00000008 +#define DMAOR_AE 0x00000004 +#define DMAOR_NMIF 0x00000002 +#define DMAOR_DME 0x00000001 + +#define MAX_DMAC_CHANNELS (CONFIG_NR_ONCHIP_DMA_CHANNELS) + +#endif /* __DMA_SH_H */ + diff -puN /dev/null arch/sh/drivers/dma/Kconfig --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,42 @@ +config SH_DMA + bool "DMA controller (DMAC) support" + help + Selecting this option will provide same API as PC's Direct Memory + Access Controller(8237A) for SuperH DMAC. + + If unsure, say N. + +config NR_ONCHIP_DMA_CHANNELS + depends on SH_DMA + int "Number of on-chip DMAC channels" + default "4" + help + This allows you to specify the number of channels that the on-chip + DMAC supports. This will be 4 for SH7750/SH7751 and 8 for the + SH7750R/SH7751R. + +config NR_DMA_CHANNELS_BOOL + depends on SH_DMA + bool "Override default number of maximum DMA channels" + help + This allows you to forcibly update the maximum number of supported + DMA channels for a given board. If this is unset, this will default + to the number of channels that the on-chip DMAC has. + +config NR_DMA_CHANNELS + int "Maximum number of DMA channels" + depends on SH_DMA && NR_DMA_CHANNELS_BOOL + default NR_ONCHIP_DMA_CHANNELS + help + This allows you to specify the maximum number of DMA channels to + support. Setting this to a higher value allows for cascading DMACs + with additional channels. + +config DMA_PAGE_OPS + bool "Use DMAC for page copy/clear" + depends on SH_DMA + help + Selecting this option will use a dual-address mode configured channel + in the SH DMAC for copy_page()/clear_page(). Primarily a performance + hack. + diff -puN /dev/null arch/sh/drivers/dma/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/dma/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,8 @@ +# +# Makefile for the SuperH DMA specific kernel interface routines under Linux. +# + +obj-y += dma-api.o dma-isa.o +obj-$(CONFIG_SH_DMA) += dma-sh.o +obj-$(CONFIG_SH_DREAMCAST) += dma-pvr2.o dma-g2.o + diff -puN /dev/null arch/sh/drivers/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,7 @@ +# +# Makefile for the Linux SuperH-specific device drivers. +# + +obj-$(CONFIG_PCI) += pci/ +obj-$(CONFIG_SH_DMA) += dma/ + diff -puN /dev/null arch/sh/drivers/pci/dma-dreamcast.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/dma-dreamcast.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,61 @@ +/* + * arch/sh/pci/dma-dreamcast.c + * + * PCI DMA support for the Sega Dreamcast + * + * Copyright (C) 2001, 2002 M. R. Brown + * Copyright (C) 2002, 2003 Paul Mundt + * + * This file originally bore the message (with enclosed-$): + * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp + * Dreamcast PCI: Supports SEGA Broadband Adaptor only. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static int gapspci_dma_used = 0; + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + unsigned long buf; + + if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE) + return NULL; + + buf = GAPSPCI_DMA_BASE+gapspci_dma_used; + + gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size); + + *dma_handle = (dma_addr_t)buf; + + buf = P2SEGADDR(buf); + + /* Flush the dcache before we hand off the buffer */ + dma_cache_wback_inv((void *)buf, size); + + return (void *)buf; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + /* XXX */ + gapspci_dma_used = 0; +} + diff -puN /dev/null arch/sh/drivers/pci/fixups-dreamcast.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/fixups-dreamcast.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,85 @@ +/* + * arch/sh/pci/fixups-dreamcast.c + * + * PCI fixups for the Sega Dreamcast + * + * Copyright (C) 2001, 2002 M. R. Brown + * Copyright (C) 2002, 2003 Paul Mundt + * + * This file originally bore the message (with enclosed-$): + * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp + * Dreamcast PCI: Supports SEGA Broadband Adaptor only. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static void __init gapspci_fixup_resources(struct pci_dev *dev) +{ + struct pci_channel *p = board_pci_channels; + + printk(KERN_NOTICE "PCI: Fixing up device %s\n", pci_name(dev)); + + switch (dev->device) { + case PCI_DEVICE_ID_SEGA_BBA: + /* + * We also assume that dev->devfn == 0 + */ + dev->resource[1].start = p->io_resource->start + 0x100; + dev->resource[1].end = dev->resource[1].start + 0x200 - 1; + break; + default: + printk("PCI: Failed resource fixup\n"); + } +} + +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, + PCI_ANY_ID, gapspci_fixup_resources }, + { 0, } +}; + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ + /* + * We don't have any sub bus to fix up, and this is a rather + * stupid place to put general device fixups. Don't do it. + * Use the pcibios_fixups table or suffer the consequences. + */ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = 0; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + /* + * The interrupt routing semantics here are quite trivial. + * + * We basically only support one interrupt, so we only bother + * updating a device's interrupt line with this single shared + * interrupt. Keeps routing quite simple, doesn't it? + */ + printk(KERN_NOTICE "PCI: Fixing up IRQ routing for device %s\n", + pci_name(dev)); + + dev->irq = GAPSPCI_IRQ; + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + diff -puN /dev/null arch/sh/drivers/pci/Kconfig --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,46 @@ +config PCI + bool "PCI support" + help + Find out whether you have a PCI motherboard. PCI is the name of a + bus system, i.e. the way the CPU talks to the other stuff inside + your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or + VESA. If you have PCI, say Y, otherwise N. + + The PCI-HOWTO, available from + , contains valuable + information about which PCI hardware does work under Linux and which + doesn't. + +config SH_PCIDMA_NONCOHERENT + bool "Cache and PCI noncoherent" + depends on PCI + help + Enable this option if your platform does not have a CPU cache which + remains coherent with PCI DMA. It is safest to say 'Y', although you + will see better performance if you can say 'N', because the PCI DMA + code will not have to flush the CPU's caches. If you have a PCI host + bridge integrated with your SH CPU, refer carefully to the chip specs + to see if you can say 'N' here. Otherwise, leave it as 'Y'. + +# This is also board-specific +config PCI_AUTO + bool + depends on PCI + default y + +config PCI_AUTO_UPDATE_RESOURCES + bool + depends on PCI_AUTO + default y if !SH_DREAMCAST + help + Selecting this option will cause the PCI auto code to leave your + BAR values alone. Otherwise they will be updated automatically. If + for some reason, you have a board that simply refuses to work + with its resources updated beyond what they are when the device + is powered up, set this to N. Everyone else will want this as Y. + +config PCI_DMA + bool + depends on PCI + default y if !SH_DREAMCAST + diff -puN /dev/null arch/sh/drivers/pci/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,16 @@ +# +# Makefile for the PCI specific kernel interface routines under Linux. +# + +obj-y += pci.o +obj-$(CONFIG_PCI_AUTO) += pci-auto.o +obj-$(CONFIG_PCI_DMA) += pci-dma.o + +obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o +obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o + +obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ + dma-dreamcast.o +obj-$(CONFIG_SH_SECUREEDGE5410) += ops-snapgear.o +obj-$(CONFIG_SH_BIGSUR) += ops-bigsur.o + diff -puN /dev/null arch/sh/drivers/pci/ops-bigsur.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/ops-bigsur.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,88 @@ +/* + * linux/arch/sh/kernel/pci-bigsur.c + * + * By Dustin McIntire (dustin@sensoria.com) (c)2001 + * + * Ported to new API by Paul Mundt . + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the Hitachi Big Sur Evaluation Board + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "pci-sh7751.h" +#include + +#define BIGSUR_PCI_IO 0x4000 +#define BIGSUR_PCI_MEM 0xfd000000 + +static struct resource sh7751_io_resource = { + .name = "SH7751 IO", + .start = BIGSUR_PCI_IO, + .end = BIGSUR_PCI_IO + (64*1024) - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource sh7751_mem_resource = { + .name = "SH7751 mem", + .start = BIGSUR_PCI_MEM, + .end = BIGSUR_PCI_MEM + (64*1024*1024) - 1, + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops sh7751_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { 0, } +}; + +static struct sh7751_pci_address_map sh7751_pci_map = { + .window0 = { + .base = SH7751_CS3_BASE_ADDR, + .size = BIGSUR_LSR0_SIZE, + }, + + .window1 = { + .base = SH7751_CS3_BASE_ADDR, + .size = BIGSUR_LSR1_SIZE, + }, +}; + +/* + * Initialize the Big Sur PCI interface + * Setup hardware to be Central Funtion + * Copy the BSR regs to the PCI interface + * Setup PCI windows into local RAM + */ +int __init pcibios_init_platform(void) +{ + return sh7751_pcic_init(&sh7751_pci_map); +} + +int pcibios_map_platform_irq(u8 slot, u8 pin) +{ + /* + * The Big Sur can be used in a CPCI chassis, but the SH7751 PCI + * interface is on the wrong end of the board so that it can also + * support a V320 CPI interface chip... Therefor the IRQ mapping is + * somewhat use dependent... I'l assume a linear map for now, i.e. + * INTA=slot0,pin0... INTD=slot3,pin0... + */ + int irq = (slot + pin-1) % 4 + BIGSUR_SH7751_PCI_IRQ_BASE; + + PCIDBG(2, "PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", + slot, pin-1+'A', irq); + + return irq; +} + diff -puN /dev/null arch/sh/drivers/pci/ops-dreamcast.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/ops-dreamcast.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,169 @@ +/* + * arch/sh/pci/ops-dreamcast.c + * + * PCI operations for the Sega Dreamcast + * + * Copyright (C) 2001, 2002 M. R. Brown + * Copyright (C) 2002, 2003 Paul Mundt + * + * This file originally bore the message (with enclosed-$): + * Id: pci.c,v 1.3 2003/05/04 19:29:46 lethal Exp + * Dreamcast PCI: Supports SEGA Broadband Adaptor only. + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct resource gapspci_io_resource = { + .name = "GAPSPCI IO", + .start = GAPSPCI_BBA_CONFIG, + .end = GAPSPCI_BBA_CONFIG + GAPSPCI_BBA_CONFIG_SIZE - 1, + .flags = IORESOURCE_IO, +}; + +static struct resource gapspci_mem_resource = { + .name = "GAPSPCI mem", + .start = GAPSPCI_DMA_BASE, + .end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_ops gapspci_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &gapspci_pci_ops, &gapspci_io_resource, + &gapspci_mem_resource, 0, 1 }, + { 0, } +}; + +/* + * The !gapspci_config_access case really shouldn't happen, ever, unless + * someone implicitly messes around with the last devfn value.. otherwise we + * only support a single device anyways, and if we didn't have a BBA, we + * wouldn't make it terribly far through the PCI setup anyways. + * + * Also, we could very easily support both Type 0 and Type 1 configurations + * here, but since it doesn't seem that there is any such implementation in + * existance, we don't bother. + * + * I suppose if someone actually gets around to ripping the chip out of + * the BBA and hanging some more devices off of it, then this might be + * something to take into consideration. However, due to the cost of the BBA, + * and the general lack of activity by DC hardware hackers, this doesn't seem + * likely to happen anytime soon. + */ +static int gapspci_config_access(unsigned char bus, unsigned int devfn) +{ + return (bus == 0) && (devfn == 0); +} + +/* + * We can also actually read and write in b/w/l sizes! Thankfully this part + * was at least done right, and we don't have to do the stupid masking and + * shifting that we do on the 7751! Small wonders never cease to amaze. + */ +static int gapspci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) +{ + *val = 0xffffffff; + + if (!gapspci_config_access(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 1: *val = inb(GAPSPCI_BBA_CONFIG+where); break; + case 2: *val = inw(GAPSPCI_BBA_CONFIG+where); break; + case 4: *val = inl(GAPSPCI_BBA_CONFIG+where); break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int gapspci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) +{ + if (!gapspci_config_access(bus->number, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + switch (size) { + case 1: outb(( u8)val, GAPSPCI_BBA_CONFIG+where); break; + case 2: outw((u16)val, GAPSPCI_BBA_CONFIG+where); break; + case 4: outl((u32)val, GAPSPCI_BBA_CONFIG+where); break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops gapspci_pci_ops = { + .read = gapspci_read, + .write = gapspci_write, +}; + +/* + * gapspci init + */ + +int __init gapspci_init(void) +{ + char idbuf[16]; + int i; + + /* + * FIXME: All of this wants documenting to some degree, + * even some basic register definitions would be nice. + * + * I haven't seen anything this ugly since.. maple. + */ + + for (i=0; i<16; i++) + idbuf[i] = inb(GAPSPCI_REGS+i); + + if (strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16)) + return -ENODEV; + + outl(0x5a14a501, GAPSPCI_REGS+0x18); + + for (i=0; i<1000000; i++) + ; + + if (inl(GAPSPCI_REGS+0x18) != 1) + return -EINVAL; + + outl(0x01000000, GAPSPCI_REGS+0x20); + outl(0x01000000, GAPSPCI_REGS+0x24); + + outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28); + outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c); + + outl(1, GAPSPCI_REGS+0x14); + outl(1, GAPSPCI_REGS+0x34); + + /* Setting Broadband Adapter */ + outw(0xf900, GAPSPCI_BBA_CONFIG+0x06); + outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30); + outb(0x00, GAPSPCI_BBA_CONFIG+0x3c); + outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d); + outw(0x0006, GAPSPCI_BBA_CONFIG+0x04); + outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10); + outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14); + + return 0; +} + +/* Haven't done anything here as yet */ +char * __devinit pcibios_setup(char *str) +{ + return str; +} diff -puN /dev/null arch/sh/drivers/pci/ops-snapgear.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/ops-snapgear.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,100 @@ +/* + * arch/sh/drivers/pci/ops-snapgear.c + * + * Author: David McCullough + * + * Ported to new API by Paul Mundt + * + * Highly leveraged from pci-bigsur.c, written by Dustin McIntire. + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * PCI initialization for the SnapGear boards + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "pci-sh7751.h" + +#define SNAPGEAR_PCI_IO 0x4000 +#define SNAPGEAR_PCI_MEM 0xfd000000 + +/* PCI: default LOCAL memory window sizes (seen from PCI bus) */ +#define SNAPGEAR_LSR0_SIZE (64*(1<<20)) //64MB +#define SNAPGEAR_LSR1_SIZE (64*(1<<20)) //64MB + +static struct resource sh7751_io_resource = { + .name = "SH7751 IO", + .start = SNAPGEAR_PCI_IO, + .end = SNAPGEAR_PCI_IO + (64*1024) - 1, /* 64KiB I/O */ + .flags = IORESOURCE_IO, +}; + +static struct resource sh7751_mem_resource = { + .name = "SH7751 mem", + .start = SNAPGEAR_PCI_MEM, + .end = SNAPGEAR_PCI_MEM + (64*1024*1024) - 1, /* 64MiB mem */ + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops sh7751_pci_ops; + +struct pci_channel board_pci_channels[] = { + { &sh7751_pci_ops, &sh7751_io_resource, &sh7751_mem_resource, 0, 0xff }, + { 0, } +}; + +static struct sh7751_pci_address_map sh7751_pci_map = { + .window0 = { + .base = SH7751_CS2_BASE_ADDR, + .size = SNAPGEAR_LSR0_SIZE, + }, + + .window1 = { + .base = SH7751_CS2_BASE_ADDR, + .size = SNAPGEAR_LSR1_SIZE, + }, +}; + +/* + * Initialize the SnapGear PCI interface + * Setup hardware to be Central Funtion + * Copy the BSR regs to the PCI interface + * Setup PCI windows into local RAM + */ +int __init pcibios_init_platform(void) +{ + return sh7751_pcic_init(&sh7751_pci_map); +} + +int __init pcibios_map_platform_irq(u8 slot, u8 pin) +{ + int irq = -1; + + switch (slot) { + case 8: /* the PCI bridge */ break; + case 11: irq = 8; break; /* USB */ + case 12: irq = 11; break; /* PCMCIA */ + case 13: irq = 5; break; /* eth0 */ + case 14: irq = 8; break; /* eth1 */ + case 15: irq = 11; break; /* safenet (unused) */ + } + + printk("PCI: Mapping SnapGear IRQ for slot %d, pin %c to irq %d\n", + slot, pin - 1 + 'A', irq); + + return irq; +} + +void __init pcibios_fixup(void) +{ + /* Nothing to fixup .. */ +} + diff -puN /dev/null arch/sh/drivers/pci/pci-auto.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-auto.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,534 @@ +/* + * PCI autoconfiguration library + * + * Author: Matt Porter + * + * Copyright 2000, 2001 MontaVista Software Inc. + * Copyright 2001 Bradley D. LaRonde + * Copyright 2003 Paul Mundt + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * Modified for MIPS by Jun Sun, jsun@mvista.com + * + * . Simplify the interface between pci_auto and the rest: a single function. + * . Assign resources from low address to upper address. + * . change most int to u32. + * + * Further modified to include it as mips generic code, ppopov@mvista.com. + * + * 2001-10-26 Bradley D. LaRonde + * - Add a top_bus argument to the "early config" functions so that + * they can set a fake parent bus pointer to convince the underlying + * pci ops to use type 1 configuration for sub busses. + * - Set bridge base and limit registers correctly. + * - Align io and memory base properly before and after bridge setup. + * - Don't fall through to pci_setup_bars for bridge. + * - Reformat the debug output to look more like lspci's output. + * + * Cloned for SuperH by M. R. Brown, mrbrown@0xd6.org + * + * 2003-08-05 Paul Mundt + * - Don't update the BAR values on systems that already have valid addresses + * and don't want these updated for whatever reason, by way of a new config + * option check. However, we still read in the old BAR values so that they + * can still be reported through the debug output. + */ + +#include +#include +#include +#include + +#define DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_dev *fake_pci_dev(struct pci_channel *hose, + int top_bus, int busnr, int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose->pci_ops; + + if(busnr != top_bus) + /* Fake a parent bus structure. */ + bus.parent = &bus; + else + bus.parent = NULL; + + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_channel *hose, \ + int top_bus, int bus, int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size( \ + fake_pci_dev(hose, top_bus, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) + +static struct resource *io_resource_inuse; +static struct resource *mem_resource_inuse; + +static u32 pciauto_lower_iospc; +static u32 pciauto_upper_iospc; + +static u32 pciauto_lower_memspc; +static u32 pciauto_upper_memspc; + +static void __init +pciauto_setup_bars(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn) +{ + u32 bar_response, bar_size, bar_value; + u32 bar, addr_mask, bar_nr = 0; + u32 * upper_limit; + u32 * lower_limit; + int found_mem64 = 0; + + for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { + u32 bar_addr; + + /* Read the old BAR value */ + early_read_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, + &bar_addr); + + /* Tickle the BAR and get the response */ + early_write_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, + 0xffffffff); + + early_read_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, + &bar_response); + + /* + * Write the old BAR value back out, only update the BAR + * if we implicitly want resources to be updated, which + * is done by the generic code further down. -- PFM. + */ + early_write_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, + bar_addr); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + /* + * Workaround for a BAR that doesn't use its upper word, + * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457). + * bdl + */ + if (!(bar_response & 0xffff0000)) + bar_response |= 0xffff0000; + +retry: + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + addr_mask = PCI_BASE_ADDRESS_IO_MASK; + upper_limit = &pciauto_upper_iospc; + lower_limit = &pciauto_lower_iospc; + DBG(" I/O"); + } else { + if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + addr_mask = PCI_BASE_ADDRESS_MEM_MASK; + upper_limit = &pciauto_upper_memspc; + lower_limit = &pciauto_lower_memspc; + DBG(" Mem"); + } + + + /* Calculate requested size */ + bar_size = ~(bar_response & addr_mask) + 1; + + /* Allocate a base address */ + bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; + + if ((bar_value + bar_size) > *upper_limit) { + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + if (io_resource_inuse->child) { + io_resource_inuse = + io_resource_inuse->child; + pciauto_lower_iospc = + io_resource_inuse->start; + pciauto_upper_iospc = + io_resource_inuse->end + 1; + goto retry; + } + + } else { + if (mem_resource_inuse->child) { + mem_resource_inuse = + mem_resource_inuse->child; + pciauto_lower_memspc = + mem_resource_inuse->start; + pciauto_upper_memspc = + mem_resource_inuse->end + 1; + goto retry; + } + } + DBG(" unavailable -- skipping, value %x size %x\n", + bar_value, bar_size); + continue; + } + +#ifdef CONFIG_PCI_AUTO_UPDATE_RESOURCES + /* Write it out and update our limit */ + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + bar, bar_value); +#endif + + *lower_limit = bar_value + bar_size; + + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ + if (found_mem64) { + bar += 4; + early_write_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, + 0x00000000); + } + + DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size); + + bar_nr++; + } + +} + +static void __init +pciauto_prescan_setup_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, + int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_PRIMARY_BUS, current_bus); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SECONDARY_BUS, sub_bus + 1); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, 0xff); + + /* Align memory and I/O to 1MB and 4KB boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) + & ~(0x100000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) + & ~(0x1000 - 1); + + /* Set base (lower limit) of address range behind bridge. */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_MEMORY_BASE, pciauto_lower_memspc >> 16); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16); + + /* We don't support prefetchable memory for now, so disable */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_PREF_MEMORY_BASE, 0); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_PREF_MEMORY_LIMIT, 0); +} + +static void __init +pciauto_postscan_setup_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, + int sub_bus) +{ + u32 temp; + + pciauto_lower_memspc += 1; + pciauto_lower_iospc += 1; + + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, sub_bus); + + /* Set upper limit of address range behind bridge. */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16); + + /* Align memory and I/O to 1MB and 4KB boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) + & ~(0x100000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) + & ~(0x1000 - 1); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, &temp); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); +} + +static void __init +pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, + int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_PRIMARY_BUS, current_bus); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SECONDARY_BUS, sub_bus + 1); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, 0xff); + + /* Align memory and I/O to 4KB and 4 byte boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) + & ~(0x1000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) + & ~(0x4 - 1); + + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_IO_BASE_0, pciauto_lower_iospc); +} + +static void __init +pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, + int sub_bus) +{ + u32 temp; + + /* + * [jsun] we always bump up baselines a little, so that if there + * nothing behind P2P bridge, we don't wind up overlapping IO/MEM + * spaces. + */ + pciauto_lower_memspc += 1; + pciauto_lower_iospc += 1; + + /* + * Configure subordinate bus number. The PCI subsystem + * bus scan will renumber buses (reserving three additional + * for this PCI<->CardBus bridge for the case where a CardBus + * adapter contains a P2P or CB2CB bridge. + */ + + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, sub_bus); + + /* + * Reserve an additional 4MB for mem space and 16KB for + * I/O space. This should cover any additional space + * requirement of unusual CardBus devices with + * additional bridges that can consume more address space. + * + * Although pcmcia-cs currently will reprogram bridge + * windows, the goal is to add an option to leave them + * alone and use the bridge window ranges as the regions + * that are searched for free resources upon hot-insertion + * of a device. This will allow a PCI<->CardBus bridge + * configured by this routine to happily live behind a + * P2P bridge in a system. + */ + + /* Align memory and I/O to 4KB and 4 byte boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) + & ~(0x1000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) + & ~(0x4 - 1); + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, &temp); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); +} + +#define PCIAUTO_IDE_MODE_MASK 0x05 + +static int __init +pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) +{ + int sub_bus; + u32 pci_devfn, pci_class, cmdstat, found_multi=0; + unsigned short vid, did; + unsigned char header_type; + int devfn_start = 0; + int devfn_stop = 0xff; + + sub_bus = current_bus; + + if (hose->first_devfn) + devfn_start = hose->first_devfn; + if (hose->last_devfn) + devfn_stop = hose->last_devfn; + + for (pci_devfn=devfn_start; pci_devfn> 16, vid, did); + if (pci_class & 0xff) + DBG(" (rev %.2x)", pci_class & 0xff); + DBG("\n"); + + if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { + DBG(" Bridge: primary=%.2x, secondary=%.2x\n", + current_bus, sub_bus + 1); + pciauto_prescan_setup_bridge(hose, top_bus, current_bus, + pci_devfn, sub_bus); + DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", + sub_bus + 1, + pciauto_lower_iospc, pciauto_lower_memspc); + sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); + DBG("Back to bus %.2x\n", current_bus); + pciauto_postscan_setup_bridge(hose, top_bus, current_bus, + pci_devfn, sub_bus); + continue; + } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) { + DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n", + current_bus, sub_bus + 1); + DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); + /* Place CardBus Socket/ExCA registers */ + pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); + + pciauto_prescan_setup_cardbus_bridge(hose, top_bus, + current_bus, pci_devfn, sub_bus); + + DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", + sub_bus + 1, + pciauto_lower_iospc, pciauto_lower_memspc); + sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); + DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus); + pciauto_postscan_setup_cardbus_bridge(hose, top_bus, + current_bus, pci_devfn, sub_bus); + continue; + } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { + + unsigned char prg_iface; + + early_read_config_byte(hose, top_bus, current_bus, + pci_devfn, PCI_CLASS_PROG, &prg_iface); + if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { + DBG("Skipping legacy mode IDE controller\n"); + continue; + } + } + + /* + * Found a peripheral, enable some standard + * settings + */ + early_read_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, &cmdstat); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, cmdstat | PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_LATENCY_TIMER, 0x80); + + /* Allocate PCI I/O and/or memory space */ + pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); + } + return sub_bus; +} + +int __init +pciauto_assign_resources(int busno, struct pci_channel *hose) +{ + /* setup resource limits */ + io_resource_inuse = hose->io_resource; + mem_resource_inuse = hose->mem_resource; + + pciauto_lower_iospc = io_resource_inuse->start; + pciauto_upper_iospc = io_resource_inuse->end + 1; + pciauto_lower_memspc = mem_resource_inuse->start; + pciauto_upper_memspc = mem_resource_inuse->end + 1; + DBG("Autoconfig PCI channel 0x%p\n", hose); + DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n", + busno, pciauto_lower_iospc, pciauto_upper_iospc, + pciauto_lower_memspc, pciauto_upper_memspc); + + return pciauto_bus_scan(hose, busno, busno); +} diff -puN /dev/null arch/sh/drivers/pci/pci.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,153 @@ +/* arch/sh/kernel/pci.c + * $Id: pci.c,v 1.1 2003/08/24 19:15:45 lethal Exp $ + * + * Copyright (c) 2002 M. R. Brown + * + * + * These functions are collected here to reduce duplication of common + * code amongst the many platform-specific PCI support code files. + * + * These routines require the following board-specific routines: + * void pcibios_fixup_irqs(); + * + * See include/asm-sh/pci.h for more information. + */ + +#include +#include +#include + +static int __init pcibios_init(void) +{ + struct pci_channel *p; + struct pci_bus *bus; + int busno; + +#ifdef CONFIG_PCI_AUTO + /* assign resources */ + busno=0; + for (p = board_pci_channels; p->pci_ops != NULL; p++) { + busno = pciauto_assign_resources(busno, p) + 1; + } +#endif + + /* scan the buses */ + busno = 0; + for (p= board_pci_channels; p->pci_ops != NULL; p++) { + bus = pci_scan_bus(busno, p->pci_ops, p); + busno = bus->subordinate+1; + } + + /* board-specific fixups */ + pcibios_fixup_irqs(); + + return 0; +} + +subsys_initcall(pcibios_init); + +void +pcibios_update_resource(struct pci_dev *dev, struct resource *root, + struct resource *res, int resource) +{ + u32 new, check; + int reg; + + new = res->start | (res->flags & PCI_REGION_FLAG_MASK); + if (resource < 6) { + reg = PCI_BASE_ADDRESS_0 + 4*resource; + } else if (resource == PCI_ROM_RESOURCE) { + res->flags |= PCI_ROM_ADDRESS_ENABLE; + new |= PCI_ROM_ADDRESS_ENABLE; + reg = dev->rom_base_reg; + } else { + /* Somebody might have asked allocation of a non-standard resource */ + return; + } + + pci_write_config_dword(dev, reg, new); + pci_read_config_dword(dev, reg, &check); + if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { + printk(KERN_ERR "PCI: Error while updating region " + "%s/%d (%08x != %08x)\n", pci_name(dev), resource, + new, check); + } +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) + __attribute__ ((weak)); + +/* + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + */ +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } + } +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for(idx=0; idx<6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR "PCI: Device %s not available because " + "of resource collisions\n", pci_name(dev)); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", + pci_name(dev), old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +/* + * If we set up a device for bus mastering, we need to check and set + * the latency timer as it may not be properly set. + */ +unsigned int pcibios_max_latency = 255; + +void pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat < 16) + lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; + else if (lat > pcibios_max_latency) + lat = pcibios_max_latency; + else + return; + printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} diff -puN /dev/null arch/sh/drivers/pci/pci-dma.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-dma.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Dynamic DMA mapping support. + */ + +#include +#include +#include +#include +#include +#include + + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + /* Is it necessary to do the memset? */ + memset(ret, 0, size); + *dma_handle = virt_to_phys(ret); + } + /* We must flush the cache before we pass it on to the device */ + dma_cache_wback_inv(ret, size); + return P2SEGADDR(ret); +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); + + free_pages(p1addr, get_order(size)); +} diff -puN /dev/null arch/sh/drivers/pci/pci-sh7751.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-sh7751.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,414 @@ +/* + * Low-Level PCI Support for the SH7751 + * + * Dustin McIntire (dustin@sensoria.com) + * Derived from arch/i386/kernel/pci-*.c which bore the message: + * (c) 1999--2000 Martin Mares + * + * Ported to the new API by Paul Mundt + * With cleanup by Paul van Gool + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + */ + +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pci-sh7751.h" + +static unsigned int pci_probe = PCI_PROBE_CONF1; + +/* + * Direct access to PCI hardware... + */ + +#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) + +/* + * Functions for accessing PCI configuration space with type 1 accesses + */ +static int sh7751_pci_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) +{ + unsigned long flags; + u32 data; + + /* + * PCIPDR may only be accessed as 32 bit words, + * so we must do byte alignment by hand + */ + local_irq_save(flags); + outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); + data = inl(PCI_REG(SH7751_PCIPDR)); + local_irq_restore(flags); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xff; + break; + case 2: + *val = (data >> ((where & 2) << 3)) & 0xffff; + break; + case 4: + *val = data; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + return PCIBIOS_SUCCESSFUL; +} + +/* + * Since SH7751 only does 32bit access we'll have to do a read,mask,write operation. + * We'll allow an odd byte offset, though it should be illegal. + */ +static int sh7751_pci_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + unsigned long flags; + int shift; + u32 data; + + local_irq_save(flags); + outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); + data = inl(PCI_REG(SH7751_PCIPDR)); + local_irq_restore(flags); + + switch (size) { + case 1: + shift = (where & 3) << 3; + data &= ~(0xff << shift); + data |= ((val & 0xff) << shift); + break; + case 2: + shift = (where & 2) << 3; + data &= ~(0xffff << shift); + data |= ((val & 0xffff) << shift); + break; + case 4: + data = val; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + outl(data, PCI_REG(SH7751_PCIPDR)); + + return PCIBIOS_SUCCESSFUL; +} + +#undef CONFIG_CMD + +struct pci_ops sh7751_pci_ops = { + .read = sh7751_pci_read, + .write = sh7751_pci_write, +}; + +static int __init pci_check_direct(void) +{ + unsigned int tmp, id; + + /* check for SH7751/SH7751R hardware */ + id = inl(SH7751_PCIREG_BASE+SH7751_PCICONF0); + if (id != ((SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID) && + id != ((SH7751R_DEVICE_ID << 16) | SH7751_VENDOR_ID)) { + pr_debug("PCI: This is not an SH7751(R) (%x)\n", id); + return -ENODEV; + } + + /* + * Check if configuration works. + */ + if (pci_probe & PCI_PROBE_CONF1) { + tmp = inl (PCI_REG(SH7751_PCIPAR)); + outl (0x80000000, PCI_REG(SH7751_PCIPAR)); + if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) { + outl (tmp, PCI_REG(SH7751_PCIPAR)); + printk(KERN_INFO "PCI: Using configuration type 1\n"); + request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1"); + return 0; + } + outl (tmp, PCI_REG(SH7751_PCIPAR)); + } + + pr_debug("PCI: pci_check_direct failed\n"); + return -EINVAL; +} + +/***************************************************************************************/ + +/* + * Handle bus scanning and fixups .... + */ + +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + pr_debug("PCI: IDE base address fixup for %s\n", d->slot_name); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} + + +/* Add future fixups here... */ +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { 0 } +}; + +/* + * Called after each bus is probed, but before its children + * are examined. + */ + +void __init pcibios_fixup_bus(struct pci_bus *b) +{ + pci_read_bridge_bases(b); +} + +/* + * Initialization. Try all known PCI access methods. Note that we support + * using both PCI BIOS and direct access: in such cases, we use I/O ports + * to access config space. + * + * Note that the platform specific initialization (BSC registers, and memory + * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it + * exitst and via the platform defined function pcibios_init_platform(). + * See pci_bigsur.c for implementation; + * + * The BIOS version of the pci functions is not yet implemented but it is left + * in for completeness. Currently an error will be genereated at compile time. + */ + +static int __init sh7751_pci_init(void) +{ + int ret; + + pr_debug("PCI: Starting intialization.\n"); + if ((ret = pci_check_direct()) != 0) + return ret; + + return pcibios_init_platform(); +} + +subsys_initcall(sh7751_pci_init); + +static int __init __area_sdram_check(unsigned int area) +{ + u32 word; + + word = inl(SH7751_BCR1); + /* check BCR for SDRAM in area */ + if(((word >> area) & 1) == 0) { + printk("PCI: Area %d is not configured for SDRAM. BCR1=0x%x\n", + area, word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR1)); + + word = (u16)inw(SH7751_BCR2); + /* check BCR2 for 32bit SDRAM interface*/ + if(((word >> (area << 1)) & 0x3) != 0x3) { + printk("PCI: Area %d is not 32 bit SDRAM. BCR2=0x%x\n", + area, word); + return 0; + } + outl(word, PCI_REG(SH7751_PCIBCR2)); + + return 1; +} + +int __init sh7751_pcic_init(struct sh7751_pci_address_map *map) +{ + u32 reg; + u32 word; + + /* Set the BCR's to enable PCI access */ + reg = inl(SH7751_BCR1); + reg |= 0x80000; + outl(reg, SH7751_BCR1); + + /* Turn the clocks back on (not done in reset)*/ + outl(0, PCI_REG(SH7751_PCICLKR)); + /* Clear Powerdown IRQ's (not done in reset) */ + word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0; + outl(word, PCI_REG(SH7751_PCICLKR)); + + /* + * XXX: This code is unused for the SnapGear boards as it is done in + * the bootloader and doing it here means the MAC addresses loaded by + * the bootloader get lost. + */ +#ifndef CONFIG_SH_SECUREEDGE5410 + /* toggle PCI reset pin */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST; + outl(word,PCI_REG(SH7751_PCICR)); + /* Wait for a long time... not 1 sec. but long enough */ + mdelay(100); + word = SH7751_PCICR_PREFIX; + outl(word,PCI_REG(SH7751_PCICR)); +#endif + + /* set the command/status bits to: + * Wait Cycle Control + Parity Enable + Bus Master + + * Mem space enable + */ + word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | + SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES; + outl(word, PCI_REG(SH7751_PCICONF1)); + + /* define this host as the host bridge */ + word = SH7751_PCI_HOST_BRIDGE << 24; + outl(word, PCI_REG(SH7751_PCICONF2)); + + /* Set IO and Mem windows to local address + * Make PCI and local address the same for easy 1 to 1 mapping + * Window0 = map->window0.size @ non-cached area base = SDRAM + * Window1 = map->window1.size @ cached area base = SDRAM + */ + word = map->window0.size - 1; + outl(word, PCI_REG(SH7751_PCILSR0)); + word = map->window1.size - 1; + outl(word, PCI_REG(SH7751_PCILSR1)); + /* Set the values on window 0 PCI config registers */ + word = P2SEGADDR(map->window0.base); + outl(word, PCI_REG(SH7751_PCILAR0)); + outl(word, PCI_REG(SH7751_PCICONF5)); + /* Set the values on window 1 PCI config registers */ + word = PHYSADDR(map->window1.base); + outl(word, PCI_REG(SH7751_PCILAR1)); + outl(word, PCI_REG(SH7751_PCICONF6)); + + /* Set the local 16MB PCI memory space window to + * the lowest PCI mapped address + */ + word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word); + outl(word , PCI_REG(SH7751_PCIMBR)); + + /* Map IO space into PCI IO window + * The IO window is 64K-PCIBIOS_MIN_IO in size + * IO addresses will be translated to the + * PCI IO window base address + */ + PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO, + (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO); + + /* + * XXX: For now, leave this board-specific. In the event we have other + * boards that need to do similar work, this can be wrapped. + */ +#ifdef CONFIG_SH_BIGSUR + bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0); +#endif + + /* Make sure the MSB's of IO window are set to access PCI space correctly */ + word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK; + PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word); + outl(word, PCI_REG(SH7751_PCIIOBR)); + + /* Set PCI WCRx, BCRx's, copy from BSC locations */ + + /* check BCR for SDRAM in specified area */ + switch (map->window0.base) { + case SH7751_CS0_BASE_ADDR: word = __area_sdram_check(0); break; + case SH7751_CS1_BASE_ADDR: word = __area_sdram_check(1); break; + case SH7751_CS2_BASE_ADDR: word = __area_sdram_check(2); break; + case SH7751_CS3_BASE_ADDR: word = __area_sdram_check(3); break; + case SH7751_CS4_BASE_ADDR: word = __area_sdram_check(4); break; + case SH7751_CS5_BASE_ADDR: word = __area_sdram_check(5); break; + case SH7751_CS6_BASE_ADDR: word = __area_sdram_check(6); break; + } + + if (!word) + return 0; + + /* configure the wait control registers */ + word = inl(SH7751_WCR1); + outl(word, PCI_REG(SH7751_PCIWCR1)); + word = inl(SH7751_WCR2); + outl(word, PCI_REG(SH7751_PCIWCR2)); + word = inl(SH7751_WCR3); + outl(word, PCI_REG(SH7751_PCIWCR3)); + word = inl(SH7751_MCR); + outl(word, PCI_REG(SH7751_PCIMCR)); + + /* NOTE: I'm ignoring the PCI error IRQs for now.. + * TODO: add support for the internal error interrupts and + * DMA interrupts... + */ + + /* SH7751 init done, set central function init complete */ + /* use round robin mode to stop a device starving/overruning */ + word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN | SH7751_PCICR_ARBM; + outl(word,PCI_REG(SH7751_PCICR)); + + return 1; +} + +char * __init pcibios_setup(char *str) +{ + if (!strcmp(str, "off")) { + pci_probe = 0; + return NULL; + } + + return str; +} + +/* + * IRQ functions + */ +static u8 __init sh7751_no_swizzle(struct pci_dev *dev, u8 *pin) +{ + /* no swizzling */ + return PCI_SLOT(dev->devfn); +} + +static int sh7751_pci_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = -1; + + /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ + irq = pcibios_map_platform_irq(slot,pin); + if( irq < 0 ) { + pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name); + return irq; + } + + pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq); + + return irq; +} + +void __init pcibios_fixup_irqs(void) +{ + pci_fixup_irqs(sh7751_no_swizzle, sh7751_pci_lookup_irq); +} + diff -puN /dev/null arch/sh/drivers/pci/pci-sh7751.h --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-sh7751.h 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,296 @@ +/* + * Low-Level PCI Support for SH7751 targets + * + * Dustin McIntire (dustin@sensoria.com) (c) 2001 + * Paul Mundt (lethal@linux-sh.org) (c) 2003 + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + */ + +#ifndef _PCI_SH7751_H_ +#define _PCI_SH7751_H_ + +#include + +/* set debug level 4=verbose...1=terse */ +//#define DEBUG_PCI 3 +#undef DEBUG_PCI + +#ifdef DEBUG_PCI +#define PCIDBG(n, x...) { if(DEBUG_PCI>=n) printk(x); } +#else +#define PCIDBG(n, x...) +#endif + +/* startup values */ +#define PCI_PROBE_BIOS 1 +#define PCI_PROBE_CONF1 2 +#define PCI_PROBE_CONF2 4 +#define PCI_NO_SORT 0x100 +#define PCI_BIOS_SORT 0x200 +#define PCI_NO_CHECKS 0x400 +#define PCI_ASSIGN_ROMS 0x1000 +#define PCI_BIOS_IRQ_SCAN 0x2000 + +/* Platform Specific Values */ +#define SH7751_VENDOR_ID 0x1054 +#define SH7751_DEVICE_ID 0x3505 +#define SH7751R_DEVICE_ID 0x350e + +/* SH7751 Specific Values */ +#define SH7751_PCI_CONFIG_BASE 0xFD000000 /* Config space base addr */ +#define SH7751_PCI_CONFIG_SIZE 0x1000000 /* Config space size */ +#define SH7751_PCI_MEMORY_BASE 0xFD000000 /* Memory space base addr */ +#define SH7751_PCI_MEM_SIZE 0x01000000 /* Size of Memory window */ +#define SH7751_PCI_IO_BASE 0xFE240000 /* IO space base address */ +#define SH7751_PCI_IO_SIZE 0x40000 /* Size of IO window */ + +#define SH7751_PCIREG_BASE 0xFE200000 /* PCI regs base address */ +#define PCI_REG(n) (SH7751_PCIREG_BASE+ n) + +#define SH7751_PCICONF0 0x0 /* PCI Config Reg 0 */ + #define SH7751_PCICONF0_DEVID 0xFFFF0000 /* Device ID */ + #define SH7751_PCICONF0_VNDID 0x0000FFFF /* Vendor ID */ +#define SH7751_PCICONF1 0x4 /* PCI Config Reg 1 */ + #define SH7751_PCICONF1_DPE 0x80000000 /* Data Parity Error */ + #define SH7751_PCICONF1_SSE 0x40000000 /* System Error Status */ + #define SH7751_PCICONF1_RMA 0x20000000 /* Master Abort */ + #define SH7751_PCICONF1_RTA 0x10000000 /* Target Abort Rx Status */ + #define SH7751_PCICONF1_STA 0x08000000 /* Target Abort Exec Status */ + #define SH7751_PCICONF1_DEV 0x06000000 /* Timing Status */ + #define SH7751_PCICONF1_DPD 0x01000000 /* Data Parity Status */ + #define SH7751_PCICONF1_FBBC 0x00800000 /* Back 2 Back Status */ + #define SH7751_PCICONF1_UDF 0x00400000 /* User Defined Status */ + #define SH7751_PCICONF1_66M 0x00200000 /* 66Mhz Operation Status */ + #define SH7751_PCICONF1_PM 0x00100000 /* Power Management Status */ + #define SH7751_PCICONF1_PBBE 0x00000200 /* Back 2 Back Control */ + #define SH7751_PCICONF1_SER 0x00000100 /* SERR Output Control */ + #define SH7751_PCICONF1_WCC 0x00000080 /* Wait Cycle Control */ + #define SH7751_PCICONF1_PER 0x00000040 /* Parity Error Response */ + #define SH7751_PCICONF1_VPS 0x00000020 /* VGA Pallet Snoop */ + #define SH7751_PCICONF1_MWIE 0x00000010 /* Memory Write+Invalidate */ + #define SH7751_PCICONF1_SPC 0x00000008 /* Special Cycle Control */ + #define SH7751_PCICONF1_BUM 0x00000004 /* Bus Master Control */ + #define SH7751_PCICONF1_MES 0x00000002 /* Memory Space Control */ + #define SH7751_PCICONF1_IOS 0x00000001 /* I/O Space Control */ +#define SH7751_PCICONF2 0x8 /* PCI Config Reg 2 */ + #define SH7751_PCICONF2_BCC 0xFF000000 /* Base Class Code */ + #define SH7751_PCICONF2_SCC 0x00FF0000 /* Sub-Class Code */ + #define SH7751_PCICONF2_RLPI 0x0000FF00 /* Programming Interface */ + #define SH7751_PCICONF2_REV 0x000000FF /* Revision ID */ +#define SH7751_PCICONF3 0xC /* PCI Config Reg 3 */ + #define SH7751_PCICONF3_BIST7 0x80000000 /* Bist Supported */ + #define SH7751_PCICONF3_BIST6 0x40000000 /* Bist Executing */ + #define SH7751_PCICONF3_BIST3_0 0x0F000000 /* Bist Passed */ + #define SH7751_PCICONF3_HD7 0x00800000 /* Single Funtion device */ + #define SH7751_PCICONF3_HD6_0 0x007F0000 /* Configuration Layout */ + #define SH7751_PCICONF3_LAT 0x0000FF00 /* Latency Timer */ + #define SH7751_PCICONF3_CLS 0x000000FF /* Cache Line Size */ +#define SH7751_PCICONF4 0x10 /* PCI Config Reg 4 */ + #define SH7751_PCICONF4_BASE 0xFFFFFFFC /* I/O Space Base Addr */ + #define SH7751_PCICONF4_ASI 0x00000001 /* Address Space Type */ +#define SH7751_PCICONF5 0x14 /* PCI Config Reg 5 */ + #define SH7751_PCICONF5_BASE 0xFFFFFFF0 /* Mem Space Base Addr */ + #define SH7751_PCICONF5_LAP 0x00000008 /* Prefetch Enabled */ + #define SH7751_PCICONF5_LAT 0x00000006 /* Local Memory type */ + #define SH7751_PCICONF5_ASI 0x00000001 /* Address Space Type */ +#define SH7751_PCICONF6 0x18 /* PCI Config Reg 6 */ + #define SH7751_PCICONF6_BASE 0xFFFFFFF0 /* Mem Space Base Addr */ + #define SH7751_PCICONF6_LAP 0x00000008 /* Prefetch Enabled */ + #define SH7751_PCICONF6_LAT 0x00000006 /* Local Memory type */ + #define SH7751_PCICONF6_ASI 0x00000001 /* Address Space Type */ +/* PCICONF7 - PCICONF10 are undefined */ +#define SH7751_PCICONF11 0x2C /* PCI Config Reg 11 */ + #define SH7751_PCICONF11_SSID 0xFFFF0000 /* Subsystem ID */ + #define SH7751_PCICONF11_SVID 0x0000FFFF /* Subsystem Vendor ID */ +/* PCICONF12 is undefined */ +#define SH7751_PCICONF13 0x34 /* PCI Config Reg 13 */ + #define SH7751_PCICONF13_CPTR 0x000000FF /* PM function pointer */ +/* PCICONF14 is undefined */ +#define SH7751_PCICONF15 0x3C /* PCI Config Reg 15 */ + #define SH7751_PCICONF15_IPIN 0x000000FF /* Interrupt Pin */ +#define SH7751_PCICONF16 0x40 /* PCI Config Reg 16 */ + #define SH7751_PCICONF16_PMES 0xF8000000 /* PME Support */ + #define SH7751_PCICONF16_D2S 0x04000000 /* D2 Support */ + #define SH7751_PCICONF16_D1S 0x02000000 /* D1 Support */ + #define SH7751_PCICONF16_DSI 0x00200000 /* Bit Device Init. */ + #define SH7751_PCICONF16_PMCK 0x00080000 /* Clock for PME req. */ + #define SH7751_PCICONF16_VER 0x00070000 /* PM Version */ + #define SH7751_PCICONF16_NIP 0x0000FF00 /* Next Item Pointer */ + #define SH7751_PCICONF16_CID 0x000000FF /* Capability Identifier */ +#define SH7751_PCICONF17 0x44 /* PCI Config Reg 17 */ + #define SH7751_PCICONF17_DATA 0xFF000000 /* Data field for PM */ + #define SH7751_PCICONF17_PMES 0x00800000 /* PME Status */ + #define SH7751_PCICONF17_DSCL 0x00600000 /* Data Scaling Value */ + #define SH7751_PCICONF17_DSEL 0x001E0000 /* Data Select */ + #define SH7751_PCICONF17_PMEN 0x00010000 /* PME Enable */ + #define SH7751_PCICONF17_PWST 0x00000003 /* Power State */ +/* SH7715 Internal PCI Registers */ +#define SH7751_PCICR 0x100 /* PCI Control Register */ + #define SH7751_PCICR_PREFIX 0xA5000000 /* CR prefix for write */ + #define SH7751_PCICR_TRSB 0x00000200 /* Target Read Single */ + #define SH7751_PCICR_BSWP 0x00000100 /* Target Byte Swap */ + #define SH7751_PCICR_PLUP 0x00000080 /* Enable PCI Pullup */ + #define SH7751_PCICR_ARBM 0x00000040 /* PCI Arbitration Mode */ + #define SH7751_PCICR_MD 0x00000030 /* MD9 and MD10 status */ + #define SH7751_PCICR_SERR 0x00000008 /* SERR output assert */ + #define SH7751_PCICR_INTA 0x00000004 /* INTA output assert */ + #define SH7751_PCICR_PRST 0x00000002 /* PCI Reset Assert */ + #define SH7751_PCICR_CFIN 0x00000001 /* Central Fun. Init Done */ +#define SH7751_PCILSR0 0x104 /* PCI Local Space Register0 */ +#define SH7751_PCILSR1 0x108 /* PCI Local Space Register1 */ +#define SH7751_PCILAR0 0x10C /* PCI Local Address Register1 */ +#define SH7751_PCILAR1 0x110 /* PCI Local Address Register1 */ +#define SH7751_PCIINT 0x114 /* PCI Interrupt Register */ + #define SH7751_PCIINT_MLCK 0x00008000 /* Master Lock Error */ + #define SH7751_PCIINT_TABT 0x00004000 /* Target Abort Error */ + #define SH7751_PCIINT_TRET 0x00000200 /* Target Retry Error */ + #define SH7751_PCIINT_MFDE 0x00000100 /* Master Func. Disable Error */ + #define SH7751_PCIINT_PRTY 0x00000080 /* Address Parity Error */ + #define SH7751_PCIINT_SERR 0x00000040 /* SERR Detection Error */ + #define SH7751_PCIINT_TWDP 0x00000020 /* Tgt. Write Parity Error */ + #define SH7751_PCIINT_TRDP 0x00000010 /* Tgt. Read Parity Error Det. */ + #define SH7751_PCIINT_MTABT 0x00000008 /* Master-Tgt. Abort Error */ + #define SH7751_PCIINT_MMABT 0x00000004 /* Master-Master Abort Error */ + #define SH7751_PCIINT_MWPD 0x00000002 /* Master Write PERR Detect */ + #define SH7751_PCIINT_MRPD 0x00000002 /* Master Read PERR Detect */ +#define SH7751_PCIINTM 0x118 /* PCI Interrupt Mask Register */ +#define SH7751_PCIALR 0x11C /* Error Address Register */ +#define SH7751_PCICLR 0x120 /* Error Command/Data Register */ + #define SH7751_PCICLR_MPIO 0x80000000 /* Error Command/Data Register */ + #define SH7751_PCICLR_MDMA0 0x40000000 /* DMA0 Transfer Error */ + #define SH7751_PCICLR_MDMA1 0x20000000 /* DMA1 Transfer Error */ + #define SH7751_PCICLR_MDMA2 0x10000000 /* DMA2 Transfer Error */ + #define SH7751_PCICLR_MDMA3 0x08000000 /* DMA3 Transfer Error */ + #define SH7751_PCICLR_TGT 0x04000000 /* Target Transfer Error */ + #define SH7751_PCICLR_CMDL 0x0000000F /* PCI Command at Error */ +#define SH7751_PCIAINT 0x130 /* Arbiter Interrupt Register */ + #define SH7751_PCIAINT_MBKN 0x00002000 /* Master Broken Interrupt */ + #define SH7751_PCIAINT_TBTO 0x00001000 /* Target Bus Time Out */ + #define SH7751_PCIAINT_MBTO 0x00001000 /* Master Bus Time Out */ + #define SH7751_PCIAINT_TABT 0x00000008 /* Target Abort */ + #define SH7751_PCIAINT_MABT 0x00000004 /* Master Abort */ + #define SH7751_PCIAINT_RDPE 0x00000002 /* Read Data Parity Error */ + #define SH7751_PCIAINT_WDPE 0x00000002 /* Write Data Parity Error */ +#define SH7751_PCIAINTM 0x134 /* Arbiter Int. Mask Register */ +#define SH7751_PCIBMLR 0x138 /* Error Bus Master Register */ + #define SH7751_PCIBMLR_REQ4 0x00000010 /* REQ4 bus master at error */ + #define SH7751_PCIBMLR_REQ3 0x00000008 /* REQ3 bus master at error */ + #define SH7751_PCIBMLR_REQ2 0x00000004 /* REQ2 bus master at error */ + #define SH7751_PCIBMLR_REQ1 0x00000002 /* REQ1 bus master at error */ + #define SH7751_PCIBMLR_REQ0 0x00000001 /* REQ0 bus master at error */ +#define SH7751_PCIDMABT 0x140 /* DMA Transfer Arb. Register */ + #define SH7751_PCIDMABT_RRBN 0x00000001 /* DMA Arbitor Round-Robin */ +#define SH7751_PCIDPA0 0x180 /* DMA0 Transfer Addr. Register */ +#define SH7751_PCIDLA0 0x184 /* DMA0 Local Addr. Register */ +#define SH7751_PCIDTC0 0x188 /* DMA0 Transfer Cnt. Register */ +#define SH7751_PCIDCR0 0x18C /* DMA0 Control Register */ + #define SH7751_PCIDCR_ALGN 0x00000600 /* DMA Alignment Mode */ + #define SH7751_PCIDCR_MAST 0x00000100 /* DMA Termination Type */ + #define SH7751_PCIDCR_INTM 0x00000080 /* DMA Interrupt Done Mask*/ + #define SH7751_PCIDCR_INTS 0x00000040 /* DMA Interrupt Done Status */ + #define SH7751_PCIDCR_LHLD 0x00000020 /* Local Address Control */ + #define SH7751_PCIDCR_PHLD 0x00000010 /* PCI Address Control*/ + #define SH7751_PCIDCR_IOSEL 0x00000008 /* PCI Address Space Type */ + #define SH7751_PCIDCR_DIR 0x00000004 /* DMA Transfer Direction */ + #define SH7751_PCIDCR_STOP 0x00000002 /* Force DMA Stop */ + #define SH7751_PCIDCR_STRT 0x00000001 /* DMA Start */ +#define SH7751_PCIDPA1 0x190 /* DMA1 Transfer Addr. Register */ +#define SH7751_PCIDLA1 0x194 /* DMA1 Local Addr. Register */ +#define SH7751_PCIDTC1 0x198 /* DMA1 Transfer Cnt. Register */ +#define SH7751_PCIDCR1 0x19C /* DMA1 Control Register */ +#define SH7751_PCIDPA2 0x1A0 /* DMA2 Transfer Addr. Register */ +#define SH7751_PCIDLA2 0x1A4 /* DMA2 Local Addr. Register */ +#define SH7751_PCIDTC2 0x1A8 /* DMA2 Transfer Cnt. Register */ +#define SH7751_PCIDCR2 0x1AC /* DMA2 Control Register */ +#define SH7751_PCIDPA3 0x1B0 /* DMA3 Transfer Addr. Register */ +#define SH7751_PCIDLA3 0x1B4 /* DMA3 Local Addr. Register */ +#define SH7751_PCIDTC3 0x1B8 /* DMA3 Transfer Cnt. Register */ +#define SH7751_PCIDCR3 0x1BC /* DMA3 Control Register */ +#define SH7751_PCIPAR 0x1C0 /* PIO Address Register */ + #define SH7751_PCIPAR_CFGEN 0x80000000 /* Configuration Enable */ + #define SH7751_PCIPAR_BUSNO 0x00FF0000 /* Config. Bus Number */ + #define SH7751_PCIPAR_DEVNO 0x0000FF00 /* Config. Device Number */ + #define SH7751_PCIPAR_REGAD 0x000000FC /* Register Address Number */ +#define SH7751_PCIMBR 0x1C4 /* Memory Base Address Register */ + #define SH7751_PCIMBR_MASK 0xFF000000 /* Memory Space Mask */ + #define SH7751_PCIMBR_LOCK 0x00000001 /* Lock Memory Space */ +#define SH7751_PCIIOBR 0x1C8 /* I/O Base Address Register */ + #define SH7751_PCIIOBR_MASK 0xFFFC0000 /* IO Space Mask */ + #define SH7751_PCIIOBR_LOCK 0x00000001 /* Lock IO Space */ +#define SH7751_PCIPINT 0x1CC /* Power Mgmnt Int. Register */ + #define SH7751_PCIPINT_D3 0x00000002 /* D3 Pwr Mgmt. Interrupt */ + #define SH7751_PCIPINT_D0 0x00000001 /* D0 Pwr Mgmt. Interrupt */ +#define SH7751_PCIPINTM 0x1D0 /* Power Mgmnt Mask Register */ +#define SH7751_PCICLKR 0x1D4 /* Clock Ctrl. Register */ + #define SH7751_PCICLKR_PCSTP 0x00000002 /* PCI Clock Stop */ + #define SH7751_PCICLKR_BCSTP 0x00000002 /* BCLK Clock Stop */ +/* For definitions of BCR, MCR see ... */ +#define SH7751_PCIBCR1 0x1E0 /* Memory BCR1 Register */ +#define SH7751_PCIBCR2 0x1E4 /* Memory BCR2 Register */ +#define SH7751_PCIWCR1 0x1E8 /* Wait Control 1 Register */ +#define SH7751_PCIWCR2 0x1EC /* Wait Control 2 Register */ +#define SH7751_PCIWCR3 0x1F0 /* Wait Control 3 Register */ +#define SH7751_PCIMCR 0x1F4 /* Memory Control Register */ +#define SH7751_PCIPCTR 0x200 /* Port Control Register */ + #define SH7751_PCIPCTR_P2EN 0x000400000 /* Port 2 Enable */ + #define SH7751_PCIPCTR_P1EN 0x000200000 /* Port 1 Enable */ + #define SH7751_PCIPCTR_P0EN 0x000100000 /* Port 0 Enable */ + #define SH7751_PCIPCTR_P2UP 0x000000020 /* Port2 Pull Up Enable */ + #define SH7751_PCIPCTR_P2IO 0x000000010 /* Port2 Output Enable */ + #define SH7751_PCIPCTR_P1UP 0x000000008 /* Port1 Pull Up Enable */ + #define SH7751_PCIPCTR_P1IO 0x000000004 /* Port1 Output Enable */ + #define SH7751_PCIPCTR_P0UP 0x000000002 /* Port0 Pull Up Enable */ + #define SH7751_PCIPCTR_P0IO 0x000000001 /* Port0 Output Enable */ +#define SH7751_PCIPDTR 0x204 /* Port Data Register */ + #define SH7751_PCIPDTR_PB5 0x000000020 /* Port 5 Enable */ + #define SH7751_PCIPDTR_PB4 0x000000010 /* Port 4 Enable */ + #define SH7751_PCIPDTR_PB3 0x000000008 /* Port 3 Enable */ + #define SH7751_PCIPDTR_PB2 0x000000004 /* Port 2 Enable */ + #define SH7751_PCIPDTR_PB1 0x000000002 /* Port 1 Enable */ + #define SH7751_PCIPDTR_PB0 0x000000001 /* Port 0 Enable */ +#define SH7751_PCIPDR 0x220 /* Port IO Data Register */ + +/* Memory Control Registers */ +#define SH7751_BCR1 0xFF800000 /* Memory BCR1 Register */ +#define SH7751_BCR2 0xFF800004 /* Memory BCR2 Register */ +#define SH7751_WCR1 0xFF800008 /* Wait Control 1 Register */ +#define SH7751_WCR2 0xFF80000C /* Wait Control 2 Register */ +#define SH7751_WCR3 0xFF800010 /* Wait Control 3 Register */ +#define SH7751_MCR 0xFF800014 /* Memory Control Register */ + +/* General Memory Config Addresses */ +#define SH7751_CS0_BASE_ADDR 0x0 +#define SH7751_MEM_REGION_SIZE 0x04000000 +#define SH7751_CS1_BASE_ADDR (SH7751_CS0_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS2_BASE_ADDR (SH7751_CS1_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS3_BASE_ADDR (SH7751_CS2_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS4_BASE_ADDR (SH7751_CS3_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS5_BASE_ADDR (SH7751_CS4_BASE_ADDR + SH7751_MEM_REGION_SIZE) +#define SH7751_CS6_BASE_ADDR (SH7751_CS5_BASE_ADDR + SH7751_MEM_REGION_SIZE) + +/* General PCI values */ +#define SH7751_PCI_HOST_BRIDGE 0x6 + +/* External functions defined per platform i.e. Big Sur, SE... (these could be routed + * through the machine vectors... */ +extern int pcibios_init_platform(void); +extern int pcibios_map_platform_irq(u8 slot, u8 pin); + +struct sh7751_pci_address_space { + unsigned long base; + unsigned long size; +}; + +struct sh7751_pci_address_map { + struct sh7751_pci_address_space window0; + struct sh7751_pci_address_space window1; +}; + +/* arch/sh/drivers/pci/pci-sh7751.c */ +extern int sh7751_pcic_init(struct sh7751_pci_address_map *map); + +#endif /* _PCI_SH7751_H_ */ + diff -puN /dev/null arch/sh/drivers/pci/pci-st40.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-st40.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,423 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Support functions for the ST40 PCI hardware. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pci-st40.h" + +/* This is in P2 of course */ +#define ST40PCI_BASE_ADDRESS (0xb0000000) +#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) +#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) +#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) + +#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) + +#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) +#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) +#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) + +#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) +#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) +#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) + +#define ST40PCI_SERR_IRQ 64 +#define ST40PCI_SERR_INT_GROUP 0 +#define ST40PCI_SERR_INT_POS 0 +#define ST40PCI_SERR_INT_PRI 15 + +#define ST40PCI_ERR_IRQ 65 +#define ST40PCI_ERR_INT_GROUP 1 +#define ST40PCI_ERR_INT_POS 1 +#define ST40PCI_ERR_INT_PRI 14 + + +/* Macros to extract PLL params */ +#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) +#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) +#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) +#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) + +/* Build up the appropriate settings */ +#define PLL_SET(mdiv,ndiv,pdiv,setup) \ +( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) + +#define PLLPCICR (0xbb040000+0x10) + +#define PLLPCICR_POWERON (1<<28) +#define PLLPCICR_OUT_EN (1<<29) +#define PLLPCICR_LOCKSELECT (1<<30) +#define PLLPCICR_LOCK (1<<31) + + +#define PLL_25MHZ 0x793c8512 +#define PLL_33MHZ PLL_SET(18,88,3,295) + + +static __init void SetPCIPLL(void) +{ + /* Stop the PLL */ + writel(0, PLLPCICR); + + /* Always run at 33Mhz. The PCI clock is totally async + * to the rest of the system + */ + writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR); + + printk("ST40PCI: Waiting for PCI PLL to lock\n"); + while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0); + writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR); +} + + +static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) +{ + + unsigned pci_int, pci_air, pci_cir, pci_aint; + + pci_int = ST40PCI_READ(INT); + pci_cir = ST40PCI_READ(CIR); + pci_air = ST40PCI_READ(AIR); + + if (pci_int) { + printk("PCI INTERRUPT!\n"); + printk("PCI INT -> 0x%x\n", pci_int & 0xffff); + printk("PCI AIR -> 0x%x\n", pci_air); + printk("PCI CIR -> 0x%x\n", pci_cir); + ST40PCI_WRITE(INT, ~0); + } + + pci_aint = ST40PCI_READ(AINT); + if (pci_aint) { + printk("PCI ARB INTERRUPT!\n"); + printk("PCI AINT -> 0x%x\n", pci_aint); + printk("PCI AIR -> 0x%x\n", pci_air); + printk("PCI CIR -> 0x%x\n", pci_cir); + ST40PCI_WRITE(AINT, ~0); + } + + return IRQ_HANDLED; +} + + +/* Rounds a number UP to the nearest power of two. Used for + * sizing the PCI window. + */ +static u32 __init r2p2(u32 num) +{ + int i = 31; + u32 tmp = num; + + if (num == 0) + return 0; + + do { + if (tmp & (1 << 31)) + break; + i--; + tmp <<= 1; + } while (i >= 0); + + tmp = 1 << i; + /* If the original number isn't a power of 2, round it up */ + if (tmp != num) + tmp <<= 1; + + return tmp; +} + +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + printk("PCI: IDE base address fixup for %s\n", d->slot_name); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} + + +/* Add future fixups here... */ +struct pci_fixup pcibios_fixups[] = { + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, + { 0 } +}; + +int __init st40pci_init(unsigned memStart, unsigned memSize) +{ + u32 lsr0; + + SetPCIPLL(); + + /* Initialises the ST40 pci subsystem, performing a reset, then programming + * up the address space decoders appropriately + */ + + /* Should reset core here as well methink */ + + ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); + + /* Loop while core resets */ + while (ST40PCI_READ(CR) & CR_SOFT_RESET); + + /* Now, lets reset all the cards on the bus with extreme prejudice */ + ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); + udelay(250); + + /* Set bus active, take it out of reset */ + ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE); + + /* The PCI spec says that no access must be made to the bus until 1 second + * after reset. This seem ludicrously long, but some delay is needed here + */ + mdelay(1000); + + /* Switch off interrupts */ + ST40PCI_WRITE(INTM, 0); + ST40PCI_WRITE(AINT, 0); + + /* Allow it to be a master */ + + ST40PCI_WRITE_SHORT(CSR_CMD, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_IO); + + /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 + * on the PCI bus. This allows a nice 1-1 bus to phys mapping. + */ + + + ST40PCI_WRITE(MBR, 0x10000000); + /* Always set the max size 128M (actually, it is only 96MB wide) */ + ST40PCI_WRITE(MBMR, 0x07ff0000); + + /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to + * allow cards that have legacy io such as vga to function correctly. This gives a + * maximum of 64K of io/space as only the bottom 16 bits of the address are copied + * over to the bus when the transaction is made. 64K of io space is more than enough + */ + ST40PCI_WRITE(IOBR, 0x0); + /* Set up the 64K window */ + ST40PCI_WRITE(IOBMR, 0x0); + + /* Now we set up the mbars so the PCI bus can see the memory of the machine */ + + if (memSize < (64 * 1024)) { + printk("Ridiculous memory size of 0x%x?\n",memSize); + return 0; + } + + lsr0 = + (memSize > + (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) - + 0x10000) | 0x1); + + ST40PCI_WRITE(LSR0, lsr0); + + ST40PCI_WRITE(CSR_MBAR0, memStart); + ST40PCI_WRITE(LAR0, memStart); + + /* Maximise timeout values */ + ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); + ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); + ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); + + + /* Install the pci interrupt handlers */ + make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0, + ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS, + ST40PCI_SERR_INT_PRI); + + make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP, + ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI); + + + return 1; +} + +char * __init pcibios_setup(char *str) +{ + return str; +} + + +#define SET_CONFIG_BITS(bus,devfn,where)\ + (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) + +#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) + + +static int CheckForMasterAbort(void) +{ + if (ST40PCI_READ(INT) & INT_MADIM) { + /* Should we clear config space version as well ??? */ + ST40PCI_WRITE(INT, INT_MADIM); + ST40PCI_WRITE_SHORT(CSR_STATUS, 0); + return 1; + } + + return 0; +} + +/* Write to config register */ +static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) +{ + ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); + switch (size) { + case 1: + *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); + break; + case 2: + *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); + break; + case 4: + *val = ST40PCI_READ(PDR); + break; + } + + if (CheckForMasterAbort()){ + switch (size) { + case 1: + *val = (u8)0xff; + break; + case 2: + *val = (u16)0xffff; + break; + case 4: + *val = 0xffffffff; + break; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) +{ + ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); + + switch (size) { + case 1: + ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); + break; + case 2: + ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); + break; + case 4: + ST40PCI_WRITE(PDR, val); + break; + } + + CheckForMasterAbort(); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops pci_config_ops = { + .read = st40pci_read, + .write = st40pci_write, +}; + + +/* Everything hangs off this */ +static struct pci_bus *pci_root_bus; + + +static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) +{ + return PCI_SLOT(dev->devfn); +} + + +/* This needs to be shunted out of here into the board specific bit */ +#define HARP_PCI_IRQ 1 +#define HARP_BRIDGE_IRQ 2 +#define OVERDRIVE_SLOT0_IRQ 0 + +static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + switch (slot) { +#ifdef CONFIG_SH_STB1_HARP + case 2: /*This is the PCI slot on the */ + return HARP_PCI_IRQ; + case 1: /* this is the bridge */ + return HARP_BRIDGE_IRQ; +#elif defined(CONFIG_SH_STB1_OVERDRIVE) + case 1: + case 2: + case 3: + return slot - 1; +#else +#error Unknown board +#endif + default: + return -1; + } +} + +void __init pcibios_init(void) +{ + extern unsigned long memory_start, memory_end; + + if (sh_mv.mv_init_pci != NULL) { + sh_mv.mv_init_pci(); + } + + /* The pci subsytem needs to know where memory is and how much + * of it there is. I've simply made these globals. A better mechanism + * is probably needed. + */ + st40pci_init(PHYSADDR(memory_start), + PHYSADDR(memory_end) - PHYSADDR(memory_start)); + + if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, + SA_INTERRUPT, "st40pci", NULL)) { + printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); + return; + } + + /* Enable the PCI interrupts on the device */ + ST40PCI_WRITE(INTM, ~0); + ST40PCI_WRITE(AINT, ~0); + + /* Map the io address apprioately */ +#ifdef CONFIG_HD64465 + hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, + ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); +#endif + + /* ok, do the scan man */ + pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); + pci_assign_unassigned_resources(); + pci_fixup_irqs(no_swizzle, map_harp_irq); + +} + +void __init pcibios_fixup_bus(struct pci_bus *bus) +{ +} diff -puN /dev/null arch/sh/drivers/pci/pci-st40.h --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/drivers/pci/pci-st40.h 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Defintions for the ST40 PCI hardware. + */ + +#ifndef __PCI_ST40_H__ +#define __PCI_ST40_H__ + +#define ST40PCI_VCR_STATUS 0x00 + +#define ST40PCI_VCR_VERSION 0x08 + +#define ST40PCI_CR 0x10 + +#define CR_SOFT_RESET (1<<12) +#define CR_PFCS (1<<11) +#define CR_PFE (1<<9) +#define CR_BMAM (1<<6) +#define CR_HOST (1<<5) +#define CR_CLKEN (1<<4) +#define CR_SOCS (1<<3) +#define CR_IOCS (1<<2) +#define CR_RSTCTL (1<<1) +#define CR_CFINT (1<<0) +#define CR_LOCK_MASK 0x5a000000 + + +#define ST40PCI_LSR0 0X14 +#define ST40PCI_LAR0 0x1c + +#define ST40PCI_INT 0x24 +#define INT_MADIM (1<<2) + + +#define ST40PCI_INTM 0x28 +#define ST40PCI_AIR 0x2c +#define ST40PCI_CIR 0x30 +#define ST40PCI_AINT 0x40 +#define ST40PCI_AINTM 0x44 +#define ST40PCI_BMIR 0x48 +#define ST40PCI_PAR 0x4c +#define ST40PCI_MBR 0x50 +#define ST40PCI_IOBR 0x54 +#define ST40PCI_PINT 0x58 +#define ST40PCI_PINTM 0x5c +#define ST40PCI_MBMR 0x70 +#define ST40PCI_IOBMR 0x74 +#define ST40PCI_PDR 0x78 + +/* These are configs space registers */ +#define ST40PCI_CSR_VID 0x10000 +#define ST40PCI_CSR_DID 0x10002 +#define ST40PCI_CSR_CMD 0x10004 +#define ST40PCI_CSR_STATUS 0x10006 +#define ST40PCI_CSR_MBAR0 0x10010 +#define ST40PCI_CSR_TRDY 0x10040 +#define ST40PCI_CSR_RETRY 0x10041 +#define ST40PCI_CSR_MIT 0x1000d + +#define ST40_IO_ADDR 0xb6000000 + +#endif /* __PCI_ST40_H__ */ diff -puN arch/sh/Kconfig~linus arch/sh/Kconfig --- 25/arch/sh/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -25,14 +25,6 @@ config RWSEM_GENERIC_SPINLOCK config RWSEM_XCHGADD_ALGORITHM bool -config GENERIC_ISA_DMA - bool - default y - -config VARIABLE_CLOCK_TICK_RATE - bool - default y - source "init/Kconfig" @@ -54,6 +46,12 @@ config SH_7751_SOLUTION_ENGINE Select 7751 SolutionEngine if configuring for a Hitachi SH7751 evalutation board. +config SH_7751_SYSTEMH + bool "SystemH7751R" + help + Select SystemH if you are configuring for a Renesas SystemH + 7751R evaluation board. + config SH_STB1_HARP bool "STB1_Harp" @@ -102,6 +100,8 @@ config SH_EC3104 config SH_SATURN bool "Saturn" + help + Select Saturn if configuring for a SEGA Saturn. config SH_DREAMCAST bool "Dreamcast" @@ -132,6 +132,13 @@ config SH_ADX config SH_MPC1211 bool "MPC1211" +config SH_SECUREEDGE5410 + bool "SecureEdge5410" + help + Select SecureEdge5410 if configuring for a SnapGear SH board. + This includes both the OEM SecureEdge products as well as the + SME product line. + config SH_UNKNOWN bool "BareCPU" help @@ -146,6 +153,85 @@ config SH_UNKNOWN endchoice +choice + prompt "Processor family" + default CPU_SH4 + help + This option determines the CPU family to compile for. Supported + targets are SH-2, SH-3, and SH-4. These options are independent of + CPU functionality. As such, SH-DSP users will still want to select + their respective processor family in addition to the DSP support + option. + +config CPU_SH2 + bool "SH-2" + select SH_WRITETHROUGH + +config CPU_SH3 + bool "SH-3" + +config CPU_SH4 + bool "SH-4" + +endchoice + +choice + prompt "Processor subtype" + +config CPU_SUBTYPE_SH7604 + bool "SH7604" + depends on CPU_SH2 + help + Select SH7604 if you have SH7604 + +config CPU_SUBTYPE_SH7300 + bool "SH7300" + depends on CPU_SH3 + +config CPU_SUBTYPE_SH7707 + bool "SH7707" + depends on CPU_SH3 + help + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. + +config CPU_SUBTYPE_SH7708 + bool "SH7708" + depends on CPU_SH3 + help + Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or + if you have a 100 Mhz SH-3 HD6417708R CPU. + +config CPU_SUBTYPE_SH7709 + bool "SH7709" + depends on CPU_SH3 + help + Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. + +config CPU_SUBTYPE_SH7750 + bool "SH7750" + depends on CPU_SH4 + help + Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. + +config CPU_SUBTYPE_SH7751 + bool "SH7751/SH7751R" + depends on CPU_SH4 + help + Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, + or if you have a HD6417751R CPU. + +config CPU_SUBTYPE_SH7760 + bool "SH7760" + depends on CPU_SH4 + +config CPU_SUBTYPE_ST40STB1 + bool "ST40STB1" + depends on CPU_SH4 + help + Select ST40STB1 if you have a ST40STB1 CPU. + +endchoice + config MMU bool "Support for memory management hardware" depends on !CPU_SH2 @@ -169,8 +255,8 @@ config CMDLINE # Platform-specific memory start and size definitions config MEMORY_START hex "Physical memory start address" if !MEMORY_SET || MEMORY_OVERRIDE - default "08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 - default "0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) + default "0x08000000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || SH_MPC1211 || SH_SECUREEDGE5410 + default "0x0c000000" if !MEMORY_OVERRIDE && (SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) ---help--- Computers built with Hitachi SuperH processors always map the ROM starting at address zero. But the processor @@ -187,11 +273,11 @@ config MEMORY_START config MEMORY_SIZE hex "Physical memory size" if !MEMORY_SET || MEMORY_OVERRIDE - default "00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) - default "01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST - default "04000000" if !MEMORY_OVERRIDE && SH_7751_SOLUTION_ENGINE - default "02000000" if !MEMORY_OVERRIDE && SH_SOLUTION_ENGINE - default "08000000" if SH_MPC1211 + default "0x00400000" if !MEMORY_SET || MEMORY_OVERRIDE || !MEMORY_OVERRIDE && SH_ADX || !MEMORY_OVERRIDE && (SH_HP600 || SH_BIGSUR || SH_SH2000) + default "0x01000000" if !MEMORY_OVERRIDE && SH_DREAMCAST || SH_SECUREEDGE5410 + default "0x04000000" if !MEMORY_OVERRIDE && SH_7751_SOLUTION_ENGINE + default "0x02000000" if !MEMORY_OVERRIDE && SH_SOLUTION_ENGINE + default "0x08000000" if SH_MPC1211 help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command @@ -201,7 +287,7 @@ config MEMORY_SIZE config MEMORY_SET bool - depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE) + depends on !MEMORY_OVERRIDE && (SH_MPC1211 || SH_ADX || SH_DREAMCAST || SH_HP600 || SH_BIGSUR || SH_SH2000 || SH_7751_SOLUTION_ENGINE || SH_SOLUTION_ENGINE || SH_SECUREEDGE5410) default y help This is an option about which you will never be asked a question. @@ -254,15 +340,13 @@ endchoice config CF_BASE_ADDR hex depends on CF_ENABLER - default "b8000000" if CF_AREA6 - default "b4000000" if CF_AREA5 - -endmenu + default "0xb8000000" if CF_AREA6 + default "0xb4000000" if CF_AREA5 # The SH7750 RTC module is disabled in the Dreamcast config SH_RTC bool - depends on !SH_DREAMCAST + depends on !SH_DREAMCAST && !SH_SATURN default y help Selecting this option will allow the Linux kernel to emulate @@ -270,9 +354,16 @@ config SH_RTC If unsure, say N. -# This is also board-specific -config PCI_AUTO - bool +config SH_DSP + bool "DSP support" + depends on !CPU_SH4 + default y + help + Selecting this option will enable support for SH processors that + have DSP units (ie, SH2-DSP and SH3-DSP). It is safe to say Y here + by default, as the existance of the DSP will be probed at runtime. + + This option must be set in order to enable the DSP. config SH_HP600 bool @@ -289,91 +380,10 @@ config DISCONTIGMEM or have huge holes in the physical address space for other reasons. See for more. - -menu "Processor type and features" - -# -# Ick, get rid of all this CPU_SUBTYPE nonsense. Just probe it, fill in -# cpu_data, and leave it alone. (Feasible for SH-4 at least, and some -# SH-3). ++paulm -# -choice - prompt "Processor type" - default CPU_SUBTYPE_SH7708 - -config CPU_SUBTYPE_SH7604 - bool "SH7604" - help - Select SH7604 if you have SH7604 - -config CPU_SUBTYPE_SH7707 - bool "SH7707" - ---help--- - Select the type of SuperH processor you have. This information is - used for optimizing and configuration purposes. - - Select SH7604 if you have a SH-2 CPU. - - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - - Select SH7751 if you have a SH7751 - - Select ST40STB1 if you have a ST40STB1 - -config CPU_SUBTYPE_SH7708 - bool "SH7708" - help - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -config CPU_SUBTYPE_SH7709 - bool "SH7709" - help - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -config CPU_SUBTYPE_SH7750 - bool "SH7750" - help - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -config CPU_SUBTYPE_SH7751 - bool "SH7751" - help - Select SH7750 if you have a 166 Mhz SH-4 HD6417751 CPU. - -config CPU_SUBTYPE_ST40STB1 - bool "ST40STB1" - help - Select ST40STB1 if you have a ST40STB1 CPU. - -endchoice - -config CPU_SH2 - bool - depends on CPU_SUBTYPE_SH7604 - default y - -config CPU_SH3 - bool - depends on !CPU_SH2 && (CPU_SUBTYPE_SH7707 || CPU_SUBTYPE_SH7708 || CPU_SUBTYPE_SH7709) - default y - -config CPU_SH4 - bool - depends on !CPU_SH3 && !CPU_SH2 && (CPU_SUBTYPE_SH7750 || CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_ST40STB1) - default y - config ZERO_PAGE_OFFSET hex "Zero page offset" - default "00001000" if !SH_MPC1211 - default "00004000" if SH_MPC1211 + default "0x00001000" if !SH_MPC1211 + default "0x00004000" if SH_MPC1211 help This sets the default offset of zero page. @@ -385,18 +395,26 @@ config ST40_LMI_MEMORY config MEMORY_START hex depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "08000000" + default "0x08000000" config MEMORY_SIZE hex depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY - default "00400000" + default "0x00400000" config MEMORY_SET bool depends on CPU_SUBTYPE_ST40STB1 && ST40_LMI_MEMORY default y +config BOOT_LINK_OFFSET + hex "Link address offset for booting" + default "0x00800000" + help + This option allows you to set the link address offset of the zImage. + This can be useful if you are on a board which has a small amount of + memory. + config CPU_LITTLE_ENDIAN bool "Little Endian" help @@ -442,6 +460,13 @@ config SH_OCRAM If unsure, say N. +config SH_STORE_QUEUES + bool "Support for Store Queues" + depends on CPU_SH4 + help + Selecting this option will enable an in-kernel API for manipulating + the store queues integrated in the SH-4 processors. + config SMP bool "Symmetric multi-processing support" ---help--- @@ -467,6 +492,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "2" help @@ -477,13 +503,18 @@ config NR_CPUS This is purely to save memory - each supported CPU adds approximately eight kilobytes to the kernel image. -config SH_DMA - bool "DMA controller (DMAC) support" - help - Selecting this option will provide same API as PC's Direct Memory - Access Controller(8237A) for SuperH DMAC. - - If unsure, say N. +config SH_PCLK_FREQ + int "Peripheral clock frequency (in Hz)" + default "49876504" if CPU_SUBTYPE_SH7750 + default "60013568" if CPU_SUBTYPE_SH7751 + default "1193182" + help + This option is used to specify the peripheral clock frequency. This + option must be set for each processor in order for the kernel to + function reliably. If no sane default exists, we use a default from + the legacy i8254. Any discrepancies will be reported on boot time + with an auto-probed frequency which should be considered the proper + value for your hardware. config CPU_FREQ bool "CPU Frequency scaling" @@ -518,80 +549,9 @@ config SH_CPU_FREQ source "drivers/cpufreq/Kconfig" -# A board must have defined HD6446X_SERIES in order to see these -choice - prompt "HD6446x options" - depends HD6446X_SERIES - default HD64461 - -config HD64461 - bool "Hitachi HD64461 companion chip support" - depends on CPU_SUBTYPE_SH7709 - ---help--- - The Hitachi HD64461 provides an interface for - the SH7709 CPU, supporting a LCD controller, - CRT color controller, IrDA up to 4 Mbps, and a - PCMCIA controller supporting 2 slots. - - More information is available at - . - - Say Y if you want support for the HD64461. - Otherwise, say N. - -config HD64465 - bool "Hitachi HD64465 companion chip support" - depends on CPU_SUBTYPE_SH7750 - ---help--- - The Hitachi HD64465 provides an interface for - the SH7750 CPU, supporting a LCD controller, - CRT color controller, IrDA, USB, PCMCIA, - keyboard controller, and a printer interface. - - More information is available at - . - - Say Y if you want support for the HD64465. - Otherwise, say N. - -endchoice - -# These will also be split into the Kconfig's below -config HD64461_IRQ - int "HD64461 IRQ" - depends on HD64461 - default "36" - help - The default setting of the HD64461 IRQ is 36. - - Do not change this unless you know what you are doing. - -config HD64461_ENABLER - bool "HD64461 PCMCIA enabler" - depends on HD64461 - help - Say Y here if you want to enable PCMCIA support - via the HD64461 companion chip. - Otherwise, say N. - +source "arch/sh/drivers/dma/Kconfig" -config HD64465_IOBASE - hex "HD64465 start address" - depends on HD64465 - default "b0000000" - help - The default setting of the HD64465 IO base address is 0xb0000000. - - Do not change this unless you know what you are doing. - -config HD64465_IRQ - int "HD64465 IRQ" - depends on HD64465 - default "5" - help - The default setting of the HD64465 IRQ is 5. - - Do not change this unless you know what you are doing. +source "arch/sh/cchips/Kconfig" endmenu @@ -601,9 +561,13 @@ menu "Bus options (PCI, PCMCIA, EISA, MC # Even on SuperH devices which don't have an ISA bus, # this variable helps the PCMCIA modules handle # IRQ requesting properly -- Greg Banks. +# +# Though we're generally not interested in it when +# we're not using PCMCIA, so we make it dependent on +# PCMCIA outright. -- PFM. config ISA bool - default y + default y if PCMCIA help Find out whether you have ISA slots on your motherboard. ISA is the name of a bus system, i.e. the way the CPU talks to the other stuff @@ -637,68 +601,11 @@ config MCA config SBUS bool -config PCI - bool "PCI support" - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -choice - prompt "PCI access mode" - depends on PCI - default PCI_GOANY - -config PCI_GOBIOS - bool "BIOS" - ---help--- - On PCI systems, the BIOS can be used to detect the PCI devices and - determine their configuration. However, some old PCI motherboards - have BIOS bugs and may crash if this is done. Also, some embedded - PCI-based systems don't have any BIOS at all. Linux can also try to - detect the PCI hardware directly without using the BIOS. - - With this option, you can specify how Linux should detect the PCI - devices. If you choose "BIOS", the BIOS will be used, if you choose - "Direct", the BIOS won't be used, and if you choose "Any", the - kernel will try the direct access method and falls back to the BIOS - if that doesn't work. If unsure, go with the default, which is - "Any". - -config PCI_GODIRECT - bool "Direct" - -config PCI_GOANY - bool "Any" - -endchoice - -config PCI_BIOS - bool - depends on PCI && (PCI_GOBIOS || PCI_GOANY) - default y - -config PCI_DIRECT +config MAPLE bool - depends on PCI && (PCI_GODIRECT || PCI_GOANY) - default y + default y if SH_DREAMCAST -config SH_PCIDMA_NONCOHERENT - bool "Cache and PCI noncoherent" - depends on PCI - help - Enable this option if your platform does not have a CPU cache which - remains coherent with PCI DMA. It is safest to say 'Y', although you - will see better performance if you can say 'N', because the PCI DMA - code will not have to flush the CPU's caches. If you have a PCI host - bridge integrated with your SH CPU, refer carefully to the chip specs - to see if you can say 'N' here. Otherwise, leave it as 'Y'. +source "arch/sh/drivers/pci/Kconfig" source "drivers/pci/Kconfig" @@ -762,10 +669,6 @@ source "drivers/telephony/Kconfig" # source "drivers/input/Kconfig" -#if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then -# source drivers/maple/Config.in -#fi - menu "Character devices" config VT @@ -1136,6 +1039,7 @@ source "sound/Kconfig" source "drivers/usb/Kconfig" +source "arch/sh/oprofile/Kconfig" menu "Kernel hacking" @@ -1184,6 +1088,97 @@ config SH_EARLY_PRINTK when the kernel may crash or hang before the serial console is initialised. If unsure, say N. +config KGDB + bool "Include KGDB kernel debugger" + help + Include in-kernel hooks for kgdb, the Linux kernel source level + debugger. See for more information. + Unless you are intending to debug the kernel, say N here. + +menu "KGDB configuration options" + depends on KGDB + +config MORE_COMPILE_OPTIONS + bool "Add any additional compile options" + help + If you want to add additional CFLAGS to the kernel build, enable this + option and then enter what you would like to add in the next question. + Note however that -g is already appended with the selection of KGDB. + +config COMPILE_OPTIONS + string "Additional compile arguments" + depends on MORE_COMPILE_OPTIONS + +config KGDB_NMI + bool "Enter KGDB on NMI" + default n + +config KGDB_THREAD + bool "Include KGDB thread support" + default y + +config SH_KGDB_CONSOLE + bool "Console messages through GDB" + default n + +config KGDB_SYSRQ + bool "Allow SysRq 'G' to enter KGDB" + default y + +config KGDB_KERNEL_ASSERTS + bool "Include KGDB kernel assertions" + default n + +comment "Serial port setup" + +config KGDB_DEFPORT + int "Port number (ttySCn)" + default "1" + +config KGDB_DEFBAUD + int "Baud rate" + default "115200" + +choice + prompt "Parity" + depends on KGDB + default KGDB_DEFPARITY_N + +config KGDB_DEFPARITY_N + bool "None" + +config KGDB_DEFPARITY_E + bool "Even" + +config KGDB_DEFPARITY_O + bool "Odd" + +endchoice + +choice + prompt "Data bits" + depends on KGDB + default KGDB_DEFBITS_8 + +config KGDB_DEFBITS_8 + bool "8" + +config KGDB_DEFBITS_7 + bool "7" + +endchoice + +endmenu + +config FRAME_POINTER + bool "Compile the kernel with frame pointers" + default y if KGDB + help + If you say Y here the resulting kernel image will be slightly larger + and slower, but it will give very useful debugging information. + If you don't debug the kernel, you can say N, but we may not be able + to solve problems without frame pointers. + endmenu source "security/Kconfig" diff -puN -L arch/sh/kernel/cpu/dma.c arch/sh/kernel/cpu/dma.c~linus /dev/null --- 25/arch/sh/kernel/cpu/dma.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,211 +0,0 @@ -/* - * arch/sh/kernel/cpu/dma.c - * - * Copyright (C) 2000 Takashi YOSHII - * Copyright (C) 2003 Paul Mundt - * - * PC like DMA API for SuperH's DMAC. - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include -#include - -static struct dma_info_t *dma_info[MAX_DMA_CHANNELS]; -static struct dma_info_t *autoinit_info[SH_MAX_DMA_CHANNELS] = {0}; -extern spinlock_t dma_spin_lock; - -/* - * The SuperH DMAC supports a number of transmit sizes, we list them here, - * with their respective values as they appear in the CHCR registers. - * - * Defaults to a 64-bit transfer size. - */ -enum { - XMIT_SZ_64BIT = 0, - XMIT_SZ_8BIT = 1, - XMIT_SZ_16BIT = 2, - XMIT_SZ_32BIT = 3, - XMIT_SZ_256BIT = 4, -}; - -/* - * The DMA count is defined as the number of bytes to transfer. - */ -static unsigned int ts_shift[] = { - [XMIT_SZ_64BIT] 3, - [XMIT_SZ_8BIT] 0, - [XMIT_SZ_16BIT] 1, - [XMIT_SZ_32BIT] 2, - [XMIT_SZ_256BIT] 5, -}; - -/* - * We determine the correct shift size based off of the CHCR transmit size - * for the given channel. Since we know that it will take: - * - * info->count >> ts_shift[transmit_size] - * - * iterations to complete the transfer. - */ -static inline unsigned int calc_xmit_shift(struct dma_info_t *info) -{ - return ts_shift[(ctrl_inl(CHCR[info->chan]) >> 4) & 0x0007]; -} - -static irqreturn_t dma_tei(int irq, void *dev_id, struct pt_regs *regs) -{ - int chan = irq - DMTE_IRQ[0]; - struct dma_info_t *info = autoinit_info[chan]; - - if( info->mode & DMA_MODE_WRITE ) - ctrl_outl(info->mem_addr, SAR[info->chan]); - else - ctrl_outl(info->mem_addr, DAR[info->chan]); - - ctrl_outl(info->count >> calc_xmit_shift(info), DMATCR[info->chan]); - ctrl_outl(ctrl_inl(CHCR[info->chan])&~CHCR_TE, CHCR[info->chan]); - - return IRQ_HANDLED; -} - -static struct irqaction irq_tei = { - .handler = dma_tei, - .flags = SA_INTERRUPT, - .name = "dma_tei", -}; - -void setup_dma(unsigned int dmanr, struct dma_info_t *info) -{ - make_ipr_irq(DMTE_IRQ[info->chan], DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - setup_irq(DMTE_IRQ[info->chan], &irq_tei); - dma_info[dmanr] = info; -} - -unsigned long claim_dma_lock(void) -{ - unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); - return flags; -} - -void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -void enable_dma(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - unsigned long chcr; - - chcr = ctrl_inl(CHCR[info->chan]); - chcr |= CHCR_DE; - ctrl_outl(chcr, CHCR[info->chan]); -} - -void disable_dma(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - unsigned long chcr; - - chcr = ctrl_inl(CHCR[info->chan]); - chcr &= ~CHCR_DE; - ctrl_outl(chcr, CHCR[info->chan]); -} - -void set_dma_mode(unsigned int dmanr, char mode) -{ - struct dma_info_t *info = dma_info[dmanr]; - - info->mode = mode; - set_dma_addr(dmanr, info->mem_addr); - set_dma_count(dmanr, info->count); - autoinit_info[info->chan] = info; -} - -void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - struct dma_info_t *info = dma_info[dmanr]; - unsigned long sar, dar; - - info->mem_addr = a; - sar = (info->mode & DMA_MODE_WRITE)? info->mem_addr: info->dev_addr; - dar = (info->mode & DMA_MODE_WRITE)? info->dev_addr: info->mem_addr; - ctrl_outl(sar, SAR[info->chan]); - ctrl_outl(dar, DAR[info->chan]); -} - -void set_dma_count(unsigned int dmanr, unsigned int count) -{ - struct dma_info_t *info = dma_info[dmanr]; - info->count = count; - ctrl_outl(count >> calc_xmit_shift(info), DMATCR[info->chan]); -} - -int get_dma_residue(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - return (ctrl_inl(DMATCR[info->chan]) << calc_xmit_shift(info)); -} - -#if defined(CONFIG_CPU_SH4) -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) -{ - printk(KERN_WARNING "DMAE: DMAOR=%x\n",ctrl_inl(DMAOR)); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_NMIF, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)&~DMAOR_AE, DMAOR); - ctrl_outl(ctrl_inl(DMAOR)|DMAOR_DME, DMAOR); - - return IRQ_HANDLED; -} - -static struct irqaction irq_err = { - .handler = dma_err, - .flags = SA_INTERRUPT, - .name = "dma_err", -}; -#endif - -int __init init_dma(void) -{ -#if defined(CONFIG_CPU_SH4) - make_ipr_irq(DMAE_IRQ, DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - setup_irq(DMAE_IRQ, &irq_err); -#endif - - ctrl_outl(DMAOR_DME, DMAOR); - return 0; -} - -static void __exit exit_dma(void) -{ -#ifdef CONFIG_CPU_SH4 - free_irq(DMAE_IRQ, 0); -#endif -} - -module_init(init_dma); -module_exit(exit_dma); - -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(setup_dma); -EXPORT_SYMBOL(claim_dma_lock); -EXPORT_SYMBOL(release_dma_lock); -EXPORT_SYMBOL(enable_dma); -EXPORT_SYMBOL(disable_dma); -EXPORT_SYMBOL(set_dma_mode); -EXPORT_SYMBOL(set_dma_addr); -EXPORT_SYMBOL(set_dma_count); -EXPORT_SYMBOL(get_dma_residue); - diff -puN /dev/null arch/sh/kernel/cpu/init.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/kernel/cpu/init.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,214 @@ +/* + * arch/sh/kernel/cpu/init.c + * + * CPU init code + * + * Copyright (C) 2002, 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern void detect_cpu_and_cache_system(void); + +/* + * Generic wrapper for command line arguments to disable on-chip + * peripherals (nofpu, nodsp, and so forth). + */ +#define onchip_setup(x) \ +static int x##_disabled __initdata = 0; \ + \ +static int __init x##_setup(char *opts) \ +{ \ + x##_disabled = 1; \ + return 0; \ +} \ +__setup("no" __stringify(x), x##_setup); + +onchip_setup(fpu); +onchip_setup(dsp); + +/* + * Generic first-level cache init + */ +static void __init cache_init(void) +{ + unsigned long ccr, flags = 0; + + if (cpu_data->type == CPU_SH_NONE) + panic("Unknown CPU"); + + jump_to_P2(); + ccr = ctrl_inl(CCR); + + /* + * If the cache is already enabled .. flush it. + */ + if (ccr & CCR_CACHE_ENABLE) { + unsigned long entries, i, j; + + entries = cpu_data->dcache.sets; + + /* + * If the OC is already in RAM mode, we only have + * half of the entries to flush.. + */ + if (ccr & CCR_CACHE_ORA) + entries >>= 1; + + for (i = 0; i < entries; i++) { + for (j = 0; j < cpu_data->dcache.ways; j++) { + unsigned long data, addr; + + addr = CACHE_OC_ADDRESS_ARRAY | + (j << cpu_data->dcache.way_shift) | + (i << cpu_data->dcache.entry_shift); + + data = ctrl_inl(addr); + + if ((data & (SH_CACHE_UPDATED | SH_CACHE_VALID)) + == (SH_CACHE_UPDATED | SH_CACHE_VALID)) + ctrl_outl(data & ~SH_CACHE_UPDATED, addr); + } + } + } + + /* + * Default CCR values .. enable the caches + * and flush them immediately.. + */ + flags |= CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE; + +#ifdef CCR_CACHE_EMODE + flags |= (ccr & CCR_CACHE_EMODE); +#endif + +#ifdef CONFIG_SH_WRITETHROUGH + /* Turn on Write-through caching */ + flags |= CCR_CACHE_WT; +#else + /* .. or default to Write-back */ + flags |= CCR_CACHE_CB; +#endif + +#ifdef CONFIG_SH_OCRAM + /* Turn on OCRAM -- halve the OC */ + flags |= CCR_CACHE_ORA; + cpu_data->dcache.sets >>= 1; +#endif + + ctrl_outl(flags, CCR); + back_to_P1(); +} + +#ifdef CONFIG_SH_DSP +static void __init release_dsp(void) +{ + unsigned long sr; + + /* Clear SR.DSP bit */ + __asm__ __volatile__ ( + "stc\tsr, %0\n\t" + "and\t%1, %0\n\t" + "ldc\t%0, sr\n\t" + : "=&r" (sr) + : "r" (~SR_DSP) + ); +} + +static void __init dsp_init(void) +{ + unsigned long sr; + + /* + * Set the SR.DSP bit, wait for one instruction, and then read + * back the SR value. + */ + __asm__ __volatile__ ( + "stc\tsr, %0\n\t" + "or\t%1, %0\n\t" + "ldc\t%0, sr\n\t" + "nop\n\t" + "stc\tsr, %0\n\t" + : "=&r" (sr) + : "r" (SR_DSP) + ); + + /* If the DSP bit is still set, this CPU has a DSP */ + if (sr & SR_DSP) + set_bit(CPU_HAS_DSP, &(cpu_data->flags)); + + /* Now that we've determined the DSP status, clear the DSP bit. */ + release_dsp(); +} +#endif /* CONFIG_SH_DSP */ + +/* + * sh_cpu_init + * + * This is our initial entry point for each CPU, and is invoked on the boot + * CPU prior to calling start_kernel(). For SMP, a combination of this and + * start_secondary() will bring up each processor to a ready state prior + * to hand forking the idle loop. + * + * We do all of the basic processor init here, including setting up the + * caches, FPU, DSP, kicking the UBC, etc. By the time start_kernel() is + * hit (and subsequently platform_setup()) things like determining the + * CPU subtype and initial configuration will all be done. + * + * Each processor family is still responsible for doing its own probing + * and cache configuration in detect_cpu_and_cache_system(). + */ +asmlinkage void __init sh_cpu_init(void) +{ + /* First, probe the CPU */ + detect_cpu_and_cache_system(); + + /* Init the cache */ + cache_init(); + + /* Disable the FPU */ + if (fpu_disabled) { + printk("FPU Disabled\n"); + cpu_data->flags &= ~CPU_HAS_FPU; + release_fpu(); + } + + /* FPU initialization */ + if (test_bit(CPU_HAS_FPU, &(cpu_data->flags))) { + clear_thread_flag(TIF_USEDFPU); + current->used_math = 0; + } + +#ifdef CONFIG_SH_DSP + /* Probe for DSP */ + dsp_init(); + + /* Disable the DSP */ + if (dsp_disabled) { + printk("DSP Disabled\n"); + cpu_data->flags &= ~CPU_HAS_DSP; + release_dsp(); + } +#endif + +#ifdef CONFIG_UBC_WAKEUP + /* + * Some brain-damaged loaders decided it would be a good idea to put + * the UBC to sleep. This causes some issues when it comes to things + * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So .. + * we wake it up and hope that all is well. + */ + ubc_wakeup(); +#endif +} + diff -puN arch/sh/kernel/cpu/Makefile~linus arch/sh/kernel/cpu/Makefile --- 25/arch/sh/kernel/cpu/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/cpu/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,13 +2,12 @@ # Makefile for the Linux/SuperH CPU-specifc backends. # -obj-y := irq_ipr.o irq_imask.o +obj-y := irq_ipr.o irq_imask.o init.o obj-$(CONFIG_CPU_SH2) += sh2/ obj-$(CONFIG_CPU_SH3) += sh3/ obj-$(CONFIG_CPU_SH4) += sh4/ -obj-$(CONFIG_SH_DMA) += dma.o obj-$(CONFIG_SH_RTC) += rtc.o obj-$(CONFIG_UBC_WAKEUP) += ubc.o diff -puN /dev/null arch/sh/kernel/cpu/sh3/ex.S --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/kernel/cpu/sh3/ex.S 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,124 @@ +/* + * arch/sh/kernel/cpu/sh3/ex.S + * + * The SH-3 exception vector table. + + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * 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. + * + */ +#include +#include + + .align 2 + .data + +ENTRY(exception_handling_table) + .long exception_error /* 000 */ + .long exception_error +#if defined(CONFIG_MMU) + .long tlb_miss_load /* 040 */ + .long tlb_miss_store + .long initial_page_write + .long tlb_protection_violation_load + .long tlb_protection_violation_store + .long address_error_load + .long address_error_store /* 100 */ +#else + .long exception_error ! tlb miss load /* 040 */ + .long exception_error ! tlb miss store + .long exception_error ! initial page write + .long exception_error ! tlb prot violation load + .long exception_error ! tlb prot violation store + .long exception_error ! address error load + .long exception_error ! address error store /* 100 */ +#endif + .long exception_error ! fpu_exception /* 120 */ + .long exception_error /* 140 */ + .long system_call ! Unconditional Trap /* 160 */ + .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ + .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ +ENTRY(nmi_slot) +#if defined (CONFIG_KGDB_NMI) + .long debug_enter /* 1C0 */ ! Allow trap to debugger +#else + .long exception_none /* 1C0 */ ! Not implemented yet +#endif +ENTRY(user_break_point_trap) + .long break_point_trap /* 1E0 */ +ENTRY(interrupt_table) + ! external hardware + .long do_IRQ ! 0000 /* 200 */ + .long do_IRQ ! 0001 + .long do_IRQ ! 0010 + .long do_IRQ ! 0011 + .long do_IRQ ! 0100 + .long do_IRQ ! 0101 + .long do_IRQ ! 0110 + .long do_IRQ ! 0111 + .long do_IRQ ! 1000 /* 300 */ + .long do_IRQ ! 1001 + .long do_IRQ ! 1010 + .long do_IRQ ! 1011 + .long do_IRQ ! 1100 + .long do_IRQ ! 1101 + .long do_IRQ ! 1110 + .long exception_error + ! Internal hardware + .long do_IRQ ! TMU0 tuni0 /* 400 */ + .long do_IRQ ! TMU1 tuni1 + .long do_IRQ ! TMU2 tuni2 + .long do_IRQ ! ticpi2 + .long do_IRQ ! RTC ati + .long do_IRQ ! pri + .long do_IRQ ! cui + .long do_IRQ ! SCI eri + .long do_IRQ ! rxi /* 500 */ + .long do_IRQ ! txi + .long do_IRQ ! tei + .long do_IRQ ! WDT iti /* 560 */ + .long do_IRQ ! REF rcmi + .long do_IRQ ! rovi + .long do_IRQ + .long do_IRQ /* 5E0 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) + .long do_IRQ ! 32 IRQ irq0 /* 600 */ + .long do_IRQ ! 33 irq1 + .long do_IRQ ! 34 irq2 + .long do_IRQ ! 35 irq3 + .long do_IRQ ! 36 irq4 + .long do_IRQ ! 37 irq5 + .long do_IRQ ! 38 + .long do_IRQ ! 39 + .long do_IRQ ! 40 PINT pint0-7 /* 700 */ + .long do_IRQ ! 41 pint8-15 + .long do_IRQ ! 42 + .long do_IRQ ! 43 + .long do_IRQ ! 44 + .long do_IRQ ! 45 + .long do_IRQ ! 46 + .long do_IRQ ! 47 + .long do_IRQ ! 48 DMAC dei0 /* 800 */ + .long do_IRQ ! 49 dei1 + .long do_IRQ ! 50 dei2 + .long do_IRQ ! 51 dei3 + .long do_IRQ ! 52 IrDA eri1 + .long do_IRQ ! 53 rxi1 + .long do_IRQ ! 54 bri1 + .long do_IRQ ! 55 txi1 + .long do_IRQ ! 56 SCIF eri2 + .long do_IRQ ! 57 rxi2 + .long do_IRQ ! 58 bri2 + .long do_IRQ ! 59 txi2 + .long do_IRQ ! 60 ADC adi /* 980 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7707) + .long do_IRQ ! 61 LCDC lcdi /* 9A0 */ + .long do_IRQ ! 62 PCC pcc0i + .long do_IRQ ! 63 pcc1i /* 9E0 */ +#endif +#endif + diff -puN arch/sh/kernel/cpu/sh3/Makefile~linus arch/sh/kernel/cpu/sh3/Makefile --- 25/arch/sh/kernel/cpu/sh3/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/cpu/sh3/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,3 +2,5 @@ # Makefile for the Linux/SuperH SH-3 backends. # +obj-y := ex.o + diff -puN /dev/null arch/sh/kernel/cpu/sh4/ex.S --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/kernel/cpu/sh4/ex.S 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,316 @@ +/* + * arch/sh/kernel/cpu/sh4/ex.S + * + * The SH-4 exception vector table. + + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * 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. + * + */ +#include +#include + + .align 2 + .data + +ENTRY(exception_handling_table) + .long exception_error /* 000 */ + .long exception_error +#if defined(CONFIG_MMU) + .long tlb_miss_load /* 040 */ + .long tlb_miss_store + .long initial_page_write + .long tlb_protection_violation_load + .long tlb_protection_violation_store + .long address_error_load + .long address_error_store /* 100 */ +#else + .long exception_error ! tlb miss load /* 040 */ + .long exception_error ! tlb miss store + .long exception_error ! initial page write + .long exception_error ! tlb prot violation load + .long exception_error ! tlb prot violation store + .long exception_error ! address error load + .long exception_error ! address error store /* 100 */ +#endif + + .long do_fpu_error /* 120 */ + .long exception_error /* 140 */ + .long system_call ! Unconditional Trap /* 160 */ + .long exception_error ! reserved_instruction (filled by trap_init) /* 180 */ + .long exception_error ! illegal_slot_instruction (filled by trap_init) /*1A0*/ +ENTRY(nmi_slot) +#if defined (CONFIG_KGDB_NMI) + .long debug_enter /* 1C0 */ ! Allow trap to debugger +#else + .long exception_none /* 1C0 */ ! Not implemented yet +#endif +ENTRY(user_break_point_trap) + .long break_point_trap /* 1E0 */ +ENTRY(interrupt_table) + ! external hardware + .long do_IRQ ! 0000 /* 200 */ + .long do_IRQ ! 0001 + .long do_IRQ ! 0010 + .long do_IRQ ! 0011 + .long do_IRQ ! 0100 + .long do_IRQ ! 0101 + .long do_IRQ ! 0110 + .long do_IRQ ! 0111 + .long do_IRQ ! 1000 /* 300 */ + .long do_IRQ ! 1001 + .long do_IRQ ! 1010 + .long do_IRQ ! 1011 + .long do_IRQ ! 1100 + .long do_IRQ ! 1101 + .long do_IRQ ! 1110 + .long exception_error + ! Internal hardware + .long do_IRQ ! TMU0 tuni0 /* 400 */ + .long do_IRQ ! TMU1 tuni1 + .long do_IRQ ! TMU2 tuni2 + .long do_IRQ ! ticpi2 +#if defined(CONFIG_CPU_SUBTYPE_SH7760) + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error /* 500 */ + .long exception_error + .long exception_error +#else + .long do_IRQ ! RTC ati + .long do_IRQ ! pri + .long do_IRQ ! cui + .long do_IRQ ! SCI eri + .long do_IRQ ! rxi /* 500 */ + .long do_IRQ ! txi + .long do_IRQ ! tei +#endif + .long do_IRQ ! WDT iti /* 560 */ + .long do_IRQ ! REF rcmi + .long do_IRQ ! rovi + .long do_IRQ + .long do_IRQ /* 5E0 */ + .long do_IRQ ! 32 Hitachi UDI /* 600 */ + .long do_IRQ ! 33 GPIO + .long do_IRQ ! 34 DMAC dmte0 + .long do_IRQ ! 35 dmte1 + .long do_IRQ ! 36 dmte2 + .long do_IRQ ! 37 dmte3 + .long do_IRQ ! 38 dmae + .long exception_error ! 39 /* 6E0 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7760) + .long exception_error /* 700 */ + .long exception_error + .long exception_error + .long exception_error /* 760 */ +#else + .long do_IRQ ! 40 SCIF eri /* 700 */ + .long do_IRQ ! 41 rxi + .long do_IRQ ! 42 bri + .long do_IRQ ! 43 txi +#endif +#if CONFIG_NR_ONCHIP_DMA_CHANNELS == 8 + .long do_IRQ ! 44 DMAC dmte4 /* 780 */ + .long do_IRQ ! 45 dmte5 + .long do_IRQ ! 46 dmte6 + .long do_IRQ ! 47 dmte7 /* 7E0 */ +#else + .long exception_error ! 44 /* 780 */ + .long exception_error ! 45 + .long exception_error ! 46 + .long exception_error ! 47 +#endif + .long do_fpu_state_restore ! 48 /* 800 */ + .long do_fpu_state_restore ! 49 /* 820 */ +#if defined(CONFIG_CPU_SUBTYPE_SH7751) + .long exception_error /* 840 */ + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error /* 900 */ + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long do_IRQ ! PCI serr /* A00 */ + .long do_IRQ ! dma3 + .long do_IRQ ! dma2 + .long do_IRQ ! dma1 + .long do_IRQ ! dma0 + .long do_IRQ ! pwon + .long do_IRQ ! pwdwn + .long do_IRQ ! err + .long do_IRQ ! TMU3 tuni3 /* B00 */ + .long exception_error + .long exception_error + .long exception_error + .long do_IRQ ! TMU4 tuni4 /* B80 */ +#elif defined(CONFIG_CPU_SUBTYPE_SH7760) + .long do_IRQ ! IRQ irq6 /* 840 */ + .long do_IRQ ! irq7 + .long do_IRQ ! SCIF eri0 + .long do_IRQ ! rxi0 + .long do_IRQ ! bri0 + .long do_IRQ ! txi0 + .long do_IRQ ! HCAN2 cani0 /* 900 */ + .long do_IRQ ! cani1 + .long do_IRQ ! SSI ssii0 + .long do_IRQ ! ssii1 + .long do_IRQ ! HAC haci0 + .long do_IRQ ! haci1 + .long do_IRQ ! IIC iici0 + .long do_IRQ ! iici1 + .long do_IRQ ! USB usbi /* A00 */ + .long do_IRQ ! LCDC vint + .long exception_error + .long exception_error + .long do_IRQ ! DMABRG dmabrgi0 + .long do_IRQ ! dmabrgi1 + .long do_IRQ ! dmabrgi2 + .long exception_error + .long do_IRQ ! SCIF eri1 /* B00 */ + .long do_IRQ ! rxi1 + .long do_IRQ ! bri1 + .long do_IRQ ! txi1 + .long do_IRQ ! eri2 + .long do_IRQ ! rxi2 + .long do_IRQ ! bri2 + .long do_IRQ ! txi2 + .long do_IRQ ! SIM simeri /* C00 */ + .long do_IRQ ! simrxi + .long do_IRQ ! simtxi + .long do_IRQ ! simtei + .long do_IRQ ! HSPI spii + .long exception_error + .long exception_error + .long exception_error + .long do_IRQ ! MMCIF mmci0 /* D00 */ + .long do_IRQ ! mmci1 + .long do_IRQ ! mmci2 + .long do_IRQ ! mmci3 + .long exception_error + .long exception_error + .long exception_error + .long exception_error + .long exception_error /* E00 */ + .long exception_error + .long exception_error + .long exception_error + .long do_IRQ ! MFI mfii + .long exception_error + .long exception_error + .long exception_error + .long exception_error /* F00 */ + .long exception_error + .long exception_error + .long exception_error + .long do_IRQ ! ADC adi + .long do_IRQ ! CMT cmti /* FA0 */ +#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) + .long exception_error ! 50 0x840 + .long exception_error ! 51 0x860 + .long exception_error ! 52 0x880 + .long exception_error ! 53 0x8a0 + .long exception_error ! 54 0x8c0 + .long exception_error ! 55 0x8e0 + .long exception_error ! 56 0x900 + .long exception_error ! 57 0x920 + .long exception_error ! 58 0x940 + .long exception_error ! 59 0x960 + .long exception_error ! 60 0x980 + .long exception_error ! 61 0x9a0 + .long exception_error ! 62 0x9c0 + .long exception_error ! 63 0x9e0 + .long do_IRQ ! 64 0xa00 PCI serr + .long do_IRQ ! 65 0xa20 err + .long do_IRQ ! 66 0xa40 ad + .long do_IRQ ! 67 0xa60 pwr_dwn + .long exception_error ! 68 0xa80 + .long exception_error ! 69 0xaa0 + .long exception_error ! 70 0xac0 + .long exception_error ! 71 0xae0 + .long do_IRQ ! 72 0xb00 DMA INT0 + .long do_IRQ ! 73 0xb20 INT1 + .long do_IRQ ! 74 0xb40 INT2 + .long do_IRQ ! 75 0xb60 INT3 + .long do_IRQ ! 76 0xb80 INT4 + .long exception_error ! 77 0xba0 + .long do_IRQ ! 78 0xbc0 DMA ERR + .long exception_error ! 79 0xbe0 + .long do_IRQ ! 80 0xc00 PIO0 + .long do_IRQ ! 81 0xc20 PIO1 + .long do_IRQ ! 82 0xc40 PIO2 + .long exception_error ! 83 0xc60 + .long exception_error ! 84 0xc80 + .long exception_error ! 85 0xca0 + .long exception_error ! 86 0xcc0 + .long exception_error ! 87 0xce0 + .long exception_error ! 88 0xd00 + .long exception_error ! 89 0xd20 + .long exception_error ! 90 0xd40 + .long exception_error ! 91 0xd60 + .long exception_error ! 92 0xd80 + .long exception_error ! 93 0xda0 + .long exception_error ! 94 0xdc0 + .long exception_error ! 95 0xde0 + .long exception_error ! 96 0xe00 + .long exception_error ! 97 0xe20 + .long exception_error ! 98 0xe40 + .long exception_error ! 99 0xe60 + .long exception_error ! 100 0xe80 + .long exception_error ! 101 0xea0 + .long exception_error ! 102 0xec0 + .long exception_error ! 103 0xee0 + .long exception_error ! 104 0xf00 + .long exception_error ! 105 0xf20 + .long exception_error ! 106 0xf40 + .long exception_error ! 107 0xf60 + .long exception_error ! 108 0xf80 + .long exception_error ! 109 0xfa0 + .long exception_error ! 110 0xfc0 + .long exception_error ! 111 0xfe0 + .long do_IRQ ! 112 0x1000 Mailbox + .long exception_error ! 113 0x1020 + .long exception_error ! 114 0x1040 + .long exception_error ! 115 0x1060 + .long exception_error ! 116 0x1080 + .long exception_error ! 117 0x10a0 + .long exception_error ! 118 0x10c0 + .long exception_error ! 119 0x10e0 + .long exception_error ! 120 0x1100 + .long exception_error ! 121 0x1120 + .long exception_error ! 122 0x1140 + .long exception_error ! 123 0x1160 + .long exception_error ! 124 0x1180 + .long exception_error ! 125 0x11a0 + .long exception_error ! 126 0x11c0 + .long exception_error ! 127 0x11e0 + .long exception_error ! 128 0x1200 + .long exception_error ! 129 0x1220 + .long exception_error ! 130 0x1240 + .long exception_error ! 131 0x1260 + .long exception_error ! 132 0x1280 + .long exception_error ! 133 0x12a0 + .long exception_error ! 134 0x12c0 + .long exception_error ! 135 0x12e0 + .long exception_error ! 136 0x1300 + .long exception_error ! 137 0x1320 + .long exception_error ! 138 0x1340 + .long exception_error ! 139 0x1360 + .long do_IRQ ! 140 0x1380 EMPI INV_ADDR + .long exception_error ! 141 0x13a0 + .long exception_error ! 142 0x13c0 + .long exception_error ! 143 0x13e0 +#endif + diff -puN arch/sh/kernel/cpu/sh4/fpu.c~linus arch/sh/kernel/cpu/sh4/fpu.c --- 25/arch/sh/kernel/cpu/sh4/fpu.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/cpu/sh4/fpu.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: fpu.c,v 1.2 2003/05/04 19:29:54 lethal Exp $ +/* $Id: fpu.c,v 1.3 2003/09/23 23:15:44 lethal Exp $ * * linux/arch/sh/kernel/fpu.c * @@ -18,6 +18,14 @@ #include #include +/* The PR (precision) bit in the FP Status Register must be clear when + * an frchg instruction is executed, otherwise the instruction is undefined. + * Executing frchg with PR set causes a trap on some SH4 implementations. + */ + +#define FPSCR_RCHG 0x00000000 + + /* * Save FPU registers onto task structure. * Assume called with FPU enabled (SR.FD=0). @@ -61,9 +69,11 @@ save_fpu(struct task_struct *tsk) "fmov.s fr3, @-%0\n\t" "fmov.s fr2, @-%0\n\t" "fmov.s fr1, @-%0\n\t" - "fmov.s fr0, @-%0" + "fmov.s fr0, @-%0\n\t" + "lds %2, fpscr\n\t" : /* no output */ : "r" ((char *)(&tsk->thread.fpu.hard.status)), + "r" (FPSCR_RCHG), "r" (FPSCR_INIT) : "memory"); @@ -112,7 +122,7 @@ restore_fpu(struct task_struct *tsk) "lds.l @%0+, fpscr\n\t" "lds.l @%0+, fpul\n\t" : /* no output */ - : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT) + : "r" (&tsk->thread.fpu), "r" (FPSCR_RCHG) : "memory"); } @@ -160,9 +170,10 @@ fpu_init(void) "fsts fpul, fr13\n\t" "fsts fpul, fr14\n\t" "fsts fpul, fr15\n\t" - "frchg" + "frchg\n\t" + "lds %2, fpscr\n\t" : /* no output */ - : "r" (0), "r" (FPSCR_INIT)); + : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); } /** diff -puN arch/sh/kernel/cpu/sh4/Makefile~linus arch/sh/kernel/cpu/sh4/Makefile --- 25/arch/sh/kernel/cpu/sh4/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/cpu/sh4/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,13 +2,8 @@ # Makefile for the Linux/SuperH SH-4 backends. # -obj-y := fpu.o +obj-y := fpu.o ex.o obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += irq_intc2.o -obj-$(CONFIG_CPU_SUBTYPE_SH7751) += irq_intc2.o - -ifeq ($(CONFIG_PCI),y) -obj-$(CONFIG_CPU_SUBTYPE_ST40STB1) += pci-st40.o -obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci-sh7751.o -endif +obj-$(CONFIG_SH_STORE_QUEUES) += sq.o diff -puN -L arch/sh/kernel/cpu/sh4/pci-sh7751.c arch/sh/kernel/cpu/sh4/pci-sh7751.c~linus /dev/null --- 25/arch/sh/kernel/cpu/sh4/pci-sh7751.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,503 +0,0 @@ -/* - * Low-Level PCI Support for the SH7751 - * - * Dustin McIntire (dustin@sensoria.com) - * Derived from arch/i386/kernel/pci-*.c which bore the message: - * (c) 1999--2000 Martin Mares - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct pci_ops *pci_check_direct(void); -void pcibios_resource_survey(void); -static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin); -static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin); - -unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1; -int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus; -struct pci_ops *pci_root_ops; - -/* - * Direct access to PCI hardware... - */ - -#ifdef CONFIG_PCI_DIRECT - - -#define CONFIG_CMD(bus, devfn, where) (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3)) - -#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg) - -/* - * Functions for accessing PCI configuration space with type 1 accesses - */ -static int pci_conf1_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) -{ - unsigned long flags; - u32 word; - - /* - * PCIPDR may only be accessed as 32 bit words, - * so we must do byte alignment by hand - */ - local_irq_save(flags); - outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); - word = inl(PCI_REG(SH7751_PCIPDR)); - local_irq_restore(flags); - - switch (size) { - case 1: - switch (where & 0x3) { - case 3: *value = (u8)(word >> 24); break; - case 2: *value = (u8)(word >> 16); break; - case 1: *value = (u8)(word >> 8); break; - } - break; - case 2: - switch (where & 0x2) { - case 2: *value = (u16)(word >> 16); break; - case 1: *value = (u16)(word >> 8); break; - } - break; - case 4: - *value = word; - break; - } - - PCIDBG(4,"pci_conf1_read@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),*value); - - return PCIBIOS_SUCCESSFUL; -} - -/* - * Since SH7751 only does 32bit access we'll have to do a read,mask,write operation. - * We'll allow an odd byte offset, though it should be illegal. - */ -static int pci_conf1_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) -{ - u32 word,mask; - unsigned long flags; - u32 shift = (where & 3) * 8; - - if(size == 1) { - mask = ((1 << 8) - 1) << shift; // create the byte mask - } else if(size == 2){ - if(shift == 24) - return PCIBIOS_BAD_REGISTER_NUMBER; - mask = ((1 << 16) - 1) << shift; // create the word mask - } - - local_irq_save(flags); - outl(CONFIG_CMD(bus,devfn,where), PCI_REG(SH7751_PCIPAR)); - - if(size == 4){ - outl(value, PCI_REG(SH7751_PCIPDR)); - local_irq_restore(flags); - - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),value); - - return PCIBIOS_SUCCESSFUL; - } - - word = inl(PCI_REG(SH7751_PCIPDR)) ; - word &= ~mask; - word |= value << shift; - outl(word, PCI_REG(SH7751_PCIPDR)); - local_irq_restore(flags); - - PCIDBG(4,"pci_conf1_write@0x%08x=0x%x\n", CONFIG_CMD(bus,devfn,where),word); - - return PCIBIOS_SUCCESSFUL; -} - -#undef CONFIG_CMD - -static struct pci_ops pci_direct_conf1 = { - .read = pci_conf1_read, - .write = pci_conf1_write, -}; - -struct pci_ops * __init pci_check_direct(void) -{ - unsigned int tmp, id; - - /* check for SH7751 hardware */ - id = (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID; - if(inl(SH7751_PCIREG_BASE+SH7751_PCICONF0) != id) { - PCIDBG(2,"PCI: This is not an SH7751\n"); - return NULL; - } - /* - * Check if configuration works. - */ - if (pci_probe & PCI_PROBE_CONF1) { - tmp = inl (PCI_REG(SH7751_PCIPAR)); - outl (0x80000000, PCI_REG(SH7751_PCIPAR)); - if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) { - outl (tmp, PCI_REG(SH7751_PCIPAR)); - printk(KERN_INFO "PCI: Using configuration type 1\n"); - request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1"); - return &pci_direct_conf1; - } - outl (tmp, PCI_REG(SH7751_PCIPAR)); - } - - PCIDBG(2,"PCI: pci_check_direct failed\n"); - return NULL; -} - -#endif - -/* - * BIOS32 and PCI BIOS handling. - * - * The BIOS version of the pci functions is not yet implemented but it is left - * in for completeness. Currently an error will be generated at compile time. - */ - -#ifdef CONFIG_PCI_BIOS - -#error PCI BIOS is not yet supported on SH7751 - -#endif /* CONFIG_PCI_BIOS */ - -/***************************************************************************************/ - -/* - * Handle bus scanning and fixups .... - */ - - -/* - * Discover remaining PCI buses in case there are peer host bridges. - * We use the number of last PCI bus provided by the PCI BIOS. - */ -static void __init pcibios_fixup_peer_bridges(void) -{ - int n; - struct pci_bus bus; - struct pci_dev dev; - u16 l; - - if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) - return; - PCIDBG(2,"PCI: Peer bridge fixup\n"); - for (n=0; n <= pcibios_last_bus; n++) { - if (pci_find_bus(0, n)) - continue; - bus.number = n; - bus.ops = pci_root_ops; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn<256; dev.devfn += 8) - if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) && - l != 0x0000 && l != 0xffff) { - PCIDBG(3,"Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); - printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); - pci_scan_bus(n, pci_root_ops, NULL); - break; - } - } -} - - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - PCIDBG(3,"PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; - -/* - * Called after each bus is probed, but before its children - * are examined. - */ - -void __init pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -/* - * Initialization. Try all known PCI access methods. Note that we support - * using both PCI BIOS and direct access: in such cases, we use I/O ports - * to access config space. - * - * Note that the platform specific initialization (BSC registers, and memory - * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it - * exitst and via the platform defined function pcibios_init_platform(). - * See pci_bigsur.c for implementation; - * - * The BIOS version of the pci functions is not yet implemented but it is left - * in for completeness. Currently an error will be genereated at compile time. - */ - -void __init pcibios_init(void) -{ - struct pci_ops *bios = NULL; - struct pci_ops *dir = NULL; - - PCIDBG(1,"PCI: Starting intialization.\n"); -#ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) { - pci_probe |= PCI_BIOS_SORT; - pci_bios_present = 1; - } -#endif -#ifdef CONFIG_PCI_DIRECT - if (pci_probe & PCI_PROBE_CONF1 ) - dir = pci_check_direct(); -#endif - if (dir) { - pci_root_ops = dir; - if(!pcibios_init_platform()) - PCIDBG(1,"PCI: Initialization failed\n"); - if (sh_mv.mv_init_pci != NULL) - sh_mv.mv_init_pci(); - } - else if (bios) - pci_root_ops = bios; - else { - PCIDBG(1,"PCI: No PCI bus detected\n"); - return; - } - - PCIDBG(1,"PCI: Probing PCI hardware\n"); - pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL); - //pci_assign_unassigned_resources(); - pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq); - pcibios_fixup_peer_bridges(); - pcibios_resource_survey(); - -#ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) - pcibios_sort(); -#endif -} - -char * __init pcibios_setup(char *str) -{ - if (!strcmp(str, "off")) { - pci_probe = 0; - return NULL; - } -#ifdef CONFIG_PCI_BIOS - else if (!strcmp(str, "bios")) { - pci_probe = PCI_PROBE_BIOS; - return NULL; - } else if (!strcmp(str, "nobios")) { - pci_probe &= ~PCI_PROBE_BIOS; - return NULL; - } else if (!strcmp(str, "nosort")) { - pci_probe |= PCI_NO_SORT; - return NULL; - } else if (!strcmp(str, "biosirq")) { - pci_probe |= PCI_BIOS_IRQ_SCAN; - return NULL; - } -#endif -#ifdef CONFIG_PCI_DIRECT - else if (!strcmp(str, "conf1")) { - pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS; - return NULL; - } -#endif - else if (!strcmp(str, "rom")) { - pci_probe |= PCI_ASSIGN_ROMS; - return NULL; - } else if (!strncmp(str, "lastbus=", 8)) { - pcibios_last_bus = simple_strtol(str+8, NULL, 0); - return NULL; - } - return str; -} - -/* - * Allocate the bridge and device resources - */ - -static void __init pcibios_allocate_bus_resources(struct list_head *bus_list) -{ - struct list_head *ln; - struct pci_bus *bus; - struct pci_dev *dev; - int idx; - struct resource *r, *pr; - - PCIDBG(2,"PCI: pcibios_allocate_bus_reasources called\n" ); - /* Depth-First Search on bus tree */ - for (ln=bus_list->next; ln != bus_list; ln=ln->next) { - bus = pci_bus_b(ln); - if ((dev = bus->self)) { - for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) { - r = &dev->resource[idx]; - if (!r->start) - continue; - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) - printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev)); - } - } - pcibios_allocate_bus_resources(&bus->children); - } -} - -static void __init pcibios_allocate_resources(int pass) -{ - struct pci_dev *dev; - int idx, disabled; - u16 command; - struct resource *r, *pr; - - PCIDBG(2,"PCI: pcibios_allocate_resources pass %d called\n", pass); - pci_for_each_dev(dev) { - pci_read_config_word(dev, PCI_COMMAND, &command); - for(idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (r->parent) /* Already allocated */ - continue; - if (!r->start) /* Address not assigned at all */ - continue; - if (r->flags & IORESOURCE_IO) - disabled = !(command & PCI_COMMAND_IO); - else - disabled = !(command & PCI_COMMAND_MEMORY); - if (pass == disabled) { - PCIDBG(3,"PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n", - r->start, r->end, r->flags, disabled, pass); - pr = pci_find_parent_resource(dev, r); - if (!pr || request_resource(pr, r) < 0) { - printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, pci_name(dev)); - /* We'll assign a new address later */ - r->end -= r->start; - r->start = 0; - } - } - } - if (!pass) { - r = &dev->resource[PCI_ROM_RESOURCE]; - if (r->flags & PCI_ROM_ADDRESS_ENABLE) { - /* Turn the ROM off, leave the resource region, but keep it unregistered. */ - u32 reg; - PCIDBG(3,"PCI: Switching off ROM of %s\n", pci_name(dev)); - r->flags &= ~PCI_ROM_ADDRESS_ENABLE; - pci_read_config_dword(dev, dev->rom_base_reg, ®); - pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE); - } - } - } -} - -static void __init pcibios_assign_resources(void) -{ - struct pci_dev *dev; - int idx; - struct resource *r; - - PCIDBG(2,"PCI: pcibios_assign_resources called\n"); - pci_for_each_dev(dev) { - int class = dev->class >> 8; - - /* Don't touch classless devices and host bridges */ - if (!class || class == PCI_CLASS_BRIDGE_HOST) - continue; - - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - - /* - * Don't touch IDE controllers and I/O ports of video cards! - */ - if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) || - (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO))) - continue; - - /* - * We shall assign a new address to this resource, either because - * the BIOS forgot to do so or because we have decided the old - * address was unusable for some reason. - */ - if (!r->start && r->end) - pci_assign_resource(dev, idx); - } - - if (pci_probe & PCI_ASSIGN_ROMS) { - r = &dev->resource[PCI_ROM_RESOURCE]; - r->end -= r->start; - r->start = 0; - if (r->end) - pci_assign_resource(dev, PCI_ROM_RESOURCE); - } - } -} - -void __init pcibios_resource_survey(void) -{ - PCIDBG(1,"PCI: Allocating resources\n"); - pcibios_allocate_bus_resources(&pci_root_buses); - pcibios_allocate_resources(0); - pcibios_allocate_resources(1); - pcibios_assign_resources(); -} - - -/***************************************************************************************/ -/* - * IRQ functions - */ -static u8 __init pcibios_swizzle(struct pci_dev *dev, u8 *pin) -{ - /* no swizzling */ - return PCI_SLOT(dev->devfn); -} - -static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - - /* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */ - irq = pcibios_map_platform_irq(slot,pin); - if( irq < 0 ) { - PCIDBG(3,"PCI: Error mapping IRQ on device %s\n", dev->name); - return irq; - } - - PCIDBG(2,"Setting IRQ for slot %s to %d\n", pci_name(dev), irq); - - return irq; -} diff -puN -L arch/sh/kernel/cpu/sh4/pci-st40.c arch/sh/kernel/cpu/sh4/pci-st40.c~linus /dev/null --- 25/arch/sh/kernel/cpu/sh4/pci-st40.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,423 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Support functions for the ST40 PCI hardware. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pci-st40.h" - -/* This is in P2 of course */ -#define ST40PCI_BASE_ADDRESS (0xb0000000) -#define ST40PCI_MEM_ADDRESS (ST40PCI_BASE_ADDRESS+0x0) -#define ST40PCI_IO_ADDRESS (ST40PCI_BASE_ADDRESS+0x06000000) -#define ST40PCI_REG_ADDRESS (ST40PCI_BASE_ADDRESS+0x07000000) - -#define ST40PCI_REG(x) (ST40PCI_REG_ADDRESS+(ST40PCI_##x)) - -#define ST40PCI_WRITE(reg,val) writel((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_SHORT(reg,val) writew((val),ST40PCI_REG(reg)) -#define ST40PCI_WRITE_BYTE(reg,val) writeb((val),ST40PCI_REG(reg)) - -#define ST40PCI_READ(reg) readl(ST40PCI_REG(reg)) -#define ST40PCI_READ_SHORT(reg) readw(ST40PCI_REG(reg)) -#define ST40PCI_READ_BYTE(reg) readb(ST40PCI_REG(reg)) - -#define ST40PCI_SERR_IRQ 64 -#define ST40PCI_SERR_INT_GROUP 0 -#define ST40PCI_SERR_INT_POS 0 -#define ST40PCI_SERR_INT_PRI 15 - -#define ST40PCI_ERR_IRQ 65 -#define ST40PCI_ERR_INT_GROUP 1 -#define ST40PCI_ERR_INT_POS 1 -#define ST40PCI_ERR_INT_PRI 14 - - -/* Macros to extract PLL params */ -#define PLL_MDIV(reg) ( ((unsigned)reg) & 0xff ) -#define PLL_NDIV(reg) ( (((unsigned)reg)>>8) & 0xff ) -#define PLL_PDIV(reg) ( (((unsigned)reg)>>16) & 0x3 ) -#define PLL_SETUP(reg) ( (((unsigned)reg)>>19) & 0x1ff ) - -/* Build up the appropriate settings */ -#define PLL_SET(mdiv,ndiv,pdiv,setup) \ -( ((mdiv)&0xff) | (((ndiv)&0xff)<<8) | (((pdiv)&3)<<16)| (((setup)&0x1ff)<<19)) - -#define PLLPCICR (0xbb040000+0x10) - -#define PLLPCICR_POWERON (1<<28) -#define PLLPCICR_OUT_EN (1<<29) -#define PLLPCICR_LOCKSELECT (1<<30) -#define PLLPCICR_LOCK (1<<31) - - -#define PLL_25MHZ 0x793c8512 -#define PLL_33MHZ PLL_SET(18,88,3,295) - - -static __init void SetPCIPLL(void) -{ - /* Stop the PLL */ - writel(0, PLLPCICR); - - /* Always run at 33Mhz. The PCI clock is totally async - * to the rest of the system - */ - writel(PLL_33MHZ | PLLPCICR_POWERON, PLLPCICR); - - printk("ST40PCI: Waiting for PCI PLL to lock\n"); - while ((readl(PLLPCICR) & PLLPCICR_LOCK) == 0); - writel(readl(PLLPCICR) | PLLPCICR_OUT_EN, PLLPCICR); -} - - -static irqreturn_t st40_pci_irq(int irq, void *dev_instance, struct pt_regs *regs) -{ - - unsigned pci_int, pci_air, pci_cir, pci_aint; - - pci_int = ST40PCI_READ(INT); - pci_cir = ST40PCI_READ(CIR); - pci_air = ST40PCI_READ(AIR); - - if (pci_int) { - printk("PCI INTERRUPT!\n"); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(INT, ~0); - } - - pci_aint = ST40PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - ST40PCI_WRITE(AINT, ~0); - } - - return IRQ_HANDLED; -} - - -/* Rounds a number UP to the nearest power of two. Used for - * sizing the PCI window. - */ -static u32 __init r2p2(u32 num) -{ - int i = 31; - u32 tmp = num; - - if (num == 0) - return 0; - - do { - if (tmp & (1 << 31)) - break; - i--; - tmp <<= 1; - } while (i >= 0); - - tmp = 1 << i; - /* If the original number isn't a power of 2, round it up */ - if (tmp != num) - tmp <<= 1; - - return tmp; -} - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - printk("PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} - - -/* Add future fixups here... */ -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { 0 } -}; - -int __init st40pci_init(unsigned memStart, unsigned memSize) -{ - u32 lsr0; - - SetPCIPLL(); - - /* Initialises the ST40 pci subsystem, performing a reset, then programming - * up the address space decoders appropriately - */ - - /* Should reset core here as well methink */ - - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_SOFT_RESET); - - /* Loop while core resets */ - while (ST40PCI_READ(CR) & CR_SOFT_RESET); - - /* Now, lets reset all the cards on the bus with extreme prejudice */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_RSTCTL); - udelay(250); - - /* Set bus active, take it out of reset */ - ST40PCI_WRITE(CR, CR_LOCK_MASK | CR_CFINT | CR_PFCS | CR_PFE); - - /* The PCI spec says that no access must be made to the bus until 1 second - * after reset. This seem ludicrously long, but some delay is needed here - */ - mdelay(1000); - - /* Switch off interrupts */ - ST40PCI_WRITE(INTM, 0); - ST40PCI_WRITE(AINT, 0); - - /* Allow it to be a master */ - - ST40PCI_WRITE_SHORT(CSR_CMD, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_IO); - - /* Accesse to the 0xb0000000 -> 0xb6000000 area will go through to 0x10000000 -> 0x16000000 - * on the PCI bus. This allows a nice 1-1 bus to phys mapping. - */ - - - ST40PCI_WRITE(MBR, 0x10000000); - /* Always set the max size 128M (actually, it is only 96MB wide) */ - ST40PCI_WRITE(MBMR, 0x07ff0000); - - /* I/O addresses are mapped at 0xb6000000 -> 0xb7000000. These are changed to 0, to - * allow cards that have legacy io such as vga to function correctly. This gives a - * maximum of 64K of io/space as only the bottom 16 bits of the address are copied - * over to the bus when the transaction is made. 64K of io space is more than enough - */ - ST40PCI_WRITE(IOBR, 0x0); - /* Set up the 64K window */ - ST40PCI_WRITE(IOBMR, 0x0); - - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ - - if (memSize < (64 * 1024)) { - printk("Ridiculous memory size of 0x%x?\n",memSize); - return 0; - } - - lsr0 = - (memSize > - (512 * 1024 * 1024)) ? 0x1fff0001 : ((r2p2(memSize) - - 0x10000) | 0x1); - - ST40PCI_WRITE(LSR0, lsr0); - - ST40PCI_WRITE(CSR_MBAR0, memStart); - ST40PCI_WRITE(LAR0, memStart); - - /* Maximise timeout values */ - ST40PCI_WRITE_BYTE(CSR_TRDY, 0xff); - ST40PCI_WRITE_BYTE(CSR_RETRY, 0xff); - ST40PCI_WRITE_BYTE(CSR_MIT, 0xff); - - - /* Install the pci interrupt handlers */ - make_intc2_irq(ST40PCI_SERR_IRQ, INTC2_BASE0, - ST40PCI_SERR_INT_GROUP, ST40PCI_SERR_INT_POS, - ST40PCI_SERR_INT_PRI); - - make_intc2_irq(ST40PCI_ERR_IRQ, INTC2_BASE0, ST40PCI_ERR_INT_GROUP, - ST40PCI_ERR_INT_POS, ST40PCI_ERR_INT_PRI); - - - return 1; -} - -char * __init pcibios_setup(char *str) -{ - return str; -} - - -#define SET_CONFIG_BITS(bus,devfn,where)\ - (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0)) - -#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) - - -static int CheckForMasterAbort(void) -{ - if (ST40PCI_READ(INT) & INT_MADIM) { - /* Should we clear config space version as well ??? */ - ST40PCI_WRITE(INT, INT_MADIM); - ST40PCI_WRITE_SHORT(CSR_STATUS, 0); - return 1; - } - - return 0; -} - -/* Write to config register */ -static int st40pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - switch (size) { - case 1: - *val = (u8)ST40PCI_READ_BYTE(PDR + (where & 3)); - break; - case 2: - *val = (u16)ST40PCI_READ_SHORT(PDR + (where & 2)); - break; - case 4: - *val = ST40PCI_READ(PDR); - break; - } - - if (CheckForMasterAbort()){ - switch (size) { - case 1: - *val = (u8)0xff; - break; - case 2: - *val = (u16)0xffff; - break; - case 4: - *val = 0xffffffff; - break; - } - } - - return PCIBIOS_SUCCESSFUL; -} - -static int st40pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - ST40PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - ST40PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); - break; - case 2: - ST40PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); - break; - case 4: - ST40PCI_WRITE(PDR, val); - break; - } - - CheckForMasterAbort(); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - .read = st40pci_read, - .write = st40pci_write, -}; - - -/* Everything hangs off this */ -static struct pci_bus *pci_root_bus; - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - return PCI_SLOT(dev->devfn); -} - - -/* This needs to be shunted out of here into the board specific bit */ -#define HARP_PCI_IRQ 1 -#define HARP_BRIDGE_IRQ 2 -#define OVERDRIVE_SLOT0_IRQ 0 - -static int __init map_harp_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - switch (slot) { -#ifdef CONFIG_SH_STB1_HARP - case 2: /*This is the PCI slot on the */ - return HARP_PCI_IRQ; - case 1: /* this is the bridge */ - return HARP_BRIDGE_IRQ; -#elif defined(CONFIG_SH_STB1_OVERDRIVE) - case 1: - case 2: - case 3: - return slot - 1; -#else -#error Unknown board -#endif - default: - return -1; - } -} - -void __init pcibios_init(void) -{ - extern unsigned long memory_start, memory_end; - - if (sh_mv.mv_init_pci != NULL) { - sh_mv.mv_init_pci(); - } - - /* The pci subsytem needs to know where memory is and how much - * of it there is. I've simply made these globals. A better mechanism - * is probably needed. - */ - st40pci_init(PHYSADDR(memory_start), - PHYSADDR(memory_end) - PHYSADDR(memory_start)); - - if (request_irq(ST40PCI_ERR_IRQ, st40_pci_irq, - SA_INTERRUPT, "st40pci", NULL)) { - printk(KERN_ERR "st40pci: Cannot hook interrupt\n"); - return; - } - - /* Enable the PCI interrupts on the device */ - ST40PCI_WRITE(INTM, ~0); - ST40PCI_WRITE(AINT, ~0); - - /* Map the io address apprioately */ -#ifdef CONFIG_HD64465 - hd64465_port_map(PCIBIOS_MIN_IO, (64 * 1024) - PCIBIOS_MIN_IO + 1, - ST40_IO_ADDR + PCIBIOS_MIN_IO, 0); -#endif - - /* ok, do the scan man */ - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_harp_irq); - -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ -} diff -puN -L arch/sh/kernel/cpu/sh4/pci-st40.h arch/sh/kernel/cpu/sh4/pci-st40.h~linus /dev/null --- 25/arch/sh/kernel/cpu/sh4/pci-st40.h +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Defintions for the ST40 PCI hardware. - */ - -#ifndef __PCI_ST40_H__ -#define __PCI_ST40_H__ - -#define ST40PCI_VCR_STATUS 0x00 - -#define ST40PCI_VCR_VERSION 0x08 - -#define ST40PCI_CR 0x10 - -#define CR_SOFT_RESET (1<<12) -#define CR_PFCS (1<<11) -#define CR_PFE (1<<9) -#define CR_BMAM (1<<6) -#define CR_HOST (1<<5) -#define CR_CLKEN (1<<4) -#define CR_SOCS (1<<3) -#define CR_IOCS (1<<2) -#define CR_RSTCTL (1<<1) -#define CR_CFINT (1<<0) -#define CR_LOCK_MASK 0x5a000000 - - -#define ST40PCI_LSR0 0X14 -#define ST40PCI_LAR0 0x1c - -#define ST40PCI_INT 0x24 -#define INT_MADIM (1<<2) - - -#define ST40PCI_INTM 0x28 -#define ST40PCI_AIR 0x2c -#define ST40PCI_CIR 0x30 -#define ST40PCI_AINT 0x40 -#define ST40PCI_AINTM 0x44 -#define ST40PCI_BMIR 0x48 -#define ST40PCI_PAR 0x4c -#define ST40PCI_MBR 0x50 -#define ST40PCI_IOBR 0x54 -#define ST40PCI_PINT 0x58 -#define ST40PCI_PINTM 0x5c -#define ST40PCI_MBMR 0x70 -#define ST40PCI_IOBMR 0x74 -#define ST40PCI_PDR 0x78 - -/* These are configs space registers */ -#define ST40PCI_CSR_VID 0x10000 -#define ST40PCI_CSR_DID 0x10002 -#define ST40PCI_CSR_CMD 0x10004 -#define ST40PCI_CSR_STATUS 0x10006 -#define ST40PCI_CSR_MBAR0 0x10010 -#define ST40PCI_CSR_TRDY 0x10040 -#define ST40PCI_CSR_RETRY 0x10041 -#define ST40PCI_CSR_MIT 0x1000d - -#define ST40_IO_ADDR 0xb6000000 - -#endif /* __PCI_ST40_H__ */ diff -puN /dev/null arch/sh/kernel/cpu/sh4/sq.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/kernel/cpu/sh4/sq.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,484 @@ +/* + * arch/sh/kernel/cpu/sq.c + * + * General management API for SH-4 integrated Store Queues + * + * Copyright (C) 2001, 2002, 2003 Paul Mundt + * Copyright (C) 2001, 2002 M. R. Brown + * + * Some of this code has been adopted directly from the old arch/sh/mm/sq.c + * hack that was part of the LinuxDC project. For all intensive purposes, this + * is a completely new interface that really doesn't have much in common with + * the old zone-based approach at all. Infact, I'm only listing it here for + * general completeness. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static LIST_HEAD(sq_mapping_list); + +/** + * sq_flush - Flush (prefetch) the store queue cache + * + * @addr: the store queue address to flush + * + * Executes a prefetch instruction on the specified store queue cache, + * so that the cached data is written to physical memory. + */ +inline void sq_flush(void *addr) +{ + __asm__ __volatile__ ("pref @%0": "=r" (addr) : : "memory"); +} + +/** + * sq_flush_range - Flush (prefetch) a specific SQ range + * + * @start: the store queue address to start flushing from + * @len: the length to flush + * + * Flushes the store queue cache from @start to @start + @len in a + * linear fashion. + */ +void sq_flush_range(unsigned long start, unsigned int len) +{ + volatile unsigned long *sq = (unsigned long *)start; + + /* Flush the queues */ + for (len >>= 5; len--; sq += 8) + sq_flush((void *)sq); + + /* Wait for completion */ + sq = (volatile unsigned long *)start; +} + +static struct sq_mapping *__sq_alloc_mapping(unsigned long virt, unsigned long phys, unsigned long size, const char *name) +{ + struct sq_mapping *map; + + if (virt + size > SQ_ADDRMAX) + return ERR_PTR(-ENOSPC); + + map = kmalloc(sizeof(struct sq_mapping), GFP_KERNEL); + if (!map) + return ERR_PTR(-ENOMEM); + + INIT_LIST_HEAD(&map->list); + + map->sq_addr = virt; + map->addr = phys; + map->size = size; + map->name = name; + + list_add(&map->list, &sq_mapping_list); + + return map; +} + +static unsigned long __sq_get_next_addr(void) +{ + if (!list_empty(&sq_mapping_list)) { + struct list_head *pos, *tmp; + + /* + * Read one off the list head, as it will have the highest + * mapped allocation. Set the next one up right above it. + * + * This is somewhat sub-optimal, as we don't look at + * gaps between allocations or anything lower then the + * highest-level allocation. + * + * However, in the interest of performance and the general + * lack of desire to do constant list rebalancing, we don't + * worry about it. + */ + list_for_each_safe(pos, tmp, &sq_mapping_list) { + struct sq_mapping *entry; + + entry = list_entry(pos, typeof(*entry), list); + + return entry->sq_addr + entry->size; + } + } + + return P4SEG_STORE_QUE; +} + +/** + * __sq_remap - Perform a translation from the SQ to a phys addr + * + * @phys: Physical address to map store queues too. + * @virt: Associated store queue address. + * + * Maps the store queue address @virt to the physical address @phys. + */ +static struct sq_mapping *__sq_remap(struct sq_mapping *map) +{ + /* + * First check the MMU status.. + */ +#ifndef CONFIG_MMU + /* + * Without an MMU (or with it turned off), this is much more + * straightforward, as we can just load up each queue's QACR with + * the physical address appropriately masked. + */ + ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR0); + ctrl_outl(((map->addr >> 26) << 2) & 0x1c, SQ_QACR1); +#else + unsigned long flags, pteh, ptel; + pgprot_t pgprot; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + /* + * With an MMU on the other hand, things are slightly more involved. + * Namely, we have to have a direct mapping between the SQ addr and + * the associated physical address in the UTLB by way of setting up + * a virt<->phys translation by hand. We do this by simply specifying + * the SQ addr in UTLB.VPN and the associated physical address in + * UTLB.PPN. + * + * Notably, even though this is a special case translation, and some + * of the configuration bits are meaningless, we're still required + * to have a valid ASID context in PTEH. + * + * We could also probably get by without explicitly setting PTEA, but + * we do it here just for good measure. + */ + local_irq_save(flags); + + pteh = map->sq_addr; + ctrl_outl((pteh & MMU_VPN_MASK) | get_asid(), MMU_PTEH); + + ptel = map->addr & PAGE_MASK; + ctrl_outl(((ptel >> 28) & 0xe) | (ptel & 0x1), MMU_PTEA); + + pgprot = pgprot_noncached(PAGE_KERNEL); + + ptel &= _PAGE_FLAGS_HARDWARE_MASK; + ptel |= pgprot_val(pgprot); + ctrl_outl(ptel, MMU_PTEL); + + __asm__ __volatile__ ("ldtlb" : : : "memory"); + + /* + * Next, we need to map ourselves in the kernel page table, so that + * future accesses after a TLB flush will be handled when we take a + * page fault. + * + * Theoretically we could just do this directly and not worry about + * setting up the translation by hand ahead of time, but for the + * cases where we want a one-shot SQ mapping followed by a quick + * writeout before we hit the TLB flush, we do it anyways. This way + * we at least save ourselves the initial page fault overhead. + */ + pgd = pgd_offset_k(map->sq_addr); + + spin_lock(&init_mm.page_table_lock); + + pmd = pmd_alloc(&init_mm, pgd, map->sq_addr); + if (!pmd) + goto out; + + pte = pte_alloc_map(&init_mm, pmd, map->sq_addr); + if (!pte) + goto out; + if (!pte_none(*pte)) { + pte_unmap(pte); + goto out; + } + + set_pte(pte, mk_pte(phys_to_page(map->addr), pgprot)); + pte_unmap(pte); + +out: + spin_unlock(&init_mm.page_table_lock); + sq_flush((void *)pteh); + + local_irq_restore(flags); + +#endif /* CONFIG_MMU */ + + return map; +} + +/** + * sq_remap - Map a physical address through the Store Queues + * + * @phys: Physical address of mapping. + * @size: Length of mapping. + * @name: User invoking mapping. + * + * Remaps the physical address @phys through the next available store queue + * address of @size length. @name is logged at boot time as well as through + * the procfs interface. + * + * A pre-allocated and filled sq_mapping pointer is returned, and must be + * cleaned up with a call to sq_unmap() when the user is done with the + * mapping. + */ +struct sq_mapping *sq_remap(unsigned long phys, unsigned int size, const char *name) +{ + struct sq_mapping *map; + unsigned long virt; + unsigned int psz; + + phys &= PAGE_MASK; + + virt = __sq_get_next_addr(); + psz = (size + (PAGE_SIZE - 1)) / PAGE_SIZE; + map = __sq_alloc_mapping(virt, phys, size, name); + + printk("sqremap: %15s [%4d page%s] va 0x%08lx pa 0x%08lx\n", + map->name ? map->name : "???", + psz, psz == 1 ? " " : "s", + map->sq_addr, map->addr); + + return __sq_remap(map); +} + +/** + * sq_unmap - Unmap a Store Queue allocation + * + * @map: Pre-allocated Store Queue mapping. + * + * Unmaps the store queue allocation @map that was previously created by + * sq_remap(). Also frees up the pte that was previously inserted into + * the kernel page table and discards the UTLB translation. + */ +void sq_unmap(struct sq_mapping *map) +{ +#ifdef CONFIG_MMU + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + pgd = pgd_offset_k(map->sq_addr); + pmd = pmd_offset(pgd, map->sq_addr); + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + + pte = pte_offset_kernel(pmd, map->sq_addr); + if (pte_none(*pte) || pte_not_present(*pte)) + return; + + ptep_get_and_clear(pte); + + __flush_tlb_page(get_asid(), map->sq_addr & PAGE_MASK); +#endif + + list_del(&map->list); + kfree(map); +} + +/** + * sq_clear - Clear a store queue range + * + * @addr: Address to start clearing from. + * @len: Length to clear. + * + * A quick zero-fill implementation for clearing out memory that has been + * remapped through the store queues. + */ +void sq_clear(unsigned long addr, unsigned int len) +{ + int i; + + /* Clear out both queues linearly */ + for (i = 0; i < 8; i++) { + ctrl_outl(0, addr + i + 0); + ctrl_outl(0, addr + i + 8); + } + + sq_flush_range(addr, len); +} + +/** + * sq_vma_unmap - Unmap a VMA range + * + * @area: VMA containing range. + * @addr: Start of range. + * @len: Length of range. + * + * Searches the sq_mapping_list for a mapping matching the sq addr @addr, + * and subsequently frees up the entry. Further cleanup is done by generic + * code. + */ +static void sq_vma_unmap(struct vm_area_struct *area, + unsigned long addr, size_t len) +{ + struct list_head *pos, *tmp; + + list_for_each_safe(pos, tmp, &sq_mapping_list) { + struct sq_mapping *entry; + + entry = list_entry(pos, typeof(*entry), list); + + if (entry->sq_addr == addr) { + /* + * We could probably get away without doing the tlb flush + * here, as generic code should take care of most of this + * when unmapping the rest of the VMA range for us. Leave + * it in for added sanity for the time being.. + */ + __flush_tlb_page(get_asid(), entry->sq_addr & PAGE_MASK); + + list_del(&entry->list); + kfree(entry); + + return; + } + } +} + +/** + * sq_vma_sync - Sync a VMA range + * + * @area: VMA containing range. + * @start: Start of range. + * @len: Length of range. + * @flags: Additional flags. + * + * Synchronizes an sq mapped range by flushing the store queue cache for + * the duration of the mapping. + * + * Used internally for user mappings, which must use msync() to prefetch + * the store queue cache. + */ +static int sq_vma_sync(struct vm_area_struct *area, + unsigned long start, size_t len, unsigned int flags) +{ + sq_flush_range(start, len); + + return 0; +} + +static struct vm_operations_struct sq_vma_ops = { + .unmap = sq_vma_unmap, + .sync = sq_vma_sync, +}; + +/** + * sq_mmap - mmap() for /dev/cpu/sq + * + * @file: unused. + * @vma: VMA to remap. + * + * Remap the specified vma @vma through the store queues, and setup associated + * information for the new mapping. Also build up the page tables for the new + * area. + */ +static int sq_mmap(struct file *file, struct vm_area_struct *vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long size = vma->vm_end - vma->vm_start; + struct sq_mapping *map; + + /* + * We're not interested in any arbitrary virtual address that has + * been stuck in the VMA, as we already know what addresses we + * want. Save off the size, and reposition the VMA to begin at + * the next available sq address. + */ + vma->vm_start = __sq_get_next_addr(); + vma->vm_end = vma->vm_start + size; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + vma->vm_flags |= VM_IO | VM_RESERVED; + + map = __sq_alloc_mapping(vma->vm_start, offset, size, "Userspace"); + + if (io_remap_page_range(vma, map->sq_addr, map->addr, + size, vma->vm_page_prot)) + return -EAGAIN; + + vma->vm_ops = &sq_vma_ops; + + return 0; +} + +#ifdef CONFIG_PROC_FS +static int sq_mapping_read_proc(char *buf, char **start, off_t off, + int len, int *eof, void *data) +{ + struct list_head *pos; + char *p = buf; + + list_for_each_prev(pos, &sq_mapping_list) { + struct sq_mapping *entry; + + entry = list_entry(pos, typeof(*entry), list); + + p += sprintf(p, "%08lx-%08lx [%08lx]: %s\n", entry->sq_addr, + entry->sq_addr + entry->size - 1, entry->addr, + entry->name); + } + + return p - buf; +} +#endif + +static struct file_operations sq_fops = { + .owner = THIS_MODULE, + .mmap = sq_mmap, +}; + +static struct miscdevice sq_dev = { + .minor = STORE_QUEUE_MINOR, + .name = "sq", + .devfs_name = "cpu/sq", + .fops = &sq_fops, +}; + +static int __init sq_api_init(void) +{ + printk(KERN_NOTICE "sq: Registering store queue API.\n"); + +#ifdef CONFIG_PROC_FS + create_proc_read_entry("sq_mapping", 0, 0, sq_mapping_read_proc, 0); +#endif + + return misc_register(&sq_dev); +} + +static void __exit sq_api_exit(void) +{ + misc_deregister(&sq_dev); +} + +module_init(sq_api_init); +module_exit(sq_api_exit); + +MODULE_AUTHOR("Paul Mundt , M. R. Brown "); +MODULE_DESCRIPTION("Simple API for SH-4 integrated Store Queues"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(sq_remap); +EXPORT_SYMBOL(sq_unmap); +EXPORT_SYMBOL(sq_clear); +EXPORT_SYMBOL(sq_flush); +EXPORT_SYMBOL(sq_flush_range); + diff -puN -L arch/sh/kernel/dma.c arch/sh/kernel/dma.c~linus /dev/null --- 25/arch/sh/kernel/dma.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,142 +0,0 @@ -/* - * arch/sh/kernel/dma.c - * - * Copyright (C) 2000 Takashi YOSHII - * - * PC like DMA API for SuperH's DMAC. - */ - -#include -#include -#include -#include - -#include -#include - -static struct dma_info_t *dma_info[MAX_DMA_CHANNELS]; -static struct dma_info_t *autoinit_info[SH_MAX_DMA_CHANNELS] = {0}; -static spinlock_t dma_spin_lock; - -static unsigned int calc_chcr(struct dma_info_t *info) -{ - unsigned int chcr; - - chcr = ( info->mode & DMA_MODE_WRITE )? info->mode_write : info->mode_read; - if( info->mode & DMA_AUTOINIT ) - chcr |= CHCR_IE; - return chcr; -} - -static __inline__ int ts_shift(unsigned long chcr) -{ - return ((int[]){3,0,1,2,5,0,0,0})[(chcr>>4)&0x000007]; -} - -static void dma_tei(int irq, void *dev_id, struct pt_regs *regs) -{ - int chan = irq - DMTE_IRQ[0]; - struct dma_info_t *info = autoinit_info[chan]; - - if( info->mode & DMA_MODE_WRITE ) - ctrl_outl(info->mem_addr, SAR[info->chan]); - else - ctrl_outl(info->mem_addr, DAR[info->chan]); - - ctrl_outl(info->count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]); - ctrl_outl(ctrl_inl(CHCR[info->chan])&~CHCR_TE, CHCR[info->chan]); -} - -static struct irqaction irq_tei = { dma_tei, SA_INTERRUPT, 0, "dma_tei", NULL, NULL}; - -void setup_dma(unsigned int dmanr, struct dma_info_t *info) -{ - make_ipr_irq(DMTE_IRQ[info->chan], DMA_IPR_ADDR, DMA_IPR_POS, DMA_PRIORITY); - setup_irq(DMTE_IRQ[info->chan], &irq_tei); - dma_info[dmanr] = info; -} - -unsigned long claim_dma_lock(void) -{ - unsigned long flags; - spin_lock_irqsave(&dma_spin_lock, flags); - return flags; -} - -void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -void enable_dma(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - ctrl_outl(calc_chcr(info)|CHCR_DE, CHCR[info->chan]); -} - -void disable_dma(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - ctrl_outl(calc_chcr(info)&~CHCR_DE, CHCR[info->chan]); -} - -void set_dma_mode(unsigned int dmanr, char mode) -{ - struct dma_info_t *info = dma_info[dmanr]; - - info->mode = mode; - set_dma_addr(dmanr, info->mem_addr); - set_dma_count(dmanr, info->count); - autoinit_info[info->chan] = info; -} - -void set_dma_addr(unsigned int dmanr, unsigned int a) -{ - struct dma_info_t *info = dma_info[dmanr]; - unsigned long sar, dar; - - info->mem_addr = a; - sar = (info->mode & DMA_MODE_WRITE)? info->mem_addr: info->dev_addr; - dar = (info->mode & DMA_MODE_WRITE)? info->dev_addr: info->mem_addr; - ctrl_outl(sar, SAR[info->chan]); - ctrl_outl(dar, DAR[info->chan]); -} - -void set_dma_count(unsigned int dmanr, unsigned int count) -{ - struct dma_info_t *info = dma_info[dmanr]; - info->count = count; - ctrl_outl(count>>ts_shift(calc_chcr(info)), DMATCR[info->chan]); -} - -int get_dma_residue(unsigned int dmanr) -{ - struct dma_info_t *info = dma_info[dmanr]; - return ctrl_inl(DMATCR[info->chan])<preempt_count + tst r0, r0 + bf restore_all +need_resched: + mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags + tst #_TIF_NEED_RESCHED, r0 ! need_resched set? + bt restore_all + + stc sr, r0 ! interrupts disabled? + tst #0xf0, r0 + bf restore_all + + mov.l 1f, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + + STI() + mov.l 2f, r0 + jsr @r0 + nop + mov #0, r0 + mov.l r0, @(TI_PRE_COUNT,r8) + CLI() + + bra need_resched + nop + + .align 2 +1: .long PREEMPT_ACTIVE +2: .long schedule +#endif + ENTRY(resume_userspace) ! r8: current_thread_info - /* CLI */ - stc sr, r0 - or #0xf0, r0 - ldc r0, sr - ! + CLI() mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 bt/s restore_all @@ -377,10 +429,7 @@ work_resched: mov.l 1f, r1 jsr @r1 ! schedule nop - /* CLI */ - stc sr, r0 - or #0xf0, r0 - ldc r0, sr + CLI() ! mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_WORK_MASK, r0 @@ -469,7 +518,7 @@ ret_from_fork: .align 2 1: .long schedule_tail ! -system_call: +ENTRY(system_call) mov.l 1f, r9 mov.l @r9, r8 ! Read from TRA (Trap Address) Register ! @@ -510,10 +559,7 @@ syscall_call: mov.l r0, @(OFF_R0,r15) ! save the return value ! syscall_exit: - /* CLI */ - stc sr, r0 - or #0xf0, r0 - ldc r0, sr + CLI() ! GET_THREAD_INFO(r8) mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags @@ -550,6 +596,40 @@ restore_all: lds.l @r15+, macl add #4, r15 ! Skip syscall number ! +#ifdef CONFIG_SH_DSP + mov.l @r15+, k0 ! DSP mode marker + mov.l 5f, k1 + cmp/eq k0, k1 ! Do we have a DSP stack frame? + bf skip_restore + + stc sr, k0 ! Enable CPU DSP mode + or k1, k0 ! (within kernel it may be disabled) + ldc k0, sr + mov r2, k0 ! Backup r2 + + ! Restore DSP registers from stack + mov r15, r2 + movs.l @r2+, a1 + movs.l @r2+, a0g + movs.l @r2+, a1g + movs.l @r2+, m0 + movs.l @r2+, m1 + mov r2, r15 + + lds.l @r15+, a0 + lds.l @r15+, x0 + lds.l @r15+, x1 + lds.l @r15+, y0 + lds.l @r15+, y1 + lds.l @r15+, dsr + ldc.l @r15+, rs + ldc.l @r15+, re + ldc.l @r15+, mod + + mov k0, r2 ! Restore r2 +skip_restore: +#endif + ! ! Calculate new SR value mov k3, k2 ! original SR value mov.l 8f, k1 @@ -576,6 +656,7 @@ restore_all: mov #0, k1 mov.b k1, @k0 #endif + mov.l @r15+, k2 ! restore EXPEVT mov k4, r15 rte nop @@ -585,14 +666,12 @@ restore_all: 2: .long NR_syscalls 3: .long sys_call_table 4: .long do_syscall_trace +5: .long 0x00001000 ! DSP 7: .long 0x30000000 8: .long 0x00008000 ! FD 9: .long 0xffff7f0f ! ~(IMASK+FD) __INV_IMASK: .long 0xffffff0f ! ~(IMASK) -#if defined(CONFIG_KGDB_NMI) -10: .long in_nmi -#endif ! Exception Vector Base ! @@ -637,7 +716,7 @@ interrupt: nop .align 2 5: .long NMI_VEC -6: .long SYMBOL_NAME(in_nmi) +6: .long in_nmi 0: #endif /* defined(CONFIG_KGDB_NMI) */ bra handle_exception @@ -669,7 +748,50 @@ handle_exception: ! 1: mov #-1, k4 mov.l 2f, k1 + ! +#ifdef CONFIG_SH_DSP + mov.l r2, @-r15 ! Save r2, we need another reg + stc sr, k4 + mov.l 1f, r2 + tst r2, k4 ! Check if in DSP mode + mov.l @r15+, r2 ! Restore r2 now + bt/s skip_save + mov #0, k4 ! Set marker for no stack frame + + mov r2, k4 ! Backup r2 (in k4) for later + + ! Save DSP registers on stack + stc.l mod, @-r15 + stc.l re, @-r15 + stc.l rs, @-r15 + sts.l dsr, @-r15 + sts.l y1, @-r15 + sts.l y0, @-r15 + sts.l x1, @-r15 + sts.l x0, @-r15 + sts.l a0, @-r15 + + ! GAS is broken, does not generate correct "movs.l Ds,@-As" instr. + + ! FIXME: Make sure that this is still the case with newer toolchains, + ! as we're not at all interested in supporting ancient toolchains at + ! this point. -- PFM. + + mov r15, r2 + .word 0xf653 ! movs.l a1, @-r2 + .word 0xf6f3 ! movs.l a0g, @-r2 + .word 0xf6d3 ! movs.l a1g, @-r2 + .word 0xf6c3 ! movs.l m0, @-r2 + .word 0xf6e3 ! movs.l m1, @-r2 + mov r2, r15 + + mov k4, r2 ! Restore r2 + mov.l 1f, k4 ! Force DSP stack frame +skip_save: + mov.l k4, @-r15 ! Push DSP mode marker onto stack +#endif ! Save the user registers on the stack. + mov.l k2, @-r15 ! EXPEVT mov.l k4, @-r15 ! set TRA (default: -1) ! sts.l macl, @-r15 @@ -715,264 +837,17 @@ handle_exception: nop .align 2 +1: .long 0x00001000 ! DSP=1 2: .long 0x000000f0 ! FD=0, IMASK=15 3: .long 0xcfffffff ! RB=0, BL=0 4: .long exception_handling_table .align 2 -none: +ENTRY(exception_none) rts nop -.data -ENTRY(exception_handling_table) - .long error - .long error -#if defined(CONFIG_MMU) - .long tlb_miss_load - .long tlb_miss_store - .long initial_page_write - .long tlb_protection_violation_load - .long tlb_protection_violation_store - .long address_error_load - .long address_error_store -#else - .long error ! tlb miss load - .long error ! tlb miss store - .long error ! initial page write - .long error ! tlb prot violation load - .long error ! tlb prot violation store - .long error ! address error load - .long error ! address error store -#endif - -#if defined(CONFIG_CPU_SH4) - .long do_fpu_error -#else - .long error ! fpu_exception -#endif - .long error - .long system_call ! Unconditional Trap - .long error ! reserved_instruction (filled by trap_init) - .long error ! illegal_slot_instruction (filled by trap_init) -ENTRY(nmi_slot) -#if defined (CONFIG_KGDB_NMI) - .long debug_enter ! Allow trap to debugger -#else - .long none ! Not implemented yet -#endif -ENTRY(user_break_point_trap) - .long break_point_trap -ENTRY(interrupt_table) - ! external hardware - .long do_IRQ ! 0000 - .long do_IRQ ! 0001 - .long do_IRQ ! 0010 - .long do_IRQ ! 0011 - .long do_IRQ ! 0100 - .long do_IRQ ! 0101 - .long do_IRQ ! 0110 - .long do_IRQ ! 0111 - .long do_IRQ ! 1000 - .long do_IRQ ! 1001 - .long do_IRQ ! 1010 - .long do_IRQ ! 1011 - .long do_IRQ ! 1100 - .long do_IRQ ! 1101 - .long do_IRQ ! 1110 - .long error - ! Internal hardware - .long do_IRQ ! TMU0 tuni0 - .long do_IRQ ! TMU1 tuni1 - .long do_IRQ ! TMU2 tuni2 - .long do_IRQ ! ticpi2 - .long do_IRQ ! RTC ati - .long do_IRQ ! pri - .long do_IRQ ! cui - .long do_IRQ ! SCI eri - .long do_IRQ ! rxi - .long do_IRQ ! txi - .long do_IRQ ! tei - .long do_IRQ ! WDT iti - .long do_IRQ ! REF rcmi - .long do_IRQ ! rovi - .long do_IRQ - .long do_IRQ -#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709) - .long do_IRQ ! 32 IRQ irq0 - .long do_IRQ ! 33 irq1 - .long do_IRQ ! 34 irq2 - .long do_IRQ ! 35 irq3 - .long do_IRQ ! 36 irq4 - .long do_IRQ ! 37 irq5 - .long do_IRQ ! 38 - .long do_IRQ ! 39 - .long do_IRQ ! 40 PINT pint0-7 - .long do_IRQ ! 41 pint8-15 - .long do_IRQ ! 42 - .long do_IRQ ! 43 - .long do_IRQ ! 44 - .long do_IRQ ! 45 - .long do_IRQ ! 46 - .long do_IRQ ! 47 - .long do_IRQ ! 48 DMAC dei0 - .long do_IRQ ! 49 dei1 - .long do_IRQ ! 50 dei2 - .long do_IRQ ! 51 dei3 - .long do_IRQ ! 52 IrDA eri1 - .long do_IRQ ! 53 rxi1 - .long do_IRQ ! 54 bri1 - .long do_IRQ ! 55 txi1 - .long do_IRQ ! 56 SCIF eri2 - .long do_IRQ ! 57 rxi2 - .long do_IRQ ! 58 bri2 - .long do_IRQ ! 59 txi2 - .long do_IRQ ! 60 ADC adi -#if defined(CONFIG_CPU_SUBTYPE_SH7707) - .long do_IRQ ! 61 LCDC lcdi - .long do_IRQ ! 62 PCC pcc0i - .long do_IRQ ! 63 pcc1i -#endif -#elif defined(CONFIG_CPU_SH4) - .long do_IRQ ! 32 Hitachi UDI - .long do_IRQ ! 33 GPIO - .long do_IRQ ! 34 DMAC dmte0 - .long do_IRQ ! 35 dmte1 - .long do_IRQ ! 36 dmte2 - .long do_IRQ ! 37 dmte3 - .long do_IRQ ! 38 dmae - .long error ! 39 - .long do_IRQ ! 40 SCIF eri - .long do_IRQ ! 41 rxi - .long do_IRQ ! 42 bri - .long do_IRQ ! 43 txi - .long error ! 44 - .long error ! 45 - .long error ! 46 - .long error ! 47 - .long do_fpu_state_restore ! 48 - .long do_fpu_state_restore ! 49 -#endif -#if defined(CONFIG_CPU_SUBTYPE_SH7751) - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long error - .long do_IRQ ! PCI serr - .long do_IRQ ! dma3 - .long do_IRQ ! dma2 - .long do_IRQ ! dma1 - .long do_IRQ ! dma0 - .long do_IRQ ! pwon - .long do_IRQ ! pwdwn - .long do_IRQ ! err -#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1) - .long error ! 50 0x840 - .long error ! 51 0x860 - .long error ! 52 0x880 - .long error ! 53 0x8a0 - .long error ! 54 0x8c0 - .long error ! 55 0x8e0 - .long error ! 56 0x900 - .long error ! 57 0x920 - .long error ! 58 0x940 - .long error ! 59 0x960 - .long error ! 60 0x980 - .long error ! 61 0x9a0 - .long error ! 62 0x9c0 - .long error ! 63 0x9e0 - .long do_IRQ ! 64 0xa00 PCI serr - .long do_IRQ ! 65 0xa20 err - .long do_IRQ ! 66 0xa40 ad - .long do_IRQ ! 67 0xa60 pwr_dwn - .long error ! 68 0xa80 - .long error ! 69 0xaa0 - .long error ! 70 0xac0 - .long error ! 71 0xae0 - .long do_IRQ ! 72 0xb00 DMA INT0 - .long do_IRQ ! 73 0xb20 INT1 - .long do_IRQ ! 74 0xb40 INT2 - .long do_IRQ ! 75 0xb60 INT3 - .long do_IRQ ! 76 0xb80 INT4 - .long error ! 77 0xba0 - .long do_IRQ ! 78 0xbc0 DMA ERR - .long error ! 79 0xbe0 - .long do_IRQ ! 80 0xc00 PIO0 - .long do_IRQ ! 81 0xc20 PIO1 - .long do_IRQ ! 82 0xc40 PIO2 - .long error ! 83 0xc60 - .long error ! 84 0xc80 - .long error ! 85 0xca0 - .long error ! 86 0xcc0 - .long error ! 87 0xce0 - .long error ! 88 0xd00 - .long error ! 89 0xd20 - .long error ! 90 0xd40 - .long error ! 91 0xd60 - .long error ! 92 0xd80 - .long error ! 93 0xda0 - .long error ! 94 0xdc0 - .long error ! 95 0xde0 - .long error ! 96 0xe00 - .long error ! 97 0xe20 - .long error ! 98 0xe40 - .long error ! 99 0xe60 - .long error ! 100 0xe80 - .long error ! 101 0xea0 - .long error ! 102 0xec0 - .long error ! 103 0xee0 - .long error ! 104 0xf00 - .long error ! 105 0xf20 - .long error ! 106 0xf40 - .long error ! 107 0xf60 - .long error ! 108 0xf80 - .long error ! 109 0xfa0 - .long error ! 110 0xfc0 - .long error ! 111 0xfe0 - .long do_IRQ ! 112 0x1000 Mailbox - .long error ! 113 0x1020 - .long error ! 114 0x1040 - .long error ! 115 0x1060 - .long error ! 116 0x1080 - .long error ! 117 0x10a0 - .long error ! 118 0x10c0 - .long error ! 119 0x10e0 - .long error ! 120 0x1100 - .long error ! 121 0x1120 - .long error ! 122 0x1140 - .long error ! 123 0x1160 - .long error ! 124 0x1180 - .long error ! 125 0x11a0 - .long error ! 126 0x11c0 - .long error ! 127 0x11e0 - .long error ! 128 0x1200 - .long error ! 129 0x1220 - .long error ! 130 0x1240 - .long error ! 131 0x1260 - .long error ! 132 0x1280 - .long error ! 133 0x12a0 - .long error ! 134 0x12c0 - .long error ! 135 0x12e0 - .long error ! 136 0x1300 - .long error ! 137 0x1320 - .long error ! 138 0x1340 - .long error ! 139 0x1360 - .long do_IRQ ! 140 0x1380 EMPI INV_ADDR - .long error ! 141 0x13a0 - .long error ! 142 0x13c0 - .long error ! 143 0x13e0 -#endif - + .data ENTRY(sys_call_table) .long sys_ni_syscall /* 0 - old "setup()" system call*/ .long sys_exit @@ -1242,6 +1117,12 @@ ENTRY(sys_call_table) .long sys_clock_gettime /* 265 */ .long sys_clock_getres .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 270 */ + .long sys_utimes + .long sys_fadvise64_64_wrapper + .long sys_ni_syscall /* Reserved for vserver */ .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall diff -puN -L arch/sh/kernel/fpu.c arch/sh/kernel/fpu.c~linus /dev/null --- 25/arch/sh/kernel/fpu.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,314 +0,0 @@ -/* $Id: fpu.c,v 1.29 2000/03/22 13:42:10 gniibe Exp $ - * - * linux/arch/sh/kernel/fpu.c - * - * Save/restore floating point context for signal handlers. - * - * 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) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - * FIXME! These routines can be optimized in big endian case. - */ - -#include -#include -#include -#include - -/* - * Save FPU registers onto task structure. - * Assume called with FPU enabled (SR.FD=0). - */ -void -save_fpu(struct task_struct *tsk) -{ - asm volatile("sts.l fpul, @-%0\n\t" - "sts.l fpscr, @-%0\n\t" - "lds %1, fpscr\n\t" - "frchg\n\t" - "fmov.s fr15, @-%0\n\t" - "fmov.s fr14, @-%0\n\t" - "fmov.s fr13, @-%0\n\t" - "fmov.s fr12, @-%0\n\t" - "fmov.s fr11, @-%0\n\t" - "fmov.s fr10, @-%0\n\t" - "fmov.s fr9, @-%0\n\t" - "fmov.s fr8, @-%0\n\t" - "fmov.s fr7, @-%0\n\t" - "fmov.s fr6, @-%0\n\t" - "fmov.s fr5, @-%0\n\t" - "fmov.s fr4, @-%0\n\t" - "fmov.s fr3, @-%0\n\t" - "fmov.s fr2, @-%0\n\t" - "fmov.s fr1, @-%0\n\t" - "fmov.s fr0, @-%0\n\t" - "frchg\n\t" - "fmov.s fr15, @-%0\n\t" - "fmov.s fr14, @-%0\n\t" - "fmov.s fr13, @-%0\n\t" - "fmov.s fr12, @-%0\n\t" - "fmov.s fr11, @-%0\n\t" - "fmov.s fr10, @-%0\n\t" - "fmov.s fr9, @-%0\n\t" - "fmov.s fr8, @-%0\n\t" - "fmov.s fr7, @-%0\n\t" - "fmov.s fr6, @-%0\n\t" - "fmov.s fr5, @-%0\n\t" - "fmov.s fr4, @-%0\n\t" - "fmov.s fr3, @-%0\n\t" - "fmov.s fr2, @-%0\n\t" - "fmov.s fr1, @-%0\n\t" - "fmov.s fr0, @-%0" - : /* no output */ - : "r" ((char *)(&tsk->thread.fpu.hard.status)), - "r" (FPSCR_INIT) - : "memory"); - - tsk->flags &= ~PF_USEDFPU; - release_fpu(); -} - -static void -restore_fpu(struct task_struct *tsk) -{ - asm volatile("lds %1, fpscr\n\t" - "fmov.s @%0+, fr0\n\t" - "fmov.s @%0+, fr1\n\t" - "fmov.s @%0+, fr2\n\t" - "fmov.s @%0+, fr3\n\t" - "fmov.s @%0+, fr4\n\t" - "fmov.s @%0+, fr5\n\t" - "fmov.s @%0+, fr6\n\t" - "fmov.s @%0+, fr7\n\t" - "fmov.s @%0+, fr8\n\t" - "fmov.s @%0+, fr9\n\t" - "fmov.s @%0+, fr10\n\t" - "fmov.s @%0+, fr11\n\t" - "fmov.s @%0+, fr12\n\t" - "fmov.s @%0+, fr13\n\t" - "fmov.s @%0+, fr14\n\t" - "fmov.s @%0+, fr15\n\t" - "frchg\n\t" - "fmov.s @%0+, fr0\n\t" - "fmov.s @%0+, fr1\n\t" - "fmov.s @%0+, fr2\n\t" - "fmov.s @%0+, fr3\n\t" - "fmov.s @%0+, fr4\n\t" - "fmov.s @%0+, fr5\n\t" - "fmov.s @%0+, fr6\n\t" - "fmov.s @%0+, fr7\n\t" - "fmov.s @%0+, fr8\n\t" - "fmov.s @%0+, fr9\n\t" - "fmov.s @%0+, fr10\n\t" - "fmov.s @%0+, fr11\n\t" - "fmov.s @%0+, fr12\n\t" - "fmov.s @%0+, fr13\n\t" - "fmov.s @%0+, fr14\n\t" - "fmov.s @%0+, fr15\n\t" - "frchg\n\t" - "lds.l @%0+, fpscr\n\t" - "lds.l @%0+, fpul\n\t" - : /* no output */ - : "r" (&tsk->thread.fpu), "r" (FPSCR_INIT) - : "memory"); -} - -/* - * Load the FPU with signalling NANS. This bit pattern we're using - * has the property that no matter whether considered as single or as - * double precission represents signaling NANS. - */ - -static void -fpu_init(void) -{ - asm volatile("lds %0, fpul\n\t" - "lds %1, fpscr\n\t" - "fsts fpul, fr0\n\t" - "fsts fpul, fr1\n\t" - "fsts fpul, fr2\n\t" - "fsts fpul, fr3\n\t" - "fsts fpul, fr4\n\t" - "fsts fpul, fr5\n\t" - "fsts fpul, fr6\n\t" - "fsts fpul, fr7\n\t" - "fsts fpul, fr8\n\t" - "fsts fpul, fr9\n\t" - "fsts fpul, fr10\n\t" - "fsts fpul, fr11\n\t" - "fsts fpul, fr12\n\t" - "fsts fpul, fr13\n\t" - "fsts fpul, fr14\n\t" - "fsts fpul, fr15\n\t" - "frchg\n\t" - "fsts fpul, fr0\n\t" - "fsts fpul, fr1\n\t" - "fsts fpul, fr2\n\t" - "fsts fpul, fr3\n\t" - "fsts fpul, fr4\n\t" - "fsts fpul, fr5\n\t" - "fsts fpul, fr6\n\t" - "fsts fpul, fr7\n\t" - "fsts fpul, fr8\n\t" - "fsts fpul, fr9\n\t" - "fsts fpul, fr10\n\t" - "fsts fpul, fr11\n\t" - "fsts fpul, fr12\n\t" - "fsts fpul, fr13\n\t" - "fsts fpul, fr14\n\t" - "fsts fpul, fr15\n\t" - "frchg" - : /* no output */ - : "r" (0), "r" (FPSCR_INIT)); -} - -/** - * denormal_to_double - Given denormalized float number, - * store double float - * - * @fpu: Pointer to sh_fpu_hard structure - * @n: Index to FP register - */ -static void -denormal_to_double (struct sh_fpu_hard_struct *fpu, int n) -{ - unsigned long du, dl; - unsigned long x = fpu->fpul; - int exp = 1023 - 126; - - if (x != 0 && (x & 0x7f800000) == 0) { - du = (x & 0x80000000); - while ((x & 0x00800000) == 0) { - x <<= 1; - exp--; - } - x &= 0x007fffff; - du |= (exp << 20) | (x >> 3); - dl = x << 29; - - fpu->fp_regs[n] = du; - fpu->fp_regs[n+1] = dl; - } -} - -/** - * ieee_fpe_handler - Handle denormalized number exception - * - * @regs: Pointer to register structure - * - * Returns 1 when it's handled (should not cause exception). - */ -static int -ieee_fpe_handler (struct pt_regs *regs) -{ - unsigned short insn = *(unsigned short *) regs->pc; - unsigned short finsn; - unsigned long nextpc; - int nib[4] = { - (insn >> 12) & 0xf, - (insn >> 8) & 0xf, - (insn >> 4) & 0xf, - insn & 0xf}; - - if (nib[0] == 0xb || - (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ - regs->pr = regs->pc + 4; - - if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ - nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ - if (regs->sr & 1) - nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); - else - nextpc = regs->pc + 4; - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ - if (regs->sr & 1) - nextpc = regs->pc + 4; - else - nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x4 && nib[3] == 0xb && - (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ - nextpc = regs->regs[nib[1]]; - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x0 && nib[3] == 0x3 && - (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ - nextpc = regs->pc + 4 + regs->regs[nib[1]]; - finsn = *(unsigned short *) (regs->pc + 2); - } else if (insn == 0x000b) { /* rts */ - nextpc = regs->pr; - finsn = *(unsigned short *) (regs->pc + 2); - } else { - nextpc = regs->pc + 2; - finsn = insn; - } - - if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ - struct task_struct *tsk = current; - - save_fpu(tsk); - if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) { - /* FPU error */ - denormal_to_double (&tsk->thread.fpu.hard, - (finsn >> 8) & 0xf); - tsk->thread.fpu.hard.fpscr &= - ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); - grab_fpu(); - restore_fpu(tsk); - tsk->flags |= PF_USEDFPU; - } else { - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; - force_sig(SIGFPE, tsk); - } - - regs->pc = nextpc; - return 1; - } - - return 0; -} - -asmlinkage void -do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs regs) -{ - struct task_struct *tsk = current; - - if (ieee_fpe_handler (®s)) - return; - - regs.pc += 2; - save_fpu(tsk); - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; - force_sig(SIGFPE, tsk); -} - -asmlinkage void -do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs regs) -{ - struct task_struct *tsk = current; - - grab_fpu(); - if (!user_mode(®s)) { - printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); - return; - } - - if (tsk->used_math) { - /* Using the FPU again. */ - restore_fpu(tsk); - } else { - /* First time FPU user. */ - fpu_init(); - tsk->used_math = 1; - } - tsk->flags |= PF_USEDFPU; -} diff -puN arch/sh/kernel/head.S~linus arch/sh/kernel/head.S --- 25/arch/sh/kernel/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: head.S,v 1.6 2003/05/04 19:29:53 lethal Exp $ +/* $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $ * * arch/sh/kernel/head.S * @@ -50,7 +50,7 @@ ENTRY(_stext) sub r1, r0 ! ldc r0, r7_bank ! ... and initial thread_info ! - ! Enable cache + ! Additional CPU initialization mov.l 6f, r0 jsr @r0 nop @@ -73,4 +73,4 @@ ENTRY(_stext) 3: .long __bss_start 4: .long _end 5: .long start_kernel -6: .long sh_cache_init +6: .long sh_cpu_init diff -puN arch/sh/kernel/io.c~linus arch/sh/kernel/io.c --- 25/arch/sh/kernel/io.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/io.c 2004-01-19 22:17:21.000000000 -0800 @@ -10,186 +10,6 @@ #include #include -unsigned char _inb(unsigned long port) -{ - return __inb(port); -} -EXPORT_SYMBOL(_inb); - -unsigned short _inw(unsigned long port) -{ - return __inw(port); -} -EXPORT_SYMBOL(_inw); - -unsigned int _inl(unsigned long port) -{ - return __inl(port); -} -EXPORT_SYMBOL(_inl); - -void _outb(unsigned char b, unsigned long port) -{ - __outb(b, port); -} -EXPORT_SYMBOL(_outb); - -void _outw(unsigned short b, unsigned long port) -{ - __outw(b, port); -} -EXPORT_SYMBOL(_outw); - - -void _outl(unsigned int b, unsigned long port) -{ - __outl(b, port); -} -EXPORT_SYMBOL(_outl); - - -unsigned char _inb_p(unsigned long port) -{ - return __inb_p(port); -} -EXPORT_SYMBOL(_inb_p); - -unsigned short _inw_p(unsigned long port) -{ - return __inw_p(port); -} -EXPORT_SYMBOL(_inw_p); - - -void _outb_p(unsigned char b, unsigned long port) -{ - __outb_p(b, port); -} -EXPORT_SYMBOL(_outb_p); - -void _outw_p(unsigned short b, unsigned long port) -{ - __outw_p(b, port); -} -EXPORT_SYMBOL(_outw_p); - -void _insb(unsigned long port, void *buffer, unsigned long count) -{ - return __insb(port, buffer, count); -} -EXPORT_SYMBOL(_insb); - -void _insw(unsigned long port, void *buffer, unsigned long count) -{ - __insw(port, buffer, count); -} -EXPORT_SYMBOL(_insw); - -void _insl(unsigned long port, void *buffer, unsigned long count) -{ - __insl(port, buffer, count); -} -EXPORT_SYMBOL(_insl); - -void _outsb(unsigned long port, const void *buffer, unsigned long count) -{ - __outsb(port, buffer, count); -} -EXPORT_SYMBOL(_outsb); - -void _outsw(unsigned long port, const void *buffer, unsigned long count) -{ - __outsw(port, buffer, count); -} -EXPORT_SYMBOL(_outsw); - -void _outsl(unsigned long port, const void *buffer, unsigned long count) -{ - __outsl(port, buffer, count); - -} -EXPORT_SYMBOL(_outsl); - -unsigned char ___raw_readb(unsigned long addr) -{ - return __readb(addr); -} -EXPORT_SYMBOL(___raw_readb); - -unsigned short ___raw_readw(unsigned long addr) -{ - return __readw(addr); -} -EXPORT_SYMBOL(___raw_readw); - -unsigned int ___raw_readl(unsigned long addr) -{ - return __readl(addr); -} -EXPORT_SYMBOL(___raw_readl); - -unsigned char _readb(unsigned long addr) -{ - unsigned long r = __readb(addr); - mb(); - return r; -} -EXPORT_SYMBOL(_readb); - -unsigned short _readw(unsigned long addr) -{ - unsigned long r = __readw(addr); - mb(); - return r; -} -EXPORT_SYMBOL(_readw); - -unsigned int _readl(unsigned long addr) -{ - unsigned long r = __readl(addr); - mb(); - return r; -} -EXPORT_SYMBOL(_readl); - -void ___raw_writeb(unsigned char b, unsigned long addr) -{ - __writeb(b, addr); -} - -void ___raw_writew(unsigned short b, unsigned long addr) -{ - __writew(b, addr); -} -EXPORT_SYMBOL(___raw_writew); - -void ___raw_writel(unsigned int b, unsigned long addr) -{ - __writel(b, addr); -} -EXPORT_SYMBOL(___raw_writel); - -void _writeb(unsigned char b, unsigned long addr) -{ - __writeb(b, addr); - mb(); -} -EXPORT_SYMBOL(_writeb); - -void _writew(unsigned short b, unsigned long addr) -{ - __writew(b, addr); - mb(); -} -EXPORT_SYMBOL(_writew); - -void _writel(unsigned int b, unsigned long addr) -{ - __writel(b, addr); - mb(); -} -EXPORT_SYMBOL(_writel); - /* * Copy data from IO memory space to "real" memory space. * This needs to be optimized. @@ -230,3 +50,8 @@ void memset_io(unsigned long dst, int c dst++; } } + +EXPORT_SYMBOL(memcpy_fromio); +EXPORT_SYMBOL(memcpy_toio); +EXPORT_SYMBOL(memset_io); + diff -puN arch/sh/kernel/irq.c~linus arch/sh/kernel/irq.c --- 25/arch/sh/kernel/irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.12 2003/06/28 15:34:55 lethal Exp $ +/* $Id: irq.c,v 1.19 2004/01/10 01:25:32 lethal Exp $ * * linux/arch/sh/kernel/irq.c * @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { [0 ... NR_IRQS-1] = { .handler = &no_irq_type, + .lock = SPIN_LOCK_UNLOCKED } }; @@ -150,23 +152,88 @@ int handle_IRQ_event(unsigned int irq, s add_interrupt_randomness(irq); local_irq_disable(); + return retval; +} - if (retval != 1) { - static int count = 100; +static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + struct irqaction *action; - if (count) { - count--; + if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + printk(KERN_ERR "irq event %d: bogus return value %x\n", + irq, action_ret); + } else { + printk(KERN_ERR "irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk(KERN_ERR "handlers:\n"); + action = desc->action; + do { + printk(KERN_ERR "[<%p>]", action->handler); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); +} - if (retval) { - printk("irq event %d: bogus retval mask %x\n", - irq, retval); - } else { - printk("irq %d: nobody cared\n", irq); - } - } +static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + static int count = 100; + + if (count) { + count--; + __report_bad_irq(irq, desc, action_ret); + } +} + +static int noirqdebug; + +static int __init noirqdebug_setup(char *str) +{ + noirqdebug = 1; + printk("IRQ lockup detection disabled\n"); + return 1; +} + +__setup("noirqdebug", noirqdebug_setup); + +/* + * If 99,900 of the previous 100,000 interrupts have not been handled then + * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to + * turn the IRQ off. + * + * (The other 100-of-100,000 interrupts may have been a correctly-functioning + * device sharing an IRQ with the failing one) + * + * Called under desc->lock + */ +static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + if (action_ret != IRQ_HANDLED) { + desc->irqs_unhandled++; + if (action_ret != IRQ_NONE) + report_bad_irq(irq, desc, action_ret); } - return status; + desc->irq_count++; + if (desc->irq_count < 100000) + return; + + desc->irq_count = 0; + if (desc->irqs_unhandled > 99900) { + /* + * The interrupt is stuck + */ + __report_bad_irq(irq, desc, action_ret); + /* + * Now kill the IRQ + */ + printk(KERN_EMERG "Disabling IRQ #%d\n", irq); + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + desc->irqs_unhandled = 0; } /* @@ -194,8 +261,10 @@ inline void disable_irq_nosync(unsigned */ void disable_irq(unsigned int irq) { + irq_desc_t *desc = irq_desc + irq; disable_irq_nosync(irq); - synchronize_irq(irq); + if (desc->action) + synchronize_irq(irq); } void enable_irq(unsigned int irq) @@ -206,7 +275,7 @@ void enable_irq(unsigned int irq) spin_lock_irqsave(&desc->lock, flags); switch (desc->depth) { case 1: { - unsigned int status = desc->status & ~IRQ_DISABLED; + unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS); desc->status = status; if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { desc->status = status | IRQ_REPLAY; @@ -243,7 +312,6 @@ asmlinkage int do_IRQ(unsigned long r4, * handled by some other CPU. (or is disabled) */ int irq; - int cpu = smp_processor_id(); irq_desc_t *desc; struct irqaction * action; unsigned int status; @@ -259,7 +327,7 @@ asmlinkage int do_IRQ(unsigned long r4, :"=z" (irq)); irq = irq_demux(irq); - kstat_cpu(cpu).irqs[irq]++; + kstat_this_cpu.irqs[irq]++; desc = irq_desc + irq; spin_lock(&desc->lock); desc->handler->ack(irq); @@ -302,10 +370,13 @@ asmlinkage int do_IRQ(unsigned long r4, * SMP environment. */ for (;;) { + irqreturn_t action_ret; + spin_unlock(&desc->lock); - handle_IRQ_event(irq, ®s, action); + action_ret = handle_IRQ_event(irq, ®s, action); spin_lock(&desc->lock); - + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; @@ -454,16 +525,17 @@ unsigned long probe_irq_on(void) * Wait for spurious interrupts to trigger */ for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ synchronize_irq(); + /* about 100ms delay */ barrier(); /* * Now filter out any obviously spurious interrupts */ val = 0; for (i=0; ilock); status = desc->status; diff -puN arch/sh/kernel/kgdb_stub.c~linus arch/sh/kernel/kgdb_stub.c --- 25/arch/sh/kernel/kgdb_stub.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/kgdb_stub.c 2004-01-19 22:17:21.000000000 -0800 @@ -778,7 +778,7 @@ static short *get_step_address(void) else addr = trap_registers.pc + 2; - flush_icache_range(addr, addr + 2); + kgdb_flush_icache_range(addr, addr + 2); return (short *) addr; } @@ -801,7 +801,7 @@ static void do_single_step(void) *addr = STEP_OPCODE; /* Flush and return */ - flush_icache_range((long) addr, (long) addr + 2); + kgdb_flush_icache_range((long) addr, (long) addr + 2); return; } @@ -812,7 +812,7 @@ static void undo_single_step(void) /* Use stepped_address in case we stopped elsewhere */ if (stepped_opcode != 0) { *(short*)stepped_address = stepped_opcode; - flush_icache_range(stepped_address, stepped_address + 2); + kgdb_flush_icache_range(stepped_address, stepped_address + 2); } stepped_opcode = 0; } @@ -924,7 +924,7 @@ static void write_mem_msg(int binary) ebin_to_mem(ptr, (char*)addr, length); else hex_to_mem(ptr, (char*)addr, length); - flush_icache_range(addr, addr + length); + kgdb_flush_icache_range(addr, addr + length); ptr = 0; send_ok_msg(); } diff -puN arch/sh/kernel/Makefile~linus arch/sh/kernel/Makefile --- 25/arch/sh/kernel/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -17,11 +17,5 @@ obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kg obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o obj-$(CONFIG_MODULES) += module.o -ifneq ($(CONFIG_SH_DREAMCAST),y) -obj-$(CONFIG_PCI) += pci-dma.o -endif -obj-$(CONFIG_PCI) += pci.o -obj-$(CONFIG_PCI_AUTO) += pci_auto.o - USE_STANDARD_AS_RULE := true diff -puN arch/sh/kernel/module.c~linus arch/sh/kernel/module.c --- 25/arch/sh/kernel/module.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/module.c 2004-01-19 22:17:21.000000000 -0800 @@ -138,3 +138,7 @@ int module_finalize(const Elf_Ehdr *hdr, { return 0; } + +void module_arch_cleanup(struct module *mod) +{ +} diff -puN -L arch/sh/kernel/pci_auto.c arch/sh/kernel/pci_auto.c~linus /dev/null --- 25/arch/sh/kernel/pci_auto.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,502 +0,0 @@ -/* - * PCI autoconfiguration library - * - * Author: Matt Porter - * - * Copyright 2000, 2001 MontaVista Software Inc. - * Copyright 2001 Bradley D. LaRonde - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -/* - * Modified for MIPS by Jun Sun, jsun@mvista.com - * - * . Simplify the interface between pci_auto and the rest: a single function. - * . Assign resources from low address to upper address. - * . change most int to u32. - * - * Further modified to include it as mips generic code, ppopov@mvista.com. - * - * 2001-10-26 Bradley D. LaRonde - * - Add a top_bus argument to the "early config" functions so that - * they can set a fake parent bus pointer to convince the underlying - * pci ops to use type 1 configuration for sub busses. - * - Set bridge base and limit registers correctly. - * - Align io and memory base properly before and after bridge setup. - * - Don't fall through to pci_setup_bars for bridge. - * - Reformat the debug output to look more like lspci's output. - */ - -#include -#include -#include -#include - -#define DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* - * These functions are used early on before PCI scanning is done - * and all of the pci_dev and pci_bus structures have been created. - */ -static struct pci_dev *fake_pci_dev(struct pci_channel *hose, - int top_bus, int busnr, int devfn) -{ - static struct pci_dev dev; - static struct pci_bus bus; - - dev.bus = &bus; - dev.sysdata = hose; - dev.devfn = devfn; - bus.number = busnr; - bus.ops = hose->pci_ops; - - if(busnr != top_bus) - /* Fake a parent bus structure. */ - bus.parent = &bus; - else - bus.parent = NULL; - - return &dev; -} - -#define EARLY_PCI_OP(rw, size, type) \ -int early_##rw##_config_##size(struct pci_channel *hose, \ - int top_bus, int bus, int devfn, int offset, type value) \ -{ \ - return pci_##rw##_config_##size( \ - fake_pci_dev(hose, top_bus, bus, devfn), \ - offset, value); \ -} - -EARLY_PCI_OP(read, byte, u8 *) -EARLY_PCI_OP(read, word, u16 *) -EARLY_PCI_OP(read, dword, u32 *) -EARLY_PCI_OP(write, byte, u8) -EARLY_PCI_OP(write, word, u16) -EARLY_PCI_OP(write, dword, u32) - -static struct resource *io_resource_inuse; -static struct resource *mem_resource_inuse; - -static u32 pciauto_lower_iospc; -static u32 pciauto_upper_iospc; - -static u32 pciauto_lower_memspc; -static u32 pciauto_upper_memspc; - -static void __init -pciauto_setup_bars(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn) -{ - u32 bar_response, bar_size, bar_value; - u32 bar, addr_mask, bar_nr = 0; - u32 * upper_limit; - u32 * lower_limit; - int found_mem64 = 0; - - for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { - /* Tickle the BAR and get the response */ - early_write_config_dword(hose, top_bus, - current_bus, - pci_devfn, - bar, - 0xffffffff); - early_read_config_dword(hose, top_bus, - current_bus, - pci_devfn, - bar, - &bar_response); - - /* If BAR is not implemented go to the next BAR */ - if (!bar_response) - continue; - - /* - * Workaround for a BAR that doesn't use its upper word, - * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457). - * bdl - */ - if (!(bar_response & 0xffff0000)) - bar_response |= 0xffff0000; - -retry: - /* Check the BAR type and set our address mask */ - if (bar_response & PCI_BASE_ADDRESS_SPACE) { - addr_mask = PCI_BASE_ADDRESS_IO_MASK; - upper_limit = &pciauto_upper_iospc; - lower_limit = &pciauto_lower_iospc; - DBG(" I/O"); - } else { - if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; - - addr_mask = PCI_BASE_ADDRESS_MEM_MASK; - upper_limit = &pciauto_upper_memspc; - lower_limit = &pciauto_lower_memspc; - DBG(" Mem"); - } - - - /* Calculate requested size */ - bar_size = ~(bar_response & addr_mask) + 1; - - /* Allocate a base address */ - bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; - - if ((bar_value + bar_size) > *upper_limit) { - if (bar_response & PCI_BASE_ADDRESS_SPACE) { - if (io_resource_inuse->child) { - io_resource_inuse = - io_resource_inuse->child; - pciauto_lower_iospc = - io_resource_inuse->start; - pciauto_upper_iospc = - io_resource_inuse->end + 1; - goto retry; - } - - } else { - if (mem_resource_inuse->child) { - mem_resource_inuse = - mem_resource_inuse->child; - pciauto_lower_memspc = - mem_resource_inuse->start; - pciauto_upper_memspc = - mem_resource_inuse->end + 1; - goto retry; - } - } - DBG(" unavailable -- skipping, value %x size %x\n", - bar_value, bar_size); - continue; - } - - /* Write it out and update our limit */ - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - bar, bar_value); - - *lower_limit = bar_value + bar_size; - - /* - * If we are a 64-bit decoder then increment to the - * upper 32 bits of the bar and force it to locate - * in the lower 4GB of memory. - */ - if (found_mem64) { - bar += 4; - early_write_config_dword(hose, top_bus, - current_bus, - pci_devfn, - bar, - 0x00000000); - } - - DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size); - - bar_nr++; - } - -} - -static void __init -pciauto_prescan_setup_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, - int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_PRIMARY_BUS, current_bus); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SECONDARY_BUS, sub_bus + 1); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, 0xff); - - /* Align memory and I/O to 1MB and 4KB boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) - & ~(0x100000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) - & ~(0x1000 - 1); - - /* Set base (lower limit) of address range behind bridge. */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_MEMORY_BASE, pciauto_lower_memspc >> 16); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_IO_BASE, (pciauto_lower_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_IO_BASE_UPPER16, pciauto_lower_iospc >> 16); - - /* We don't support prefetchable memory for now, so disable */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_PREF_MEMORY_BASE, 0); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_PREF_MEMORY_LIMIT, 0); -} - -static void __init -pciauto_postscan_setup_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, - int sub_bus) -{ - u32 temp; - - pciauto_lower_memspc += 1; - pciauto_lower_iospc += 1; - - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, sub_bus); - - /* Set upper limit of address range behind bridge. */ - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_MEMORY_LIMIT, pciauto_lower_memspc >> 16); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_IO_LIMIT, (pciauto_lower_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, top_bus, current_bus, pci_devfn, - PCI_IO_LIMIT_UPPER16, pciauto_lower_iospc >> 16); - - /* Align memory and I/O to 1MB and 4KB boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) - & ~(0x100000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) - & ~(0x1000 - 1); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, &temp); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY - | PCI_COMMAND_MASTER); -} - -static void __init -pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, - int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_PRIMARY_BUS, current_bus); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SECONDARY_BUS, sub_bus + 1); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, 0xff); - - /* Align memory and I/O to 4KB and 4 byte boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) - & ~(0x1000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) - & ~(0x4 - 1); - - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_MEMORY_BASE_0, pciauto_lower_memspc); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_IO_BASE_0, pciauto_lower_iospc); -} - -static void __init -pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, - int top_bus, - int current_bus, - int pci_devfn, - int sub_bus) -{ - u32 temp; - - /* - * [jsun] we always bump up baselines a little, so that if there - * nothing behind P2P bridge, we don't wind up overlapping IO/MEM - * spaces. - */ - pciauto_lower_memspc += 1; - pciauto_lower_iospc += 1; - - /* - * Configure subordinate bus number. The PCI subsystem - * bus scan will renumber buses (reserving three additional - * for this PCI<->CardBus bridge for the case where a CardBus - * adapter contains a P2P or CB2CB bridge. - */ - - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, sub_bus); - - /* - * Reserve an additional 4MB for mem space and 16KB for - * I/O space. This should cover any additional space - * requirement of unusual CardBus devices with - * additional bridges that can consume more address space. - * - * Although pcmcia-cs currently will reprogram bridge - * windows, the goal is to add an option to leave them - * alone and use the bridge window ranges as the regions - * that are searched for free resources upon hot-insertion - * of a device. This will allow a PCI<->CardBus bridge - * configured by this routine to happily live behind a - * P2P bridge in a system. - */ - - /* Align memory and I/O to 4KB and 4 byte boundaries. */ - pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) - & ~(0x1000 - 1); - pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) - & ~(0x4 - 1); - /* Set up memory and I/O filter limits, assume 32-bit I/O space */ - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_MEMORY_LIMIT_0, pciauto_lower_memspc - 1); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_CB_IO_LIMIT_0, pciauto_lower_iospc - 1); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, &temp); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY - | PCI_COMMAND_MASTER); -} - -#define PCIAUTO_IDE_MODE_MASK 0x05 - -static int __init -pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) -{ - int sub_bus; - u32 pci_devfn, pci_class, cmdstat, found_multi=0; - unsigned short vid, did; - unsigned char header_type; - int devfn_start = 0; - int devfn_stop = 0xff; - - sub_bus = current_bus; - - if (hose->first_devfn) - devfn_start = hose->first_devfn; - if (hose->last_devfn) - devfn_stop = hose->last_devfn; - - for (pci_devfn=devfn_start; pci_devfn> 16, vid, did); - if (pci_class & 0xff) - DBG(" (rev %.2x)", pci_class & 0xff); - DBG("\n"); - - if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { - DBG(" Bridge: primary=%.2x, secondary=%.2x\n", - current_bus, sub_bus + 1); - pciauto_prescan_setup_bridge(hose, top_bus, current_bus, - pci_devfn, sub_bus); - DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", - sub_bus + 1, - pciauto_lower_iospc, pciauto_lower_memspc); - sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); - DBG("Back to bus %.2x\n", current_bus); - pciauto_postscan_setup_bridge(hose, top_bus, current_bus, - pci_devfn, sub_bus); - continue; - } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) { - DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n", - current_bus, sub_bus + 1); - DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); - /* Place CardBus Socket/ExCA registers */ - pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); - - pciauto_prescan_setup_cardbus_bridge(hose, top_bus, - current_bus, pci_devfn, sub_bus); - - DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", - sub_bus + 1, - pciauto_lower_iospc, pciauto_lower_memspc); - sub_bus = pciauto_bus_scan(hose, top_bus, sub_bus+1); - DBG("Back to bus %.2x, sub_bus is %x\n", current_bus, sub_bus); - pciauto_postscan_setup_cardbus_bridge(hose, top_bus, - current_bus, pci_devfn, sub_bus); - continue; - } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { - - unsigned char prg_iface; - - early_read_config_byte(hose, top_bus, current_bus, - pci_devfn, PCI_CLASS_PROG, &prg_iface); - if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { - DBG("Skipping legacy mode IDE controller\n"); - continue; - } - } - - /* - * Found a peripheral, enable some standard - * settings - */ - early_read_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, &cmdstat); - early_write_config_dword(hose, top_bus, current_bus, pci_devfn, - PCI_COMMAND, cmdstat | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); - early_write_config_byte(hose, top_bus, current_bus, pci_devfn, - PCI_LATENCY_TIMER, 0x80); - - /* Allocate PCI I/O and/or memory space */ - pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn); - } - return sub_bus; -} - -int __init -pciauto_assign_resources(int busno, struct pci_channel *hose) -{ - /* setup resource limits */ - io_resource_inuse = hose->io_resource; - mem_resource_inuse = hose->mem_resource; - - pciauto_lower_iospc = io_resource_inuse->start; - pciauto_upper_iospc = io_resource_inuse->end + 1; - pciauto_lower_memspc = mem_resource_inuse->start; - pciauto_upper_memspc = mem_resource_inuse->end + 1; - DBG("Autoconfig PCI channel 0x%p\n", hose); - DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n", - busno, pciauto_lower_iospc, pciauto_upper_iospc, - pciauto_lower_memspc, pciauto_upper_memspc); - - return pciauto_bus_scan(hose, busno, busno); -} diff -puN -L arch/sh/kernel/pcibios.c arch/sh/kernel/pcibios.c~linus /dev/null --- 25/arch/sh/kernel/pcibios.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,97 +0,0 @@ -/* - * $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $ - * - * arch/sh/kernel/pcibios.c - * - * This is GPL'd. - * - * Provided here are generic versions of: - * pcibios_align_resource() - * pcibios_enable_device() - * pcibios_set_master() - * pcibios_update_irq() - * - * These functions are collected here to reduce duplication of common - * code amongst the many platform-specific PCI support code files. - * - * Platform-specific files are expected to provide: - * pcibios_fixup_bus() - * pcibios_init() - * pcibios_setup() - */ - -#include -#include -#include - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - -int pcibios_enable_device(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check and set - * the latency timer as it may not be properly set. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} diff -puN -L arch/sh/kernel/pci.c arch/sh/kernel/pci.c~linus /dev/null --- 25/arch/sh/kernel/pci.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,153 +0,0 @@ -/* arch/sh/kernel/pci.c - * $Id: pci.c,v 1.4 2003/05/25 01:29:24 lethal Exp $ - * - * Copyright (c) 2002 M. R. Brown - * - * - * These functions are collected here to reduce duplication of common - * code amongst the many platform-specific PCI support code files. - * - * These routines require the following board-specific routines: - * void pcibios_fixup(); - * void pcibios_fixup_irqs(); - * - * See include/asm-sh/pci.h for more information. - */ - -#include -#include -#include - -static int __init pcibios_init(void) -{ - struct pci_channel *p; - struct pci_bus *bus; - int busno; - -#ifdef CONFIG_PCI_AUTO - /* assign resources */ - busno=0; - for (p = board_pci_channels; p->pci_ops != NULL; p++) { - busno = pciauto_assign_resources(busno, p) + 1; - } -#endif - - /* scan the buses */ - busno = 0; - for (p= board_pci_channels; p->pci_ops != NULL; p++) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate+1; - } - - /* board-specific fixups */ - pcibios_fixup(); - pcibios_fixup_irqs(); - - return 0; -} - -subsys_initcall(pcibios_init); - -void -pcibios_update_resource(struct pci_dev *dev, struct resource *root, - struct resource *res, int resource) -{ - u32 new, check; - int reg; - - new = res->start | (res->flags & PCI_REGION_FLAG_MASK); - if (resource < 6) { - reg = PCI_BASE_ADDRESS_0 + 4*resource; - } else if (resource == PCI_ROM_RESOURCE) { - res->flags |= PCI_ROM_ADDRESS_ENABLE; - new |= PCI_ROM_ADDRESS_ENABLE; - reg = dev->rom_base_reg; - } else { - /* Somebody might have asked allocation of a non-standard resource */ - return; - } - - pci_write_config_dword(dev, reg, new); - pci_read_config_dword(dev, reg, &check); - if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) { - printk(KERN_ERR "PCI: Error while updating region " - "%s/%d (%08x != %08x)\n", pci_name(dev), resource, - new, check); - } -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) - __attribute__ ((weak)); - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev)); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (dev->resource[PCI_ROM_RESOURCE].start) - cmd |= PCI_COMMAND_MEMORY; - if (cmd != old_cmd) { - printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->dev.name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -/* - * If we set up a device for bus mastering, we need to check and set - * the latency timer as it may not be properly set. - */ -unsigned int pcibios_max_latency = 255; - -void pcibios_set_master(struct pci_dev *dev) -{ - u8 lat; - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - if (lat < 16) - lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency; - else if (lat > pcibios_max_latency) - lat = pcibios_max_latency; - else - return; - printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->dev.name, lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} diff -puN -L arch/sh/kernel/pci-dma.c arch/sh/kernel/pci-dma.c~linus /dev/null --- 25/arch/sh/kernel/pci-dma.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Dynamic DMA mapping support. - */ - -#include -#include -#include -#include -#include -#include - - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - ret = (void *) __get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - /* Is it necessary to do the memset? */ - memset(ret, 0, size); - *dma_handle = virt_to_phys(ret); - } - /* We must flush the cache before we pass it on to the device */ - dma_cache_wback_inv(ret, size); - return P2SEGADDR(ret); -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - unsigned long p1addr=P1SEGADDR((unsigned long)vaddr); - - free_pages(p1addr, get_order(size)); -} diff -puN arch/sh/kernel/process.c~linus arch/sh/kernel/process.c --- 25/arch/sh/kernel/process.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/process.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.17 2003/05/27 21:37:11 lethal Exp $ +/* $Id: process.c,v 1.24 2003/11/28 23:05:43 kkojima Exp $ * * linux/arch/sh/kernel/process.c * @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,8 @@ static int hlt_counter=0; +int ubc_usercnt = 0; + #define HARD_IDLE_TIMEOUT (HZ / 3) void disable_hlt(void) @@ -47,19 +50,9 @@ void default_idle(void) { /* endless idle loop with no priority at all */ while (1) { - if (hlt_counter) { - while (1) - if (need_resched()) - break; - } else { - local_irq_disable(); - while (!need_resched()) { - local_irq_enable(); - asm volatile("sleep" : : : "memory"); - local_irq_disable(); - } - local_irq_enable(); - } + while (!need_resched()) + cpu_relax(); + schedule(); } } @@ -81,7 +74,7 @@ EXPORT_SYMBOL(machine_restart); void machine_halt(void) { while (1) - asm volatile("sleep" : : : "memory"); + cpu_relax(); } EXPORT_SYMBOL(machine_halt); @@ -95,8 +88,17 @@ EXPORT_SYMBOL(machine_power_off); void show_regs(struct pt_regs * regs) { printk("\n"); - printk("PC : %08lx SP : %08lx SR : %08lx TEA : %08x %s\n", - regs->pc, regs->regs[15], regs->sr, ctrl_inl(MMU_TEA), print_tainted()); + printk("Pid : %d, Comm: %20s\n", current->pid, current->comm); + print_symbol("PC is at %s\n", regs->pc); + printk("PC : %08lx SP : %08lx SR : %08lx ", + regs->pc, regs->regs[15], regs->sr); +#ifdef CONFIG_MMU + printk("TEA : %08x ", ctrl_inl(MMU_TEA)); +#else + printk(" "); +#endif + printk("%s\n", print_tainted()); + printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", regs->regs[0],regs->regs[1], regs->regs[2],regs->regs[3]); @@ -162,7 +164,10 @@ int kernel_thread(int (*fn)(void *), voi */ void exit_thread(void) { - /* Nothing to do. */ + if (current->thread.ubc_pc) { + current->thread.ubc_pc = 0; + ubc_usercnt -= 1; + } } void flush_thread(void) @@ -207,7 +212,11 @@ int dump_task_regs(struct task_struct *t struct pt_regs ptregs; ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs)); + ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs) +#ifdef CONFIG_SH_DSP + - sizeof(struct pt_dspregs) +#endif + - sizeof(unsigned long)); elf_core_copy_regs(regs, &ptregs); return 1; @@ -237,7 +246,12 @@ int copy_thread(int nr, unsigned long cl { struct pt_regs *childregs; - childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long) p->thread_info)) - 1; + childregs = ((struct pt_regs *) + (THREAD_SIZE + (unsigned long) p->thread_info) +#ifdef CONFIG_SH_DSP + - sizeof(struct pt_dspregs) +#endif + - sizeof(unsigned long)) - 1; *childregs = *regs; if (user_mode(regs)) { @@ -255,6 +269,8 @@ int copy_thread(int nr, unsigned long cl p->thread.sp = (unsigned long) childregs; p->thread.pc = (unsigned long) ret_from_fork; + p->thread.ubc_pc = 0; + #if defined(CONFIG_CPU_SH4) { struct task_struct *tsk = current; @@ -288,6 +304,27 @@ void dump_thread(struct pt_regs * regs, dump->u_fpvalid = dump_fpu(regs, &dump->fpu); } +/* Tracing by user break controller. */ +static void +ubc_set_tracing(int asid, unsigned long pc) +{ + ctrl_outl(pc, UBC_BARA); + + /* We don't have any ASID settings for the SH-2! */ + if (cpu_data->type != CPU_SH7604) + ctrl_outb(asid, UBC_BASRA); + + ctrl_outl(0, UBC_BAMRA); + + if (cpu_data->type == CPU_SH7729) { + ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); + ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR); + } else { + ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); + ctrl_outw(BRCR_PCBA, UBC_BRCR); + } +} + /* * switch_to(x,y) should switch tasks from x to y. * @@ -305,6 +342,19 @@ struct task_struct *__switch_to(struct t : /* no output */ : "r" (next->thread_info)); +#ifdef CONFIG_MMU + /* If no tasks are using the UBC, we're done */ + if (ubc_usercnt == 0) + /* If no tasks are using the UBC, we're done */; + else if (next->thread.ubc_pc && next->mm) { + ubc_set_tracing(next->mm->context & MMU_CONTEXT_ASID_MASK, + next->thread.ubc_pc); + } else { + ctrl_outw(0, UBC_BBRA); + ctrl_outw(0, UBC_BBRB); + } +#endif + return prev; } @@ -328,7 +378,7 @@ asmlinkage int sys_clone(unsigned long c if (!newsp) newsp = regs.regs[15]; return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, - (int *)parent_tidptr, (int *)child_tidptr); + (int __user *)parent_tidptr, (int __user *)child_tidptr); } /* @@ -359,12 +409,15 @@ asmlinkage int sys_execve(char *ufilenam int error; char *filename; - filename = getname(ufilename); + filename = getname((char __user *)ufilename); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; - error = do_execve(filename, uargv, uenvp, ®s); + error = do_execve(filename, + (char __user * __user *)uargv, + (char __user * __user *)uenvp, + ®s); if (error == 0) current->ptrace &= ~PT_DTRACE; putname(filename); @@ -406,6 +459,8 @@ asmlinkage void break_point_trap(unsigne /* Clear tracing. */ ctrl_outw(0, UBC_BBRA); ctrl_outw(0, UBC_BBRB); + current->thread.ubc_pc = 0; + ubc_usercnt -= 1; force_sig(SIGTRAP, current); } diff -puN arch/sh/kernel/ptrace.c~linus arch/sh/kernel/ptrace.c --- 25/arch/sh/kernel/ptrace.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/ptrace.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: ptrace.c,v 1.9 2003/05/06 23:28:47 lethal Exp $ +/* $Id: ptrace.c,v 1.14 2003/11/28 23:05:43 kkojima Exp $ * * linux/arch/sh/kernel/ptrace.c * @@ -41,7 +41,12 @@ static inline int get_stack_long(struct { unsigned char *stack; - stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs); + stack = (unsigned char *) + task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) +#ifdef CONFIG_SH_DSP + - sizeof(struct pt_dspregs) +#endif + - sizeof(unsigned long); stack += offset; return (*((int *)stack)); } @@ -54,97 +59,17 @@ static inline int put_stack_long(struct { unsigned char *stack; - stack = (unsigned char *)task->thread_info + THREAD_SIZE - sizeof(struct pt_regs); + stack = (unsigned char *) + task->thread_info + THREAD_SIZE - sizeof(struct pt_regs) +#ifdef CONFIG_SH_DSP + - sizeof(struct pt_dspregs) +#endif + - sizeof(unsigned long); stack += offset; *(unsigned long *) stack = data; return 0; } -static void -compute_next_pc(struct pt_regs *regs, unsigned short inst, - unsigned long *pc1, unsigned long *pc2) -{ - int nib[4] - = { (inst >> 12) & 0xf, - (inst >> 8) & 0xf, - (inst >> 4) & 0xf, - inst & 0xf}; - - /* bra & bsr */ - if (nib[0] == 0xa || nib[0] == 0xb) { - *pc1 = regs->pc + 4 + ((short) ((inst & 0xfff) << 4) >> 3); - *pc2 = (unsigned long) -1; - return; - } - - /* bt & bf */ - if (nib[0] == 0x8 && (nib[1] == 0x9 || nib[1] == 0xb)) { - *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1); - *pc2 = regs->pc + 2; - return; - } - - /* bt/s & bf/s */ - if (nib[0] == 0x8 && (nib[1] == 0xd || nib[1] == 0xf)) { - *pc1 = regs->pc + 4 + ((char) (inst & 0xff) << 1); - *pc2 = regs->pc + 4; - return; - } - - /* jmp & jsr */ - if (nib[0] == 0x4 && nib[3] == 0xb - && (nib[2] == 0x0 || nib[2] == 0x2)) { - *pc1 = regs->regs[nib[1]]; - *pc2 = (unsigned long) -1; - return; - } - - /* braf & bsrf */ - if (nib[0] == 0x0 && nib[3] == 0x3 - && (nib[2] == 0x0 || nib[2] == 0x2)) { - *pc1 = regs->pc + 4 + regs->regs[nib[1]]; - *pc2 = (unsigned long) -1; - return; - } - - if (inst == 0x000b) { - *pc1 = regs->pr; - *pc2 = (unsigned long) -1; - return; - } - - *pc1 = regs->pc + 2; - *pc2 = (unsigned long) -1; - return; -} - -/* Tracing by user break controller. */ -static void -ubc_set_tracing(int asid, unsigned long nextpc1, unsigned nextpc2) -{ - ctrl_outl(nextpc1, UBC_BARA); - ctrl_outb(asid, UBC_BASRA); - ctrl_outl(0, UBC_BAMRA); - if(UBC_TYPE_SH7729) - ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); - else - ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); - - if (nextpc2 != (unsigned long) -1) { - ctrl_outl(nextpc2, UBC_BARB); - ctrl_outb(asid, UBC_BASRB); - ctrl_outl(0, UBC_BAMRB); - if(UBC_TYPE_SH7729) - ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRB); - else - ctrl_outw(BBR_INST | BBR_READ, UBC_BBRB); - } - if(UBC_TYPE_SH7729) - ctrl_outl(BRCR_PCTE, UBC_BRCR); - else - ctrl_outw(0, UBC_BRCR); -} - /* * Called by kernel/ptrace.c when detaching.. * @@ -300,11 +225,8 @@ asmlinkage int sys_ptrace(long request, } case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long tmp, pc; + long pc; struct pt_regs *dummy = NULL; - struct pt_regs *regs; - unsigned long nextpc1, nextpc2; - unsigned short insn; ret = -EIO; if ((unsigned long) data > _NSIG) @@ -315,34 +237,12 @@ asmlinkage int sys_ptrace(long request, child->ptrace |= PT_DTRACE; } - /* Compute next pc. */ pc = get_stack_long(child, (long)&dummy->pc); - regs = (struct pt_regs *)(THREAD_SIZE + (unsigned long)child->thread_info) - 1; - if (access_process_vm(child, pc&~3, &tmp, sizeof(tmp), 0) != sizeof(tmp)) - break; - -#ifdef __LITTLE_ENDIAN__ - if (pc & 3) - insn = tmp >> 16; - else - insn = tmp & 0xffff; -#else - if (pc & 3) - insn = tmp & 0xffff; - else - insn = tmp >> 16; -#endif - compute_next_pc(regs, insn, &nextpc1, &nextpc2); - - if (nextpc1 & 0x80000000) - break; - if (nextpc2 != (unsigned long) -1 && (nextpc2 & 0x80000000)) - break; -#ifdef CONFIG_MMU - ubc_set_tracing(child->mm->context & MMU_CONTEXT_ASID_MASK, - nextpc1, nextpc2); -#endif + /* Next scheduling will set up UBC */ + if (child->thread.ubc_pc == 0) + ubc_usercnt += 1; + child->thread.ubc_pc = pc; child->exit_code = data; /* give it a chance to run. */ @@ -362,7 +262,36 @@ asmlinkage int sys_ptrace(long request, child->ptrace &= ~PT_TRACESYSGOOD; ret = 0; break; +#ifdef CONFIG_SH_DSP + case PTRACE_GETDSPREGS: { + unsigned long dp; + + ret = -EIO; + dp = ((unsigned long) child) + THREAD_SIZE - + sizeof(struct pt_dspregs); + if (*((int *) (dp - 4)) == SR_FD) { + copy_to_user(addr, (void *) dp, + sizeof(struct pt_dspregs)); + ret = 0; + } + break; + } + + case PTRACE_SETDSPREGS: { + unsigned long dp; + int i; + ret = -EIO; + dp = ((unsigned long) child) + THREAD_SIZE - + sizeof(struct pt_dspregs); + if (*((int *) (dp - 4)) == SR_FD) { + copy_from_user((void *) dp, addr, + sizeof(struct pt_dspregs)); + ret = 0; + } + break; + } +#endif default: ret = ptrace_request(child, request, addr, data); break; diff -puN -L arch/sh/kernel/rtc.c arch/sh/kernel/rtc.c~linus /dev/null --- 25/arch/sh/kernel/rtc.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,124 +0,0 @@ -/* - * linux/arch/sh/kernel/rtc.c -- SH3 / SH4 on-chip RTC support - * - * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka - */ - -#include -#include -#include -#include -#include - -#include -#include - -void sh_rtc_gettimeofday(struct timeval *tv) -{ - unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100; - - again: - do { - ctrl_outb(0, RCR1); /* Clear CF-bit */ - sec128 = ctrl_inb(R64CNT); - sec = ctrl_inb(RSECCNT); - min = ctrl_inb(RMINCNT); - hr = ctrl_inb(RHRCNT); - wk = ctrl_inb(RWKCNT); - day = ctrl_inb(RDAYCNT); - mon = ctrl_inb(RMONCNT); -#if defined(__SH4__) - yr = ctrl_inw(RYRCNT); - yr100 = (yr >> 8); - yr &= 0xff; -#else - yr = ctrl_inb(RYRCNT); - yr100 = (yr == 0x99) ? 0x19 : 0x20; -#endif - } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); - -#if RTC_BIT_INVERTED != 0 - /* Work around to avoid reading incorrect value. */ - if (sec128 == RTC_BIT_INVERTED) { - schedule_timeout(1); - goto again; - } -#endif - - BCD_TO_BIN(yr100); - BCD_TO_BIN(yr); - BCD_TO_BIN(mon); - BCD_TO_BIN(day); - BCD_TO_BIN(hr); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - - if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || - hr > 23 || min > 59 || sec > 59) { - printk(KERN_ERR - "SH RTC: invalid value, resetting to 1 Jan 2000\n"); - ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ - ctrl_outb(0, RSECCNT); - ctrl_outb(0, RMINCNT); - ctrl_outb(0, RHRCNT); - ctrl_outb(6, RWKCNT); - ctrl_outb(1, RDAYCNT); - ctrl_outb(1, RMONCNT); -#if defined(__SH4__) - ctrl_outw(0x2000, RYRCNT); -#else - ctrl_outb(0, RYRCNT); -#endif - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */ - goto again; - } - -#if RTC_BIT_INVERTED != 0 - if ((sec128 & RTC_BIT_INVERTED)) - sec--; -#endif - - tv->tv_sec = mktime(yr100 * 100 + yr, mon, day, hr, min, sec); - tv->tv_usec = (sec128 * 1000000) / 128; -} - -int sh_rtc_settimeofday(const struct timeval *tv) -{ - unsigned long nowtime = tv->tv_sec; - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - - ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ - - cmos_minutes = ctrl_inb(RMINCNT); - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - ctrl_outb(real_seconds, RSECCNT); - ctrl_outb(real_minutes, RMINCNT); - } else { - printk(KERN_WARNING - "set_rtc_time: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ - - return retval; -} diff -puN arch/sh/kernel/setup.c~linus arch/sh/kernel/setup.c --- 25/arch/sh/kernel/setup.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/setup.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: setup.c,v 1.17 2003/05/20 01:51:37 lethal Exp $ +/* $Id: setup.c,v 1.30 2003/10/13 07:21:19 lethal Exp $ * * linux/arch/sh/kernel/setup.c * @@ -10,38 +10,21 @@ * This file handles the architecture-dependent parts of initialization */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include #include #include #include -#include #include -#include #include #include #include -#include -#include -#include #include -#include #include #include -#include +#include +#include #ifdef CONFIG_SH_EARLY_PRINTK #include #endif @@ -63,7 +46,6 @@ static int kgdb_parse_options(char *opti struct sh_cpuinfo boot_cpu_data = { CPU_SH_NONE, 0, 10000000, }; struct screen_info screen_info; unsigned char aux_device_present = 0xaa; -static int fpu_disabled __initdata = 0; #if defined(CONFIG_SH_UNKNOWN) struct sh_machine_vector sh_mv; @@ -82,11 +64,9 @@ struct screen_info screen_info = { 16 /* orig-video-points */ }; -extern void fpu_init(void); extern void platform_setup(void); extern char *get_system_type(void); extern int root_mountflags; -extern int _text, _etext, _edata, _end; #define MV_NAME_SIZE 32 @@ -174,7 +154,7 @@ static void scif_sercon_write(struct con static int __init scif_sercon_setup(struct console *con, char *options) { - con->cflag = CREAD | HUPCL | CLOCAL | B115200 | CS8; + con->cflag = CREAD | HUPCL | CLOCAL | B57600 | CS8; return 0; } @@ -333,7 +313,7 @@ static inline void parse_cmdline (char * *cmdline_p = command_line; } -void __init setup_arch(char **cmdline_p) +static int __init sh_mv_setup(char **cmdline_p) { #if defined(CONFIG_SH_UNKNOWN) extern struct sh_machine_vector mv_unknown; @@ -342,41 +322,11 @@ void __init setup_arch(char **cmdline_p) char mv_name[MV_NAME_SIZE] = ""; unsigned long mv_io_base = 0; int mv_mmio_enable = 0; - unsigned long bootmap_size; - unsigned long start_pfn, max_pfn, max_low_pfn; - -/* XXX: MRB-remove */ -#if 0 - scif_sercon_init(115200); -#endif -#ifdef CONFIG_SH_EARLY_PRINTK - sh_console_init(); -#endif - - ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); - -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long)&_text; - init_mm.end_code = (unsigned long) &_etext; - init_mm.end_data = (unsigned long) &_edata; - init_mm.brk = (unsigned long) &_end; - - code_resource.start = virt_to_bus(&_text); - code_resource.end = virt_to_bus(&_etext)-1; - data_resource.start = virt_to_bus(&_etext); - data_resource.end = virt_to_bus(&_edata)-1; parse_cmdline(cmdline_p, mv_name, &mv, &mv_io_base, &mv_mmio_enable); #ifdef CONFIG_CMDLINE_BOOL - sprintf(*cmdline_p, CONFIG_CMDLINE); + sprintf(*cmdline_p, CONFIG_CMDLINE); #endif #ifdef CONFIG_SH_GENERIC @@ -393,42 +343,75 @@ void __init setup_arch(char **cmdline_p) sh_mv = mv_unknown; #endif -#if defined(CONFIG_SH_UNKNOWN) - if (mv_io_base != 0) { - sh_mv.mv_inb = generic_inb; - sh_mv.mv_inw = generic_inw; - sh_mv.mv_inl = generic_inl; - sh_mv.mv_outb = generic_outb; - sh_mv.mv_outw = generic_outw; - sh_mv.mv_outl = generic_outl; - - sh_mv.mv_inb_p = generic_inb_p; - sh_mv.mv_inw_p = generic_inw_p; - sh_mv.mv_inl_p = generic_inl_p; - sh_mv.mv_outb_p = generic_outb_p; - sh_mv.mv_outw_p = generic_outw_p; - sh_mv.mv_outl_p = generic_outl_p; - - sh_mv.mv_insb = generic_insb; - sh_mv.mv_insw = generic_insw; - sh_mv.mv_insl = generic_insl; - sh_mv.mv_outsb = generic_outsb; - sh_mv.mv_outsw = generic_outsw; - sh_mv.mv_outsl = generic_outsl; - - sh_mv.mv_isa_port2addr = generic_isa_port2addr; - generic_io_base = mv_io_base; - } - if (mv_mmio_enable != 0) { - sh_mv.mv_readb = generic_readb; - sh_mv.mv_readw = generic_readw; - sh_mv.mv_readl = generic_readl; - sh_mv.mv_writeb = generic_writeb; - sh_mv.mv_writew = generic_writew; - sh_mv.mv_writel = generic_writel; - } + /* + * Manually walk the vec, fill in anything that the board hasn't yet + * by hand, wrapping to the generic implementation. + */ +#define mv_set(elem) do { \ + if (!sh_mv.mv_##elem) \ + sh_mv.mv_##elem = generic_##elem; \ +} while (0) + + mv_set(inb); mv_set(inw); mv_set(inl); + mv_set(outb); mv_set(outw); mv_set(outl); + + mv_set(inb_p); mv_set(inw_p); mv_set(inl_p); + mv_set(outb_p); mv_set(outw_p); mv_set(outl_p); + + mv_set(insb); mv_set(insw); mv_set(insl); + mv_set(outsb); mv_set(outsw); mv_set(outsl); + + mv_set(readb); mv_set(readw); mv_set(readl); + mv_set(writeb); mv_set(writew); mv_set(writel); + + mv_set(ioremap); + mv_set(iounmap); + + mv_set(isa_port2addr); + mv_set(irq_demux); + +#ifdef CONFIG_SH_UNKNOWN + __set_io_port_base(mv_io_base); #endif + return 0; +} + +void __init setup_arch(char **cmdline_p) +{ + unsigned long bootmap_size; + unsigned long start_pfn, max_pfn, max_low_pfn; + +/* XXX: MRB-remove */ +#if 0 + scif_sercon_init(57600); +#endif +#ifdef CONFIG_SH_EARLY_PRINTK + sh_console_init(); +#endif + + ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); + +#ifdef CONFIG_BLK_DEV_RAM + rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; + rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); + rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); +#endif + + if (!MOUNT_ROOT_RDONLY) + root_mountflags &= ~MS_RDONLY; + init_mm.start_code = (unsigned long) _text; + init_mm.end_code = (unsigned long) _etext; + init_mm.end_data = (unsigned long) _edata; + init_mm.brk = (unsigned long) _end; + + code_resource.start = virt_to_bus(_text); + code_resource.end = virt_to_bus(_etext)-1; + data_resource.start = virt_to_bus(_etext); + data_resource.end = virt_to_bus(_edata)-1; + + sh_mv_setup(cmdline_p); + #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) #define PFN_DOWN(x) ((x) >> PAGE_SHIFT) #define PFN_PHYS(x) ((x) << PAGE_SHIFT) @@ -459,7 +442,8 @@ void __init setup_arch(char **cmdline_p) * Partially used pages are not usable - thus * we are rounding upwards: */ - start_pfn = PFN_UP(__pa(&_end)); + start_pfn = PFN_UP(__pa(_end)); + /* * Find a proper area for the bootmem bitmap. After this * bootstrap step all allocations (until the page allocator @@ -524,40 +508,13 @@ void __init setup_arch(char **cmdline_p) } #endif -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) +#ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif -#endif /* Perform the machine specific initialisation */ platform_setup(); -#if defined(CONFIG_CPU_SH4) - /* FPU initialization */ - clear_thread_flag(TIF_USEDFPU); - current->used_math = 0; -#endif - - /* Disable the FPU */ - if (fpu_disabled) { - printk("FPU Disabled\n"); - cpu_data->flags &= ~CPU_HAS_FPU; - release_fpu(); - } - -#ifdef CONFIG_UBC_WAKEUP - /* - * Some brain-damaged loaders decided it would be a good idea to put - * the UBC to sleep. This causes some issues when it comes to things - * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So .. - * we wake it up and hope that all is well. - */ - ubc_wakeup(); -#endif - paging_init(); } @@ -599,17 +556,20 @@ static int __init topology_init(void) subsys_initcall(topology_init); static const char *cpu_name[] = { - [CPU_SH7604] "SH7604", - [CPU_SH7708] "SH7708", - [CPU_SH7729] "SH7729", - [CPU_SH7750] "SH7750", - [CPU_SH7750S] "SH7750S", - [CPU_SH7750R] "SH7750R", - [CPU_SH7751] "SH7751", - [CPU_SH7751R] "SH7751R", - [CPU_ST40RA] "ST40RA", - [CPU_ST40GX1] "ST40GX1", - [CPU_SH_NONE] "Unknown" + [CPU_SH7604] = "SH7604", + [CPU_SH7708] = "SH7708", + [CPU_SH7729] = "SH7729", + [CPU_SH7750] = "SH7750", + [CPU_SH7750S] = "SH7750S", + [CPU_SH7750R] = "SH7750R", + [CPU_SH7751] = "SH7751", + [CPU_SH7751R] = "SH7751R", + [CPU_SH7760] = "SH7760", + [CPU_ST40RA] = "ST40RA", + [CPU_ST40GX1] = "ST40GX1", + [CPU_SH4_202] = "SH4-202", + [CPU_SH4_501] = "SH4-501", + [CPU_SH_NONE] = "Unknown" }; const char *get_cpu_subtype(void) @@ -617,44 +577,73 @@ const char *get_cpu_subtype(void) return cpu_name[boot_cpu_data.type]; } +#ifdef CONFIG_PROC_FS +static const char *cpu_flags[] = { + "none", "fpu", "p2flush", "mmuassoc", "dsp", +}; + +static void show_cpuflags(struct seq_file *m) +{ + unsigned long i; + + seq_printf(m, "cpu flags\t:"); + + if (!cpu_data->flags) { + seq_printf(m, " %s\n", cpu_flags[0]); + return; + } + + for (i = 0; i < cpu_data->flags; i++) + if ((cpu_data->flags & (1 << i))) + seq_printf(m, " %s", cpu_flags[i]); + + seq_printf(m, "\n"); +} + +static void show_cacheinfo(struct seq_file *m, const char *type, struct cache_info info) +{ + unsigned int cache_size; + + cache_size = info.ways * info.sets * info.linesz; + + seq_printf(m, "%s size\t: %dKiB\n", type, cache_size >> 10); +} + /* * Get CPU information for use by the procfs. */ -#ifdef CONFIG_PROC_FS static int show_cpuinfo(struct seq_file *m, void *v) { - unsigned int dcachesz, icachesz; unsigned int cpu = smp_processor_id(); - icachesz = boot_cpu_data.icache.ways * - boot_cpu_data.icache.sets * - boot_cpu_data.icache.linesz; - if (!cpu && cpu_online(cpu)) seq_printf(m, "machine\t\t: %s\n", get_system_type()); seq_printf(m, "processor\t: %d\n", cpu); seq_printf(m, "cpu family\t: %s\n", system_utsname.machine); seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype()); - seq_printf(m, "cache size\t: %dK-bytes", icachesz >> 10); + + show_cpuflags(m); + + seq_printf(m, "cache type\t: "); /* - * SH-2 and SH-3 have a combined cache, thus there's no real - * I/D distinction .. so don't inadvertently double - * up the output. + * Check for what type of cache we have, we support both the + * unified cache on the SH-2 and SH-3, as well as the harvard + * style cache on the SH-4. */ - if (strcmp(system_utsname.machine, "sh2") || - strcmp(system_utsname.machine, "sh3")) { - dcachesz = boot_cpu_data.dcache.ways * - boot_cpu_data.dcache.sets * - boot_cpu_data.dcache.linesz; - - seq_printf(m, "/%dK-bytes", dcachesz >> 10); + if (test_bit(SH_CACHE_COMBINED, &(boot_cpu_data.icache.flags))) { + seq_printf(m, "unified\n"); + show_cacheinfo(m, "cache", boot_cpu_data.icache); + } else { + seq_printf(m, "split (harvard)\n"); + show_cacheinfo(m, "icache", boot_cpu_data.icache); + show_cacheinfo(m, "dcache", boot_cpu_data.dcache); } - seq_printf(m, "\nbogomips\t: %lu.%02lu\n", - loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100); + seq_printf(m, "bogomips\t: %lu.%02lu\n", + boot_cpu_data.loops_per_jiffy/(500000/HZ), + (boot_cpu_data.loops_per_jiffy/(5000/HZ)) % 100); #define PRINT_CLOCK(name, value) \ seq_printf(m, name " clock\t: %d.%02dMHz\n", \ @@ -780,10 +769,3 @@ static int __init kgdb_parse_options(cha __setup("kgdb=", kgdb_parse_options); #endif /* CONFIG_SH_KGDB */ -static int __init fpu_setup(char *opts) -{ - fpu_disabled = 1; - return 0; -} -__setup("nofpu", fpu_setup); - diff -puN arch/sh/kernel/sh_bios.c~linus arch/sh/kernel/sh_bios.c --- 25/arch/sh/kernel/sh_bios.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/sh_bios.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: sh_bios.c,v 1.5 2001/01/08 08:42:32 gniibe Exp $ +/* $Id: sh_bios.c,v 1.2 2003/05/04 19:29:53 lethal Exp $ * * linux/arch/sh/kernel/sh_bios.c * C interface for trapping into the standard LinuxSH BIOS. diff -puN arch/sh/kernel/sh_ksyms.c~linus arch/sh/kernel/sh_ksyms.c --- 25/arch/sh/kernel/sh_ksyms.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/sh_ksyms.c 2004-01-19 22:17:21.000000000 -0800 @@ -25,6 +25,8 @@ extern void dump_thread(struct pt_regs * extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); extern struct hw_interrupt_type no_irq_type; +EXPORT_SYMBOL(sh_mv); + /* platform dependent support */ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(dump_fpu); @@ -71,7 +73,9 @@ EXPORT_SYMBOL(screen_info); EXPORT_SYMBOL(boot_cpu_data); +#ifdef CONFIG_MMU EXPORT_SYMBOL(get_vm_area); +#endif /* semaphore exports */ EXPORT_SYMBOL(__up); diff -puN arch/sh/kernel/signal.c~linus arch/sh/kernel/signal.c --- 25/arch/sh/kernel/signal.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/signal.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.15 2003/05/06 23:28:47 lethal Exp $ +/* $Id: signal.c,v 1.19 2003/10/13 07:21:19 lethal Exp $ * * linux/arch/sh/kernel/signal.c * @@ -93,8 +93,8 @@ sys_rt_sigsuspend(sigset_t *unewset, siz } asmlinkage int -sys_sigaction(int sig, const struct old_sigaction *act, - struct old_sigaction *oact) +sys_sigaction(int sig, const struct old_sigaction __user *act, + struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_ } asmlinkage int -sys_sigaltstack(const stack_t *uss, stack_t *uoss, +sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r6, unsigned long r7, struct pt_regs regs) { @@ -137,24 +137,26 @@ sys_sigaltstack(const stack_t *uss, stac * Do a signal return; undo the signal stack. */ +#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ +#define TRAP16 0xc310 /* Syscall w/no args (NR in R3) */ +#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ + struct sigframe { struct sigcontext sc; unsigned long extramask[_NSIG_WORDS-1]; - char retcode[4]; + u16 retcode[8]; }; struct rt_sigframe { - struct siginfo *pinfo; - void *puc; struct siginfo info; struct ucontext uc; - char retcode[4]; + u16 retcode[8]; }; #ifdef CONFIG_CPU_SH4 -static inline int restore_sigcontext_fpu(struct sigcontext *sc) +static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) { struct task_struct *tsk = current; @@ -166,7 +168,7 @@ static inline int restore_sigcontext_fpu sizeof(long)*(16*2+2)); } -static inline int save_sigcontext_fpu(struct sigcontext *sc) +static inline int save_sigcontext_fpu(struct sigcontext __user *sc) { struct task_struct *tsk = current; @@ -192,7 +194,7 @@ static inline int save_sigcontext_fpu(st #endif /* CONFIG_CPU_SH4 */ static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p) +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p) { unsigned int err = 0; @@ -233,7 +235,7 @@ asmlinkage int sys_sigreturn(unsigned lo unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct sigframe *frame = (struct sigframe *)regs.regs[15]; + struct sigframe __user *frame = (struct sigframe __user *)regs.regs[15]; sigset_t set; int r0; @@ -266,7 +268,7 @@ asmlinkage int sys_rt_sigreturn(unsigned unsigned long r6, unsigned long r7, struct pt_regs regs) { - struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15]; + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs.regs[15]; sigset_t set; stack_t st; int r0; @@ -304,7 +306,7 @@ badframe: */ static int -setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask) { int err = 0; @@ -336,19 +338,19 @@ setup_sigcontext(struct sigcontext *sc, /* * Determine which stack to use.. */ -static inline void * +static inline void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; - return (void *)((sp - frame_size) & -8ul); + return (void __user *)((sp - frame_size) & -8ul); } static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { - struct sigframe *frame; + struct sigframe __user *frame; int err = 0; int signal; @@ -375,15 +377,16 @@ static void setup_frame(int sig, struct if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is : mov #__NR_sigreturn,r3 ; trapa #0x10 */ -#ifdef __LITTLE_ENDIAN__ - unsigned long code = 0xc310e300 | (__NR_sigreturn); -#else - unsigned long code = 0xe300c310 | (__NR_sigreturn << 16); -#endif - + /* Generate return code (system call to sigreturn) */ + err |= __put_user(MOVW(7), &frame->retcode[0]); + err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(OR_R0_R0, &frame->retcode[2]); + err |= __put_user(OR_R0_R0, &frame->retcode[3]); + err |= __put_user(OR_R0_R0, &frame->retcode[4]); + err |= __put_user(OR_R0_R0, &frame->retcode[5]); + err |= __put_user(OR_R0_R0, &frame->retcode[6]); + err |= __put_user((__NR_sigreturn), &frame->retcode[7]); regs->pr = (unsigned long) frame->retcode; - err |= __put_user(code, (long *)(frame->retcode+0)); } if (err) @@ -392,6 +395,8 @@ static void setup_frame(int sig, struct /* Set up registers for signal handler */ regs->regs[15] = (unsigned long) frame; regs->regs[4] = signal; /* Arg for signal handler */ + regs->regs[5] = 0; + regs->regs[6] = (unsigned long) &frame->sc; regs->pc = (unsigned long) ka->sa.sa_handler; set_fs(USER_DS); @@ -402,6 +407,8 @@ static void setup_frame(int sig, struct #endif flush_cache_sigtramp(regs->pr); + if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) + flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); return; give_sigsegv: @@ -413,7 +420,7 @@ give_sigsegv: static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { - struct rt_sigframe *frame; + struct rt_sigframe __user *frame; int err = 0; int signal; @@ -428,8 +435,6 @@ static void setup_rt_frame(int sig, stru ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ @@ -449,15 +454,16 @@ static void setup_rt_frame(int sig, stru if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { - /* This is : mov #__NR_rt_sigreturn,r3 ; trapa #0x10 */ -#ifdef __LITTLE_ENDIAN__ - unsigned long code = 0xc310e300 | (__NR_rt_sigreturn); -#else - unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16); -#endif - + /* Generate return code (system call to rt_sigreturn) */ + err |= __put_user(MOVW(7), &frame->retcode[0]); + err |= __put_user(TRAP16, &frame->retcode[1]); + err |= __put_user(OR_R0_R0, &frame->retcode[2]); + err |= __put_user(OR_R0_R0, &frame->retcode[3]); + err |= __put_user(OR_R0_R0, &frame->retcode[4]); + err |= __put_user(OR_R0_R0, &frame->retcode[5]); + err |= __put_user(OR_R0_R0, &frame->retcode[6]); + err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]); regs->pr = (unsigned long) frame->retcode; - err |= __put_user(code, (long *)(frame->retcode+0)); } if (err) @@ -466,6 +472,8 @@ static void setup_rt_frame(int sig, stru /* Set up registers for signal handler */ regs->regs[15] = (unsigned long) frame; regs->regs[4] = signal; /* Arg for signal handler */ + regs->regs[5] = (unsigned long) &frame->info; + regs->regs[6] = (unsigned long) &frame->uc; regs->pc = (unsigned long) ka->sa.sa_handler; set_fs(USER_DS); @@ -476,6 +484,8 @@ static void setup_rt_frame(int sig, stru #endif flush_cache_sigtramp(regs->pr); + if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) + flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); return; give_sigsegv: diff -puN /dev/null arch/sh/kernel/smp.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/kernel/smp.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,207 @@ +/* + * arch/sh/kernel/smp.c + * + * SMP support for the SuperH processors. + * + * Copyright (C) 2002, 2003 Paul Mundt + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * This was written with the Sega Saturn (SMP SH-2 7604) in mind, + * but is designed to be usable regardless if there's an MMU + * present or not. + */ +int smp_threads_ready = 0; +struct sh_cpuinfo cpu_data[NR_CPUS]; + +extern int cpu_idle(void *unused); +extern void per_cpu_trap_init(void); + +cpumask_t cpu_possible_map; +cpumask_t cpu_online_map; +unsigned long cache_decay_ticks = HZ / 100; +static atomic_t cpus_booted = ATOMIC_INIT(0); + +/* These are defined by the board-specific code. */ + +/* + * Cause the function described by call_data to be executed on the passed + * cpu. When the function has finished, increment the finished field of + * call_data. + */ +void __smp_send_ipi(unsigned int cpu, unsigned int action); + +/* + * Find the number of available processors + */ +unsigned int __smp_probe_cpus(void); + +/* + * Start a particular processor + */ +void __smp_slave_init(unsigned int cpu); + +/* + * Run specified function on a particular processor. + */ +void __smp_call_function(unsigned int cpu); + +static inline void __init smp_store_cpu_info(unsigned int cpu) +{ + cpu_data[cpu].loops_per_jiffy = loops_per_jiffy; +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int cpu = smp_processor_id(); + int i; + + atomic_set(&cpus_booted, 1); + smp_store_cpu_info(cpu); + + for (i = 0; i < __smp_probe_cpus(); i++) + cpu_set(i, cpu_possible_map); +} + +void __devinit smp_prepare_boot_cpu(void) +{ + unsigned int cpu = smp_processor_id(); + + cpu_set(cpu, cpu_online_map); + cpu_set(cpu, cpu_possible_map); +} + +int __cpu_up(unsigned int cpu) +{ + struct task_struct *tsk; + struct pt_regs regs; + + memset(®s, 0, sizeof(struct pt_regs)); + tsk = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, 0, 0); + + if (IS_ERR(tsk)) + panic("Failed forking idle task for cpu %d\n", cpu); + + wake_up_forked_process(tsk); + + init_idle(tsk, cpu); + unhash_process(tsk); + + tsk->thread_info->cpu = cpu; + + cpu_set(cpu, cpu_online_map); + + return 0; +} + +int start_secondary(void *unused) +{ + unsigned int cpu = smp_processor_id(); + + atomic_inc(&init_mm.mm_count); + current->active_mm = &init_mm; + + smp_store_cpu_info(cpu); + + __smp_slave_init(cpu); + per_cpu_trap_init(); + + atomic_inc(&cpus_booted); + + return cpu_idle(0); +} + +void __init smp_cpus_done(unsigned int max_cpus) +{ + smp_threads_ready = 1; + smp_mb(); +} + +void smp_send_reschedule(int cpu) +{ + __smp_send_ipi(cpu, SMP_MSG_RESCHEDULE); +} + +static void stop_this_cpu(void *unused) +{ + cpu_clear(smp_processor_id(), cpu_online_map); + local_irq_disable(); + + for (;;) + cpu_relax(); +} + +void smp_send_stop(void) +{ + smp_call_function(stop_this_cpu, 0, 1, 0); +} + + +struct smp_fn_call_struct smp_fn_call = { + .lock = SPIN_LOCK_UNLOCKED, + .finished = ATOMIC_INIT(0), +}; + +/* + * The caller of this wants the passed function to run on every cpu. If wait + * is set, wait until all cpus have finished the function before returning. + * The lock is here to protect the call structure. + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + */ +int smp_call_function(void (*func)(void *info), void *info, int retry, int wait) +{ + unsigned int nr_cpus = atomic_read(&cpus_booted); + int i; + + if (nr_cpus < 2) + return 0; + + spin_lock(&smp_fn_call.lock); + + atomic_set(&smp_fn_call.finished, 0); + smp_fn_call.fn = func; + smp_fn_call.data = info; + + for (i = 0; i < nr_cpus; i++) + if (i != smp_processor_id()) + __smp_call_function(i); + + if (wait) + while (atomic_read(&smp_fn_call.finished) != (nr_cpus - 1)); + + spin_unlock(&smp_fn_call.lock); + + return 0; +} + +/* Not really SMP stuff ... */ +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; +} + diff -puN arch/sh/kernel/sys_sh.c~linus arch/sh/kernel/sys_sh.c --- 25/arch/sh/kernel/sys_sh.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/sys_sh.c 2004-01-19 22:17:21.000000000 -0800 @@ -132,7 +132,7 @@ asmlinkage long sys_mmap2(unsigned long * This is really horribly ugly. */ asmlinkage int sys_ipc(uint call, int first, int second, - int third, void *ptr, long fifth) + int third, void __user *ptr, long fifth) { int version, ret; @@ -142,19 +142,19 @@ asmlinkage int sys_ipc(uint call, int fi if (call <= SEMCTL) switch (call) { case SEMOP: - return sys_semtimedop(first, (struct sembuf *)ptr, + return sys_semtimedop(first, (struct sembuf __user *)ptr, second, NULL); case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf *)ptr, + return sys_semtimedop(first, (struct sembuf __user *)ptr, second, - (const struct timespec *)fifth); + (const struct timespec __user *)fifth); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { union semun fourth; if (!ptr) return -EINVAL; - if (get_user(fourth.__pad, (void **) ptr)) + if (get_user(fourth.__pad, (void * __user *) ptr)) return -EFAULT; return sys_semctl (first, second, third, fourth); } @@ -165,7 +165,7 @@ asmlinkage int sys_ipc(uint call, int fi if (call <= MSGCTL) switch (call) { case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third); case MSGRCV: switch (version) { @@ -175,7 +175,7 @@ asmlinkage int sys_ipc(uint call, int fi return -EINVAL; if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, + (struct ipc_kludge __user *) ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, @@ -183,14 +183,14 @@ asmlinkage int sys_ipc(uint call, int fi } default: return sys_msgrcv (first, - (struct msgbuf *) ptr, + (struct msgbuf __user *) ptr, second, fifth, third); } case MSGGET: return sys_msgget ((key_t) first, second); case MSGCTL: return sys_msgctl (first, second, - (struct msqid_ds *) ptr); + (struct msqid_ds __user *) ptr); default: return -EINVAL; } @@ -200,25 +200,25 @@ asmlinkage int sys_ipc(uint call, int fi switch (version) { default: { ulong raddr; - ret = sys_shmat (first, (char *) ptr, + ret = sys_shmat (first, (char __user *) ptr, second, &raddr); if (ret) return ret; - return put_user (raddr, (ulong *) third); + return put_user (raddr, (ulong __user *) third); } case 1: /* iBCS2 emulator entry point */ if (!segment_eq(get_fs(), get_ds())) return -EINVAL; - return sys_shmat (first, (char *) ptr, + return sys_shmat (first, (char __user *) ptr, second, (ulong *) third); } case SHMDT: - return sys_shmdt ((char *)ptr); + return sys_shmdt ((char __user *)ptr); case SHMGET: return sys_shmget (first, second, third); case SHMCTL: return sys_shmctl (first, second, - (struct shmid_ds *) ptr); + (struct shmid_ds __user *) ptr); default: return -EINVAL; } @@ -252,3 +252,15 @@ asmlinkage ssize_t sys_pwrite_wrapper(un size_t count, loff_t pos); return sys_pwrite64(fd, buf, count, pos); } + +asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, + u32 len0, u32 len1, int advice) +{ +#ifdef __LITTLE_ENDIAN__ + return sys_fadvise64_64(fd, (u64)offset1 << 32 | offset0, + (u64)len1 << 32 | len0, advice); +#else + return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1, + (u64)len0 << 32 | len1, advice); +#endif +} diff -puN arch/sh/kernel/time.c~linus arch/sh/kernel/time.c --- 25/arch/sh/kernel/time.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/time.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.12 2003/06/28 15:35:28 lethal Exp $ +/* $Id: time.c,v 1.18 2003/10/09 16:28:14 lethal Exp $ * * linux/arch/sh/kernel/time.c * @@ -68,7 +68,7 @@ #endif /* CONFIG_CPU_SH3 or CONFIG_CPU_SH4 */ extern unsigned long wall_jiffies; -#define TICK_SIZE (TICK_NSEC / 1000) +#define TICK_SIZE (tick_nsec / 1000) spinlock_t tmu0_lock = SPIN_LOCK_UNLOCKED; u64 jiffies_64 = INITIAL_JIFFIES; @@ -101,6 +101,14 @@ static int pfc_values[] = { 0, 0, 1, 2 #error "Unknown ifc/bfc/pfc/stc values for this processor" #endif +/* + * Scheduler clock - returns current time in nanosec units. + */ +unsigned long long sched_clock(void) +{ + return (unsigned long long)jiffies * (1000000000 / HZ); +} + static unsigned long do_gettimeoffset(void) { int count; @@ -198,7 +206,7 @@ int do_settimeofday(struct timespec *tv) * made, and then undo it! */ nsec -= 1000 * (do_gettimeoffset() + - (jiffies - wall_jiffies) * (1000000 / HZ)); + (jiffies - wall_jiffies) * (1000000 / HZ)); wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec); wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec); @@ -230,7 +238,8 @@ extern char _stext; static inline void sh_do_profile(unsigned long pc) { - if (!prof_buffer) + /* Don't profile cpu_idle.. */ + if (!prof_buffer || !current->pid) return; if (pc >= 0xa0000000UL && pc < 0xc0000000UL) @@ -365,6 +374,19 @@ static unsigned int __init get_timer_fre void (*board_time_init)(void) = 0; void (*board_timer_setup)(struct irqaction *irq) = 0; +static unsigned int sh_pclk_freq __initdata = CONFIG_SH_PCLK_FREQ; + +static int __init sh_pclk_setup(char *str) +{ + unsigned int freq; + + if (get_option(&str, &freq)) + sh_pclk_freq = freq; + + return 1; +} +__setup("sh_pclk=", sh_pclk_setup); + static struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; void get_current_frequency_divisors(unsigned int *ifc, unsigned int *bfc, unsigned int *pfc) @@ -407,23 +429,46 @@ _FREQ_TABLE(pfc); void __init time_init(void) { - unsigned int timer_freq; + unsigned int timer_freq = 0; unsigned int ifc, pfc, bfc; unsigned long interval; if (board_time_init) board_time_init(); - /* - * XXX: Hmm... when cpu/ is proposed, this looks like a good spot for - * it, but we need a rtc to get the timer_freq so board_time_init() - * must always come before a CPU time_(rtc?)_init(). - */ get_current_frequency_divisors(&ifc, &bfc, &pfc); - timer_freq = get_timer_frequency(); + /* + * If we don't have an RTC (such as with the SH7300), don't attempt to + * probe the timer frequency. Rely on an either hardcoded peripheral + * clock value, or on the sh_pclk command line option. + */ + current_cpu_data.module_clock = sh_pclk_freq; - current_cpu_data.module_clock = timer_freq * 4; + /* XXX: Switch this over to a more generic test. */ + if (current_cpu_data.type != CPU_SH7300) { + unsigned int freq; + + /* + * If we've specified a peripheral clock frequency, and we have + * an RTC, compare it against the autodetected value. Complain + * if there's a mismatch. + * + * Note: We should allow for some high and low watermarks for + * the frequency here (compensating for potential drift), as + * otherwise we'll likely end up triggering this essentially + * on every boot. + */ + timer_freq = get_timer_frequency(); + freq = timer_freq * 4; + + if (sh_pclk_freq && sh_pclk_freq != freq) { + printk(KERN_NOTICE "Calculated peripheral clock value " + "%d differs from sh_pclk value %d, fixing..\n", + freq, sh_pclk_freq); + current_cpu_data.module_clock = freq; + } + } rtc_get_time(&xtime); diff -puN arch/sh/kernel/traps.c~linus arch/sh/kernel/traps.c --- 25/arch/sh/kernel/traps.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/kernel/traps.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.7 2003/05/04 19:29:53 lethal Exp $ +/* $Id: traps.c,v 1.14 2003/11/14 18:40:10 lethal Exp $ * * linux/arch/sh/traps.c * @@ -26,12 +26,14 @@ #include #include #include +#include #include #include #include #include #include +#include #ifdef CONFIG_SH_KGDB #include @@ -46,21 +48,36 @@ #define CHK_REMOTE_DEBUG(regs) #endif -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ - unsigned long r6, unsigned long r7, \ - struct pt_regs regs) \ -{ \ - unsigned long error_code; \ - \ - asm volatile("stc r2_bank, %0": "=r" (error_code)); \ - local_irq_enable(); \ - tsk->thread.error_code = error_code; \ - tsk->thread.trap_no = trapnr; \ - CHK_REMOTE_DEBUG(®s); \ - force_sig(signr, tsk); \ - die_if_no_fixup(str,®s,error_code); \ -} +#define DO_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ + unsigned long r6, unsigned long r7, \ + struct pt_regs regs) \ +{ \ + unsigned long error_code; \ + \ + /* Check if it's a DSP instruction */ \ + if (is_dsp_inst(®s)) { \ + /* Enable DSP mode, and restart instruction. */ \ + regs.sr |= SR_DSP; \ + return; \ + } \ + \ + asm volatile("stc r2_bank, %0": "=r" (error_code)); \ + local_irq_enable(); \ + tsk->thread.error_code = error_code; \ + tsk->thread.trap_no = trapnr; \ + CHK_REMOTE_DEBUG(®s); \ + force_sig(signr, tsk); \ + die_if_no_fixup(str,®s,error_code); \ +} + +#ifdef CONFIG_CPU_SH2 +#define TRAP_RESERVED_INST 4 +#define TRAP_ILLEGAL_SLOT_INST 6 +#else +#define TRAP_RESERVED_INST 12 +#define TRAP_ILLEGAL_SLOT_INST 13 +#endif /* * These constants are for searching for possible module text @@ -530,8 +547,37 @@ asmlinkage void do_address_error(struct } } -DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) -DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) +#ifdef CONFIG_SH_DSP +/* + * SH-DSP support gerg@snapgear.com. + */ +int is_dsp_inst(struct pt_regs *regs) +{ + unsigned short inst; + + /* + * Safe guard if DSP mode is already enabled or we're lacking + * the DSP altogether. + */ + if (!test_bit(CPU_HAS_DSP, &(cpu_data->flags)) || (regs->sr & SR_DSP)) + return 0; + + get_user(inst, ((unsigned short *) regs->pc)); + + inst &= 0xf000; + + /* Check for any type of DSP or support instruction */ + if ((inst == 0xf000) || (inst == 0x4000)) + return 1; + + return 0; +} +#else +#define is_dsp_inst(regs) (0) +#endif /* CONFIG_SH_DSP */ + +DO_ERROR(TRAP_RESERVED_INST, SIGILL, "reserved instruction", reserved_inst, current) +DO_ERROR(TRAP_ILLEGAL_SLOT_INST, SIGILL, "illegal slot instruction", illegal_slot_inst, current) asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7, @@ -547,18 +593,18 @@ void *gdb_vbr_vector; static inline void __init gdb_vbr_init(void) { - /* + register unsigned long vbr; + + /* * Read the old value of the VBR register to initialise * the vector through which debug and BIOS traps are * delegated by the Linux trap handler. */ - { - register unsigned long vbr; - asm volatile("stc vbr, %0" : "=r" (vbr)); - gdb_vbr_vector = (void *)(vbr + 0x100); - printk("Setting GDB trap vector to 0x%08lx\n", - (unsigned long)gdb_vbr_vector); - } + asm volatile("stc vbr, %0" : "=r" (vbr)); + + gdb_vbr_vector = (void *)(vbr + 0x100); + printk("Setting GDB trap vector to 0x%08lx\n", + (unsigned long)gdb_vbr_vector); } #endif @@ -582,11 +628,24 @@ void __init per_cpu_trap_init(void) void __init trap_init(void) { - extern void *exception_handling_table[14]; - - exception_handling_table[12] = (void *)do_reserved_inst; - exception_handling_table[13] = (void *)do_illegal_slot_inst; + extern void *exception_handling_table[]; + exception_handling_table[TRAP_RESERVED_INST] + = (void *)do_reserved_inst; + exception_handling_table[TRAP_ILLEGAL_SLOT_INST] + = (void *)do_illegal_slot_inst; + +#ifdef CONFIG_CPU_SH4 + if (!test_bit(CPU_HAS_FPU, &(cpu_data->flags))) { + /* For SH-4 lacking an FPU, treat floating point instructions + as reserved. */ + /* entry 64 corresponds to EXPEVT=0x800 */ + exception_handling_table[64] = (void *)do_reserved_inst; + exception_handling_table[65] = (void *)do_illegal_slot_inst; + } +#endif + + /* Setup VBR for boot cpu */ per_cpu_trap_init(); } @@ -595,7 +654,6 @@ void show_stack(struct task_struct *tsk, unsigned long *stack, addr; unsigned long module_start = VMALLOC_START; unsigned long module_end = VMALLOC_END; - extern long _text, _etext; int i = 1; if (!sp) { @@ -612,19 +670,25 @@ void show_stack(struct task_struct *tsk, stack = sp; printk("\nCall trace: "); +#ifdef CONFIG_KALLSYMS + printk("\n"); +#endif - while (((long)stack & (THREAD_SIZE - 1))) { + while (!kstack_end(stack)) { addr = *stack++; - if (((addr >= (unsigned long)&_text) && - (addr <= (unsigned long)&_etext)) || + if (((addr >= (unsigned long)_text) && + (addr <= (unsigned long)_etext)) || ((addr >= module_start) && (addr <= module_end))) { /* * For 80-columns display, 6 entry is maximum. * NOTE: '[<8c00abcd>] ' consumes 13 columns . */ +#ifndef CONFIG_KALLSYMS if (i && ((i % 6) == 0)) printk("\n "); +#endif printk("[<%08lx>] ", addr); + print_symbol("%s\n", addr); i++; } } diff -puN /dev/null arch/sh/lib/div64-generic.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/lib/div64-generic.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,19 @@ +/* + * Generic __div64_32 wrapper for __xdiv64_32. + */ + +#include + +extern u64 __xdiv64_32(u64 n, u32 d); + +u64 __div64_32(u64 *xp, u32 y) +{ + u64 rem; + u64 q = __xdiv64_32(*xp, y); + + rem = *xp - q * y; + *xp = q; + + return rem; +} + diff -puN arch/sh/lib/div64.S~linus arch/sh/lib/div64.S --- 25/arch/sh/lib/div64.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/lib/div64.S 2004-01-19 22:17:21.000000000 -0800 @@ -1,11 +1,11 @@ /* - * unsigned long long __div64_32(unsigned long long n, unsigned long d); + * unsigned long long __xdiv64_32(unsigned long long n, unsigned long d); */ #include .text -ENTRY(__div64_32) +ENTRY(__xdiv64_32) #ifdef __LITTLE_ENDIAN__ mov r4, r0 mov r5, r1 diff -puN arch/sh/lib/Makefile~linus arch/sh/lib/Makefile --- 25/arch/sh/lib/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/lib/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -3,4 +3,5 @@ # lib-y = delay.o memcpy.o memset.o memmove.o memchr.o \ - checksum.o strcasecmp.o strlen.o div64.o udivdi3.o + checksum.o strcasecmp.o strlen.o div64.o udivdi3.o \ + div64-generic.o diff -puN arch/sh/lib/udivdi3.c~linus arch/sh/lib/udivdi3.c --- 25/arch/sh/lib/udivdi3.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/lib/udivdi3.c 2004-01-19 22:17:21.000000000 -0800 @@ -4,13 +4,13 @@ #include -extern u64 __div64_32(u64 n, u32 d); +extern u64 __xdiv64_32(u64 n, u32 d); extern void panic(const char * fmt, ...); u64 __udivdi3(u64 n, u64 d) { if (d & ~0xffffffff) panic("Need true 64-bit/64-bit division"); - return __div64_32(n, (u32)d); + return __xdiv64_32(n, (u32)d); } diff -puN arch/sh/Makefile~linus arch/sh/Makefile --- 25/arch/sh/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.17 2003/05/20 03:12:54 lethal Exp $ +# $Id: Makefile,v 1.32 2003/10/26 23:33:49 lethal Exp $ # # 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 @@ -25,20 +25,20 @@ ifndef include_config -include .config endif -cpu-y := -mb -cpu-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml +cflags-y := -mb +cflags-$(CONFIG_CPU_LITTLE_ENDIAN) := -ml -cpu-$(CONFIG_CPU_SH2) += -m2 -cpu-$(CONFIG_CPU_SH3) += -m3 -cpu-$(CONFIG_CPU_SH4) += -m4 -mno-implicit-fp - -ifdef CONFIG_SH_KGDB -CFLAGS :=$(CFLAGS:-fomit-frame-pointer=) -g -AFLAGS += -g -ifdef CONFIG_KGDB_MORE -CFLAGS += $(shell echo $(CONFIG_KGDB_OPTIONS) | sed -e 's/"//g') -endif -endif +cflags-$(CONFIG_CPU_SH2) += -m2 +cflags-$(CONFIG_CPU_SH3) += -m3 +cflags-$(CONFIG_CPU_SH4) += -m4 \ + $(call check_gcc,-mno-implicit-fp,-m4-nofpu) + +cflags-$(CONFIG_SH_DSP) += -Wa,-dsp +cflags-$(CONFIG_SH_KGDB) += -g +cflags-$(CONFIG_EMBEDDED) += -Os + +cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \ + $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S @@ -49,13 +49,15 @@ OBJCOPYFLAGS := -O binary -R .note -R .c LDFLAGS_vmlinux += -e _stext ifdef CONFIG_CPU_LITTLE_ENDIAN -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' -EL +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' +LDFLAGS += -EL else -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' -EB +LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' +LDFLAGS += -EB endif -CFLAGS += -pipe $(cpu-y) -AFLAGS += $(cpu-y) +CFLAGS += -pipe $(cflags-y) +AFLAGS += $(cflags-y) head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o @@ -66,6 +68,7 @@ core-y += arch/sh/kernel/ arch/sh/mm/ # Boards machdir-$(CONFIG_SH_SOLUTION_ENGINE) := se/770x machdir-$(CONFIG_SH_7751_SOLUTION_ENGINE) := se/7751 +machdir-$(CONFIG_SH_7751_SYSTEMH) := systemh machdir-$(CONFIG_SH_STB1_HARP) := harp machdir-$(CONFIG_SH_STB1_OVERDRIVE) := overdrive machdir-$(CONFIG_SH_HP620) := hp6xx/hp620 @@ -81,6 +84,7 @@ machdir-$(CONFIG_SH_BIGSUR) := bigsur machdir-$(CONFIG_SH_SH2000) := sh2000 machdir-$(CONFIG_SH_ADX) := adx machdir-$(CONFIG_SH_MPC1211) := mpc1211 +machdir-$(CONFIG_SH_SECUREEDGE5410) := snapgear machdir-$(CONFIG_SH_UNKNOWN) := unknown incdir-y := $(machdir-y) @@ -99,7 +103,10 @@ cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 -libs-y += arch/sh/lib/ $(LIBGCC) +libs-y := arch/sh/lib/ $(libs-y) $(LIBGCC) + +drivers-y += arch/sh/drivers/ +drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ boot := arch/sh/boot @@ -110,18 +117,36 @@ prepare: target_links .PHONY: target_links FORCE target_links: @echo ' Making asm-sh/cpu -> asm-sh/$(cpuincdir-y) link' + @rm -f include/asm-sh/cpu @ln -sf $(cpuincdir-y) include/asm-sh/cpu @echo ' Making asm-sh/mach -> asm-sh/$(incdir-y) link' + @rm -f include/asm-sh/mach @ln -sf $(incdir-y) include/asm-sh/mach $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h -BOOTIMAGE=arch/sh/boot/zImage zImage: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(BOOTIMAGE) + $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ compressed: zImage archclean: $(Q)$(MAKE) $(clean)=$(boot) + +defconfig-%: + @echo ' Copying arch/sh/configs/$@ -> .config' + @if [ -e .config ]; then mv -f .config .config.old; fi + @cp -f arch/sh/configs/$@ .config + @chmod 644 .config + +define archhelp + @echo ' zImage - Compressed kernel image (arch/sh/boot/zImage)' + for board in arch/sh/configs/*; \ + do \ + echo -n ' ' $$board | sed -e 's|arch/sh/configs/||g' ; \ + echo -n ' - Build for ' ; \ + echo -e $$board | sed -e 's|.*-||g'; \ + done +endef + diff -puN arch/sh/mm/cache-sh3.c~linus arch/sh/mm/cache-sh3.c --- 25/arch/sh/mm/cache-sh3.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/cache-sh3.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: cache-sh3.c,v 1.5 2003/05/06 23:28:48 lethal Exp $ +/* $Id: cache-sh3.c,v 1.7 2003/08/28 16:16:09 lethal Exp $ * * linux/arch/sh/mm/cache-sh3.c * @@ -70,6 +70,8 @@ detect_cpu_and_cache_system(void) cpu_data->dcache.entry_mask = 0x7f0; cpu_data->dcache.sets = 128; cpu_data->type = CPU_SH7708; + + set_bit(CPU_HAS_MMU_PAGE_ASSOC, &(cpu_data->flags)); } else { /* 7709A or 7729 */ cpu_data->dcache.way_shift = 12; cpu_data->dcache.entry_mask = 0xff0; @@ -77,9 +79,9 @@ detect_cpu_and_cache_system(void) cpu_data->type = CPU_SH7729; } - /* + /* * SH-3 doesn't have separate caches - */ + */ cpu_data->dcache.flags |= SH_CACHE_COMBINED; cpu_data->icache = cpu_data->dcache; diff -puN arch/sh/mm/cache-sh4.c~linus arch/sh/mm/cache-sh4.c --- 25/arch/sh/mm/cache-sh4.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/cache-sh4.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: cache-sh4.c,v 1.20 2003/05/10 03:22:05 sugioka Exp $ +/* $Id: cache-sh4.c,v 1.24 2003/10/12 19:40:12 lethal Exp $ * * linux/arch/sh/mm/cache-sh4.c * @@ -26,10 +26,7 @@ extern void __flush_cache_4096_all(unsig static void __flush_cache_4096_all_ex(unsigned long start); extern void __flush_dcache_all(void); static void __flush_dcache_all_ex(void); -/* - * FIXME: Add ST40STB1 probe support (and clean up the manual overdrive stuff) - * seems to rely on some quirky PVR shifting .. stuart? ++paulm - */ + int __init detect_cpu_and_cache_system(void) { unsigned long pvr, prr, ccr; @@ -37,9 +34,9 @@ int __init detect_cpu_and_cache_system(v pvr = (ctrl_inl(CCN_PVR) >> 8) & 0xffff; prr = (ctrl_inl(CCN_PRR) >> 4) & 0xff; - /* + /* * Setup some sane SH-4 defaults for the icache - */ + */ cpu_data->icache.way_shift = 13; cpu_data->icache.entry_shift = 5; cpu_data->icache.entry_mask = 0x1fe0; @@ -64,9 +61,17 @@ int __init detect_cpu_and_cache_system(v switch (pvr) { case 0x205: cpu_data->type = CPU_SH7750; + set_bit(CPU_HAS_P2_FLUSH_BUG, &(cpu_data->flags)); break; case 0x206: cpu_data->type = CPU_SH7750S; + + /* + * FIXME: This is needed for 7750, but do we need it for the + * 7750S and 7750R too? For now, assume we do.. -- PFM + */ + set_bit(CPU_HAS_P2_FLUSH_BUG, &(cpu_data->flags)); + break; case 0x1100: cpu_data->type = CPU_SH7751; @@ -77,28 +82,46 @@ int __init detect_cpu_and_cache_system(v case 0x8100: cpu_data->type = CPU_ST40GX1; break; - case 0x500: - if (prr == 0x10) - cpu_data->type = CPU_SH7750R; - else - cpu_data->type = CPU_SH7751R; + case 0x700: + /* XXX: Add proper CVR probing */ + cpu_data->type = CPU_SH4_501; + break; + case 0x600: + cpu_data->type = CPU_SH4_202; + /* fall */ + case 0x500 ... 0x501: + switch (prr) { + case 0x10: cpu_data->type = CPU_SH7750R; break; + case 0x11: cpu_data->type = CPU_SH7751R; break; + case 0x50: cpu_data->type = CPU_SH7760; break; + } + + if (cpu_data->type == CPU_SH7750R) + set_bit(CPU_HAS_P2_FLUSH_BUG, &(cpu_data->flags)); + jump_to_P2(); ccr = ctrl_inl(CCR); - back_to_P1(); - if(ccr & CCR_CACHE_EMODE) { - cpu_data->icache.ways = 2; - cpu_data->dcache.ways = 2; + + /* Force EMODE */ + if (!(ccr & CCR_CACHE_EMODE)) { + ccr |= CCR_CACHE_EMODE; + ctrl_outl(ccr, CCR); } + + back_to_P1(); + + cpu_data->icache.ways = 2; + cpu_data->dcache.ways = 2; + break; default: cpu_data->type = CPU_SH_NONE; break; } - /* - * For now, all SH-4's have an FPU .. - */ - cpu_data->flags |= CPU_HAS_FPU; + /* No FPU on the SH4-500 series.. */ + if (cpu_data->type != CPU_SH4_501) + set_bit(CPU_HAS_FPU, &(cpu_data->flags)); return 0; } @@ -257,20 +280,16 @@ static inline void flush_cache_4096(unsi unsigned long flags; extern void __flush_cache_4096(unsigned long addr, unsigned long phys, unsigned long exec_offset); - /* + /* * SH7751, SH7751R, and ST40 have no restriction to handle cache. - * (While SH7750 must do that at P2 area.) - */ - if ((cpu_data->type == CPU_SH7751 || - cpu_data->type == CPU_SH7751R || - cpu_data->type == CPU_ST40RA || - cpu_data->type == CPU_ST40GX1) && - (start >= CACHE_OC_ADDRESS_ARRAY)) { - __flush_cache_4096(start | SH_CACHE_ASSOC, phys | 0x80000000, 0); - } else { + * (While SH7750 must do that at P2 area.) + */ + if (test_bit(CPU_HAS_P2_FLUSH_BUG, &(cpu_data->flags))) { local_irq_save(flags); __flush_cache_4096(start | SH_CACHE_ASSOC, phys | 0x80000000, 0x20000000); local_irq_restore(flags); + } else if (start >= CACHE_OC_ADDRESS_ARRAY) { + __flush_cache_4096(start | SH_CACHE_ASSOC, phys | 0x80000000, 0); } } diff -puN arch/sh/mm/clear_page.S~linus arch/sh/mm/clear_page.S --- 25/arch/sh/mm/clear_page.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/clear_page.S 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: clear_page.S,v 1.12 2003/05/10 03:22:05 sugioka Exp $ +/* $Id: clear_page.S,v 1.13 2003/08/25 17:03:10 lethal Exp $ * * __clear_user_page, __clear_user, clear_page implementation of SuperH * @@ -10,10 +10,10 @@ #include /* - * clear_page + * clear_page_slow * @to: P1 address * - * void clear_page(void *to) + * void clear_page_slow(void *to) */ /* @@ -21,7 +21,7 @@ * r4 --- to * r5 --- to + 4096 */ -ENTRY(clear_page) +ENTRY(clear_page_slow) mov r4,r5 mov.w .Llimit,r0 add r0,r5 diff -puN -L arch/sh/mm/__clear_user_page-sh4.S arch/sh/mm/__clear_user_page-sh4.S~linus /dev/null --- 25/arch/sh/mm/__clear_user_page-sh4.S +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,49 +0,0 @@ -/* $Id$ - * - * __clear_user_page implementation of SuperH - * - * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima - * - */ - -/* - * __clear_user_page - * @to: P1 address (with same color) - * @orig_to: P1 address - * - * void __clear_user_page(void *to, void *orig_to) - */ - -/* - * r0 --- scratch - * r4 --- to - * r5 --- orig_to - * r6 --- to + 4096 - */ -#include -ENTRY(__clear_user_page) - mov r4,r6 - mov.w .L4096,r0 - add r0,r6 - mov #0,r0 - ! -1: ocbi @r5 - add #32,r5 - movca.l r0,@r4 - mov r4,r1 - add #32,r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - add #28,r4 - cmp/eq r6,r4 - bf/s 1b - ocbwb @r1 - ! - rts - nop -.L4096: .word 4096 diff -puN arch/sh/mm/copy_page.S~linus arch/sh/mm/copy_page.S --- 25/arch/sh/mm/copy_page.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/copy_page.S 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: copy_page.S,v 1.7 2003/05/04 19:29:54 lethal Exp $ +/* $Id: copy_page.S,v 1.8 2003/08/25 17:03:10 lethal Exp $ * * copy_page, __copy_user_page, __copy_user implementation of SuperH * @@ -9,11 +9,11 @@ #include /* - * copy_page + * copy_page_slow * @to: P1 address * @from: P1 address * - * void copy_page(void *to, void *from) + * void copy_page_slow(void *to, void *from) */ /* @@ -23,7 +23,7 @@ * r10 --- to * r11 --- from */ -ENTRY(copy_page) +ENTRY(copy_page_slow) mov.l r8,@-r15 mov.l r10,@-r15 mov.l r11,@-r15 diff -puN -L arch/sh/mm/__copy_user_page-sh4.S arch/sh/mm/__copy_user_page-sh4.S~linus /dev/null --- 25/arch/sh/mm/__copy_user_page-sh4.S +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,69 +0,0 @@ -/* $Id: __copy_user_page-sh4.S,v 1.1 2001/07/23 09:02:17 gniibe Exp $ - * - * __copy_user_page implementation of SuperH - * - * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima - * - */ - -/* - * __copy_user_page - * @to: P1 address (with same color) - * @from: P1 address - * @orig_to: P1 address - * - * void __copy_user_page(void *to, void *from, void *orig_to) - */ - -/* - * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + 4096 - * r9 --- orig_to - * r10 --- to - * r11 --- from - */ -#include -ENTRY(__copy_user_page) - mov.l r8,@-r15 - mov.l r9,@-r15 - mov.l r10,@-r15 - mov.l r11,@-r15 - mov r4,r10 - mov r5,r11 - mov r6,r9 - mov r5,r8 - mov.w .L4096,r0 - add r0,r8 - ! -1: ocbi @r9 - add #32,r9 - mov.l @r11+,r0 - mov.l @r11+,r1 - mov.l @r11+,r2 - mov.l @r11+,r3 - mov.l @r11+,r4 - mov.l @r11+,r5 - mov.l @r11+,r6 - mov.l @r11+,r7 - movca.l r0,@r10 - mov r10,r0 - add #32,r10 - mov.l r7,@-r10 - mov.l r6,@-r10 - mov.l r5,@-r10 - mov.l r4,@-r10 - mov.l r3,@-r10 - mov.l r2,@-r10 - mov.l r1,@-r10 - ocbwb @r0 - cmp/eq r11,r8 - bf/s 1b - add #28,r10 - ! - mov.l @r15+,r11 - mov.l @r15+,r10 - mov.l @r15+,r9 - mov.l @r15+,r8 - rts - nop -.L4096: .word 4096 diff -puN arch/sh/mm/extable.c~linus arch/sh/mm/extable.c --- 25/arch/sh/mm/extable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/extable.c 2004-01-19 22:17:21.000000000 -0800 @@ -9,29 +9,6 @@ #include #include -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - - return NULL; -} - int fixup_exception(struct pt_regs *regs) { const struct exception_table_entry *fixup; diff -puN arch/sh/mm/fault.c~linus arch/sh/mm/fault.c --- 25/arch/sh/mm/fault.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/fault.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,7 +1,8 @@ -/* $Id: fault.c,v 1.10 2003/05/04 19:29:54 lethal Exp $ +/* $Id: fault.c,v 1.13 2003/08/11 11:44:50 lethal Exp $ * * linux/arch/sh/mm/fault.c * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt * * Based on linux/arch/i386/mm/fault.c: * Copyright (C) 1995 Linus Torvalds @@ -28,10 +29,7 @@ #include #include #include - -#if defined(CONFIG_SH_KGDB) #include -#endif extern void die(const char *,struct pt_regs *,long); @@ -47,11 +45,10 @@ asmlinkage void do_page_fault(struct pt_ struct mm_struct *mm; struct vm_area_struct * vma; unsigned long page; - const struct exception_table_entry *fixup; -#if defined(CONFIG_SH_KGDB) +#ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); + kgdb_bus_err_hook(); #endif tsk = current; @@ -61,7 +58,7 @@ asmlinkage void do_page_fault(struct pt_ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; down_read(&mm->mmap_sem); @@ -95,16 +92,18 @@ good_area: */ survive: switch (handle_mm_fault(mm, vma, address, writeaccess)) { - case 1: - tsk->min_flt++; - break; - case 2: - tsk->maj_flt++; - break; - case 0: - goto do_sigbus; - default: - goto out_of_memory; + case VM_FAULT_MINOR: + tsk->min_flt++; + break; + case VM_FAULT_MAJOR: + tsk->maj_flt++; + break; + case VM_FAULT_SIGBUS: + goto do_sigbus; + case VM_FAULT_OOM: + goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); @@ -126,11 +125,8 @@ bad_area: no_context: /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; + if (fixup_exception(regs)) return; - } /* * Oops. The kernel tried to access some bad page. We'll have to @@ -198,16 +194,22 @@ do_sigbus: asmlinkage int __do_page_fault(struct pt_regs *regs, unsigned long writeaccess, unsigned long address) { + unsigned long addrmax = P4SEG; pgd_t *dir; pmd_t *pmd; pte_t *pte; pte_t entry; -#if defined(CONFIG_SH_KGDB) +#ifdef CONFIG_SH_KGDB if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); + kgdb_bus_err_hook(); +#endif + +#ifdef CONFIG_SH_STORE_QUEUES + addrmax = P4SEG_STORE_QUE + 0x04000000; #endif - if (address >= P3SEG && address < P4SEG) + + if (address >= P3SEG && address < addrmax) dir = pgd_offset_k(address); else if (address >= TASK_SIZE) return 1; @@ -233,15 +235,19 @@ asmlinkage int __do_page_fault(struct pt if (writeaccess) entry = pte_mkdirty(entry); entry = pte_mkyoung(entry); -#if defined(CONFIG_CPU_SH4) + +#ifdef CONFIG_CPU_SH4 /* * ITLB is not affected by "ldtlb" instruction. * So, we need to flush the entry by ourselves. */ + __flush_tlb_page(get_asid(), address&PAGE_MASK); #endif + set_pte(pte, entry); update_mmu_cache(NULL, address, entry); + return 0; } diff -puN arch/sh/mm/init.c~linus arch/sh/mm/init.c --- 25/arch/sh/mm/init.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/init.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.11 2003/05/27 16:21:23 lethal Exp $ +/* $Id: init.c,v 1.18 2003/10/31 09:26:59 kkojima Exp $ * * linux/arch/sh/mm/init.c * @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -55,6 +56,9 @@ pg_data_t discontig_page_data[MAX_NUMNOD bootmem_data_t discontig_node_bdata[MAX_NUMNODES]; #endif +void (*copy_page)(void *from, void *to); +void (*clear_page)(void *to); + void show_mem(void) { int i, total = 0, reserved = 0; @@ -112,13 +116,13 @@ void __init paging_init(void) { unsigned long max_dma, low, start_pfn; pgd_t *pg_dir; - int i; + int i; - /* We don't need kernel mapping as hardware support that. */ - pg_dir = swapper_pg_dir; + /* We don't need kernel mapping as hardware support that. */ + pg_dir = swapper_pg_dir; for (i = 0; i < PTRS_PER_PGD; i++) - pgd_val(pg_dir[i]) = 0; + pgd_val(pg_dir[i]) = 0; /* Turn on the MMU */ enable_mmu(); @@ -130,11 +134,13 @@ void __init paging_init(void) if (low < max_dma) { zones_size[ZONE_DMA] = low - start_pfn; + zones_size[ZONE_NORMAL] = 0; } else { zones_size[ZONE_DMA] = max_dma - start_pfn; zones_size[ZONE_NORMAL] = low - max_dma; } } + #elif defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) /* * If we don't have CONFIG_MMU set and the processor in question @@ -149,17 +155,17 @@ void __init paging_init(void) disable_mmu(); #endif - free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); + free_area_init_node(0, NODE_DATA(0), 0, zones_size, __MEMORY_START >> PAGE_SHIFT, 0); /* XXX: MRB-remove - this doesn't seem sane, should this be done somewhere else ?*/ - mem_map = NODE_DATA(0)->node_mem_map; + mem_map = NODE_DATA(0)->node_mem_map; #ifdef CONFIG_DISCONTIGMEM /* * And for discontig, do some more fixups on the zone sizes.. */ - zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; - zones_size[ZONE_NORMAL] = 0; - free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); + zones_size[ZONE_DMA] = __MEMORY_SIZE_2ND >> PAGE_SHIFT; + zones_size[ZONE_NORMAL] = 0; + free_area_init_node(1, NODE_DATA(1), 0, zones_size, __MEMORY_START_2ND >> PAGE_SHIFT, 0); #endif } @@ -183,6 +189,13 @@ void __init mem_init(void) memset(empty_zero_page, 0, PAGE_SIZE); __flush_wback_region(empty_zero_page, PAGE_SIZE); + /* + * Setup wrappers for copy/clear_page(), these will get overridden + * later in the boot process if a better method is available. + */ + copy_page = copy_page_slow; + clear_page = clear_page_slow; + /* this will put all low memory onto the freelists */ totalram_pages += free_all_bootmem_node(NODE_DATA(0)); #ifdef CONFIG_DISCONTIGMEM @@ -195,6 +208,7 @@ void __init mem_init(void) */ if (PageReserved(mem_map+tmp)) reservedpages++; + codesize = (unsigned long) &_etext - (unsigned long) &_text; datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; @@ -238,75 +252,3 @@ void free_initrd_mem(unsigned long start } #endif -/* - * Generic first-level cache init - */ -void __init sh_cache_init(void) -{ - extern int detect_cpu_and_cache_system(void); - unsigned long ccr, flags = 0; - - detect_cpu_and_cache_system(); - - if (cpu_data->type == CPU_SH_NONE) - panic("Unknown CPU"); - - jump_to_P2(); - ccr = ctrl_inl(CCR); - - /* - * If the cache is already enabled .. flush it. - */ - if (ccr & CCR_CACHE_ENABLE) { - unsigned long entries, i, j; - - entries = cpu_data->dcache.sets; - - /* - * If the OC is already in RAM mode, we only have - * half of the entries to flush.. - */ - if (ccr & CCR_CACHE_ORA) - entries >>= 1; - - for (i = 0; i < entries; i++) { - for (j = 0; j < cpu_data->dcache.ways; j++) { - unsigned long data, addr; - - addr = CACHE_OC_ADDRESS_ARRAY | - (j << cpu_data->dcache.way_shift) | - (i << cpu_data->dcache.entry_shift); - - data = ctrl_inl(addr); - - if ((data & (SH_CACHE_UPDATED | SH_CACHE_VALID)) - == (SH_CACHE_UPDATED | SH_CACHE_VALID)) - ctrl_outl(data & ~SH_CACHE_UPDATED, addr); - } - } - } - - /* - * Default CCR values .. enable the caches - * and flush them immediately.. - */ - flags |= CCR_CACHE_ENABLE | CCR_CACHE_INVALIDATE | (ccr & CCR_CACHE_EMODE); - -#ifdef CONFIG_SH_WRITETHROUGH - /* Turn on Write-through caching */ - flags |= CCR_CACHE_WT; -#else - /* .. or default to Write-back */ - flags |= CCR_CACHE_CB; -#endif - -#ifdef CONFIG_SH_OCRAM - /* Turn on OCRAM -- halve the OC */ - flags |= CCR_CACHE_ORA; - cpu_data->dcache.sets >>= 1; -#endif - - ctrl_outl(flags, CCR); - back_to_P1(); -} - diff -puN arch/sh/mm/ioremap.c~linus arch/sh/mm/ioremap.c --- 25/arch/sh/mm/ioremap.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/ioremap.c 2004-01-19 22:17:21.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: ioremap.c,v 1.6 2003/05/04 19:29:55 lethal Exp $ +/* $Id: ioremap.c,v 1.8 2003/10/09 15:25:42 lethal Exp $ * * arch/sh/mm/ioremap.c * @@ -140,7 +140,7 @@ void * p3_ioremap(unsigned long phys_add */ offset = phys_addr & ~PAGE_MASK; phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr) - phys_addr; + size = PAGE_ALIGN(last_addr+1) - phys_addr; /* * Ok, go for it.. @@ -148,9 +148,10 @@ void * p3_ioremap(unsigned long phys_add area = get_vm_area(size, VM_IOREMAP); if (!area) return NULL; + area->phys_addr = phys_addr; addr = area->addr; if (remap_area_pages((unsigned long) addr, phys_addr, size, flags)) { - vfree(addr); + vunmap(addr); return NULL; } return (void *) (offset + (char *)addr); diff -puN arch/sh/mm/Makefile~linus arch/sh/mm/Makefile --- 25/arch/sh/mm/Makefile~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -2,14 +2,16 @@ # Makefile for the Linux SuperH-specific parts of the memory manager. # -obj-y := init.o extable.o clear_page.o copy_page.o +obj-y := init.o extable.o obj-$(CONFIG_CPU_SH2) += cache-sh2.o -obj-$(CONFIG_CPU_SH3) += cache-sh3.o +obj-$(CONFIG_CPU_SH3) += cache-sh3.o obj-$(CONFIG_CPU_SH4) += cache-sh4.o pg-sh4.o -mmu-y := fault-nommu.o tlb-nommu.o -mmu-$(CONFIG_MMU) := fault.o +obj-$(CONFIG_DMA_PAGE_OPS) += pg-dma.o + +mmu-y := fault-nommu.o tlb-nommu.o pg-nommu.o +mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o obj-y += $(mmu-y) diff -puN /dev/null arch/sh/mm/pg-dma.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/mm/pg-dma.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,97 @@ +/* + * arch/sh/mm/pg-dma.c + * + * Fast clear_page()/copy_page() implementation using the SH DMAC + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Channel to use for page ops, must be dual-address mode capable. */ +static int dma_channel = 3; + +static void copy_page_dma(void *to, void *from) +{ + /* + * This doesn't seem to get triggered until further along in the + * boot process, at which point the DMAC is already initialized. + * Fix this in the same fashion as clear_page_dma() in the event + * that this crashes due to the DMAC not being initialized. + */ + + flush_icache_range((unsigned long)from, PAGE_SIZE); + dma_write_page(dma_channel, (unsigned long)from, (unsigned long)to); + dma_wait_for_completion(dma_channel); +} + +static void clear_page_dma(void *to) +{ + extern unsigned long empty_zero_page[1024]; + + /* + * We get invoked quite early on, if the DMAC hasn't been initialized + * yet, fall back on the slow manual implementation. + */ + if (dma_info[dma_channel].chan != dma_channel) { + clear_page_slow(to); + return; + } + + dma_write_page(dma_channel, (unsigned long)empty_zero_page, + (unsigned long)to); + + /* + * FIXME: Something is a bit racy here, if we poll the counter right + * away, we seem to lock. flushing the page from the dcache doesn't + * seem to make a difference one way or the other, though either a full + * icache or dcache flush does. + * + * The location of this is important as well, and must happen prior to + * the completion loop but after the transfer was initiated. + * + * Oddly enough, this doesn't appear to be an issue for copy_page().. + */ + flush_icache_range((unsigned long)to, PAGE_SIZE); + + dma_wait_for_completion(dma_channel); +} + +static int __init pg_dma_init(void) +{ + int ret; + + ret = request_dma(dma_channel, "page ops"); + if (ret != 0) + return ret; + + copy_page = copy_page_dma; + clear_page = clear_page_dma; + + return ret; +} + +static void __exit pg_dma_exit(void) +{ + free_dma(dma_channel); +} + +module_init(pg_dma_init); +module_exit(pg_dma_exit); + +MODULE_AUTHOR("Paul Mundt "); +MODULE_DESCRIPTION("Optimized page copy/clear routines using a dual-address mode capable DMAC channel"); +MODULE_LICENSE("GPL"); + diff -puN /dev/null arch/sh/mm/pg-nommu.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/mm/pg-nommu.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,36 @@ +/* + * arch/sh/mm/pg-nommu.c + * + * clear_page()/copy_page() implementation for MMUless SH. + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include + +static void copy_page_nommu(void *to, void *from) +{ + memcpy(to, from, PAGE_SIZE); +} + +static void clear_page_nommu(void *to) +{ + memset(to, 0, PAGE_SIZE); +} + +static int __init pg_nommu_init(void) +{ + copy_page = copy_page_nommu; + clear_page = clear_page_nommu; + + return 0; +} + +subsys_initcall(pg_nommu_init); + diff -puN arch/sh/mm/tlb-sh3.c~linus arch/sh/mm/tlb-sh3.c --- 25/arch/sh/mm/tlb-sh3.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/mm/tlb-sh3.c 2004-01-19 22:17:21.000000000 -0800 @@ -61,6 +61,7 @@ void update_mmu_cache(struct vm_area_str void __flush_tlb_page(unsigned long asid, unsigned long page) { unsigned long addr, data; + int i, ways = MMU_NTLB_WAYS; /* * NOTE: PTEH.ASID should be set to this MM @@ -68,8 +69,15 @@ void __flush_tlb_page(unsigned long asid * * It would be simple if we didn't need to set PTEH.ASID... */ - addr = MMU_TLB_ADDRESS_ARRAY |(page & 0x1F000)| MMU_PAGE_ASSOC_BIT; + addr = MMU_TLB_ADDRESS_ARRAY | (page & 0x1F000); data = (page & 0xfffe0000) | asid; /* VALID bit is off */ - ctrl_outl(data, addr); + + if (test_bit(CPU_HAS_MMU_PAGE_ASSOC, &(cpu_data->flags))) { + addr |= MMU_PAGE_ASSOC_BIT; + ways = 1; /* we already know the way .. */ + } + + for (i = 0; i < ways; i++) + ctrl_outl(data, addr + (i << 8)); } diff -puN /dev/null arch/sh/oprofile/Kconfig --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/oprofile/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff -puN /dev/null arch/sh/oprofile/Makefile --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/oprofile/Makefile 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,13 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +profdrvr-y := op_model_null.o +profdrvr-$(CONFIG_SH_DREAMCAST) := op_model_dreamcast.o + +oprofile-y := $(DRIVER_OBJS) $(profdrvr-y) + diff -puN /dev/null arch/sh/oprofile/op_model_null.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/arch/sh/oprofile/op_model_null.c 2004-01-19 22:17:21.000000000 -0800 @@ -0,0 +1,23 @@ +/* + * arch/sh/oprofile/op_model_null.c + * + * Copyright (C) 2003 Paul Mundt + * + * 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. + */ +#include +#include +#include +#include + +int __init oprofile_arch_init(struct oprofile_operations **ops) +{ + return -ENODEV; +} + +void oprofile_arch_exit(void) +{ +} + diff -puN arch/sh/tools/mach-types~linus arch/sh/tools/mach-types --- 25/arch/sh/tools/mach-types~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sh/tools/mach-types 2004-01-19 22:17:21.000000000 -0800 @@ -7,6 +7,7 @@ # SE SH_SOLUTION_ENGINE 7751SE SH_7751_SOLUTION_ENGINE +7751SYSTEMH SH_7751_SYSTEMH HP600 SH_HP600 HP620 SH_HP620 HP680 SH_HP680 @@ -19,4 +20,5 @@ DREAMCAST SH_DREAMCAST BIGSUR SH_BIGSUR ADX SH_ADX MPC1211 SH_MPC1211 +SNAPGEAR SH_SECUREEDGE5410 diff -puN arch/sparc64/defconfig~linus arch/sparc64/defconfig --- 25/arch/sparc64/defconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/defconfig 2004-01-19 22:17:21.000000000 -0800 @@ -102,6 +102,7 @@ CONFIG_ENVCTRL=m CONFIG_DISPLAY7SEG=m CONFIG_WATCHDOG_CP1XXX=m CONFIG_WATCHDOG_RIO=m +# CONFIG_CMDLINE_BOOL is not set # # Generic Driver Options @@ -1286,6 +1287,7 @@ CONFIG_DVB_CORE=m CONFIG_DVB_TWINHAN_DST=m CONFIG_DVB_STV0299=m CONFIG_DVB_SP887X=m +CONFIG_DVB_SP887X_FIRMWARE_FILE="/etc/dvb/sc_main.mc" CONFIG_DVB_ALPS_TDLB7=m CONFIG_DVB_ALPS_TDMB7=m CONFIG_DVB_ATMEL_AT76C651=m @@ -1295,12 +1297,12 @@ CONFIG_DVB_GRUNDIG_29504_401=m CONFIG_DVB_MT312=m CONFIG_DVB_VES1820=m CONFIG_DVB_VES1X93=m -CONFIG_DVB_SP887X_FIRMWARE_FILE="/etc/dvb/sc_main.mc" # # Supported SAA7146 based PCI Adapters # -# CONFIG_DVB_AV7110 is not set +CONFIG_DVB_AV7110=m +# CONFIG_DVB_AV7110_OSD is not set CONFIG_DVB_BUDGET=m CONFIG_DVB_BUDGET_CI=m CONFIG_DVB_BUDGET_AV=m diff -puN arch/sparc64/Kconfig~linus arch/sparc64/Kconfig --- 25/arch/sparc64/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -128,6 +128,7 @@ config PREEMPT config NR_CPUS int "Maximum number of CPUs (2-64)" + range 2 64 depends on SMP default "64" @@ -489,6 +490,22 @@ config WATCHDOG_RIO machines. The watchdog timeout period is normally one minute but can be changed with a boot-time parameter. +config CMDLINE_BOOL + bool "Default bootloader kernel arguments" + +config CMDLINE + string "Initial kernel command string" + depends on CMDLINE_BOOL + default "console=ttyS0,9600 root=/dev/sda1" + help + Say Y here if you want to be able to pass default arguments to + the kernel. This will be overridden by the bootloader, if you + use one (such as SILO). This is most useful if you want to boot + a kernel from TFTP, and want default options to be available + with having them passed on the command line. + + NOTE: This option WILL override the PROM bootargs setting! + endmenu source "drivers/base/Kconfig" diff -puN arch/sparc64/kernel/head.S~linus arch/sparc64/kernel/head.S --- 25/arch/sparc64/kernel/head.S~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/kernel/head.S 2004-01-19 22:17:21.000000000 -0800 @@ -151,6 +151,9 @@ cheetah_generic_boot: blu,pt %xcc, 1b add %l0, (1 << 3), %l0 + /* BUG() if we get here... */ + ta 0x5 + cheetah_got_tlbentry: ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g0 ldxa [%l0] ASI_ITLB_DATA_ACCESS, %g1 @@ -333,6 +336,9 @@ spitfire_create_mappings: blu,pt %xcc, 1b add %l0, (1 << 3), %l0 + /* BUG() if we get here... */ + ta 0x5 + spitfire_got_tlbentry: /* Nops here again, perhaps Cheetah/Blackbird are better behaved... */ nop diff -puN arch/sparc64/kernel/pci_common.c~linus arch/sparc64/kernel/pci_common.c --- 25/arch/sparc64/kernel/pci_common.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/kernel/pci_common.c 2004-01-19 22:17:21.000000000 -0800 @@ -303,14 +303,23 @@ __init get_device_resource(struct linux_ { struct resource *res; int breg = (ap->phys_hi & 0xff); - int space = (ap->phys_hi >> 24) & 3; switch (breg) { case PCI_ROM_ADDRESS: + /* Unfortunately I have seen several cases where + * buggy FCODE uses a space value of '1' (I/O space) + * in the register property for the ROM address + * so disable this sanity check for now. + */ +#if 0 + { + int space = (ap->phys_hi >> 24) & 3; + /* It had better be MEM space. */ if (space != 2) bad_assignment(pdev, ap, NULL, 0); - + } +#endif res = &pdev->resource[PCI_ROM_RESOURCE]; break; diff -puN arch/sparc64/mm/extable.c~linus arch/sparc64/mm/extable.c --- 25/arch/sparc64/mm/extable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/mm/extable.c 2004-01-19 22:17:21.000000000 -0800 @@ -9,6 +9,11 @@ extern const struct exception_table_entry __start___ex_table[]; extern const struct exception_table_entry __stop___ex_table[]; +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish) +{ +} + /* Caller knows they are in a range if ret->fixup == 0 */ const struct exception_table_entry * search_extable(const struct exception_table_entry *start, diff -puN arch/sparc64/prom/bootstr.c~linus arch/sparc64/prom/bootstr.c --- 25/arch/sparc64/prom/bootstr.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc64/prom/bootstr.c 2004-01-19 22:17:21.000000000 -0800 @@ -21,6 +21,10 @@ struct { char bootstr_buf[BARG_LEN]; } bootstr_info = { .bootstr_len = BARG_LEN, +#ifdef CONFIG_CMDLINE + .bootstr_valid = 1, + .bootstr_buf = CONFIG_CMDLINE, +#endif }; char * __init diff -puN arch/sparc/Kconfig~linus arch/sparc/Kconfig --- 25/arch/sparc/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -112,6 +112,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "32" diff -puN arch/sparc/kernel/irq.c~linus arch/sparc/kernel/irq.c --- 25/arch/sparc/kernel/irq.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc/kernel/irq.c 2004-01-19 22:17:21.000000000 -0800 @@ -49,6 +49,9 @@ #include #include +/* Used to protect the IRQ action lists */ +spinlock_t irq_action_lock = SPIN_LOCK_UNLOCKED; + /* * Dave Redman (djhr@tadpole.co.uk) * @@ -492,7 +495,7 @@ int request_fast_irq(unsigned int irq, return -EBUSY; } - save_and_cli(flags); + spin_lock_irqsave(&irq_action_lock, flags); /* If this is flagged as statically allocated then we use our * private struct which is never freed. @@ -507,10 +510,10 @@ int request_fast_irq(unsigned int irq, if (action == NULL) action = (struct irqaction *)kmalloc(sizeof(struct irqaction), - GFP_KERNEL); + GFP_ATOMIC); if (!action) { - restore_flags(flags); + spin_unlock_irqrestore(&irq_action_lock, flags); return -ENOMEM; } @@ -547,7 +550,7 @@ int request_fast_irq(unsigned int irq, *(cpu_irq + irq_action) = action; enable_irq(irq); - restore_flags(flags); + spin_unlock_irqrestore(&irq_action_lock, flags); return 0; } @@ -586,7 +589,7 @@ int request_irq(unsigned int irq, action = NULL; /* Or else! */ } - save_and_cli(flags); + spin_lock_irqsave(&irq_action_lock, flags); /* If this is flagged as statically allocated then we use our * private struct which is never freed. @@ -600,10 +603,10 @@ int request_irq(unsigned int irq, if (action == NULL) action = (struct irqaction *)kmalloc(sizeof(struct irqaction), - GFP_KERNEL); + GFP_ATOMIC); if (!action) { - restore_flags(flags); + spin_unlock_irqrestore(&irq_action_lock, flags); return -ENOMEM; } @@ -620,7 +623,7 @@ int request_irq(unsigned int irq, *(cpu_irq + irq_action) = action; enable_irq(irq); - restore_flags(flags); + spin_unlock_irqrestore(&irq_action_lock, flags); return 0; } diff -puN arch/sparc/mm/extable.c~linus arch/sparc/mm/extable.c --- 25/arch/sparc/mm/extable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc/mm/extable.c 2004-01-19 22:17:21.000000000 -0800 @@ -6,6 +6,11 @@ #include #include +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish) +{ +} + /* Caller knows they are in a range if ret->fixup == 0 */ const struct exception_table_entry * search_extable(const struct exception_table_entry *start, diff -puN arch/sparc/mm/fault.c~linus arch/sparc/mm/fault.c --- 25/arch/sparc/mm/fault.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc/mm/fault.c 2004-01-19 22:17:21.000000000 -0800 @@ -36,7 +36,6 @@ #define ELEMENTS(arr) (sizeof (arr)/sizeof (arr[0])) -extern struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS+1]; extern int prom_node_root; /* At boot time we determine these two values necessary for setting diff -puN arch/sparc/mm/srmmu.c~linus arch/sparc/mm/srmmu.c --- 25/arch/sparc/mm/srmmu.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/sparc/mm/srmmu.c 2004-01-19 22:17:21.000000000 -0800 @@ -349,7 +349,7 @@ void srmmu_free_nocache(unsigned long va vaddr, (unsigned long)SRMMU_NOCACHE_VADDR); BUG(); } - if (vaddr+size >= srmmu_nocache_end) { + if (vaddr+size > srmmu_nocache_end) { printk("Vaddr %lx is bigger than nocache end 0x%lx\n", vaddr, srmmu_nocache_end); BUG(); @@ -1071,7 +1071,7 @@ void __init srmmu_early_allocate_ptable_ } if (start > (0xffffffffUL - SRMMU_PMD_SIZE_SOFT)) break; - start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK; + start = (start + SRMMU_PMD_SIZE_SOFT) & SRMMU_PMD_MASK_SOFT; } } @@ -1101,7 +1101,7 @@ void __init srmmu_allocate_ptable_skelet } if (start > (0xffffffffUL - SRMMU_PMD_SIZE_SOFT)) break; - start = (start + SRMMU_PMD_SIZE) & SRMMU_PMD_MASK; + start = (start + SRMMU_PMD_SIZE_SOFT) & SRMMU_PMD_MASK_SOFT; } } diff -puN arch/um/Kconfig~linus arch/um/Kconfig --- 25/arch/um/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/um/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -128,6 +128,7 @@ config SMP config NR_CPUS int "Maximum number of CPUs (2-32)" + range 2 32 depends on SMP default "32" diff -puN arch/x86_64/Kconfig~linus arch/x86_64/Kconfig --- 25/arch/x86_64/Kconfig~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/x86_64/Kconfig 2004-01-19 22:17:21.000000000 -0800 @@ -233,6 +233,7 @@ config HAVE_DEC_LOCK # to use clustered mode or whatever your big iron needs config NR_CPUS int "Maximum number of CPUs (2-8)" + range 2 8 depends on SMP default "8" help diff -puN arch/x86_64/mm/extable.c~linus arch/x86_64/mm/extable.c --- 25/arch/x86_64/mm/extable.c~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/arch/x86_64/mm/extable.c 2004-01-19 22:17:21.000000000 -0800 @@ -36,10 +36,9 @@ search_extable(const struct exception_ta /* When an exception handler is in an non standard section (like __init) the fixup table can end up unordered. Fix that here. */ -static __init int check_extable(void) +void sort_extable(struct exception_table_entry *start, + struct exception_table_entry *finish) { - extern struct exception_table_entry __start___ex_table[]; - extern struct exception_table_entry __stop___ex_table[]; struct exception_table_entry *e; int change; @@ -47,7 +46,7 @@ static __init int check_extable(void) best (and simplest) sort algorithm. */ do { change = 0; - for (e = __start___ex_table+1; e < __stop___ex_table; e++) { + for (e = start+1; e < finish; e++) { if (e->insn < e[-1].insn) { struct exception_table_entry tmp = e[-1]; e[-1] = e[0]; @@ -58,4 +57,3 @@ static __init int check_extable(void) } while (change != 0); return 0; } -core_initcall(check_extable); diff -puN CREDITS~linus CREDITS --- 25/CREDITS~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/CREDITS 2004-01-19 22:17:09.000000000 -0800 @@ -1394,7 +1394,9 @@ S: USA N: Marcel Holtmann E: marcel@holtmann.org W: http://www.holtmann.org +D: Maintainer of the Linux Bluetooth Subsystem D: Author and maintainer of the various Bluetooth HCI drivers +D: Author and maintainer of the CAPI message transport protocol driver D: Various other Bluetooth related patches, cleanups and fixes S: Germany diff -puN Documentation/devices.txt~linus Documentation/devices.txt --- 25/Documentation/devices.txt~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/Documentation/devices.txt 2004-01-19 22:17:09.000000000 -0800 @@ -2526,17 +2526,17 @@ Your cooperation is appreciated. 1 = /dev/dri/card1 Second graphics card ... -227 char IBM 3270 terminal block-mode access +227 char IBM 3270 terminal Unix tty access + 1 = /dev/3270/tty1 First 3270 terminal + 2 = /dev/3270/tty2 Seconds 3270 terminal + ... + +228 char IBM 3270 terminal block-mode access 0 = /dev/3270/tub Controlling interface 1 = /dev/3270/tub1 First 3270 terminal 2 = /dev/3270/tub2 Second 3270 terminal ... -228 char IBM 3270 terminal Unix tty access - 1 = /dev/3270/tty1 First 3270 terminal - 2 = /dev/3270/tty2 Seconds 3270 terminal - ... - 229 char IBM iSeries virtual console 0 = /dev/iseries/vtty0 First console port 1 = /dev/iseries/vtty1 Second console port diff -puN Documentation/DocBook/kernel-locking.tmpl~linus Documentation/DocBook/kernel-locking.tmpl --- 25/Documentation/DocBook/kernel-locking.tmpl~linus 2004-01-19 22:17:04.000000000 -0800 +++ 25-akpm/Documentation/DocBook/kernel-locking.tmpl 2004-01-19 22:17:09.000000000 -0800 @@ -66,6 +66,7 @@ fundamentals of concurrency and locking for SMP. + The Problem With Concurrency @@ -193,6 +194,7 @@ And then there are the unfriendly primitives, but I'll pretend they don't exist. + @@ -657,6 +659,7 @@ + @@ -1110,6 +1113,7 @@ used to protect the reference count itse return obj; } + @@ -1229,6 +1233,7 @@ which locks. This is extremely importan behavior of the code, and can be hard to gain from just reading. And as Alan Cox says, Lock data, not code. + @@ -1317,6 +1322,7 @@ as Alan Cox says, Lock data, not The two CPUs will spin forever, waiting for the other to give up their lock. It will look, smell, and feel like a crash. + Preventing Deadlock @@ -1886,6 +1892,7 @@ machines due to caching. + Some Functions Which Don't Sleep diff -puN Documentation/fb/modedb.txt~linus Documentation/fb/modedb.txt --- 25/Documentation/fb/modedb.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/fb/modedb.txt 2004-01-19 22:17:09.000000000 -0800 @@ -55,6 +55,7 @@ There may be more modes. aty128fb - ATI Rage128 / Pro frame buffer atyfb - ATI Mach64 frame buffer tdfx - 3D Fx frame buffer + tridentfb - Trident (Cyber)blade chipset frame buffer BTW, only a few drivers use this at the moment. Others are to follow (feel free to send patches). diff -puN Documentation/fb/tridentfb.txt~linus Documentation/fb/tridentfb.txt --- 25/Documentation/fb/tridentfb.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/fb/tridentfb.txt 2004-01-19 22:17:09.000000000 -0800 @@ -11,10 +11,15 @@ Only PCI/AGP based cards are supported, How to use it? ============== -Just do your usual console work :) -When booting you can pass the following parameters -================================================== +When booting you can pass the video parameter. +video=tridentfb + +The parameters for tridentfb are concatenated with a ':' as in this example. + +video=tridentfb:800x600,bpp=16,noaccel + +The second level parameters that tridentfb understands are: noaccel - turns off acceleration (when it doesn't work for your card) accel - force text acceleration (for boards which by default are noacceled) diff -puN Documentation/filesystems/ntfs.txt~linus Documentation/filesystems/ntfs.txt --- 25/Documentation/filesystems/ntfs.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/filesystems/ntfs.txt 2004-01-19 22:17:09.000000000 -0800 @@ -272,6 +272,9 @@ ChangeLog Note, a technical ChangeLog aimed at kernel hackers is in fs/ntfs/ChangeLog. +2.1.6: + - Fix minor bug in handling of compressed directories that fixes the + erroneous "du" and "stat" output people reported. 2.1.5: - Minor bug fix in attribute list attribute handling that fixes the I/O errors on "ls" of certain fragmented files found by at least two diff -puN Documentation/i2c/porting-clients~linus Documentation/i2c/porting-clients --- 25/Documentation/i2c/porting-clients~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/i2c/porting-clients 2004-01-19 22:17:09.000000000 -0800 @@ -92,7 +92,10 @@ Technical changes: i2c_get_clientdata(client) instead. * [Interface] Init function should not print anything. Make sure - there is a MODULE_LICENSE() line. + there is a MODULE_LICENSE() line. MODULE_PARM() is replaced + by module_param(). Note that module_param has a third parameter, + that you should set to 0 by default. See include/linux/moduleparam.h + for details. Coding policy: diff -puN Documentation/i386/zero-page.txt~linus Documentation/i386/zero-page.txt --- 25/Documentation/i386/zero-page.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/i386/zero-page.txt 2004-01-19 22:17:09.000000000 -0800 @@ -28,8 +28,13 @@ Offset Type Description 0xa0 16 bytes System description table truncated to 16 bytes. ( struct sys_desc_table_struct ) - 0xb0 - 0x1df Free. Add more parameters here if you really need them. + 0xb0 - 0x1c3 Free. Add more parameters here if you really need them. +0x1c4 unsigned long EFI system table pointer +0x1c8 unsigned long EFI memory descriptor size +0x1cc unsigned long EFI memory descriptor version +0x1d0 unsigned long EFI memory descriptor map pointer +0x1d4 unsigned long EFI memory descriptor map size 0x1e0 unsigned long ALT_MEM_K, alternative mem check, in Kb 0x1e8 char number of entries in E820MAP (below) 0x1e9 unsigned char number of entries in EDDBUF (below) diff -puN Documentation/kernel-parameters.txt~linus Documentation/kernel-parameters.txt --- 25/Documentation/kernel-parameters.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/kernel-parameters.txt 2004-01-19 22:17:09.000000000 -0800 @@ -37,7 +37,7 @@ restrictions referred to are that the re MCA MCA bus support is enabled. MDA MDA console support is enabled. MOUSE Appropriate mouse support is enabled. - MTD MTD support is nebaled. + MTD MTD support is enabled. NET Appropriate network support is enabled. NFS Appropriate NFS support is enabled. OSS OSS sound support is enabled. @@ -57,6 +57,7 @@ restrictions referred to are that the re SMP The kernel is an SMP kernel. SPARC Sparc architecture is enabled. SWSUSP Software suspension is enabled. + TS Appropriate touchscreen support is enabled. USB USB support is enabled. V4L Video For Linux support is enabled. VGA The VGA console has been enabled. @@ -85,6 +86,9 @@ running once the system is up. See header of drivers/scsi/53c7xx.c. See also Documentation/scsi/ncr53c7xx.txt. + 98busmouse.irq= [HW,MOUSE] PC-9801 Bus Mouse Driver + Format: , default is 13 + acpi= [HW,ACPI] Advanced Configuration and Power Interface Format: { force | off | ht } force -- enables ACPI for systems with default off @@ -153,10 +157,11 @@ running once the system is up. atascsi= [HW,SCSI] Atari SCSI - atkbd_set= [HW] Select keyboard code set + atkbd.set= [HW] Select keyboard code set Format: - - atkbd_reset [HW] Reset keyboard during initialization + atkbd.softrepeat= + [HW] Use software keyboard repeat + atkbd.reset= [HW] Reset keyboard during initialization autotest [IA64] @@ -372,13 +377,15 @@ running once the system is up. noirqbalance [IA-32,SMP,KNL] Disable kernel irq balancing - i8042_direct [HW] Keyboard has been put into non-translated mode - by BIOS - i8042_dumbkbd [HW] Don't attempt to blink the leds - i8042_noaux [HW] Don't check for auxiliary (== mouse) port - i8042_nomux - i8042_reset [HW] Reset the controller during init and cleanup - i8042_unlock [HW] Unlock (ignore) the keylock + i8042.direct [HW] Put keyboard port into non-translated mode + i8042.dumbkbd [HW] Pretend that controlled can only read data from + keyboard and can not control its state + (Don't attempt to blink the leds) + i8042.noaux [HW] Don't check for auxiliary (== mouse) port + i8042.nomux [HW] Don't check presence of an active multiplexing + controller + i8042.reset [HW] Reset the controller during init and cleanup + i8042.unlock [HW] Unlock (ignore) the keylock i810= [HW,DRM] @@ -414,7 +421,7 @@ running once the system is up. initrd= [BOOT] Specify the location of the initial ramdisk - inport_irq= [HW] Inport (ATI XL and Microsoft) busmouse driver + inport.irq= [HW] Inport (ATI XL and Microsoft) busmouse driver Format: inttest= [IA64] @@ -462,7 +469,7 @@ running once the system is up. lockd.tcpport= [NFS] - logibm_irq= [HW,MOUSE] Logitech Bus Mouse Driver + logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: log_buf_len=n Sets the size of the printk ring buffer, in bytes. @@ -562,6 +569,11 @@ running once the system is up. mga= [HW,DRM] + mousedev.xres [MOUSE] Horizontal screen resolution, used for devices + reporting absolute coordinates, such as tablets + mousedev.yres [MOUSE] Vertical screen resolution, used for devices + reporting absolute coordinates, such as tablets + mpu401= [HW,OSS] Format: , @@ -795,12 +807,18 @@ running once the system is up. before loading. See Documentation/ramdisk.txt. - psmouse_proto= [HW,MOUSE] Highest PS2 mouse protocol extension to + psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to probe for (bare|imps|exps). - - psmouse_resetafter= + psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports + per second. + psmouse.resetafter= [HW,MOUSE] Try to reset Synaptics Touchpad after so many bad packets (0 = never). + psmouse.resolution= + [HW,MOUSE] Set desired mouse resolution, in dpi. + psmouse.smartscroll= + [HW,MOUSE] Controls Logitech smartscroll autorepeat, + 0 = disabled, 1 = enabled (default). pss= [HW,OSS] Personal Sound System (ECHO ESC614) Format: ,,,,, @@ -1118,6 +1136,9 @@ running once the system is up. trix= [HW,OSS] MediaTrix AudioTrix Pro Format: ,,,,,,,, + tsdev.xres [TS] Horizontal screen resolution. + tsdev.yres [TS] Vertical screen resolution. + u14-34f= [HW,SCSI] UltraStor 14F/34F SCSI host adapter See header of drivers/scsi/u14-34f.c. diff -puN Documentation/m68k/00-INDEX~linus Documentation/m68k/00-INDEX --- 25/Documentation/m68k/00-INDEX~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/m68k/00-INDEX 2004-01-19 22:17:09.000000000 -0800 @@ -1,7 +1,5 @@ 00-INDEX - this file -framebuffer.txt - - info about the Linux/m68k frame buffer device kernel-options.txt - command line options for Linux/m68k diff -puN Documentation/networking/ip-sysctl.txt~linus Documentation/networking/ip-sysctl.txt --- 25/Documentation/networking/ip-sysctl.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/networking/ip-sysctl.txt 2004-01-19 22:17:09.000000000 -0800 @@ -667,6 +667,13 @@ regen_max_retry - INTEGER valid temporary addresses. Default: 5 +max_addresses - INTEGER + Number of maximum addresses per interface. 0 disables limitation. + It is recommended not set too large value (or 0) because it would + be too easy way to crash kernel to allow to create too much of + autoconfigured addresses. + Default: 16 + icmp/*: ratelimit - INTEGER Limit the maximal rates for sending ICMPv6 packets. diff -puN Documentation/networking/sk98lin.txt~linus Documentation/networking/sk98lin.txt --- 25/Documentation/networking/sk98lin.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/networking/sk98lin.txt 2004-01-19 22:17:09.000000000 -0800 @@ -2,9 +2,9 @@ All rights reserved =========================================================================== -sk98lin.txt created 23-Sep-2003 +sk98lin.txt created 15-Dec-2003 -Readme File for sk98lin v6.18 +Readme File for sk98lin v6.21 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains @@ -466,7 +466,7 @@ The Marvell Yukon/SysKonnect Linux drive Link Aggregation according to IEEE standards 802.1, 802.1q, and 802.3ad. These features are only available after installation of open source modules available on the Internet: -For VLAN go to: http://scry.wanfear.com/~greear/vlan.html +For VLAN go to: http://www.candelatech.com/~greear/vlan.html For Link Aggregation go to: http://www.st.rim.or.jp/~yumo NOTE: SysKonnect GmbH does not offer any support for these open source diff -puN Documentation/power/swsusp.txt~linus Documentation/power/swsusp.txt --- 25/Documentation/power/swsusp.txt~linus 2004-01-19 22:17:05.000000000 -0800 +++ 25-akpm/Documentation/power/swsusp.txt 2004-01-19 22:17:09.000000000 -0800 @@ -17,13 +17,30 @@ From kernel/suspend.c: You need to append resume=/dev/your_swap_partition to kernel command line. Then you suspend by echo 4 > /proc/acpi/sleep. -[Notice. Rest docs is pretty outdated (see date!) It should be safe to -use swsusp on ext3/reiserfs these days.] +Pavel's unreliable guide to swsusp mess +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There are currently two versions of swap suspend in the kernel, the old +"Pavel's" version in kernel/power/swsusp.c and the new "Patrick's" +version in kernel/power/pmdisk.c. They provide the same functionality; +the old version looks ugly but was tested, while the new version looks +nicer but did not receive so much testing. echo 4 > /proc/acpi/sleep +calls the old version, echo disk > /sys/power/state calls the new one. + +[In the future, when the new version is stable enough, two things can +happen: + +* the new version is moved into swsusp.c, and swsusp is renamed to swap + suspend (Pavel prefers this) + +* pmdisk is kept as is and swsusp.c is removed from the kernel] + Article about goals and implementation of Software Suspend for Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Author: G‚ábor Kuti -Last revised: 2002-04-08 +Last revised: 2003-10-20 by Pavel Machek Idea and goals to achieve @@ -36,84 +53,23 @@ real high when running from batteries. T interrupt our programs so processes that are calculating something for a long time shouldn't need to be written interruptible. -On desk machines the power saving function isn't as important as it is in -laptops but we really may benefit from the second one. Nowadays the number of -desk machines supporting suspend function in their APM is going up but there -are (and there will still be for a long time) machines that don't even support -APM of any kind. On the other hand it is reported that using APM's suspend -some irqs (e.g. ATA disk irq) is lost and it is annoying for the user until -the Linux kernel resets the device. - -So I started thinking about implementing Software Suspend which doesn't need -any APM support and - since it uses pretty near only high-level routines - is -supposed to be architecture independent code. - Using the code -The code is experimental right now - testers, extra eyes are welcome. To -compile this support into the kernel, you need CONFIG_EXPERIMENTAL, -and then CONFIG_SOFTWARE_SUSPEND in menu General Setup to be enabled. It -cannot be used as a module and I don't think it will ever be needed. - -You have two ways to use this code. The first one is if you've compiled in -sysrq support then you may press Sysrq-D to request suspend. The other way -is with a patched SysVinit (my patch is against 2.76 and available at my -home page). You might call 'swsusp' or 'shutdown -z