# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet v2.5.64 -> 1.1120 # arch/sparc/Kconfig 1.10 -> 1.11 # drivers/video/fbmem.c 1.58 -> 1.59 # arch/m68knommu/platform/68360/ints.c 1.2 -> 1.3 # arch/i386/kernel/process.c 1.46 -> 1.47 # drivers/char/rio/riointr.c 1.4 -> 1.5 # drivers/video/tcx.c 1.1 -> 1.4 # arch/arm/kernel/irq.c 1.26 -> 1.27 # arch/m68k/vmlinux-sun3.lds 1.11 -> 1.12 # drivers/scsi/inia100.h 1.13 -> 1.14 # net/bridge/netfilter/ebtable_broute.c 1.2 -> 1.3 # arch/sparc64/kernel/smp.c 1.48 -> 1.49 # arch/ia64/kernel/fsys.S 1.5 -> 1.9 # arch/ppc64/kernel/pci.h 1.6 -> 1.7 # drivers/block/ps2esdi.c 1.61 -> 1.62 # Documentation/scsi/ncr53c8xx.txt 1.5 -> 1.6 # net/irda/ircomm/ircomm_core.c 1.10 -> 1.11 # arch/i386/kernel/cpu/cpufreq/speedstep.c 1.13 -> 1.16 # fs/cifs/file.c 1.9 -> 1.12 # net/ipv4/netfilter/arptable_filter.c 1.2 -> 1.4 # include/linux/kernel.h 1.33 -> 1.34 # Documentation/swsusp.txt 1.4 -> 1.5 # drivers/ide/pci/via82cxxx.c 1.9 -> 1.10 # drivers/media/video/tda9887.c 1.2 -> 1.3 # drivers/ide/legacy/hd.c 1.17 -> 1.18 # drivers/serial/8250.h 1.5 -> 1.6 # drivers/scsi/sym53c8xx_2/sym_hipd.c 1.6 -> 1.7 # Documentation/s390/driver-model.txt 1.2 -> 1.3 # arch/i386/mm/fault.c 1.23 -> 1.24 # drivers/block/cciss.h 1.18 -> 1.19 # drivers/block/swim_iop.c 1.22 -> 1.23 # net/llc/af_llc.c 1.33 -> 1.34 # drivers/pnp/Makefile 1.12 -> 1.13 # drivers/scsi/scsi_error.c 1.38 -> 1.43 # net/bluetooth/rfcomm/core.c 1.13 -> 1.14 # include/asm-ia64/topology.h 1.6 -> 1.7 # include/asm-ppc/processor.h 1.26 -> 1.28 # drivers/isdn/hisax/saphir.c 1.26 -> 1.27 # arch/ia64/kernel/palinfo.c 1.10 -> 1.12 # crypto/digest.c 1.12 -> 1.13 # drivers/char/vme_scc.c 1.10 -> 1.11 # drivers/ide/ide-taskfile.c 1.11 -> 1.12 # arch/x86_64/pci/legacy.c 1.2 -> 1.3 # include/asm-sparc64/processor.h 1.15 -> 1.16 # kernel/ksyms.c 1.185 -> 1.189 # include/asm-i386/msr.h 1.12 -> 1.13 # drivers/cdrom/gscd.c 1.30 -> 1.31 # arch/arm/kernel/entry-common.S 1.12 -> 1.13 # arch/sparc64/kernel/us3_cpufreq.c 1.3 -> 1.5 # arch/ppc64/kernel/entry.S 1.22 -> 1.24 # Documentation/sonypi.txt 1.11 -> 1.12 # drivers/oprofile/cpu_buffer.c 1.5 -> 1.7 # crypto/internal.h 1.14 -> 1.16 # arch/arm/mach-sa1100/cpu-sa1110.c 1.17 -> 1.19 # arch/i386/kernel/cpu/cpufreq/powernow-k7.c 1.4 -> 1.9 # mm/fremap.c 1.3 -> 1.4 # include/asm-sparc64/pgtable.h 1.27 -> 1.28 # drivers/mtd/nftlcore.c 1.40 -> 1.41 # include/linux/jiffies.h 1.7 -> 1.8 # drivers/pci/quirks.c 1.23 -> 1.24 # drivers/isdn/hardware/avm/b1pci.c 1.28 -> 1.29 # include/asm-ppc64/fcntl.h 1.2 -> 1.3 # net/ipv4/xfrm_input.c 1.4 -> 1.5 # scripts/kconfig/images.c 1.1 -> 1.2 # include/asm-mips/processor.h 1.9 -> 1.10 # drivers/char/Kconfig 1.8 -> 1.11 # Documentation/DocBook/journal-api.tmpl 1.5 -> 1.6 # drivers/isdn/i4l/isdn_net_lib.c 1.37 -> 1.38 # net/ipv6/netfilter/ip6t_dst.c 1.1 -> 1.2 # include/net/dn_route.h 1.4 -> 1.5 # arch/ia64/Makefile 1.37 -> 1.39 # drivers/atm/Makefile 1.16 -> 1.17 # scripts/kconfig/qconf.cc 1.4 -> 1.5 # include/linux/mm.h 1.108 -> 1.110 # fs/file_table.c 1.17 -> 1.18 # include/asm-i386/processor.h 1.40 -> 1.43 # arch/i386/kernel/cpu/common.c 1.18 -> 1.20 # include/linux/init.h 1.24 -> 1.25 # arch/sparc/kernel/irq.c 1.20 -> 1.21 # drivers/serial/8250.c 1.29 -> 1.32 # include/linux/raid/md_k.h 1.51 -> 1.56 # arch/x86_64/lib/getuser.S 1.1 -> 1.2 # arch/i386/kernel/cpu/cpufreq/longhaul.c 1.11 -> 1.14 # drivers/net/dgrs.c 1.14 -> 1.15 # arch/x86_64/vmlinux.lds.S 1.13 -> 1.14 # include/linux/i2c-id.h 1.9 -> 1.10 # net/ipv6/ip6_output.c 1.11 -> 1.13 # drivers/usb/serial/io_edgeport.c 1.38 -> 1.39 # drivers/isdn/hisax/hisax_isac.c 1.4 -> 1.5 # net/llc/llc_conn.c 1.23 -> 1.24 # arch/i386/kernel/irq.c 1.26 -> 1.28 # include/linux/raid/md.h 1.23 -> 1.25 # arch/i386/oprofile/op_model_p4.c 1.2 -> 1.4 # arch/m68knommu/platform/68VZ328/Makefile 1.2 -> 1.3 # arch/mips/philips/nino/irq.c 1.4 -> 1.5 # include/asm-i386/hdreg.h 1.2 -> 1.3 # drivers/char/decserial.c 1.2 -> 1.3 # drivers/video/sbuslib.h 1.1 -> 1.3 # arch/alpha/kernel/pci.c 1.24 -> 1.25 # include/asm-ppc64/processor.h 1.26 -> 1.27 # mm/readahead.c 1.28 -> 1.29 # arch/ia64/ia32/ia32_support.c 1.6 -> 1.7 # arch/arm/mach-sa1100/cpu-sa1100.c 1.13 -> 1.15 # drivers/i2c/busses/Makefile 1.2 -> 1.5 # include/asm-ppc64/pci-bridge.h 1.4 -> 1.5 # drivers/isdn/i4l/isdn_ppp_mp.c 1.7 -> 1.8 # include/asm-arm/posix_types.h 1.1 -> 1.2 # drivers/isdn/hisax/hfc_sx.c 1.36 -> 1.37 # drivers/char/random.c 1.31 -> 1.32 # net/ipv6/netfilter/ip6table_filter.c 1.4 -> 1.5 # arch/sparc/vmlinux.lds.S 1.14 -> 1.15 # include/asm-ia64/spinlock.h 1.6 -> 1.7 # Documentation/cpu-freq/user-guide.txt 1.1 -> 1.3 # net/x25/x25_timer.c 1.9 -> 1.10 # arch/m68knommu/platform/68328/entry.S 1.3 -> 1.4 # drivers/parport/ieee1284.c 1.5 -> 1.6 # Documentation/networking/sis900.txt 1.1 -> 1.2 # arch/alpha/kernel/core_marvel.c 1.7 -> 1.8 # Documentation/sound/alsa/ALSA-Configuration.txt 1.3 -> 1.4 # Documentation/scsi/sym53c8xx_2.txt 1.2 -> 1.3 # arch/mips64/sgi-ip22/ip22-int.c 1.6 -> 1.7 # include/linux/netfilter_bridge/ebt_mark_t.h 1.1 -> 1.2 # Documentation/video4linux/zr36120.txt 1.1 -> 1.2 # drivers/isdn/hisax/avm_a1.c 1.23 -> 1.24 # arch/i386/kernel/cpu/cpufreq/acpi.c 1.4 -> 1.5 # kernel/fork.c 1.111 -> 1.114 # include/linux/sched.h 1.136 -> 1.137 # net/sunrpc/svcsock.c 1.40 -> 1.42 # drivers/isdn/hisax/s0box.c 1.25 -> 1.26 # sound/isa/als100.c 1.7 -> 1.9 # include/asm-ia64/machvec_hpzx1.h 1.4 -> 1.5 # drivers/block/ll_rw_blk.c 1.155 -> 1.157 # arch/i386/kernel/vm86.c 1.20 -> 1.21 # Makefile 1.392 -> 1.395 # drivers/cpufreq/userspace.c 1.1 -> 1.4 # net/bridge/netfilter/ebt_log.c 1.2 -> 1.3 # drivers/media/radio/miropcm20-rds.c 1.6 -> 1.7 # Documentation/sound/oss/cs46xx 1.2 -> 1.3 # drivers/video/Makefile 1.76 -> 1.78 # include/asm-ia64/unistd.h 1.23 -> 1.25 # drivers/media/video/bttv-if.c 1.8 -> 1.9 # drivers/isdn/hisax/hisax_fcclassic.c 1.2 -> 1.3 # include/asm-i386/xor.h 1.12 -> 1.14 # drivers/base/platform.c 1.6 -> 1.9 # include/linux/serial_core.h 1.16 -> 1.20 # include/net/tcp.h 1.30 -> 1.32 # arch/x86_64/ia32/socket32.c 1.3 -> (deleted) # include/asm-ia64/page.h 1.14 -> 1.15 # drivers/serial/amba.c 1.16 -> 1.17 # arch/ppc64/kernel/chrp_setup.c 1.19 -> 1.20 # drivers/net/wan/sdla_ft1.c 1.5 -> 1.6 # Documentation/vm/hugetlbpage.txt 1.4 -> 1.5 # drivers/atm/firestream.c 1.16 -> 1.17 # include/asm-i386/thread_info.h 1.10 -> 1.11 # include/asm-arm/system.h 1.13 -> 1.15 # include/linux/if_shaper.h 1.1 -> 1.2 # net/ipv6/netfilter/ip6t_ah.c 1.1 -> 1.2 # arch/i386/kernel/cpu/cpufreq/powernow-k6.c 1.12 -> 1.13 # net/ipv4/af_inet.c 1.38 -> 1.40 # Documentation/pnp.txt 1.2 -> 1.3 # arch/ia64/kernel/setup.c 1.36 -> 1.37 # drivers/serial/sa1100.c 1.18 -> 1.20 # arch/mips/kernel/irq.c 1.8 -> 1.9 # fs/proc/proc_misc.c 1.67 -> 1.68 # arch/ppc64/Makefile 1.23 -> 1.24 # drivers/s390/char/sclp_tty.c 1.4 -> 1.5 # Documentation/filesystems/sysfs.txt 1.8 -> 1.9 # arch/m68knommu/platform/5307/config.c 1.1 -> 1.2 # drivers/block/cpqarray.c 1.70 -> 1.71 # drivers/pnp/interface.c 1.13 -> 1.14 # arch/x86_64/kernel/apic.c 1.13 -> 1.14 # drivers/i2c/i2c-core.c 1.18 -> 1.23 # include/asm-i386/bug.h 1.1 -> 1.2 # Documentation/arm/Setup 1.1 -> 1.2 # arch/i386/Kconfig 1.46 -> 1.48 # drivers/isdn/hisax/elsa.c 1.35 -> 1.36 # drivers/block/floppy.c 1.68 -> 1.69 # include/linux/genhd.h 1.46 -> 1.47 # arch/ia64/kernel/ivt.S 1.13 -> 1.14 # drivers/block/ataflop.c 1.33 -> 1.34 # include/linux/elf.h 1.19 -> 1.20 # drivers/media/video/saa7134/saa7134-i2c.c 1.4 -> 1.5 # Documentation/networking/wan-router.txt 1.2 -> 1.3 # drivers/isdn/hisax/sportster.c 1.24 -> 1.25 # net/ax25/ax25_in.c 1.8 -> 1.9 # net/ipx/af_ipx.c 1.23 -> 1.25 # drivers/cdrom/sbpcd.c 1.41 -> 1.42 # arch/ppc/boot/simple/rw4/ppc_40x.h 1.2 -> 1.3 # drivers/media/video/saa7134/saa7134-video.c 1.3 -> 1.4 # net/ipv4/udp.c 1.30 -> 1.31 # init/main.c 1.93 -> 1.94 # fs/devfs/base.c 1.71 -> 1.73 # arch/i386/kernel/traps.c 1.46 -> 1.47 # arch/sparc64/kernel/sys32.S 1.4 -> 1.5 # Documentation/networking/ifenslave.c 1.4 -> 1.5 # include/linux/i2c.h 1.12 -> 1.15 # net/bridge/netfilter/ebt_snat.c 1.1 -> 1.2 # Documentation/networking/wanpipe.txt 1.2 -> 1.3 # arch/ia64/sn/kernel/mca.c 1.3 -> 1.4 # scripts/modpost.c 1.9 -> 1.10 # net/bluetooth/af_bluetooth.c 1.13 -> 1.14 # Documentation/s390/Debugging390.txt 1.8 -> 1.9 # arch/i386/vmlinux.lds.S 1.25 -> 1.26 # include/asm-x86_64/fcntl.h 1.1 -> 1.2 # drivers/net/wan/sdla_ppp.c 1.21 -> 1.22 # drivers/md/raid5.c 1.59 -> 1.63 # Documentation/specialix.txt 1.1 -> 1.2 # arch/parisc/vmlinux.lds.S 1.11 -> 1.12 # drivers/serial/anakin.c 1.13 -> 1.14 # Documentation/uml/UserModeLinux-HOWTO.txt 1.1 -> 1.2 # kernel/cpufreq.c 1.21 -> 1.27 # drivers/acorn/block/mfmhd.c 1.48 -> 1.49 # arch/ia64/kernel/time.c 1.13.1.1 -> 1.16 # include/linux/raid/md_p.h 1.2 -> 1.3 # include/asm-sparc64/termios.h 1.4 -> 1.5 # net/atm/atm_misc.c 1.1 -> 1.2 # net/ipv6/netfilter/ip6t_frag.c 1.1 -> 1.2 # drivers/char/watchdog/amd7xx_tco.c 1.4 -> 1.5 # arch/i386/kernel/srat.c 1.1 -> 1.2 # fs/cifs/cifssmb.c 1.9 -> 1.11 # include/asm-ppc/pgtable.h 1.19 -> 1.20 # include/net/ip6_route.h 1.4 -> 1.5 # arch/ppc/mm/init.c 1.26 -> 1.27 # Documentation/oops-tracing.txt 1.3 -> 1.4 # arch/i386/kernel/microcode.c 1.16 -> 1.17 # drivers/block/nbd.c 1.50 -> 1.51 # arch/arm/mach-sa1100/pm.c 1.10 -> 1.12 # drivers/serial/core.c 1.38 -> 1.50 # drivers/media/video/audiochip.h 1.3 -> 1.5 include/media/audiochip.h (moved) # scripts/kconfig/mconf.c 1.4 -> 1.5 # drivers/net/wan/sdladrv.c 1.6 -> 1.7 # drivers/base/bus.c 1.41 -> 1.42 # drivers/usb/core/message.c 1.21 -> 1.22 # include/asm-ppc64/compat.h 1.6 -> 1.7 # drivers/media/video/bw-qcam.c 1.10 -> 1.11 # arch/m68knommu/platform/68VZ328/de2/config.c 1.1 -> 1.2 # drivers/net/wan/comx-hw-munich.c 1.8 -> 1.9 # net/bluetooth/sco.c 1.11 -> 1.13 # kernel/softirq.c 1.33 -> 1.34 # drivers/isdn/hisax/nj_u.c 1.24 -> 1.25 # arch/um/drivers/stdio_console.c 1.7 -> 1.8 # scripts/kconfig/symbol.c 1.3 -> 1.4 # drivers/cdrom/optcd.c 1.24 -> 1.25 # net/x25/x25_subr.c 1.8 -> 1.9 # include/asm-x86_64/uaccess.h 1.7 -> 1.9 # arch/sparc64/kernel/pci_common.c 1.17 -> 1.18 # drivers/scsi/sr.c 1.72 -> 1.74 # arch/s390x/kernel/entry.S 1.28 -> 1.30 # net/key/af_key.c 1.21 -> 1.25 # drivers/char/rio/rioboot.c 1.5 -> 1.6 # arch/ia64/sn/io/Makefile 1.9 -> 1.10 # drivers/scsi/scsi.h 1.65 -> 1.66 # Documentation/cdrom/cdrom-standard.tex 1.1 -> 1.2 # include/linux/fs.h 1.223 -> 1.225 # drivers/video/sa1100fb.c 1.25 -> 1.26 # arch/ia64/sn/kernel/setup.c 1.9 -> 1.10 # arch/i386/mm/ioremap.c 1.16 -> 1.17 # arch/ia64/kernel/entry.S 1.30 -> 1.36 # fs/intermezzo/dir.c 1.11 -> 1.12 # include/asm-arm/pgtable.h 1.14 -> 1.16 # include/asm-ia64/hardirq.h 1.10 -> 1.11 # include/asm-v850/processor.h 1.3 -> 1.4 # Documentation/networking/3c509.txt 1.1 -> 1.2 # arch/i386/kernel/entry.S 1.58 -> 1.59 # Documentation/networking/bonding.txt 1.7 -> 1.8 # Documentation/kobject.txt 1.4 -> 1.5 # fs/cifs/cifs_fs_sb.h 1.1 -> 1.2 # net/ax25/ax25_std_timer.c 1.4 -> 1.5 # drivers/oprofile/buffer_sync.c 1.8 -> 1.9 # drivers/isdn/hisax/nj_s.c 1.25 -> 1.26 # drivers/sgi/char/sgiserial.c 1.7 -> 1.8 # net/ipv6/netfilter/ip6t_rt.c 1.1 -> 1.2 # arch/arm/mach-sa1100/generic.c 1.16 -> 1.18 # net/ipv4/tcp.c 1.34 -> 1.35 # include/asm-i386/srat.h 1.1 -> 1.3 # arch/m68knommu/platform/68VZ328/ucdimm/config.c 1.1 -> 1.2 # include/linux/crypto.h 1.25 -> 1.27 # drivers/video/cg6.c 1.1 -> 1.4 # drivers/eisa/eisa-bus.c 1.3 -> 1.4 # Documentation/filesystems/proc.txt 1.12 -> 1.13 # drivers/isdn/hisax/isdnl1.c 1.15 -> 1.16 # drivers/scsi/fdomain.h 1.6 -> (deleted) # include/asm-ia64/machvec_dig.h 1.2 -> 1.3 # arch/x86_64/kernel/setup64.c 1.10 -> 1.11 # arch/x86_64/ia32/ptrace32.c 1.4 -> 1.5 # fs/lockd/svclock.c 1.6 -> 1.7 # drivers/char/rio/rioinit.c 1.4 -> 1.5 # drivers/md/md.c 1.143 -> 1.155 # drivers/serial/clps711x.c 1.13 -> 1.14 # fs/cifs/transport.c 1.5 -> 1.6 # arch/mips64/Kconfig 1.9 -> 1.10 # arch/x86_64/ia32/Makefile 1.11 -> 1.13 # arch/alpha/kernel/core_titan.c 1.13 -> 1.14 # include/asm-x86_64/ptrace.h 1.6 -> 1.7 # include/asm-alpha/pgtable.h 1.16 -> 1.17 # arch/ppc/mm/fault.c 1.14 -> 1.15 # net/atm/proc.c 1.8 -> 1.9 # drivers/video/sbuslib.c 1.1 -> 1.3 # drivers/scsi/ncr53c8xx.c 1.22 -> 1.23 # arch/alpha/mm/fault.c 1.10 -> 1.11 # net/bridge/netfilter/ebt_arp.c 1.1 -> 1.2 # net/bridge/netfilter/ebt_mark_m.c 1.1 -> 1.2 # net/ipv6/icmp.c 1.17 -> 1.18 # Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl 1.4 -> 1.5 # drivers/scsi/inia100.c 1.18 -> 1.19 # Documentation/usb/hiddev.txt 1.4 -> 1.5 # include/asm-x86_64/socket32.h 1.3 -> (deleted) # arch/m68knommu/platform/5272/config.c 1.1 -> 1.2 # include/asm-ia64/pgtable.h 1.16 -> 1.17 # include/linux/wanrouter.h 1.4 -> 1.5 # arch/mips/au1000/common/serial.c 1.8 -> 1.9 # arch/x86_64/kernel/ptrace.c 1.10 -> 1.11 # drivers/usb/serial/visor.c 1.58 -> 1.59 # drivers/char/rio/riocmd.c 1.6 -> 1.7 # Documentation/usb/URB.txt 1.3 -> 1.4 # arch/arm/kernel/entry-armv.S 1.26 -> 1.27 # include/asm-arm/pci.h 1.17 -> 1.18 # arch/s390x/vmlinux.lds.S 1.9 -> 1.10 # include/asm-ia64/sn/module.h 1.4 -> 1.5 # net/irda/af_irda.c 1.35 -> 1.37 # arch/m68knommu/platform/68328/ints.c 1.1 -> 1.2 # include/asm-ia64/posix_types.h 1.1 -> 1.2 # drivers/media/video/tvaudio.c 1.13 -> 1.15 # net/ipv4/tcp_ipv4.c 1.43 -> 1.44 # arch/ppc64/mm/extable.c 1.8 -> 1.9 # drivers/media/video/saa7134/saa7134-core.c 1.2 -> 1.3 # drivers/isdn/i4l/Kconfig 1.2 -> 1.3 # arch/i386/kernel/io_apic.c 1.52 -> 1.55 # drivers/hotplug/acpiphp_glue.c 1.7 -> 1.8 # fs/char_dev.c 1.7 -> 1.8 # include/asm-sh/processor.h 1.10 -> 1.11 # net/8021q/vlanproc.c 1.8 -> 1.9 # arch/sparc64/defconfig 1.75 -> 1.76 # drivers/acorn/block/fd1772.c 1.32 -> 1.33 # arch/parisc/kernel/sys_parisc32.c 1.8 -> 1.10 # mm/filemap.c 1.181 -> 1.182 # arch/mips/vmlinux.lds.S 1.7 -> 1.8 # drivers/cdrom/sonycd535.c 1.31 -> 1.32 # drivers/scsi/qlogicfas.h 1.7 -> (deleted) # drivers/isdn/hisax/avm_pci.c 1.41 -> 1.42 # drivers/ide/ide-iops.c 1.7 -> 1.8 # fs/namei.c 1.65 -> 1.67 # net/decnet/dn_nsp_in.c 1.7 -> 1.8 # net/bridge/netfilter/ebtables.c 1.4 -> 1.5 # Documentation/kbuild/kconfig-language.txt 1.1 -> 1.2 # arch/m68knommu/platform/5206e/config.c 1.1 -> 1.2 # arch/arm/vmlinux-armv.lds.in 1.21 -> 1.22 # fs/intermezzo/fileset.c 1.2 -> 1.3 # arch/x86_64/pci/pci.h 1.5 -> 1.6 # net/socket.c 1.43 -> 1.44 # arch/sh/kernel/irq.c 1.10 -> 1.11 # arch/i386/Makefile 1.47 -> 1.48 # include/asm-ia64/processor.h 1.30 -> 1.32 # drivers/scsi/ncr53c8xx.h 1.9 -> 1.10 # arch/s390/vmlinux.lds.S 1.9 -> 1.10 # fs/smbfs/sock.c 1.13 -> 1.14 # net/ipv4/netfilter/iptable_filter.c 1.4 -> 1.6 # fs/intermezzo/intermezzo_lib.h 1.2 -> 1.3 # drivers/block/swim3.c 1.22 -> 1.23 # net/netrom/nr_in.c 1.4 -> 1.5 # sound/pci/ac97/ac97_codec.c 1.29 -> 1.30 # net/ipv4/xfrm_algo.c 1.3 -> 1.5 # drivers/char/amd768_rng.c 1.3 -> 1.7 drivers/char/hw_random.c (moved) # arch/i386/kernel/dmi_scan.c 1.29 -> 1.30 # fs/partitions/ldm.c 1.11 -> 1.12 # drivers/media/video/bttvp.h 1.9 -> 1.10 # Documentation/filesystems/Exporting 1.2 -> 1.3 # init/do_mounts.c 1.46 -> 1.47 # drivers/char/rio/riotty.c 1.5 -> 1.6 # arch/x86_64/boot/Makefile 1.14 -> 1.16 # drivers/mtd/mtdblock.c 1.37 -> 1.38 # drivers/isdn/hisax/amd7930.c 1.11 -> (deleted) # include/asm-ia64/machvec_sn2.h 1.3 -> 1.4 # Documentation/arm/SA1100/serial_UART 1.2 -> 1.3 # net/ipv4/netfilter/ip_fw_compat.c 1.11 -> 1.13 # net/sunrpc/clnt.c 1.32 -> 1.33 # drivers/usb/storage/transport.c 1.63 -> 1.64 # arch/alpha/kernel/sys_nautilus.c 1.10 -> 1.11 # net/core/scm.c 1.5 -> 1.6 # Documentation/arm/mem_alignment 1.1 -> 1.2 # drivers/isdn/hisax/niccy.c 1.27 -> 1.28 # net/ipv6/netfilter/ip6table_mangle.c 1.5 -> 1.6 # Documentation/filesystems/ext3.txt 1.2 -> 1.3 # fs/nfsd/vfs.c 1.55 -> 1.57 # include/net/snmp.h 1.5 -> 1.6 # Documentation/devices.txt 1.8 -> 1.9 # arch/s390/Kconfig 1.7 -> 1.8 # arch/arm/kernel/bios32.c 1.17 -> 1.18 # drivers/isdn/hisax/bkm_a4t.c 1.24 -> 1.25 # net/ipv6/raw.c 1.18 -> 1.19 # arch/alpha/oprofile/op_model_ev4.c 1.4 -> 1.5 # drivers/serial/uart00.c 1.12 -> 1.13 # arch/i386/boot/Makefile 1.23 -> 1.25 # include/linux/net.h 1.8 -> 1.9 # net/ipv4/netfilter/ip_nat_rule.c 1.7 -> 1.9 # drivers/char/rtc.c 1.22 -> 1.23 # arch/x86_64/kernel/head64.c 1.5 -> 1.6 # arch/um/kernel/mem.c 1.12 -> 1.14 # arch/i386/kernel/cpu/cpufreq/elanfreq.c 1.11 -> 1.12 # net/netsyms.c 1.50 -> 1.52 # include/linux/efs_fs.h 1.8 -> 1.9 # Documentation/networking/tuntap.txt 1.3 -> 1.4 # include/linux/pci_ids.h 1.83 -> 1.85 # drivers/usb/serial/usb-serial.c 1.72 -> 1.73 # arch/sparc/kernel/sys_sunos.c 1.22 -> 1.23 # drivers/char/rio/rioctrl.c 1.7 -> 1.8 # drivers/scsi/sym53c8xx.h 1.11 -> 1.12 # fs/intermezzo/cache.c 1.8 -> 1.9 # drivers/ide/ide-disk.c 1.32 -> 1.33 # include/asm-ia64/system.h 1.31 -> 1.32 # arch/cris/vmlinux.lds.S 1.15 -> 1.16 # scripts/kconfig/qconf.h 1.2 -> 1.3 # include/net/bluetooth/bluetooth.h 1.10 -> 1.11 # Documentation/filesystems/devfs/README 1.12 -> 1.14 # include/asm-s390x/pgtable.h 1.15 -> 1.17 # Documentation/scsi/ChangeLog.sym53c8xx_2 1.5 -> 1.6 # drivers/md/linear.c 1.23 -> 1.25 # fs/sysfs/dir.c 1.2 -> 1.5 # drivers/isdn/hisax/hfc_pci.c 1.40 -> 1.41 # drivers/media/video/tuner-3036.c 1.5 -> 1.6 # net/Makefile 1.19 -> 1.20 # arch/x86_64/kernel/irq.c 1.9 -> 1.10 # arch/sparc64/kernel/systbls.S 1.31 -> 1.34 # drivers/serial/mcfserial.c 1.3 -> 1.4 # arch/x86_64/ia32/sys_ia32.c 1.20 -> 1.23 # include/asm-arm/ide.h 1.9 -> 1.10 # net/bridge/netfilter/ebt_ip.c 1.2 -> 1.3 # arch/ia64/kernel/unwind_i.h 1.4 -> 1.5 # include/linux/usb.h 1.72 -> 1.73 # drivers/net/sis900.c 1.33 -> 1.34 # drivers/media/video/tda9875.c 1.8 -> 1.10 # drivers/char/serial167.c 1.14 -> 1.15 # arch/ppc64/kernel/irq.c 1.20 -> 1.22 # drivers/char/i810_rng.c 1.13 -> (deleted) # drivers/net/wan/pc300_tty.c 1.6 -> 1.7 # net/ipv4/netfilter/ip_conntrack_standalone.c 1.13 -> 1.15 # arch/x86_64/ia32/ia32entry.S 1.12 -> 1.15 # arch/ia64/hp/sim/simscsi.c 1.11 -> 1.12 # arch/ia64/pci/pci.c 1.21 -> 1.22 # fs/binfmt_elf.c 1.37 -> 1.41 # mm/memory.c 1.112 -> 1.114 # drivers/md/multipath.c 1.43 -> 1.45 # drivers/usb/serial/pl2303.c 1.35 -> 1.36 # arch/v850/Kconfig 1.7 -> 1.8 # arch/mips64/vmlinux.lds.S 1.6 -> 1.7 # fs/aio.c 1.28 -> 1.29 # include/linux/usb_ch9.h 1.2 -> 1.3 # drivers/sbus/char/jsflash.c 1.28 -> 1.29 # Documentation/kernel-doc-nano-HOWTO.txt 1.4 -> 1.5 # fs/compat.c 1.4 -> 1.5 # drivers/usb/core/hub.c 1.56 -> 1.57 # include/linux/compat.h 1.7 -> 1.9 # drivers/block/amiflop.c 1.35 -> 1.36 # drivers/cdrom/mcdx.c 1.29 -> 1.30 # drivers/block/genhd.c 1.71 -> 1.74 # include/linux/pci.h 1.64 -> 1.68 # include/linux/profile.h 1.4 -> 1.5 # arch/ia64/kernel/mca.c 1.17 -> 1.18 # arch/ia64/kernel/iosapic.c 1.18 -> 1.23 # include/asm-s390/processor.h 1.10 -> 1.11 # fs/cifs/cifs_debug.c 1.5 -> 1.6 # arch/ia64/kernel/process.c 1.25 -> 1.26 # arch/arm/tools/mach-types 1.24 -> 1.25 # fs/readdir.c 1.17 -> 1.18 # include/asm-sparc/termios.h 1.4 -> 1.5 # arch/i386/kernel/smpboot.c 1.52 -> 1.53 # arch/ppc/kernel/process.c 1.31 -> 1.32 # drivers/media/video/bttv-cards.c 1.14 -> 1.15 # arch/mips/Kconfig 1.8 -> 1.9 # arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 1.5 -> 1.7 # arch/um/drivers/ubd_kern.c 1.26 -> 1.27 # arch/arm/mach-integrator/cpu.c 1.13 -> 1.15 # include/asm-arm/processor.h 1.12 -> 1.13 # drivers/mtd/mtdblock_ro.c 1.23 -> 1.24 # include/net/scm.h 1.3 -> 1.4 # arch/x86_64/mm/pageattr.c 1.3 -> 1.4 # arch/um/Kconfig 1.8 -> 1.9 # arch/ia64/hp/sim/simserial.c 1.10 -> 1.11 # arch/ia64/kernel/acpi.c 1.27 -> 1.34 # arch/m68knommu/kernel/entry.S 1.1 -> 1.2 # arch/x86_64/kernel/suspend.c 1.1 -> 1.2 # include/linux/netfilter_ipv4/ipchains_core.h 1.1 -> 1.3 # include/linux/hugetlb.h 1.13 -> 1.15 # include/asm-cris/processor.h 1.12 -> 1.13 # arch/ia64/kernel/machvec.c 1.3 -> 1.4 # drivers/media/video/id.h 1.3 -> 1.4 include/media/id.h (moved) # drivers/net/wan/sdla_chdlc.c 1.19 -> 1.20 # include/asm-s390x/compat.h 1.5 -> 1.6 # drivers/ide/ide-floppy.c 1.25 -> 1.26 # net/econet/af_econet.c 1.13 -> 1.15 # drivers/media/video/zr36120.c 1.17 -> 1.18 # drivers/media/video/video-buf.c 1.7 -> 1.9 # fs/sysfs/bin.c 1.2 -> 1.3 # include/asm-mips64/processor.h 1.7 -> 1.8 # drivers/scsi/scsi_lib.c 1.73 -> 1.74 # drivers/message/fusion/lsi/mpi_raid.h 1.4 -> 1.5 # drivers/isdn/hisax/teles0.c 1.24 -> 1.25 # net/netrom/af_netrom.c 1.21 -> 1.23 # net/rose/af_rose.c 1.18 -> 1.20 # drivers/pnp/Kconfig 1.3 -> 1.4 # include/linux/tty.h 1.8 -> 1.10 # arch/i386/boot/bootsect.S 1.7 -> 1.8 # include/asm-i386/mmzone.h 1.8 -> 1.11 # net/netlink/af_netlink.c 1.18 -> 1.20 # arch/sparc/kernel/systbls.S 1.16 -> 1.17 # include/asm-arm/arch-anakin/time.h 1.3 -> 1.4 # arch/i386/boot/tools/build.c 1.2 -> 1.3 # arch/x86_64/kernel/io_apic.c 1.7 -> 1.8 # drivers/ide/ide-dma.c 1.11 -> 1.12 # net/ipv6/Kconfig 1.2 -> 1.3 # net/ipv4/xfrm_policy.c 1.15 -> 1.17 # drivers/ide/Makefile 1.10 -> 1.11 # arch/m68knommu/kernel/comempci.c 1.2 -> 1.3 # drivers/s390/char/sclp_con.c 1.3 -> 1.4 # drivers/usb/core/usb.c 1.115 -> 1.116 # fs/jfs/jfs_logmgr.c 1.45 -> 1.46 # arch/mips64/sgi-ip27/ip27-irq.c 1.6 -> 1.7 # kernel/posix-timers.c 1.4 -> 1.5 # arch/ppc64/kernel/head.S 1.24.1.1 -> 1.26 # drivers/i2c/i2c-proc.c 1.16 -> 1.17 # arch/ia64/mm/hugetlbpage.c 1.9 -> 1.10 # arch/s390x/Kconfig 1.8 -> 1.9 # drivers/scsi/zalon.h 1.2 -> 1.3 # crypto/cipher.c 1.11 -> 1.14 # Documentation/driver-model/driver.txt 1.3 -> 1.4 # drivers/scsi/i91uscsi.h 1.3 -> 1.4 # drivers/i2c/i2c-algo-bit.c 1.12 -> 1.13 # arch/alpha/vmlinux.lds.S 1.18 -> 1.20 # net/decnet/af_decnet.c 1.20 -> 1.21 # Documentation/cpqarray.txt 1.1 -> 1.2 # drivers/scsi/pcmcia/qlogic_stub.c 1.11 -> 1.12 # net/bridge/netfilter/ebt_vlan.c 1.2 -> 1.3 # drivers/char/serial_tx3912.c 1.7 -> 1.8 # include/asm-arm/proc-fns.h 1.7 -> 1.8 # fs/ext3/dir.c 1.8 -> 1.9 # include/linux/sunrpc/cache.h 1.10 -> 1.11 # arch/mips/kernel/old-irq.c 1.5 -> 1.6 # drivers/media/video/video-buf.h 1.5 -> 1.7 include/media/video-buf.h (moved) # include/asm-x86_64/suspend.h 1.2 -> 1.3 # include/asm-alpha/core_cia.h 1.5 -> 1.6 # sound/oss/sb_card.h 1.1 -> 1.2 # arch/arm/Kconfig 1.9 -> 1.12 # drivers/isdn/hisax/gazel.c 1.31 -> 1.32 # fs/ext2/dir.c 1.19 -> 1.20 # drivers/isdn/hisax/isurf.c 1.22 -> 1.23 # drivers/md/raid1.c 1.52 -> 1.56 # include/asm-ia64/intrinsics.h 1.3 -> 1.4 # include/linux/nfsd/export.h 1.26 -> 1.28 # include/asm-ia64/machvec.h 1.8 -> 1.10 # include/asm-ia64/unwind.h 1.3 -> 1.4 # include/asm-i386/numaq.h 1.7 -> 1.10 # net/sunrpc/sched.c 1.22 -> 1.23 # drivers/net/mac8390.c 1.10 -> 1.11 # drivers/usb/serial/pl2303.h 1.7 -> 1.8 # arch/mips/ite-boards/generic/irq.c 1.6 -> 1.7 # include/asm-ia64/machvec_hpsim.h 1.2 -> 1.3 # fs/cifs/cifsfs.c 1.7 -> 1.9 # drivers/pnp/isapnp/core.c 1.31 -> 1.32 # arch/ppc64/Kconfig 1.13 -> 1.14 # mm/mremap.c 1.28 -> 1.29 # drivers/md/raid0.c 1.21 -> 1.23 # arch/ppc/platforms/lopec_setup.c 1.14 -> 1.16 # arch/i386/mm/discontig.c 1.9 -> 1.12 # drivers/char/rio/rioroute.c 1.6 -> 1.7 # arch/ia64/ia32/ia32_entry.S 1.18 -> 1.20 # include/asm-m68knommu/processor.h 1.3 -> 1.4 # usr/Makefile 1.4 -> 1.5 # include/linux/list.h 1.21 -> 1.24 # scripts/Makefile.modpost 1.2 -> 1.3 # Documentation/cpu-freq/governors.txt 1.1 -> 1.2 # arch/x86_64/kernel/process.c 1.14 -> 1.15 # arch/sh/vmlinux.lds.S 1.9 -> 1.10 # net/ipv4/raw.c 1.27 -> 1.28 # Documentation/DocBook/sis900.tmpl 1.2 -> 1.3 # fs/ncpfs/ioctl.c 1.5 -> 1.6 # net/ipv6/tcp_ipv6.c 1.38 -> 1.40 # drivers/pcmcia/tcic.c 1.15 -> 1.16 # net/bluetooth/hci_sock.c 1.17 -> 1.18 # arch/ppc64/kernel/rtc.c 1.6 -> 1.7 # include/asm-ia64/ide.h 1.12 -> 1.13 # include/asm-ia64/iosapic.h 1.5 -> 1.9 # fs/ext3/xattr.c 1.10 -> 1.11 # include/asm-ia64/perfmon.h 1.11 -> 1.12 # Documentation/networking/NAPI_HOWTO.txt 1.3 -> 1.4 # fs/intermezzo/replicator.c 1.3 -> 1.4 # arch/mips/dec/irq.c 1.6 -> 1.7 # include/linux/netfilter_bridge/ebt_nat.h 1.1 -> 1.2 # drivers/pcmcia/hd64465_ss.c 1.10 -> 1.11 # net/ipv4/xfrm_user.c 1.10 -> 1.12 # fs/Kconfig 1.18 -> 1.19 # arch/ia64/kernel/sys_ia64.c 1.20 -> 1.21 # arch/m68knommu/platform/5249/config.c 1.1 -> 1.2 # drivers/block/loop.c 1.82 -> 1.83 # drivers/pnp/resource.c 1.9 -> 1.10 # arch/ia64/kernel/signal.c 1.20 -> 1.21 # Documentation/ia64/fsys.txt 1.4 -> 1.5 # Documentation/magic-number.txt 1.3 -> 1.4 # net/ipv4/esp.c 1.13 -> 1.15 # fs/nfsd/export.c 1.71 -> 1.74 # drivers/ide/ide-probe.c 1.32 -> 1.33 # arch/ppc/syslib/open_pic.c 1.22 -> 1.23 # arch/m68knommu/platform/5206/config.c 1.1 -> 1.2 # include/linux/raid/raid1.h 1.15 -> 1.16 # arch/ppc64/kernel/htab.c 1.31 -> 1.32 # net/rose/rose_in.c 1.5 -> 1.6 # arch/arm/mm/fault-common.c 1.14 -> 1.15 # drivers/acorn/net/ether1.c 1.8 -> 1.9 # drivers/char/tty_io.c 1.63 -> 1.65 # drivers/video/bw2.c 1.1 -> 1.4 # drivers/scsi/pcmcia/fdomain_stub.c 1.12 -> 1.13 # arch/m68k/Kconfig 1.9 -> 1.10 # arch/x86_64/pci/irq.c 1.5 -> 1.6 # include/asm-arm/arch-shark/time.h 1.6 -> 1.7 # net/ipv6/ndisc.c 1.23 -> 1.24 # drivers/usb/core/urb.c 1.11 -> 1.13 # fs/jfs/jfs_txnmgr.c 1.39 -> 1.40 # MAINTAINERS 1.126 -> 1.127 # fs/reiserfs/journal.c 1.65 -> 1.66 # sound/pci/intel8x0.c 1.26 -> 1.27 # arch/parisc/Kconfig 1.10 -> 1.11 # net/ipv6/netfilter/ip6t_esp.c 1.1 -> 1.2 # drivers/usb/class/usb-midi.h 1.3 -> 1.4 # arch/ppc64/kernel/pci_dma.c 1.10 -> 1.11 # usr/gen_init_cpio.c 1.2 -> 1.3 # net/bridge/netfilter/ebt_dnat.c 1.1 -> 1.2 # include/linux/cpufreq.h 1.18 -> 1.22 # drivers/pcmcia/sa1100_generic.c 1.25 -> 1.26 # drivers/char/rio/rio_linux.c 1.14 -> 1.15 # arch/ia64/ia32/sys_ia32.c 1.43 -> 1.45 # arch/sparc64/kernel/sys_sunos32.c 1.28 -> 1.30 # drivers/block/rd.c 1.68 -> 1.69 # net/atm/lec.c 1.14 -> 1.16 # drivers/media/video/msp3400.c 1.13 -> 1.15 # drivers/char/raw.c 1.28 -> 1.29 # drivers/cdrom/mcd.c 1.29 -> 1.30 # mm/mmap.c 1.72 -> 1.74 # arch/i386/kernel/cpu/centaur.c 1.6 -> 1.7 # arch/mips64/kernel/linux32.c 1.11 -> 1.12 # scripts/kconfig/expr.h 1.3 -> 1.4 # include/linux/netfilter_bridge/ebt_redirect.h 1.1 -> 1.2 # fs/ext2/xattr.c 1.9 -> 1.10 # include/asm-sparc64/compat.h 1.7 -> 1.8 # net/unix/af_unix.c 1.35 -> 1.37 # net/sunrpc/svcauth_unix.c 1.14 -> 1.15 # Documentation/kernel-docs.txt 1.4 -> 1.5 # Documentation/input/ff.txt 1.3 -> 1.4 # arch/sparc64/kernel/sys_sparc32.c 1.65 -> 1.67 # include/asm-i386/mach-summit/mach_apic.h 1.20 -> 1.22 # drivers/net/pppoe.c 1.21 -> 1.23 # drivers/hotplug/cpci_hotplug_pci.c 1.6 -> 1.7 # include/linux/compiler.h 1.12 -> 1.13 # fs/intermezzo/file.c 1.8 -> 1.9 # drivers/video/cg3.c 1.1 -> 1.4 # net/bluetooth/rfcomm/sock.c 1.12 -> 1.14 # sound/oss/sb_card.c 1.15 -> 1.17 # drivers/block/z2ram.c 1.21 -> 1.22 # include/linux/if_wanpipe_common.h 1.3 -> 1.4 # net/rose/rose_timer.c 1.7 -> 1.8 # arch/ppc/boot/simple/head.S 1.4 -> 1.5 # Documentation/networking/sk98lin.txt 1.3 -> 1.4 # drivers/net/eepro100.c 1.57 -> 1.59 # init/do_mounts.h 1.3 -> 1.4 # drivers/scsi/pcmcia/Kconfig 1.3 -> 1.4 # include/linux/wanpipe.h 1.5 -> 1.6 # drivers/isdn/i4l/isdn_ppp.c 1.72 -> 1.74 # drivers/net/sk_mca.c 1.8 -> 1.9 # fs/ext2/super.c 1.45 -> 1.46 # include/asm-ia64/ptrace.h 1.8 -> 1.9 # fs/nfs/file.c 1.25 -> 1.26 # arch/ppc64/kernel/eeh.c 1.9 -> 1.10 # drivers/i2c/i2c-algo-ibm_ocp.c 1.4 -> 1.5 # arch/sparc64/solaris/socket.c 1.8 -> 1.10 # arch/m68knommu/platform/5407/config.c 1.1 -> 1.2 # drivers/net/sk98lin/h/skgepnm2.h 1.2 -> 1.3 # drivers/isdn/hisax/telespci.c 1.22 -> 1.23 # drivers/isdn/hisax/hisax.h 1.45 -> 1.49 # arch/arm/mach-sa1100/generic.h 1.5 -> 1.6 # drivers/cdrom/sjcd.c 1.23 -> 1.24 # arch/mips/baget/irq.c 1.7 -> 1.8 # Documentation/i810_rng.txt 1.6 -> 1.7 Documentation/hw_random.txt (moved) # include/asm-ia64/machvec_sn1.h 1.5 -> 1.6 # Documentation/ia64/IRQ-redir.txt 1.1 -> 1.2 # drivers/scsi/sym53c8xx.c 1.29 -> 1.30 # Documentation/md.txt 1.2 -> 1.3 # drivers/scsi/zalon.c 1.2 -> 1.3 # net/packet/af_packet.c 1.18 -> 1.20 # Documentation/ide.txt 1.7 -> 1.8 # arch/i386/oprofile/op_model_ppro.c 1.4 -> 1.5 # drivers/block/paride/pf.c 1.37 -> 1.38 # include/asm-x86_64/unistd.h 1.12 -> 1.13 # mm/page-writeback.c 1.56 -> 1.57 # net/sunrpc/xprt.c 1.50 -> 1.51 # arch/x86_64/kernel/time.c 1.13 -> 1.14 # net/bluetooth/bnep/core.c 1.14 -> 1.15 # net/ipv4/tcp_output.c 1.23 -> 1.24 # net/bluetooth/l2cap.c 1.18 -> 1.20 # drivers/isdn/hisax/hisax_isac.h 1.3 -> 1.4 # drivers/oprofile/oprofile_stats.c 1.2 -> 1.3 # arch/mips/mips-boards/atlas/atlas_int.c 1.4 -> 1.5 # drivers/s390/char/con3215.c 1.12 -> 1.13 # drivers/cdrom/cdu31a.c 1.32 -> 1.33 # net/ax25/ax25_ds_in.c 1.4 -> 1.5 # drivers/net/wan/sdla_x25.c 1.20 -> 1.21 # Documentation/scsi/ibmmca.txt 1.7 -> 1.8 # arch/m68knommu/Kconfig 1.6 -> 1.8 # arch/x86_64/kernel/signal.c 1.14 -> 1.15 # arch/m68knommu/platform/68360/entry.S 1.3 -> 1.4 # Documentation/crypto/api-intro.txt 1.11 -> 1.12 # include/linux/netfilter_bridge/ebt_ip.h 1.2 -> 1.3 # arch/arm/kernel/time.c 1.14 -> 1.15 # arch/ppc64/kernel/sys_ppc32.c 1.49 -> 1.52 # arch/ia64/mm/tlb.c 1.14 -> 1.15 # include/linux/ipv6.h 1.3 -> 1.4 # Documentation/filesystems/directory-locking 1.3 -> 1.4 # drivers/scsi/fdomain.c 1.18 -> 1.19 # drivers/pci/probe.c 1.30 -> 1.33 # init/do_mounts_rd.c 1.1 -> 1.2 # CREDITS 1.77 -> 1.78 # drivers/media/video/tuner.h 1.7 -> 1.8 include/media/tuner.h (moved) # drivers/video/p9100.c 1.1 -> 1.4 # drivers/message/i2o/i2o_block.c 1.51 -> 1.52 # fs/seq_file.c 1.7 -> 1.8 # drivers/media/video/tda7432.c 1.7 -> 1.8 # Documentation/scsi/ChangeLog.ncr53c8xx 1.4 -> 1.5 # arch/i386/kernel/cpu/cpufreq/longrun.c 1.11 -> 1.12 # include/asm-x86_64/compat.h 1.5 -> 1.6 # drivers/usb/host/ohci-pci.c 1.9 -> 1.10 # drivers/net/shaper.c 1.12 -> 1.13 # Documentation/arm/Booting 1.1 -> 1.2 # arch/ppc64/kernel/prom.c 1.18 -> 1.19 # arch/mips64/mips-boards/malta/malta_int.c 1.3 -> 1.4 # arch/i386/kernel/numaq.c 1.6 -> 1.8 # arch/s390x/kernel/linux32.c 1.39 -> 1.41 # include/asm-x86_64/pgtable.h 1.13 -> 1.15 # drivers/eisa/virtual_root.c 1.1 -> 1.2 # net/ipv4/xfrm_state.c 1.9 -> 1.11 # net/core/skbuff.c 1.19 -> 1.20 # include/asm-i386/cpufeature.h 1.6 -> 1.7 # include/linux/sdladrv.h 1.2 -> 1.3 # drivers/scsi/qlogicfc.c 1.27 -> 1.28 # arch/ppc/8xx_io/uart.c 1.18 -> 1.19 # include/net/sock.h 1.30 -> 1.33 # include/asm-parisc/bug.h 1.1 -> 1.2 # net/netrom/nr_timer.c 1.6 -> 1.7 # drivers/media/video/zoran.h 1.1 -> 1.2 # drivers/net/wan/sdlamain.c 1.14 -> 1.15 # drivers/isdn/hisax/isdnl1.h 1.29 -> 1.30 # drivers/media/video/saa7134/saa7134.h 1.3 -> 1.4 # Documentation/scsi/dpti.txt 1.3 -> 1.4 # include/asm-m68k/processor.h 1.7 -> 1.8 # net/core/sock.c 1.14 -> 1.18 # include/net/inet_common.h 1.4 -> 1.5 # include/asm-m68k/sun3_pgtable.h 1.3 -> 1.4 # include/linux/devfs_fs_kernel.h 1.28 -> 1.30 # scripts/kconfig/zconf.l 1.5 -> 1.6 # net/atm/common.h 1.2 -> 1.3 # Documentation/block/biodoc.txt 1.3 -> 1.4 # net/ipv6/ip6_input.c 1.6 -> 1.7 # arch/i386/oprofile/op_model_athlon.c 1.4 -> 1.5 # arch/mips64/kernel/scall_o32.S 1.6 -> 1.7 # Documentation/isdn/INTERFACE 1.5 -> 1.6 # drivers/pnp/driver.c 1.12 -> 1.14 # include/asm-i386/pgtable.h 1.26 -> 1.30 # arch/ia64/ia32/ia32_ioctl.c 1.6 -> 1.7 # Documentation/kbuild/makefiles.txt 1.6 -> 1.7 # drivers/isdn/hisax/mic.c 1.26 -> 1.27 # drivers/s390/block/xpram.c 1.35 -> 1.36 # include/linux/raid/multipath.h 1.14 -> 1.15 # Documentation/networking/3c359.txt 1.1 -> 1.2 # net/ipv6/route.c 1.19 -> 1.21 # drivers/serial/21285.c 1.14 -> 1.15 # drivers/isdn/hisax/hisax_fcpcipnp.c 1.13 -> 1.15 # net/ipv4/tcp_input.c 1.33 -> 1.34 # drivers/scsi/sd.c 1.103 -> 1.105 # arch/m68k/atari/stram.c 1.21 -> 1.22 # drivers/s390/char/tape_block.c 1.1 -> 1.2 # net/ax25/ax25_std_in.c 1.4 -> 1.5 # arch/i386/mm/init.c 1.43 -> 1.45 # net/ipv4/tcp_minisocks.c 1.22 -> 1.24 # arch/ppc64/vmlinux.lds.S 1.12 -> 1.13 # include/asm-arm/proc-armv/tlbflush.h 1.2 -> 1.3 # include/asm-i386/i387.h 1.7 -> 1.10 # Documentation/cpu-freq/core.txt 1.3 -> 1.4 # sound/oss/trident.c 1.35 -> 1.36 # Documentation/arm/XScale/IOP3XX/dma.txt 1.1 -> 1.2 # drivers/serial/8250_pci.c 1.15 -> 1.17 # net/ipv6/Makefile 1.9 -> 1.10 # drivers/media/video/bttv-driver.c 1.25 -> 1.26 # drivers/isdn/hisax/enternow_pci.c 1.19 -> 1.20 # arch/alpha/Kconfig 1.10 -> 1.11 # arch/arm/kernel/ecard.c 1.20 -> 1.21 # drivers/block/DAC960.c 1.52 -> 1.53 # Documentation/scsi/ChangeLog.sym53c8xx 1.5 -> 1.6 # drivers/s390/block/dasd_genhd.c 1.21 -> 1.22 # Documentation/usb/philips.txt 1.6 -> 1.7 # arch/v850/kernel/irq.c 1.5 -> 1.6 # drivers/i2c/i2c-algo-pcf.c 1.8 -> 1.9 # net/atm/signaling.c 1.4 -> 1.5 # mm/slab.c 1.65 -> 1.69 # include/linux/socket.h 1.6 -> 1.7 # include/linux/eisa.h 1.2 -> 1.3 # arch/alpha/kernel/irq.c 1.18 -> 1.19 # drivers/md/dm.c 1.16 -> 1.17 # include/linux/bio.h 1.26 -> 1.27 # net/ipv4/netfilter/ip_nat_standalone.c 1.16 -> 1.18 # fs/filesystems.c 1.11 -> 1.12 # drivers/scsi/scsi_scan.c 1.63 -> 1.64 # arch/x86_64/Kconfig 1.15 -> 1.16 # include/asm-s390/pgtable.h 1.14 -> 1.15 # net/bridge/netfilter/ebt_mark.c 1.1 -> 1.2 # kernel/sched.c 1.161 -> 1.170 # Documentation/s390/cds.txt 1.7 -> 1.8 # drivers/media/video/planb.c 1.12 -> 1.13 # drivers/Makefile 1.31 -> 1.32 # arch/m68knommu/platform/5307/Makefile 1.2 -> 1.3 # drivers/block/paride/pd.c 1.46 -> 1.47 # net/atm/resources.h 1.1 -> 1.2 # arch/ia64/kernel/sigframe.h 1.3 -> 1.4 # include/asm-i386/pgtable-3level.h 1.10 -> 1.11 # init/Kconfig 1.10 -> 1.12 # drivers/usb/storage/sddr09.c 1.22 -> 1.23 # Documentation/sound/oss/NEWS 1.3 -> 1.4 # scripts/Makefile.build 1.31 -> 1.32 # arch/ia64/kernel/gate.S 1.13 -> 1.14 # drivers/block/xd.c 1.49 -> 1.50 # net/ipv6/netfilter/ip6t_hbh.c 1.1 -> 1.2 # drivers/ide/ide-io.c 1.3 -> 1.4 # include/asm-s390x/processor.h 1.10 -> 1.11 # arch/ppc/kernel/irq.c 1.23 -> 1.25 # net/atm/mpc.c 1.8 -> 1.9 # drivers/s390/char/tuball.c 1.8 -> 1.9 # net/bridge/netfilter/ebt_redirect.c 1.1 -> 1.2 # drivers/mtd/ftl.c 1.44 -> 1.45 # drivers/i2c/busses/i2c-amd8111.c 1.3 -> 1.4 # include/linux/atmdev.h 1.7 -> 1.8 # net/ipv6/udp.c 1.18 -> 1.19 # arch/sparc64/kernel/sparc64_ksyms.c 1.38 -> 1.40 # drivers/serial/8250_acorn.c 1.2 -> 1.3 # include/asm-generic/xor.h 1.2 -> 1.3 # drivers/net/eth16i.c 1.12 -> 1.13 # include/net/xfrm.h 1.13 -> 1.16 # scripts/kconfig/zconf.tab.c_shipped 1.4 -> 1.6 # fs/sysfs/inode.c 1.83 -> 1.84 # drivers/media/video/tuner.c 1.14 -> 1.15 # include/asm-m68knommu/pci.h 1.1 -> 1.2 # Documentation/driver-model/platform.txt 1.1 -> 1.2 # fs/sysfs/mount.c 1.5 -> 1.6 # drivers/s390/block/dasd_3990_erp.c 1.11 -> 1.12 # arch/ppc64/kernel/sys32.S 1.11 -> 1.13 # include/linux/raid/raid5.h 1.14 -> 1.15 # Documentation/computone.txt 1.3 -> 1.4 # arch/m68knommu/platform/68360/commproc.c 1.2 -> 1.3 # arch/ia64/vmlinux.lds.S 1.27 -> 1.28 # drivers/media/video/saa7134/saa7134-cards.c 1.3 -> 1.4 # drivers/char/vt.c 1.32 -> 1.35 # drivers/char/hvc_console.c 1.12 -> 1.13 # scripts/per-cpu-check.awk 1.3 -> 1.4 # drivers/i2c/busses/i2c-amd756.c 1.3 -> 1.4 # arch/ppc64/xmon/xmon.c 1.23 -> 1.24 # drivers/i2c/busses/Kconfig 1.4 -> 1.7 # arch/ppc64/kernel/pci.c 1.22 -> 1.24 # include/asm-arm/ecard.h 1.6 -> 1.7 # arch/sparc64/vmlinux.lds.S 1.16 -> 1.17 # drivers/scsi/aic7xxx/aicasm/Makefile 1.8 -> 1.9 # arch/arm/mach-sa1100/system3.c 1.16 -> 1.17 # drivers/pci/setup-res.c 1.12 -> 1.13 # drivers/isdn/hisax/config.c 1.43 -> 1.46 # drivers/acorn/net/etherh.c 1.12 -> 1.13 # arch/sparc64/Kconfig 1.14 -> 1.16 # arch/ppc64/kernel/misc.S 1.50 -> 1.52 # net/ipv4/netfilter/iptable_mangle.c 1.8 -> 1.10 # include/asm-s390x/fcntl.h 1.2 -> 1.3 # arch/ia64/kernel/irq.c 1.18 -> 1.20 # fs/cifs/CHANGES 1.8 -> 1.10 # include/asm-parisc/pgtable.h 1.10 -> 1.11 # net/ipv4/ah.c 1.11 -> 1.13 # include/asm-x86_64/proto.h 1.7 -> 1.8 # arch/m68k/vmlinux-std.lds 1.14 -> 1.15 # arch/i386/kernel/cpu/proc.c 1.8 -> 1.9 # arch/arm/mach-integrator/Makefile 1.6 -> 1.7 # drivers/pcmcia/i82365.c 1.23 -> 1.24 # include/asm-x86_64/ia32.h 1.10 -> 1.13 # drivers/isdn/hisax/w6692.c 1.50 -> 1.51 # fs/hugetlbfs/inode.c 1.21 -> 1.22 # net/bridge/netfilter/ebtable_filter.c 1.2 -> 1.3 # arch/sparc64/kernel/ioctl32.c 1.53 -> 1.54 # drivers/cpufreq/freq_table.c 1.1 -> 1.3 # drivers/media/video/tvmixer.c 1.11 -> 1.12 # arch/ppc/kernel/ppc-stub.c 1.6 -> 1.8 # drivers/scsi/Kconfig 1.16 -> 1.17 # fs/ext3/super.c 1.51 -> 1.53 # arch/arm/kernel/Makefile 1.15 -> 1.16 # arch/ia64/tools/print_offsets.c 1.13 -> 1.16 # scripts/kconfig/menu.c 1.2 -> 1.4 # include/linux/device.h 1.83 -> 1.85 # fs/cifs/connect.c 1.11 -> 1.13 # drivers/cdrom/cm206.c 1.29 -> 1.30 # arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 1.12 -> 1.14 # drivers/pci/Makefile 1.23 -> 1.24 # scripts/kconfig/zconf.y 1.3 -> 1.5 # arch/arm/common/sa1111.c 1.22 -> 1.23 # fs/partitions/check.c 1.95 -> 1.96 # arch/cris/Kconfig 1.5 -> 1.6 # scripts/kconfig/lex.zconf.c_shipped 1.5 -> 1.6 # include/asm-ia64/siginfo.h 1.11 -> 1.12 # drivers/serial/68328serial.h 1.2 -> 1.3 # drivers/serial/Kconfig 1.5 -> 1.6 # net/ax25/af_ax25.c 1.17 -> 1.19 # include/asm-ia64/pci.h 1.11 -> 1.12 # net/ax25/ax25_ds_timer.c 1.8 -> 1.9 # net/ipv4/tcp_timer.c 1.12 -> 1.13 # drivers/cdrom/aztcd.c 1.26 -> 1.27 # include/net/dst.h 1.10 -> 1.11 # drivers/net/bonding.c 1.17 -> 1.18 # include/asm-x86_64/segment.h 1.6 -> 1.7 # fs/intermezzo/methods.c 1.6 -> 1.7 # net/atm/raw.c 1.1 -> 1.2 # arch/ia64/kernel/perfmon.c 1.35.1.1 -> 1.38 # drivers/hotplug/cpqphp_pci.c 1.15 -> 1.16 # net/ax25/ax25_subr.c 1.5 -> 1.6 # net/sctp/ulpqueue.c 1.13 -> 1.14 # arch/i386/oprofile/nmi_int.c 1.8 -> 1.9 # include/asm-i386/mach-bigsmp/mach_apic.h 1.6 -> 1.8 # drivers/isdn/hisax/diva.c 1.39 -> 1.40 # net/ipv4/icmp.c 1.26 -> 1.27 # drivers/pnp/card.c 1.8 -> 1.10 # fs/locks.c 1.37 -> 1.39 # drivers/isdn/hisax/hfcscard.c 1.15 -> 1.16 # net/atm/resources.c 1.6 -> 1.7 # drivers/char/rio/riotable.c 1.7 -> 1.8 # drivers/oprofile/cpu_buffer.h 1.3 -> 1.4 # arch/ia64/Kconfig 1.14 -> 1.18 # arch/s390x/kernel/linux32.h 1.7 -> 1.8 # drivers/video/cg14.c 1.1 -> 1.4 # drivers/char/Makefile 1.55 -> 1.56 # net/x25/af_x25.c 1.21 -> 1.23 # include/asm-ia64/sal.h 1.12 -> 1.14 # drivers/isdn/hisax/ix1_micro.c 1.26 -> 1.27 # crypto/api.c 1.26 -> 1.27 # include/linux/netfilter_bridge/ebtables.h 1.2 -> 1.3 # fs/cifs/TODO 1.3 -> 1.4 # drivers/char/sh-sci.c 1.12 -> 1.13 # arch/arm/mach-sa1100/irq.c 1.12 -> 1.13 # drivers/pnp/manager.c 1.4 -> 1.5 # drivers/serial/68360serial.c 1.6 -> 1.7 # fs/cifs/misc.c 1.5 -> 1.6 # arch/ia64/kernel/traps.c 1.25 -> 1.26 # arch/arm/vmlinux-armo.lds.in 1.13 -> 1.14 # drivers/ide/ide-lib.c 1.6 -> 1.7 # drivers/block/cciss.c 1.74 -> 1.76 # arch/ia64/mm/fault.c 1.10 -> 1.12 # include/asm-sparc64/fcntl.h 1.4 -> 1.5 # drivers/parport/ieee1284_ops.c 1.9 -> 1.10 # drivers/macintosh/macserial.c 1.12 -> 1.13 # include/linux/netfilter_bridge/ebt_log.h 1.1 -> 1.2 # arch/x86_64/boot/setup.S 1.3 -> 1.4 # arch/x86_64/ia32/ia32_signal.c 1.10 -> 1.11 # drivers/block/paride/pcd.c 1.31 -> 1.32 # drivers/serial/68328serial.c 1.2 -> 1.3 # net/rose/rose_route.c 1.6 -> 1.7 # include/asm-i386/serial.h 1.2 -> 1.3 # drivers/isdn/hisax/sedlbauer.c 1.33 -> 1.34 # drivers/pci/setup-bus.c 1.13 -> 1.14 # include/asm-ppc64/topology.h 1.5 -> 1.6 # net/atm/clip.c 1.6 -> 1.7 # net/rose/rose_subr.c 1.6 -> 1.7 # drivers/acorn/net/ether3.c 1.12 -> 1.13 # net/wanrouter/af_wanpipe.c 1.15 -> 1.18 # include/asm-x86_64/processor.h 1.12 -> 1.13 # fs/mbcache.c 1.3 -> 1.4 # net/x25/x25_in.c 1.9 -> 1.10 # include/linux/if_wanpipe.h 1.3 -> 1.4 # arch/s390x/kernel/wrapper32.S 1.17 -> 1.19 # arch/mips64/mips-boards/atlas/atlas_int.c 1.3 -> 1.4 # include/linux/pnp.h 1.14 -> 1.17 # net/ipv4/igmp.c 1.13 -> 1.15 # arch/ppc/Kconfig 1.17 -> 1.18 # arch/ia64/kernel/ptrace.c 1.18 -> 1.20 # net/bridge/netfilter/ebtable_nat.c 1.2 -> 1.3 # drivers/net/wan/sdla_fr.c 1.23 -> 1.24 # Documentation/usb/scanner.txt 1.4 -> 1.5 # arch/ia64/sn/kernel/sn2/Makefile 1.8 -> 1.9 # arch/cris/kernel/irq.c 1.9 -> 1.10 # fs/inode.c 1.83 -> 1.84 # arch/ia64/kernel/smp.c 1.22 -> 1.23 # arch/sh/Kconfig 1.7 -> 1.8 # include/asm-alpha/processor.h 1.8 -> 1.9 # arch/ia64/kernel/init_task.c 1.7 -> 1.8 # fs/intermezzo/super.c 1.11 -> 1.12 # net/ipv4/route.c 1.40 -> 1.42 # drivers/scsi/imm.c 1.18 -> 1.19 # arch/i386/kernel/i386_ksyms.c 1.46 -> 1.49 # include/linux/slab.h 1.17 -> 1.18 # drivers/block/acsi.c 1.47 -> 1.48 # arch/i386/kernel/sysenter.c 1.9 -> 1.11 # drivers/isdn/hisax/teles3.c 1.25 -> 1.26 # drivers/block/umem.c 1.34 -> 1.35 # scripts/kconfig/Makefile 1.5 -> 1.6 # include/asm-sparc/processor.h 1.11 -> 1.12 # arch/mips/arc/arc_con.c 1.1 -> 1.2 # Documentation/sound/oss/PSS-updates 1.3 -> 1.4 # arch/parisc/kernel/syscall.S 1.7 -> 1.8 # net/appletalk/ddp.c 1.16 -> 1.18 # arch/i386/pci/irq.c 1.20 -> 1.22 # drivers/isdn/hisax/asuscom.c 1.31 -> 1.32 # drivers/ide/pci/amd74xx.c 1.14 -> 1.15 # drivers/char/amiserial.c 1.12 -> 1.13 # include/asm-i386/mach-default/mach_apic.h 1.20 -> 1.22 # drivers/net/wan/wanpipe_multppp.c 1.11 -> 1.12 # drivers/scsi/qlogicfas.c 1.17 -> 1.18 # drivers/isdn/hisax/teleint.c 1.19 -> 1.20 # Documentation/cpu-freq/cpu-drivers.txt 1.1 -> 1.4 # include/asm-ia64/thread_info.h 1.6 -> 1.8 # arch/arm/mach-sa1100/Makefile 1.24 -> 1.26 # arch/i386/kernel/i387.c 1.12 -> 1.14 # drivers/video/leofb.c 1.11 -> (deleted) # net/ipv6/netfilter/ip6t_ipv6header.c 1.1 -> 1.2 # include/asm-arm/arch-sa1100/time.h 1.6 -> 1.7 # drivers/isdn/hisax/avm_a1p.c 1.24 -> 1.25 # drivers/hotplug/ibmphp_core.c 1.23 -> 1.24 # arch/ppc/boot/common/util.S 1.4 -> 1.5 # arch/arm/mach-sa1100/Kconfig 1.3 -> 1.4 # include/asm-parisc/processor.h 1.8 -> 1.9 # include/asm-ia64/mmzone.h 1.3 -> 1.4 # Documentation/video4linux/bttv/Sound-FAQ 1.6 -> 1.7 # arch/ppc64/boot/main.c 1.5 -> 1.6 # drivers/pnp/system.c 1.6 -> 1.8 # fs/block_dev.c 1.122 -> 1.123 # include/asm-sh/pgtable.h 1.13 -> 1.16 # arch/x86_64/pci/direct.c 1.3 -> 1.4 # arch/i386/mm/pgtable.c 1.8 -> 1.9 # mm/pdflush.c 1.17 -> 1.18 # include/asm-x86_64/desc.h 1.7 -> 1.8 # arch/ia64/kernel/unwind.c 1.11 -> 1.16 # arch/ppc64/kernel/pSeries_pci.c 1.20 -> 1.22 # net/netrom/nr_subr.c 1.5 -> 1.6 # drivers/video/ffb.c 1.1 -> 1.4 # include/asm-um/pgtable.h 1.7 -> 1.10 # drivers/char/rio/rioparam.c 1.3 -> 1.4 # net/atm/common.c 1.12 -> 1.14 # include/asm-parisc/compat.h 1.2 -> 1.3 # arch/ppc/vmlinux.lds.S 1.17 -> 1.18 # drivers/isdn/i4l/isdn_ppp_mp.h 1.3 -> 1.4 # (new) -> 1.1 arch/ia64/sn/io/sn2/ml_iograph.c # (new) -> 1.1 arch/ia64/sn/io/sn2/xtalk.c # (new) -> 1.1 arch/ia64/sn/io/sn2/ml_SN_init.c # (new) -> 1.1 include/asm-ia64/sn/rw_mmr.h # (new) -> 1.1 arch/ia64/sn/io/sn2/klconflib.c # (new) -> 1.1 arch/ia64/sn/io/sn2/module.c # (new) -> 1.1 arch/ia64/sn/kernel/iomv.c # (new) -> 1.1 arch/ia64/sn/io/sn2/pci_bus_cvlink.c # (new) -> 1.1 include/net/ah.h # (new) -> 1.1 arch/i386/boot/mtools.conf.in # (new) -> 1.4 drivers/i2c/busses/i2c-piix4.c # (new) -> 1.1 include/net/compat_socket.h # (new) -> 1.1 arch/ia64/sn/io/sn2/sgi_io_init.c # (new) -> 1.2 include/asm-ia64/rwsem.h # (new) -> 1.1 arch/ia64/sn/io/sn2/l1_command.c # (new) -> 1.1 Documentation/basic_profiling.txt # (new) -> 1.1 arch/ia64/sn/io/sn2/xbow.c # (new) -> 1.1 arch/m68knommu/platform/68VZ328/de2/Makefile # (new) -> 1.1 scripts/kconfig/gconf.glade # (new) -> 1.3 drivers/i2c/busses/i2c-i801.c # (new) -> 1.1 include/asm-ia64/sn/pci/pic.h # (new) -> 1.3 drivers/i2c/busses/i2c-ali15x3.c # (new) -> 1.1 arch/ia64/sn/io/sn2/shub.c # (new) -> 1.1 net/compat.c # (new) -> 1.1 arch/ia64/sn/io/sn2/pic.c # (new) -> 1.1 arch/arm/mach-sa1100/ssp.c # (new) -> 1.1 arch/ia64/sn/io/sn2/geo_op.c # (new) -> 1.1 arch/ia64/sn/io/sn2/klgraph.c # (new) -> 1.1 include/asm-ia64/sn/geo.h # (new) -> 1.2 net/ipv6/esp6.c # (new) -> 1.1 Documentation/eisa.txt # (new) -> 1.1 arch/ia64/sn/io/ioconfig_bus.c # (new) -> 1.1 include/net/esp.h # (new) -> 1.2 net/ipv6/ah6.c # (new) -> 1.1 arch/m68knommu/platform/68VZ328/ucdimm/Makefile # (new) -> 1.1 arch/ia64/sn/io/sn2/l1.c # (new) -> 1.1 arch/x86_64/ia32/tls32.c # (new) -> 1.1 arch/ia64/sn/io/sn2/shubio.c # (new) -> 1.1 drivers/video/leo.c # (new) -> 1.1 arch/ia64/sn/io/sn2/pcibr/Makefile # (new) -> 1.1 scripts/kconfig/gconf.c # (new) -> 1.1 include/asm-ia64/sn/ioconfig_bus.h # (new) -> 1.1 arch/arm/kernel/apm.c # (new) -> 1.1 arch/ia64/sn/kernel/sn2/ptc_deadlock.S # (new) -> 1.2 drivers/pci/bus.c # (new) -> 1.1 arch/ia64/sn/kernel/sn2/sn_proc_fs.c # (new) -> 1.1 arch/ia64/sn/io/sn2/pciio.c # (new) -> 1.1 arch/arm/kernel/pm.c # (new) -> 1.1 arch/ia64/sn/io/sn2/Makefile # (new) -> 1.1 arch/m68knommu/platform/5307/timers.c # (new) -> 1.1 include/asm-ia64/sn/sn2/geo.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/03/04 torvalds@home.transmeta.com 1.1068.2.17 # Linux 2.5.64 # -------------------------------------------- # 03/03/05 davem@redhat.com 1.1068.2.18 # [PATCH] Fix time comparison typing bugs. # # Many places use inappropriate types for comparing jiffies, # int for example. Fix those places up. # -------------------------------------------- # 03/03/06 anton@samba.org 1.1068.1.9 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.2.19 # Merge nuts.ninka.net:/home/davem/src/BK/sparcwork-2.5 # into nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.2.20 # [SPARC64]: Fix cpufreq config deps. # -------------------------------------------- # 03/03/05 Jeff.Wiedemeier@hp.com 1.1025.21.2 # [PATCH] enable setting of marvel/titan agp->type # # Now that the agpgart support is in, this can be enabled. # # /jeff # -------------------------------------------- # 03/03/05 greg@kroah.com 1.1068.9.1 # [PATCH] USB: add support for Treo devices to the visor driver. # # Finally... # -------------------------------------------- # 03/03/05 clemens@ladisch.de 1.1068.9.2 # [PATCH] usb-midi.h: fixes for SC-8820/50 # # sync with Nagano's version: # - protect vendors ids against multiple definitions # - sort Roland device ids # - fix SC-8850 cable bitmask # - add quirk for the SC-8820 # - add quirk for the MOTU Fastlane # -------------------------------------------- # 03/03/05 andre.breiler@null-mx.org 1.1068.9.3 # [PATCH] io_edgeport.c diff to fix endianess bugs # # attached a fix for the io_edgeport usb serial driver # This diff fixes endianess issues which prevented the driver to work on # bigendian machines (e.g. sparc). # -------------------------------------------- # 03/03/05 andmike@us.ibm.com 1.1068.2.21 # [PATCH] Fix SCSI error handler abort case # # I had my list empty checks reversed if aborting and bus device reset # failed. The condition that causes the error handler to run is still # unknown. # -------------------------------------------- # 03/03/05 greg@kroah.com 1.1068.9.4 # [PATCH] USB: added support for radio shack device to pl2303 driver. # # Thanks to gene_heskett@iolinc.net for the info for this. # -------------------------------------------- # 03/03/05 levon@movementarian.org 1.1068.2.22 # [PATCH] Fix oprofile on UP, small additional fix # # The below has been in -mm for a while, and has been tested on my UP # and 2-way machines. # # OProfile was completely unsafe on UP - a spinlock is no protection # against the NMI arriving and putting data into the buffer. Pretty stupid # bug. This fixes it by implementing reader/writer windows in the buffer # and removing the lock altogether. This patch was originally done by Will # Cohen. # # It also fixes the oops Dave Hansen saw on 2.5.62 SMP # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1070 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/03/06 anton@samba.org 1.1068.1.10 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.10.1 # sysfs: Make sure root inode is executable and readable by everyone. # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.10.2 # driver model: fix platform_match() # # - Make it compare the name in struct platform_dev to the driver's name. # # From Dominik Brodowski # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.10.3 # sysfs: don't complain when sysfs can't register. # # During startup, sysfs won't succeed in registering with itself, because # it's not yet inititialized. This was causing an unnecessary error on boot. # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.10.4 # cpufreq: fix compile error. # # Use ->dev instead of ->intf.dev in struct cpufreq_policy. Introduced whilst # cleaning up part of the cpufreq code. # -------------------------------------------- # 03/03/05 miyazawa@linux-ipv6.org 1.1071 # [IPSEC]: Add full ipv6 support. # # Credits also to Mitsuru Kanda , # YOSHIFUJI Hideaki , # and Kunihiro Ishiguro. # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.2.23 # Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin # into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core # -------------------------------------------- # 03/03/05 torvalds@home.transmeta.com 1.1068.11.1 # Merge bk://ldm.bkbits.net/linux-2.5-core # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 anton@samba.org 1.1068.1.11 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/05 kai@tp1.ruhr-uni-bochum.de 1.1068.12.1 # kbuild: Make build stop on vmlinux link error # # set -e is needed for each (continued) line. # -------------------------------------------- # 03/03/05 kai@tp1.ruhr-uni-bochum.de 1.1068.12.2 # kbuild: Add some missing FORCE # # Those were missing, not particularly harmful, but still needed for # correctness. # -------------------------------------------- # 03/03/05 kai@tp1.ruhr-uni-bochum.de 1.1068.12.3 # kbuild: Make per-cpu-check ignore __crc_ symbols. # # We warn when symbols end in __per_cpu, but aren't in the per-cpu section. # However, checksum symbols gave false positives. # -------------------------------------------- # 03/03/05 sam@mars.ravnborg.org 1.1068.12.4 # [PATCH] kbuild: Smart notation for non-verbose output # # Create a nice shorthand to enable the non-verbose output mode. # make V=1 => Gives verbose output (default) # make V=0 => Gives non-verbose output # # One of the reasons why people does not use KBUILD_VERBOSE=0 that # much is simply the typing needed. # This notation should make it acceptable to type it. # The usage of "make V=0" is restricted to the command line. # Anyone that wants to enable the non-verbose mode pr. default shall # set KBUILD_VERBOSE in the shell. # -------------------------------------------- # 03/03/05 arnd@arndb.de 1.1068.12.5 # [trivial] avoid a warning for each module on s390x # # s390x has a reference to _GLOBAL_OFFSET_TABLE_ in each module # that is resolved by the module loader. This patch prevents # modpost from emitting a warning about that symbol. # -------------------------------------------- # 03/03/05 sam@mars.ravnborg.org 1.1068.12.6 # [PATCH] kbuild: touch-module after successfull creation only # # On Mon, Mar 03, 2003 at 05:11:10PM -0500, Bill Davidsen wrote: # > scripts/Makefile.modinst:16: *** Uh-oh, you have stale module entries. You # messed with SUBDIRS, do not complain if something goes wrong. # # This happens if you have encountered a compile error in a module. # In this case you did not succeed the compilation of fs/binfmt_aout, # and therefore no .o file can be located. # kbuild assumes this is because you have messed with SUBDIRS, which is wrong. # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.11.2 # [KERNEL]: Add typecheck macro for verifying types at compile time. # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.11.3 # [JIFFIES]: Use typecheck in time_foo jiffies macros. # -------------------------------------------- # 03/03/05 torvalds@home.transmeta.com 1.1068.11.4 # Fix up some timeouts to use the proper types. # # (While "signed long" is the same in practice, it is technically # incorrect, and the new anal type-checker complains). # -------------------------------------------- # 03/03/06 anton@samba.org 1.1068.1.12 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.1 # [ARM] Remove set_mac_address from acorn drivers. # # Acorn Ethernet drivers provided a duplicate set_mac_address # implementation which reflects the generic ethernet version in # drivers/net/net_init.c. Use the generic version instead. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.2 # [ARM] Convert ecard.c shutdown/reboot to use driver model # # ecard.c used to use the reboot notifier to ensure that the expansion # cards are in the correct state for rebooting. Use the driver model # shutdown method instead. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.3 # [ARM] Always call schedule_tail() after a fork() # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.4 # [ARM] Always claim the timer IRQ using SA_INTERRUPT. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.5 # [ARM] Add new kernel typedefs for __kernel_{timer,clockid}_t. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.6 # [ARM] Add dummy set_pgd() implementation. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.7 # [ARM] Make ARM's pci_controller_num dev argument appear to be used. # # This cuts down on the number of warnings during the build. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.8 # [ARM] Kill old mkdep dependency hack. # # We include a header file in an indirect method, which mkdep didn't # understand. Now that mkdep is gone, we don't need the hack to make # mkdep do the right thing. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.9 # [ARM] Fix ARM ide.h # # Kill ide_* resource handling. Add __ide_mm* macros to use our string # based mmio. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.10 # [ARM] Make TLB instruction selection more fine-grained # # This eliminates some unnecessary branches and instructions in the # TLB flush macros where configurations allow for this to occur. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.11 # [ARM] Update mach-types to latest vesion. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.12 # [ARM] Ensure we preserve other CPSR bits when switching to SVC mode. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.13 # [ARM] Power management updates # # This provides an element of core PM support to ARM, providing an APM # like user space interface, and separating the core PM support from # the SA1100 PM implementation. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.14 # [ARM] Add better PM support to SA1111 and SA11x0. # # This follows our existing PM interfaces. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.15 # [ARM] Clean up ARM PCI support (bios32.c) # # Eliminate have_isa_bridge - use isa_bridge instead. # Clean up PCI bus walking. # Clean up detection of fast back to back capability. # Ensure we set the bridge control register appropriately. # Pin swizzle functions are never called with pin == 0. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.16 # [CPUFREQ] Update ARM CPUFREQ drivers # # A 4 patch set from Dominik Brodowski, tested and fixed up by rmk # for ARM. # # (1) # # - the system3.c cpufreq notifier couldn't possibly compile before because # cpufreq_updateminmax has been undefined for ages. # - clean up sa1100fb.c notifier to specify exactly what's left TBD. # - double #include of cpufreq.c in drivers/pcmcia/sa1100_generic.c # # (2) # # Split up config symbols, add help text for CPU_FREQ_PROC_INTF # # (3) # # - update the Integrator CPUfreq driver so that it can get along with # cpufreq policies. # - modularize Integrator CPUfreq driver (all it did with # !CONFIG_CPU_FREQ was to print out some debug information) # # (4) # # - update the SA11x0 CPUfreq drivers so that they can get along with # cpufreq policies and governors. # - update the cpufreq core so that cpufreq_get() returns something # sensible during the first ->setpolicy or ->target call. # -------------------------------------------- # 03/03/06 jmorris@intercode.com.au 1.1072 # [IPV4]: Fix multicast route lookups. # -------------------------------------------- # 03/03/06 laforge@netfilter.org 1.1073 # [NETFILTER]: Fix ipv6 build. # -------------------------------------------- # 03/03/06 davem@kernel.bkbits.net 1.1074 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/03/06 ink@jurassic.park.msu.ru 1.1025.21.3 # [PATCH] alpha pcibios_claim_console_setup fix # # pcibios_claim_console_setup() doesn't look behind PCI-PCI bridges. # # Noticed by Anton Blanchard. # # Ivan. # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075 # Merge bk://are.twiddle.net/axp-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1073.1.1 # [NETFILTER]: Remove 2.0 and 2.2 stuff from netfilter. # -------------------------------------------- # 03/03/06 davem@nuts.ninka.net 1.1076 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/03/06 bcrl@redhat.com 1.1077 # [NET]: Simplify scm handling and sendmsg/recvmsg invocation, consolidate net compat syscalls. # # 1) Pull scm argument from sendmsg/recvmsg, it is available # from I/O control block # 2) Consolidate networking syscall compat call into net/compat.c # 3) Change ops->{sendmsg,recvmsg}() code sequences into sock_{sendmsg,recvmsg}() # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.914.127.34 # ia64: Make ia64_fetch_and_add() simpler to optimize so lib/rwsem.c # can be optimized properly. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.17 # [ARM] CPUFREQ - allow ARM to work with userspace governor. # # Patch from Dominik Brodowski. # # This patch is necessary to update the ARM drivers so that they can # live with the new cpufreq governor "userspace" (which I sent to Linus a # moment ago). # -------------------------------------------- # 03/03/06 davem@nuts.ninka.net 1.1078 # [NET]: Do not duplicate verify_compat_iovec in sparc64 solaris module. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.4.18 # [CPUFREQ] Make sa11x0_ppcr_to_freq return in units of kHz, not 100kHz. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1068.11.5 # Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5 # into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-rmk # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.1.1 # Make the "interactive bonus" work both ways - both the process # that is actually showing interactive behaviour (sleeping) and the # process that wakes up the interative process get a bonus. # # This means that processes that help interactive processes (usually # system daemons, and X11 in particular) will themselves get some bonus. # # The waker only gets whatever is left over from the "real" interactive # user, to avoid any bad behaviour. # -------------------------------------------- # 03/03/06 mingo@elte.hu 1.1075.2.1 # [PATCH] "interactivity changes", sched-2.5.64-A6 # # This includes the following items: # # - a new wakeup feature: SMART_WAKE_CHILD (now unconditional) [this is a # reworked version of the wakeup changes from Andrea's tree.] # # - scheduler parameter tunings (CHILD_PENALTY, MAX_TIMESLICE, # STARVATION_LIMIT, MAX_SLEEP_AVG) # # - activate_task() splitup to separate the interactivity-active variant # from the task-queue variant => this fixes our statistics in some cases. # # - finer-grained preemption: if priority is equal then the task with the # longer pending timeslice wins. # # - make it possible to disable sync-wakeups via SYNC_WAKEUPS (default:1) # # - a naming cleanup (sleep_timestamp => last_run) # # - fix up STARVATION_LIMIT usage so that a value of 0 is recognized as 'no # starvation limit'. # # It also merges Linus' "priority boost backmerging" # -------------------------------------------- # 03/03/06 torvalds@penguin.transmeta.com 1.1075.1.2 # Merge # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.13.1 # ia64: Sync with 2.5.64. # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.13.2 # ia64: Correct the value of siginfo.si_addr for SIGSEGV signals # triggered by NaT-page-consumption faults. # -------------------------------------------- # 03/03/06 ambx1@neo.rr.com 1.1075.1.3 # Manual Resource Setting Update # # This patch allows for partial setting of manual resources as needed by ALSA. # It does not change any existing APIs. # -------------------------------------------- # 03/03/06 stern@rowland.harvard.edu 1.1068.9.5 # [PATCH] USB: Patch for auto-sense cmd_len # # This patch fixes an oversight in usb-storage whereby the command length # and command buffer for an automatically-generated REQUEST-SENSE command # would not be initialized properly. # -------------------------------------------- # 03/03/07 anton@samba.org 1.1075.3.1 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.13.3 # ia64: Hook up POSIX-timer syscalls. Take advantage of ptrace_notify(). # -------------------------------------------- # 03/03/06 david-b@pacbell.net 1.1068.9.6 # [PATCH] USB: track usb ch9 device state # # This patch merges the USB state definitions from the ARM Linux # code (inside the sa1100 driver) and uses them to track what can # be done with the device. That replaces the recently added # "udev->present" flag with a more complete/standard state model. # # There are a few changes that might affect behavior if things # start to go really haywire: # # - usb_set_address() and usb_set_configuration(), used while # enumerating, handle some unlikely cases more correctly: # don't allow setting address to zero (undefined behavior), # and do allow un-configuring (config 0). (Adds a FIXME # for an existing set-configuration bug too.) # # - usb_disconnect() flags the state change earlier (as soon # as it's known). # # - usb_submit_urb() works in the states where messaging is # allowed, and also enforces the "unless configured, only # control traffic is legal" rule. # # - usb_unlink_urb() doesn't care any more about that state. # (There seemed to be agreement that it must not matter.) # # This will help with some further cleanups in the complex of # issues relating to driver removal, device removal, config # changing (with driver unbind and rebind), reset, and so on. # -------------------------------------------- # 03/03/06 greg@kroah.com 1.1068.9.7 # [PATCH] USB: unfortunatly, we can't call usb_unlink_urb() right now all of the time. # # The host controllers have to be fixed up before we can safely take # out the check for dev->state. # -------------------------------------------- # 03/03/06 greg@kroah.com 1.1075.4.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/03/07 rmk@flint.arm.linux.org.uk 1.1068.11.6 # [ARM] Add generic SSP "PIO" mode driver # # Add SSP PIO driver - provides an interface for talking to # microcontrollers and such like connected to the SA1110's # SSP port. # -------------------------------------------- # 03/03/06 davem@nuts.ninka.net 1.1075.5.1 # [IPSEC]: Fix build when ipsec is disabled. # -------------------------------------------- # 03/03/06 davem@kernel.bkbits.net 1.1075.6.1 # Merge davem@nuts.ninka.net:/home/davem/src/BK/netfix-2.5 # into kernel.bkbits.net:/home/davem/netfix-2.5 # -------------------------------------------- # 03/03/06 kai@tp1.ruhr-uni-bochum.de 1.1068.12.7 # do_mounts: Fix boot from ramdisk # # Russell King investigated a failure case I introduced: When booting # with "load_ramdisk=1", we use the kernel root= parameter to determine # from what device to get the contents to copy into a ramdisk and then # mount that ramdisk as root. # # For the copy to work, /dev/root needs to point to the device to load the # ramdisk from. # -------------------------------------------- # 03/03/06 rddunlap@osdl.org 1.1079 # [IPV4/IPV6]: ICMP cleanups. # -------------------------------------------- # 03/03/06 kai@tp1.ruhr-uni-bochum.de 1.1075.7.1 # Merge tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5 # into tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5.make # -------------------------------------------- # 03/03/06 hch@lst.de 1.1075.8.1 # [PATCH] update fdomain pcmcia support # # get it to actually compile cleanly again, switch to scsi_add_host, # remove host list walking. # -------------------------------------------- # 03/03/06 hch@lst.de 1.1075.8.2 # [PATCH] update qlogic pcmcia support # # dito # -------------------------------------------- # 03/03/06 willy@debian.org 1.1075.8.3 # [PATCH] Remove naked GFP_DMA from drivers/scsi/sd.c # # This GFP_DMA can be GFP_KERNEL because sd_init_onedisk calls sd_spinup_disk # calls scsi_wait_req which can sleep. # -------------------------------------------- # 03/03/06 willy@debian.org 1.1075.8.4 # [PATCH] Remove naked GFP_DMA from drivers/scsi/sr.c # # In get_sectorsize(), we can already sleep in scsi_wait_req(). # In get_capabilities(), we can use GFP_KERNEL because it is only called # from sr_attach() which already does a GFP_KERNEL allocation. # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.4.2 # Merge bk://kernel.bkbits.net/davem/netfix-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.4.3 # Merge bk://bk.arm.linux.org.uk # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.4.4 # Merge http://linux-isdn.bkbits.net/linux-2.5.make # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.5 # [PATCH] i386 IRQ balancing cleanup # # General coding cleanups in io_apic.c: # # - make pending_irq_balance_apicid[] static # # - reorder several functions so that forward decls are not needed and so # that `inline' actually works. # # - 80 col fixes. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.6 # [PATCH] balance_irq lockup fix # # irqdesc_t.lock is taken from interrupts - it needs irq-safe locking from # process context. # # Also timer_irq_works() needs to use an unsigned long to hold a jiffies value # (Kai Bankett) # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.7 # [PATCH] Fix nfs oops during mount # # Patch from Trond Myklebust # # This has been floating about for a while, and fixes the oops which people # keep on reporting. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.8 # [PATCH] rtc lock ranking fix # # Patch from: Zwane Mwaikambo # # Fix up a possible AB/BA deadlock identified by Dawson Engler's latest toy. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.9 # [PATCH] sk98lin 64-bit divide fix # # This driver is doing a division on a 64 bit valus which is identical to # "jiffies" and is asking for __udiv64. Cast the 64-bit value back to long. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.10 # [PATCH] cciss: fix initialization for PCI hotplug # # Patch from Stephen Cameron # # * Fix driver to wait for firmware to indicate that it is ready. # (Needed for PCI hotplug case, but for normal warm/cold reboot, by the # time driver inits, firmware will already be ready.) # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.11 # [PATCH] export pfn_to_nid to modules # # Patch from Patricia Gaughen # # This function was recently uninlined for NUMAQ. But it used to be a macro, # and modules need it. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.12 # [PATCH] Reduced stack usage in random.c # # Patch from: Matthew Wilcox # # Reduces stack use in random.c by 350 (or maybe 700) bytes by sharing a local # array between two functions. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.13 # [PATCH] fix inode reclaim imbalance # # Well I thought we were shooting down unused inodes a bit aggressively. With # 30,000 inodes total and 1000 unused, the 1000 are getting reclaimed # instantly. # # shrink_icache_memory() needs to return the number of reclaimable inodes to # page reclaim, not the total number. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.14 # [PATCH] remove __pgd_offset # # Patch from Dave Hansen # # __pgd_offset() and pgd_offset() are completely different functions. # __pgd_offset() is really just a helper to figure out which entry in a # pgd an address would fall into. pgd_offset() does all the leg work and # actually fetches the real pgd entry. # # pgd_index() is a much saner name for what __pgd_offset() does. In fact, # we do this: # #define __pgd_offset(address) pgd_index(address) # # The attached patch removes all instances of __pgd_offset and just # replaces them with pgd_index. # # Compiles with and without PAE on x86. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.15 # [PATCH] remove __pmd_offset # # Patch from Dave Hansen # # Same thing as the __pgd_offset one, just for pmds this time to keep the # naming consistent. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.16 # [PATCH] remove __pte_offset # # Patch from Dave Hansen # # ptes this time # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.17 # [PATCH] missed unlock_kernel() in ext3+htree # # Patch from Alex Tomas # # There's a missing unlock_kernel(). # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.18 # [PATCH] reduce stack size: elf_core_dump() # # Patch from "Randy.Dunlap" # # This patch reduces stack size in elf_core_dump() from over 0x400 (0x4a4 e.g.) # to less than 0x100 (0xb0 on a P4 with gcc 2.96). # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.19 # [PATCH] uninlining in fs/binfmt_elf.c # # uninline some functions which have multiple callsites. A 5% reduction in # text size. # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.20 # [PATCH] ext3: fix error-path memory leak # # Fix an error-path memory leak in ext3_fill_super(). # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1075.4.21 # [PATCH] fix ioremap off by one bug # # Patch from Andreas Klein # # Fixes an off-by-one in ioremap() - local variable `last_addr' is *inclusive* # - it is the last byte of the mapping, not the usual (last byte + 1). # -------------------------------------------- # 03/03/06 Andries.Brouwer@cwi.nl 1.1075.4.22 # [PATCH] scsi_error fix # # imm.c: spelling # scsi.h: remove old and now incorrect comment # scsi_scan.c: remove superfluous final return # scsi_error.c: apart from similar trivialities the only change: # # If a command fails (e.g. because it belongs to a newer # SCSI version than the device), it is fed to # scsi_decide_disposition(). That routine must return # SUCCESS, unless the error handler should be invoked. # # In the situation where host_byte is DID_OK, and message_byte # is COMMAND_COMPLETE, and status is CHECK_CONDITION, there is # no reason at all to invoke aborts and resets. The situation # is normal. I see here UNIT ATTENTION, Power on occurred # and ILLEGAL REQUEST, Invalid field in cdb. # # The 2.5.64 code does not return SUCCESS, but it returns the # return code of scsi_check_sense(), and that may be FAILED # in case we do not have valid sense. # -------------------------------------------- # 03/03/06 linux@brodo.de 1.1075.4.23 # [PATCH] pcmcia: it works again! # # platform_device_register may only be called after all class-specific # device data is initialized, or else the class-type add_device call (which # enables the pcmcia sockets) will fail. # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.1 # [PATCH] minor breakage fix from typo fixes # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.2 # [PATCH] minor typo fix that got missed # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.3 # [PATCH] remove 2.2 compatmac stuff from rio driver # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.4 # [PATCH] exterminate 2.2 gunk from video stuff # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.5 # [PATCH] look a typo 8) # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.6 # [PATCH] more 2.0 crap # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.7 # [PATCH] more 2.0/2.2 bits # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.8 # [PATCH] another typo that escaped # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.9 # [PATCH] fix aic7xxx aicasm build # # The -ldb has to be at the end sometimes # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.10 # [PATCH] remove a pile of 2.0 and 2.2 support # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.11 # [PATCH] filter more 2.2 junk # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.12 # [PATCH] kill stdarg in intermezzo # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.13 # [PATCH] missed patch - static not extern inline in cia # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.14 # [PATCH] correct BUG doc # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.15 # [PATCH] kill the now dead ide_ioreg_t # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.16 # [PATCH] kill long unused macro # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.17 # [PATCH] add serial port table for PC9800 # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.18 # [PATCH] correct BUG doc in parisc # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.19 # [PATCH] remove unused beep macro on sh # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.20 # [PATCH] Add ELF types for Hitach H8 series # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.21 # [PATCH] remove 2.2 junk from efs # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.22 # [PATCH] remove 2.2 bits fromw anpipe # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.23 # [PATCH] remove 2.0 and 2.2 stuff from netfilter # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.24 # [PATCH] add a new PCI quirk type for the ALi Magik series # # This chip needs latency and other setups to avoid a PCI/AGP deadlock # with tv cards # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.25 # [PATCH] remove 2.0/2.2 stuff # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.26 # [PATCH] remove 2.0/2.2 stuff from wanrouter # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.27 # [PATCH] correct emu10k url # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.28 # [PATCH] correct file names in comments in mm # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.29 # [PATCH] clean up 2.2 stuff in wanrouter code # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.30 # [PATCH] ALi it turns out has a 31bit audio device # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.31 # [PATCH] update PCI quirks # # ALi Magik requires workarounds for TV chips # IDE controllers require proper handling in legacy mode # PXB must be disabled on C0 450NX or the IDE will corrupt memory # VIA northbridge devices require the interrupt line is written # NEC_CBUS_2/3 require ISA DMA workarounds # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.32 # [PATCH] correct irq logic for x86 # # We must not look for a PCI IRQ for a non native mode IDE device # We must write PCI_INTERRUPT_LINE for VIA # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.33 # [PATCH] correct building of the old ide/hd.c driver # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.34 # [PATCH] clean up all the console inits using an initcall variant # # Dave Woodhouse did this a while ago and its been kicking around in my # tree just fine. This gets rid of a lot of the init lists of functions # still left in the kernel by having an __init type array built up for the # consoles as well # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.35 # [PATCH] bring ide-disk driver into line with 2.4.21pre # # This doesn't have the new -ac testing stuff from 2.4.21pre5-ac but it # has the stuff I now trust in it. This fixes the cache flush stuff and # also means ide-disk now should be safe shared IRQ # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.36 # [PATCH] ide-dma # # This switches ide-dma to ide_execute_command and makes IDE DMA also happy # when running shared IRQ # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.37 # [PATCH] switch ide-floppy to ide_execute_command # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.38 # [PATCH] switch ide-io (core ioctls etc) to ide_execute_command # # Also fix the irq masking bug # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.39 # [PATCH] add sensible names to the ide iops # # The outbsync one has further changes to come in the next batch to sort # out some platforms like PPC # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.40 # [PATCH] remove spare cast # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.41 # [PATCH] switch ide taskfile ioctls to ide_execute_command # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.42 # [PATCH] fix wrong type and statics in amd ide # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.14.43 # [PATCH] update via driver from 3.35-ac to 3.36 # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.4.24 # Merge home.transmeta.com:/home/torvalds/v2.5/alan # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 rmk@arm.linux.org.uk 1.1075.4.25 # [PATCH] Separate out pci bus resource allocator # # - Separate out bus resource allocator (pci_bus_alloc_resource) # - Provide pci_enable_bridges to setup command register for all # pci bridges. # -------------------------------------------- # 03/03/06 rmk@arm.linux.org.uk 1.1075.4.26 # [PATCH] Eliminate stack allocation of struct pci_dev... # # - Eliminate the stack allocation of a struct pci_dev, and make # pci_scan_slot() take a bus and a devfn argument. # - Add "dev->multifunction" to indicate whether this is a multifunction # device. # - Run header fixups before inserting the new pci device into any # device lists or announcing it to the drivers. # - Convert some more stuff to use the list_for_each* macro(s). # -------------------------------------------- # 03/03/06 rmk@arm.linux.org.uk 1.1075.4.27 # [PATCH] Only add devices to bus->devices while scanning... # # The pci_find* functions search using the following lists: # bus->children (for subordinate buses) # pci_root_buses (for all root buses) # pci_devices (for devices) # # This leaves one list which we can add devices to without any drivers # finding the new devices before we've finished with them. # # - initialise bus->node list head. # # - pci_scan_slot will scan the specified slot, and add the discovered # devices to the bus->devices list only. These devices will not # appear on the global device list, and do not show in sysfs, procfs. # pci_scan_slot returns the number of functions found. If you want # to find the devices, you have to scan bus->devices and look for # devices where list_empty(&dev->global_list) is true. # # - new function "pci_bus_add_devices" adds newly discovered devices # to the global device lists, and handles the sysfs and procfs # stuff, making the devices available to drivers. All our buses # which have an empty list head are treated as "new" (since they # are not attached to the parent buses list of children) and are # also added. Currently, no buses will be in this state when this # function is called. # # - new function "pci_scan_child_bus" scans a complete bus, building # a list of devices on bus->devices only, performing bus fixups # via pcibios_fixup_bus() and scanning behind bridges. It does # make devices externally visible. # # - pci_do_scan_bus retains its original behaviour - ie, it scans # and makes devices available immediately. # -------------------------------------------- # 03/03/06 rmk@arm.linux.org.uk 1.1075.4.28 # [PATCH] Convert setup-bus resource allocation to use bus->devices # # - Convert setup-bus.c resource allocation to scan bus->devices rather # than bus->children. As noted previously, newly discovered child # buses will not be on the parents list of children buses, so when # we're trying to assign resources, we need to scan the bus for # devices with subordinate buses rather than using the list of children # buses. # -------------------------------------------- # 03/03/06 rmk@arm.linux.org.uk 1.1075.4.29 # [PATCH] Fix up pci_scan_bridge and friends # # Now we tackle pci_add_new_bus and pci_scan_bridge. The hotplug code # currently uses this, but I'd like it to die off; pci_scan_bridge() # should be used to scan behind bridges. This may mean hotplug needs # some changes to pci_scan_bridge - if so, we need to find out what # changes are required and fix it. # # pci_alloc_child_bus() does what pci_add_new_bus() did, except it # doesn't attach the new bus to the parents list of child buses. The # only way this bus can be reached from the parent bus is by scanning # the parents devices list, and locating a device with a non-NULL # subordinate bus. The only code which should be doing this is the # PCI code. # # Since the new bus will have an empty list head for bus->node, we can # detect unattached buses prety easily. (see pci-3.diff.) # # pci_scan_bridge() changes slightly - we use our new pci_scan_child_bus() # function from pci-3.diff, which doesn't attach devices to the global # tree. This means callers of pci_scan_child_bus() and pci_scan_bridge() # (ie, hotplug) will need to call pci_bus_add_devices(). # -------------------------------------------- # 03/03/06 hpa@transmeta.com 1.1075.4.30 # [PATCH] bootsect removal # # This is the "boot sector removal" patch for i386 updated for Linux # 2.5.63-bk7. The only change against the 2.5.59 version is that the # FDOPTS Makefile variable, which lets one create a floppy image with # arbitrary kernel options, has been merged from the x86-64 version, and # the comments have been updated. # # The patch removes the in-kernel boot sector, which these days rarely # work correctly (it only supports up to 1 MB kernels, and only work on # legacy floppies -- not on IDE or USB devices, nor on any kind of # emulated devices like El Torito), replaces it with a placeholder stub, # and sets up the Makefile targets to create floppies or floppy images # using SYSLINUX. The FDOPTS Makefile variable can be used to set # kernel command line options (thanks to a suggestion by Andi Kleen.) # # Note that the same change has already been applied to the x86-64 # architecture. The last hunk of the patch corrects a comment in that # architecture. # -------------------------------------------- # 03/03/06 mochel@osdl.org 1.1068.2.24 # sysfs: fix up directory removal, once and for all. # # This patch was previously integrated, but dropped erroneously by a bk # merge. # # This fixes file cleanup during a sysfs directory removal by deleting files # from ->d_subdirs as they're iterated over, then checking if we can get a # reference on them. # -------------------------------------------- # 03/03/06 mochel@osdl.org 1.1068.2.25 # sysfs: Fix binary file handling. # # From Rusty Lynch: # # * makes sysfs cleanup the buffer->data allocated by the attribute write # functions # * fixes a bug that causes the kernel to oops when somebody attempts to # write to the file. # -------------------------------------------- # 03/03/06 mochel@osdl.org 1.1075.4.31 # Merge osdl.org:/home/mochel/src/kernel/devel/linux-2.5-virgin # into osdl.org:/home/mochel/src/kernel/devel/linux-2.5-core # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.13.4 # ia64: Fix several small bugs/omissions from the 2.5.64 sync. # -------------------------------------------- # 03/03/06 anton@samba.org 1.1075.9.1 # [PATCH] missing include # # list.h must now include stddef since it uses NULL. # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.9.2 # Fix "con_init()" function type and stale (and incorrect) declaration # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1075.9.3 # Fix a very theoretical race between the new RCU lookup and # concurrent renames in another directory. # # I doubt this can be triggered in practice, and the fix is # a bit heavy-handed, but let's see if numbers can show that # the simple fix doesn't show any real lock contention. # -------------------------------------------- # 03/03/06 sfr@canb.auug.org.au 1.1068.13.5 # [PATCH] ia64: compat_sys_futex() support # # ia 64 part of the patch. This gives you a 32 bit version of sys_futex (hopefully). # -------------------------------------------- # 03/03/06 jbarnes@sgi.com 1.1068.13.6 # [PATCH] ia64: ACPI fix for no PCI # # Andy Grover told me this should be posted here. It allows ACPI to # compile even with PCI turned off. Patch against 2.5.60. # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.13.7 # ia64: Minor formatting/whitespace fixes in ia64-version of acpi.c. # -------------------------------------------- # 03/03/06 bjorn_helgaas@hp.com 1.1068.13.8 # [PATCH] ia64: IA32 support without sysctl doesn't work # # Make CONFIG_SYSCTL control sys32_sysctl as well. Based on a patch from Peter Chubb. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.20.2 # ISDN/HiSax: Introduce probe() functions # # Just separate the setup_*() functions of hisax subdrivers # into calls to *_probe() functions, a step towards using # standard initialization and modularization of hisax. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.20.3 # ISDN/HiSax: config.c cleanup # # Consolidate allocation / freeing of various data structures into # one function. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.20.4 # ISDN/HiSax: Remove unused ISDN_CHIP_* macros # # They were only defined, never used. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.20.5 # ISDN/HiSax: Get rid of CARD_* defines # # hisax.h defined a CARD_* macro for each CONFIG option, which # is totally unnecessary, just use the CONFIG option directly. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.20.6 # ISDN/HiSax: Remove amd7930.c # # This has been around for many years but was never finished. No # need to carry it on to yet another stable kernel. # -------------------------------------------- # 03/03/07 willy@debian.org 1.1075.8.5 # [PATCH] Some parisc updates for SCSI # # The config stanza for SCSI_ZALON was in the wrong place, so move it. # Make SCSI_NCR53C8XX conflict with SCSI_ZALON. # Give ncr53c8xx and sym53c8xx names # Fill in detach and release methods unconditionally. # Call pci_set_master() in sym53c8xx. # Both these drivers need interrupt.h, not sched.h # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1075.4.32 # Merge bk://ldm.bkbits.net/linux-2.5-core # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1075.4.33 # Merge http://lia64.bkbits.net/to-linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/07 david@gibson.dropbear.id.au 1.1075.4.34 # [PATCH] Squash warnings in usb-serial.c # # This squashes (gcc-3.2) "label and end of compound statement # deprecated" warnings in usb-serial.c. # -------------------------------------------- # 03/03/07 david@gibson.dropbear.id.au 1.1075.4.35 # [PATCH] Squash warning in ohci-pci.c on PowerBooks # # Apple PowerBooks want in ohci-pci.c for the prototype of # pci_device_to_OF_node(). This patch adds it to the already present # list of PowerBook specific #includes: # -------------------------------------------- # 03/03/07 mbligh@aracnet.com 1.1075.4.36 # [PATCH] Fix NUMA scheduler problem after interactivity merge # # NODE_THRESHOLD got accidentally dropped in the interactive scheduler # changes merge. This puts it back. # -------------------------------------------- # 03/03/07 mbligh@aracnet.com 1.1075.4.37 # [PATCH] revert pfn_to_nid change. # # This change was wrong. pfn_to_nid is a macro. # -------------------------------------------- # 03/03/07 zwane@linuxpower.ca 1.1075.4.38 # [PATCH] noirqbalance still doesn't do anything # # This one simply sets TARGET_CPUS to cpu_callout_map instead of # cpu_online_map so that when we finally do boot we actually use the other # cpus for servicing interrupts. # -------------------------------------------- # 03/03/07 mzyngier@freesurf.fr 1.1075.4.39 # [PATCH] Fix fs/binfmt_elf.c build # # The stack reducing patch that recently went in prevent alpha from # building (missing some ELF_CORE_COPY_XFPREGS ifdefs). The excluded # patch fixes it. # -------------------------------------------- # 03/03/07 mzyngier@freesurf.fr 1.1075.4.40 # [PATCH] Fix arch/alpha/vmlinux.lds.S typos. # # The console initcall patch that went in contains a typo that prevents # alpha from building. # -------------------------------------------- # 03/03/07 mingo@elte.hu 1.1075.4.41 # [PATCH] NUMA scheduler breakage # # __activate_task() and wake_up_forked_process() should call # nr_running_inc(rq) rather than doing a rq->nr_running++. # # Noted by Rick Lindsley # -------------------------------------------- # 03/03/07 hch@lst.de 1.1075.8.6 # [PATCH] remove some braindamage from drivers/scsi/pcmcia/Kconfig # # It contains one user-selectable option that does nothing but hiding the # four pcmcia drivers if not seleted (although we have an extra menu for # them!) one one that does exactly nothing. Remove those two. # -------------------------------------------- # 03/03/07 green@namesys.com 1.1075.4.42 # [PATCH] memleak in drivers/char/vt.c # # Seems there is a memleak on error exit path in drivers/char/vt.c, here's # the patch. Found with help of smatch + enhanced unfree script. # -------------------------------------------- # 03/03/07 mingo@elte.hu 1.1075.4.43 # [PATCH] more "interactivity changes", sched-B2 # # - fix a (now-) bug in kernel/softirq.c, it did a wakeup outside any # atomic regions, which falsely identified random processes as a # non-atomic wakeup, and which causes random priority boost to be # distributed. # # - reset the initial idle thread's priority back to PRIO_MAX after doing # the wakeup_forked_process() - correct preemption relies on this. # # - update current->prio immediately after a backboost. # # - clean up effective_prio() & sleep_avg calculations so that there are # fewer RT-task special cases. This has the advantage of the sleep_avg # being maintained even for RT tasks - this could be advantegous for # tasks that briefly enter/exit RT mode. # -------------------------------------------- # 03/03/07 willy@debian.org 1.1075.4.44 # [PATCH] fs/locks.c: fix bugs # # - Remove broken lock accounting # - Introduce __locks_delete_block() # - Stop using kdevname() # - Fix locks_remove_posix() # -------------------------------------------- # 03/03/07 shemminger@osdl.org 1.1075.4.45 # [PATCH] Turn off aio printk meant for debugging (2.5.64) # # The following messages are of interest only when debugging aio. # Otherwise, they are just console clutter. # -------------------------------------------- # 03/03/07 mingo@elte.hu 1.1075.4.46 # [PATCH] "interactivity changes", sched-2.5.64-B2 # # This fixes the SMP runqueue locking bug when updating the wakers # priority. It also includes: # # - only update the priority and do a requeueing if the sleep average has # changed. (this does not happen for pure CPU hogs or pure interactive # tasks, so no need to requeue/recalc-prio in that case.) [All the # necessary values are available at that point already, so gcc should # have an easy job making this branch really cheap.] # # - do not do a full task activation in the migration-thread path - that is # supposed to be near-atomic anyway. # # - fix up comments # # I solved the SMP locking bug by moving the requeueing outside of # try_to_wake_up(). It does not matter that the priority update is not # atomically done now, since the current process wont do anything # inbetween. (well, it could get preempted in a preemptible kernel, but # even that wont do any harm.) # -------------------------------------------- # 03/03/07 stevef@smfhome1.austin.rr.com 1.1068.8.3 # Fix oops in getdfs when null path passed in on mount. Fix oops when changed readsize caused readpages problem. Add support for altering rsize so can reduce pages read across net # below default of 4 # -------------------------------------------- # 03/03/07 torvalds@penguin.transmeta.com 1.1075.4.47 # Merge bk://cifs.bkbits.net/linux-2.5cifs # into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1075.10.1 # [SPARC]: One too many chars in INIT_C_CC # -------------------------------------------- # 03/03/07 greg@kroah.com 1.1075.11.1 # gen_init_cpio: Add the ability to add files to the cpio image. # -------------------------------------------- # 03/03/07 greg@kroah.com 1.1075.11.2 # kbuild: handle any failures of the gen_init_cpio or initramfs image to stop the build. # # This also shows how to add files to the initramfs build, but is # commented out. # # Patch originally done by Kai. # -------------------------------------------- # 03/03/07 torvalds@penguin.transmeta.com 1.1075.4.48 # Merge bk://kernel.bkbits.net/gregkh/linux/initramfs-2.5 # into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1075.10.2 # [FRAMEBUFFER]: Convert SBUS LEO driver to new APIs. # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1075.10.3 # [SPARC64]: Use pci_remove_bus_device to delete, found by Ben Collins. # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1075.4.49 # Merge nuts.ninka.net:/home/davem/src/BK/sparcwork-2.5 # into nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1075.4.50 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1075.12.1 # Avoid warning due to missing return value # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1075.12.2 # Ignore initramfs cpio file # -------------------------------------------- # 03/03/07 kai@tp1.ruhr-uni-bochum.de 1.1075.13.1 # Merge tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5 # into tp1.ruhr-uni-bochum.de:/scratch/kai/kernel/v2.5/linux-2.5.isdn # -------------------------------------------- # 03/03/08 anton@samba.org 1.1075.3.2 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/07 marcel@holtmann.org 1.1075.4.51 # [SPARC64]: Translate AUTOFS_IOC_EXPIRE_MULTI ioctl. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.3 # [CPUFREQ] fix cpufreq core breakage(s) # # - update two more cpufreq-related sysfs files to the new interface # code # - always store the new, user-requested policy in another struct # cpufreq_policy so that we can safely fall back to the old one in # case something fails (this equals the behaviour before Pat's patch) # - the kobject which was registered in cpufreq_add_dev was inside a variable # private to this function -- so the whole cpufreq sysfs interface returned # -EINVAL. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.4 # [CPUFREQ] fix userspace governor. # Let's put the sysfs file exported by the cpufreq userspace governor also # into the cpufreq/ - subdirectory of /sys/devices/sys/cpu0/. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.5 # [CPUFREQ] remove unneeded code # # - no cpufreq driver uses the frequency table helper "setpolicy" any more # ("target" is much more appropriate for them anyways) - so remove # that helper # - all cpufreq drivers use the advanced registration process, so some # compatibility code can safely be removed. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.6 # [CPUFREQ] updated cpufreq ref-counting and locking scheme # # This patch takes use of the now-working cpufreq_interface.kset and # cpufreq_policy.kobj to use reference counting within the cpufreq core # wherever this is more appropriate than the previous approach -- using one # semaphore. Additionally, the callbacks to the driver modules are protected # now. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.7 # [CPUFREQ] add support for ICH4-M chipset in speedstep driver # # Intel ICH4-M soutbridges use exactly the same register interface for SpeedStep # as ICH2-M and ICH3-M southbridges -- which makes adding support for this # bridge (almost) trivial # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.8 # [CPUFREQ] allow cpufreq drivers to export sysfs files # # This patch lets cpufreq drivers export per-CPU files in the cpufreq and # cpu-specific sysfs directory. As an example, a file # "scaling_available_frequencies" is added to the p4-clockmod.c driver. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.9 # [CPUFREQ] update documentation # # The sysfs directory where the cpufreq-related files are stored changed due # to the new device interface code, so the documentation needs to be updated # accordingly. Also, add some information about the reference counting and the # exporting of sysfs files by the drivers. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.12.10 # [CPUFREQ] Move pci define to pci_ids.h # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1075.14.1 # [WATCHDOG] amd7xx_tco updates from Zwane, and nuke EXPORT_NO_SYMBOLS # -------------------------------------------- # 03/03/08 jejb@raven.il.steeleye.com 1.1075.15.1 # Merge raven.il.steeleye.com:/home/jejb/BK/linux-2.5.64-interim # into raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5 # -------------------------------------------- # 03/03/08 jejb@raven.il.steeleye.com 1.1075.15.2 # Correct nested variable thinko in scsi_error.c # -------------------------------------------- # 03/03/08 jejb@raven.il.steeleye.com 1.1075.15.3 # Fix DMA to stack problem in scsi_error.c # -------------------------------------------- # 03/03/08 jejb@raven.il.steeleye.com 1.1075.15.4 # Fix loop problem in SCSI error handler sense collection # # Also remove previous work around so sense is collected now if the # driver doesn't do it automatically. # # Also fix a problem where the retries get reset when the command is # reissued (we only want the retries set when the command is first # created). # -------------------------------------------- # 03/03/08 rml@tech9.net 1.1075.16.1 # [PATCH] no need for kernel_flag on UP # # This is a minor cleanup. We currently define and declare the BKL's # kernel_flag spinlock on either SMP or PREEMPT, which means a UP+PREEMPT # machine gets it. # # We only need the actual lock on SMP. # -------------------------------------------- # 03/03/08 torvalds@home.transmeta.com 1.1075.16.2 # Merge http://linux-isdn.bkbits.net/linux-2.5.isdn # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/08 davem@nuts.ninka.net 1.1075.4.52 # [SPARC64]: Make sure update_process_times runs inside of irq_{enter,exit} region. # -------------------------------------------- # 03/03/08 davem@kernel.bkbits.net 1.1075.4.53 # Merge davem@nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # into kernel.bkbits.net:/home/davem/sparc-2.5 # -------------------------------------------- # 03/03/08 torvalds@home.transmeta.com 1.1075.14.2 # Merge bk://linux-dj.bkbits.net/watchdog # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/08 torvalds@home.transmeta.com 1.1075.4.54 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/08 rmk@flint.arm.linux.org.uk 1.1075.9.4 # [SERIAL] Overhaul 8250_pci.c # # - Add local copy of flags for describing port characteristics. # - Add "quirk" handling to sort out board-specific initialisation, # per-port setup, and finalisation. # - Remove quirk information from struct pci_board array, thereby # making entries more generic. # - Initialise struct pci_board array using explicit indicies - # adding to the readability, and making sure that the right entries # are in the correct location in the table. # - Ensure we tell the serial layer to claim resources, and share # interrupts. PCI interrupts are sharable, and need to be so that # multi-function cardbus cards will work. # - Only remap each PCI memory BAR once. # - Add pci serial driver to the tty devclass (this requires the patch # to make tty_io.c register the tty devclass early.) # # Tested by CaT and myself. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.55 # [PATCH] 1/6 Share common physnode_map code between NUMA-Q and Summit # # From Andy Whitcroft # # Share a common physnode_map structure between NUMA-Q and Summit. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.56 # [PATCH] 2/6 Make CONFIG_NUMA work on non-numa machines. # # From Andy Whitcroft # # A few very simple changes in order to make CONFIG_NUMA work everywhere, so # the distros can build one common binary kernel for distributions. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.57 # [PATCH] 3/6 Convert physnode_map to u8 # # From Andy Whitcroft # # Convert physnode_map from an int to a u8 to save cachelines. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.58 # [PATCH] 4/6 Fix the type of get_zholes_size for NUMA-Q # # From Andy Whitcroft # # Fix the type of get_zholes_size for NUMA-Q # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.59 # [PATCH] 5/6 Provide basic documentation for profiling # # People keep asking for this info, and Andrew asked me to put it under the # Documentation directory ... provides really simple instructions for taking # a profile so that users can report performance changes in a useful way. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.60 # [PATCH] 6/6 cacheline align files_lock # # I'm getting a lot of cacheline bounce from .text.lock.file_table due to # false sharing of the cahceline. The following patch just aligns the lock # in it's own cacheline. # -------------------------------------------- # 03/03/08 rmk@flint.arm.linux.org.uk 1.1075.9.5 # [SERIAL] Update 8250_acorn.c # # Add resource-based addressing and ioremap support. Ask the 8250 # layer to handle the resources, and share IRQs. # -------------------------------------------- # 03/03/08 davem@nuts.ninka.net 1.1080 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/03/08 jmorros@intercode.com.au 1.1081 # [CRYPTO]: Move km_types out of header. # -------------------------------------------- # 03/03/08 jmorris@intercode.com.au 1.1082 # [TCP]: Commonize duplicated code into a new function, tcp_bucket_destroy. # -------------------------------------------- # 03/03/08 jmorris@intercode.com.au 1.1083 # [NET]: Nuke SO_BSDCOMPAT. # -------------------------------------------- # 03/03/08 ahaas@airmail.net 1.1084 # [NETFILTER]: C99 initializers for ipv6 netfilter. # -------------------------------------------- # 03/03/08 ahaas@airmail.net 1.1085 # [NETFILTER]: C99 initializers for ipv4 netfilter. # -------------------------------------------- # 03/03/08 jmorris@intercode.com.au 1.1086 # [CRYPTO]: Add encrypt_iv() and decrypt_iv() methods. # -------------------------------------------- # 03/03/08 jmorris@intercode.com.au 1.1087 # [CRYPTO]: Eliminate crypto_tfm.crt_ctx, from Adam Richter. # -------------------------------------------- # 03/03/09 anton@samba.org 1.1075.3.3 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/08 rmk@flint.arm.linux.org.uk 1.1075.9.6 # [SERIAL] Add ttydriver->owner initialisation. # -------------------------------------------- # 03/03/08 chas@locutus.cmf.nrl.navy.mil 1.1088 # [ATM]: Get lec net_device names correct. # -------------------------------------------- # 03/03/08 chas@locutus.cmf.nrl.navy.mil 1.1089 # [ATM]: Obsolete some atm_vcc members. # -------------------------------------------- # 03/03/08 rmk@flint.arm.linux.org.uk 1.1075.9.7 # [SERIAL] Make tty->driver_data point at the uart_state structure. # # Since the uart_state structure is less volatile than uart_info, we # can safely place some semaphores in uart_state. # -------------------------------------------- # 03/03/08 rmk@flint.arm.linux.org.uk 1.1075.9.8 # [SERIAL] Make uart_tasklet_action take uart_state # -------------------------------------------- # 03/03/08 davem@nuts.ninka.net 1.1090 # [ATM]: Add missing $(obj) to driver makefile. # -------------------------------------------- # 03/03/08 jmorris@intercode.com.au 1.1091 # [CRYPTO]: Documentation updates. # -------------------------------------------- # 03/03/09 rmk@flint.arm.linux.org.uk 1.1075.9.9 # [SERIAL] Eliminate some more passing of struct uart_info. # # Replace uart_info argument for uart_change_speed, uart_startup, # uart_shutdown and uart_update_termios with a uart_state structure. # We no longer pass struct uart_info around to other functions. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.61 # [PATCH] register_blkdev cleanups # # Patch from Andries.Brouwer@cwi.nl # # The following patch does the following: # # - static const char *blkdevs[MAX_BLKDEV]; disappears # - get_blkdev_list, (un)register_blkdev, __bdevname # are moved from block_dev.c to genhd.c # - the third "fops" parameter of register_blkdev was unused; # now removed everywhere # - zillions of places had printk("cannot get major") upon # error return from register_blkdev; removed all of these # and inserted a single printk in register_blkdev. # # Of course the reason for the patch is that one fixed size # array is eliminated. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.62 # [PATCH] fix possible latency in balance_dirty_pages() # # Tasks which throttle in balance_dirty_pages() will loop until the amount of # dirty memory falls below the configured dirty_ratio. # # This exposes the possibility that one task could be stuck in there for # arbitrary periods of time due to page dirtying activity by other tasks. # # The patch changes the logic so that tasks will break out of the loop if they # have written enough pages, regardless of the current dirty memory limits. # # Here "enough" pages is 1.5x the number of pages which they just dirtied. # # If the amount of dirty memory in the machine happens to still exceed # dirty_ratio (say, due to MAP_SHARED activity) then the task will again # throttle after dirtying a single page. But there is now an upper limit on # the time for which a single task will be captured in balance_dirty_pages(). # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.63 # [PATCH] Implement sendfile() for NFS # # Patch from Trond Myklebust # # Implement sendfile() for the NFS client. This is required for loop-on-NFS # support. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.64 # [PATCH] Allow VFS readahead to fall to zero # # Some workloads really, really want to have no readahead. Databases which are # perfoming small synchronous I/Os against a file which has extremely poor # layout. Any readahead at all is a lose here. # # But the current readahead code refuses to adapt that low. # # Fix it up so that we can indeed adaptively disable readahead altogether, and # do not start it again until we have seen max_readahead()'s worth of # consecutive reads. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.65 # [PATCH] Make diskstats per-cpu using kmalloc_percpu # # Patch from Ravikiran G Thirumalai # # Makes the disk stats on struct gendisk per-cpu. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.66 # [PATCH] Fix vm_area_struct slab corruption # # Patch from Hugh Dickins # # Hugh's patch fixes vm_area_struct slab corruption due to mremap's move_vma # mistaking how do_munmap splits vmas in one case. # # Neither of us are very happy with it - it is fragile, and obscure. Hugh will # revisit this later, but for now it should fix up the potential memory # corruption. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.67 # [PATCH] slab use-after-free detector # # Patch from Petr Vandrovec # # Modifies check_poison function to not only verify that last byte is # POISON_END, but also that all preceeding bytes are either POISON_BEFORE or # POISON_AFTER bytes. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.68 # [PATCH] slab debug: track caller program counter # # Patch from Manfred Spraul # # A patch that records the last kfree caller's program counter # and prints that if a poison check fails. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.69 # [PATCH] slab debug: symbolic output in caller tracking # # use print_symbol() to decode the offender's program counter. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.70 # [PATCH] Fix copy_page_range()'s handling of invalid pages # # Patch from Xavier Bru # # If copy_page_range encounters a pte which maps an invalid pageframe it will # proceed to try to add an rmap entry against that page. This causes oopses # when an application which has mapped an IO device via /dev/mem forks. # # Fix that up by correctly skipping the page_add_rmap() for these pte's. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.71 # [PATCH] move CONFIG_SWAP around # # Patch from Tom Rini # # Take CONFIG_SWAP out of the top-level menu into the general setup menu. Make # it dependent on CONFIG_MMU and common to all architectures. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.72 # [PATCH] fix div-by-zero in bonding.c # # Patch from: Shmulik Hen # # The following patch fixes a division by zero bug in the bonding module that # happens when transmitting through a bond with no slaves, in the XOR bonding # mode. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.73 # [PATCH] usercopy checks in old_readdir() # # Fix up some unchecked copy_to_user()s # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.74 # [PATCH] hugetlb unmap_vmas() SMP && PREEMPT fix # # Patch from Kevin Pedretti # # The unmap_vmas() logic is designed to chew away at all the pages without # holding off preemption for too long. But with CONFIG_SMP=y and # CONFIG_PREEMPT=y the number of pages which we batch up between rescheduling # opportunities is not a multiple of HPAGE_SIZE. So unmap_vmas() ends up # calling unmap_hugepage_range() with a poorly aligned&sized region, and it # goes BUG. # # Fix that up by ensuring that we always work across hugepage regions in # HPAGE_SIZE chunks. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.75 # [PATCH] ext2: fix error-path double-free # # Fix a double-kfree on an ext2 error path. Reported by Oleg Drokin. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.76 # [PATCH] fix memory leak in load_elf_binary() # # - Fix an error-path leak of memory and a dentry in load_elf_binary() # (spotted by Oleg Drokin). # # - Tidy up the handling of bad executable images: return -ENOEXEC rather # than 0. (We've committed suicide anyway, so probably nobody gets to see # this). # # - Fix up the logic in load_aout_interp(). It gets itself all set up to # return -ENOEXEC but there is in fact no path by which it can do this. Just # return ~0UL on errors, like load_elf_interp(). # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.77 # [PATCH] Extended attribute sharing and debug macro typo fixes # # Patch from Andreas Gruenbacher # # Tony Dziedzic has found two bugs in the extended attributes code. Patches with # explanations are attached. # # 1: Extended attribute sharing on ext2/ext3 not working # # The mb_cache_entry_insert function constantly returns an -EBUSY error # instead of 0, which causes the xattr cache that is needed by the xattr # sharing mechanism on ext2/ext3 to not share anything. This patch fixes # the problem. (It is possible that after applying this fix we will hit # bugs in code that wasn't used before.) # # 2: Oops in one of the xattr debug statements: The old_bh variable is NULL # if an inode that previously had no EA's assigned would share an EA block # with another inode. (This was hidden by the xattr sharing bug). # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.78 # [PATCH] protect 'action' in show_interrupts # # Patch from Zwane Mwaikambo # # On SMP or preemptible kernels, every instance of show_interrupts() is oopsily # racy wrt request_irq() and free_irq(). # # Fix that up by taking the irq_desc_t's lock while walking the action list. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.79 # [PATCH] i386 show_interrupts() fix # # show_interrupts() is accidentally modifying the incoming seq_file pointer. # It goes oops if seq_printf() returns non-zero. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.80 # [PATCH] fix SMP lockup in eepro100 with ethtool on unused # # Patch from Jason Lunz # # When support for the GSET and SSET ethtool ioctls was added to eepro100.c in # 2.4.20, the tx lock was overloaded to serialize their use. Unfortunately, # this lock is only initialized in dev->open(), causing ethtool to deadlock the # machine when used on an unconfigured eepro100 interface. # # The fix is to initialize the spinlock at probe time. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.81 # [PATCH] Larger buffer for /proc/interrupts display # # Patch from Zwane Mwaikambo # # Scale the buffer which is used for accumulating the /proc/interrupts output. # On large SMP it overflows. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.82 # [PATCH] Disable the "Unknown IO_APIC" message # # This message is the source of 90% of the traffic on linux-smp and is now # starting to fill up kernel bugzilla. # # Nobody has ever actually done anything about it and the message is wasting # people's time. Ingo acked this change. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.83 # [PATCH] raw.c: dev_t cleanup and oops fix # # Patch from Andries.Brouwer@cwi.nl # # The next patch in the dev_t series eliminates the last applied use # of MAX_BLKDEV - only the definition in major.h remains. # # Sneaky as I am, I combine this patch with the fix for an Oops: # On open, raw_open does # filp->f_dentry->d_inode->i_mapping = # bdev->bd_inode->i_mapping; # storing a pointer to bdev stuff. # But on release this pointer stayed, the block device is not # referenced anymore and disappears, and the next open references # undefined stuff. # I checked, and this can actually cause an Oops - scenario: # # # raw /dev/raw/raw12 /dev/hdf # # dd if=/dev/raw/raw12 of=/dev/null bs=512 count=1 # # raw /dev/raw/raw12 0 0 # # dd if=/dev/raw/raw12 of=/dev/null bs=512 count=1 # # Oops. # # More precisely the problem is that dentry_open does # file_ra_state_init(&f->f_ra, inode->i_mapping); # And file_ra_state_init uses mapping->backing_dev_info->ra_pages. # Ugly, to use so much information about the inode even before # the inode has been opened. # # In the patch below I reset i_mapping upon release of the raw device. # # akpm: I fixed a typo and exported default_backing_dev_info to GPL modules for # this. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.84 # [PATCH] missing spin_unlock() in sysfs_remove_dir() # # missing spin_unlock() in sysfs_remove_dir() # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.85 # [PATCH] rpc_delete_timer race fix # # Patch from Ulrich Weigand # # Fix a race wherein timer_pending() returns false, but the timer handler is # actually running on another CPU. We need to call del_timer_sync() # regardless, so we wait for completion of the handler. # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.86 # [PATCH] remove compile warning from serial console initcall # # Patch from: "Martin J. Bligh" # # This tiny patch removes the new compiler warning from my build - the new # console_initcall mechanism seems to require int from console_init ... I made # serial8250_console_init look like con_init # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.87 # [PATCH] revert the "remove kernel_flag" patch # # With CONFIG_SMP=n, CONFIG_PREEMPT=y, CONFIG_DEBUG_SPINLOCK=y we get many # undefined refs to kernel_flag. # # This is because spinlock debugging works on uniprocessor kernels now, and it # stores state inside the spinlock structure to do this. # # Having working spinlock debugging on UP kernels seems more important than # saving four bytes, so... # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1075.4.88 # [PATCH] fix a warning in eepro100.c # # Remove the unneeded forward declaration of eepro100_remove_one(). # # It is defeating the __attribute__(unused) tag on the definition of # eepro100_remove_one() and is causing a "defined but not used" warning. # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1075.4.89 # [PATCH] NUMA scheduler fixup # # From: Ingo Molnar # # This cleans up the NUMA scheduler to have separate triggers for idle # and busy rebalance ratio, preventing some complex interactions where # idle cpus can cause busy ones to busy rebalance more often. The core # functionality of this patch is rebalace_tick(). # # Tested in -mjb tree for over 1 month ... no problems at all found - # retested on top of 64-bk3 with new scheduler updates. # -------------------------------------------- # 03/03/09 rmk@flint.arm.linux.org.uk 1.1075.9.10 # [SERIAL] Add per-port semaphore. # # Add a per-port semaphore to protect against simultaneous opens, # closes, hangups, and the like. This removes the need for the # UIF_CLOSING flag, as well as the extra tests and wait queues. # # Disable the old PM code for now - it is incompatible with the # per-port semaphore. # -------------------------------------------- # 03/03/09 jejb@raven.il.steeleye.com 1.1075.4.90 # Merge raven.il.steeleye.com:/home/jejb/BK/scsi-misc-2.5 # into raven.il.steeleye.com:/home/jejb/BK/scsi-for-linus-2.5 # -------------------------------------------- # 03/03/09 rmk@flint.arm.linux.org.uk 1.1075.9.11 # [SERIAL] Remove remaining notifier-based PM support. # -------------------------------------------- # 03/03/09 rmk@flint.arm.linux.org.uk 1.1075.9.12 # [SERIAL] Four bug fixes # # - Preserve per-port flags which are not modifyable from user space. # - Only allow DTR, RTS, OUT1 and OUT2 to be controlled from user space. # - Don't put the console port into sleep mode when closing a port. # - Ensure that we wake up people waiting on modem status changes when # we receive a hangup. # -------------------------------------------- # 03/03/09 rmk@flint.arm.linux.org.uk 1.1075.9.13 # [SERIAL] Prevent multiple calls to tty_{un,}register_device() # # There were a couple of cases where we call tty_register_device() # multiple times for the same port, notibly when ports are discovered # via 8250_pci, 8250_pnp or 8250_cs modules. With devfs configured, # this causes a warning. Don't call tty_register_device() multiple # times. # -------------------------------------------- # 03/03/09 torvalds@home.transmeta.com 1.1075.17.1 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/09 torvalds@home.transmeta.com 1.1075.4.91 # Merge http://linux-scsi.bkbits.net/scsi-for-linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/09 levon@movementarian.org 1.1075.4.92 # [PATCH] fix oprofile on x86 > 1 counter # # Without this we have a choice between dropping lots of counter events # for counters > 0, or getting dazed and confused. This brings it inline # with the 2.4 module code. Tested on my 2-way. # # Also fix a typo from Steven Cole, and remove some unnecessary code # -------------------------------------------- # 03/03/09 ak@muc.de 1.1075.4.93 # [PATCH] Fast path context switch - microoptimize FPU reload # # Following some changes on x86-64. # # When cpu_has_fxsr is defined to 1 like in many kernels unlazy_fpu can # collapse to three instructions. For that inlining is a very good idea. # Otherwise it's 10 instructions or so, which can be still inlined. # # We don't need the lock prefix to test our local thread flags state. # Unfortunately test_thread_flag currently always uses test_bit which # has a LOCK on SMP, but that's unnecessary. LOCK is costly on P4, # so it's a good idea to avoid it. # # Work around this for now by testing directly. Better would be # probably to define __set_bit for all architectures to not guarantee # atomicity and then always use that for local thread_info accesses # in linux/thread_info.h # -------------------------------------------- # 03/03/09 torvalds@home.transmeta.com 1.1075.4.94 # Fix up i387 task switching bug introduced by Andi Kleen's patch # to speed it up - use the proper bitmask for clearing "used-fpu" # state. # -------------------------------------------- # 03/03/10 anton@samba.org 1.1075.3.4 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/09 green@linuxhacker.ru 1.1092 # [VLAN]: Fix memory leak in procfs handling. # -------------------------------------------- # 03/03/10 anton@samba.org 1.1075.3.5 # ppc64: handle 8 byte loads and stores atomically in xmon # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.4 # Interface Changes # # A few minor revisions. Simpifies a few commands and adds config mode # information. # -------------------------------------------- # 03/03/09 torvalds@home.transmeta.com 1.1075.4.95 # Fix nanosleep() problem noticed by Todd Mokros . # # If we raced on a timer expire, we'd get a negative timeout and think # that is was a _huge_ positive timeout. # -------------------------------------------- # 03/03/09 torvalds@home.transmeta.com 1.1075.4.96 # Cache the MSR_IA32_SYSENTER_CS value in the per-CPU TSS (using # the otherwise unused cpl1 entry for SS), so that we can avoid # re-loading it on task switches if it doesn't change. # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.5 # Merge http://linux.bkbits.net/linux-2.5 # into neo.rr.com:/home/ambx1/src/bk/linus-2.5 # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.6 # PnP Card Serivice Revisions # # This set of changes addresses the following issues with the existing card # service implementation: # # 1.) Only one driver can be bound to a card. # 2.) repetive code is required for pnp_request_card_device and other # functions # # This patch will make the card services usable by ALSA. # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.7 # ALS100 Updates # # Updates the als100 driver to use the pnp apis. Includes resource config # templates. # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.8 # OSS SB driver Updates # # Compatibility update for the latest changes. # -------------------------------------------- # 03/03/09 ambx1@neo.rr.com 1.1075.1.9 # Aditional Card Service Changes # # Fixes many issues that were discovered after testing. Also cleans up the # card service code and fixes the card_drvdata bug in which only one driver # at a time could have driver data. # -------------------------------------------- # 03/03/10 anton@samba.org 1.1075.3.6 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/10 davej@codemonkey.org.uk 1.1075.4.97 # [CPUFREQ] Fix documentation typos. # -------------------------------------------- # 03/03/10 davej@codemonkey.org.uk 1.1075.4.98 # [CPUFREQ] powernow-k7 lazy voltage setting. # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1075.18.1 # Move "used FPU status" into new non-atomic thread_info->status field. # # This allows us to avoid having to use atomic updates for the lazy FP # status setting, since we don't have to worry about other CPU's racing # on the fields. # # Also, fix x86 FP state after fork() by making sure the FP is unlazied # _before_ we copy the state information. Otherwise, if a process did a # fork() while holding the FP state lazily in the registers, the child # would incorrectly unlazy bogus state. # -------------------------------------------- # 03/03/10 shaggy@shaggy.austin.ibm.com 1.1068.15.1 # JFS: Fix hang while flushing outstanding transactions under heavy load # # During syncbarrier recovery, when JFS is waiting for all outstanding # transactions to complete before allowing new ones to start, there was a # window where a new transaction starts, but is not committed when JFS thought # it could stop flushing the journal to disk. This caused the log_SYNCBARRIER # flag to not be reset, and no new transactions are allowed to start. # # This is fixed by using the log->active field to determine when to reset the # log_FLUSH flag. # -------------------------------------------- # 03/03/10 kraxel@bytesex.org 1.1075.18.2 # [PATCH] v4l: video-buf update # # This patch is a update for the video-buf mm helper module. It has # some minor bugfixes and a number of signed/unsigned cleanups to make # gcc 3.3 happy. # -------------------------------------------- # 03/03/10 rddunlap@osdl.org 1.1093 # [SNMP]: Fix SNMP_STAT_{USR,BH}PTR. # -------------------------------------------- # 03/03/10 davem@nuts.ninka.net 1.1094 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/03/11 anton@samba.org 1.1075.3.7 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/10 trini@kernel.crashing.org 1.914.128.4 # PPC32: Fix a typo in modular IDE support on Motorola LoPEC. # -------------------------------------------- # 03/03/10 trini@kernel.crashing.org 1.914.128.5 # PPC32: Fix building of the Motorola LoPEC and CONFIG_DUMMY_CONSOLE # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1075.18.3 # Remove 's own home-made FPU begin/end macros, # use the real ones instead. # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1075.18.4 # Use a fixed per-cpu SYSENTER_MSR_ESP value by having the sysenter # entry routine load the real ESP0 off that per-cpu stack. Make this # even faster by putting the sysenter stack in the per-CPU TSS, so # that we can use the tss->esp0 value directly (which we have to # update on task switches anyway). # # CAREFUL! This needs very subtle code for debug and NMI exceptions, # to make sure we don't run with the sysenter stack in any real kernel # code! # -------------------------------------------- # 03/03/10 kuznet@ms2.inr.ac.ru 1.1095 # [IPV4]: Fix deadlock in IGMP locking. # -------------------------------------------- # 03/03/10 willy@debian.org 1.1075.18.5 # [PATCH] neaten fs/locks.c a little # # - Fix my email address to one which reaches me ;-) # - Remove timer.h include as we don't use timers. # - Add module.h. # - Sort includes alphabetically. # - Move EXPORT_SYMBOL from ksyms.c to locks.c. # - Simplify locks_conflict(). # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1094.1.1 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.2 # [PATCH] revert "noirqbalance still doesn't do anything" # # This recent patch caused Nick Piggin's 2xPIII VIA686B chipset machine into an # interrupts-off lockup during IDE probing. # # We don't really know why - it might be because an interrupt is delivered to a # secondary which doesn't expect it. # # I have a second patch from Zwane which solves the same problem in a different # way, but until that's had some wider testing I suggest we just back off the # original. # -------------------------------------------- # 03/03/10 hpa@transmeta.com 1.1094.1.3 # [PATCH] Fix $(src) versus $(obj) # # This fixes a bunch of "src" versus "obj" confusions that apparently # existed in my bootsect removal patch. How embarrassing... # -------------------------------------------- # 03/03/10 hch@lst.de 1.1094.1.4 # [PATCH] i2c-core.c procfs updates # # Cleanup the i2c procfs code a bit (less ifdef mess), partially based # on the lm_sensors CVS code. # -------------------------------------------- # 03/03/10 hch@lst.de 1.1094.1.5 # [PATCH] remove devfs_only() # # Rationale: devfs_only does nothing but disabling {un,}register_blkdev # and {un,}register_chrdev. {un,}register_blkdev already do nothing but # adding it's name argument to a lookup table for the __bdevname and # /proc/device output so this use is already bogus. The disabling of # the character device per-major arrays can work in practice but is # useless as any driver relying on it can't be used on non-devfs systems. # -------------------------------------------- # 03/03/10 ak@muc.de 1.1094.1.6 # [PATCH] x86-64 updates for 2.5.64-bk3 # # Make x86-64 boot again after the INITIAL_JIFFIES changes # and some bug fixes. Also some work for NPTL. # # - Merge with i386/2.5.64-bk3 # - Fix memory leak in copy_thread # - arch_prctl uses GDT for base if possible. Cleanup. # - clone supports bases >32bit for SETTLS etc. %fs hardcoded now. # - new ptrace support for 64bit TLS # - Disable (set|get)_thread_* for 64bit processes. # - Audit arch/x86_64 for jiffies wrap issues. # - Fix initial jiffies problem (that caused hanging kernels) # - FIx a few 32bit emulation bugs (sigaltstack, sigqueue) # - Some cleanup from Pavel # - Should compile again as UP # - Shrink size a bit by not putting exception tables into object files. # - Fix compilation with gcc 3.3 :- force inlining when needed # - Work around 2.5.64-bk3 console init bug. # - Fix some alignments in assembly code # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1094.1.7 # Merge bk://linux-pnp.bkbits.net/linux-pnp # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/10 torvalds@home.transmeta.com 1.1094.1.8 # Use cond_sched() instead of manual expansion of it. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.9 # [PATCH] ACPI suspend/resume locking fix # # Patch from Andreas Mohr # # Need to retake the spinlock in __pdflush() before continuing. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.10 # [PATCH] fix typo in init/Kconfig # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.11 # [PATCH] pnp warning fix # # The pnp_request_card_device() stub should return NULL, not -ENODEV. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.12 # [PATCH] fix console ordering default # # The conversion of the console registration to an initcall-style thing has # broken lots of people's setups. It is now dependent upon linkage order and # if you have both CONFIG_VT_CONSOLE and CONFIG_SERIAL_CONSOLE, no boot # messages come out on the screen because the kernel is selecting the serial # console first. # # It can be fixed by specifying console=tty0, but nobody is doing that. # # We can fix it up by placing drivers/char/ in front of drivers/serial/ in # linkage order. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.13 # [PATCH] work around gcc-3.x inlining bugs # # Force inlining even when gcc-3.x is too confused to do it for us. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.14 # [PATCH] NCPFS memleak fix # # Patch from Petr Vandrovec # Reported by Oleg Drokin. # # In NCP_IOC_SETOBJECTNAME handler, we allocated space (newname pointer), # copy stuff from userspace to there and then assign userspace # pointer to our internal structure, whoops! # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.15 # [PATCH] Memleak in Windows Logical Disk Manager partition # # Patch from Oleg Drokin # # Not freeing allocated memory on error exit path. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.16 # [PATCH] Fix memleak in ircomm_core # # Patch from Oleg Drokin # # There seems to be a memleak on error exit path. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.17 # [PATCH] Force cache alignment of task_structs # # I enabled the advanced use-after-free detector for large slab objects and the # kernel oopsed. This is because that debug code adds things at the head of # the slab objects, and the kernel will die if task_structs are not # well-aligned. # # The way to tell the slab allocator that it is not allowed to misalign objects # from this slab is SLAB_MUST_HWCACHE_ALIGN. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.18 # [PATCH] ext3: error handling robustness # # Fix a couple of ext3 error handling routines to not assume that the # superblock has valid journal and buffer_head pointers. These functions are # called during mount and unmount and that may not be true. # # This should fix the oops which Zwane saw when mounting a corrupt filesystem. # -------------------------------------------- # 03/03/10 akpm@digeo.com 1.1094.1.19 # [PATCH] ext2: fix directory handling bug # # Patch from Dave Miller. Fixes a very long-standing bug. # # If a process has an fd open against a now-removed directory, lookups on that # fd will end up calling ext2_find_entry() against a zero-length directory. # # When this happens ext2_find_entry() will, on the first pass through the loop, # set `kaddr' to page_address(page) - 20. Things get confused and the "zero # length directory entry" warning triggers. # # This only happens on 64-bit machines, because ext2_last_byte() is returning # an unsigned (32-bit) value, and the arithmetic works out OK for 32-bit # machines. # # So we change ext2_find_entry() to bale out immediately if the directory is # zero-length. All other directory-walking functions do this, but # ext2_find_entry() forgot to, due to the search-from-the-last-place # optimisation. # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1075.4.99 # [CPUFREQ] More typos. # -------------------------------------------- # 03/03/11 davej@tetrachloride.(none) 1.1094.1.20 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/cpufreq # -------------------------------------------- # 03/03/11 rmk@flint.arm.linux.org.uk 1.1075.9.14 # [SERIAL] Add new device model based power management infrastructure. # # Add uart_suspend_port(), uart_resume_port() which are responsible # for suspending/resuming one UART port. Low level drivers are # expected to call this from their device model suspend and resume # methods. # -------------------------------------------- # 03/03/12 anton@samba.org 1.1094.2.1 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/11 sfr@canb.auug.org.au 1.1094.1.21 # [PATCH] compat_sys_fcntl{,64} Generic part # # This patch creates compat_sys_fcntl{,64}. The diffstat for the whole # patch set is below, but this is just the generic part, the architecture # specific parts will follow. # # This patch also removes struct flock64 from all the 64 bit architectures # (except parisc). # -------------------------------------------- # 03/03/11 sfr@canb.auug.org.au 1.1094.1.22 # [PATCH] compat_sys_fcntl{,64} x86_64 part # # Here is the x86_64 part of the patch with Andi's blessing. # -------------------------------------------- # 03/03/11 sfr@canb.auug.org.au 1.1094.1.23 # [PATCH] compat_sys_fcntl{,64} s390x part # # Here is the s390x part of the patch with Martin's blessing. # -------------------------------------------- # 03/03/11 sfr@canb.auug.org.au 1.1094.1.24 # [PATCH] compat_sys_fcntl{,64} parisc part # # Here is the parisc part of the patch with Willy's blessing. # -------------------------------------------- # 03/03/11 mzyngier@freesurf.fr 1.1094.1.25 # [PATCH] EISA/sysfs update # # Here is the latest round of EISA/sysfs update. # # - Add documentation, # - Add support for per EISA-id driver data, # - Move virtual_root device to a platform device, # - Update CREDITS. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.26 # [PATCH] include unistd.h in m68knommu 68360 entry code # # Include asm/unistd.h to get the NR_syscalls definition in the # m68knommu 68360 interrupt entry code. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.27 # [PATCH] include unistd.h in m68knommu 68328 entry code # # Include asm/unistd.h to get the NR_syscalls definition in the # m68knommu 68328 interrupt entry code. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.28 # [PATCH] include errn0.h in m68knommu 68328 interrupt setup code # # Include errno.h in the m68knommu 68328 specific interrupt setup code. # It needs a few E* types as return values. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.29 # [PATCH] m68knommu/ucdimm should use generic 68328 irq setup. # # This patch fixes the m68knommu ucdimm platform config to use the generic # 68328 irq setup. All 68*328 family can use the same setup. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.30 # [PATCH] fix spelling in m68knommu Kconfig help # # This patch fixes a couple of spelling errors in the m68knommy Kconfig # help entries. Also makes CONFIG_HIGHPROFILE dependant on CONFIG_COLDFIRE, # since that feature is only implemented on ColdFIre based platforms. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.31 # [PATCH] m68knommu/de2 should use generic 68328 irq setup. # # This patch fixes the m68knommu de2 platform config to use the generic # 68328 irq setup. All 68*328 family can use the same setup. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.32 # [PATCH] fix wrong argument prototype in m68knommu/68360 for interrupt handler # # Fix wrong argument prototype in m68knommu commproc.c. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.33 # [PATCH] include errno.h in m68knommu 68360 interrupt setup code # # Include errno.h in the m68knommu 68360 specific interrupt setup code. # It needs a few E* types as return values. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.34 # [PATCH] fix m68knommu/68VZ328 Makefile to traverse sub-dirs # # Fix m68knommu 68VZ328 Makefile to only traverse its sub-directories. # There is no local code files for it to compile. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.35 # [PATCH] fix m68knommu COMEM-lite PCI bios code # # This patch fixes up a lot of problems in the m68knommu architecture # CO-MEMlite PCI interface code. The code was seriously out of date, # not implementing many of the requried PCI bios support functions. # Also fixes many wrong function return types and arguments. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.36 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5272 # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5272 ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # This patch also removes the reset button support, this is now moved to # a proper device driver, where it belongs. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.37 # [PATCH] fix m68knommu/68VZ328/de2 Makefile to compile local code files # # This patch fixes the m68knomu/68VZ328/de2 Makefile to build all its # local code files. Previously it relied on Makefiles above it to do # this. It should be done here. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.38 # [PATCH] fix m68knommu/68VZ328/ucdimm Makefile to compile local code files # # This patch fixes the m68knomu/68VZ328/ucdimm Makefile to build all its # local code files. Previously it relied on Makefiles above it to do # this. It should be done here. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.39 # [PATCH] call schedule_tail() in m68knommu return from fork code path # # This patch adds a call to schedule_tail() in the return from fork # post processing. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.40 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5307 # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5307 ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # This patch also removes the reset button support, this is now moved to # a proper device driver, where it belongs. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.41 # [PATCH] fix m68knommu/68360 Kconfig wrong define # # This patch fixes a wrong m68knommu/68360 config define, # CONFIG_68630_SCC -> CONFIG_68360_SCC. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.42 # [PATCH] inline some mm functions for MMUless targets # # This patch is the last of the MMUless support changes to the mm system. # It inlines for MMUless targets the following functions: # # vmalloc_to_page() # follow_page() # remap_page_range() # # All of these return NULL for the non-MMU case. Doing the inline here # minimizes changes to assorted mm/ files. This patch was originally # from Christoph Hellwig. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.43 # [PATCH] include stddef.h in include/linux/list.h # # This patches add an include to stddef.h into include/linux/list.h. # It uses the NULL define. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.44 # [PATCH] fix m68knommu COMEM-lite PCI header code # # This patch fixes up the PCI bios header for the m68knommu COMEM-lite # PCI hardware support. Adds missing definitions, and a couple of trivial # inline functions here. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.45 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5407 # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5407 ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.46 # [PATCH] fix m68knommu/68328 serial driver to use work_struct # # This patches fixes the m68knommu 68328 serial driver header to use the # work_struct, not the obsoleted workqueue. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.47 # [PATCH] build m68knommu/ColdFire common vectors.c and timers.c # # This patch puts the new common ColdFire timers.c and vectors.c into # the build list (in the m68knommu architecture branch). # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.48 # [PATCH] create common timer code for m68knommu/ColdFire processors # # This patch creates common timer setup and handling code for the m68knommu # ColdFire CPU sub-architecture. All 6 ColdFire CPU varients contain the # same hardware timers. Currently each sub-arch has its own timer code. # This reduces a lot of code duplication. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.49 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5249 # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5249 ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.50 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5206e # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5206e ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # This patch also removes the reset button support, this is now moved to # a proper device driver, where it belongs. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.51 # [PATCH] move common timer and vector code for m68knommu/ColdFire/5206 # # This patch moves common ColdFire vector and timer procesing code from # the local per-processor config.c for the 5206 ColdFire sub-architecture. # All ColdFire CPU's have the same timer and basic vector setup, seems # crazy to repeat this code for each of 6 ColdFire CPU varients. # -------------------------------------------- # 03/03/11 gerg@snapgear.com 1.1094.1.52 # [PATCH] fix m68knommu/68360 serial driver to use work_struct # # This patches fixes the m68knommu 68360 serial driver to use the # work_struct, not the obsoleted workqueue. # -------------------------------------------- # 03/03/11 axboe@suse.de 1.1094.1.53 # [PATCH] Fix x86-64 build # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.54 # [PATCH] fix kmem_cache_size() for new slab poisoning # # The new slab poisoning code broke kmem_cache_size(), it now returns # a too large size as the poisoning area after the object is includes. # XFS's kmem_zone_zalloc thus overwrites exactly that area and triggers # the new checks everytime such an object is freed again. # # I don't recommend using XFS on BK-current without this patch applied :) # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.55 # [PATCH] remaining bits of DEVFS_FL_AUTO_DEVNUM # # Sorry, the devs_only() patch accidentally included the devfs-portion # of the DEVFS_FL_AUTO_DEVNUM patch. This patch contains the remaining # parts. # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.56 # [PATCH] remove regular file support from devfs # # It's the _device_ filesystem, so regular files are grossly misplaced # here. Fortauntely only one driver actually tries to use it (microcode) # and it's works fine with a regular miscdevice as well. # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.57 # [PATCH] missing drivers/video/Makefile entry # # This somehow got lost in the uClinux merge. # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.58 # [PATCH] i2c ID updates # # another bunch of IDs appeared in lm_sensors CVS lately.. # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.59 # [PATCH] update i2c algorithm drivers # # This one is from lm_sensors CVS and mostly cosmetic changes. I it up a # bit to compile properly under latest 2.5. # -------------------------------------------- # 03/03/11 hch@sgi.com 1.1094.1.60 # [PATCH] i2c-core locking updates # # The old adap_lock and driver_lock could deadlock and there was a bunch # of stuff that was horribly racy. The new locking scheme is from # lm_sensors CVS but I had to fix quite a few bugs to make this work. # -------------------------------------------- # 03/03/11 rmk@flint.arm.linux.org.uk 1.1075.9.15 # [SERIAL] Add sa1100 serial PM support using device model. # -------------------------------------------- # 03/03/11 rmk@flint.arm.linux.org.uk 1.1075.9.16 # [SERIAL] Add uart_console(port) macro. # -------------------------------------------- # 03/03/11 mochel@osdl.org 1.1094.1.61 # sysfs: fix BUG()s on directory creation and removal. # # - Don't d_delete() files when removing a directory - they must still be # hashed when dput() reaps them, and it will __d_drop() them anyway. # # - Don't d_invalidate() the directory on removal. # # - do simple_rmdir() after d_delete() on directory. # # - Remove extra dput(), which was causing refcount to go negative, causing # an oops when someone tried to create the directory again. # # - Make sure we don't d_delete() or do extra dput() on file when updating, # either. # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.1 # [CPUFREQ] Yet another typo # From Steven Cole # -------------------------------------------- # 03/03/11 mochel@osdl.org 1.1094.1.62 # driver model: add bus_rescan_devices() # # From Ben Collins # # Used as manual trigger for device/driver binding, so drivers can claim # devices that are present but failed to be bound. In case of ieee1394, this # can happen if two computers are attached to a device - the second one won't # be able to claim it until the first detaches. # # Changed device_attach() to return 1 when a driver was bound to a device. # Makes it so bus_rescan_devices() can return the number of devices attached. # Tested this with ieee1394 over a bus reset and it worked as expected. # -------------------------------------------- # 03/03/11 rmk@flint.arm.linux.org.uk 1.1075.9.17 # [SERIAL] Add PCI serial power management support. # -------------------------------------------- # 03/03/11 shaggy@shaggy.austin.ibm.com 1.1094.4.1 # Merge jfs@jfs.bkbits.net:linux-2.5 # into shaggy.austin.ibm.com:/shaggy/bk/jfs-2.5 # -------------------------------------------- # 03/03/11 Andries.Brouwer@cwi.nl 1.1094.4.2 # [PATCH] some more NAND flash IDs # -------------------------------------------- # 03/03/11 torvalds@home.transmeta.com 1.1094.1.63 # Merge bk://ldm.bkbits.net/linux-2.5-core # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/11 davem@nuts.ninka.net 1.1096 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.2 # [CPUFREQ] Yet more typos # -------------------------------------------- # 03/03/11 sfr@canb.auug.org.au 1.1094.5.1 # [COMPAT]: Sparc64 part of fcntl changes. # -------------------------------------------- # 03/03/11 uzi@uzix.org 1.1094.5.2 # [SPARC64]: Fix warning during uniprocessor build of US3 cpufreq. # -------------------------------------------- # 03/03/11 uzi@uzix.org 1.1094.5.3 # [SPARC64]: Need to export up_clock_tick on uniprocessor. # -------------------------------------------- # 03/03/11 ahaas@airmail.net 1.1097 # [NETFILTER]: Really apply the ipv4 C99 patches this time. :-) # -------------------------------------------- # 03/03/11 davem@kernel.bkbits.net 1.1098 # Merge davem@nuts.ninka.net:/home/davem/src/BK/net-2.5 # into kernel.bkbits.net:/home/davem/net-2.5 # -------------------------------------------- # 03/03/11 torvalds@home.transmeta.com 1.1094.1.64 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.3 # [CPUFREQ] Fix formatting of 'nothing' output. # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.4 # [CPUFREQ] powernow_decode_bios can be static # -------------------------------------------- # 03/03/11 torvalds@home.transmeta.com 1.1099 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.5 # [CPUFREQ] Fix signed comparison warning in powernow-k7 # -------------------------------------------- # 03/03/11 davej@codemonkey.org.uk 1.1094.3.6 # [CPUFREQ] fix signed comparison warnings for longhaul # -------------------------------------------- # 03/03/12 davej@codemonkey.org.uk 1.1094.3.7 # [CPUFREQ] Drop FSB scaling from VIA longhaul driver. # This was incomplete, and never worked 100% on every system, and is # better off dead than half-baked, as it makes the driver a lot simpler, # and removes the possibility of someone being confused why it doesn't # work on their particular hardware. # -------------------------------------------- # 03/03/11 elenstev@mesatop.com 1.1100 # [PATCH] Documentation spelling cleanup # # This patch fixes spelling errors in the Documentation directory and was # extensively reviewed by the following people: Dan Kegel, David # Woodhouse, Joe Perches, Jared Daniel J. Smith, Michael Hayes, and # Steven Cole # -------------------------------------------- # 03/03/11 akpm@digeo.com 1.1101 # [PATCH] unplugging fix # # Patch from Neil Brown # # Allow auto-unplugging to work for devices that do it themselves. # # Auto-unplugging - and blk_unplug_work in particular - assumes that the device # uses "generic_unplug_device" for unplugging, but some devices don't. md # crashes. # # So blk_unplug_work should use ->unplug_fn # -------------------------------------------- # 03/03/12 rmk@flint.arm.linux.org.uk 1.1075.9.18 # [SERIAL] Add Xircom RBM56G PCI ID # -------------------------------------------- # 03/03/12 rmk@flint.arm.linux.org.uk 1.1075.9.19 # [SERIAL] Only update the console termios cflag once # -------------------------------------------- # 03/03/12 paulus@samba.org 1.1102 # PPC32: Add a thread-pointer argument to the clone syscall, make a prepare_to_copy(). # # The thread-pointer argument gets copied to R2 in the child in copy_thread() if # the CLONE_SETTLS flag is set. Adding a prepare_to_copy simplifies the copy_thread # logic since we don't have to do the extra copy of fpu/altivec state to the child. # -------------------------------------------- # 03/03/12 kraxel@bytesex.org 1.1101.1.1 # [PATCH] v4l: crunch MIN/MAX macros. # # This patch deletes the MIN/MAX macros from audiochip.h # and fixes all users of these macros to use the kernels # min/max macros instead. # -------------------------------------------- # 03/03/12 kraxel@bytesex.org 1.1101.1.2 # [PATCH] v4l: create include/media # # This patch creates a new include directory include/media, populates # it with a few files header files and fixups the affected drivers to # compile with the new directory layout. # # The directory is intented to be used for (kernel-internal) header files # of the media drivers (which are sitting below drivers/media). For now # the video-buf.h (mm helper), tuner.h (tv/radio tuner) and audiochip.h # (tv sound decoder drivers) header files are moved. Some more header # files from the dvb folks will likely follow. # -------------------------------------------- # 03/03/12 torvalds@home.transmeta.com 1.1101.1.3 # Error out for the case of a gcc-2.96 compiler with CONFIG_FRAME_POINTER # set. A few versions of gcc-2.96 generate seriously incorrect code. # -------------------------------------------- # 03/03/12 mgreer@mvista.com 1.914.128.6 # PPC32: Fix a problem with 'next' and 'step' type KGDB commands. # -------------------------------------------- # 03/03/12 trini@kernel.crashing.org 1.914.128.7 # PPC32: Replace 2 inline functions with their normal macro equivalents # -------------------------------------------- # 03/03/13 anton@samba.org 1.1075.19.1 # ppc64: add/remove config.h where necessary # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.4 # i2c: add bus driver for ALI15x3 devices # # This is from the i2c CVS tree. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.5 # i2c: get i2c-ali15x3 driver to actually bind to a PCI device. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.6 # i2c: add bus driver for Intel 801 devices # # This is from the i2c CVS tree. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.7 # i2c: get i2c-i801 driver to actually bind to a PCI device. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.8 # i2c: add bus driver for Intel PIIX4 devices # # This is from the i2c CVS tree. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.9 # i2c: get i2c-piix4 driver to actually bind to a PCI device. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.10 # i2c: i2c-piix4.c: Clean up the ibm dma scan logic # # Also export the is_unsafe_smbus variable, which is needed. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.11 # i2c: add i2c sysfs bus support. # -------------------------------------------- # 03/03/13 jgarzik@redhat.com 1.1101.2.1 # [hw_random] shuffle files in preparation for hw_random driver update # # Delete drivers/char/i810_rng.c, superceded. # Rename Doc/i810_rng.txt to Doc/hw_random.txt. # Rename drv/char/amd768_rng.c to drv/char/hw_random.c. # -------------------------------------------- # 03/03/13 jgarzik@redhat.com 1.1101.2.2 # [hw_random] update amd768_rng driver to be modular; add Intel support # # Take Alan's amd768_rng driver, recently renamed to hw_random.c, # and convert it's very-simple structure to support multiple # types of hardware RNG. Integrate Intel i8xx (ICH) RNG support. # -------------------------------------------- # 03/03/13 axboe@suse.de 1.1101.3.1 # [PATCH] remove redundant local_irq_disable in bio_kmap_irq() # -------------------------------------------- # 03/03/13 jgarzik@redhat.com 1.1101.2.3 # [ia32] cpu capabilities cleanups and additions # # * Add support for new Centaur(VIA) and Intel cpuid feature bits, # expanding the x86_capability array by two. # * (cleanup) Move cpu setup for newer Via C3 cpus into its own # function, init_c3() # * Add support for RNG control msr on VIA Nehemiah # * export X86_FEATURE_XSTORE and cpu_has_xstore macros so that # kernel code may easily test for cpu support of the new # "xstore" instruction. # -------------------------------------------- # 03/03/13 jgarzik@redhat.com 1.1101.2.4 # [hw_random] add support for VIA Nehemiah RNG ("xstore" instruction) # -------------------------------------------- # 03/03/13 jgarzik@redhat.com 1.1101.2.5 # [hw_random] fixes and cleanups # # * s/Via/VIA/ # * allow multiple simultaneous open(2)s of the chrdev. This allows # us to eliminate some code, without modifying the core code (rng_dev_read) # at all. # * s/__exit// in ->cleanup ops, to eliminate link error # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.12 # driver core: Export the legacy_bus structure for drivers to use. # -------------------------------------------- # 03/03/13 greg@kroah.com 1.1101.1.13 # i2c: add driver model support to i2c adapter drivers # -------------------------------------------- # 03/03/14 anton@samba.org 1.1101.3.2 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/14 anton@samba.org 1.1101.3.3 # ppc64: compat_sys_fcntl from Stephen Rothwell, remove socketcall emulation # -------------------------------------------- # 03/03/14 paulus@samba.org 1.1103 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/03/14 green@angband.namesys.com 1.1101.4.1 # reiserfs: Correctly free all the allocated memory if open of the journal failed. # Also added \n to some error messages. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.1 # [PATCH] md: Missing mddev_put in md resync code # # Whenever a ITERATE_MDDEV loop is exitted abnormally # we need to mddev_put the current mddev. There was # one point in md_do_sync where we didn't so use counts # became wrong. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.2 # [PATCH] md: Convert /proc/mdstat to use seq_file # # From: Angus Sawyer # # Mainly straightforward convert of sprintf -> seq_printf. seq_start and # seq_next modelled on /proc/partitions. locking/ref counting as for # ITERATE_MDDEV. # # pos == 0 -> header # pos == n -> nth mddev # pos == 0x10000 -> tail # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.3 # [PATCH] md: C99 initiailzers for xor.h # # From: Art Haas # # This patch converts the file to use C99 initializers. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.4 # [PATCH] md: Opencode flush_curr_signals in md.c # # It is (now) too trivial to even have an inline. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.5 # [PATCH] md: Tidy up recovery_running flags in md # # Md uses ->recovery_running and ->recovery_err to keep track of the # status or recovery. This is rather ad hoc and race prone. # # This patch changes it to ->recovery which has bit flags for various # states. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.6 # [PATCH] md: Include asm-i386/387.h in asm-i386/xor.h # # It is needed for kernel_fpu_* # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.7 # [PATCH] md: Remove md_recoveryd thread for md # # The md_recoveryd thread is responsible for initiating and cleaning # up resync threads. # This job can be equally well done by the per-array threads # for those arrays which might need it. # # So the mdrecoveryd thread is gone and the core code that # it ran is now run by raid5d, raid1d or multipathd. # # We add an MD_RECOVERY_NEEDED flag so those daemon don't have # to bother trying to lock the md array unless it is likely # that something needs to be done. # # Also modify the names of all threads to have the number of # md device. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.8 # [PATCH] md: Fulltime delayed 'safe_mode' for md # # From: Angus Sawyer # # If there are no writes for 20 milliseconds, write out superblock # to mark array as clean. Write out superblock with # dirty flag before allowing any further write to succeed. # # If an md thread gets signaled with SIGKILL, reduce the # delay to 0. # # # Also tidy up some printk's and make sure writing the # superblock isn't noisy. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.9 # [PATCH] md: Fix bad interaction between sync checkpointing and recovery # # Md devices (raid1/raid5) can resync or recover. # There are similar but importantly different. # resync happens after an unclean shutdown # recovery happens when a failed drive is being replaced by a hot spare. # # The sync-checkpoint code confused the two somewhat and this causes # problems. # # This patch makes sure "recovery_cp" only relates to resync, # not recovery. # It also fixes a small problem with recording spares in # the superblock. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.10 # [PATCH] md: Allow components of MD raid array to have data start at offset from start of device. # # Normally the data stored on a component of a RAID array is stored # from the start of the device. This patch allows a per-device # data_offset so the data can start elsewhere. This will allow # RAID arrays where the metadata is at the head of the device # rather than the tail. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.11 # [PATCH] md: Allow md to select between superblock formats # # The code to understand a specific superblock format is # already highly localised in md. This patch defines a # user-space interface for selecting which superblock format # to use, and obeys that selection. # # Md currently has a concept of 3 version numbers: # A major version number # A minor version number # A patch version number # # There historically seems to be some confusion about whether # these refer to a version of the superblock layout, # or a version of the software. # # We will now define that: # the "major_version" defines the superblock handler. # '0' is the current superblock format. All new formats # will need new numbers. # the "minor_version" can specify minor variations in the # superblock, such as different location on the device # the "patch_version" will be used to indicate new extenstions # to the software.. patch_version=1 will mean multiple superblock # support. # # A superblock version number is selected by specifing major_version # in SET_ARRAY_INFO ioctl. # # This patch: # Updates Documentation/md.txt with details of new interface. # Generalises desc_nr handling and makes sure that an array never # has two devices with the same desc_nr. # makes sure mddev->major_version is always valid and is 0 by default. # uses mddev->major_version to select superblock handlers. # Modifies set_array_info to just record version number if raid_disks==0 # Makes sure max_disks is always set correctly. # Determines device size when reading superblock, or a hot-add/add-new. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.12 # [PATCH] md: Add new superblock format for md # # Superblock format '1' resolves a number of issues with # superblock format '0'. # It is more dense and can support many more sub-devices. # It does not contains un-needed redundancy. # It adds a few new useful fields # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.13 # [PATCH] kNFSd: Fix exit-without-free bug in nfsd # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.14 # [PATCH] kNFSd: Fix race in svcsock.c # # From: Trond Myklebust # # # knfsd needs to disable soft interrupts when calling # csum_partial_copy_to_xdr(). # # At the moment there's a nasty conflict between the RPC server and # client. The problem arises when you get to xdr_partial_copy_from_skb() # (and the kmap_atomic()); the RPC client can end up calling the same # function from a ->data_ready() soft interrupt, and corrupt any data # the knfsd process may have copied. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.15 # [PATCH] kNFSd: Fix deadlock problem in lockd. # # nlmsvc_lock calls nlmsvc_create_block with file->f_sema # held. # nlmsvc_create_block calls nlmclnt_lookup_host which might # call nlm_gc_hosts which might, eventually, try to claim # file->f_sema for the same file -> deadlock. # # nlmsvc_create_block does not need any protection under # any lock as lockd is single-threaded and _create_block # only plays with internal data structures. # # So we release the f_sema before calling in, and make sure # it gets claimed again afterwards. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.16 # [PATCH] kNFSd: Assort fixes to nfsd auth cache stuff. # # 1/ call cache_fresh when replacing a cache entry (instead of only # when updating) so that up-calls waiting on the replaced entry continue. # # 2/ in svcauth_unix_accept, don't put the verifier until all tests have # succeeded. # # 3/ calculate size of request-being-deferred correctly. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.17 # [PATCH] kNFSd: Rename NFSEXP_CROSSMNT to NFSEXP_NOHIDE # # becase nohide is the user-space visible name # for the flag, and we are about to define a real # CROSSMNT. # -------------------------------------------- # 03/03/14 neilb@cse.unsw.edu.au 1.1101.5.18 # [PATCH] kNFSd: Introduce CROSSMNT flag for knfsd # # Now that we have working up-calls to userspace, # CROSSMNT makes sense. # If CROSSMNT is set for an export, and we too a # LOOKUP which crosses a mountpoint, we initiate an # upcall to find out if and how that filesystem # is exported. # -------------------------------------------- # 03/03/14 jt@bougret.hpl.hp.com 1.1101.5.19 # [PATCH] export platform_bus_type # -------------------------------------------- # 03/03/14 torvalds@home.transmeta.com 1.1101.4.2 # Merge bk://thebsh.namesys.com/bk/reiser3-linux-2.5-relocation-fix # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/14 torvalds@home.transmeta.com 1.1101.2.6 # Merge bk://kernel.bkbits.net/jgarzik/random-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/14 hch@lst.de 1.1101.2.7 # [PATCH] fix OOPS in i2c sysctl registration # # I had to rewrite the code from scratch to understand what it does, # but at least it doesn't OOPS anymore on boot.. # -------------------------------------------- # 03/03/14 hch@lst.de 1.1101.2.8 # [PATCH] fix up the i2c locking changes # # There was one place where we missed an unlock, in addition some more # code cleanups. # -------------------------------------------- # 03/03/14 hch@lst.de 1.1101.2.9 # [PATCH] switch over /proc/bus/i2c to seq_file interface # -------------------------------------------- # 03/03/14 torvalds@home.transmeta.com 1.1101.1.14 # Merge # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1104 # Merge samba.org:/home/paulus/kernel/linux-2.5 # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1105 # Merge bk://stop.crashing.org/linux-2.5-misc # into samba.org:/home/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/03/15 rmk@flint.arm.linux.org.uk 1.1075.9.20 # [TTY] Register tty devclass before use. # # Register the tty devclass with sysfs before tty drivers initialise - # sysfs requires structures to be registered before use. This is # required for the previous serial csets, as well as any drivers which # are initialising using __initcall() or module_init(). # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1106 # PPC32: Better check for when we should expand the stack. # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1107 # PPC32: Set max_pfn correctly. # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1108 # PPC32: Make sure interrupts are disabled in IPI handlers. # -------------------------------------------- # 03/03/15 paulus@samba.org 1.1109 # PPC32: Don't reregister existing /proc/irq entries. # -------------------------------------------- # 03/03/15 torvalds@home.transmeta.com 1.1110 # Revert duplicate addition. # -------------------------------------------- # 03/03/16 anton@samba.org 1.1101.1.15 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/sfr # -------------------------------------------- # 03/03/16 anton@samba.org 1.1068.16.1 # ppc64: remove -finline-limit now that we force inlines # -------------------------------------------- # 03/03/16 anton@samba.org 1.1075.20.1 # Merge bk://ppc.bkbits.net/for-linus-ppc64 # into samba.org:/home/anton/ppc64/for-linus-ppc64 # -------------------------------------------- # 03/03/16 anton@samba.org 1.1101.1.16 # Merge samba.org:/scratch/anton/sfr # into samba.org:/scratch/anton/linux-2.5_ppc64 # -------------------------------------------- # 03/03/16 anton@samba.org 1.1101.1.17 # Merge bk://ppc.bkbits.net/for-linus-ppc64 # into samba.org:/home/anton/ppc64/for-linus-ppc64 # -------------------------------------------- # 03/03/15 torvalds@home.transmeta.com 1.1111 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/15 torvalds@home.transmeta.com 1.1112 # Merge http://ppc.bkbits.net/for-linus-ppc64 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/15 torvalds@home.transmeta.com 1.1113 # Merge bk://bk.arm.linux.org.uk # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/15 zippel@linux-m68k.org 1.1114 # [PATCH] restore old config behaviour for dependencies on 'm' # # This restores the old config behaviour for dependencies on 'm', # such entries are only activ if CONFIG_MODULES is enabled as well. # -------------------------------------------- # 03/03/15 zippel@linux-m68k.org 1.1115 # [PATCH] menu structure fix # # A menu entry was possibly inserted to high in the menu hierarchie if # the previous entry was a derived config symbol. # -------------------------------------------- # 03/03/15 zippel@linux-m68k.org 1.1116 # [PATCH] add menuconfig support # # This adds the support for the menuconfig keyword, which allows to define # a config symbol and a submenu with a single step, e.g. instead of # # menu "SCSI device support" # # config SCSI # tristate "SCSI device support" # # this is now enough: # # menuconfig SCSI # tristate "SCSI device support" # -------------------------------------------- # 03/03/15 zippel@linux-m68k.org 1.1117 # [PATCH] add menuconfig support to the front ends # # This adds the support for the menuconfig to the front ends. # qconf also has now an ".." entry to make it more obvious # how to get to a parent menu. # -------------------------------------------- # 03/03/15 zippel@linux-m68k.org 1.1118 # [PATCH] gtk front end # # This adds the gtk front end by Romain Liévin # -------------------------------------------- # 03/03/15 randy.dunlap@verizon.net 1.1119 # [PATCH] update filesystems config. menu # # This is Robert PJ Day's patch that updates the filesystems # config menu. It had become a bit ad hoc (jumbled:) and this # patch attempts to arrange it more logically. # -------------------------------------------- # 03/03/15 randy.dunlap@verizon.net 1.1120 # [PATCH] typos only # # No code changes; still builds OK. # -------------------------------------------- # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS Sat Mar 15 18:40:43 2003 +++ b/CREDITS Sat Mar 15 18:40:43 2003 @@ -3492,9 +3492,9 @@ N: Marc Zyngier E: maz@wild-wind.fr.eu.org +W: http://www.misterjones.org D: MD driver -S: 11 rue Victor HUGO -S: 95560 Montsoult +D: EISA/sysfs subsystem S: France # Don't add your name here, unless you really _are_ after Marc diff -Nru a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl --- a/Documentation/DocBook/journal-api.tmpl Sat Mar 15 18:40:39 2003 +++ b/Documentation/DocBook/journal-api.tmpl Sat Mar 15 18:40:39 2003 @@ -216,7 +216,7 @@ A new feature of jbd since 2.5.25 is commit callbacks with the new journal_callback_set() function you can now ask the journalling layer -to call you back when the transaction is finally commited to disk, so that +to call you back when the transaction is finally committed to disk, so that you can do some of your own management. The key to this is the journal_callback struct, this maintains the internal callback information but you can extend it like this:- @@ -232,7 +232,7 @@ -this would be useful if you needed to know when data was commited to a +this would be useful if you needed to know when data was committed to a particular inode. diff -Nru a/Documentation/DocBook/sis900.tmpl b/Documentation/DocBook/sis900.tmpl --- a/Documentation/DocBook/sis900.tmpl Sat Mar 15 18:40:42 2003 +++ b/Documentation/DocBook/sis900.tmpl Sat Mar 15 18:40:42 2003 @@ -536,7 +536,7 @@ November 13, 2000, Revision 1.07, seventh release, 630E problem fixed -and furthur clean up. +and further clean up. diff -Nru a/Documentation/arm/Booting b/Documentation/arm/Booting --- a/Documentation/arm/Booting Sat Mar 15 18:40:43 2003 +++ b/Documentation/arm/Booting Sat Mar 15 18:40:43 2003 @@ -47,7 +47,7 @@ used for debugging purposes, or communication with the target.) As an alternative, the boot loader can pass the relevant 'console=' -option to the kernel via the tagged lists specifing the port, and +option to the kernel via the tagged lists specifying the port, and serial format options as described in linux/Documentation/kernel-parameters.txt. diff -Nru a/Documentation/arm/SA1100/serial_UART b/Documentation/arm/SA1100/serial_UART --- a/Documentation/arm/SA1100/serial_UART Sat Mar 15 18:40:41 2003 +++ b/Documentation/arm/SA1100/serial_UART Sat Mar 15 18:40:41 2003 @@ -39,7 +39,7 @@ name. The classic example is the content of the /etc/inittab file where you might have a getty process started on ttyS0. In this case: -- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. +- replace occurrences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. - don't forget to add 'ttySA0', 'console', or the appropriate tty name in /etc/securetty for root to be allowed to login as well. diff -Nru a/Documentation/arm/Setup b/Documentation/arm/Setup --- a/Documentation/arm/Setup Sat Mar 15 18:40:40 2003 +++ b/Documentation/arm/Setup Sat Mar 15 18:40:40 2003 @@ -97,7 +97,7 @@ initrd_size This describes the kernel virtual start address and size of the - inital ramdisk. + initial ramdisk. rd_start diff -Nru a/Documentation/arm/XScale/IOP3XX/dma.txt b/Documentation/arm/XScale/IOP3XX/dma.txt --- a/Documentation/arm/XScale/IOP3XX/dma.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/arm/XScale/IOP3XX/dma.txt Sat Mar 15 18:40:43 2003 @@ -142,7 +142,7 @@ /* User's responsibility to keep buffers cached coherent */ cpu_dcache_clean(sgl->data, sgl->data + 1024); - /* queing the buffer, this function will sleep since no callback */ + /* queuing the buffer, this function will sleep since no callback */ err = dma_queue_buffer(channel, sgl_head); /* now we are woken from DMA complete */ @@ -186,7 +186,7 @@ int dma_flush_all(dmach_t channel); This completely flushes all queued buffers and on-going DMA transfers on a -given channel. This is called when DMA channel errors have occured. +given channel. This is called when DMA channel errors have occurred. void dma_free(dmach_t channel); diff -Nru a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment --- a/Documentation/arm/mem_alignment Sat Mar 15 18:40:41 2003 +++ b/Documentation/arm/mem_alignment Sat Mar 15 18:40:41 2003 @@ -51,7 +51,7 @@ echo 1 > /proc/sys/debug/alignment You can also read the content of the same file to get statistical -information on unaligned access occurences plus the current mode of +information on unaligned access occurrences plus the current mode of operation for user space code. diff -Nru a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/basic_profiling.txt Sat Mar 15 18:40:45 2003 @@ -0,0 +1,48 @@ +These instructions are deliberately very basic. If you want something clever, +go read the real docs ;-) Please don't add more stuff, but feel free to +correct my mistakes ;-) (mbligh@aracnet.com) +Thanks to John Levon, Dave Hansen, et al. for help writing this. + + is the thing you're trying to measure. +Make sure you have the correct System.map / vmlinux referenced! +IMHO it's easier to use "make install" for linux and hack /sbin/installkernel +to copy config files, system.map, vmlinux to /boot. + +Readprofile +----------- +You need a fixed readprofile command for 2.5 ... either get hold of +a current version from: +http://www.kernel.org/pub/linux/utils/util-linux/ +or get readprofile binary fixed for 2.5 / akpm's 2.5 patch from +ftp://ftp.kernel.org/pub/linux/kernel/people/mbligh/tools/readprofile/ + +Add "profile=2" to the kernel command line. + +clear readprofile -r + +dump output readprofile -m /boot/System.map > captured_profile + +Oprofile +-------- +get source (I use 0.5) from http://oprofile.sourceforge.net/ +add "idle=poll" to the kernel command line +Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel +./configure --with-kernel-support +make install + +One time setup (pick appropriate one for your CPU): +P3 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=CPU_CLK_UNHALTED --ctr0-count=100000 +Athlon/x86-64 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=RETIRED_INSNS --ctr0-count=100000 +P4 opcontrol --setup --vmlinux=/boot/vmlinux \ + --ctr0-event=GLOBAL_POWER_EVENTS \ + --ctr0-unit-mask=1 --ctr0-count=100000 + +start daemon opcontrol --start-daemon +clear opcontrol --reset +start opcontrol --start + +stop opcontrol --stop +dump output oprofpp -dl -i /boot/vmlinux > output_file + diff -Nru a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt --- a/Documentation/block/biodoc.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/block/biodoc.txt Sat Mar 15 18:40:43 2003 @@ -635,9 +635,9 @@ be one of the many segments in the current bio (i.e i/o completion unit). The nr_sectors value refers to the total number of sectors in the whole request that remain to be transferred (no change). The purpose of the -hard_xxx values is for block to remember these counts everytime it hands +hard_xxx values is for block to remember these counts every time it hands over the request to the driver. These values are updated by block on -end_that_request_first, i.e. everytime the driver completes a part of the +end_that_request_first, i.e. every time the driver completes a part of the transfer and invokes block end*request helpers to mark this. The driver should not modify these values. The block layer sets up the nr_sectors and current_nr_sectors fields (based on the corresponding diff -Nru a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex --- a/Documentation/cdrom/cdrom-standard.tex Sat Mar 15 18:40:40 2003 +++ b/Documentation/cdrom/cdrom-standard.tex Sat Mar 15 18:40:40 2003 @@ -758,11 +758,8 @@ \subsection{$Struct\ file_operations\ cdrom_fops$} The contents of this structure were described in section~\ref{cdrom.c}. -As already stated, this structure should be used to register block -devices with the kernel: -$$ -register_blkdev(major, , \&cdrom_fops); -$$ +A pointer to this structure is assigned to the $fops$ field +of the $struct gendisk$. \subsection{$Int\ register_cdrom( struct\ cdrom_device_info\ * cdi)$} diff -Nru a/Documentation/computone.txt b/Documentation/computone.txt --- a/Documentation/computone.txt Sat Mar 15 18:40:44 2003 +++ b/Documentation/computone.txt Sat Mar 15 18:40:44 2003 @@ -539,7 +539,7 @@ X for PORTNO in $MINORS X do X if test ! -c /dev/ttyF$PORTNO ; then -X # We got the harware but no device - make it +X # We got the hardware but no device - make it X mknod /dev/ttyF$PORTNO c $TTYMAJOR $PORTNO X fi X done @@ -552,7 +552,7 @@ X for PORTNO in $MINORS X do X if test ! -c /dev/cuf$PORTNO ; then -X # We got the harware but no device - make it +X # We got the hardware but no device - make it X mknod /dev/cuf$PORTNO c $CUAMAJOR $PORTNO X fi X done diff -Nru a/Documentation/cpqarray.txt b/Documentation/cpqarray.txt --- a/Documentation/cpqarray.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/cpqarray.txt Sat Mar 15 18:40:42 2003 @@ -49,9 +49,9 @@ ----------------- If you want to use an EISA controller you'll have to supply some -insmod/lilo paramaters. If the driver is compiled into the kernel, must +insmod/lilo parameters. If the driver is compiled into the kernel, must give it the controller's IO port address at boot time (it is no longer -necessary to specifiy the IRQ). For example, if you had two SMART-2/E +necessary to specify the IRQ). For example, if you had two SMART-2/E controllers, in EISA slots 1 and 2 you'd give it a boot argument like this: diff -Nru a/Documentation/cpu-freq/core.txt b/Documentation/cpu-freq/core.txt --- a/Documentation/cpu-freq/core.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/cpu-freq/core.txt Sat Mar 15 18:40:43 2003 @@ -35,6 +35,10 @@ kernel "constant" loops_per_jiffy is updated on frequency changes here. +Reference counting is done by cpufreq_get_cpu and cpufreq_put_cpu, +which make sure that the cpufreq processor driver is correctly +registered with the core, and will not be unloaded until +cpufreq_put_cpu is called. 2. CPUFreq notifiers ==================== diff -Nru a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt --- a/Documentation/cpu-freq/cpu-drivers.txt Sat Mar 15 18:40:45 2003 +++ b/Documentation/cpu-freq/cpu-drivers.txt Sat Mar 15 18:40:45 2003 @@ -35,7 +35,7 @@ So, you just got a brand-new CPU / chipset with datasheets and want to add cpufreq support for this CPU / chipset? Great. Here are some hints -on what is neccessary: +on what is necessary: 1.1 Initialization @@ -54,7 +54,7 @@ cpufreq_driver.init - A pointer to the per-CPU initialization function. -cpufreq_driver.verify - A pointer to a "verfication" funciton. +cpufreq_driver.verify - A pointer to a "verification" function. cpufreq_driver.setpolicy _or_ cpufreq_driver.target - See below on the differences. @@ -63,13 +63,16 @@ cpufreq_driver.exit - A pointer to a per-CPU cleanup function. +cpufreq_driver.attr - A pointer to a NULL-terminated list of + "struct freq_attr" which allow to + export values to sysfs. 1.2 Per-CPU Initialization -------------------------- Whenever a new CPU is registered with the device model, or after the -cpufreq driver registers itself, the per-CPU initialization fucntion +cpufreq driver registers itself, the per-CPU initialization function cpufreq_driver.init is called. It takes a struct cpufreq_policy *policy as argument. What to do now? @@ -91,7 +94,7 @@ this CPU (if appropriate) policy->min, policy->max, -policy->policy and, if neccessary, +policy->policy and, if necessary, policy->governor must contain the "default policy" for this CPU. A few moments later, cpufreq_driver.verify and either diff -Nru a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt --- a/Documentation/cpu-freq/governors.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/cpu-freq/governors.txt Sat Mar 15 18:40:42 2003 @@ -98,7 +98,7 @@ ------------- The CPUfreq governor "userspace" allows the user, or any userspace -program running with UID "root", to set the CPU to a specifc frequency +program running with UID "root", to set the CPU to a specific frequency by making a sysfs file "scaling_setspeed" available in the CPU-device directory. diff -Nru a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt --- a/Documentation/cpu-freq/user-guide.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/cpu-freq/user-guide.txt Sat Mar 15 18:40:39 2003 @@ -58,7 +58,8 @@ Intel Pentium 4, Intel Xeon National Semiconductors Geode GX Transmeta Crusoe -varios processors on some ACPI 2.0-compatible systems [**] +VIA Cyrix 3 / C3 +various processors on some ACPI 2.0-compatible systems [**] [*] only certain Intel mobile PIII processors are supported. If you know that you own a speedstep-capable processor, pass the option @@ -81,9 +82,9 @@ 2. "Policy" / "Governor" ? ========================== -Some CPU frequency scaling-capable processor switch between varios +Some CPU frequency scaling-capable processor switch between various frequencies and operating voltages "on the fly" without any kernel or -user involvement. This guarantuees very fast switching to a frequency +user involvement. This guarantees very fast switching to a frequency which is high enough to serve the user's needs, but low enough to save power. @@ -93,7 +94,7 @@ On these systems, all you can do is select the lower and upper frequency limit as well as whether you want more aggressive -power-saving or more instantly avaialble processing power. +power-saving or more instantly available processing power. 2.2 Governor @@ -114,9 +115,9 @@ ------------------------------ The preferred interface is located in the sysfs filesystem. If you -mounted it at /sys, the cpufreq interface is located in the -cpu-device directory (e.g. /sys/devices/sys/cpu0/ for the first -CPU). +mounted it at /sys, the cpufreq interface is located in a subdirectory +"cpufreq" within the cpu-device directory +(e.g. /sys/devices/sys/cpu0/cpufreq/ for the first CPU). cpuinfo_min_freq : this file shows the minimum operating frequency the processor can run at(in kHz) @@ -125,7 +126,7 @@ scaling_driver : this file shows what cpufreq driver is used to set the frequency on this CPU -available_scaling_governors : this file shows the CPUfreq governors +scaling_available_governors : this file shows the CPUfreq governors available in this kernel. You can see the currently activated governor in diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/crypto/api-intro.txt Sat Mar 15 18:40:43 2003 @@ -38,9 +38,8 @@ Compressors. The compression algorithms especially seem to be performing very well so far. -An asynchronous scheduling interface is in planning but not yet -implemented, as we need to further analyze the requirements of all of -the possible hardware scenarios (e.g. IPsec NIC offload). +Support for hardware crypto devices via an asynchronous interface is +under development. Here's an example of how to use the API: @@ -87,8 +86,8 @@ DEVELOPER NOTES -None of this code should be called from hardirq context, only softirq and -user contexts. +Transforms may only be allocated in user context, and cryptographic +methods may only be called from softirq and user contexts. When using the API for ciphers, performance will be optimal if each scatterlist contains data which is a multiple of the cipher's block @@ -137,16 +136,11 @@ list, see: http://samba.org/~jamesm/crypto/ -Ongoing development discussion may also be found on -kerneli cryptoapi-devel, -see http://www.kerneli.org/mailman/listinfo/cryptoapi-devel - AUTHORS James Morris David S. Miller -Jean-Francois Dive (SHA1 algorithm module) CREDITS @@ -191,6 +185,10 @@ Matthew Skala (Twofish) Dag Arne Osvik (Serpent) Brian Gladman (AES) + + +SHA1 algorithm contributors: + Jean-Francois Dive DES algorithm contributors: Raimar Falke @@ -215,6 +213,8 @@ Herbert Valerio Riedel Kyle McMartin Adam J. Richter + +Generic scatterwalk code by Adam J. Richter Please send any credits updates or corrections to: James Morris diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt --- a/Documentation/devices.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/devices.txt Sat Mar 15 18:40:41 2003 @@ -898,7 +898,7 @@ ... Network Block Device is somehow similar to loopback - devices: If you read from it, it sends packet accross + devices: If you read from it, it sends packet across network asking server for data. If you write to it, it sends packet telling server to write. It could be used to mounting filesystems over the net, swapping over diff -Nru a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt --- a/Documentation/driver-model/driver.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/driver-model/driver.txt Sat Mar 15 18:40:42 2003 @@ -36,7 +36,7 @@ ~~~~~~~~~~~~~~ The driver must initialize at least the name and bus fields. It should -also initalize the devclass field (when it arrives), so it may obtain +also initialize the devclass field (when it arrives), so it may obtain the proper linkage internally. It should also initialize as many of the callbacks as possible, though each is optional. @@ -93,7 +93,7 @@ }, }; -Some may find the syntax of embedded struct intialization awkward or +Some may find the syntax of embedded struct initialization awkward or even a bit ugly. So far, it's the best way we've found to do what we want... Registration @@ -198,7 +198,7 @@ int (*suspend) (struct device * dev, u32 state, u32 level); suspend is called to put the device in a low power state. There are -several stages to sucessfully suspending a device, which is denoted in +several stages to successfully suspending a device, which is denoted in the @level parameter. Breaking the suspend transition into several stages affords the platform flexibility in performing device power management based on the requirements of the system and the @@ -206,7 +206,7 @@ SUSPEND_NOTIFY notifies the device that a suspend transition is about to happen. This happens on system power state transition to verify -that all devices can sucessfully suspend. +that all devices can successfully suspend. A driver may choose to fail on this call, which should cause the entire suspend transition to fail. A driver should fail only if it diff -Nru a/Documentation/driver-model/platform.txt b/Documentation/driver-model/platform.txt --- a/Documentation/driver-model/platform.txt Sat Mar 15 18:40:44 2003 +++ b/Documentation/driver-model/platform.txt Sat Mar 15 18:40:44 2003 @@ -34,7 +34,7 @@ gives them a common parent if they don't already have one. But, besides the organizational benefits, the platform bus can also -accomodate firmware-based enumeration. +accommodate firmware-based enumeration. Device Discovery diff -Nru a/Documentation/eisa.txt b/Documentation/eisa.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/eisa.txt Sat Mar 15 18:40:45 2003 @@ -0,0 +1,164 @@ +EISA bus support (Marc Zyngier ) + +This document groups random notes about porting EISA drivers to the +new EISA/sysfs API. + +Starting from version 2.5.59, the EISA bus is almost given the same +status as other much more mainstream busses such as PCI or USB. This +has been possible through sysfs, which defines a nice enough set of +abstractions to manage busses, devices and drivers. + +Although the new API is quite simple to use, converting existing +drivers to the new infrastructure is not an easy task (mostly because +detection code is generally also used to probe ISA cards). Moreover, +most EISA drivers are among the oldest Linux drivers so, as you can +imagine, some dust has settled here over the years. + +The EISA infrastructure is made up of three parts : + + - The bus code implements most of the generic code. It is shared + among all the architectures that the EISA code runs on. It + implements bus probing (detecting EISA cards avaible on the bus), + allocates I/O resources, allows fancy naming through sysfs, and + offers interfaces for driver to register. + + - The bus root driver implements the glue between the bus hardware + and the generic bus code. It is responsible for discovering the + device implementing the bus, and setting it up to be latter probed + by the bus code. This can go from something as simple as reserving + an I/O region on x86, to the rather more complex, like the hppa + EISA code. This is the part to implement in order to have EISA + running on an "new" platform. + + - The driver offers the bus a list of devices that it manages, and + implements the necessary callbacks to probe and release devices + whenever told to. + +Every function/structure below lives in , which depends +heavily on . + +** Bus root driver : + +int eisa_root_register (struct eisa_root_device *root); + +The eisa_root_register function is used to declare a device as the +root of an EISA bus. The eisa_root_device structure holds a reference +to this device, as well as some parameters for probing purposes. + +struct eisa_root_device { + struct list_head node; + struct device *dev; /* Pointer to bridge device */ + struct resource *res; + unsigned long bus_base_addr; + int slots; /* Max slot number */ + int bus_nr; /* Set by eisa_root_register */ +}; + +node : used for eisa_root_register internal purpose +dev : pointer to the root device +res : root device I/O resource +bus_base_addr : slot 0 address on this bus +slots : max slot number to probe +bus_nr : unique bus id, set by eisa_root_register + +** Driver : + +int eisa_driver_register (struct eisa_driver *edrv); +void eisa_driver_unregister (struct eisa_driver *edrv); + +Clear enough ? + +struct eisa_device_id { + char sig[EISA_SIG_LEN]; + unsigned long driver_data; +}; + +struct eisa_driver { + const struct eisa_device_id *id_table; + struct device_driver driver; +}; + +id_table : an array of NULL terminated EISA id strings, + followed by an empty string. Each string can be + paired with a driver-dependant value (driver_data). + +driver : a generic driver, such as described in + Documentation/driver-model/driver.txt. Only .name, + .probe and .remove members are mandatory. + +An example is the 3c509 driver : + +struct eisa_device_id el3_eisa_ids[] = { + { "TCM5092" }, + { "TCM5093" }, + { "" } +}; + +struct eisa_driver el3_eisa_driver = { + .id_table = el3_eisa_ids, + .driver = { + .name = "3c509", + .probe = el3_eisa_probe, + .remove = __devexit_p (el3_device_remove) + } +}; + +** Device : + +The sysfs framework calls .probe and .remove functions upon device +discovery and removal (note that the .remove function is only called +when driver is built as a module). + +Both functions are passed a pointer to a 'struct device', which is +encapsulated in a 'struct eisa_device' described as follows : + +struct eisa_device { + struct eisa_device_id id; + int slot; + unsigned long base_addr; + struct resource res; + struct device dev; /* generic device */ +}; + +id : EISA id, as read from device. id.driver_data is set from the + matching driver EISA id. +slot : slot number which the device was detected on +res : I/O resource allocated to this device +dev : generic device (see Documentation/driver-model/device.txt) + +You can get the 'struct eisa_device' from 'struct device' using the +'to_eisa_device' macro. + +** Misc stuff : + +void eisa_set_drvdata (struct eisa_device *edev, void *data); + +Stores data into the device's driver_data area. + +void *eisa_get_drvdata (struct eisa_device *edev): + +Gets the pointer previously stored into the device's driver_data area. + +** Random notes : + +Converting an EISA driver to the new API mostly involves *deleting* +code (since probing is now in the core EISA code). Unfortunately, most +drivers share their probing routine between ISA, MCA and EISA. Special +care must be taken when ripping out the EISA code, so other busses +won't suffer from these surgical strikes... + +You *must not* expect any EISA device to be detected when returning +from eisa_driver_register, since the chances are that the bus has not +yet been probed. In fact, that's what happens most of the time (the +bus root driver usually kicks in rather late in the boot process). +Unfortunately, most drivers are doing the probing by themselves, and +expect to have explored the whole machine when they exit their probe +routine. + +** Thanks : + +I'd like to thank the following people for their help : +- Xavier Benigni for lending me a wonderful Alpha Jensen, +- James Bottomley, Jeff Garzik for getting this stuff into the kernel, +- Andries Brouwer for contributing numerous EISA ids, +- Catrin Jones for coping with too many machines at home diff -Nru a/Documentation/filesystems/Exporting b/Documentation/filesystems/Exporting --- a/Documentation/filesystems/Exporting Sat Mar 15 18:40:41 2003 +++ b/Documentation/filesystems/Exporting Sat Mar 15 18:40:41 2003 @@ -45,7 +45,7 @@ to already have a (non-connected) dentry, and must be able to move that dentry into place (based on the parent and name in the ->lookup). This is particuarly needed for directories as - it is a dcache invarient that directories only have one dentry. + it is a dcache invariant that directories only have one dentry. To implement these features, the dcache has: diff -Nru a/Documentation/filesystems/devfs/README b/Documentation/filesystems/devfs/README --- a/Documentation/filesystems/devfs/README Sat Mar 15 18:40:41 2003 +++ b/Documentation/filesystems/devfs/README Sat Mar 15 18:40:41 2003 @@ -56,7 +56,7 @@ Operational issues (essential reading) Instructions for the impatient -Permissions persistence accross reboots +Permissions persistence across reboots Dealing with drivers without devfs support All the way with Devfs Other Issues @@ -1465,13 +1465,6 @@ The simplest option (especially when porting drivers to devfs) is to keep using the old major and minor numbers. Devfs will take whatever values are given for major&minor and pass them onto userspace. - -Alternatively, you can have devfs choose unique device numbers for -you. When you register a character or block device using -devfs_register you can provide the optional -DEVFS_FL_AUTO_DEVNUM flag, which will then automatically allocate a -unique device number (the allocation is separated for the character -and block devices). This device number is a 16 bit number, so this leaves plenty of space for large numbers of discs and partitions. This scheme can also be diff -Nru a/Documentation/filesystems/directory-locking b/Documentation/filesystems/directory-locking --- a/Documentation/filesystems/directory-locking Sat Mar 15 18:40:43 2003 +++ b/Documentation/filesystems/directory-locking Sat Mar 15 18:40:43 2003 @@ -110,4 +110,4 @@ Notice that "directory" in the above == "anything that might have children", so if we are going to introduce hybrid objects we will need either to make sure that link(2) doesn't work for them or to make changes -in is_subdir() that would make it work even in presense of such beasts. +in is_subdir() that would make it work even in presence of such beasts. diff -Nru a/Documentation/filesystems/ext3.txt b/Documentation/filesystems/ext3.txt --- a/Documentation/filesystems/ext3.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/filesystems/ext3.txt Sat Mar 15 18:40:41 2003 @@ -48,11 +48,11 @@ sb=n Use alternate superblock at this location. -data=journal All data are commited into the journal prior +data=journal All data are committed into the journal prior to being written into the main file system. data=ordered (*) All data are forced directly out to the main file - system prior to its metadata being commited to + system prior to its metadata being committed to the journal. data=writeback Data ordering is not preserved, data may be diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/filesystems/proc.txt Sat Mar 15 18:40:40 2003 @@ -344,7 +344,7 @@ Each column represents the number of pages of a certain order which are available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE -availble in ZONE_NORMAL, etc... +available in ZONE_NORMAL, etc... 1.3 IDE devices in /proc/ide diff -Nru a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt --- a/Documentation/filesystems/sysfs.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/filesystems/sysfs.txt Sat Mar 15 18:40:40 2003 @@ -55,7 +55,7 @@ value per file, so it is socially acceptable to express an array of values of the same type. -Mixing types, expressing mulitple lines of data, and doing fancy +Mixing types, expressing multiple lines of data, and doing fancy formatting of data is heavily frowned upon. Doing these things may get you publically humiliated and your code rewritten without notice. diff -Nru a/Documentation/hw_random.txt b/Documentation/hw_random.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/hw_random.txt Sat Mar 15 18:40:43 2003 @@ -0,0 +1,134 @@ + Hardware driver for Intel i810 Random Number Generator (RNG) + Copyright 2000,2001 Jeff Garzik + Copyright 2000,2001 Philipp Rumpf + +Introduction: + + The i810_rng device driver is software that makes use of a + special hardware feature on the Intel i8xx-based chipsets, + a Random Number Generator (RNG). + + In order to make effective use of this device driver, you + should download the support software as well. Download the + latest version of the "intel-rng-tools" package from the + i810_rng driver's official Web site: + + http://sourceforge.net/projects/gkernel/ + +About the Intel RNG hardware, from the firmware hub datasheet: + + The Firmware Hub integrates a Random Number Generator (RNG) + using thermal noise generated from inherently random quantum + mechanical properties of silicon. When not generating new random + bits the RNG circuitry will enter a low power state. Intel will + provide a binary software driver to give third party software + access to our RNG for use as a security feature. At this time, + the RNG is only to be used with a system in an OS-present state. + +Theory of operation: + + Character driver. Using the standard open() + and read() system calls, you can read random data from + the i810 RNG device. This data is NOT CHECKED by any + fitness tests, and could potentially be bogus (if the + hardware is faulty or has been tampered with). Data is only + output if the hardware "has-data" flag is set, but nevertheless + a security-conscious person would run fitness tests on the + data before assuming it is truly random. + + /dev/intel_rng is char device major 10, minor 183. + +Driver notes: + + * FIXME: support poll(2) + + NOTE: request_mem_region was removed, for two reasons: + 1) Only one RNG is supported by this driver, 2) The location + used by the RNG is a fixed location in MMIO-addressable memory, + 3) users with properly working BIOS e820 handling will always + have the region in which the RNG is located reserved, so + request_mem_region calls always fail for proper setups. + However, for people who use mem=XX, BIOS e820 information is + -not- in /proc/iomem, and request_mem_region(RNG_ADDR) can + succeed. + +Driver details: + + Based on: + Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet + May 1999 Order Number: 290658-002 R + + Intel 82802 Firmware Hub: Random Number Generator + Programmer's Reference Manual + December 1999 Order Number: 298029-001 R + + Intel 82802 Firmware HUB Random Number Generator Driver + Copyright (c) 2000 Matt Sottek + + Special thanks to Matt Sottek. I did the "guts", he + did the "brains" and all the testing. + +Change history: + + Version 0.9.8: + * Support other i8xx chipsets by adding 82801E detection + * 82801DB detection is the same as for 82801CA. + + Version 0.9.7: + * Support other i8xx chipsets too (by adding 82801BA(M) and + 82801CA(M) detection) + + Version 0.9.6: + * Internal driver cleanups, prep for 1.0.0 release. + + Version 0.9.5: + * Rip out entropy injection via timer. It never ever worked, + and a better solution (rngd) is now available. + + Version 0.9.4: + * Fix: Remove request_mem_region + * Fix: Horrible bugs in FIPS calculation and test execution + + Version 0.9.3: + * Clean up rng_read a bit. + * Update i810_rng driver Web site URL. + * Increase default timer interval to 4 samples per second. + * Abort if mem region is not available. + * BSS zero-initialization cleanup. + * Call misc_register() from rng_init_one. + * Fix O_NONBLOCK to occur before we schedule. + + Version 0.9.2: + * Simplify open blocking logic + + Version 0.9.1: + * Support i815 chipsets too (Matt Sottek) + * Fix reference counting when statically compiled (prumpf) + * Rewrite rng_dev_read (prumpf) + * Make module races less likely (prumpf) + * Small miscellaneous bug fixes (prumpf) + * Use pci table for PCI id list + + Version 0.9.0: + * Don't register a pci_driver, because we are really + using PCI bridge vendor/device ids, and someone + may want to register a driver for the bridge. (bug fix) + * Don't let the usage count go negative (bug fix) + * Clean up spinlocks (bug fix) + * Enable PCI device, if necessary (bug fix) + * iounmap on module unload (bug fix) + * If RNG chrdev is already in use when open(2) is called, + sleep until it is available. + * Remove redundant globals rng_allocated, rng_use_count + * Convert numeric globals to unsigned + * Module unload cleanup + + Version 0.6.2: + * Clean up spinlocks. Since we don't have any interrupts + to worry about, but we do have a timer to worry about, + we use spin_lock_bh everywhere except the timer function + itself. + * Fix module load/unload. + * Fix timer function and h/w enable/disable logic + * New timer interval sysctl + * Clean up sysctl names diff -Nru a/Documentation/i810_rng.txt b/Documentation/i810_rng.txt --- a/Documentation/i810_rng.txt Sat Mar 15 18:40:43 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,134 +0,0 @@ - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik - Copyright 2000,2001 Philipp Rumpf - -Introduction: - - The i810_rng device driver is software that makes use of a - special hardware feature on the Intel i8xx-based chipsets, - a Random Number Generator (RNG). - - In order to make effective use of this device driver, you - should download the support software as well. Download the - latest version of the "intel-rng-tools" package from the - i810_rng driver's official Web site: - - http://sourceforge.net/projects/gkernel/ - -About the Intel RNG hardware, from the firmware hub datasheet: - - The Firmware Hub integrates a Random Number Generator (RNG) - using thermal noise generated from inherently random quantum - mechanical properties of silicon. When not generating new random - bits the RNG circuitry will enter a low power state. Intel will - provide a binary software driver to give third party software - access to our RNG for use as a security feature. At this time, - the RNG is only to be used with a system in an OS-present state. - -Theory of operation: - - Character driver. Using the standard open() - and read() system calls, you can read random data from - the i810 RNG device. This data is NOT CHECKED by any - fitness tests, and could potentially be bogus (if the - hardware is faulty or has been tampered with). Data is only - output if the hardware "has-data" flag is set, but nevertheless - a security-conscious person would run fitness tests on the - data before assuming it is truly random. - - /dev/intel_rng is char device major 10, minor 183. - -Driver notes: - - * FIXME: support poll(2) - - NOTE: request_mem_region was removed, for two reasons: - 1) Only one RNG is supported by this driver, 2) The location - used by the RNG is a fixed location in MMIO-addressable memory, - 3) users with properly working BIOS e820 handling will always - have the region in which the RNG is located reserved, so - request_mem_region calls always fail for proper setups. - However, for people who use mem=XX, BIOS e820 information is - -not- in /proc/iomem, and request_mem_region(RNG_ADDR) can - succeed. - -Driver details: - - Based on: - Intel 82802AB/82802AC Firmware Hub (FWH) Datasheet - May 1999 Order Number: 290658-002 R - - Intel 82802 Firmware Hub: Random Number Generator - Programmer's Reference Manual - December 1999 Order Number: 298029-001 R - - Intel 82802 Firmware HUB Random Number Generator Driver - Copyright (c) 2000 Matt Sottek - - Special thanks to Matt Sottek. I did the "guts", he - did the "brains" and all the testing. - -Change history: - - Version 0.9.8: - * Support other i8xx chipsets by adding 82801E detection - * 82801DB detection is the same as for 82801CA. - - Version 0.9.7: - * Support other i8xx chipsets too (by adding 82801BA(M) and - 82801CA(M) detection) - - Version 0.9.6: - * Internal driver cleanups, prep for 1.0.0 release. - - Version 0.9.5: - * Rip out entropy injection via timer. It never ever worked, - and a better solution (rngd) is now available. - - Version 0.9.4: - * Fix: Remove request_mem_region - * Fix: Horrible bugs in FIPS calculation and test execution - - Version 0.9.3: - * Clean up rng_read a bit. - * Update i810_rng driver Web site URL. - * Increase default timer interval to 4 samples per second. - * Abort if mem region is not available. - * BSS zero-initialization cleanup. - * Call misc_register() from rng_init_one. - * Fix O_NONBLOCK to occur before we schedule. - - Version 0.9.2: - * Simplify open blocking logic - - Version 0.9.1: - * Support i815 chipsets too (Matt Sottek) - * Fix reference counting when statically compiled (prumpf) - * Rewrite rng_dev_read (prumpf) - * Make module races less likely (prumpf) - * Small miscellaneous bug fixes (prumpf) - * Use pci table for PCI id list - - Version 0.9.0: - * Don't register a pci_driver, because we are really - using PCI bridge vendor/device ids, and someone - may want to register a driver for the bridge. (bug fix) - * Don't let the usage count go negative (bug fix) - * Clean up spinlocks (bug fix) - * Enable PCI device, if necessary (bug fix) - * iounmap on module unload (bug fix) - * If RNG chrdev is already in use when open(2) is called, - sleep until it is available. - * Remove redundant globals rng_allocated, rng_use_count - * Convert numeric globals to unsigned - * Module unload cleanup - - Version 0.6.2: - * Clean up spinlocks. Since we don't have any interrupts - to worry about, but we do have a timer to worry about, - we use spin_lock_bh everywhere except the timer function - itself. - * Fix module load/unload. - * Fix timer function and h/w enable/disable logic - * New timer interval sysctl - * Clean up sysctl names diff -Nru a/Documentation/ia64/IRQ-redir.txt b/Documentation/ia64/IRQ-redir.txt --- a/Documentation/ia64/IRQ-redir.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/ia64/IRQ-redir.txt Sat Mar 15 18:40:43 2003 @@ -29,7 +29,7 @@ The output of the command cat /proc/irq/IRQ#/smp_affinity gives the target CPU mask for the specified interrupt vector. If the CPU -mask is preceeded by the character "r", the interrupt is redirectable +mask is preceded by the character "r", the interrupt is redirectable (i.e. lowest priority mode routing is used), otherwise its route is fixed. diff -Nru a/Documentation/ia64/fsys.txt b/Documentation/ia64/fsys.txt --- a/Documentation/ia64/fsys.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/ia64/fsys.txt Sat Mar 15 18:40:42 2003 @@ -4,7 +4,7 @@ ----------------------------------- Started: 13-Jan-2003 - Last update: 24-Jan-2003 + Last update: 11-Feb-2003 David Mosberger-Tang @@ -42,9 +42,9 @@ can disable interrupts and avoid all other interruption-sources to avoid preemption) - - neither the memory nor the register stack can be trusted while + - neither the memory-stack nor the register-stack can be trusted while in fsys-mode (they point to the user-level stacks, which may - be invalid) + be invalid, or completely bogus addresses) In summary, fsys-mode is much more similar to running in user-mode than it is to running in kernel-mode. Of course, given that the diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt --- a/Documentation/ide.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/ide.txt Sat Mar 15 18:40:43 2003 @@ -4,7 +4,7 @@ ============================================================================== - The hdparm utility can be used to controll various IDE features on a + The hdparm utility can be used to control various IDE features on a running system. It is packaged separately. Please Look for it on popular linux FTP sites. @@ -37,7 +37,7 @@ ================================================================================ Common pitfalls: -- 40-conductor IDE cables are capable of transfering data in DMA modes up to +- 40-conductor IDE cables are capable of transferring data in DMA modes up to udma2, but no faster. - If possible devices should be attached to separate channels if they are diff -Nru a/Documentation/input/ff.txt b/Documentation/input/ff.txt --- a/Documentation/input/ff.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/input/ff.txt Sat Mar 15 18:40:42 2003 @@ -163,7 +163,7 @@ ~~~~~~~~~~~~~~~~~~~~ Not all devices have the same strength. Therefore, users should set a gain factor depending on how strong they want effects to be. This setting is -persistent accross access to the driver, so you should not care about it if +persistent across access to the driver, so you should not care about it if you are writing games, as another utility probably already set this for you. /* Set the gain of the device @@ -200,7 +200,7 @@ Proceed as if you wanted to upload a new effect, except that instead of setting the id field to -1, you set it to the wanted effect id. Normally, the effect is not stopped and restarted. However, depending on the -type of device, not all paramaters can be dynamically updated. For example, +type of device, not all parameters can be dynamically updated. For example, the direction of an effect cannot be updated with iforce devices. In this case, the driver stops the effect, up-load it, and restart it. diff -Nru a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE --- a/Documentation/isdn/INTERFACE Sat Mar 15 18:40:43 2003 +++ b/Documentation/isdn/INTERFACE Sat Mar 15 18:40:43 2003 @@ -735,7 +735,7 @@ driver = driver-Id command = ISDN_STAT_PROT arg = The lower 8 Bits define the addressed protocol as defined - in ISDN_PTYPE..., the upper bits are used to differenciate + in ISDN_PTYPE..., the upper bits are used to differentiate the protocol specific STAT. para = protocol and function specific. See isdnif.h for detail. diff -Nru a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt --- a/Documentation/kbuild/kconfig-language.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/kbuild/kconfig-language.txt Sat Mar 15 18:40:41 2003 @@ -69,7 +69,7 @@ default values are visible, only the first defined one is active. Default values are not limited to the menu entry, where they are defined, this means the default can be defined somewhere else or be - overriden by an earlier definition. + overridden by an earlier definition. The default value is only assigned to the config symbol if no other value was set by the user (via the input prompt above). If an input prompt is visible the default value is presented to the user and can @@ -142,7 +142,7 @@ -------------- The position of a menu entry in the tree is determined in two ways. First -it can be specified explicitely: +it can be specified explicitly: menu "Network device support" depends NET diff -Nru a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt --- a/Documentation/kbuild/makefiles.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/kbuild/makefiles.txt Sat Mar 15 18:40:43 2003 @@ -561,7 +561,7 @@ Usually kbuild descends down in subdirectories due to "obj-* := dir/", but in the architecture makefiles where the kbuild infrastructure -is not sufficent this sometimes needs to be explicit. +is not sufficient this sometimes needs to be explicit. Example: #arch/i386/boot/Makefile diff -Nru a/Documentation/kernel-doc-nano-HOWTO.txt b/Documentation/kernel-doc-nano-HOWTO.txt --- a/Documentation/kernel-doc-nano-HOWTO.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/kernel-doc-nano-HOWTO.txt Sat Mar 15 18:40:41 2003 @@ -21,7 +21,7 @@ This is a program for converting SGML template files into SGML files. When a file is referenced it is searched for symbols - exported (EXPORT_SYMBOL), to be able to distingush between internal + exported (EXPORT_SYMBOL), to be able to distinguish between internal and external functions. It invokes kernel-doc, giving it the list of functions that are to be documented. diff -Nru a/Documentation/kernel-docs.txt b/Documentation/kernel-docs.txt --- a/Documentation/kernel-docs.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/kernel-docs.txt Sat Mar 15 18:40:42 2003 @@ -488,7 +488,7 @@ memory allocation. Description: Article written for people wishing to make their data acquisition boards work on their GNU/Linux machines. Gives a basic - overview on writting drivers, from the naming of functions to + overview on writing drivers, from the naming of functions to interrupt handling. Notes: Two-parts article. Part II is at http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm diff -Nru a/Documentation/kobject.txt b/Documentation/kobject.txt --- a/Documentation/kobject.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/kobject.txt Sat Mar 15 18:40:40 2003 @@ -7,7 +7,7 @@ 0. Introduction -The kobject infrastructure performs basic object managment that larger +The kobject infrastructure performs basic object management that larger data structures and subsystems can leverage, rather than reimplement similar functionality. This functionality consists primarily concerns: diff -Nru a/Documentation/magic-number.txt b/Documentation/magic-number.txt --- a/Documentation/magic-number.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/magic-number.txt Sat Mar 15 18:40:42 2003 @@ -146,7 +146,7 @@ NMI_MAGIC 0x48414d4d455201 nmi_s include/asm-mips64/sn/nmi.h Note that there are also defined special per-driver magic numbers in sound -memory managment. See include/sound/sndmagic.h for complete list of them. Many +memory management. See include/sound/sndmagic.h for complete list of them. Many OSS sound drivers have their magic numbers constructed from the soundcard PCI ID - these are not listed here as well. diff -Nru a/Documentation/md.txt b/Documentation/md.txt --- a/Documentation/md.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/md.txt Sat Mar 15 18:40:43 2003 @@ -1,10 +1,10 @@ Tools that manage md devices can be found at - http://www..kernel.org/pub/linux/daemons/raid/.... + http://www..kernel.org/pub/linux/utils/raid/.... -You can boot (if you selected boot support in the configuration) with your md -device with the following kernel command lines: +You can boot with your md device with the following kernel command +lines: for old raid arrays without persistent superblocks: md=,,,,dev0,dev1,...,devn @@ -33,4 +33,64 @@ A possible loadlin line (Harald Hoyer ) looks like this: e:\loadlin\loadlin e:\zimage root=/dev/md0 md=0,0,4,0,/dev/hdb2,/dev/hdc3 ro - + +------------------------------- +The md driver can support a variety of different superblock formats. +(It doesn't yet, but it can) + +The kernel does *NOT* autodetect which format superblock is being +used. It must be told. + +Superblock format '0' is treated differently to others for legacy +reasons. + + +General Rules - apply for all superblock formats +------------------------------------------------ + +An array is 'created' by writing appropriate superblocks to all +devices. +It is 'assembled' by associating each of these devices with an +particular md virtual device. Once it is completely assembled, it can +be accessed. + +An array should be created by a user-space tool. This will write +superblocks to all devices. It will usually mark the array as +'unclean', or with some devices missing so that the kernel md driver +can create approrpriate redundancy (copying in raid1, parity +calculation in raid4/5). + +When an array is assembled, it is first initialised with the +SET_ARRAY_INFO ioctl. This contains, in particular, a major and minor +version number. The major version number selects which superblock +format is to be used. The minor number might be used to tune handling +of the format, such as suggesting where on each device to look for the +superblock. + +Then each device is added using the ADD_NEW_DISK ioctl. This +provides, in particular, a major and minor number identifying the +device to add. + +The array is started with the RUN_ARRAY ioctl. + +Once started, new devices can be added. They should have an +appropriate superblock written to them, and then passed be in with +ADD_NEW_DISK. + +Devices that have failed or are not yet active can be detached from an +array using HOT_REMOVE_DISK. + + +Specific Rules that apply to format-0 super block arrays, and + arrays with no superblock (non-presistant). +------------------------------------------------------------- + +An array can be 'created' by describing the array (level, chunksize +etc) in a SET_ARRAY_INFO ioctl. This must has major_version==0 and +raid_disks != 0. +Then uninitialised devices can be added with ADD_NEW_DISK. The +structure passed to ADD_NEW_DISK must specify the state of the device +and it's role in the array. + +One started with RUN_ARRAY, uninitialised spares can be added with +HOT_ADD_DISK. diff -Nru a/Documentation/networking/3c359.txt b/Documentation/networking/3c359.txt --- a/Documentation/networking/3c359.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/networking/3c359.txt Sat Mar 15 18:40:43 2003 @@ -41,7 +41,7 @@ message_level: Controls level of messages created by the driver. Defaults to 0: which only displays start-up and critical messages. Presently any non-zero value will display all soft messages as well. NB This does not turn -debuging messages on, that must be done by modified the source code. +debugging messages on, that must be done by modified the source code. Variable MTU size: diff -Nru a/Documentation/networking/3c509.txt b/Documentation/networking/3c509.txt --- a/Documentation/networking/3c509.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/networking/3c509.txt Sat Mar 15 18:40:40 2003 @@ -106,7 +106,7 @@ 8 transceiver type and duplex mode taken from card's EEPROM config settings 12 10baseT (RJ-45 connector); force full-duplex mode -Prior to driver version 1.18c, only tranceiver codes 0-4 were supported. Note +Prior to driver version 1.18c, only transceiver codes 0-4 were supported. Note that the new transceiver codes 8 and 12 are the *only* ones that will enable full-duplex mode, no matter what the card's detected EEPROM settings might be. This insured that merely upgrading the driver from an earlier version would @@ -146,7 +146,7 @@ Tx Carrier Errors Reported in /proc/net/dev If an EtherLink III appears to transmit packets, but the "Tx carrier errors" field in /proc/net/dev increments as quickly as the Tx packet count, you -likely have an unterminated network or the incorrect media tranceiver selected. +likely have an unterminated network or the incorrect media transceiver selected. 3c509B card is not detected on machines with an ISA PnP BIOS. While the updated driver works with most PnP BIOS programs, it does not work diff -Nru a/Documentation/networking/NAPI_HOWTO.txt b/Documentation/networking/NAPI_HOWTO.txt --- a/Documentation/networking/NAPI_HOWTO.txt Sat Mar 15 18:40:42 2003 +++ b/Documentation/networking/NAPI_HOWTO.txt Sat Mar 15 18:40:42 2003 @@ -85,7 +85,7 @@ In this case your only choice is to move all to dev->poll() II) Clear-on-write (COW) - i) you clear the status by writting a 1 in the bit-location you want. + i) you clear the status by writing a 1 in the bit-location you want. These are the majority of the NICs and work the best with NAPI. Put only receive events in dev->poll(); leave the rest in the old interrupt handler. @@ -200,7 +200,7 @@ /* two new additions */ /* first register my poll method */ dev->poll = my_poll; -/* next register my weight/quanta; can be overriden in /proc */ +/* next register my weight/quanta; can be overridden in /proc */ dev->weight = 16; . . @@ -346,10 +346,10 @@ netif_rx_schedule_prep() returns 1 if device is in running state and gets successfully added to the core poll list. If we get a zero value we can _almost_ assume are already added to the list (instead of not running. -Logic based on the fact that you shouldnt get interrupt if not running) +Logic based on the fact that you shouldn't get interrupt if not running) We rectify this by disabling rx and rxnobuf interrupts. -II) that receive_packets(dev) and make_rx_buffs_avail() may have dissapeared. +II) that receive_packets(dev) and make_rx_buffs_avail() may have disappeared. These functionalities are still around actually...... infact, receive_packets(dev) is very close to my_poll() and @@ -442,7 +442,7 @@ int rx_work_limit = dev->quota; /************************ end note note *********************************/ - do { // outer beggining loop starts here + do { // outer beginning loop starts here clear_rx_status_register_bit(); diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt --- a/Documentation/networking/bonding.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/networking/bonding.txt Sat Mar 15 18:40:40 2003 @@ -304,7 +304,7 @@ Configuring Multiple ARP Targets ================================ -While ARP monitoring can be done with just one target, it can be usefull +While ARP monitoring can be done with just one target, it can be useful in a High Availability setup to have several targets to monitor. In the case of just one target, the target itself may go down or have a problem making it unresponsive to ARP requests. Having an additional target (or diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c --- a/Documentation/networking/ifenslave.c Sat Mar 15 18:40:40 2003 +++ b/Documentation/networking/ifenslave.c Sat Mar 15 18:40:40 2003 @@ -540,7 +540,7 @@ static short mif_flags; -/* Get the inteface configuration from the kernel. */ +/* Get the interface configuration from the kernel. */ static int if_getconfig(char *ifname) { struct ifreq ifr; diff -Nru a/Documentation/networking/sis900.txt b/Documentation/networking/sis900.txt --- a/Documentation/networking/sis900.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/networking/sis900.txt Sat Mar 15 18:40:39 2003 @@ -243,7 +243,7 @@ Chapter 7. Revision History * November 13, 2000, Revision 1.07, seventh release, 630E problem - fixed and furthur clean up. + fixed and further clean up. * November 4, 1999, Revision 1.06, Second release, lots of clean up and optimization. * August 8, 1999, Revision 1.05, Initial Public Release diff -Nru a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt --- a/Documentation/networking/sk98lin.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/networking/sk98lin.txt Sat Mar 15 18:40:43 2003 @@ -138,7 +138,7 @@ options sk98lin ... For "...", use the same syntax as described below for the command -line paramaters of modprobe. +line parameters of modprobe. You either have to reboot your computer or unload and reload the driver to activate the new parameters. The syntax of the driver parameters is: @@ -276,7 +276,7 @@ Large frames (also called jumbo frames) are now supported by the driver. This can result in a greatly improved throughput if -transfering large amounts of data. +transferring large amounts of data. To enable large frames, set the MTU (maximum transfer unit) of the interface to the value you wish (up to 9000). The command for this is: @@ -489,7 +489,7 @@ established (#10402) - Installation problems with RedHat 6.0 (#10409) New Features: -- Connection state ouput at "network connection up" +- Connection state output at "network connection up" Known limitations: - None diff -Nru a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt --- a/Documentation/networking/tuntap.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/networking/tuntap.txt Sat Mar 15 18:40:41 2003 @@ -40,7 +40,7 @@ Set permissions: e.g. chmod 0700 /dev/net/tun - if you want the device only accesible by root. Giving regular users the + if you want the device only accessible by root. Giving regular users the right to assign network devices is NOT a good idea. Users could assign bogus network interfaces to trick firewalls or administrators. diff -Nru a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt --- a/Documentation/networking/wan-router.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/networking/wan-router.txt Sat Mar 15 18:40:40 2003 @@ -577,7 +577,7 @@ bata2-2.2.1 Feb 20 2001 o Bug fixes to the CHDLC device drivers. - The driver had compilation problmes under kernels + The driver had compilation problems under kernels 2.2.14 or lower. o Bug fixes to the Setup installation script. diff -Nru a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt --- a/Documentation/networking/wanpipe.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/networking/wanpipe.txt Sat Mar 15 18:40:40 2003 @@ -577,7 +577,7 @@ bata2-2.2.1 Feb 20 2001 o Bug fixes to the CHDLC device drivers. - The driver had compilation problmes under kernels + The driver had compilation problems under kernels 2.2.14 or lower. o Bug fixes to the Setup installation script. diff -Nru a/Documentation/oops-tracing.txt b/Documentation/oops-tracing.txt --- a/Documentation/oops-tracing.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/oops-tracing.txt Sat Mar 15 18:40:40 2003 @@ -219,7 +219,7 @@ 2: 'F' if any module was force loaded by insmod -f, ' ' if all modules were loaded normally. - 3: 'S' if the oops occured on an SMP kernel running on hardware that + 3: 'S' if the oops occurred on an SMP kernel running on hardware that hasn't been certified as safe to run multiprocessor. Currently this occurs only on various Athlons that are not SMP capable. diff -Nru a/Documentation/pnp.txt b/Documentation/pnp.txt --- a/Documentation/pnp.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/pnp.txt Sat Mar 15 18:40:40 2003 @@ -96,7 +96,7 @@ All Plug and Play drivers, protocols, and services meet at a central location called the Plug and Play Layer. This layer is responsible for the exchange of information between PnP drivers and PnP protocols. Thus it automatically -forwards commands to the proper protocol. This makes writting PnP drivers +forwards commands to the proper protocol. This makes writing PnP drivers significantly easier. The following functions are available from the Plug and Play Layer: diff -Nru a/Documentation/s390/Debugging390.txt b/Documentation/s390/Debugging390.txt --- a/Documentation/s390/Debugging390.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/s390/Debugging390.txt Sat Mar 15 18:40:40 2003 @@ -52,7 +52,7 @@ 16 General propose registers, 32 bit on s/390 64 bit on z/Architecture, r0-r15 or gpr0-gpr15 used for arithmetic & addressing. -16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory managment, +16 Control registers, 32 bit on s/390 64 bit on z/Architecture, ( cr0-cr15 kernel usage only ) used for memory management, interrupt control,debugging control etc. 16 Access registers ( ar0-ar15 ) 32 bit on s/390 & z/Architecture @@ -243,7 +243,7 @@ spaces for the user & kernel. This means we can support 2GB of non Extended RAM on s/390, & more -with the Extended memory managment swap device & +with the Extended memory management swap device & currently 4TB of physical memory currently on z/Architecture. @@ -385,7 +385,7 @@ of extra space on the callers stack which is obviously freed up on function exit ( e.g. the caller may choose to allocate nothing of a buffer of 4k if required for temporary purposes ), it generates -very efficent code ( a few cycles ) when compared to alternatives +very efficient code ( a few cycles ) when compared to alternatives like malloc. automatics: These are local variables on the stack, @@ -1091,7 +1091,7 @@ The VM Debugger is case insensitive. VM's strengths are usually other debuggers weaknesses you can get at any resource -no matter how sensitive e.g. memory managment resources,change address translation +no matter how sensitive e.g. memory management resources,change address translation in the PSW. For kernel hacking you will reap dividends if you get good at it. The VM Debugger displays operators but not operands, probably because some @@ -1194,7 +1194,7 @@ Displaying & modifying Registers -------------------------------- D G will display all the gprs -Adding a extra G to all the commands is neccessary to access the full 64 bit +Adding a extra G to all the commands is necessary to access the full 64 bit content in VM on z/Architecture obviously this isn't required for access registers as these are still 32 bit. e.g. DGG instead of DG @@ -1280,7 +1280,7 @@ Tracing particular processes ---------------------------- -The kernels text segment is intentionally at an address in memory that it will +The kernel's text segment is intentionally at an address in memory that it will very seldom collide with text segments of user programs ( thanks Martin ), this simplifies debugging the kernel. However it is quite common for user processes to have addresses which collide @@ -1425,7 +1425,7 @@ shutdown -h now or halt. do a Q CPUS to find out how many cpus you have detach each one of them from cp except cpu 0 -by issueing a +by issuing a DETACH CPU 01-(number of cpus in configuration) & boot linux again. TR SIGP will trace inter processor signal processor instructions. @@ -1671,7 +1671,7 @@ ( & many other instructions ) they consist of a length field & an absolute address field. For each IO typically get 1 or 2 interrupts one for channel end ( primary status ) when the channel is idle & the second for device end ( secondary status ) sometimes you get both -concurrently, you check how the IO went on by issueing a TEST SUBCHANNEL at each interrupt, +concurrently, you check how the IO went on by issuing a TEST SUBCHANNEL at each interrupt, from which you receive an Interruption response block (IRB). If you get channel & device end status in the IRB without channel checks etc. your IO probably went okay. If you didn't you probably need a doctorto examine the IRB & extended status word etc. @@ -2153,14 +2153,14 @@ current working directory. This is very useful in that a customer can mail a core dump to a technical support department & the technical support department can reconstruct what happened. -Provided the have an indentical copy of this program with debugging symbols compiled in & +Provided the have an identical copy of this program with debugging symbols compiled in & the source base of this build is available. In short it is far more useful than something like a crash log could ever hope to be. In theory all that is missing to restart a core dumped program is a kernel patch which will do the following. 1) Make a new kernel task structure -2) Reload all the dumped pages back into the kernels memory managment structures. +2) Reload all the dumped pages back into the kernel's memory management structures. 3) Do the required clock fixups 4) Get all files & network connections for the process back into an identical state ( really difficult ). 5) A few more difficult things I haven't thought of. @@ -2374,7 +2374,7 @@ e.g. to switch on the lcs "debug feature" echo 5 > /proc/s390dbf/lcs/level -& then after the error occured. +& then after the error occurred. cat /proc/s390dbf/lcs/sprintf >/logfile the logfile now contains some information which may help tech support resolve a problem in the field. @@ -2462,9 +2462,9 @@ SGI's lcrash tool which allows one to look at kernel structures in a running kernel. -It also complements a tool called dumptool which dumps all the kernels +It also complements a tool called dumptool which dumps all the kernel's memory pages & registers to either a tape or a disk. -This can be used by tech support or an ambitous end user do +This can be used by tech support or an ambitious end user do post mortem debugging of a machine like gdb core dumps. Going into how to use this tool in detail will be explained diff -Nru a/Documentation/s390/cds.txt b/Documentation/s390/cds.txt --- a/Documentation/s390/cds.txt Sat Mar 15 18:40:44 2003 +++ b/Documentation/s390/cds.txt Sat Mar 15 18:40:44 2003 @@ -214,7 +214,7 @@ cdev - the ccw_device the data is requested for. buffer - Pointer to a buffer pointer. The read_conf_data() routine will allocate a buffer and initialize the buffer pointer - accordingly. It's the device driver's responsability to + accordingly. It's the device driver's responsibility to release the kernel memory if no longer needed. length - Length of the buffer allocated and retrieved. lpm - Logical path mask to be used for retrieving the data. If @@ -224,7 +224,7 @@ 0 - Successful completion -ENODEV - cdev invalid. -EINVAL - An invalid parameter was detected, or the function was called early. --EIO - An irrecoverable I/O error occured or the device is +-EIO - An irrecoverable I/O error occurred or the device is not operational. -ENOMEM - The read_conf_data() routine couldn't obtain storage. -EOPNOTSUPP - The device doesn't support the read configuration @@ -428,7 +428,7 @@ can handle lost data on the network to allow for enhanced I/O processing. Unless the channel subsystem at any time presents a secondary status interrupt, -exploiting this feature will cause only primary status interrups to be +exploiting this feature will cause only primary status interrupts to be presented to the device driver while overlapping I/O is performed. When a secondary status without error (alert status) is presented, this indicates successful completion for all overlapping ccw_device_start() requests that have diff -Nru a/Documentation/s390/driver-model.txt b/Documentation/s390/driver-model.txt --- a/Documentation/s390/driver-model.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/s390/driver-model.txt Sat Mar 15 18:40:39 2003 @@ -53,7 +53,7 @@ a. Each driver can provide one or more parameter interfaces where parameters can be specified. These interfaces are also in the driver's responsibility. -b. After a. has been performed, if neccessary, the device is finally brought up +b. After a. has been performed, if necessary, the device is finally brought up via the 'online' interface. @@ -145,7 +145,7 @@ The handler field of the struct ccw_device is meant to be set to the interrupt -handler for the device. In order to accomodate drivers which use several +handler for the device. In order to accommodate drivers which use several distinct handlers (e.g. multi subchannel devices), this is a member of ccw_device instead of ccw_driver. The handler is registered with the common layer during set_online() processing diff -Nru a/Documentation/scsi/ChangeLog.ncr53c8xx b/Documentation/scsi/ChangeLog.ncr53c8xx --- a/Documentation/scsi/ChangeLog.ncr53c8xx Sat Mar 15 18:40:43 2003 +++ b/Documentation/scsi/ChangeLog.ncr53c8xx Sat Mar 15 18:40:43 2003 @@ -247,7 +247,7 @@ - Add the 53c876 description to the chip table. This is only useful for printing the right name of the controller. - DEL-441 Item 2 work-around for the 53c876 rev <= 5 (0x15). - - Add additionnal checking of INQUIRY data: + - Add additional checking of INQUIRY data: Check INQUIRY data received length is at least 7. Byte 7 of inquiry data contains device features bits and the driver might be confused by garbage. Also check peripheral qualifier. @@ -420,7 +420,7 @@ - Split DATA_IN and DATA_OUT scripts into 2 sub-scripts. 64 segments are moved from on-chip RAM scripts. If more segments, a script in main memory is used for the - additionnal segments. + additional segments. - Since the SCRIPTS processor continues SCRIPTS execution after having won arbitration, do some stuff prior to testing any SCSI phase on reselection. This should have the vertue to process @@ -475,7 +475,7 @@ ------------------------------ - Use FAST-5 instead of SLOW for slow scsi devices according to new SPI-2 draft. - - Make some changes in order to accomodate with 875 rev <= 3 + - Make some changes in order to accommodate with 875 rev <= 3 device errata listing 397. Minor consequences are: . Leave use of PCI Write and Invalidate under user control. Now, by default the driver does not enable PCI MWI and option diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx b/Documentation/scsi/ChangeLog.sym53c8xx --- a/Documentation/scsi/ChangeLog.sym53c8xx Sat Mar 15 18:40:43 2003 +++ b/Documentation/scsi/ChangeLog.sym53c8xx Sat Mar 15 18:40:43 2003 @@ -15,7 +15,7 @@ - In ncr_soft_reset(), only try to ABORT the current operation for chips that support SRUN bit in ISTAT1 and if SCRIPTS are currently running, as 896 and 1010 manuals suggest. - - In the CCB abort path, donnot assume that the CCB is currently + - In the CCB abort path, do not assume that the CCB is currently queued to SCRIPTS. This is not always true, notably after a QUEUE FULL status or when using untagged commands. @@ -562,7 +562,7 @@ * version pre-sym53c8xx-0.10 - Add the 53c876 description to the chip table. This is only useful for printing the right name of the controller. - - Add additionnal checking of INQUIRY data: + - Add additional checking of INQUIRY data: Check INQUIRY data received length is at least 7. Byte 7 of inquiry data contains device features bits and the driver might be confused by garbage. Also check peripheral qualifier. diff -Nru a/Documentation/scsi/ChangeLog.sym53c8xx_2 b/Documentation/scsi/ChangeLog.sym53c8xx_2 --- a/Documentation/scsi/ChangeLog.sym53c8xx_2 Sat Mar 15 18:40:41 2003 +++ b/Documentation/scsi/ChangeLog.sym53c8xx_2 Sat Mar 15 18:40:41 2003 @@ -32,7 +32,7 @@ missing free of this memory on instance detach. - Check against GPIO3 pulled low for HVD controllers (driver did just the opposite). - Misdetection of BUS mode was triggerred on module reload only, + Misdetection of BUS mode was triggered on module reload only, since BIOS settings were trusted instead on first load. Wed Feb 7 21:00 2001 Gerard Roudier @@ -71,7 +71,7 @@ #LUN <= 7. - Set busy_itl in LCB to 1 if the LCB is allocated and a SCSI command is active. This is a simplification. - - In sym_hcb_free(), donnot scan the free_ccbq if no CCBs + - In sym_hcb_free(), do not scan the free_ccbq if no CCBs has been allocated. This fixes a panic if attach failed. - Add DT/ST (double/simple transition) in the transfer negotiation announce. diff -Nru a/Documentation/scsi/dpti.txt b/Documentation/scsi/dpti.txt --- a/Documentation/scsi/dpti.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/scsi/dpti.txt Sat Mar 15 18:40:43 2003 @@ -75,7 +75,7 @@ * to the board. * * The files dpti_ioctl.h dptsig.h osd_defs.h osd_util.h sys_info.h are part of the - * interface files for Adaptecs managment routines. These define the structures used + * interface files for Adaptec's management routines. These define the structures used * in the ioctls. They are written to be portable. They are hard to read, but I need * to use them 'as is' or I can miss changes in the interface. * diff -Nru a/Documentation/scsi/ibmmca.txt b/Documentation/scsi/ibmmca.txt --- a/Documentation/scsi/ibmmca.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/scsi/ibmmca.txt Sat Mar 15 18:40:43 2003 @@ -810,9 +810,9 @@ commandline parameter is added, called 'activity'. 2) Added the READ_CONTROL bit for test_unit_ready SCSI-command. 3) Added some suppress_exception bits to read_device_capacity and - all device_inquiry occurences in the driver code. + all device_inquiry occurrences in the driver code. 4) Complaints about the various KERNEL_VERSION implementations are - taken into account. Every local_LinuxKernelVersion occurence is + taken into account. Every local_LinuxKernelVersion occurrence is now replaced by KERNEL_VERSION, defined in linux/version.h. Corresponding changes were applied to ibmmca.h, too. This was a contribution to all kernel-parts by Philipp Hahn. @@ -866,7 +866,7 @@ 2) Adapter-information and autoadaption to address-space is done. 3) Auto-probing for maximum synchronous SCSI transfer rate is working. 4) Optimization to some embedded function calls is applied. - 5) Added some comment for the user to wait for SCSI-devices beeing probed. + 5) Added some comment for the user to wait for SCSI-devices being probed. 6) Finished version 3.2 for Kernel 2.4.0. It least, I thought it is but... - Michael Lang @@ -966,7 +966,7 @@ ------DA where '-' stays dark, 'D' shows the SCSI-device id - and 'A' shows the SCSI hostindex, beeing currently + and 'A' shows the SCSI hostindex, being currently accessed. During boottime, this will give the message SCSIini* @@ -1091,7 +1091,7 @@ now. Normally you really won't need to activate this flag in the kernel configuration, as all post 1989 SCSI-devices should accept the reset-signal, when the computer is switched on. The SCSI- - subsystem generates this reset while beeing initialized. This flag + subsystem generates this reset while being initialized. This flag is really reserved for users with very old, very strange or self-made SCSI-devices. Q: Why is the SCSI-order of my drives mirrored to the device-order diff -Nru a/Documentation/scsi/ncr53c8xx.txt b/Documentation/scsi/ncr53c8xx.txt --- a/Documentation/scsi/ncr53c8xx.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/scsi/ncr53c8xx.txt Sat Mar 15 18:40:39 2003 @@ -238,7 +238,7 @@ optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. In order to really gain advantage of this feature, devices must have -a reasonnable cache size (No miracle is to be expected for a low-end +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some kown SCSI devices do not properly support tagged command queuing. Generally, firmware revisions that fix this kind of problems are available @@ -592,7 +592,7 @@ Some SCSI-2 devices do not report this feature in byte 7 of inquiry response but do support it properly (TAMARACK scanners for example). -CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonnable answer: n) +CONFIG_SCSI_NCR53C8XX_NO_DISCONNECT (default and only reasonable answer: n) If you suspect a device of yours does not properly support disconnections, you can answer "y". Then, all SCSI devices will never disconnect the bus even while performing long SCSI operations. @@ -827,7 +827,7 @@ Available option bits: 0x0: No check. - 0x1: Check and donnot attach the controller on error. + 0x1: Check and do not attach the controller on error. 0x2: Check and just warn on error. 0x4: Disable SCSI bus integrity checking. @@ -850,7 +850,7 @@ 10.2.22 Enable use of IMMEDIATE ARBITRATION (only supported by the sym53c8xx driver. See 10.7 for more details) - iarb:0 donnot use this feature. + iarb:0 do not use this feature. iarb:#x use this feature according to bit fields as follow: bit 0 (1) : enable IARB each time the initiator has been reselected @@ -880,7 +880,7 @@ settle time 10 seconds settle:10 differential support from BIOS settings diff:1 irq mode from BIOS settings irqm:1 - SCSI BUS check donnot attach on error buschk:1 + SCSI BUS check do not attach on error buschk:1 immediate arbitration disabled iarb:0 10.3 Advised boot setup commands @@ -1272,7 +1272,7 @@ - terminations at both end of the SCSI chain - linux syslog messages (some of them may help you) -If you donnot find the source of problems, you can configure the +If you do not find the source of problems, you can configure the driver with no features enabled. - only asynchronous data transfers @@ -1345,14 +1345,14 @@ Field C : SIST io register (SCSI Interrupt Status) Bit 0x08 : SGE SCSI GROSS ERROR Indicates that the chip detected a severe error condition - on the SCSI BUS that prevents the SCSI protocol from functionning + on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Undexpected Disconnection + Bit 0x04 : UDC Unexpected Disconnection Indicates that the device released the SCSI BUS when the chip was not expecting this to happen. A device may behave so to indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets donnot reset the SCSI BUS, although any + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. Bit 0x01 : PAR Parity SCSI parity error detected. diff -Nru a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt --- a/Documentation/scsi/sym53c8xx_2.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/scsi/sym53c8xx_2.txt Sat Mar 15 18:40:39 2003 @@ -205,7 +205,7 @@ optimizations based on actual head positions and its mechanical characteristics. This feature may also reduce average command latency. In order to really gain advantage of this feature, devices must have -a reasonnable cache size (No miracle is to be expected for a low-end +a reasonable cache size (No miracle is to be expected for a low-end hard disk with 128 KB or less). Some kown old SCSI devices do not properly support tagged command queuing. Generally, firmware revisions that fix this kind of problems are available @@ -579,7 +579,7 @@ Available option bits: 0x0: No check. - 0x1: Check and donnot attach the controller on error. + 0x1: Check and do not attach the controller on error. 0x2: Check and just warn on error. 10.2.16 Exclude a host from being attached @@ -698,7 +698,7 @@ - terminations at both end of the SCSI chain - linux syslog messages (some of them may help you) -If you donnot find the source of problems, you can configure the +If you do not find the source of problems, you can configure the driver or devices in the NVRAM with minimal features. - only asynchronous data transfers @@ -756,14 +756,14 @@ Field C : SIST io register (SCSI Interrupt Status) Bit 0x08 : SGE SCSI GROSS ERROR Indicates that the chip detected a severe error condition - on the SCSI BUS that prevents the SCSI protocol from functionning + on the SCSI BUS that prevents the SCSI protocol from functioning properly. - Bit 0x04 : UDC Undexpected Disconnection + Bit 0x04 : UDC Unexpected Disconnection Indicates that the device released the SCSI BUS when the chip was not expecting this to happen. A device may behave so to - indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occured. + indicate the SCSI initiator that an error condition not reportable using the SCSI protocol has occurred. Bit 0x02 : RST SCSI BUS Reset - Generally SCSI targets donnot reset the SCSI BUS, although any + Generally SCSI targets do not reset the SCSI BUS, although any device on the BUS can reset it at any time. Bit 0x01 : PAR Parity SCSI parity error detected. diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt --- a/Documentation/sonypi.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/sonypi.txt Sat Mar 15 18:40:39 2003 @@ -130,7 +130,7 @@ tested) when using the driver with the fnkeyinit parameter. I cannot reproduce it on my laptop and not all users have this problem. This happens because the fnkeyinit parameter enables the ACPI - mode (but without additionnal ACPI control, like processor + mode (but without additional ACPI control, like processor speed handling etc). Use ACPI instead of APM if it works on your laptop. diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt --- a/Documentation/sound/alsa/ALSA-Configuration.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/sound/alsa/ALSA-Configuration.txt Sat Mar 15 18:40:39 2003 @@ -659,7 +659,7 @@ Module supports autoprobe and multiple chips (max 8). Note: on some notebooks the buffer address cannot be detected automatically, or causes hang-up during initialization. - In such a case, specify the buffer top address explicity via + In such a case, specify the buffer top address explicitly via buffer_top option. For example, Sony F250: buffer_top=0x25a800 diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl Sat Mar 15 18:40:41 2003 +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl Sat Mar 15 18:40:41 2003 @@ -2807,7 +2807,7 @@ - If you aquire a spinlock in the interrupt handler, and the + If you acquire a spinlock in the interrupt handler, and the lock is used in other pcm callbacks, too, then you have to release the lock before calling snd_pcm_period_elapsed(), because diff -Nru a/Documentation/sound/oss/NEWS b/Documentation/sound/oss/NEWS --- a/Documentation/sound/oss/NEWS Sat Mar 15 18:40:44 2003 +++ b/Documentation/sound/oss/NEWS Sat Mar 15 18:40:44 2003 @@ -19,7 +19,7 @@ Before Linux 2.4 you had to specify the resources for sounddrivers statically linked into the kernel at compile time -(in make config/menuconfig/xconfig). In Linux 2.4 the ressources are +(in make config/menuconfig/xconfig). In Linux 2.4 the resources are now specified at the boot-time kernel commandline (e.g. the lilo 'append=' line or everything that's after the kernel name in grub). Read the Configure.help entry for your card for the parameters. diff -Nru a/Documentation/sound/oss/PSS-updates b/Documentation/sound/oss/PSS-updates --- a/Documentation/sound/oss/PSS-updates Sat Mar 15 18:40:45 2003 +++ b/Documentation/sound/oss/PSS-updates Sat Mar 15 18:40:45 2003 @@ -22,12 +22,12 @@ This parameter takes a port address as its parameter. Any available port address can be specified to enable the CDROM port, except for 0x0 and -1 as these values would leave the port disabled. Like the joystick port, the cdrom -port will require that an appropiate CDROM driver be loaded before you can make +port will require that an appropriate CDROM driver be loaded before you can make use of the newly enabled CDROM port. Like the joystick port option above, remember to load the CDROM driver AFTER the pss sound driver. While it may differ on some PSS sound cards, all the PSS sound cards that I have seen have a builtin Wearnes CDROM port. If this is the case with your PSS sound card you -should load aztcd with the appropiate port option that matches the port you +should load aztcd with the appropriate port option that matches the port you assigned to the CDROM port when you loaded your pss sound driver. (ex. modprobe pss pss_cdrom_port=0x340 && modprobe aztcd aztcd=0x340) The default setting of this parameter leaves the CDROM port disabled to maintain full @@ -44,7 +44,7 @@ value will only attept to configure the CDROM and joystick ports. This parameter can be used by a user who only wished to use the builtin joystick and/or CDROM port(s) of his PSS sound card. If this driver is loaded with this -parameter and with the paramter below set to true then a user can safely unload +parameter and with the parameter below set to true then a user can safely unload this driver with the following command "rmmod pss && rmmod ad1848 && rmmod mpu401 && rmmod sound && rmmod soundcore" and retain the full functionality of his CDROM and/or joystick port(s) while gaining back the memory previously used diff -Nru a/Documentation/sound/oss/cs46xx b/Documentation/sound/oss/cs46xx --- a/Documentation/sound/oss/cs46xx Sat Mar 15 18:40:40 2003 +++ b/Documentation/sound/oss/cs46xx Sat Mar 15 18:40:40 2003 @@ -78,7 +78,7 @@ driver to disable compilation of the CS_DBGOUT print statements: #define CSDEBUG 1 -Please see the defintions for cs_debuglevel and cs_debugmask for additional +Please see the definitions for cs_debuglevel and cs_debugmask for additional information on the debug levels and sections. There is also a csdbg executable to allow runtime manipulation of these diff -Nru a/Documentation/specialix.txt b/Documentation/specialix.txt --- a/Documentation/specialix.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/specialix.txt Sat Mar 15 18:40:40 2003 @@ -326,7 +326,7 @@ Fixed bugs and restrictions: - - During intialization, interrupts are blindly turned on. + - During initialization, interrupts are blindly turned on. Having a shadow variable would cause an extra memory access on every IO instruction. - The interrupt (on the card) should be disabled when we diff -Nru a/Documentation/swsusp.txt b/Documentation/swsusp.txt --- a/Documentation/swsusp.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/swsusp.txt Sat Mar 15 18:40:39 2003 @@ -90,7 +90,7 @@ function do_software_suspend, it is called. Here we shrink everything including dcache, inodes, buffers and memory (here mainly processes are swapped out). We count how many pages we need to duplicate (we have to be atomical!) then we -create an appropiate sized page directory. It will point to the original and +create an appropriate sized page directory. It will point to the original and the new (copied) address of the page. We get the free pages by __get_free_pages() but since it changes state we have to be able to track it later so it also flips in a bit in page's flags (a new Nosave flag). We diff -Nru a/Documentation/uml/UserModeLinux-HOWTO.txt b/Documentation/uml/UserModeLinux-HOWTO.txt --- a/Documentation/uml/UserModeLinux-HOWTO.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/uml/UserModeLinux-HOWTO.txt Sat Mar 15 18:40:40 2003 @@ -2509,7 +2509,7 @@ 1100..88.. ssttoopp This puts the UML in a loop reading mconsole requests until a 'go' - mconsole command is recieved. This is very useful for making backups + mconsole command is received. This is very useful for making backups of UML filesystems, as the UML can be stopped, then synced via 'sysrq s', so that everything is written to the filesystem. You can then copy the filesystem and then send the UML 'go' via mconsole. diff -Nru a/Documentation/usb/URB.txt b/Documentation/usb/URB.txt --- a/Documentation/usb/URB.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/usb/URB.txt Sat Mar 15 18:40:41 2003 @@ -86,7 +86,7 @@ Return value is a pointer to the allocated URB, 0 if allocation failed. The parameter isoframes specifies the number of isochronous transfer frames -you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags paramter +you want to schedule. For CTRL/BULK/INT, use 0. The mem_flags parameter holds standard memory allocation flags, letting you control (among other things) whether the underlying code may block or not. diff -Nru a/Documentation/usb/hiddev.txt b/Documentation/usb/hiddev.txt --- a/Documentation/usb/hiddev.txt Sat Mar 15 18:40:41 2003 +++ b/Documentation/usb/hiddev.txt Sat Mar 15 18:40:41 2003 @@ -173,7 +173,7 @@ usage to be retrieved can be specified as above, or the user can choose to fill in the report_type field and specify the report_id as HID_REPORT_ID_UNKNOWN. In this case, the hiddev_usage_ref will be -filled in with the report and field infomation associated with this +filled in with the report and field information associated with this usage if it is found. HIDIOCSUSAGE - struct hiddev_usage_ref (write) diff -Nru a/Documentation/usb/philips.txt b/Documentation/usb/philips.txt --- a/Documentation/usb/philips.txt Sat Mar 15 18:40:43 2003 +++ b/Documentation/usb/philips.txt Sat Mar 15 18:40:43 2003 @@ -27,9 +27,9 @@ Specifies the desired framerate. Is an integer in the range of 4-30. fbufs - This paramter specifies the number of internal buffers to use for storing + This parameter specifies the number of internal buffers to use for storing frames from the cam. This will help if the process that reads images from - the cam is a bit slow or momentarely busy. However, on slow machines it + the cam is a bit slow or momentarily busy. However, on slow machines it only introduces lag, so choose carefully. The default is 3, which is reasonable. You can set it between 2 and 5. diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt --- a/Documentation/usb/scanner.txt Sat Mar 15 18:40:45 2003 +++ b/Documentation/usb/scanner.txt Sat Mar 15 18:40:45 2003 @@ -282,7 +282,7 @@ } if((fpout=fopen("out.dat", "w+")) == NULL) { - perror("Unable to open ouput file"); + perror("Unable to open output file"); exit(1); } diff -Nru a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ --- a/Documentation/video4linux/bttv/Sound-FAQ Sat Mar 15 18:40:45 2003 +++ b/Documentation/video4linux/bttv/Sound-FAQ Sat Mar 15 18:40:45 2003 @@ -15,18 +15,18 @@ bttv0: model: BT848(Hauppauge old) [autodetected] -You should verify this is correct. If it is'nt, you have to pass the +You should verify this is correct. If it isn't, you have to pass the correct board type as insmod argument, "insmod bttv card=2" for example. The file CARDLIST has a list of valid arguments for card. -If your card is'nt listed there, you might check the source code for -new entries which are not listed yet. If there is'nt one for your +If your card isn't listed there, you might check the source code for +new entries which are not listed yet. If there isn't one for your card, you can check if one of the existing entries does work for you (just trial and error...). Some boards have an extra processor for sound to do stereo decoding and other nice features. The msp34xx chips are used by Hauppauge for example. If your board has one, you might have to load a helper -module like msp3400.o to make sound work. If there is'nt one for the +module like msp3400.o to make sound work. If there isn't one for the chip used on your board: Bad luck. Start writing a new one. Well, you might want to check the video4linux mailing list archive first... diff -Nru a/Documentation/video4linux/zr36120.txt b/Documentation/video4linux/zr36120.txt --- a/Documentation/video4linux/zr36120.txt Sat Mar 15 18:40:39 2003 +++ b/Documentation/video4linux/zr36120.txt Sat Mar 15 18:40:39 2003 @@ -146,10 +146,10 @@ The consequence is that, when loading the driver as a module, the module may tell you it's out of memory, but 'free' says otherwise. The reason is simple; the modules wants its memory -contingious, not fragmented, and after a long uptime there +contiguous, not fragmented, and after a long uptime there probably isn't a fragment of memory large enough... -The driver uses a double buffering scheme, which should realy +The driver uses a double buffering scheme, which should really be an n-way buffer, depending on the size of allocated framebuffer and the requested grab-size/format. This current version also fixes a dead-lock situation during irq diff -Nru a/Documentation/vm/hugetlbpage.txt b/Documentation/vm/hugetlbpage.txt --- a/Documentation/vm/hugetlbpage.txt Sat Mar 15 18:40:40 2003 +++ b/Documentation/vm/hugetlbpage.txt Sat Mar 15 18:40:40 2003 @@ -69,7 +69,7 @@ mount none /mnt/huge -t hugetlbfs -This commands mounts a (psuedo) filesystem of type hugetlbfs on the directory +This command mounts a (pseudo) filesystem of type hugetlbfs on the directory /mnt/huge. Any files created on /mnt/huge uses hugepages. An example is given at the end of this document. diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sat Mar 15 18:40:42 2003 +++ b/MAINTAINERS Sat Mar 15 18:40:42 2003 @@ -641,7 +641,7 @@ P: Rui Sousa M: rui.p.m.sousa@clix.pt L: emu10k1-devel@lists.sourceforge.net -W: http://opensource.creative.com/ +W: http://sourceforge.net/projects/emu10k1/ S: Maintained ETHEREXPRESS-16 NETWORK DRIVER diff -Nru a/Makefile b/Makefile --- a/Makefile Sat Mar 15 18:40:40 2003 +++ b/Makefile Sat Mar 15 18:40:40 2003 @@ -107,6 +107,11 @@ # For now, leave verbose as default +ifdef V + ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) + endif +endif ifndef KBUILD_VERBOSE KBUILD_VERBOSE = 1 endif @@ -193,7 +198,7 @@ comma := , depfile = $(subst $(comma),_,$(@D)/.$(@F).d) -noconfig_targets := xconfig menuconfig config oldconfig randconfig \ +noconfig_targets := xconfig gconfig menuconfig config oldconfig randconfig \ defconfig allyesconfig allnoconfig allmodconfig \ clean mrproper distclean rpm \ help tags TAGS cscope sgmldocs psdocs pdfdocs htmldocs \ @@ -322,13 +327,14 @@ # set -e makes the rule exit immediately on error define rule_vmlinux__ - set -e; \ + set -e \ $(if $(filter .tmp_kallsyms%,$^),, \ echo ' GEN .version'; \ . $(srctree)/scripts/mkversion > .tmp_version; \ mv -f .tmp_version .version; \ $(MAKE) $(build)=init; \ ) + set -e \ $(call cmd,vmlinux__); \ echo 'cmd_$@ := $(cmd_vmlinux__)' > $(@D)/.$(@F).cmd endef @@ -598,14 +604,17 @@ # Kernel configuration # --------------------------------------------------------------------------- -.PHONY: oldconfig xconfig menuconfig config \ +.PHONY: oldconfig xconfig gconfig menuconfig config \ make_with_config rpm -scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf: scripts/fixdep FORCE +scripts/kconfig/conf scripts/kconfig/mconf scripts/kconfig/qconf scripts/kconfig/gconf: scripts/fixdep FORCE $(Q)$(MAKE) $(build)=scripts/kconfig $@ xconfig: scripts/kconfig/qconf ./scripts/kconfig/qconf arch/$(ARCH)/Kconfig + +gconfig: scripts/kconfig/gconf + ./scripts/kconfig/gconf arch/$(ARCH)/Kconfig menuconfig: scripts/kconfig/mconf $(Q)$(MAKE) $(build)=scripts/lxdialog diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Sat Mar 15 18:40:43 2003 +++ b/arch/alpha/Kconfig Sat Mar 15 18:40:43 2003 @@ -15,10 +15,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool diff -Nru a/arch/alpha/kernel/core_marvel.c b/arch/alpha/kernel/core_marvel.c --- a/arch/alpha/kernel/core_marvel.c Sat Mar 15 18:40:39 2003 +++ b/arch/alpha/kernel/core_marvel.c Sat Mar 15 18:40:39 2003 @@ -1076,7 +1076,7 @@ /* * Fill it in. */ - agp->type = 0 /* FIXME: ALPHA_CORE_AGP */; + agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = NULL; agp->ops = &marvel_agp_ops; diff -Nru a/arch/alpha/kernel/core_titan.c b/arch/alpha/kernel/core_titan.c --- a/arch/alpha/kernel/core_titan.c Sat Mar 15 18:40:40 2003 +++ b/arch/alpha/kernel/core_titan.c Sat Mar 15 18:40:40 2003 @@ -764,7 +764,7 @@ /* * Fill it in. */ - agp->type = 0 /* FIXME: ALPHA_CORE_AGP */; + agp->type = ALPHA_CORE_AGP; agp->hose = hose; agp->private = port; agp->ops = &titan_agp_ops; diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Sat Mar 15 18:40:43 2003 +++ b/arch/alpha/kernel/irq.c Sat Mar 15 18:40:43 2003 @@ -515,6 +515,7 @@ #endif int i; struct irqaction * action; + unsigned long flags; #ifdef CONFIG_SMP seq_puts(p, " "); @@ -525,9 +526,10 @@ #endif for (i = 0; i < ACTUAL_NR_IRQS; i++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -538,15 +540,18 @@ #endif seq_printf(p, " %14s", irq_desc[i].handler->typename); seq_printf(p, " %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', - action->name); + (action->flags & SA_INTERRUPT)?'+':' ', + action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %c%s", - (action->flags & SA_INTERRUPT)?'+':' ', - action->name); + (action->flags & SA_INTERRUPT)?'+':' ', + action->name); } + seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } #if CONFIG_SMP seq_puts(p, "IPI: "); diff -Nru a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c --- a/arch/alpha/kernel/pci.c Sat Mar 15 18:40:39 2003 +++ b/arch/alpha/kernel/pci.c Sat Mar 15 18:40:39 2003 @@ -393,26 +393,36 @@ } static void __init +pcibios_claim_one_bus(struct pci_bus *b) +{ + struct list_head *ld; + struct pci_bus *child_bus; + + for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { + struct pci_dev *dev = pci_dev_b(ld); + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r = &dev->resource[i]; + + if (r->parent || !r->start || !r->flags) + continue; + pci_claim_resource(dev, i); + } + } + + list_for_each_entry(child_bus, &b->children, node) + pcibios_claim_one_bus(child_bus); +} + +static void __init pcibios_claim_console_setup(void) { struct list_head *lb; for(lb = pci_root_buses.next; lb != &pci_root_buses; lb = lb->next) { struct pci_bus *b = pci_bus_b(lb); - struct list_head *ld; - - for (ld = b->devices.next; ld != &b->devices; ld = ld->next) { - struct pci_dev *dev = pci_dev_b(ld); - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; - - if (r->parent || !r->start || !r->flags) - continue; - pci_claim_resource(dev, i); - } - } + pcibios_claim_one_bus(b); } } diff -Nru a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c --- a/arch/alpha/kernel/sys_nautilus.c Sat Mar 15 18:40:41 2003 +++ b/arch/alpha/kernel/sys_nautilus.c Sat Mar 15 18:40:41 2003 @@ -78,6 +78,8 @@ nautilus_kill_arch(int mode) { struct pci_bus *bus = pci_isa_hose->bus; + u32 pmuport; + int off; switch (mode) { case LINUX_REBOOT_CMD_RESTART: @@ -92,14 +94,18 @@ break; case LINUX_REBOOT_CMD_POWER_OFF: - { - u32 pmuport; - pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport); - pmuport &= 0xfffe; - outl(0xffff, pmuport); /* clear pending events */ - outw(0x2000, pmuport+4); /* power off */ - /* NOTREACHED */ + /* Assume M1543C */ + off = 0x2000; /* SLP_TYPE = 0, SLP_EN = 1 */ + pci_bus_read_config_dword(bus, 0x88, 0x10, &pmuport); + if (!pmuport) { + /* M1535D/D+ */ + off = 0x3400; /* SLP_TYPE = 5, SLP_EN = 1 */ + pci_bus_read_config_dword(bus, 0x88, 0xe0, &pmuport); } + pmuport &= 0xfffe; + outw(0xffff, pmuport); /* Clear pending events. */ + outw(off, pmuport + 4); + /* NOTREACHED */ break; } } diff -Nru a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c --- a/arch/alpha/mm/fault.c Sat Mar 15 18:40:41 2003 +++ b/arch/alpha/mm/fault.c Sat Mar 15 18:40:41 2003 @@ -232,11 +232,11 @@ else { /* Synchronize this task's top level page-table with the "reference" page table from init. */ - long offset = __pgd_offset(address); + long index = pgd_index(address); pgd_t *pgd, *pgd_k; - pgd = current->active_mm->pgd + offset; - pgd_k = swapper_pg_dir + offset; + pgd = current->active_mm->pgd + index; + pgd_k = swapper_pg_dir + index; if (!pgd_present(*pgd) && pgd_present(*pgd_k)) { pgd_val(*pgd) = pgd_val(*pgd_k); return; diff -Nru a/arch/alpha/oprofile/op_model_ev4.c b/arch/alpha/oprofile/op_model_ev4.c --- a/arch/alpha/oprofile/op_model_ev4.c Sat Mar 15 18:40:41 2003 +++ b/arch/alpha/oprofile/op_model_ev4.c Sat Mar 15 18:40:41 2003 @@ -34,7 +34,7 @@ for these "disabled" counter overflows are ignored by the interrupt handler. - This is most irritating, becuase the hardware *can* enable and + This is most irritating, because the hardware *can* enable and disable the interrupts for these counters independently, but the wrperfmon interface doesn't allow it. */ diff -Nru a/arch/alpha/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S --- a/arch/alpha/vmlinux.lds.S Sat Mar 15 18:40:42 2003 +++ b/arch/alpha/vmlinux.lds.S Sat Mar 15 18:40:42 2003 @@ -63,6 +63,13 @@ .init.ramfs : { *(.init.ramfs) } __initramfs_end = .; + . = ALIGN(8); + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + . = ALIGN(64); __per_cpu_start = .; .data.percpu : { *(.data.percpu) } diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/arm/Kconfig Sat Mar 15 18:40:42 2003 @@ -20,10 +20,6 @@ bool default y -config SWAP - bool - default y - config EISA bool ---help--- @@ -534,15 +530,63 @@ written) to implement the policy. If you don't understand what this is all about, it's safe to say 'N'. + +# CPUfreq on SA11x0 is special -- it _needs_ the userspace governor + +config CPU_FREQ_SA1100 + bool + depends on CPU_FREQ && SA1100_LART + default y + +config CPU_FREQ_SA1110 + bool + depends on CPU_FREQ && (SA1100_ASSABET || SA1100_CERF || SA1100_PT_SYSTEM3) + default y + +if (CPU_FREQ_SA1100 || CPU_FREQ_SA1110) + +config CPU_FREQ_GOV_USERSPACE + bool + depends on CPU_FREQ + default y + config CPU_FREQ_24_API bool - depends on CPU_FREQ + depends on CPU_FREQ_GOV_USERSPACE && SYSCTL default y config CPU_FREQ_PROC_INTF - tristate - depends on CPU_FREQ + tristate "/proc/cpufreq interface (deprecated)" + depends on CPU_FREQ && PROC_FS + help + This enables the /proc/cpufreq interface for controlling + CPUFreq. Please note that it is recommended to use the sysfs + interface instead (which is built automatically). + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say N. + +endif + +# CPUfreq on Integrator can use the generic cpufreq core + +config CPU_FREQ_INTEGRATOR + tristate "CPUfreq driver for ARM Integrator CPUs" + depends on ARCH_INTEGRATOR && CPU_FREQ default y + help + This enables the CPUfreq driver for ARM Integrator CPUs. + + For details, take a look at linux/Documentation/cpufreq. + + If in doubt, say Y. + +if (CPU_FREQ_INTEGRATOR) + +source "drivers/cpufreq/Kconfig" + +endif source "drivers/pci/Kconfig" diff -Nru a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c --- a/arch/arm/common/sa1111.c Sat Mar 15 18:40:44 2003 +++ b/arch/arm/common/sa1111.c Sat Mar 15 18:40:44 2003 @@ -743,25 +743,23 @@ static int sa1111_suspend(struct device *dev, u32 state, u32 level) { struct sa1111 *sachip = dev_get_drvdata(dev); + struct sa1111_save_data *save; unsigned long flags; char *base; + if (!dev->saved_state && level == SUSPEND_NOTIFY) + dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + save = (struct sa1111_save_data *)dev->saved_state; + + spin_lock_irqsave(&sachip->lock, flags); + /* * Save state. */ - if (level == SUSPEND_SAVE_STATE || - level == SUSPEND_DISABLE || - level == SUSPEND_POWER_DOWN) { - struct sa1111_save_data *save; - - if (!dev->saved_state) - dev->saved_state = kmalloc(sizeof(struct sa1111_save_data), GFP_KERNEL); - if (!dev->saved_state) - return -ENOMEM; - - save = (struct sa1111_save_data *)dev->saved_state; - - spin_lock_irqsave(&sachip->lock, flags); + if (level == SUSPEND_SAVE_STATE) { base = sachip->base; save->skcr = sa1111_readl(base + SA1111_SKCR); save->skpcr = sa1111_readl(base + SA1111_SKPCR); @@ -779,26 +777,21 @@ save->wakepol1 = sa1111_readl(base + SA1111_WAKEPOL1); save->wakeen0 = sa1111_readl(base + SA1111_WAKEEN0); save->wakeen1 = sa1111_readl(base + SA1111_WAKEEN1); - spin_unlock_irqrestore(&sachip->lock, flags); } /* * Disable. */ - if (level == SUSPEND_DISABLE && state == 4) { - unsigned int val; - - spin_lock_irqsave(&sachip->lock, flags); - base = sachip->base; - - sa1111_writel(0, base + SA1111_SKPWM0); - sa1111_writel(0, base + SA1111_SKPWM1); - val = sa1111_readl(base + SA1111_SKCR); - sa1111_writel(val | SKCR_SLEEP, base + SA1111_SKCR); + if (level == SUSPEND_POWER_DOWN && state == 4) { + unsigned int val = sa1111_readl(sachip->base + SA1111_SKCR); - spin_unlock_irqrestore(&sachip->lock, flags); + sa1111_writel(val | SKCR_SLEEP, sachip->base + SA1111_SKCR); + sa1111_writel(0, sachip->base + SA1111_SKPWM0); + sa1111_writel(0, sachip->base + SA1111_SKPWM1); } + spin_unlock_irqrestore(&sachip->lock, flags); + return 0; } @@ -819,17 +812,15 @@ unsigned long flags, id; char *base; - if (level != RESUME_RESTORE_STATE && level != RESUME_ENABLE) - return 0; - save = (struct sa1111_save_data *)dev->saved_state; if (!save) return 0; - dev->saved_state = NULL; + spin_lock_irqsave(&sachip->lock, flags); /* * Ensure that the SA1111 is still here. + * FIXME: shouldn't do this here. */ id = sa1111_readl(sachip->base + SA1111_SKID); if ((id & SKID_ID_MASK) != SKID_SA1111_ID) { @@ -839,29 +830,42 @@ return 0; } - spin_lock_irqsave(&sachip->lock, flags); - sa1111_wake(sachip); + /* + * First of all, wake up the chip. + */ + if (level == RESUME_POWER_ON) { + sa1111_wake(sachip); + + sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN0); + sa1111_writel(0, sachip->base + SA1111_INTC + SA1111_INTEN1); + } + + if (level == RESUME_RESTORE_STATE) { + base = sachip->base; + sa1111_writel(save->skcr, base + SA1111_SKCR); + sa1111_writel(save->skpcr, base + SA1111_SKPCR); + sa1111_writel(save->skcdr, base + SA1111_SKCDR); + sa1111_writel(save->skaud, base + SA1111_SKAUD); + sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); + sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); + + base = sachip->base + SA1111_INTC; + sa1111_writel(save->intpol0, base + SA1111_INTPOL0); + sa1111_writel(save->intpol1, base + SA1111_INTPOL1); + sa1111_writel(save->inten0, base + SA1111_INTEN0); + sa1111_writel(save->inten1, base + SA1111_INTEN1); + sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); + sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); + sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); + sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); + } - base = sachip->base; - sa1111_writel(save->skcr, base + SA1111_SKCR); - sa1111_writel(save->skpcr, base + SA1111_SKPCR); - sa1111_writel(save->skcdr, base + SA1111_SKCDR); - sa1111_writel(save->skaud, base + SA1111_SKAUD); - sa1111_writel(save->skpwm0, base + SA1111_SKPWM0); - sa1111_writel(save->skpwm1, base + SA1111_SKPWM1); - - base = sachip->base + SA1111_INTC; - sa1111_writel(save->intpol0, base + SA1111_INTPOL0); - sa1111_writel(save->intpol1, base + SA1111_INTPOL1); - sa1111_writel(save->inten0, base + SA1111_INTEN0); - sa1111_writel(save->inten1, base + SA1111_INTEN1); - sa1111_writel(save->wakepol0, base + SA1111_WAKEPOL0); - sa1111_writel(save->wakepol1, base + SA1111_WAKEPOL1); - sa1111_writel(save->wakeen0, base + SA1111_WAKEEN0); - sa1111_writel(save->wakeen1, base + SA1111_WAKEEN1); spin_unlock_irqrestore(&sachip->lock, flags); - kfree(save); + if (level == RESUME_ENABLE) { + dev->saved_state = NULL; + kfree(save); + } return 0; } diff -Nru a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile --- a/arch/arm/kernel/Makefile Sat Mar 15 18:40:44 2003 +++ b/arch/arm/kernel/Makefile Sat Mar 15 18:40:44 2003 @@ -16,6 +16,7 @@ obj- := obj-$(CONFIG_APM) += apm.o +obj-$(CONFIG_PM) += pm.o obj-$(CONFIG_ARCH_ACORN) += ecard.o time-acorn.o obj-$(CONFIG_ARCH_CLPS7500) += time-acorn.o obj-$(CONFIG_FOOTBRIDGE) += isa.o diff -Nru a/arch/arm/kernel/apm.c b/arch/arm/kernel/apm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/apm.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,573 @@ +/* + * bios-less APM driver for ARM Linux + * Jamey Hicks + * adapted from the APM BIOS driver for Linux by Stephen Rothwell (sfr@linuxcare.com) + * + * APM 1.2 Reference: + * Intel Corporation, Microsoft Corporation. Advanced Power Management + * (APM) BIOS Interface Specification, Revision 1.2, February 1996. + * + * [This document is available from Microsoft at: + * http://www.microsoft.com/hwdev/busbios/amp_12.htm] + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The apm_bios device is one of the misc char devices. + * This is its minor number. + */ +#define APM_MINOR_DEV 134 + +/* + * See Documentation/Config.help for the configuration options. + * + * Various options can be changed at boot time as follows: + * (We allow underscores for compatibility with the modules code) + * apm=on/off enable/disable APM + */ + +/* + * Maximum number of events stored + */ +#define APM_MAX_EVENTS 20 + +/* + * The per-file APM data + */ +struct apm_user { + struct list_head list; + + int suser: 1; + int writer: 1; + int reader: 1; + int suspend_wait: 1; + int suspend_result; + + int suspends_pending; + int standbys_pending; + unsigned int suspends_read; + unsigned int standbys_read; + + int event_head; + int event_tail; + apm_event_t events[APM_MAX_EVENTS]; +}; + +/* + * Local variables + */ +static int suspends_pending; +static int standbys_pending; +static int apm_disabled; + +static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); +static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); + +/* + * This is a list of everyone who has opened /dev/apm_bios + */ +static spinlock_t user_list_lock = SPIN_LOCK_UNLOCKED; +static LIST_HEAD(apm_user_list); + +/* + * The kapmd info. + */ +static struct task_struct *kapmd; +static DECLARE_COMPLETION(kapmd_exit); + +static const char driver_version[] = "1.13"; /* no spaces */ + +/* + * This structure gets filled in by the machine specific 'get_power_status' + * implementation. Any fields which are not set default to a safe value. + */ +struct apm_power_info { + unsigned char ac_line_status; + unsigned char battery_status; + unsigned char battery_flag; + unsigned char battery_life; + int time; + int units; +}; + +/* + * Compatibility cruft until the IPAQ people move over to the new + * interface. + */ +static void __apm_get_power_status(struct apm_power_info *info) +{ +#if 0 && defined(CONFIG_SA1100_H3600) && defined(CONFIG_TOUCHSCREEN_H3600) + extern int h3600_apm_get_power_status(u_char *, u_char *, u_char *, + u_char *, u_short *); + + if (machine_is_h3600()) { + int dx; + h3600_apm_get_power_status(&info->ac_line_status, + &info->battery_status, &info->battery_flag, + &info->battery_life, &dx); + info->time = dx & 0x7fff; + info->units = dx & 0x8000 ? 0 : 1; + } +#endif +} + +/* + * This allows machines to provide their own "apm get power status" function. + */ +void (*apm_get_power_status)(struct apm_power_info *) = __apm_get_power_status; +EXPORT_SYMBOL(apm_get_power_status); + +static int queue_empty(struct apm_user *as) +{ + return as->event_head == as->event_tail; +} + +static apm_event_t get_queued_event(struct apm_user *as) +{ + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + return as->events[as->event_tail]; +} + +static void queue_event_one_user(struct apm_user *as, apm_event_t event) +{ + as->event_head = (as->event_head + 1) % APM_MAX_EVENTS; + if (as->event_head == as->event_tail) { + static int notified; + + if (notified++ == 0) + printk(KERN_ERR "apm: an event queue overflowed\n"); + as->event_tail = (as->event_tail + 1) % APM_MAX_EVENTS; + } + as->events[as->event_head] = event; + + if (!as->suser || !as->writer) + return; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + as->suspends_pending++; + suspends_pending++; + break; + + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + as->standbys_pending++; + standbys_pending++; + break; + } +} + +static void queue_event(apm_event_t event, struct apm_user *sender) +{ + struct list_head *l; + + spin_lock(&user_list_lock); + list_for_each(l, &apm_user_list) { + struct apm_user *as = list_entry(l, struct apm_user, list); + + if (as != sender && as->reader) + queue_event_one_user(as, event); + } + spin_unlock(&user_list_lock); + wake_up_interruptible(&apm_waitqueue); +} + +/* defined in pm.c */ +extern int suspend(void); + +static int apm_suspend(void) +{ + struct list_head *l; + int err = suspend(); + + /* + * Anyone on the APM queues will think we're still suspended. + * Send a message so everyone knows we're now awake again. + */ + queue_event(APM_NORMAL_RESUME, NULL); + + /* + * Finally, wake up anyone who is sleeping on the suspend. + */ + spin_lock(&user_list_lock); + list_for_each(l, &apm_user_list) { + struct apm_user *as = list_entry(l, struct apm_user, list); + + as->suspend_result = err; + as->suspend_wait = 0; + } + spin_unlock(&user_list_lock); + + wake_up_interruptible(&apm_suspend_waitqueue); + return err; +} + +static ssize_t apm_read(struct file *fp, char *buf, size_t count, loff_t *ppos) +{ + struct apm_user *as = fp->private_data; + apm_event_t event; + int i = count, ret = 0, nonblock = fp->f_flags & O_NONBLOCK; + + if (count < sizeof(apm_event_t)) + return -EINVAL; + + if (queue_empty(as) && nonblock) + return -EAGAIN; + + wait_event_interruptible(apm_waitqueue, !queue_empty(as)); + + while ((i >= sizeof(event)) && !queue_empty(as)) { + event = get_queued_event(as); + printk(" apm_read: event=%d\n", event); + + ret = -EFAULT; + if (copy_to_user(buf, &event, sizeof(event))) + break; + + switch (event) { + case APM_SYS_SUSPEND: + case APM_USER_SUSPEND: + as->suspends_read++; + break; + + case APM_SYS_STANDBY: + case APM_USER_STANDBY: + as->standbys_read++; + break; + } + + buf += sizeof(event); + i -= sizeof(event); + } + + if (i < count) + ret = count - i; + + return ret; +} + +static unsigned int apm_poll(struct file *fp, poll_table * wait) +{ + struct apm_user * as = fp->private_data; + + poll_wait(fp, &apm_waitqueue, wait); + return queue_empty(as) ? 0 : POLLIN | POLLRDNORM; +} + +/* + * apm_ioctl - handle APM ioctl + * + * APM_IOC_SUSPEND + * This IOCTL is overloaded, and performs two functions. It is used to: + * - initiate a suspend + * - acknowledge a suspend read from /dev/apm_bios. + * Only when everyone who has opened /dev/apm_bios with write permission + * has acknowledge does the actual suspend happen. + */ +static int +apm_ioctl(struct inode * inode, struct file *filp, u_int cmd, u_long arg) +{ + struct apm_user *as = filp->private_data; + int err = -EINVAL; + + if (!as->suser || !as->writer) + return -EPERM; + + switch (cmd) { + case APM_IOC_STANDBY: + break; + + case APM_IOC_SUSPEND: + /* + * If we read a suspend command from /dev/apm_bios, + * then the corresponding APM_IOC_SUSPEND ioctl is + * interpreted as an acknowledge. + */ + if (as->suspends_read > 0) { + as->suspends_read--; + as->suspends_pending--; + suspends_pending--; + } else { + queue_event(APM_USER_SUSPEND, as); + } + + /* + * If there are outstanding suspend requests for other + * people on /dev/apm_bios, we must sleep for them. + * Last one to bed turns the lights out. + */ + if (suspends_pending > 0) { + as->suspend_wait = 1; + err = wait_event_interruptible(apm_suspend_waitqueue, + as->suspend_wait == 0); + if (err == 0) + err = as->suspend_result; + } else { + err = apm_suspend(); + } + break; + } + + return err; +} + +static int apm_release(struct inode * inode, struct file * filp) +{ + struct apm_user *as = filp->private_data; + filp->private_data = NULL; + + spin_lock(&user_list_lock); + list_del(&as->list); + spin_unlock(&user_list_lock); + + /* + * We are now unhooked from the chain. As far as new + * events are concerned, we no longer exist. However, we + * need to balance standbys_pending and suspends_pending, + * which means the possibility of sleeping. + */ + if (as->standbys_pending > 0) { + standbys_pending -= as->standbys_pending; +// if (standbys_pending <= 0) +// standby(); + } + if (as->suspends_pending > 0) { + suspends_pending -= as->suspends_pending; + if (suspends_pending <= 0) + apm_suspend(); + } + + kfree(as); + return 0; +} + +static int apm_open(struct inode * inode, struct file * filp) +{ + struct apm_user *as; + + as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); + if (as) { + memset(as, 0, sizeof(*as)); + + /* + * XXX - this is a tiny bit broken, when we consider BSD + * process accounting. If the device is opened by root, we + * instantly flag that we used superuser privs. Who knows, + * we might close the device immediately without doing a + * privileged operation -- cevans + */ + as->suser = capable(CAP_SYS_ADMIN); + as->writer = (filp->f_mode & FMODE_WRITE) == FMODE_WRITE; + as->reader = (filp->f_mode & FMODE_READ) == FMODE_READ; + + spin_lock(&user_list_lock); + list_add(&as->list, &apm_user_list); + spin_unlock(&user_list_lock); + + filp->private_data = as; + } + + return as ? 0 : -ENOMEM; +} + +static struct file_operations apm_bios_fops = { + owner: THIS_MODULE, + read: apm_read, + poll: apm_poll, + ioctl: apm_ioctl, + open: apm_open, + release: apm_release, +}; + +static struct miscdevice apm_device = { + minor: APM_MINOR_DEV, + name: "apm_bios", + fops: &apm_bios_fops +}; + + +#ifdef CONFIG_PROC_FS +/* + * Arguments, with symbols from linux/apm_bios.h. + * + * 0) Linux driver version (this will change if format changes) + * 1) APM BIOS Version. Usually 1.0, 1.1 or 1.2. + * 2) APM flags from APM Installation Check (0x00): + * bit 0: APM_16_BIT_SUPPORT + * bit 1: APM_32_BIT_SUPPORT + * bit 2: APM_IDLE_SLOWS_CLOCK + * bit 3: APM_BIOS_DISABLED + * bit 4: APM_BIOS_DISENGAGED + * 3) AC line status + * 0x00: Off-line + * 0x01: On-line + * 0x02: On backup power (BIOS >= 1.1 only) + * 0xff: Unknown + * 4) Battery status + * 0x00: High + * 0x01: Low + * 0x02: Critical + * 0x03: Charging + * 0x04: Selected battery not present (BIOS >= 1.2 only) + * 0xff: Unknown + * 5) Battery flag + * bit 0: High + * bit 1: Low + * bit 2: Critical + * bit 3: Charging + * bit 7: No system battery + * 0xff: Unknown + * 6) Remaining battery life (percentage of charge): + * 0-100: valid + * -1: Unknown + * 7) Remaining battery life (time units): + * Number of remaining minutes or seconds + * -1: Unknown + * 8) min = minutes; sec = seconds + */ +static int apm_get_info(char *buf, char **start, off_t fpos, int length) +{ + struct apm_power_info info; + char *units; + int ret; + + info.ac_line_status = 0xff; + info.battery_status = 0xff; + info.battery_flag = 0xff; + info.battery_life = 255; + info.time = -1; + info.units = -1; + + if (apm_get_power_status) + apm_get_power_status(&info); + + switch (info.units) { + default: units = "?"; break; + case 0: units = "min"; break; + case 1: units = "sec"; break; + } + + ret = sprintf(buf, "%s 1.2 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", + driver_version, APM_32_BIT_SUPPORT, + info.ac_line_status, info.battery_status, + info.battery_flag, info.battery_life, + info.time, units); + + return ret; +} +#endif + +#if 0 +static int kapmd(void *startup) +{ + struct task_struct *tsk = current; + + daemonize(); + strcpy(tsk->comm, "kapmd"); + kapmd = tsk; + + spin_lock_irq(&tsk->sigmask_lock); + siginitsetinv(&tsk->blocked, sigmask(SIGQUIT)); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + + complete((struct completion *)startup); + + do { + set_task_state(tsk, TASK_INTERRUPTIBLE); + schedule(); + } while (!signal_pending(tsk)); + + complete_and_exit(&kapmd_exit, 0); +} +#endif + +static int __init apm_init(void) +{ +// struct completion startup = COMPLETION_INITIALIZER(startup); + int ret; + + if (apm_disabled) { + printk(KERN_NOTICE "apm: disabled on user request.\n"); + return -ENODEV; + } + + if (PM_IS_ACTIVE()) { + printk(KERN_NOTICE "apm: overridden by ACPI.\n"); + return -EINVAL; + } + +// ret = kernel_thread(kapmd, &startup, CLONE_FS | CLONE_FILES); +// if (ret) +// return ret; +// wait_for_completion(&startup); + + pm_active = 1; + +#ifdef CONFIG_PROC_FS + create_proc_info_entry("apm", 0, NULL, apm_get_info); +#endif + + ret = misc_register(&apm_device); + if (ret != 0) { + pm_active = 0; + remove_proc_entry("apm", NULL); + send_sig(SIGQUIT, kapmd, 1); + wait_for_completion(&kapmd_exit); + } + + return ret; +} + +static void __exit apm_exit(void) +{ + misc_deregister(&apm_device); + remove_proc_entry("apm", NULL); + pm_active = 0; +// send_sig(SIGQUIT, kapmd, 1); +// wait_for_completion(&kapmd_exit); +} + +module_init(apm_init); +module_exit(apm_exit); + +MODULE_AUTHOR("Stephen Rothwell"); +MODULE_DESCRIPTION("Advanced Power Management"); +MODULE_LICENSE("GPL"); + +EXPORT_NO_SYMBOLS; + +#ifndef MODULE +static int __init apm_setup(char *str) +{ + while ((str != NULL) && (*str != '\0')) { + if (strncmp(str, "off", 3) == 0) + apm_disabled = 1; + if (strncmp(str, "on", 2) == 0) + apm_disabled = 0; + str = strchr(str, ','); + if (str != NULL) + str += strspn(str, ", \t"); + } + return 1; +} + +__setup("apm=", apm_setup); +#endif diff -Nru a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c --- a/arch/arm/kernel/bios32.c Sat Mar 15 18:40:41 2003 +++ b/arch/arm/kernel/bios32.c Sat Mar 15 18:40:41 2003 @@ -18,7 +18,6 @@ #include static int debug_pci; -int have_isa_bridge; void pcibios_report_status(u_int status_mask, int warn) { @@ -363,9 +362,8 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) { struct pci_sys_data *root = bus->sysdata; - struct list_head *walk; - u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - u16 all_status = -1; + struct pci_dev *dev; + u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK; pbus_assign_bus_resources(bus, root); @@ -373,42 +371,43 @@ * Walk the devices on this bus, working out what we can * and can't support. */ - for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { - struct pci_dev *dev = pci_dev_b(walk); + list_for_each_entry(dev, &bus->devices, bus_list) { u16 status; pdev_fixup_device_resources(root, dev); pci_read_config_word(dev, PCI_STATUS, &status); - all_status &= status; + + /* + * If any device on this bus does not support fast back + * to back transfers, then the bus as a whole is not able + * to support them. Having fast back to back transfers + * on saves us one PCI cycle per transaction. + */ + if (!(status & PCI_STATUS_FAST_BACK)) + features &= ~PCI_COMMAND_FAST_BACK; if (pdev_bad_for_parity(dev)) features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - /* - * If this device is an ISA bridge, set the have_isa_bridge - * flag. We will then go looking for things like keyboard, - * etc - */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_ISA || - dev->class >> 8 == PCI_CLASS_BRIDGE_EISA) - have_isa_bridge = !0; + switch (dev->class >> 8) { +#if defined(CONFIG_ISA) || defined(CONFIG_EISA) + case PCI_CLASS_BRIDGE_ISA: + case PCI_CLASS_BRIDGE_EISA: + /* + * If this device is an ISA bridge, set isa_bridge + * to point at this device. We will then go looking + * for things like keyboard, etc. + */ + isa_bridge = dev; + break; +#endif } /* - * If any device on this bus does not support fast back to back - * transfers, then the bus as a whole is not able to support them. - * Having fast back to back transfers on saves us one PCI cycle - * per transaction. - */ - if (all_status & PCI_STATUS_FAST_BACK) - features |= PCI_COMMAND_FAST_BACK; - - /* * Now walk the devices again, this time setting them up. */ - for (walk = bus->devices.next; walk != &bus->devices; walk = walk->next) { - struct pci_dev *dev = pci_dev_b(walk); + list_for_each_entry(dev, &bus->devices, bus_list) { u16 cmd; pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -416,7 +415,17 @@ pci_write_config_word(dev, PCI_COMMAND, cmd); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - SMP_CACHE_BYTES >> 2); + L1_CACHE_BYTES >> 2); + } + + /* + * Propagate the flags to the PCI bridge. + */ + if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + if (features & PCI_COMMAND_FAST_BACK) + bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK; + if (features & PCI_COMMAND_PARITY) + bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY; } /* @@ -454,20 +463,17 @@ */ u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 *pinp) { - int pin = *pinp; + int pin = *pinp - 1; - if (pin != 0) { - pin -= 1; - while (dev->bus->self) { - pin = (pin + PCI_SLOT(dev->devfn)) & 3; - /* - * move up the chain of bridges, - * swizzling as we go. - */ - dev = dev->bus->self; - } - *pinp = pin + 1; + while (dev->bus->self) { + pin = (pin + PCI_SLOT(dev->devfn)) & 3; + /* + * move up the chain of bridges, + * swizzling as we go. + */ + dev = dev->bus->self; } + *pinp = pin + 1; return PCI_SLOT(dev->devfn); } diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c --- a/arch/arm/kernel/ecard.c Sat Mar 15 18:40:43 2003 +++ b/arch/arm/kernel/ecard.c Sat Mar 15 18:40:43 2003 @@ -37,7 +37,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,7 @@ enum req { req_readbytes, - req_reset_all + req_reset }; struct ecard_request { @@ -131,14 +130,11 @@ #define POD_INT_ADDR(x) ((volatile unsigned char *)\ ((BUS_ADDR((x)) - IO_BASE) + IO_START)) -static inline void ecard_task_reset(void) +static inline void ecard_task_reset(struct ecard_request *req) { - ecard_t *ec; - - for (ec = cards; ec; ec = ec->next) - if (ec->loader) - ecard_loader_reset(POD_INT_ADDR(ec->podaddr), - ec->loader); + struct expansion_card *ec = req->ec; + if (ec->loader) + ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader); } static void @@ -218,8 +214,8 @@ ecard_task_readbytes(req); break; - case req_reset_all: - ecard_task_reset(); + case req_reset: + ecard_task_reset(req); break; } } @@ -355,60 +351,6 @@ /* ======================= Mid-level card control ===================== */ -/* - * This function is responsible for resetting the expansion cards to a - * sensible state immediately prior to rebooting the system. This function - * has process state (keventd), so we can sleep. - * - * Possible "val" values here: - * SYS_RESTART - restarting system - * SYS_HALT - halting system - * SYS_POWER_OFF - powering down system - * - * We ignore all calls, unless it is a SYS_RESTART call - power down/halts - * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again. - */ -static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v) -{ - struct ecard_request req; - - if (val != SYS_RESTART) - return 0; - - /* - * Disable the expansion card interrupt - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * If we have any expansion card loader code which will handle - * the reset for us, call it now. - */ - req.req = req_reset_all; - ecard_call(&req); - - /* - * Disable the expansion card interrupt again, just to be sure. - */ - disable_irq(IRQ_EXPANSIONCARD); - - /* - * Finally, reset the expansion card interrupt mask to - * all enable (RISC OS doesn't set this) - */ -#ifdef HAS_EXPMASK - have_expmask = ~0; - __raw_writeb(have_expmask, EXPMASK_ENABLE); -#endif - return 0; -} - -static struct notifier_block ecard_reboot_notifier = { - .notifier_call = ecard_reboot, -}; - - - static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld) { @@ -1083,11 +1025,6 @@ { int slot, irqhw; - /* - * Register our reboot notifier - */ - register_reboot_notifier(&ecard_reboot_notifier); - #ifdef CONFIG_CPU_32 init_waitqueue_head(&ecard_wait); #endif @@ -1158,11 +1095,32 @@ return 0; } +/* + * Before rebooting, we must make sure that the expansion card is in a + * sensible state, so it can be re-detected. This means that the first + * page of the ROM must be visible. We call the expansion cards reset + * handler, if any. + */ +static void ecard_drv_shutdown(struct device *dev) +{ + struct expansion_card *ec = ECARD_DEV(dev); + struct ecard_driver *drv = ECARD_DRV(dev->driver); + struct ecard_request req; + + if (drv->shutdown) + drv->shutdown(ec); + ecard_release(ec); + req.req = req_reset; + req.ec = ec; + ecard_call(&req); +} + int ecard_register_driver(struct ecard_driver *drv) { drv->drv.bus = &ecard_bus_type; drv->drv.probe = ecard_drv_probe; drv->drv.remove = ecard_drv_remove; + drv->drv.shutdown = ecard_drv_shutdown; return driver_register(&drv->drv); } diff -Nru a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S --- a/arch/arm/kernel/entry-armv.S Sat Mar 15 18:40:41 2003 +++ b/arch/arm/kernel/entry-armv.S Sat Mar 15 18:40:41 2003 @@ -1028,8 +1028,10 @@ @ @ now branch to the relevant MODE handling routine @ - mov r13, #PSR_I_BIT | MODE_SVC - msr spsr_c, r13 @ switch to SVC_32 mode + mrs r13, cpsr + bic r13, r13, #MODE_MASK + orr r13, r13, #MODE_SVC + msr spsr, r13 @ switch to SVC_32 mode and lr, lr, #15 ldr lr, [pc, lr, lsl #2] diff -Nru a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S --- a/arch/arm/kernel/entry-common.S Sat Mar 15 18:40:39 2003 +++ b/arch/arm/kernel/entry-common.S Sat Mar 15 18:40:39 2003 @@ -75,9 +75,8 @@ * This is how we return from a fork. */ ENTRY(ret_from_fork) -#ifdef CONFIG_PREEMPT + ldr r0, [r0, #TI_TASK] bl schedule_tail -#endif get_thread_info tsk ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing mov why, #1 diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c --- a/arch/arm/kernel/irq.c Sat Mar 15 18:40:39 2003 +++ b/arch/arm/kernel/irq.c Sat Mar 15 18:40:39 2003 @@ -165,17 +165,22 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < NR_IRQS ; i++) { + spin_lock_irqsave(&irq_controller_lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; + seq_printf(p, "%3d: %10u ", i, kstat_irqs(i)); seq_printf(p, " %s", action->name); - for (action = action->next; action; action = action->next) { + for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); - } + seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_controller_lock, flags); } #ifdef CONFIG_ARCH_ACORN diff -Nru a/arch/arm/kernel/pm.c b/arch/arm/kernel/pm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/kernel/pm.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,126 @@ +/* + * linux/arch/arm/kernel/suspend.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License. + * + * This is the common support code for suspending an ARM machine. + * pm_do_suspend() is responsible for actually putting the CPU to + * sleep. + */ +#include +#include +#include +#include + +#include +#include + +int suspend(void) +{ + int ret; + + /* + * Suspend "legacy" devices. + */ + ret = pm_send_all(PM_SUSPEND, (void *)3); + if (ret != 0) + goto out; + + /* + * Tell LDM devices we're going to suspend. + */ + ret = device_suspend(4, SUSPEND_NOTIFY); + if (ret != 0) + goto resume_legacy; + + /* + * Disable, devices, and save state. + */ + device_suspend(4, SUSPEND_DISABLE); + device_suspend(4, SUSPEND_SAVE_STATE); + + /* + * Tell devices that they're going to be powered off. + */ + device_suspend(4, SUSPEND_POWER_DOWN); + + local_irq_disable(); + leds_event(led_stop); + + ret = pm_do_suspend(); + + leds_event(led_start); + local_irq_enable(); + + /* + * Tell devices that they now have power. + */ + device_resume(RESUME_POWER_ON); + + /* + * Restore the CPU frequency settings. + */ +#ifdef CONFIG_CPU_FREQ + cpufreq_restore(); +#endif + + /* + * Resume LDM devices. + */ + device_resume(RESUME_RESTORE_STATE); + device_resume(RESUME_ENABLE); + + resume_legacy: + /* + * Resume "legacy" devices. + */ + pm_send_all(PM_RESUME, (void *)0); + + out: + return ret; +} + +#ifdef CONFIG_SYSCTL +#include +#include + +/* + * This came from arch/arm/mach-sa1100/pm.c: + * Copyright (c) 2001 Cliff Brake + * with modifications by Nicolas Pitre and Russell King. + * + * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than + * linux/sysctl.h. + * + * This means our interface here won't survive long - it needs a new + * interface. Quick hack to get this working - use sysctl id 9999. + */ +#warning ACPI broke the kernel, this interface needs to be fixed up. +#define CTL_ACPI 9999 +#define ACPI_S1_SLP_TYP 19 + +static struct ctl_table pm_table[] = +{ + {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&suspend}, + {0} +}; + +static struct ctl_table pm_dir_table[] = +{ + {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, + {0} +}; + +/* + * Initialize power interface + */ +static int __init pm_init(void) +{ + register_sysctl_table(pm_dir_table, 1); + return 0; +} + +fs_initcall(pm_init); + +#endif diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c --- a/arch/arm/kernel/time.c Sat Mar 15 18:40:43 2003 +++ b/arch/arm/kernel/time.c Sat Mar 15 18:40:43 2003 @@ -200,6 +200,7 @@ static struct irqaction timer_irq = { .name = "timer", + .flags = SA_INTERRUPT, }; /* diff -Nru a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile --- a/arch/arm/mach-integrator/Makefile Sat Mar 15 18:40:44 2003 +++ b/arch/arm/mach-integrator/Makefile Sat Mar 15 18:40:44 2003 @@ -4,10 +4,11 @@ # Object file lists. -obj-y := arch.o cpu.o irq.o mm.o time.o +obj-y := arch.o irq.o mm.o time.o obj-m := obj-n := obj- := obj-$(CONFIG_LEDS) += leds.o obj-$(CONFIG_PCI) += pci_v3.o pci.o +obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o diff -Nru a/arch/arm/mach-integrator/cpu.c b/arch/arm/mach-integrator/cpu.c --- a/arch/arm/mach-integrator/cpu.c Sat Mar 15 18:40:42 2003 +++ b/arch/arm/mach-integrator/cpu.c Sat Mar 15 18:40:42 2003 @@ -23,6 +23,8 @@ #include #include +static struct cpufreq_driver integrator_driver; + #define CM_ID (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_ID_OFFSET) #define CM_OSC (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_OSC_OFFSET) #define CM_STAT (IO_ADDRESS(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_STAT_OFFSET) @@ -43,7 +45,6 @@ return 2000 * (vco.vdw + 8) / cc_divisor[vco.od] / factor; } -#ifdef CONFIG_CPU_FREQ /* * Divisor indexes in ascending divisor order */ @@ -69,21 +70,17 @@ return vco; } + /* - * Validate the speed in khz. If it is outside our - * range, then return the lowest. + * Validate the speed policy. */ -static int integrator_verify_speed(struct cpufreq_policy *policy) +static int integrator_verify_policy(struct cpufreq_policy *policy) { struct vco vco; - if (policy->max > policy->cpuinfo.max_freq) - policy->max = policy->cpuinfo.max_freq; - - if (policy->max < 12000) - policy->max = 12000; - if (policy->max > 160000) - policy->max = 160000; + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); vco = freq_to_vco(policy->max, 1); @@ -92,12 +89,28 @@ if (vco.vdw > 152) vco.vdw = 152; - policy->min = policy->max = vco_to_freq(vco, 1); + policy->max = vco_to_freq(vco, 1); + + vco = freq_to_vco(policy->min, 1); + + if (vco.vdw < 4) + vco.vdw = 4; + if (vco.vdw > 152) + vco.vdw = 152; + + policy->min = vco_to_freq(vco, 1); + + cpufreq_verify_within_limits(policy, + policy->cpuinfo.min_freq, + policy->cpuinfo.max_freq); return 0; } -static int integrator_set_policy(struct cpufreq_policy *policy) + +static int integrator_set_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { unsigned long cpus_allowed; int cpu = policy->cpu; @@ -121,9 +134,18 @@ cm_osc = __raw_readl(CM_OSC); vco.od = (cm_osc >> 8) & 7; vco.vdw = cm_osc & 255; - freqs.old = vco_to_freq(vco, 1); - freqs.new = target_freq; + + /* freq_to_vco rounds down -- so we need the next larger freq in + * case of CPUFREQ_RELATION_L. + */ + if (relation == CPUFREQ_RELATION_L) + target_freq += 1999; + if (target_freq > policy->max) + target_freq = policy->max; + vco = freq_to_vco(target_freq, 1); + freqs.new = vco_to_freq(vco, 1); + freqs.cpu = policy->cpu; if (freqs.old == freqs.new) { @@ -132,7 +154,6 @@ } cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - vco = freq_to_vco(policy->max, 1); cm_osc = __raw_readl(CM_OSC); cm_osc &= 0xfffff800; @@ -152,80 +173,64 @@ return 0; } -static struct cpufreq_policy integrator_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 160000, - .min_freq = 12000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int integrator_cpufreq_init(struct cpufreq *policy) +{ + unsigned long cus_allowed; + unsigned int cpu = policy->cpu; + u_int cm_osc, cm_stat, mem_freq_khz; + struct vco vco; -static struct cpufreq_driver integrator_driver = { - .verify = integrator_verify_speed, - .setpolicy = integrator_set_policy, - .policy = &integrator_policy, - .name = "integrator", -}; -#endif + cpus_allowed = current->cpus_allowed; -static int __init integrator_cpu_init(void) -{ - struct cpufreq_policy *policies; - unsigned long cpus_allowed; - int cpu; + set_cpus_allowed(current, 1 << cpu); + BUG_ON(cpu != smp_processor_id()); - policies = kmalloc(sizeof(struct cpufreq_policy) * NR_CPUS, - GFP_KERNEL); - if (!policies) { - printk(KERN_ERR "CPU: unable to allocate policies structure\n"); - return -ENOMEM; - } + /* detect memory etc. */ + cm_stat = __raw_readl(CM_STAT); + cm_osc = __raw_readl(CM_OSC); + vco.od = (cm_osc >> 20) & 7; + vco.vdw = (cm_osc >> 12) & 255; + mem_freq_khz = vco_to_freq(vco, 2); + + printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255); + printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n", + cpu, mem_freq_khz / 1000, mem_freq_khz % 1000); - cpus_allowed = current->cpus_allowed; - for (cpu = 0; cpu < NR_CPUS; cpu++) { - u_int cm_osc, cm_stat, mem_freq_khz; - struct vco vco; - - if (!cpu_online(cpu)) - continue; - - set_cpus_allowed(current, 1 << cpu); - BUG_ON(cpu != smp_processor_id()); - - cm_stat = __raw_readl(CM_STAT); - cm_osc = __raw_readl(CM_OSC); - vco.od = (cm_osc >> 20) & 7; - vco.vdw = (cm_osc >> 12) & 255; - mem_freq_khz = vco_to_freq(vco, 2); - - printk(KERN_INFO "CPU%d: Module id: %d\n", cpu, cm_stat & 255); - printk(KERN_INFO "CPU%d: Memory clock = %d.%03d MHz\n", - cpu, mem_freq_khz / 1000, mem_freq_khz % 1000); - - vco.od = (cm_osc >> 8) & 7; - vco.vdw = cm_osc & 255; - - policies[cpu].cpu = cpu; - policies[cpu].policy = CPUFREQ_POLICY_POWERSAVE, - policies[cpu].cpuinfo.max_freq = 160000; - policies[cpu].cpuinfo.min_freq = 12000; - policies[cpu].cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policies[cpu].min = - policies[cpu].max = vco_to_freq(vco, 1); - } + vco.od = (cm_osc >> 8) & 7; + vco.vdw = cm_osc & 255; - set_cpus_allowed(current, cpus_allowed); + /* set default policy and cpuinfo */ + policy->policy = CPUFREQ_POLICY_PERFORMANCE; + policy->cpuinfo.max_freq = 160000; + policy->cpuinfo.min_freq = 12000; + policy->cpuinfo.transition_latency = 1000; /* 1 ms, assumed */ + policy->cur = policy->min = policy->max = vco_to_freq(vco, 1); /* current freq */ -#ifdef CONFIG_CPU_FREQ - integrator_driver.policy = policies; - cpufreq_register(&integrator_driver); -#else - kfree(policies); -#endif + set_cpus_allowed(current, cpus_allowed); return 0; } -arch_initcall(integrator_cpu_init); +static struct cpufreq_driver integrator_driver = { + .verify = integrator_verify_policy, + .target = integrator_set_target, + .init = integrator_cpufreq_init, + .name = "integrator", +}; + +static int __init integrator_cpu_init(void) +{ + return cpufreq_register_driver(&integrator_driver); +} + +static void __exit integrator_cpu_exit(void) +{ + cpufreq_unregister_driver(&integrator_driver); +} + +MODULE_AUTHOR ("Russell M. King"); +MODULE_DESCRIPTION ("cpufreq driver for ARM Integrator CPUs"); +MODULE_LICENSE ("GPL"); + +module_init(integrator_cpu_init); +module_exit(integrator_cpu_exit); diff -Nru a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig --- a/arch/arm/mach-sa1100/Kconfig Sat Mar 15 18:40:45 2003 +++ b/arch/arm/mach-sa1100/Kconfig Sat Mar 15 18:40:45 2003 @@ -326,6 +326,15 @@ # help # :: write me :: +config SA1100_SSP + tristate "Generic PIO SSP" + depends on ARCH_SA1100 + help + Say Y here to enable support for the generic PIO SSP driver. + This isn't for audio support, but for attached sensors and + other devices, eg for BadgePAD 4 sensor support, or Jornada + 720 touchscreen support. + config SA1100_USB tristate "SA1100 USB function support" depends on ARCH_SA1100 diff -Nru a/arch/arm/mach-sa1100/Makefile b/arch/arm/mach-sa1100/Makefile --- a/arch/arm/mach-sa1100/Makefile Sat Mar 15 18:40:45 2003 +++ b/arch/arm/mach-sa1100/Makefile Sat Mar 15 18:40:45 2003 @@ -9,15 +9,8 @@ obj- := led-y := leds.o -# This needs to be cleaned up. We probably need to have SA1100 -# and SA1110 config symbols. -ifeq ($(CONFIG_CPU_FREQ),y) -obj-$(CONFIG_SA1100_ASSABET) += cpu-sa1110.o -obj-$(CONFIG_SA1100_CERF) += cpu-sa1110.o -obj-$(CONFIG_SA1100_HACKKIT) += cpu-sa1110.o -obj-$(CONFIG_SA1100_LART) += cpu-sa1100.o -obj-$(CONFIG_SA1100_PT_SYSTEM3) += cpu-sa1110.o -endif +obj-$(CONFIG_CPU_FREQ_SA1100) += cpu-sa1100.o +obj-$(CONFIG_CPU_FREQ_SA1110) += cpu-sa1110.o # Specific board support obj-$(CONFIG_SA1100_ADSBITSY) += adsbitsy.o @@ -99,3 +92,4 @@ # Miscelaneous functions obj-$(CONFIG_PM) += pm.o sleep.o +obj-$(CONFIG_SA1100_SSP) += ssp.o diff -Nru a/arch/arm/mach-sa1100/cpu-sa1100.c b/arch/arm/mach-sa1100/cpu-sa1100.c --- a/arch/arm/mach-sa1100/cpu-sa1100.c Sat Mar 15 18:40:39 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Sat Mar 15 18:40:39 2003 @@ -101,7 +101,7 @@ } sa1100_dram_regs_t; - +static struct cpufreq_driver sa1100_driver; static sa1100_dram_regs_t sa1100_dram_settings[] = { @@ -176,60 +176,73 @@ } } -static int sa1100_setspeed(struct cpufreq_policy *policy) +static int sa1100_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { unsigned int cur = sa11x0_getspeed(); + unsigned int new_ppcr; + struct cpufreq_freqs freqs; + switch(relation){ + case CPUFREQ_RELATION_L: + new_ppcr = sa11x0_freq_to_ppcr(target_freq); + if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max) + new_ppcr--; + break; + case CPUFREQ_RELATION_H: + new_ppcr = sa11x0_freq_to_ppcr(target_freq); + if ((sa11x0_ppcr_to_freq(new_ppcr) > target_freq) && + (sa11x0_ppcr_to_freq(new_ppcr - 1) >= policy->min)) + mew_ppcr--; + break; + } freqs.old = cur; - freqs.new = policy->max; + freqs.new = sa11x0_ppcr_to_freq(new_ppcr); freqs.cpu = 0; cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - if (policy->max > cur) - sa1100_update_dram_timings(cur, policy->max); + if (freqs.new > cur) + sa1100_update_dram_timings(cur, freqs.new); - PPCR = sa11x0_freq_to_ppcr(policy->max); + PPCR = new_ppcr; - if (policy->max < cur) - sa1100_update_dram_timings(cur, policy->max); + if (freqs.new < cur) + sa1100_update_dram_timings(cur, freqs.new); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } -static struct cpufreq_policy sa1100_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 287000, - .min_freq = 59000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int __init sa1100_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.min_freq = 59000; + policy->cpuinfo.max_freq = 287000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + return 0; +} static struct cpufreq_driver sa1100_driver = { .verify = sa11x0_verify_speed, - .setpolicy = sa1100_setspeed, - .policy = &sa1100_policy, + .target = sa1100_target, + .init = sa1100_cpu_init, .name = "sa1100", }; static int __init sa1100_dram_init(void) { - int ret = -ENODEV; - - if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) { - sa1100_driver.cpu_cur_freq[0] = - sa1100_policy.min = - sa1100_policy.max = sa11x0_getspeed(); - - ret = cpufreq_register(&sa1100_driver); - } - - return ret; + cpufreq_gov_userspace_init(); + if ((processor_id & CPU_SA1100_MASK) == CPU_SA1100_ID) + return cpufreq_register_driver(&sa1100_driver); + else + return -ENODEV; } arch_initcall(sa1100_dram_init); diff -Nru a/arch/arm/mach-sa1100/cpu-sa1110.c b/arch/arm/mach-sa1100/cpu-sa1110.c --- a/arch/arm/mach-sa1100/cpu-sa1110.c Sat Mar 15 18:40:39 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Sat Mar 15 18:40:39 2003 @@ -32,6 +32,8 @@ #undef DEBUG +static struct cpufreq_driver sa1110_driver; + struct sdram_params { u_char rows; /* bits */ u_char cas_latency; /* cycles */ @@ -208,11 +210,11 @@ } /* - * Ok, set the CPU frequency. Since we've done the validation - * above, we can match for an exact frequency. If we don't find - * an exact match, we will to set the lowest frequency to be safe. + * Ok, set the CPU frequency. */ -static int sa1110_setspeed(struct cpufreq_policy *policy) +static int sa1110_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) { struct sdram_params *sdram = &sdram_params; struct cpufreq_freqs freqs; @@ -220,8 +222,25 @@ unsigned long flags; unsigned int ppcr, unused; - ppcr = sa11x0_freq_to_ppcr(policy->max); - sdram_calculate_timing(&sd, policy->max, sdram); + switch(relation){ + case CPUFREQ_RELATION_L: + ppcr = sa11x0_freq_to_ppcr(target_freq); + if (sa11x0_ppcr_to_freq(ppcr) > policy->max) + ppcr--; + break; + case CPUFREQ_RELATION_H: + ppcr = sa11x0_freq_to_ppcr(target_freq); + if (ppcr && (sa11x0_ppcr_to_freq(ppcr) > target_freq) && + (sa11x0_ppcr_to_freq(ppcr-1) >= policy->min)) + ppcr--; + break; + } + + freqs.old = sa11x0_getspeed(); + freqs.new = sa11x0_ppcr_to_freq(ppcr); + freqs.cpu = 0; + + sdram_calculate_timing(&sd, freqs.new, sdram); #if 0 /* @@ -240,10 +259,6 @@ sd.mdcas[2] = 0xaaaaaaaa; #endif - freqs.old = sa11x0_getspeed(); - freqs.new = policy->max; - freqs.cpu = 0; - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); /* @@ -288,27 +303,29 @@ /* * Now, return the SDRAM refresh back to normal. */ - sdram_update_refresh(policy->max, sdram); + sdram_update_refresh(freqs.new, sdram); cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); return 0; } -static struct cpufreq_policy sa1110_policy = { - .cpu = 0, - .policy = CPUFREQ_POLICY_POWERSAVE, - .cpuinfo = { - .max_freq = 287000, - .min_freq = 59000, - .transition_latency = CPUFREQ_ETERNAL, - }, -}; +static int __init sa1110_cpu_init(struct cpufreq_policy *policy) +{ + if (policy->cpu != 0) + return -EINVAL; + policy->cur = policy->min = policy->max = sa11x0_getspeed(); + policy->policy = CPUFREQ_POLICY_POWERSAVE; + policy->cpuinfo.min_freq = 59000; + policy->cpuinfo.max_freq = 287000; + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; + return 0; +} static struct cpufreq_driver sa1110_driver = { - .verify = sa11x0_verify_speed, - .setpolicy = sa1110_setspeed, - .policy = &sa1110_policy, + .verify = sa11x0_verify_speed, + .target = sa1110_target, + .init = sa1110_cpu_init, .name = "sa1110", }; @@ -331,15 +348,11 @@ sdram->tck, sdram->trcd, sdram->trp, sdram->twr, sdram->refresh, sdram->cas_latency); + cpufreq_gov_userspace_init(); + memcpy(&sdram_params, sdram, sizeof(sdram_params)); - sa1110_driver.cpu_cur_freq[0] = - sa1110_policy.min = - sa1110_policy.max = sa11x0_getspeed(); - - sa1110_setspeed(&sa1110_policy); - - return cpufreq_register(&sa1110_driver); + return cpufreq_register_driver(&sa1110_driver); } return 0; diff -Nru a/arch/arm/mach-sa1100/generic.c b/arch/arm/mach-sa1100/generic.c --- a/arch/arm/mach-sa1100/generic.c Sat Mar 15 18:40:40 2003 +++ b/arch/arm/mach-sa1100/generic.c Sat Mar 15 18:40:40 2003 @@ -48,33 +48,48 @@ 2802 /* 280.2 MHz */ }; -#ifdef CONFIG_CPU_FREQ +#if defined(CONFIG_CPU_FREQ_SA1100) || defined(CONFIG_CPU_FREQ_SA1110) +/* rounds up(!) */ unsigned int sa11x0_freq_to_ppcr(unsigned int khz) { int i; khz /= 100; - for (i = NR_FREQS - 1; i > 0; i--) - if (cclk_frequency_100khz[i] <= khz) + for (i = 0; i < NR_FREQS; i++) + if (cclk_frequency_100khz[i] >= khz) break; return i; } -/* - * Validate the policy. We aren't able to do any fancy in-kernel - * scaling, so we force min=max, and set the policy to "performance". - * If we can't generate the precise frequency requested, round it up. +unsigned int sa11x0_ppcr_to_freq(unsigned int idx) +{ + unsigned int freq = 0; + if (idx < NR_FREQS) + freq = cclk_frequency_100khz[idx] * 100; + return freq; +} + + +/* make sure that only the "userspace" governor is run -- anything else wouldn't make sense on + * this platform, anyway. */ int sa11x0_verify_speed(struct cpufreq_policy *policy) { - if (policy->max > policy->cpuinfo.max_freq) - policy->max = policy->cpuinfo.max_freq; + unsigned int tmp; + if (policy->cpu) + return -EINVAL; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); + + /* make sure that at least one frequency is within the policy */ + tmp = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->min)] * 100; + if (tmp > policy->max) + policy->max = tmp; + + cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - policy->max = cclk_frequency_100khz[sa11x0_freq_to_ppcr(policy->max)] * 100; - policy->min = policy->max; - policy->policy = CPUFREQ_POLICY_POWERSAVE; return 0; } diff -Nru a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h --- a/arch/arm/mach-sa1100/generic.h Sat Mar 15 18:40:43 2003 +++ b/arch/arm/mach-sa1100/generic.h Sat Mar 15 18:40:43 2003 @@ -23,3 +23,4 @@ extern unsigned int sa11x0_freq_to_ppcr(unsigned int khz); extern int sa11x0_verify_speed(struct cpufreq_policy *policy); extern unsigned int sa11x0_getspeed(void); +extern unsigned int sa11x0_ppcr_to_freq(unsigned int idx); diff -Nru a/arch/arm/mach-sa1100/irq.c b/arch/arm/mach-sa1100/irq.c --- a/arch/arm/mach-sa1100/irq.c Sat Mar 15 18:40:44 2003 +++ b/arch/arm/mach-sa1100/irq.c Sat Mar 15 18:40:44 2003 @@ -211,6 +211,99 @@ .end = 0x9005ffff, }; +struct sa1100irq_state { + unsigned int saved; + unsigned int icmr; + unsigned int iclr; + unsigned int iccr; +}; + +static int sa1100irq_suspend(struct device *dev, u32 state, u32 level) +{ + struct sa1100irq_state *st; + + if (!dev->saved_state && level == SUSPEND_NOTIFY) + dev->saved_state = kmalloc(sizeof(struct sa1100irq_state), + GFP_KERNEL); + if (!dev->saved_state) + return -ENOMEM; + + if (level == SUSPEND_POWER_DOWN) { + st = (struct sa1100irq_state *)dev->saved_state; + + st->saved = 1; + st->icmr = ICMR; + st->iclr = ICLR; + st->iccr = ICCR; + + /* + * Disable all GPIO-based interrupts. + */ + ICMR &= ~(IC_GPIO11_27|IC_GPIO10|IC_GPIO9|IC_GPIO8|IC_GPIO7| + IC_GPIO6|IC_GPIO5|IC_GPIO4|IC_GPIO3|IC_GPIO2| + IC_GPIO1|IC_GPIO0); + + /* + * Set the appropriate edges for wakeup. + */ + GRER = PWER & GPIO_IRQ_rising_edge; + GFER = PWER & GPIO_IRQ_falling_edge; + + /* + * Clear any pending GPIO interrupts. + */ + GEDR = GEDR; + } + return 0; +} + +static int sa1100irq_resume(struct device *dev, u32 level) +{ + struct sa1100irq_state *st; + + if (level == RESUME_POWER_ON) { + st = (struct sa1100irq_state *)dev->saved_state; + dev->saved_state = NULL; + + if (st->saved) { + ICCR = st->iccr; + ICLR = st->iclr; + + GRER = GPIO_IRQ_rising_edge & GPIO_IRQ_mask; + GFER = GPIO_IRQ_falling_edge & GPIO_IRQ_mask; + + ICMR = st->icmr; + } + + kfree(st); + } + return 0; +} + +static struct device_driver sa1100irq_driver = { + .name = "sa11x0-irq", + .bus = &system_bus_type, + .suspend = sa1100irq_suspend, + .resume = sa1100irq_resume, +}; + +static struct sys_device sa1100irq_device = { + .name = "irq", + .id = 0, + .dev = { + .name = "Intel SA11x0 [Interrupt Controller]", + .driver = &sa1100irq_driver, + }, +}; + +static int __init sa1100irq_init_devicefs(void) +{ + driver_register(&sa1100irq_driver); + return sys_device_register(&sa1100irq_device); +} + +device_initcall(sa1100irq_init_devicefs); + void __init sa1100_init_irq(void) { unsigned int irq; diff -Nru a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c --- a/arch/arm/mach-sa1100/pm.c Sat Mar 15 18:40:40 2003 +++ b/arch/arm/mach-sa1100/pm.c Sat Mar 15 18:40:40 2003 @@ -22,25 +22,12 @@ * 2002-05-27: Nicolas Pitre Killed sleep.h and the kmalloced save array. * Storage is local on the stack now. */ -#include -#include -#include -#include -#include #include -#include -#include +#include #include #include #include -#include - - -/* - * Debug macros - */ -#undef DEBUG extern void sa1100_cpu_suspend(void); extern void sa1100_cpu_resume(void); @@ -58,10 +45,9 @@ SLEEP_SAVE_OSCR, SLEEP_SAVE_OIER, SLEEP_SAVE_OSMR0, SLEEP_SAVE_OSMR1, SLEEP_SAVE_OSMR2, SLEEP_SAVE_OSMR3, - SLEEP_SAVE_GPDR, SLEEP_SAVE_GRER, SLEEP_SAVE_GFER, SLEEP_SAVE_GAFR, + SLEEP_SAVE_GPDR, SLEEP_SAVE_GAFR, SLEEP_SAVE_PPDR, SLEEP_SAVE_PPSR, SLEEP_SAVE_PPAR, SLEEP_SAVE_PSDR, - SLEEP_SAVE_ICMR, SLEEP_SAVE_Ser1SDCR0, SLEEP_SAVE_SIZE @@ -72,10 +58,6 @@ { unsigned long sleep_save[SLEEP_SAVE_SIZE]; - local_irq_disable(); - - leds_event(led_stop); - /* preserve current time */ RCNR = xtime.tv_sec; @@ -88,8 +70,6 @@ SAVE(OIER); SAVE(GPDR); - SAVE(GRER); - SAVE(GFER); SAVE(GAFR); SAVE(PPDR); @@ -99,13 +79,6 @@ SAVE(Ser1SDCR0); - SAVE(ICMR); - - /* ... maybe a global variable initialized by arch code to set this? */ - GRER = PWER; - GFER = 0; - GEDR = GEDR; - /* Clear previous reset status */ RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR; @@ -115,22 +88,23 @@ /* go zzz */ sa1100_cpu_suspend(); - /* ensure not to come back here if it wasn't intended */ + /* + * Ensure not to come back here if it wasn't intended + */ PSPR = 0; -#ifdef DEBUG - printk(KERN_DEBUG "*** made it back from resume\n"); -#endif + /* + * Ensure interrupt sources are disabled; we will re-init + * the interrupt subsystem via the device manager. + */ + ICLR = 0; + ICCR = 1; + ICMR = 0; /* restore registers */ RESTORE(GPDR); - RESTORE(GRER); - RESTORE(GFER); RESTORE(GAFR); - /* clear any edge detect bit */ - GEDR = GEDR; - RESTORE(PPDR); RESTORE(PPSR); RESTORE(PPAR); @@ -138,6 +112,9 @@ RESTORE(Ser1SDCR0); + /* + * Clear the peripheral sleep-hold bit. + */ PSSR = PSSR_PH; RESTORE(OSMR0); @@ -147,24 +124,9 @@ RESTORE(OSCR); RESTORE(OIER); - ICLR = 0; - ICCR = 1; - RESTORE(ICMR); - /* restore current time */ xtime.tv_sec = RCNR; - leds_event(led_start); - - local_irq_enable(); - - /* - * Restore the CPU frequency settings. - */ -#ifdef CONFIG_CPU_FREQ - cpufreq_restore(); -#endif - return 0; } @@ -172,78 +134,3 @@ { return virt_to_phys(sp); } - -#ifdef CONFIG_SYSCTL -/* - * ARGH! ACPI people defined CTL_ACPI in linux/acpi.h rather than - * linux/sysctl.h. - * - * This means our interface here won't survive long - it needs a new - * interface. Quick hack to get this working - use sysctl id 9999. - */ -#warning ACPI broke the kernel, this interface needs to be fixed up. -#define CTL_ACPI 9999 -#define ACPI_S1_SLP_TYP 19 - -/* - * Send us to sleep. - */ -static int sysctl_pm_do_suspend(void) -{ - int retval; - - /* - * Suspend "legacy" devices. - */ - retval = pm_send_all(PM_SUSPEND, (void *)3); - if (retval == 0) { - /* - * Suspend LDM devices. - */ - device_suspend(4, SUSPEND_NOTIFY); - device_suspend(4, SUSPEND_SAVE_STATE); - device_suspend(4, SUSPEND_DISABLE); - - retval = pm_do_suspend(); - - /* - * Resume LDM devices. - */ - device_resume(RESUME_RESTORE_STATE); - device_resume(RESUME_ENABLE); - - /* - * Resume "legacy" devices. - */ - pm_send_all(PM_RESUME, (void *)0); - } - - return retval; -} - -static struct ctl_table pm_table[] = -{ - {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, (proc_handler *)&sysctl_pm_do_suspend}, - {0} -}; - -static struct ctl_table pm_dir_table[] = -{ - {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, - {0} -}; - -/* - * Initialize power interface - */ -static int __init pm_init(void) -{ - register_sysctl_table(pm_dir_table, 1); - return 0; -} - -fs_initcall(pm_init); - -#endif - -EXPORT_SYMBOL(pm_do_suspend); diff -Nru a/arch/arm/mach-sa1100/ssp.c b/arch/arm/mach-sa1100/ssp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/mach-sa1100/ssp.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,208 @@ +/* + * linux/arch/arm/mach-sa1100/ssp.c + * + * Copyright (C) 2003 Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Generic SSP driver. This provides the generic core for simple + * IO-based SSP applications. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static void ssp_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int status = Ser4SSSR; + + if (status & SSSR_ROR) { + printk(KERN_WARNING "SSP: receiver overrun\n"); + } + + Ser4SSSR = SSSR_ROR; +} + +/** + * ssp_write_word - write a word to the SSP port + * @data: 16-bit, MSB justified data to write. + * + * Wait for a free entry in the SSP transmit FIFO, and write a data + * word to the SSP port. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 0 success + */ +int ssp_write_word(u16 data) +{ + while (!(Ser4SSSR & SSSR_TNF)) + cpu_relax(); + + Ser4SSDR = data; + + return 0; +} + +/** + * ssp_read_word - read a word from the SSP port + * + * Wait for a data word in the SSP receive FIFO, and return the + * received data. Data is LSB justified. + * + * Note: Currently, if data is not expected to be received, this + * function will wait for ever. + * + * The caller is expected to perform the necessary locking. + * + * Returns: + * %-ETIMEDOUT timeout occurred (for future) + * 16-bit data success + */ +int ssp_read_word(void) +{ + while (!(Ser4SSSR & SSSR_RNE)) + cpu_relax(); + + return Ser4SSDR; +} + +/** + * ssp_flush - flush the transmit and receive FIFOs + * + * Wait for the SSP to idle, and ensure that the receive FIFO + * is empty. + * + * The caller is expected to perform the necessary locking. + */ +void ssp_flush(void) +{ + do { + while (Ser4SSSR & SSSR_RNE) { + (void) Ser4SSDR; + } + } while (Ser4SSSR & SSSR_BSY); +} + +/** + * ssp_enable - enable the SSP port + * + * Turn on the SSP port. + */ +void ssp_enable(void) +{ + Ser4SSCR0 |= SSCR0_SSE; +} + +/** + * ssp_disable - shut down the SSP port + * + * Turn off the SSP port, optionally powering it down. + */ +void ssp_disable(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_save_state - save the SSP configuration + * @ssp: pointer to structure to save SSP configuration + * + * Save the configured SSP state for suspend. + */ +void ssp_save_state(struct ssp_state *ssp) +{ + ssp->cr0 = Ser4SSCR0; + ssp->cr1 = Ser4SSCR1; + + Ser4SSCR0 &= ~SSCR0_SSE; +} + +/** + * ssp_restore_state - restore a previously saved SSP configuration + * @ssp: pointer to configuration saved by ssp_save_state + * + * Restore the SSP configuration saved previously by ssp_save_state. + */ +void ssp_restore_state(struct ssp_state *ssp) +{ + Ser4SSSR = SSSR_ROR; + + Ser4SSCR0 = ssp->cr0 & ~SSCR0_SSE; + Ser4SSCR1 = ssp->cr1; + Ser4SSCR0 = ssp->cr0; +} + +/** + * ssp_init - setup the SSP port + * + * initialise and claim resources for the SSP port. + * + * Returns: + * %-ENODEV if the SSP port is unavailable + * %-EBUSY if the resources are already in use + * %0 on success + */ +int ssp_init(void) +{ + int ret; + + if (!(PPAR & PPAR_SPR) && (Ser4MCCR0 & MCCR0_MCE)) + return -ENODEV; + + if (!request_mem_region(__PREG(Ser4SSCR0), 0x18, "SSP")) { + return -EBUSY; + } + + Ser4SSSR = SSSR_ROR; + + ret = request_irq(IRQ_Ser4SSP, ssp_interrupt, 0, "SSP", NULL); + if (ret) + goto out_region; + + return 0; + + out_region: + release_mem_region(__PREG(Ser4SSCR0), 0x18); + return ret; +} + +/** + * ssp_exit - undo the effects of ssp_init + * + * release and free resources for the SSP port. + */ +void ssp_exit(void) +{ + Ser4SSCR0 &= ~SSCR0_SSE; + + free_irq(IRQ_Ser4SSP, NULL); + release_mem_region(__PREG(Ser4SSCR0), 0x18); +} + +MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("SA11x0 SSP PIO driver"); +MODULE_LICENSE("GPL"); + +EXPORT_SYMBOL(ssp_write_word); +EXPORT_SYMBOL(ssp_read_word); +EXPORT_SYMBOL(ssp_flush); +EXPORT_SYMBOL(ssp_enable); +EXPORT_SYMBOL(ssp_disable); +EXPORT_SYMBOL(ssp_save_state); +EXPORT_SYMBOL(ssp_restore_state); +EXPORT_SYMBOL(ssp_init); +EXPORT_SYMBOL(ssp_exit); diff -Nru a/arch/arm/mach-sa1100/system3.c b/arch/arm/mach-sa1100/system3.c --- a/arch/arm/mach-sa1100/system3.c Sat Mar 15 18:40:44 2003 +++ b/arch/arm/mach-sa1100/system3.c Sat Mar 15 18:40:44 2003 @@ -213,11 +213,17 @@ static int sdram_notifier(struct notifier_block *nb, unsigned long event, void *data) { + struct cpufreq_policy *policy = data; switch (event) { - case CPUFREQ_MINMAX: - cpufreq_updateminmax(data, 147500, 206000); + case CPUFREQ_ADJUST: + case CPUFREQ_INCOMPATIBLE: + cpufreq_verify_within_limits(policy, 147500, 206000); + break; + case CPUFREQ_NOTIFY: + if ((policy->min < 147500) || + (policy->max > 206000)) + panic("cpufreq failed to limit the speed\n"); break; - } return 0; } @@ -405,7 +411,7 @@ goto DONE; } -#if defined( CONFIG_CPU_FREQ ) +#ifdef CONFIG_CPU_FREQ ret = cpufreq_register_notifier(&system3_clkchg_block); if ( ret != 0 ) { printk( KERN_WARNING"PT Digital Board: could not register clock scale callback\n" ); diff -Nru a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c --- a/arch/arm/mm/fault-common.c Sat Mar 15 18:40:42 2003 +++ b/arch/arm/mm/fault-common.c Sat Mar 15 18:40:42 2003 @@ -342,20 +342,20 @@ struct pt_regs *regs) { struct task_struct *tsk; - unsigned int offset; + unsigned int index; pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; if (addr < TASK_SIZE) return do_page_fault(addr, fsr, regs); - offset = __pgd_offset(addr); + index = pgd_index(addr); /* * FIXME: CP15 C1 is write only on ARMv3 architectures. */ - pgd = cpu_get_pgd() + offset; - pgd_k = init_mm.pgd + offset; + pgd = cpu_get_pgd() + index; + pgd_k = init_mm.pgd + index; if (pgd_none(*pgd_k)) goto bad_area; diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types --- a/arch/arm/tools/mach-types Sat Mar 15 18:40:41 2003 +++ b/arch/arm/tools/mach-types Sat Mar 15 18:40:41 2003 @@ -6,7 +6,7 @@ # To add an entry into this database, please see Documentation/arm/README, # or contact rmk@arm.linux.org.uk # -# Last update: Mon Jan 13 22:55:16 2003 +# Last update: Wed Mar 5 22:11:59 2003 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -228,7 +228,7 @@ arnold SA1100_ARNOLD ARNOLD 217 psiboard SA1100_PSIBOARD PSIBOARD 218 jz8028 ARCH_JZ8028 JZ8028 219 -ipaq3 ARCH_IPAQ3 IPAQ3 220 +h5400 ARCH_IPAQ3 IPAQ3 220 forte SA1100_FORTE FORTE 221 acam SA1100_ACAM ACAM 222 abox SA1100_ABOX ABOX 223 @@ -259,7 +259,7 @@ stork_egg ARCH_STORK_EGG STORK_EGG 248 wismo SA1100_WISMO WISMO 249 ezlinx ARCH_EZLINX EZLINX 250 -at91rm9200 ARCH_AT91 AT91 251 +at91 ARCH_AT91 AT91 251 orion ARCH_ORION ORION 252 neptune ARCH_NEPTUNE NEPTUNE 253 hackkit SA1100_HACKKIT HACKKIT 254 @@ -281,3 +281,27 @@ siren ARCH_SIREN SIREN 270 greenlake ARCH_GREENLAKE GREENLAKE 271 argus ARCH_ARGUS ARGUS 272 +combadge SA1100_COMBADGE COMBADGE 273 +rokepxa ARCH_ROKEPXA ROKEPXA 274 +cintegrator ARCH_CINTEGRATOR CINTEGRATOR 275 +guidea07 ARCH_GUIDEA07 GUIDEA07 276 +tat257 ARCH_TAT257 TAT257 277 +igp2425 ARCH_IGP2425 IGP2425 278 +bluegrama ARCH_BLUEGRAMMA BLUEGRAMMA 279 +ipod ARCH_IPOD IPOD 280 +adsbitsyx ARCH_ADSBITSYX ADSBITSYX 281 +trizeps2 ARCH_TRIZEPS2 TRIZEPS2 282 +viper ARCH_VIPER VIPER 283 +adsbitsyplus SA1100_ADSBITSYPLUS ADSBITSYPLUS 284 +adsagc SA1100_ADSAGC ADSAGC 285 +stp7312 ARCH_STP7312 STP7312 286 +nx_phnx ARCH_PXA255 PXA255 287 +wep_ep250 ARCH_WEP_EP250 WEP_EP250 288 +inhandelf3 ARCH_INHANDELF3 INHANDELF3 289 +adi_coyote ARCH_ADI_COYOTE ADI_COYOTE 290 +iyonix ARCH_IYONIX IYONIX 291 +damicam_sa1110 ARCH_DAMICAM_SA1110 DAMICAM_SA1110 292 +meg03 ARCH_MEG03 MEG03 293 +pxa_whitechapel ARCH_PXA_WHITECHAPEL PXA_WHITECHAPEL 294 +nwsc ARCH_NWSC NWSC 295 +nwlarm ARCH_NWLARM NWLARM 296 diff -Nru a/arch/arm/vmlinux-armo.lds.in b/arch/arm/vmlinux-armo.lds.in --- a/arch/arm/vmlinux-armo.lds.in Sat Mar 15 18:40:44 2003 +++ b/arch/arm/vmlinux-armo.lds.in Sat Mar 15 18:40:44 2003 @@ -38,6 +38,9 @@ *(.initcall6.init) *(.initcall7.init) __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; . = ALIGN(32768); __init_end = .; } diff -Nru a/arch/arm/vmlinux-armv.lds.in b/arch/arm/vmlinux-armv.lds.in --- a/arch/arm/vmlinux-armv.lds.in Sat Mar 15 18:40:41 2003 +++ b/arch/arm/vmlinux-armv.lds.in Sat Mar 15 18:40:41 2003 @@ -45,6 +45,9 @@ *(.initcall6.init) *(.initcall7.init) __initcall_end = .; + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; . = ALIGN(32); __initramfs_start = .; usr/built-in.o(.init.ramfs) diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig --- a/arch/cris/Kconfig Sat Mar 15 18:40:44 2003 +++ b/arch/cris/Kconfig Sat Mar 15 18:40:44 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/cris/kernel/irq.c b/arch/cris/kernel/irq.c --- a/arch/cris/kernel/irq.c Sat Mar 15 18:40:45 2003 +++ b/arch/cris/kernel/irq.c Sat Mar 15 18:40:45 2003 @@ -228,11 +228,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0; i < NR_IRQS; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %10u %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -243,6 +245,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/cris/vmlinux.lds.S b/arch/cris/vmlinux.lds.S --- a/arch/cris/vmlinux.lds.S Sat Mar 15 18:40:41 2003 +++ b/arch/cris/vmlinux.lds.S Sat Mar 15 18:40:41 2003 @@ -69,7 +69,12 @@ *(.initcall6.init); *(.initcall7.init); __initcall_end = .; - + } + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + /* We fill to the next page, so we can discard all init pages without needing to consider what payload might be appended to the kernel image. */ diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Sat Mar 15 18:40:40 2003 +++ b/arch/i386/Kconfig Sat Mar 15 18:40:40 2003 @@ -18,15 +18,6 @@ bool default y -config SWAP - bool "Support for paging of anonymous memory" - default y - help - This option allows you to choose whether you want to have support - for socalled swap devices or swap files in your kernel that are - used to provide more virtual memory than the actual RAM present - in your computer. If unusre say Y. - config SBUS bool @@ -488,7 +479,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) + depends on (HIGHMEM64G && (X86_NUMAQ || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY))) || X86_PC config DISCONTIGMEM bool diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Sat Mar 15 18:40:41 2003 +++ b/arch/i386/Makefile Sat Mar 15 18:40:41 2003 @@ -92,7 +92,8 @@ boot := arch/i386/boot -.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install +.PHONY: zImage bzImage compressed zlilo bzlilo \ + zdisk bzdisk fdimage fdimage144 fdimage288 install all: bzImage @@ -110,8 +111,8 @@ zdisk bzdisk: vmlinux $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) zdisk -install: vmlinux - $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) install +install fdimage fdimage144 fdimage288: vmlinux + $(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@ archclean: $(Q)$(MAKE) $(clean)=arch/i386/boot @@ -122,5 +123,8 @@ echo ' (your) ~/bin/installkernel or' echo ' (distribution) /sbin/installkernel or' echo ' install to $$(INSTALL_PATH) and run lilo' + echo ' bzdisk - Create a boot floppy in /dev/fd0' + echo ' fdimage - Create a boot floppy image' endef +CLEAN_FILES += arch/$(ARCH)/boot/fdimage arch/$(ARCH)/boot/mtools.conf diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile --- a/arch/i386/boot/Makefile Sat Mar 15 18:40:41 2003 +++ b/arch/i386/boot/Makefile Sat Mar 15 18:40:41 2003 @@ -62,8 +62,36 @@ $(Q)$(MAKE) -f scripts/Makefile.build obj=$(obj)/compressed \ IMAGE_OFFSET=$(IMAGE_OFFSET) $@ -zdisk: $(BOOTIMAGE) - dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0 +# Set this if you want to pass append arguments to the zdisk/fdimage kernel +FDARGS = + +$(obj)/mtools.conf: $(src)/mtools.conf.in + sed -e 's|@OBJ@|$(obj)|g' < $< > $@ + +# This requires write access to /dev/fd0 +zdisk: $(BOOTIMAGE) $(obj)/mtools.conf + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync + syslinux /dev/fd0 ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync + syslinux $(obj)/fdimage ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync + syslinux $(obj)/fdimage ; sync + echo 'default linux $(FDARGS)' | \ + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -Nru a/arch/i386/boot/bootsect.S b/arch/i386/boot/bootsect.S --- a/arch/i386/boot/bootsect.S Sat Mar 15 18:40:42 2003 +++ b/arch/i386/boot/bootsect.S Sat Mar 15 18:40:42 2003 @@ -4,29 +4,13 @@ * modified by Drew Eckhardt * modified by Bruce Evans (bde) * modified by Chris Noe (May 1999) (as86 -> gas) - * - * 360k/720k disk support: Andrzej Krzysztofowicz + * gutted by H. Peter Anvin (Jan 2003) * * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment * addresses must be multiplied by 16 to obtain their respective linear * addresses. To avoid confusion, linear addresses are written using leading * hex while segment addresses are written as segment:offset. * - * bde - should not jump blindly, there may be systems with only 512K low - * memory. Use int 0x12 to get the top of memory, etc. - * - * It then loads 'setup' directly after itself (0x90200), and the system - * at 0x10000, using BIOS interrupts. - * - * NOTE! currently system is at most (8*65536-4096) bytes long. This should - * be no problem, even in the future. I want to keep it simple. This 508 kB - * kernel size should be enough, especially as this doesn't contain the - * buffer cache as in minix (and especially now that the kernel is - * compressed :-) - * - * The loader has been made as simple as possible, and continuous - * read errors will result in a unbreakable loop. Reboot by hand. It - * loads pretty fast by getting whole tracks at a time whenever possible. */ #include @@ -59,359 +43,51 @@ .global _start _start: -# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there. + # Normalize the start address + jmpl $BOOTSEG, $start2 - movw $BOOTSEG, %ax - movw %ax, %ds # %ds = BOOTSEG - movw $INITSEG, %ax - movw %ax, %es # %ax = %es = INITSEG - movw $256, %cx - subw %si, %si - subw %di, %di - cld - rep - movsw - ljmp $INITSEG, $go - -# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde). We -# wouldn't have to worry about this if we checked the top of memory. Also -# my BIOS can be configured to put the wini drive tables in high memory -# instead of in the vector table. The old stack might have clobbered the -# drive table. - -go: movw $0x4000-12, %di # 0x4000 is an arbitrary value >= - # length of bootsect + length of - # setup + room for stack; - # 12 is disk parm size. - movw %ax, %ds # %ax and %es already contain INITSEG +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es movw %ax, %ss - movw %di, %sp # put stack at INITSEG:0x4000-12. + movw $0x7c00, %sp + sti + cld -# Many BIOS's default disk parameter tables will not recognize -# multi-sector reads beyond the maximum sector number specified -# in the default diskette parameter tables - this may mean 7 -# sectors in some cases. -# -# Since single sector reads are slow and out of the question, -# we must take care of this by creating new parameter tables -# (for the first disk) in RAM. We will set the maximum sector -# count to 36 - the most we will encounter on an ED 2.88. -# -# High doesn't hurt. Low does. -# -# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0, -# and %gs is unused. - - movw %cx, %fs # %fs = 0 - movw $0x78, %bx # %fs:%bx is parameter table address - pushw %ds - ldsw %fs:(%bx), %si # %ds:%si is source - movb $6, %cl # copy 12 bytes - pushw %di # %di = 0x4000-12. - rep # don't worry about cld - movsw # already done above - popw %di - popw %ds - movb $36, 0x4(%di) # patch sector count - movw %di, %fs:(%bx) - movw %es, %fs:2(%bx) - -# Get disk drive parameters, specifically number of sectors/track. - -# It seems that there is no BIOS call to get the number of sectors. -# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18 -# can be read, 15 if sector 15 can be read. Otherwise guess 9. -# Note that %cx = 0 from rep movsw above. + movw $bugger_off_msg, %si - movw $disksizes, %si # table of sizes to try -probe_loop: +msg_loop: lodsb - cbtw # extend to word - movw %ax, sectors - cmpw $disksizes+4, %si - jae got_sectors # If all else fails, try 9 - - xchgw %cx, %ax # %cx = track and sector - xorw %dx, %dx # drive 0, head 0 - movw $0x0200, %bx # address = 512, in INITSEG (%es = %cs) - movw $0x0201, %ax # service 2, 1 sector - int $0x13 - jc probe_loop # try next value - -got_sectors: - movb $0x03, %ah # read cursor pos - xorb %bh, %bh - int $0x10 - movw $9, %cx - movb $0x07, %bl # page 0, attribute 7 (normal) - # %bh is set above; int10 doesn't - # modify it - movw $msg1, %bp - movw $0x1301, %ax # write string, move cursor - int $0x10 # tell the user we're loading.. - -# Load the setup-sectors directly after the moved bootblock (at 0x90200). -# We should know the drive geometry to do it, as setup may exceed first -# cylinder (for 9-sector 360K and 720K floppies). - - movw $0x0001, %ax # set sread (sector-to-read) to 1 as - movw $sread, %si # the boot sector has already been read - movw %ax, (%si) - - call kill_motor # reset FDC - movw $0x0200, %bx # address = 512, in INITSEG -next_step: - movb setup_sects, %al - movw sectors, %cx - subw (%si), %cx # (%si) = sread - cmpb %cl, %al - jbe no_cyl_crossing - movw sectors, %ax - subw (%si), %ax # (%si) = sread -no_cyl_crossing: - call read_track - pushw %ax # save it - call set_next # set %bx properly; it uses %ax,%cx,%dx - popw %ax # restore - subb %al, setup_sects # rest - for next step - jnz next_step - - pushw $SYSSEG - popw %es # %es = SYSSEG - call read_it - call kill_motor - call print_nl - -# After that we check which root-device to use. If the device is -# defined (!= 0), nothing is done and the given device is used. -# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8) -# depending on the number of sectors we pretend to know we have. - -# Segments are as follows: %cs = %ds = %ss = INITSEG, -# %es = SYSSEG, %fs = 0, %gs is unused. - - movw root_dev, %ax - orw %ax, %ax - jne root_defined - - movw sectors, %bx - movw $0x0208, %ax # /dev/ps0 - 1.2Mb - cmpw $15, %bx - je root_defined - - movb $0x1c, %al # /dev/PS0 - 1.44Mb - cmpw $18, %bx - je root_defined - - movb $0x20, %al # /dev/fd0H2880 - 2.88Mb - cmpw $36, %bx - je root_defined - - movb $0, %al # /dev/fd0 - autodetect -root_defined: - movw %ax, root_dev - -# After that (everything loaded), we jump to the setup-routine -# loaded directly after the bootblock: - - ljmp $SETUPSEG, $0 - -# These variables are addressed via %si register as it gives shorter code. - -sread: .word 0 # sectors read of current track -head: .word 0 # current head -track: .word 0 # current track - -# This routine loads the system at address SYSSEG, making sure -# no 64kB boundaries are crossed. We try to load it as fast as -# possible, loading whole tracks whenever we can. - -read_it: - movw %es, %ax # %es = SYSSEG when called - testw $0x0fff, %ax -die: jne die # %es must be at 64kB boundary - xorw %bx, %bx # %bx is starting address within segment -rp_read: -#ifdef __BIG_KERNEL__ # look in setup.S for bootsect_kludge - bootsect_kludge = 0x220 # 0x200 + 0x20 which is the size of the - lcall *bootsect_kludge # bootsector + bootsect_kludge offset -#else - movw %es, %ax - subw $SYSSEG, %ax - movw %bx, %cx - shr $4, %cx - add %cx, %ax # check offset -#endif - cmpw syssize, %ax # have we loaded everything yet? - jbe ok1_read - - ret - -ok1_read: - movw sectors, %ax - subw (%si), %ax # (%si) = sread - movw %ax, %cx - shlw $9, %cx - addw %bx, %cx - jnc ok2_read - - je ok2_read - - xorw %ax, %ax - subw %bx, %ax - shrw $9, %ax -ok2_read: - call read_track - call set_next - jmp rp_read - -read_track: - pusha - pusha - movw $0xe2e, %ax # loading... message 2e = . + andb %al, %al + jz die + movb $0xe, %ah movw $7, %bx - int $0x10 - popa - -# Accessing head, track, sread via %si gives shorter code. + int $0x10 + jmp msg_loop - movw 4(%si), %dx # 4(%si) = track - movw (%si), %cx # (%si) = sread - incw %cx - movb %dl, %ch - movw 2(%si), %dx # 2(%si) = head - movb %dl, %dh - andw $0x0100, %dx - movb $2, %ah - pushw %dx # save for error dump - pushw %cx - pushw %bx - pushw %ax - int $0x13 - jc bad_rt - - addw $8, %sp - popa - ret - -set_next: - movw %ax, %cx - addw (%si), %ax # (%si) = sread - cmp sectors, %ax - jne ok3_set - movw $0x0001, %ax - xorw %ax, 2(%si) # change head - jne ok4_set - incw 4(%si) # next track -ok4_set: +die: + # Allow the user to press a key, then reboot xorw %ax, %ax -ok3_set: - movw %ax, (%si) # set sread - shlw $9, %cx - addw %cx, %bx - jnc set_next_fin - movw %es, %ax - addb $0x10, %ah - movw %ax, %es - xorw %bx, %bx -set_next_fin: - ret - -bad_rt: - pushw %ax # save error code - call print_all # %ah = error, %al = read - xorb %ah, %ah - xorb %dl, %dl - int $0x13 - addw $10, %sp - popa - jmp read_track - -# print_all is for debugging purposes. -# -# it will print out all of the registers. The assumption is that this is -# called from a routine, with a stack frame like -# -# %dx -# %cx -# %bx -# %ax -# (error) -# ret <- %sp - -print_all: - movw $5, %cx # error code + 4 registers - movw %sp, %bp -print_loop: - pushw %cx # save count remaining - call print_nl # <-- for readability - cmpb $5, %cl - jae no_reg # see if register name is needed - - movw $0xe05 + 'A' - 1, %ax - subb %cl, %al - int $0x10 - movb $'X', %al - int $0x10 - movb $':', %al - int $0x10 -no_reg: - addw $2, %bp # next register - call print_hex # print it - popw %cx - loop print_loop - ret + int $0x16 + int $0x19 -print_nl: - movw $0xe0d, %ax # CR - int $0x10 - movb $0xa, %al # LF - int $0x10 - ret - -# print_hex is for debugging purposes, and prints the word -# pointed to by %ss:%bp in hexadecimal. - -print_hex: - movw $4, %cx # 4 hex digits - movw (%bp), %dx # load word into %dx -print_digit: - rolw $4, %dx # rotate to use low 4 bits - movw $0xe0f, %ax # %ah = request - andb %dl, %al # %al = mask for nybble - addb $0x90, %al # convert %al to ascii hex - daa # in only four instructions! - adc $0x40, %al - daa - int $0x10 - loop print_digit - ret + # int 0x19 should never return. In case it does anyway, + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 -# This procedure turns off the floppy drive motor, so -# that we enter the kernel in a known state, and -# don't have to worry about it later. -# NOTE: Doesn't save %ax or %dx; do it yourself if you need to. - -kill_motor: -#if 1 - xorw %ax, %ax # reset FDC - xorb %dl, %dl - int $0x13 -#else - movw $0x3f2, %dx - xorb %al, %al - outb %al, %dx -#endif - ret -sectors: .word 0 -disksizes: .byte 36, 21, 18, 15, 9 -msg1: .byte 13, 10 - .ascii "Loading" +bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" + .ascii "\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + -# XXX: This is a fairly snug fit. + # Kernel attributes; used by setup -.org 497 + .org 497 setup_sects: .byte SETUPSECTS root_flags: .word ROOT_RDONLY syssize: .word SYSSIZE diff -Nru a/arch/i386/boot/mtools.conf.in b/arch/i386/boot/mtools.conf.in --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/boot/mtools.conf.in Sat Mar 15 18:40:45 2003 @@ -0,0 +1,17 @@ +# +# mtools configuration file for "make (b)zdisk" +# + +# Actual floppy drive +drive a: + file="/dev/fd0" + +# 1.44 MB floppy disk image +drive v: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=18 filter + +# 2.88 MB floppy disk image (mostly for virtual uses) +drive w: + file="@OBJ@/fdimage" cylinders=80 heads=2 sectors=36 filter + + diff -Nru a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c --- a/arch/i386/boot/tools/build.c Sat Mar 15 18:40:42 2003 +++ b/arch/i386/boot/tools/build.c Sat Mar 15 18:40:42 2003 @@ -150,13 +150,10 @@ sz = sb.st_size; fprintf (stderr, "System is %d kB\n", sz/1024); sys_size = (sz + 15) / 16; - /* 0x28000*16 = 2.5 MB, conservative estimate for the current maximum */ - if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE)) + /* 0x40000*16 = 4.0 MB, reasonable estimate for the current maximum */ + if (sys_size > (is_big_kernel ? 0x40000 : DEF_SYSSIZE)) die("System is too big. Try using %smodules.", is_big_kernel ? "" : "bzImage or "); - if (sys_size > 0xefff) - fprintf(stderr,"warning: kernel is too big for standalone boot " - "from floppy\n"); while (sz > 0) { int l, n; diff -Nru a/arch/i386/kernel/cpu/centaur.c b/arch/i386/kernel/cpu/centaur.c --- a/arch/i386/kernel/cpu/centaur.c Sat Mar 15 18:40:42 2003 +++ b/arch/i386/kernel/cpu/centaur.c Sat Mar 15 18:40:42 2003 @@ -248,6 +248,37 @@ } #endif +static void __init init_c3(struct cpuinfo_x86 *c) +{ + u32 lo, hi; + + /* Test for Centaur Extended Feature Flags presence */ + if (cpuid_eax(0xC0000000) >= 0xC0000001) { + /* store Centaur Extended Feature Flags as + * word 5 of the CPU capability bit array + */ + c->x86_capability[5] = cpuid_edx(0xC0000001); + } + + switch (c->x86_model) { + case 6 ... 8: /* Cyrix III family */ + rdmsr (MSR_VIA_FCR, lo, hi); + lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ + wrmsr (MSR_VIA_FCR, lo, hi); + + set_bit(X86_FEATURE_CX8, c->x86_capability); + set_bit(X86_FEATURE_3DNOW, c->x86_capability); + + /* fall through */ + + case 9: /* Nehemiah */ + default: + get_model_name(c); + display_cacheinfo(c); + break; + } +} + static void __init init_centaur(struct cpuinfo_x86 *c) { enum { @@ -386,21 +417,7 @@ break; case 6: - switch (c->x86_model) { - case 6 ... 8: /* Cyrix III family */ - rdmsr (MSR_VIA_FCR, lo, hi); - lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ - wrmsr (MSR_VIA_FCR, lo, hi); - - set_bit(X86_FEATURE_CX8, c->x86_capability); - set_bit(X86_FEATURE_3DNOW, c->x86_capability); - - case 9: /* Nehemiah */ - default: - get_model_name(c); - display_cacheinfo(c); - break; - } + init_c3(c); break; } } diff -Nru a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c --- a/arch/i386/kernel/cpu/common.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/cpu/common.c Sat Mar 15 18:40:39 2003 @@ -211,9 +211,10 @@ /* Intel-defined flags: level 0x00000001 */ if ( c->cpuid_level >= 0x00000001 ) { - u32 capability; - cpuid(0x00000001, &tfms, &junk, &junk, &capability); + u32 capability, excap; + cpuid(0x00000001, &tfms, &junk, &excap, &capability); c->x86_capability[0] = capability; + c->x86_capability[4] = excap; c->x86 = (tfms >> 8) & 15; c->x86_model = (tfms >> 4) & 15; c->x86_mask = tfms & 15; @@ -480,7 +481,7 @@ */ atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; - if(current->mm) + if (current->mm) BUG(); enter_lazy_tlb(&init_mm, current, cpu); @@ -508,7 +509,7 @@ /* * Force FPU initialization: */ - clear_thread_flag(TIF_USEDFPU); + current_thread_info()->status = 0; current->used_math = 0; stts(); } diff -Nru a/arch/i386/kernel/cpu/cpufreq/acpi.c b/arch/i386/kernel/cpu/cpufreq/acpi.c --- a/arch/i386/kernel/cpu/cpufreq/acpi.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/cpu/cpufreq/acpi.c Sat Mar 15 18:40:39 2003 @@ -619,6 +619,7 @@ .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, .name = "acpi-cpufreq", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/elanfreq.c b/arch/i386/kernel/cpu/cpufreq/elanfreq.c --- a/arch/i386/kernel/cpu/cpufreq/elanfreq.c Sat Mar 15 18:40:41 2003 +++ b/arch/i386/kernel/cpu/cpufreq/elanfreq.c Sat Mar 15 18:40:41 2003 @@ -250,6 +250,7 @@ .target = elanfreq_target, .init = elanfreq_cpu_init, .name = "elanfreq", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Sat Mar 15 18:40:42 2003 +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c Sat Mar 15 18:40:42 2003 @@ -444,13 +444,14 @@ /* * cpufreq_gx_init: - * MediaGX/Geode GX initilize cpufreq driver + * MediaGX/Geode GX initialize cpufreq driver */ static struct cpufreq_driver gx_suspmod_driver = { .verify = cpufreq_gx_verify, .target = cpufreq_gx_target, .init = cpufreq_gx_cpu_init, .name = "gx-suspmod", + .owner = THIS_MODULE, }; static int __init cpufreq_gx_init(void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Sat Mar 15 18:40:39 2003 @@ -40,18 +40,15 @@ #define dprintk(msg...) do { } while(0); #endif -static int numscales=16, numvscales; +static unsigned int numscales=16, numvscales; static int minvid, maxvid; static int can_scale_voltage; -static int can_scale_fsb; static int vrmrev; /* Module parameters */ -static int prefer_slow_fsb; static int dont_scale_voltage; -static int dont_scale_fsb; -static int current_fsb; +static unsigned int fsb; #define __hlt() __asm__ __volatile__("hlt": : :"memory") @@ -231,14 +228,6 @@ 145, /* 1111 -> 14.5x */ }; -/* fsb values as defined in CPU */ -static unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; -/* fsb values to favour low fsb speed (lower power) */ -static unsigned int power_fsb_table[] = { 66, 100, 133, -1 }; -/* fsb values to favour high fsb speed (for e.g. if lowering CPU - freq because of heat, but want to maintain highest performance possible) */ -static unsigned int perf_fsb_table[] = { 133, 100, 66, -1 }; - /* Voltage scales. Div by 1000 to get actual voltage. */ static int __initdata vrm85scales[32] = { 1250, 1200, 1150, 1100, 1050, 1800, 1750, 1700, @@ -258,21 +247,22 @@ static int clock_ratio[32]; static int eblcr_table[32]; static int voltage_table[32]; -static int highest_speed, lowest_speed; /* kHz */ +static unsigned int highest_speed, lowest_speed; /* kHz */ static int longhaul; /* version. */ static struct cpufreq_frequency_table *longhaul_table; static int longhaul_get_cpu_fsb (void) { + unsigned int eblcr_fsb_table[] = { 66, 133, 100, -1 }; unsigned long invalue=0,lo, hi; - if (current_fsb == 0) { + if (fsb == 0) { rdmsr (MSR_IA32_EBL_CR_POWERON, lo, hi); invalue = (lo & (1<<18|1<<19)) >>18; return eblcr_fsb_table[invalue]; } else { - return current_fsb; + return fsb; } } @@ -294,12 +284,11 @@ /** * longhaul_set_cpu_frequency() * @clock_ratio_index : index of clock_ratio[] for new frequency - * @newfsb: the new FSB * * Sets a new clock ratio, and -if applicable- a new Front Side Bus */ -static void longhaul_setstate (unsigned int clock_ratio_index, unsigned int newfsb) +static void longhaul_setstate (unsigned int clock_ratio_index) { unsigned long lo, hi; unsigned int bits; @@ -307,24 +296,21 @@ int vidindex, i; struct cpufreq_freqs freqs; - if (!newfsb || (clock_ratio[clock_ratio_index] == -1)) - return; - - if ((!can_scale_fsb) && (newfsb != current_fsb)) + if (clock_ratio[clock_ratio_index] == -1) return; - if (((clock_ratio[clock_ratio_index] * newfsb * 100) > highest_speed) || - ((clock_ratio[clock_ratio_index] * newfsb * 100) < lowest_speed)) + if (((clock_ratio[clock_ratio_index] * fsb * 100) > highest_speed) || + ((clock_ratio[clock_ratio_index] * fsb * 100) < lowest_speed)) return; freqs.old = longhaul_get_cpu_mult() * longhaul_get_cpu_fsb() * 100; - freqs.new = clock_ratio[clock_ratio_index] * newfsb * 100; + freqs.new = clock_ratio[clock_ratio_index] * fsb * 100; freqs.cpu = 0; /* longhaul.c is UP only driver */ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - dprintk (KERN_INFO "longhaul: New FSB:%d Mult(x10):%d\n", - newfsb, clock_ratio[clock_ratio_index]); + dprintk (KERN_INFO "longhaul: FSB:%d Mult(x10):%d\n", + fsb * 100, clock_ratio[clock_ratio_index]); bits = clock_ratio_index; /* "bits" contains the bitpattern of the new multiplier. @@ -358,14 +344,9 @@ lo |= revkey; if (can_scale_voltage) { - if (can_scale_fsb==1) { - dprintk (KERN_INFO "longhaul: Voltage scaling + FSB scaling not done yet.\n"); - goto bad_voltage; - } else { - /* PB: TODO fix this up */ - vidindex = (((highest_speed-lowest_speed) / (newfsb/2)) - - ((highest_speed-((clock_ratio[clock_ratio_index] * newfsb * 100)/1000)) / (newfsb/2))); - } + /* PB: TODO fix this up */ + vidindex = (((highest_speed-lowest_speed) / (fsb/2)) - + ((highest_speed-((clock_ratio[clock_ratio_index] * fsb * 100)/1000)) / (fsb/2))); for (i=0;i<32;i++) { dprintk (KERN_INFO "VID hunting. Looking for %d, found %d\n", minvid+(vidindex*25), voltage_table[i]); @@ -403,17 +384,6 @@ lo |= (1<<8); /* EnableSoftBusRatio */ lo |= revkey; - /* Set FSB */ - if (can_scale_fsb==1) { - lo &= ~(1<<28|1<<29); - switch (newfsb) { - case 66: lo |= (1<<28|1<<29); /* 11 */ - break; - case 100: lo |= 1<<28; /* 01 */ - break; - case 133: break; /* 00*/ - } - } wrmsr (MSR_VIA_LONGHAUL, lo, hi); __hlt(); @@ -431,14 +401,11 @@ static int __init longhaul_get_ranges (void) { unsigned long lo, hi, invalue; - unsigned int minmult=0, maxmult=0, minfsb=0, maxfsb=0; + unsigned int minmult=0, maxmult=0; unsigned int multipliers[32]= { 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; - unsigned int fsb_table[4] = { 133, 100, -1, 66 }; - unsigned int fsbcount = 1; - unsigned int i, j, k = 0; - static unsigned int *fsb_search_table; + unsigned int j, k = 0; switch (longhaul) { case 1: @@ -446,7 +413,6 @@ Assume min=3.0x & max = whatever we booted at. */ minmult = 30; maxmult = longhaul_get_cpu_mult(); - minfsb = maxfsb = current_fsb; break; case 2 ... 3: @@ -465,55 +431,30 @@ #else minmult = 30; /* as per spec */ #endif - - if (can_scale_fsb==1) { - invalue = (hi & (1<<9|1<<10)) >> 9; - maxfsb = fsb_table[invalue]; - - invalue = (hi & (1<<25|1<<26)) >> 25; - minfsb = fsb_table[invalue]; - - dprintk (KERN_INFO "longhaul: Min FSB=%d Max FSB=%d\n", - minfsb, maxfsb); - fsbcount = 0; - for (i=0;i<4;i++) { - if((fsb_table[i] >= minfsb) && (fsb_table[i] <= maxfsb)) - fsbcount++; - } - } else { - minfsb = maxfsb = current_fsb; - } break; } - highest_speed = maxmult * maxfsb * 100; - lowest_speed = minmult * minfsb * 100; + highest_speed = maxmult * fsb * 100; + lowest_speed = minmult * fsb * 100; dprintk (KERN_INFO "longhaul: MinMult(x10)=%d MaxMult(x10)=%d\n", minmult, maxmult); dprintk (KERN_INFO "longhaul: Lowestspeed=%d Highestspeed=%d\n", lowest_speed, highest_speed); - longhaul_table = kmalloc((numscales * fsbcount + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); + longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) return -ENOMEM; - if (prefer_slow_fsb) - fsb_search_table = perf_fsb_table; // yep, this is right: the last entry is preferred by cpufreq_frequency_table_* ... - else - fsb_search_table = power_fsb_table; - - for (i=0; (i<4); i++) { - if ((fsb_search_table[i] > maxfsb) || (fsb_search_table[i] < minfsb) || (fsb_search_table[i] == -1)) + for (j=0; (j maxmult) || (clock_ratio[j] < minmult) || (clock_ratio[j] == -1)) - continue; - longhaul_table[k].frequency= clock_ratio[j] * fsb_search_table[i] * 100; - longhaul_table[k].index = (j << 8) | (i); - k++; - } + if (((unsigned int)clock_ratio[j] > maxmult) || ((unsigned int)clock_ratio[j] < minmult)) + continue; + longhaul_table[k].frequency= clock_ratio[j] * fsb * 100; + longhaul_table[k].index = (j << 8); + k++; } - + longhaul_table[k].frequency = CPUFREQ_TABLE_END; if (!k) return -EINVAL; @@ -568,16 +509,14 @@ unsigned int relation) { unsigned int table_index = 0; - unsigned int new_fsb = 0; unsigned int new_clock_ratio = 0; if (cpufreq_frequency_table_target(policy, longhaul_table, target_freq, relation, &table_index)) return -EINVAL; new_clock_ratio = longhaul_table[table_index].index & 0xFF; - new_fsb = power_fsb_table[(longhaul_table[table_index].index & 0xFF00) >> 8]; - longhaul_setstate(new_clock_ratio, new_fsb); + longhaul_setstate(new_clock_ratio); return 0; } @@ -628,9 +567,6 @@ rdmsr (MSR_VIA_LONGHAUL, lo, hi); if ((lo & (1<<0)) && (dont_scale_voltage==0)) longhaul_setup_voltagescaling (lo, hi); - - if ((lo & (1<<1)) && (dont_scale_fsb==0) && (current_fsb==0)) - can_scale_fsb = 1; } if (longhaul_get_ranges()) @@ -639,7 +575,7 @@ policy->policy = CPUFREQ_POLICY_PERFORMANCE; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; - policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); + policy->cur = (unsigned int) (longhaul_get_cpu_fsb() * longhaul_get_cpu_mult() * 100); return cpufreq_frequency_table_cpuinfo(policy, longhaul_table); } @@ -649,6 +585,7 @@ .target = longhaul_target, .init = longhaul_cpu_init, .name = "longhaul", + .owner = THIS_MODULE, }; static int __init longhaul_init (void) @@ -676,10 +613,7 @@ kfree(longhaul_table); } -MODULE_PARM (dont_scale_fsb, "i"); MODULE_PARM (dont_scale_voltage, "i"); -MODULE_PARM (current_fsb, "i"); -MODULE_PARM (prefer_slow_fsb, "i"); MODULE_AUTHOR ("Dave Jones "); MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c --- a/arch/i386/kernel/cpu/cpufreq/longrun.c Sat Mar 15 18:40:43 2003 +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Sat Mar 15 18:40:43 2003 @@ -253,6 +253,7 @@ .setpolicy = longrun_set_policy, .init = longrun_cpu_init, .name = "longrun", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- a/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Sat Mar 15 18:40:44 2003 +++ b/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c Sat Mar 15 18:40:44 2003 @@ -214,6 +214,7 @@ else p4clockmod_table[i].frequency = (stock_freq * i)/8; } + cpufreq_frequency_table_get_attr(p4clockmod_table, policy->cpu); /* cpuinfo and default policy values */ policy->policy = CPUFREQ_POLICY_PERFORMANCE; @@ -226,9 +227,14 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { + cpufreq_frequency_table_put_attr(policy->cpu); return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); } +static struct freq_attr* p4clockmod_attr[] = { + &cpufreq_freq_attr_scaling_available_freqs, + NULL, +}; static struct cpufreq_driver p4clockmod_driver = { .verify = cpufreq_p4_verify, @@ -236,6 +242,8 @@ .init = cpufreq_p4_cpu_init, .exit = cpufreq_p4_cpu_exit, .name = "p4-clockmod", + .owner = THIS_MODULE, + .attr = p4clockmod_attr, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k6.c Sat Mar 15 18:40:40 2003 @@ -190,6 +190,7 @@ .init = powernow_k6_cpu_init, .exit = powernow_k6_cpu_exit, .name = "powernow-k6", + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Sat Mar 15 18:40:39 2003 @@ -151,7 +151,7 @@ } if (!(edx & (1 << 1 | 1 << 2))) { - printk (" nothing.\n"); + printk ("nothing.\n"); return 0; } @@ -162,9 +162,8 @@ static int get_ranges (unsigned char *pst) { - int j; + unsigned int j, speed; u8 fid, vid; - unsigned int speed; powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) @@ -239,12 +238,17 @@ __asm__("\tcli\n"); rdmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); fidvidctl.bits.SGTC = latency; /* Stop grant timeout counter */ + fidvidctl.bits.FID = fid; - fidvidctl.bits.VID = vid; - /* Note, we could set these lazily. Ie, only do voltage transition - if its changed since last time (Some speeds have the same voltage) */ fidvidctl.bits.FIDC = 1; - fidvidctl.bits.VIDC = 1; + + /* Set the voltage lazily. Ie, only do voltage transition + if its changed since last time (Some speeds have the same voltage) */ + if (fidvidctl.bits.VID != vid) { + fidvidctl.bits.VID = vid; + fidvidctl.bits.VIDC = 1; + } + wrmsrl (MSR_K7_FID_VID_CTL, fidvidctl.val); if (have_a0 == 1) __asm__("\tsti\n"); @@ -253,7 +257,7 @@ } -int powernow_decode_bios (int maxfid, int startvid) +static int powernow_decode_bios (int maxfid, int startvid) { struct psb_s *psb; struct pst_s *pst; @@ -377,6 +381,7 @@ .target = powernow_target, .init = powernow_cpu_init, .name = "powernow-k7", + .owner = THIS_MODULE, }; static int __init powernow_init (void) diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep.c b/arch/i386/kernel/cpu/cpufreq/speedstep.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep.c Sat Mar 15 18:40:39 2003 @@ -29,7 +29,6 @@ #include - /* speedstep_chipset: * It is necessary to know which chipset is used. As accesses to * this device occur at various places in this module, we need a @@ -40,7 +39,7 @@ #define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 #define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 - +#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 /* speedstep_processor */ @@ -106,6 +105,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) @@ -166,6 +166,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) @@ -245,6 +246,7 @@ switch (speedstep_chipset) { case SPEEDSTEP_CHIPSET_ICH2M: case SPEEDSTEP_CHIPSET_ICH3M: + case SPEEDSTEP_CHIPSET_ICH4M: { u16 value = 0; @@ -277,6 +279,14 @@ static unsigned int speedstep_detect_chipset (void) { speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801DB_12, + PCI_ANY_ID, + PCI_ANY_ID, + NULL); + if (speedstep_chipset_dev) + return SPEEDSTEP_CHIPSET_ICH4M; + + speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, @@ -658,6 +668,7 @@ .verify = speedstep_verify, .target = speedstep_target, .init = speedstep_cpu_init, + .owner = THIS_MODULE, }; diff -Nru a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c --- a/arch/i386/kernel/cpu/proc.c Sat Mar 15 18:40:44 2003 +++ b/arch/i386/kernel/cpu/proc.c Sat Mar 15 18:40:44 2003 @@ -37,7 +37,20 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* Other (Linux-defined) */ - "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, + "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, NULL, + "tm2", NULL, "cnxt_id", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* VIA/Cyrix/Centaur-defined */ + NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c --- a/arch/i386/kernel/dmi_scan.c Sat Mar 15 18:40:41 2003 +++ b/arch/i386/kernel/dmi_scan.c Sat Mar 15 18:40:41 2003 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -893,3 +894,5 @@ if(err == 0) dmi_check_blacklist(); } + +EXPORT_SYMBOL(is_unsafe_smbus); diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/entry.S Sat Mar 15 18:40:40 2003 @@ -72,6 +72,12 @@ NT_MASK = 0x00004000 VM_MASK = 0x00020000 +/* + * ESP0 is at offset 4. 0x100 is the size of the TSS, and + * also thus the top-of-stack pointer offset of SYSENTER_ESP + */ +TSS_ESP0_OFFSET = (4 - 0x100) + #ifdef CONFIG_PREEMPT #define preempt_stop cli #else @@ -229,6 +235,8 @@ # sysenter call handler stub ENTRY(sysenter_entry) + movl TSS_ESP0_OFFSET(%esp),%esp +sysenter_past_esp: sti pushl $(__USER_DS) pushl %ebp @@ -458,12 +466,36 @@ addl $4, %esp jmp ret_from_exception +/* + * Debug traps and NMI can happen at the one SYSENTER instruction + * that sets up the real kernel stack. Check here, since we can't + * allow the wrong stack to be used. + * + * "TSS_ESP0_OFFSET+12" is because the NMI/debug handler will have + * already pushed 3 words if it hits on the sysenter instruction: + * eflags, cs and eip. + * + * We just load the right stack, and push the three (known) values + * by hand onto the new stack - while updating the return eip past + * the instruction that would have done it for sysenter. + */ +#define CHECK_SYSENTER_EIP \ + cmpl $sysenter_entry,(%esp); \ + jne 1f; \ + movl TSS_ESP0_OFFSET+12(%esp),%esp; \ + pushfl; \ + pushl $__KERNEL_CS; \ + pushl $sysenter_past_esp; \ +1: + ENTRY(debug) + CHECK_SYSENTER_EIP pushl $0 pushl $do_debug jmp error_code ENTRY(nmi) + CHECK_SYSENTER_EIP pushl %eax SAVE_ALL movl %esp, %edx diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Sat Mar 15 18:40:45 2003 +++ b/arch/i386/kernel/i386_ksyms.c Sat Mar 15 18:40:45 2003 @@ -68,6 +68,7 @@ EXPORT_SYMBOL(MCA_bus); #ifdef CONFIG_DISCONTIGMEM EXPORT_SYMBOL(node_data); +EXPORT_SYMBOL(physnode_map); #endif #ifdef CONFIG_X86_NUMAQ EXPORT_SYMBOL(xquad_portio); diff -Nru a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c --- a/arch/i386/kernel/i387.c Sat Mar 15 18:40:45 2003 +++ b/arch/i386/kernel/i387.c Sat Mar 15 18:40:45 2003 @@ -52,29 +52,13 @@ * FPU lazy state save handling. */ -static inline void __save_init_fpu( struct task_struct *tsk ) -{ - if ( cpu_has_fxsr ) { - asm volatile( "fxsave %0 ; fnclex" - : "=m" (tsk->thread.i387.fxsave) ); - } else { - asm volatile( "fnsave %0 ; fwait" - : "=m" (tsk->thread.i387.fsave) ); - } - clear_tsk_thread_flag(tsk, TIF_USEDFPU); -} - -void save_init_fpu( struct task_struct *tsk ) -{ - __save_init_fpu(tsk); - stts(); -} - void kernel_fpu_begin(void) { + struct thread_info *thread = current_thread_info(); + preempt_disable(); - if (test_thread_flag(TIF_USEDFPU)) { - __save_init_fpu(current); + if (thread->status & TS_USEDFPU) { + __save_init_fpu(thread->task); return; } clts(); diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sat Mar 15 18:40:41 2003 +++ b/arch/i386/kernel/io_apic.c Sat Mar 15 18:40:41 2003 @@ -221,8 +221,9 @@ # define Dprintk(x...) # endif -extern unsigned long irq_affinity [NR_IRQS]; -int __cacheline_aligned pending_irq_balance_apicid [NR_IRQS]; +extern unsigned long irq_affinity[NR_IRQS]; + +static int __cacheline_aligned pending_irq_balance_apicid[NR_IRQS]; static int irqbalance_disabled = NO_BALANCE_IRQ; static int physical_balance = 0; @@ -251,8 +252,54 @@ #define BALANCED_IRQ_LESS_DELTA (HZ) long balanced_irq_interval = MAX_BALANCED_IRQ_INTERVAL; - -static inline void balance_irq(int cpu, int irq); + +static unsigned long move(int curr_cpu, unsigned long allowed_mask, + unsigned long now, int direction) +{ + int search_idle = 1; + int cpu = curr_cpu; + + goto inside; + + do { + if (unlikely(cpu == curr_cpu)) + search_idle = 0; +inside: + if (direction == 1) { + cpu++; + if (cpu >= NR_CPUS) + cpu = 0; + } else { + cpu--; + if (cpu == -1) + cpu = NR_CPUS-1; + } + } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || + (search_idle && !IDLE_ENOUGH(cpu,now))); + + return cpu; +} + +static inline void balance_irq(int cpu, int irq) +{ + unsigned long now = jiffies; + unsigned long allowed_mask; + unsigned int new_cpu; + + if (irqbalance_disabled) + return; + + allowed_mask = cpu_online_map & irq_affinity[irq]; + new_cpu = move(cpu, allowed_mask, now, 1); + if (cpu != new_cpu) { + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_apicid[irq]=cpu_to_logical_apicid(new_cpu); + spin_unlock_irqrestore(&desc->lock, flags); + } +} static inline void rotate_irqs_among_cpus(unsigned long useful_load_threshold) { @@ -263,7 +310,8 @@ if (!irq_desc[j].action) continue; /* Is it a significant load ? */ - if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < useful_load_threshold) + if (IRQ_DELTA(CPU_TO_PACKAGEINDEX(i),j) < + useful_load_threshold) continue; balance_irq(i, j); } @@ -430,7 +478,8 @@ * We seek the least loaded sibling by making the comparison * (A+B)/2 vs B */ - if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > CPU_IRQ(cpu_sibling_map[min_loaded])) + if (physical_balance && (CPU_IRQ(min_loaded) >> 1) > + CPU_IRQ(cpu_sibling_map[min_loaded])) min_loaded = cpu_sibling_map[min_loaded]; allowed_mask = cpu_online_map & irq_affinity[selected_irq]; @@ -438,11 +487,15 @@ if (target_cpu_mask & allowed_mask) { irq_desc_t *desc = irq_desc + selected_irq; - Dprintk("irq = %d moved to cpu = %d\n", selected_irq, min_loaded); + unsigned long flags; + + Dprintk("irq = %d moved to cpu = %d\n", + selected_irq, min_loaded); /* mark for change destination */ - spin_lock(&desc->lock); - pending_irq_balance_apicid[selected_irq] = cpu_to_logical_apicid(min_loaded); - spin_unlock(&desc->lock); + spin_lock_irqsave(&desc->lock, flags); + pending_irq_balance_apicid[selected_irq] = + cpu_to_logical_apicid(min_loaded); + spin_unlock_irqrestore(&desc->lock, flags); /* Since we made a change, come back sooner to * check for more variation. */ @@ -453,58 +506,16 @@ goto tryanotherirq; not_worth_the_effort: - /* if we did not find an IRQ to move, then adjust the time interval upward */ + /* + * if we did not find an IRQ to move, then adjust the time interval + * upward + */ balanced_irq_interval = min((long)MAX_BALANCED_IRQ_INTERVAL, balanced_irq_interval + BALANCED_IRQ_MORE_DELTA); Dprintk("IRQ worth rotating not found\n"); return; } -static unsigned long move(int curr_cpu, unsigned long allowed_mask, unsigned long now, int direction) -{ - int search_idle = 1; - int cpu = curr_cpu; - - goto inside; - - do { - if (unlikely(cpu == curr_cpu)) - search_idle = 0; -inside: - if (direction == 1) { - cpu++; - if (cpu >= NR_CPUS) - cpu = 0; - } else { - cpu--; - if (cpu == -1) - cpu = NR_CPUS-1; - } - } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || - (search_idle && !IDLE_ENOUGH(cpu,now))); - - return cpu; -} - -static inline void balance_irq (int cpu, int irq) -{ - unsigned long now = jiffies; - unsigned long allowed_mask; - unsigned int new_cpu; - - if (irqbalance_disabled) - return; - - allowed_mask = cpu_online_map & irq_affinity[irq]; - new_cpu = move(cpu, allowed_mask, now, 1); - if (cpu != new_cpu) { - irq_desc_t *desc = irq_desc + irq; - spin_lock(&desc->lock); - pending_irq_balance_apicid[irq] = cpu_to_logical_apicid(new_cpu); - spin_unlock(&desc->lock); - } -} - int balanced_irq(void *unused) { int i; @@ -516,26 +527,32 @@ /* push everything to CPU 0 to give us a starting point. */ for (i = 0 ; i < NR_IRQS ; i++) pending_irq_balance_apicid[i] = cpu_to_logical_apicid(0); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - time_remaining = schedule_timeout(time_remaining); - if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) { - Dprintk("balanced_irq: calling do_irq_balance() %lu\n", jiffies); - do_irq_balance(); - prev_balance_time = jiffies; - time_remaining = balanced_irq_interval; - } - } + +repeat: + set_current_state(TASK_INTERRUPTIBLE); + time_remaining = schedule_timeout(time_remaining); + if (time_after(jiffies, prev_balance_time+balanced_irq_interval)) { + Dprintk("balanced_irq: calling do_irq_balance() %lu\n", + jiffies); + do_irq_balance(); + prev_balance_time = jiffies; + time_remaining = balanced_irq_interval; + } + goto repeat; } static int __init balanced_irq_init(void) { int i; struct cpuinfo_x86 *c; + c = &boot_cpu_data; if (irqbalance_disabled) return 0; - /* Enable physical balance only if more than 1 physical processor is present */ + /* + * Enable physical balance only if more than 1 physical processor + * is present + */ if (smp_num_siblings > 1 && cpu_online_map >> 2) physical_balance = 1; @@ -1150,11 +1167,8 @@ enable_8259A_irq(0); } -void __init UNEXPECTED_IO_APIC(void) +static inline void UNEXPECTED_IO_APIC(void) { - printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n"); - printk(KERN_WARNING " http://bugzilla.kernel.org\n"); - printk(KERN_WARNING " if your kernel is less than 3 months old.\n"); } void __init print_IO_APIC(void) @@ -1566,7 +1580,7 @@ */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; local_irq_enable(); /* Let ten ticks pass... */ diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/irq.c Sat Mar 15 18:40:39 2003 @@ -135,43 +135,47 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jtypename); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - p += seq_printf(p, "%10u ", nmi_count(j)); + seq_printf(p, "%10u ", nmi_count(j)); seq_putc(p, '\n'); #if CONFIG_X86_LOCAL_APIC seq_printf(p, "LOC: "); for (j = 0; j < NR_CPUS; j++) if (cpu_online(j)) - p += seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); + seq_printf(p, "%10u ", irq_stat[j].apic_timer_irqs); seq_putc(p, '\n'); #endif seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c --- a/arch/i386/kernel/microcode.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/microcode.c Sat Mar 15 18:40:40 2003 @@ -372,7 +372,6 @@ ret = (ssize_t)len; } out_fsize: - devfs_set_file_size(devfs_handle, mc_fsize); vfree(microcode); out_unlock: up_write(µcode_rwsem); @@ -388,7 +387,6 @@ if (mc_applied) { int bytes = NR_CPUS * sizeof(struct microcode); - devfs_set_file_size(devfs_handle, 0); kfree(mc_applied); mc_applied = NULL; printk(KERN_INFO "microcode: freed %d bytes\n", bytes); diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c --- a/arch/i386/kernel/numaq.c Sat Mar 15 18:40:43 2003 +++ b/arch/i386/kernel/numaq.c Sat Mar 15 18:40:43 2003 @@ -31,8 +31,7 @@ #include /* These are needed before the pgdat's are created */ -unsigned long node_start_pfn[MAX_NUMNODES]; -unsigned long node_end_pfn[MAX_NUMNODES]; +extern long node_start_pfn[], node_end_pfn[]; #define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT)) @@ -64,26 +63,6 @@ } } } - -/* - * ----------------------------------------- - * - * functions related to physnode_map - * - * ----------------------------------------- - */ -/* - * physnode_map keeps track of the physical memory layout of the - * numaq nodes on a 256Mb break (each element of the array will - * represent 256Mb of memory and will be marked by the node id. so, - * if the first gig is on node 0, and the second gig is on node 1 - * physnode_map will contain: - * physnode_map[0-3] = 0; - * physnode_map[4-7] = 1; - * physnode_map[8- ] = -1; - */ -int physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; -EXPORT_SYMBOL(physnode_map); /* * for each node mark the regions diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/kernel/process.c Sat Mar 15 18:40:39 2003 @@ -275,6 +275,15 @@ release_x86_irqs(dead_task); } +/* + * This gets called before we allocate a new thread and copy + * the current task into it. + */ +void prepare_to_copy(struct task_struct *tsk) +{ + unlazy_fpu(tsk); +} + int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) @@ -297,9 +306,6 @@ savesegment(gs,p->thread.gs); tsk = current; - unlazy_fpu(tsk); - struct_cpy(&p->thread.i387, &tsk->thread.i387); - if (unlikely(NULL != tsk->thread.ts_io_bitmap)) { p->thread.ts_io_bitmap = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); if (!p->thread.ts_io_bitmap) diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Sat Mar 15 18:40:41 2003 +++ b/arch/i386/kernel/smpboot.c Sat Mar 15 18:40:41 2003 @@ -966,6 +966,7 @@ if (APIC_init_uniprocessor()) printk(KERN_NOTICE "Local APIC not detected." " Using dummy APIC emulation.\n"); + map_cpu_to_logical_apicid(); return; } diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c --- a/arch/i386/kernel/srat.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/srat.c Sat Mar 15 18:40:40 2003 @@ -57,8 +57,7 @@ static int zholes_size_init; static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES]; -unsigned long node_start_pfn[MAX_NUMNODES]; -unsigned long node_end_pfn[MAX_NUMNODES]; +extern unsigned long node_start_pfn[], node_end_pfn[]; extern void * boot_ioremap(unsigned long, unsigned long); @@ -182,30 +181,19 @@ } } -/* - * physnode_map keeps track of the physical memory layout of the - * numaq nodes on a 256Mb break (each element of the array will - * represent 256Mb of memory and will be marked by the node id. so, - * if the first gig is on node 0, and the second gig is on node 1 - * physnode_map will contain: - * physnode_map[0-3] = 0; - * physnode_map[4-7] = 1; - * physnode_map[8- ] = -1; - */ -int pfnnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; -EXPORT_SYMBOL(pfnnode_map); - -static void __init initialize_pfnnode_map(void) +static void __init initialize_physnode_map(void) { - unsigned long topofchunk, cur = 0; int i; - - for (i = 0; i < num_memory_chunks; i++) { - cur = node_memory_chunk[i].start_pfn; - topofchunk = node_memory_chunk[i].end_pfn; - while (cur < topofchunk) { - pfnnode_map[PFN_TO_ELEMENT(cur)] = node_memory_chunk[i].nid; - cur ++; + unsigned long pfn; + struct node_memory_chunk_s *nmcp; + + /* Run the list of memory chunks and fill in the phymap. */ + nmcp = node_memory_chunk; + for (i = num_memory_chunks; --i >= 0; nmcp++) { + for (pfn = nmcp->start_pfn; pfn <= nmcp->end_pfn; + pfn += PAGES_PER_ELEMENT) + { + physnode_map[pfn / PAGES_PER_ELEMENT] = (int)nmcp->nid; } } } @@ -272,7 +260,7 @@ for (i = 0; i < num_memory_chunks; i++) node_memory_chunk[i].nid = pxm_to_nid_map[node_memory_chunk[i].pxm]; - initialize_pfnnode_map(); + initialize_physnode_map(); printk("pxm bitmap: "); for (i = 0; i < sizeof(pxm_bitmap); i++) { diff -Nru a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c --- a/arch/i386/kernel/sysenter.c Sat Mar 15 18:40:45 2003 +++ b/arch/i386/kernel/sysenter.c Sat Mar 15 18:40:45 2003 @@ -40,8 +40,10 @@ int cpu = get_cpu(); struct tss_struct *tss = init_tss + cpu; + tss->ss1 = __KERNEL_CS; + tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss; wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0); + wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp1, 0); wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); printk("Enabling SEP on CPU %d\n", cpu); diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/traps.c Sat Mar 15 18:40:40 2003 @@ -737,13 +737,14 @@ */ asmlinkage void math_state_restore(struct pt_regs regs) { - struct task_struct *tsk = current; - clts(); /* Allow maths ops (or we recurse) */ + struct thread_info *thread = current_thread_info(); + struct task_struct *tsk = thread->task; + clts(); /* Allow maths ops (or we recurse) */ if (!tsk->used_math) init_fpu(tsk); restore_fpu(tsk); - set_thread_flag(TIF_USEDFPU); /* So we fnsave on switch_to() */ + thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ } #ifndef CONFIG_MATH_EMULATION diff -Nru a/arch/i386/kernel/vm86.c b/arch/i386/kernel/vm86.c --- a/arch/i386/kernel/vm86.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/kernel/vm86.c Sat Mar 15 18:40:40 2003 @@ -291,7 +291,7 @@ tss = init_tss + smp_processor_id(); tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; - disable_sysenter(); + disable_sysenter(tss); tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c --- a/arch/i386/mm/discontig.c Sat Mar 15 18:40:42 2003 +++ b/arch/i386/mm/discontig.c Sat Mar 15 18:40:42 2003 @@ -36,11 +36,36 @@ struct pglist_data *node_data[MAX_NUMNODES]; bootmem_data_t node0_bdata; +/* + * numa interface - we expect the numa architecture specfic code to have + * populated the following initialisation. + * + * 1) numnodes - the total number of nodes configured in the system + * 2) physnode_map - the mapping between a pfn and owning node + * 3) node_start_pfn - the starting page frame number for a node + * 3) node_end_pfn - the ending page fram number for a node + */ + +/* + * physnode_map keeps track of the physical memory layout of a generic + * numa node on a 256Mb break (each element of the array will + * represent 256Mb of memory and will be marked by the node id. so, + * if the first gig is on node 0, and the second gig is on node 1 + * physnode_map will contain: + * + * physnode_map[0-3] = 0; + * physnode_map[4-7] = 1; + * physnode_map[8- ] = -1; + */ +u8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1}; + +unsigned long node_start_pfn[MAX_NUMNODES]; +unsigned long node_end_pfn[MAX_NUMNODES]; + extern unsigned long find_max_low_pfn(void); extern void find_max_pfn(void); extern void one_highpage_init(struct page *, int, int); -extern unsigned long node_start_pfn[], node_end_pfn[]; extern struct e820map e820; extern char _end; extern unsigned long highend_pfn, highstart_pfn; @@ -55,6 +80,36 @@ unsigned long node_remap_offset[MAX_NUMNODES]; void *node_remap_start_vaddr[MAX_NUMNODES]; void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); + +/* + * FLAT - support for basic PC memory model with discontig enabled, essentially + * a single node with all available processors in it with a flat + * memory map. + */ +void __init get_memcfg_numa_flat(void) +{ + int pfn; + + printk("NUMA - single node, flat memory mode\n"); + + /* Run the memory configuration and find the top of memory. */ + find_max_pfn(); + node_start_pfn[0] = 0; + node_end_pfn[0] = max_pfn; + + /* Fill in the physnode_map with our simplistic memory model, + * all memory is in node 0. + */ + for (pfn = node_start_pfn[0]; pfn <= node_end_pfn[0]; + pfn += PAGES_PER_ELEMENT) + { + physnode_map[pfn / PAGES_PER_ELEMENT] = 0; + } + + /* Indicate there is one node available. */ + node_set_online(0); + numnodes = 1; +} /* * Find the highest page frame number we have available for the node diff -Nru a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c --- a/arch/i386/mm/fault.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/mm/fault.c Sat Mar 15 18:40:39 2003 @@ -394,14 +394,14 @@ * Do _not_ use "tsk" here. We might be inside * an interrupt in the middle of a task switch.. */ - int offset = __pgd_offset(address); + int index = pgd_index(address); pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; pte_t *pte_k; asm("movl %%cr3,%0":"=r" (pgd)); - pgd = offset + (pgd_t *)__va(pgd); - pgd_k = init_mm.pgd + offset; + pgd = index + (pgd_t *)__va(pgd); + pgd_k = init_mm.pgd + index; if (!pgd_present(*pgd_k)) goto no_context; diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c --- a/arch/i386/mm/init.c Sat Mar 15 18:40:43 2003 +++ b/arch/i386/mm/init.c Sat Mar 15 18:40:43 2003 @@ -98,26 +98,26 @@ { pgd_t *pgd; pmd_t *pmd; - int pgd_ofs, pmd_ofs; + int pgd_idx, pmd_idx; unsigned long vaddr; vaddr = start; - pgd_ofs = __pgd_offset(vaddr); - pmd_ofs = __pmd_offset(vaddr); - pgd = pgd_base + pgd_ofs; + pgd_idx = pgd_index(vaddr); + pmd_idx = pmd_index(vaddr); + pgd = pgd_base + pgd_idx; - for ( ; (pgd_ofs < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_ofs++) { + for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { if (pgd_none(*pgd)) one_md_table_init(pgd); pmd = pmd_offset(pgd, vaddr); - for (; (pmd_ofs < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_ofs++) { + for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) { if (pmd_none(*pmd)) one_page_table_init(pmd); vaddr += PMD_SIZE; } - pmd_ofs = 0; + pmd_idx = 0; } } @@ -132,17 +132,17 @@ pgd_t *pgd; pmd_t *pmd; pte_t *pte; - int pgd_ofs, pmd_ofs, pte_ofs; + int pgd_idx, pmd_idx, pte_ofs; - pgd_ofs = __pgd_offset(PAGE_OFFSET); - pgd = pgd_base + pgd_ofs; + pgd_idx = pgd_index(PAGE_OFFSET); + pgd = pgd_base + pgd_idx; pfn = 0; - for (; pgd_ofs < PTRS_PER_PGD; pgd++, pgd_ofs++) { + for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { pmd = one_md_table_init(pgd); if (pfn >= max_low_pfn) continue; - for (pmd_ofs = 0; pmd_ofs < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_ofs++) { + for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) { /* Map with big pages if possible, otherwise create normal page tables. */ if (cpu_has_pse) { set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE)); @@ -214,7 +214,7 @@ vaddr = PKMAP_BASE; page_table_range_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c --- a/arch/i386/mm/ioremap.c Sat Mar 15 18:40:40 2003 +++ b/arch/i386/mm/ioremap.c Sat Mar 15 18:40:40 2003 @@ -148,7 +148,7 @@ */ 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.. diff -Nru a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c --- a/arch/i386/mm/pgtable.c Sat Mar 15 18:40:45 2003 +++ b/arch/i386/mm/pgtable.c Sat Mar 15 18:40:45 2003 @@ -64,7 +64,7 @@ pmd_t *pmd; pte_t *pte; - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); if (pgd_none(*pgd)) { BUG(); return; @@ -104,7 +104,7 @@ printk ("set_pmd_pfn: pfn misaligned\n"); return; /* BUG(); */ } - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); if (pgd_none(*pgd)) { printk ("set_pmd_pfn: pgd_none\n"); return; /* BUG(); */ diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c --- a/arch/i386/oprofile/nmi_int.c Sat Mar 15 18:40:44 2003 +++ b/arch/i386/oprofile/nmi_int.c Sat Mar 15 18:40:44 2003 @@ -58,7 +58,7 @@ unsigned int const nr_ctrls = model->num_controls; struct op_msr_group * counters = &msrs->counters; struct op_msr_group * controls = &msrs->controls; - int i; + unsigned int i; for (i = 0; i < nr_ctrs; ++i) { rdmsr(counters->addrs[i], @@ -108,7 +108,7 @@ unsigned int const nr_ctrls = model->num_controls; struct op_msr_group * counters = &msrs->counters; struct op_msr_group * controls = &msrs->controls; - int i; + unsigned int i; for (i = 0; i < nr_ctrls; ++i) { wrmsr(controls->addrs[i], @@ -182,7 +182,7 @@ static int nmi_create_files(struct super_block * sb, struct dentry * root) { - int i; + unsigned int i; for (i = 0; i < model->num_counters; ++i) { struct dentry * dir; diff -Nru a/arch/i386/oprofile/op_model_athlon.c b/arch/i386/oprofile/op_model_athlon.c --- a/arch/i386/oprofile/op_model_athlon.c Sat Mar 15 18:40:43 2003 +++ b/arch/i386/oprofile/op_model_athlon.c Sat Mar 15 18:40:43 2003 @@ -104,10 +104,11 @@ if (CTR_OVERFLOWED(low)) { oprofile_add_sample(eip, is_kernel, i, cpu); CTR_WRITE(reset_value[i], msrs, i); - return 1; } } - return 0; + + /* See op_model_ppro.c */ + return 1; } diff -Nru a/arch/i386/oprofile/op_model_p4.c b/arch/i386/oprofile/op_model_p4.c --- a/arch/i386/oprofile/op_model_p4.c Sat Mar 15 18:40:39 2003 +++ b/arch/i386/oprofile/op_model_p4.c Sat Mar 15 18:40:39 2003 @@ -389,7 +389,7 @@ static void p4_fill_in_addresses(struct op_msrs * const msrs) { - int i; + unsigned int i; unsigned int addr, stag; setup_num_counters(); @@ -608,13 +608,14 @@ CTR_WRITE(reset_value[i], real); /* P4 quirk: you have to re-unmask the apic vector */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - return 1; } } /* P4 quirk: you have to re-unmask the apic vector */ apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); - return 0; + + /* See op_model_ppro.c */ + return 1; } diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c --- a/arch/i386/oprofile/op_model_ppro.c Sat Mar 15 18:40:43 2003 +++ b/arch/i386/oprofile/op_model_ppro.c Sat Mar 15 18:40:43 2003 @@ -98,10 +98,17 @@ if (CTR_OVERFLOWED(low)) { oprofile_add_sample(eip, is_kernel, i, cpu); CTR_WRITE(reset_value[i], msrs, i); - return 1; } } - return 0; + + /* We can't work out if we really handled an interrupt. We + * might have caught a *second* counter just after overflowing + * the interrupt for this counter then arrives + * and we don't find a counter that's overflowed, so we + * would return 0 and get dazed + confused. Instead we always + * assume we found an overflow. This sucks. + */ + return 1; } diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c Sat Mar 15 18:40:45 2003 +++ b/arch/i386/pci/irq.c Sat Mar 15 18:40:45 2003 @@ -804,6 +804,7 @@ int pirq_enable_irq(struct pci_dev *dev) { u8 pin; + extern int interrupt_line_quirk; pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { char *msg; @@ -813,9 +814,17 @@ msg = ""; else msg = " Please try using pci=biosirq."; + + /* With IDE legacy devices the IRQ lookup failure is not a problem.. */ + if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5)) + return 0; + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", 'A' + pin - 1, dev->slot_name, msg); } - + /* VIA bridges use interrupt line for apic/pci steering across + the V-Link */ + else if (interrupt_line_quirk) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); return 0; } diff -Nru a/arch/i386/vmlinux.lds.S b/arch/i386/vmlinux.lds.S --- a/arch/i386/vmlinux.lds.S Sat Mar 15 18:40:40 2003 +++ b/arch/i386/vmlinux.lds.S Sat Mar 15 18:40:40 2003 @@ -74,6 +74,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/Kconfig Sat Mar 15 18:40:44 2003 @@ -22,11 +22,7 @@ bool default y -config SWAP - bool - default y - -config RWSEM_GENERIC_SPINLOCK +config RWSEM_XCHGADD_ALGORITHM bool default y @@ -424,6 +420,18 @@ If you don't know what to do here, say N. +config PREEMPT + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. + config IA32_SUPPORT bool "Support running of Linux/x86 binaries" help @@ -874,6 +882,12 @@ and certain other kinds of spinlock errors commonly made. This is best used in conjunction with the NMI watchdog so that spinlock deadlocks are also debuggable. + +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. config IA64_DEBUG_CMPXCHG bool "Turn on compare-and-exchange bug checking (slow!)" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Sat Mar 15 18:40:39 2003 +++ b/arch/ia64/Makefile Sat Mar 15 18:40:39 2003 @@ -52,18 +52,19 @@ core-$(CONFIG_IA64_HP_ZX1) += arch/ia64/dig/ core-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/kernel/ \ arch/ia64/sn/io/ \ + arch/ia64/sn/io/sn2/ \ + arch/ia64/sn/io/sn2/pcibr/ \ arch/ia64/sn/kernel/sn2/ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_SGI_SN) += arch/ia64/sn/fakeprom/ boot := arch/ia64/boot tools := arch/ia64/tools .PHONY: boot compressed include/asm-ia64/offsets.h -all: vmlinux +all: prepare vmlinux compressed: vmlinux.gz diff -Nru a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c --- a/arch/ia64/hp/sim/simscsi.c Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/hp/sim/simscsi.c Sat Mar 15 18:40:41 2003 @@ -156,7 +156,7 @@ if (sc->request_bufflen < req.len) return; - stat.fd = desc[sc->target]; + stat.fd = desc[sc->device->id]; if (DBG) printk("simscsi_%s @ %lx (off %lx)\n", mode == SSC_READ ? "read":"write", req.addr, offset); @@ -178,7 +178,7 @@ struct disk_stat stat; struct disk_req req; - stat.fd = desc[sc->target]; + stat.fd = desc[sc->device->id]; while (list_len) { req.addr = __pa(page_address(sl->page) + sl->offset); @@ -259,6 +259,7 @@ int simscsi_queuecommand (Scsi_Cmnd *sc, void (*done)(Scsi_Cmnd *)) { + unsigned int target_id = sc->device->id; char fname[MAX_ROOT_LEN+16]; size_t disk_size; char *buf; @@ -267,21 +268,21 @@ if (DBG) printk("simscsi_queuecommand: target=%d,cmnd=%u,sc=%lu,sp=%lx,done=%p\n", - sc->target, sc->cmnd[0], sc->serial_number, sp, done); + target_id, sc->cmnd[0], sc->serial_number, sp, done); #endif sc->result = DID_BAD_TARGET << 16; sc->scsi_done = done; - if (sc->target <= 15 && sc->lun == 0) { + if (target_id <= 15 && sc->device->lun == 0) { switch (sc->cmnd[0]) { case INQUIRY: if (sc->request_bufflen < 35) { break; } - sprintf (fname, "%s%c", simscsi_root, 'a' + sc->target); - desc[sc->target] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, - 0, 0, SSC_OPEN); - if (desc[sc->target] < 0) { + sprintf (fname, "%s%c", simscsi_root, 'a' + target_id); + desc[target_id] = ia64_ssc(__pa(fname), SSC_READ_ACCESS|SSC_WRITE_ACCESS, + 0, 0, SSC_OPEN); + if (desc[target_id] < 0) { /* disk doesn't exist... */ break; } @@ -303,37 +304,37 @@ break; case READ_6: - if (desc[sc->target] < 0 ) + if (desc[target_id] < 0 ) break; simscsi_readwrite6(sc, SSC_READ); break; case READ_10: - if (desc[sc->target] < 0 ) + if (desc[target_id] < 0 ) break; simscsi_readwrite10(sc, SSC_READ); break; case WRITE_6: - if (desc[sc->target] < 0) + if (desc[target_id] < 0) break; simscsi_readwrite6(sc, SSC_WRITE); break; case WRITE_10: - if (desc[sc->target] < 0) + if (desc[target_id] < 0) break; simscsi_readwrite10(sc, SSC_WRITE); break; case READ_CAPACITY: - if (desc[sc->target] < 0 || sc->request_bufflen < 8) { + if (desc[target_id] < 0 || sc->request_bufflen < 8) { break; } buf = sc->request_buffer; - disk_size = simscsi_get_disk_size(desc[sc->target]); + disk_size = simscsi_get_disk_size(desc[target_id]); /* pretend to be a 1GB disk (partition table contains real stuff): */ buf[0] = (disk_size >> 24) & 0xff; diff -Nru a/arch/ia64/hp/sim/simserial.c b/arch/ia64/hp/sim/simserial.c --- a/arch/ia64/hp/sim/simserial.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/hp/sim/simserial.c Sat Mar 15 18:40:42 2003 @@ -63,7 +63,6 @@ static char *serial_name = "SimSerial driver"; static char *serial_version = "0.6"; -static spinlock_t serial_lock = SPIN_LOCK_UNLOCKED; /* * This has been extracted from asm/serial.h. We need one eventually but @@ -235,14 +234,14 @@ if (!tty || !info->xmit.buf) return; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) { - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } info->xmit.buf[info->xmit.head] = ch; info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) @@ -250,7 +249,8 @@ int count; unsigned long flags; - spin_lock_irqsave(&serial_lock, flags); + + local_irq_save(flags); if (info->x_char) { char c = info->x_char; @@ -293,7 +293,7 @@ info->xmit.tail += count; } out: - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } static void rs_flush_chars(struct tty_struct *tty) @@ -334,7 +334,7 @@ break; } - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); { c1 = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); @@ -344,7 +344,7 @@ info->xmit.head = ((info->xmit.head + c) & (SERIAL_XMIT_SIZE-1)); } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); buf += c; count -= c; @@ -352,7 +352,7 @@ } up(&tmp_buf_sem); } else { - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); while (1) { c = CIRC_SPACE_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); if (count < c) @@ -367,7 +367,7 @@ count -= c; ret += c; } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } /* * Hey, we transmit directly from here in our case @@ -398,9 +398,9 @@ struct async_struct *info = (struct async_struct *)tty->driver_data; unsigned long flags; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); info->xmit.head = info->xmit.tail = 0; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); wake_up_interruptible(&tty->write_wait); @@ -573,7 +573,7 @@ state->irq); #endif - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); { /* * First unlink the serial port from the IRQ chain... @@ -611,7 +611,7 @@ info->flags &= ~ASYNC_INITIALIZED; } - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); } /* @@ -634,13 +634,13 @@ state = info->state; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (tty_hung_up_p(filp)) { #ifdef SIMSERIAL_DEBUG printk("rs_close: hung_up\n"); #endif MOD_DEC_USE_COUNT; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } #ifdef SIMSERIAL_DEBUG @@ -665,11 +665,11 @@ } if (state->count) { MOD_DEC_USE_COUNT; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return; } info->flags |= ASYNC_CLOSING; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); /* * Now we wait for the transmit buffer to clear; and we notify @@ -776,7 +776,7 @@ if (!page) return -ENOMEM; - spin_lock_irqsave(&serial_lock, flags); + local_irq_save(flags); if (info->flags & ASYNC_INITIALIZED) { free_page(page); @@ -857,11 +857,11 @@ } info->flags |= ASYNC_INITIALIZED; - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return 0; errout: - spin_unlock_irqrestore(&serial_lock, flags); + local_irq_restore(flags); return retval; } diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S --- a/arch/ia64/ia32/ia32_entry.S Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/ia32/ia32_entry.S Sat Mar 15 18:40:42 2003 @@ -300,7 +300,7 @@ data8 compat_sys_statfs data8 compat_sys_fstatfs /* 100 */ data8 sys32_ioperm - data8 sys32_socketcall + data8 compat_sys_socketcall data8 sys_syslog data8 compat_sys_setitimer data8 compat_sys_getitimer /* 105 */ @@ -424,6 +424,26 @@ data8 sys_ni_syscall /* reserved for Security */ data8 sys_gettid data8 sys_readahead /* 225 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 230 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 235 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 compat_sys_futex /* 240 */ + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall + data8 sys_ni_syscall /* 245 */ data8 sys_ni_syscall data8 sys_ni_syscall data8 sys_ni_syscall diff -Nru a/arch/ia64/ia32/ia32_ioctl.c b/arch/ia64/ia32/ia32_ioctl.c --- a/arch/ia64/ia32/ia32_ioctl.c Sat Mar 15 18:40:43 2003 +++ b/arch/ia64/ia32/ia32_ioctl.c Sat Mar 15 18:40:43 2003 @@ -97,11 +97,9 @@ int info; /* [o] auxiliary information */ } sg_io_hdr32_t; /* 64 bytes long (on IA32) */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov; int i; @@ -136,7 +134,7 @@ static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32) { - struct iovec32 *uiov = (struct iovec32 *) P(uptr32); + struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32); sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; int i; diff -Nru a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c --- a/arch/ia64/ia32/ia32_support.c Sat Mar 15 18:40:39 2003 +++ b/arch/ia64/ia32/ia32_support.c Sat Mar 15 18:40:39 2003 @@ -93,7 +93,7 @@ { unsigned long eflag, fsr, fcr, fir, fdr, csd, ssd, tssd; struct pt_regs *regs = ia64_task_regs(t); - int nr = smp_processor_id(); /* LDT and TSS depend on CPU number: */ + int nr = get_cpu(); /* LDT and TSS depend on CPU number: */ eflag = t->thread.eflag; fsr = t->thread.fsr; @@ -119,6 +119,7 @@ regs->r17 = (_TSS(nr) << 48) | (_LDT(nr) << 32) | (__u32) regs->r17; regs->r30 = load_desc(_LDT(nr)); /* LDTD */ + put_cpu(); } /* diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/ia32/sys_ia32.c Sat Mar 15 18:40:42 2003 @@ -924,12 +924,11 @@ (struct compat_timeval *) A(a.tvp)); } -struct iovec32 { unsigned int iov_base; int iov_len; }; asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long); asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type) +get_compat_iovec (struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type) { int i; u32 buf, len; @@ -939,7 +938,7 @@ if (!count) return 0; - if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return NULL; if (count > UIO_MAXIOV) return NULL; @@ -971,14 +970,14 @@ } asmlinkage long -sys32_readv (int fd, struct iovec32 *vector, u32 count) +sys32_readv (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -990,14 +989,14 @@ } asmlinkage long -sys32_writev (int fd, struct iovec32 *vector, u32 count) +sys32_writev (int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; long ret; mm_segment_t old_fs = get_fs(); - iov = get_iovec32(vector, iovstack, count, VERIFY_READ); + iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ); if (!iov) return -EFAULT; set_fs(KERNEL_DS); @@ -1080,701 +1079,6 @@ } /* - * Declare the IA32 version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) -#define CMSG32_DATA(cmsg) \ - ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) \ - (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) \ - ((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -static inline struct cmsghdr32 * -__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len) -{ - struct cmsghdr32 * ptr; - - ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len)); - if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size) - return NULL; - return ptr; -} - -static inline struct cmsghdr32 * -cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len) -{ - return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len); -} - -static inline int -get_msghdr32 (struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return -EFAULT; - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return ret ? -EFAULT : 0; -} - -/* - * There is a lot of hair here because the alignment rules (and thus placement) of cmsg - * headers and length are different for 32-bit apps. -DaveM - */ -static int -get_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize) -{ - struct cmsghdr *kcmsg, *kcmsg_base; - __kernel_size_t kcmlen, tmp; - compat_size_t ucmlen; - struct cmsghdr32 *ucmsg; - long err; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - if (get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen) - > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* - * The kcmlen holds the 64-bit version of the control length. It may not be - * modified as we do not stick it into the kmsg until we have successfully copied - * over all of the data from the user. - */ - if (kcmlen > *bufsize) { - *bufsize = kcmlen; - kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL); - } - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - err = get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))); - if (err) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if (kcmsg_base != (struct cmsghdr *)stackbuf) - sock_kfree_s(sk, kcmsg_base, kcmlen); - return -EFAULT; -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32 (struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if (m->msg_namelen) { - if (mode == VERIFY_READ) { - err = move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if (err < 0) - goto out; - } - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov = iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -static void -put_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, - cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void -scm_detach_fds32 (struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) - / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); - i < fdmax; - i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - current->files->fd[new_fd] = fp[i]; - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* - * In these cases we (currently) can just copy to data over verbatim because all CMSGs - * created by the kernel have well defined types which have the same layout in both the - * 32-bit and 64-bit API. One must add some special cased conversions here if we start - * sending control messages with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void -cmsg32_recvmsg_fixup (struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - long err; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if (workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while (((unsigned long)ucmsg) < ((unsigned long)kmsg->msg_control)) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* - * UCMSG is the 64-bit format CMSG entry in user-space. KCMSG32 is within - * the kernel space temporary buffer we use to convert into a 32-bit style - * CMSG. - */ - err = get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - err |= get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - err |= get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - if (err) - goto fail2; - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - if (copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz)) - goto fail2; - - kmsg->msg_control = (struct cmsghdr *) (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - kfree(workbuf); - return; - - fail2: - kfree(workbuf); - fail: - /* - * If we leave the 64-bit format CMSG chunks in there, the application could get - * confused and crash. So to ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ -/* - * BSD sendmsg interface - */ - -int -sys32_sendmsg (int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, iov_size, total_len; - size_t ctl_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - if (msg_sys.msg_controllen) { - ctl_len = sizeof(ctl); - err = get_cmsghdr32(&msg_sys, ctl_buf, sock->sk, &ctl_len); - if (err) - goto out_freeiov; - ctl_buf = msg_sys.msg_control; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err = -EFAULT; - if (get_msghdr32(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - - /* XXX This code needs massive updating... -DaveM */ - lock_kernel(); - { - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &msg_sys; - si->size = total_len; - si->flags = flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &msg_sys, total_len, - flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if (err < 0) - goto out_unlock_freeiov; - - len = err; - if (!msg_sys.msg_control) { - if (sock->passcred || si->scm->fp) - msg_sys.msg_flags |= MSG_CTRUNC; - if (si->scm->fp) - __scm_destroy(si->scm); - } else { - /* - * If recvmsg processing itself placed some control messages into - * user space, it's is using 64-bit CMSG processing, so we need to - * fix it up before we tack on more stuff. - */ - if ((unsigned long) msg_sys.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&msg_sys, cmsg_ptr); - - /* Wheee... */ - if (sock->passcred) - put_cmsg32(&msg_sys, SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if (si->scm->fp != NULL) - scm_detach_fds32(&msg_sys, si->scm); - } - } - unlock_kernel(); - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - - out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); - out_put: - sockfd_put(sock); - out: - return err; - - out_unlock_freeiov: - goto out_freeiov; -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static const unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); - -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long -sys32_socketcall (int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *) A(a1), a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; -} - -/* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * * This is really horribly ugly. @@ -3151,6 +2455,7 @@ asmlinkage long sys32_sysctl (struct sysctl32 *args) { +#ifdef CONFIG_SYSCTL struct sysctl32 a32; mm_segment_t old_fs = get_fs (); void *oldvalp, *newvalp; @@ -3188,6 +2493,9 @@ return -EFAULT; return ret; +#else + return -ENOSYS; +#endif } asmlinkage long @@ -3433,8 +2741,12 @@ u32 bufferram; u32 totalswap; u32 freeswap; - unsigned short procs; - char _f[22]; + u16 procs; + u16 pad; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[8]; }; asmlinkage long @@ -3463,6 +2775,9 @@ err |= __put_user(s.totalswap, &info->totalswap); err |= __put_user(s.freeswap, &info->freeswap); err |= __put_user(s.procs, &info->procs); + err |= __put_user (s.totalhigh, &info->totalhigh); + err |= __put_user (s.freehigh, &info->freehigh); + err |= __put_user (s.mem_unit, &info->mem_unit); if (err) return -EFAULT; return ret; diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/kernel/acpi.c Sat Mar 15 18:40:42 2003 @@ -55,6 +55,7 @@ asm (".weak iosapic_override_isa_irq"); asm (".weak iosapic_register_platform_intr"); asm (".weak iosapic_init"); +asm (".weak iosapic_system_init"); asm (".weak iosapic_version"); void (*pm_idle) (void); @@ -182,7 +183,9 @@ #define ACPI_MAX_PLATFORM_INTERRUPTS 256 /* Array to record platform interrupt vectors for generic interrupt routing. */ -int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 }; +int platform_intr_list[ACPI_MAX_PLATFORM_INTERRUPTS] = { + [0 ... ACPI_MAX_PLATFORM_INTERRUPTS - 1] = -1 +}; enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_IOSAPIC; @@ -291,40 +294,6 @@ static int __init -acpi_find_iosapic (unsigned int gsi, u32 *gsi_base, char **iosapic_address) -{ - struct acpi_table_iosapic *iosapic; - int ver; - int max_pin; - char *p; - char *end; - - if (!gsi_base || !iosapic_address) - return -ENODEV; - - p = (char *) (acpi_madt + 1); - end = p + (acpi_madt->header.length - sizeof(struct acpi_table_madt)); - - while (p < end) { - if (*p == ACPI_MADT_IOSAPIC) { - iosapic = (struct acpi_table_iosapic *) p; - - *gsi_base = iosapic->global_irq_base; - *iosapic_address = ioremap(iosapic->address, 0); - - ver = iosapic_version(*iosapic_address); - max_pin = (ver >> 16) & 0xff; - - if ((gsi - *gsi_base) <= max_pin) - return 0; /* Found it! */ - } - p += p[1]; - } - return -ENODEV; -} - - -static int __init acpi_parse_iosapic (acpi_table_entry_header *header) { struct acpi_table_iosapic *iosapic; @@ -335,16 +304,9 @@ acpi_table_print_madt_entry(header); - if (iosapic_init) { -#ifndef CONFIG_ITANIUM - /* PCAT_COMPAT flag indicates dual-8259 setup */ - iosapic_init(iosapic->address, iosapic->global_irq_base, - acpi_madt->flags.pcat_compat); -#else - /* Firmware on old Itanium systems is broken */ - iosapic_init(iosapic->address, iosapic->global_irq_base, 1); -#endif - } + if (iosapic_init) + iosapic_init(iosapic->address, iosapic->global_irq_base); + return 0; } @@ -354,8 +316,6 @@ { struct acpi_table_plat_int_src *plintsrc; int vector; - u32 gsi_base; - char *iosapic_address; plintsrc = (struct acpi_table_plat_int_src *) header; if (!plintsrc) @@ -368,11 +328,6 @@ return -ENODEV; } - if (acpi_find_iosapic(plintsrc->global_irq, &gsi_base, &iosapic_address)) { - printk(KERN_WARNING PREFIX "IOSAPIC not found\n"); - return -ENODEV; - } - /* * Get vector assignment for this interrupt, set attributes, * and program the IOSAPIC routing table. @@ -382,10 +337,8 @@ plintsrc->iosapic_vector, plintsrc->eid, plintsrc->id, - (plintsrc->flags.polarity == 1) ? 1 : 0, - (plintsrc->flags.trigger == 1) ? 1 : 0, - gsi_base, - iosapic_address); + (plintsrc->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); platform_intr_list[plintsrc->type] = vector; return 0; @@ -408,8 +361,8 @@ return 0; iosapic_override_isa_irq(p->bus_irq, p->global_irq, - (p->flags.polarity == 1) ? 1 : 0, - (p->flags.trigger == 1) ? 1 : 0); + (p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + (p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return 0; } @@ -439,7 +392,13 @@ acpi_madt = (struct acpi_table_madt *) __va(phys_addr); /* remember the value for reference after free_initmem() */ +#ifdef CONFIG_ITANIUM + has_8259 = 1; /* Firmware on old Itanium systems is broken */ +#else has_8259 = acpi_madt->flags.pcat_compat; +#endif + if (iosapic_system_init) + iosapic_system_init(has_8259); /* Get base address of IPI Message Block */ @@ -571,7 +530,7 @@ } void __init -acpi_numa_arch_fixup(void) +acpi_numa_arch_fixup (void) { int i, j, node_from, node_to; @@ -618,7 +577,7 @@ if (!pxm_bit_test(j)) continue; node_to = pxm_to_nid_map[j]; - node_distance(node_from, node_to) = + node_distance(node_from, node_to) = slit_table->entry[i*slit_table->localities + j]; } } @@ -639,8 +598,7 @@ { struct acpi_table_header *fadt_header; struct fadt_descriptor_rev2 *fadt; - u32 sci_irq, gsi_base; - char *iosapic_address; + u32 sci_irq; if (!phys_addr || !size) return -EINVAL; @@ -662,8 +620,7 @@ if (has_8259 && sci_irq < 16) return 0; /* legacy, no setup required */ - if (!acpi_find_iosapic(sci_irq, &gsi_base, &iosapic_address)) - iosapic_register_intr(sci_irq, 0, 0, gsi_base, iosapic_address); + iosapic_register_intr(sci_irq, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); return 0; } @@ -717,8 +674,6 @@ if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) { - u32 gsi_base; - char *iosapic_address; int vector; /* We have a UART in memory space with an SAPIC interrupt */ @@ -728,11 +683,7 @@ (spcr->global_int[1] << 8) | (spcr->global_int[0]) ); - /* Which iosapic does this interrupt belong to? */ - - if (!acpi_find_iosapic(gsi, &gsi_base, &iosapic_address)) - vector = iosapic_register_intr(gsi, 1, 1, - gsi_base, iosapic_address); + vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } return 0; } @@ -741,7 +692,7 @@ int __init -acpi_boot_init (char *cmdline) +acpi_boot_init (void) { /* @@ -812,20 +763,20 @@ smp_boot_data.cpu_count = total_cpus; smp_build_cpu_map(); -#ifdef CONFIG_NUMA +# ifdef CONFIG_NUMA build_cpu_to_node_map(); -#endif +# endif #endif /* Make boot-up look pretty */ printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus); return 0; } +/* + * PCI Interrupt Routing + */ -/* -------------------------------------------------------------------------- - PCI Interrupt Routing - -------------------------------------------------------------------------- */ - +#ifdef CONFIG_PCI int __init acpi_get_prt (struct pci_vector_struct **vectors, int *count) { @@ -866,6 +817,7 @@ *count = acpi_prt.count; return 0; } +#endif /* CONFIG_PCI */ /* Assume IA64 always use I/O SAPIC */ @@ -888,12 +840,10 @@ return gsi_to_vector(irq); } -int __init +int acpi_register_irq (u32 gsi, u32 polarity, u32 trigger) { int vector = 0; - u32 irq_base; - char *iosapic_address; if (acpi_madt->flags.pcat_compat && (gsi < 16)) return isa_irq_to_vector(gsi); @@ -901,12 +851,9 @@ if (!iosapic_register_intr) return 0; - /* Find the IOSAPIC */ - if (!acpi_find_iosapic(gsi, &irq_base, &iosapic_address)) { - /* Turn it on */ - vector = iosapic_register_intr (gsi, polarity, trigger, - irq_base, iosapic_address); - } + /* Turn it on */ + vector = iosapic_register_intr (gsi, polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW, + trigger ? IOSAPIC_EDGE : IOSAPIC_LEVEL); return vector; } diff -Nru a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S --- a/arch/ia64/kernel/entry.S Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/kernel/entry.S Sat Mar 15 18:40:40 2003 @@ -586,10 +586,21 @@ // work.need_resched etc. mustn't get changed by this CPU before it returns to // user- or fsys-mode: (pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk +#ifdef CONFIG_PREEMPT + rsm psr.i // disable interrupts + adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) ld4 r21=[r20] // preempt_count ->r21 + ;; +(pKStk) cmp4.eq p6,p0=r21,r0 // p6 <- preempt_count == 0 + ;; +#else /* CONFIG_PREEMPT */ (pUStk) rsm psr.i ;; (pUStk) adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 ;; +#endif /* CONFIG_PREEMPT */ .work_processed: (p6) ld4 r18=[r17] // load current_thread_info()->flags adds r2=PT(R8)+16,r12 @@ -701,7 +712,7 @@ * NOTE: alloc, loadrs, and cover can't be predicated. */ (pNonSys) br.cond.dpnt dont_preserve_current_frame - cover // add current frame into dirty partition + cover // add current frame into dirty partition and set cr.ifs ;; mov r19=ar.bsp // get new backing store pointer sub r16=r16,r18 // krbs = old bsp - size of dirty partition @@ -727,7 +738,7 @@ # define Nregs 14 #endif alloc loc0=ar.pfs,2,Nregs-2,2,0 - shr.u loc1=r18,9 // RNaTslots <= dirtySize / (64*8) + 1 + shr.u loc1=r18,9 // RNaTslots <= floor(dirtySize / (64*8)) sub r17=r17,r18 // r17 = (physStackedSize + 8) - dirtySize ;; mov ar.rsc=r19 // load ar.rsc to be used for "loadrs" @@ -774,13 +785,13 @@ ;; mov loc3=0 mov loc4=0 - mov loc9=0 mov loc5=0 mov loc6=0 + mov loc7=0 (pRecurse) br.call.sptk.many b6=rse_clear_invalid ;; - mov loc7=0 mov loc8=0 + mov loc9=0 cmp.ne pReturn,p0=r0,in1 // if recursion count != 0, we need to do a br.ret mov loc10=0 mov loc11=0 @@ -810,15 +821,27 @@ .work_pending: tbit.z p6,p0=r18,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify +#ifdef CONFIG_PREEMPT +(pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 + ;; +(pKStk) st4 [r20]=r21 + ssm psr.i // enable interrupts +#endif + #if __GNUC__ < 3 br.call.spnt.many rp=invoke_schedule #else br.call.spnt.many rp=schedule #endif .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 - rsm psr.i + rsm psr.i // disable interrupts ;; adds r17=TI_FLAGS+IA64_TASK_SIZE,r13 +#if CONFIG_PREEMPT +(pKStk) adds r20=TI_PRE_COUNT+IA64_TASK_SIZE,r13 + ;; +(pKStk) st4 [r20]=r0 // preempt_count() <- 0 +#endif br.cond.sptk.many .work_processed // re-check .notify: @@ -904,13 +927,14 @@ mov r9=ar.unat mov loc0=rp // save return address mov out0=0 // there is no "oldset" - adds out1=0,sp // out1=&sigscratch + adds out1=8,sp // out1=&sigscratch->ar_pfs (pSys) mov out2=1 // out2==1 => we're in a syscall ;; (pNonSys) mov out2=0 // out2==0 => not a syscall .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out1]=loc1,-8 // save ar.pfs, out1=&sigscratch .body br.call.sptk.many rp=do_notify_resume_user .ret15: .restore sp @@ -931,11 +955,12 @@ mov loc0=rp // save return address mov out0=in0 // mask mov out1=in1 // sigsetsize - adds out2=0,sp // out2=&sigscratch + adds out2=8,sp // out2=&sigscratch->ar_pfs ;; .fframe 16 .spillpsp ar.unat, 16 // (note that offset is relative to psp+0x10!) st8 [sp]=r9,-16 // allocate space for ar.unat and save it + st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch .body br.call.sptk.many rp=ia64_rt_sigsuspend .ret17: .restore sp @@ -1242,7 +1267,7 @@ data8 sys_sched_setaffinity data8 sys_sched_getaffinity data8 sys_set_tid_address - data8 ia64_ni_syscall + data8 sys_fadvise64 data8 ia64_ni_syscall // 1235 data8 sys_exit_group data8 sys_lookup_dcookie @@ -1256,15 +1281,15 @@ data8 sys_epoll_wait // 1245 data8 sys_restart_syscall data8 sys_semtimedop - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall // 1250 - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall - data8 ia64_ni_syscall // 1255 - data8 ia64_ni_syscall + data8 sys_timer_create + data8 sys_timer_settime + data8 sys_timer_gettime // 1250 + data8 sys_timer_getoverrun + data8 sys_timer_delete + data8 sys_clock_settime + data8 sys_clock_gettime + data8 sys_clock_getres // 1255 + data8 sys_clock_nanosleep data8 ia64_ni_syscall data8 ia64_ni_syscall data8 ia64_ni_syscall diff -Nru a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S --- a/arch/ia64/kernel/fsys.S Sat Mar 15 18:40:39 2003 +++ b/arch/ia64/kernel/fsys.S Sat Mar 15 18:40:39 2003 @@ -3,11 +3,16 @@ * * Copyright (C) 2003 Hewlett-Packard Co * David Mosberger-Tang + * + * 18-Feb-03 louisk Implement fsys_gettimeofday(). + * 28-Feb-03 davidm Fixed several bugs in fsys_gettimeofday(). Tuned it some more, + * probably broke it along the way... ;-) */ #include #include #include +#include #include /* @@ -123,6 +128,183 @@ br.ret.sptk.many b6 END(fsys_set_tid_address) +/* + * Note 1: This routine uses floating-point registers, but only with registers that + * operate on integers. Because of that, we don't need to set ar.fpsr to the + * kernel default value. + * + * Note 2: For now, we will assume that all CPUs run at the same clock-frequency. + * If that wasn't the case, we would have to disable preemption (e.g., + * by disabling interrupts) between reading the ITC and reading + * local_cpu_data->nsec_per_cyc. + * + * Note 3: On platforms where the ITC-drift bit is set in the SAL feature vector, + * we ought to either skip the ITC-based interpolation or run an ntp-like + * daemon to keep the ITCs from drifting too far apart. + */ +ENTRY(fsys_gettimeofday) + add r9=TI_FLAGS+IA64_TASK_SIZE,r16 + movl r3=THIS_CPU(cpu_info) + + mov.m r31=ar.itc // put time stamp into r31 (ITC) == now (35 cyc) + movl r19=xtime // xtime is a timespec struct + ;; + +#ifdef CONFIG_SMP + movl r10=__per_cpu_offset + ;; + ld8 r10=[r10] // r10 <- __per_cpu_offset[0] + movl r21=cpu_info__per_cpu + ;; + add r10=r21, r10 // r10 <- &cpu_data(time_keeper_id) +#else + mov r10=r3 +#endif + ld4 r9=[r9] + movl r17=xtime_lock + ;; + + // r32, r33 should contain the 2 args of gettimeofday + adds r21=IA64_CPUINFO_ITM_NEXT_OFFSET, r10 + mov r2=-1 + tnat.nz p6,p7=r32 // guard against NaT args + ;; + + adds r10=IA64_CPUINFO_ITM_DELTA_OFFSET, r10 +(p7) tnat.nz p6,p0=r33 +(p6) br.cond.spnt.few .fail + + adds r8=IA64_CPUINFO_NSEC_PER_CYC_OFFSET, r3 + movl r24=2361183241434822607 // for division hack (only for / 1000) + ;; + + ldf8 f7=[r10] // f7 now contains itm_delta + setf.sig f11=r2 + adds r10=8, r32 + + adds r20=IA64_TIMESPEC_TV_NSEC_OFFSET, r19 // r20 = &xtime->tv_nsec + movl r26=jiffies + + setf.sig f9=r24 // f9 is used for division hack + movl r27=wall_jiffies + + and r9=TIF_ALLWORK_MASK,r9 + movl r25=last_nsec_offset + ;; + + /* + * Verify that we have permission to write to struct timeval. Note: + * Another thread might unmap the mapping before we actually get + * to store the result. That's OK as long as the stores are also + * protect by EX(). + */ +EX(.fail, probe.w.fault r32, 3) // this must come _after_ NaT-check +EX(.fail, probe.w.fault r10, 3) // this must come _after_ NaT-check + nop 0 + + ldf8 f10=[r8] // f10 <- local_cpu_data->nsec_per_cyc value + cmp.ne p8, p0=0, r9 +(p8) br.spnt.many fsys_fallback_syscall + ;; +.retry: // *** seq = read_seqbegin(&xtime_lock); *** + ld4.acq r23=[r17] // since &xtime_lock == &xtime_lock->sequence + ld8 r14=[r25] // r14 (old) = last_nsec_offset + + ld8 r28=[r26] // r28 = jiffies + ld8 r29=[r27] // r29 = wall_jiffies + ;; + + ldf8 f8=[r21] // f8 now contains itm_next + sub r28=r29, r28, 1 // r28 now contains "-(lost + 1)" + tbit.nz p9, p10=r23, 0 // p9 <- is_odd(r23), p10 <- is_even(r23) + ;; + + ld8 r2=[r19] // r2 = sec = xtime.tv_sec + ld8 r29=[r20] // r29 = nsec = xtime.tv_nsec + + setf.sig f6=r28 // f6 <- -(lost + 1) (6 cyc) + ;; + + mf + xma.l f8=f6, f7, f8 // f8 (last_tick) <- -(lost + 1)*itm_delta + itm_next (5 cyc) + nop 0 + + setf.sig f12=r31 // f12 <- ITC (6 cyc) + // *** if (unlikely(read_seqretry(&xtime_lock, seq))) continue; *** + ld4 r24=[r17] // r24 = xtime_lock->sequence (re-read) + nop 0 + ;; + + mov r31=ar.itc // re-read ITC in case we .retry (35 cyc) + xma.l f8=f11, f8, f12 // f8 (elapsed_cycles) <- (-1*last_tick + now) = (now - last_tick) + nop 0 + ;; + + getf.sig r18=f8 // r18 <- (now - last_tick) + xmpy.l f8=f8, f10 // f8 <- elapsed_cycles*nsec_per_cyc (5 cyc) + add r3=r29, r14 // r3 = (nsec + old) + ;; + + cmp.lt p7, p8=r18, r0 // if now < last_tick, set p7 = 1, p8 = 0 + getf.sig r18=f8 // r18 = elapsed_cycles*nsec_per_cyc (6 cyc) + nop 0 + ;; + +(p10) cmp.ne p9, p0=r23, r24 // if xtime_lock->sequence != seq, set p9 + shr.u r18=r18, IA64_NSEC_PER_CYC_SHIFT // r18 <- offset +(p9) br.spnt.many .retry + ;; + + mov ar.ccv=r14 // ar.ccv = old (1 cyc) + cmp.leu p7, p8=r18, r14 // if (offset <= old), set p7 = 1, p8 = 0 + ;; + +(p8) cmpxchg8.rel r24=[r25], r18, ar.ccv // compare-and-exchange (atomic!) +(p8) add r3=r29, r18 // r3 = (nsec + offset) + ;; + shr.u r3=r3, 3 // initiate dividing r3 by 1000 + ;; + setf.sig f8=r3 // (6 cyc) + mov r10=1000000 // r10 = 1000000 + ;; +(p8) cmp.ne.unc p9, p0=r24, r14 + xmpy.hu f6=f8, f9 // (5 cyc) +(p9) br.spnt.many .retry + ;; + + getf.sig r3=f6 // (6 cyc) + ;; + shr.u r3=r3, 4 // end of division, r3 is divided by 1000 (=usec) + ;; + +1: cmp.geu p7, p0=r3, r10 // while (usec >= 1000000) + ;; +(p7) sub r3=r3, r10 // usec -= 1000000 +(p7) adds r2=1, r2 // ++sec +(p7) br.spnt.many 1b + + // finally: r2 = sec, r3 = usec +EX(.fail, st8 [r32]=r2) + adds r9=8, r32 + mov r8=r0 // success + ;; +EX(.fail, st8 [r9]=r3) // store them in the timeval struct + mov r10=0 + MCKINLEY_E9_WORKAROUND + br.ret.sptk.many b6 // return to caller + /* + * Note: We are NOT clearing the scratch registers here. Since the only things + * in those registers are time-related variables and some addresses (which + * can be obtained from System.map), none of this should be security-sensitive + * and we should be fine. + */ + +.fail: adds r8=EINVAL, r0 // r8 = EINVAL + adds r10=-1, r0 // r10 = -1 + MCKINLEY_E9_WORKAROUND + br.ret.spnt.many b6 // return with r8 set to EINVAL +END(fsys_gettimeofday) + .rodata .align 8 .globl fsyscall_table @@ -190,7 +372,7 @@ data8 fsys_fallback_syscall // setrlimit data8 fsys_fallback_syscall // getrlimit // 1085 data8 fsys_fallback_syscall // getrusage - data8 fsys_fallback_syscall // gettimeofday + data8 fsys_gettimeofday // gettimeofday data8 fsys_fallback_syscall // settimeofday data8 fsys_fallback_syscall // select data8 fsys_fallback_syscall // poll // 1090 diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/kernel/gate.S Sat Mar 15 18:40:44 2003 @@ -145,11 +145,12 @@ */ #define SIGTRAMP_SAVES \ - .unwabi @svr4, 's' // mark this as a sigtramp handler (saves scratch regs) \ - .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF \ - .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF \ - .savesp pr, PR_OFF+SIGCONTEXT_OFF \ - .savesp rp, RP_OFF+SIGCONTEXT_OFF \ + .unwabi @svr4, 's'; /* mark this as a sigtramp handler (saves scratch regs) */ \ + .savesp ar.unat, UNAT_OFF+SIGCONTEXT_OFF; \ + .savesp ar.fpsr, FPSR_OFF+SIGCONTEXT_OFF; \ + .savesp pr, PR_OFF+SIGCONTEXT_OFF; \ + .savesp rp, RP_OFF+SIGCONTEXT_OFF; \ + .savesp ar.pfs, CFM_OFF+SIGCONTEXT_OFF; \ .vframesp SP_OFF+SIGCONTEXT_OFF GLOBAL_ENTRY(ia64_sigtramp) @@ -173,9 +174,7 @@ .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF (p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16) back_from_setup_rbs: - - .spillreg ar.pfs, r8 - alloc r8=ar.pfs,0,0,3,0 // get CFM0, EC0, and CPL0 into r8 + alloc r8=ar.pfs,0,0,3,0 ld8 out0=[base0],16 // load arg0 (signum) adds base1=(ARG1_OFF-(RBS_BASE_OFF+SIGCONTEXT_OFF)),base1 ;; @@ -184,17 +183,12 @@ ;; ld8 out2=[base0] // load arg2 (sigcontextp) ld8 gp=[r17] // get signal handler's global pointer - adds base0=(BSP_OFF+SIGCONTEXT_OFF),sp ;; .spillsp ar.bsp, BSP_OFF+SIGCONTEXT_OFF - st8 [base0]=r9,(CFM_OFF-BSP_OFF) // save sc_ar_bsp - dep r8=0,r8,38,26 // clear EC0, CPL0 and reserved bits - adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp - ;; - .spillsp ar.pfs, CFM_OFF+SIGCONTEXT_OFF - st8 [base0]=r8 // save CFM0 + st8 [base0]=r9 // save sc_ar_bsp adds base0=(FR6_OFF+SIGCONTEXT_OFF),sp + adds base1=(FR6_OFF+16+SIGCONTEXT_OFF),sp ;; stf.spill [base0]=f6,32 stf.spill [base1]=f7,32 @@ -217,7 +211,6 @@ ld8 r15=[base0],(CFM_OFF-BSP_OFF) // fetch sc_ar_bsp and advance to CFM_OFF mov r14=ar.bsp ;; - ld8 r8=[base0] // restore (perhaps modified) CFM0, EC0, and CPL0 cmp.ne p8,p0=r14,r15 // do we need to restore the rbs? (p8) br.cond.spnt restore_rbs // yup -> (clobbers r14-r18, f6 & f7) ;; diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Sat Mar 15 18:40:45 2003 +++ b/arch/ia64/kernel/init_task.c Sat Mar 15 18:40:45 2003 @@ -17,6 +17,7 @@ static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/kernel/iosapic.c Sat Mar 15 18:40:41 2003 @@ -29,6 +29,9 @@ * 02/07/29 T. Kochi Allocate interrupt vectors dynamically * 02/08/04 T. Kochi Cleaned up terminology (irq, global system interrupt, vector, etc.) * 02/09/20 D. Mosberger Simplified by taking advantage of ACPI's pci_irq code. + * 03/02/19 B. Helgaas Make pcat_compat system-wide, not per-IOSAPIC. + * Remove iosapic_address & gsi_base from external interfaces. + * Rationalize __init/__devinit attributes. */ /* * Here is what the interrupt logic between a PCI device and the kernel looks like: @@ -111,16 +114,17 @@ char *addr; /* base address of IOSAPIC */ unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */ unsigned short num_rte; /* number of RTE in this IOSAPIC */ - unsigned char pcat_compat; /* 8259 compatibility flag */ -} iosapic_lists[256] __devinitdata; +} iosapic_lists[256]; -static int num_iosapic = 0; +static int num_iosapic; + +static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */ /* * Find an IOSAPIC associated with a GSI */ -static inline int __devinit +static inline int find_iosapic (unsigned int gsi) { int i; @@ -423,7 +427,7 @@ * if the given vector is already owned by other, * assign a new vector for the other and make the vector available */ -static void +static void __init iosapic_reassign_vector (int vector) { int new_vector; @@ -443,50 +447,36 @@ static void register_intr (unsigned int gsi, int vector, unsigned char delivery, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { irq_desc_t *idesc; struct hw_interrupt_type *irq_type; int rte_index; + int index; + unsigned long gsi_base; + char *iosapic_address; + + index = find_iosapic(gsi); + if (index < 0) { + printk(KERN_WARNING "%s: No IOSAPIC for GSI 0x%x\n", __FUNCTION__, gsi); + return; + } + + iosapic_address = iosapic_lists[index].addr; + gsi_base = iosapic_lists[index].gsi_base; rte_index = gsi - gsi_base; iosapic_intr_info[vector].rte_index = rte_index; - iosapic_intr_info[vector].polarity = polarity ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW; + iosapic_intr_info[vector].polarity = polarity; iosapic_intr_info[vector].dmode = delivery; + iosapic_intr_info[vector].addr = iosapic_address; + iosapic_intr_info[vector].gsi_base = gsi_base; + iosapic_intr_info[vector].trigger = trigger; - /* - * In override, it may not provide addr/gsi_base. GSI is enough to - * locate iosapic addr, gsi_base and rte_index by examining - * gsi_base and num_rte of registered iosapics (tbd) - */ -#ifndef OVERRIDE_DEBUG - if (iosapic_address) { - iosapic_intr_info[vector].addr = iosapic_address; - iosapic_intr_info[vector].gsi_base = gsi_base; - } -#else - if (iosapic_address) { - if (iosapic_intr_info[vector].addr && (iosapic_intr_info[vector].addr != iosapic_address)) - printk(KERN_WARNING "warning: register_intr: diff IOSAPIC ADDRESS for " - "GSI 0x%x, vector %d\n", gsi, vector); - iosapic_intr_info[vector].addr = iosapic_address; - if (iosapic_intr_info[vector].gsi_base && (iosapic_intr_info[vector].gsi_base != gsi_base)) { - printk(KERN_WARNING "warning: register_intr: diff GSI base 0x%x for " - "GSI 0x%x, vector %d\n", gsi_base, gsi, vector); - } - iosapic_intr_info[vector].gsi_base = gsi_base; - } else if (!iosapic_intr_info[vector].addr) - printk(KERN_WARNING "warning: register_intr: invalid override for GSI 0x%x, " - "vector %d\n", gsi, vector); -#endif - if (edge_triggered) { - iosapic_intr_info[vector].trigger = IOSAPIC_EDGE; + if (trigger == IOSAPIC_EDGE) irq_type = &irq_type_iosapic_edge; - } else { - iosapic_intr_info[vector].trigger = IOSAPIC_LEVEL; + else irq_type = &irq_type_iosapic_level; - } idesc = irq_desc(vector); if (idesc->handler != irq_type) { @@ -504,8 +494,7 @@ */ int iosapic_register_intr (unsigned int gsi, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; @@ -515,11 +504,11 @@ vector = ia64_alloc_vector(); register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, - polarity, edge_triggered, gsi_base, iosapic_address); + polarity, trigger); printk(KERN_INFO "GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -530,11 +519,10 @@ * ACPI calls this when it finds an entry for a platform interrupt. * Note that the irq_base and IOSAPIC address must be set in iosapic_init(). */ -int +int __init iosapic_register_platform_intr (u32 int_type, unsigned int gsi, int iosapic_vector, u16 eid, u16 id, - unsigned long polarity, unsigned long edge_triggered, - unsigned int gsi_base, char *iosapic_address) + unsigned long polarity, unsigned long trigger) { unsigned char delivery; int vector; @@ -564,11 +552,11 @@ } register_intr(gsi, vector, delivery, polarity, - edge_triggered, gsi_base, iosapic_address); + trigger); printk(KERN_INFO "PLATFORM int 0x%x: GSI 0x%x(%s,%s) -> CPU 0x%04x vector %d\n", - int_type, gsi, (polarity ? "high" : "low"), - (edge_triggered ? "edge" : "level"), dest, vector); + int_type, gsi, (polarity == IOSAPIC_POL_HIGH ? "high" : "low"), + (trigger == IOSAPIC_EDGE ? "edge" : "level"), dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); @@ -580,54 +568,36 @@ * ACPI calls this when it finds an entry for a legacy ISA IRQ override. * Note that the gsi_base and IOSAPIC address must be set in iosapic_init(). */ -void +void __init iosapic_override_isa_irq (unsigned int isa_irq, unsigned int gsi, unsigned long polarity, - unsigned long edge_triggered) + unsigned long trigger) { - int index, vector; - unsigned int gsi_base; - char *addr; + int vector; unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; - index = find_iosapic(gsi); - - if (index < 0) { - printk(KERN_ERR "ISA: No corresponding IOSAPIC found : ISA IRQ %u -> GSI 0x%x\n", - isa_irq, gsi); - return; - } - vector = isa_irq_to_vector(isa_irq); - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, edge_triggered, - gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, polarity, trigger); DBG("ISA: IRQ %u -> GSI 0x%x (%s,%s) -> CPU 0x%04x vector %d\n", isa_irq, gsi, - polarity ? "high" : "low", edge_triggered ? "edge" : "level", + polarity == IOSAPIC_POL_HIGH ? "high" : "low", trigger == IOSAPIC_EDGE ? "edge" : "level", dest, vector); /* program the IOSAPIC routing table */ set_rte(vector, dest); } -void __devinit -iosapic_init (unsigned long phys_addr, unsigned int gsi_base, int pcat_compat) +void __init +iosapic_system_init (int system_pcat_compat) { - int num_rte, vector; - unsigned int isa_irq, ver; - char *addr; - static int first_time = 1; + int vector; - if (first_time) { - first_time = 0; - for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) - iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ - } + for (vector = 0; vector < IA64_NUM_VECTORS; ++vector) + iosapic_intr_info[vector].rte_index = -1; /* mark as unused */ + pcat_compat = system_pcat_compat; if (pcat_compat) { /* * Disable the compatibility mode interrupts (8259 style), needs IN/OUT support @@ -637,6 +607,14 @@ outb(0xff, 0xA1); outb(0xff, 0x21); } +} + +void __init +iosapic_init (unsigned long phys_addr, unsigned int gsi_base) +{ + int num_rte; + unsigned int isa_irq, ver; + char *addr; addr = ioremap(phys_addr, 0); ver = iosapic_version(addr); @@ -649,7 +627,6 @@ num_rte = ((ver >> 16) & 0xff) + 1; iosapic_lists[num_iosapic].addr = addr; - iosapic_lists[num_iosapic].pcat_compat = pcat_compat; iosapic_lists[num_iosapic].gsi_base = gsi_base; iosapic_lists[num_iosapic].num_rte = num_rte; num_iosapic++; @@ -658,30 +635,18 @@ (ver & 0xf0) >> 4, (ver & 0x0f), phys_addr, gsi_base, gsi_base + num_rte - 1); if ((gsi_base == 0) && pcat_compat) { - unsigned int dest = (ia64_get_lid() >> 16) & 0xffff; /* * Map the legacy ISA devices into the IOSAPIC data. Some of these may * get reprogrammed later on with data from the ACPI Interrupt Source * Override table. */ - for (isa_irq = 0; isa_irq < 16; ++isa_irq) { - vector = isa_irq_to_vector(isa_irq); - - register_intr(isa_irq, vector, IOSAPIC_LOWEST_PRIORITY, - /* IOSAPIC_POL_HIGH, IOSAPIC_EDGE */ - 1, 1, gsi_base, addr); - - DBG("ISA: IRQ %u -> GSI 0x%x (high,edge) -> CPU 0x%04x vector %d\n", - isa_irq, isa_irq, dest, vector); - - /* program the IOSAPIC routing table: */ - set_rte(vector, dest); - } + for (isa_irq = 0; isa_irq < 16; ++isa_irq) + iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); } } -static void +static void __init fixup_vector (int vector, unsigned int gsi, const char *pci_id) { struct hw_interrupt_type *irq_type = &irq_type_iosapic_level; @@ -731,10 +696,9 @@ { struct acpi_prt_entry *entry; struct list_head *node; - unsigned int gsi, gsi_base; - int index, vector, pcat_compat; + unsigned int gsi; + int vector; char pci_id[16]; - char *addr; list_for_each(node, &acpi_prt.entries) { entry = list_entry(node, struct acpi_prt_entry, node); @@ -748,23 +712,13 @@ vector = gsi_to_vector(gsi); if (vector < 0) { /* allocate a vector for this interrupt line */ - index = find_iosapic(gsi); - - if (index < 0) { - printk(KERN_WARNING "IOSAPIC: GSI 0x%x has no IOSAPIC!\n", gsi); - continue; - } - addr = iosapic_lists[index].addr; - gsi_base = iosapic_lists[index].gsi_base; - pcat_compat = iosapic_lists[index].pcat_compat; - if (pcat_compat && (gsi < 16)) vector = isa_irq_to_vector(gsi); else /* new GSI; allocate a vector for it */ vector = ia64_alloc_vector(); - register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, 0, 0, gsi_base, addr); + register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); } snprintf(pci_id, sizeof(pci_id), "%02x:%02x:%02x[%c]", entry->id.segment, entry->id.bus, entry->id.device, 'A' + entry->pin); diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/kernel/irq.c Sat Mar 15 18:40:44 2003 @@ -154,6 +154,7 @@ int i, j; struct irqaction * action; irq_desc_t *idesc; + unsigned long flags; seq_puts(p, " "); for (j=0; jlock, flags); action = idesc->action; if (!action) - continue; + goto skip; seq_printf(p, "%3d: ",i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -176,10 +178,12 @@ #endif seq_printf(p, " %14s", idesc->handler->typename); seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&idesc->lock, flags); } seq_puts(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) @@ -340,12 +344,14 @@ * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - int cpu = smp_processor_id(); + int cpu; irq_desc_t *desc = irq_desc(irq); struct irqaction * action; unsigned int status; irq_enter(); + cpu = smp_processor_id(); + kstat_cpu(cpu).irqs[irq]++; if (desc->status & IRQ_PER_CPU) { diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S --- a/arch/ia64/kernel/ivt.S Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/kernel/ivt.S Sat Mar 15 18:40:40 2003 @@ -848,7 +848,7 @@ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group ;; ld4 r8=[r14],8 // r8 == eax (syscall number) - mov r15=230 // number of entries in ia32 system call table + mov r15=250 // number of entries in ia32 system call table ;; cmp.ltu.unc p6,p7=r8,r15 ld4 out1=[r14],8 // r9 == ecx diff -Nru a/arch/ia64/kernel/machvec.c b/arch/ia64/kernel/machvec.c --- a/arch/ia64/kernel/machvec.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/kernel/machvec.c Sat Mar 15 18:40:42 2003 @@ -10,19 +10,6 @@ struct ia64_machine_vector ia64_mv; -/* - * Most platforms use this routine for mapping page frame addresses into a memory map - * index. - * - * Note: we can't use __pa() because map_nr_dense(X) MUST map to something >= max_mapnr if - * X is outside the identity mapped kernel space. - */ -unsigned long -map_nr_dense (unsigned long addr) -{ - return (addr - PAGE_OFFSET) >> PAGE_SHIFT; -} - static struct ia64_machine_vector * lookup_machvec (const char *name) { diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/kernel/mca.c Sat Mar 15 18:40:41 2003 @@ -825,7 +825,7 @@ plog_ptr=(ia64_err_rec_t *)IA64_LOG_CURR_BUFFER(SAL_INFO_TYPE_INIT); proc_ptr = &plog_ptr->proc_err; - ia64_process_min_state_save(&proc_ptr->processor_static_info.min_state_area); + ia64_process_min_state_save(&SAL_LPI_PSI_INFO(proc_ptr)->min_state_area); /* Clear the INIT SAL logs now that they have been saved in the OS buffer */ ia64_sal_clear_state_info(SAL_INFO_TYPE_INIT); @@ -1620,7 +1620,7 @@ * absent. Also, current implementations only allocate space for number of * elements used. So we walk the data pointer from here on. */ - p_data = &slpi->cache_check_info[0]; + p_data = &slpi->info[0]; /* Print the cache check information if any*/ for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++) diff -Nru a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c --- a/arch/ia64/kernel/palinfo.c Sat Mar 15 18:40:39 2003 +++ b/arch/ia64/kernel/palinfo.c Sat Mar 15 18:40:39 2003 @@ -341,11 +341,11 @@ return 0; } - p += sprintf(p, "\nTLB walker : %s implemented\n" \ + p += sprintf(p, "\nTLB walker : %simplemented\n" \ "Number of DTR : %d\n" \ "Number of ITR : %d\n" \ "TLB insertable page sizes : ", - vm_info_1.pal_vm_info_1_s.vw ? "\b":"not", + vm_info_1.pal_vm_info_1_s.vw ? "" : "not ", vm_info_1.pal_vm_info_1_s.max_dtr_entry+1, vm_info_1.pal_vm_info_1_s.max_itr_entry+1); @@ -894,10 +894,12 @@ * in SMP mode, we may need to call another CPU to get correct * information. PAL, by definition, is processor specific */ - if (f->req_cpu == smp_processor_id()) + if (f->req_cpu == get_cpu()) len = (*palinfo_entries[f->func_id].proc_read)(page); else len = palinfo_handle_smp(f, page); + + put_cpu(); if (len <= off+count) *eof = 1; diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/kernel/perfmon.c Sat Mar 15 18:40:44 2003 @@ -8,7 +8,7 @@ * Modifications by Stephane Eranian, Hewlett-Packard Co. * Modifications by David Mosberger-Tang, Hewlett-Packard Co. * - * Copyright (C) 1999-2002 Hewlett Packard Co + * Copyright (C) 1999-2003 Hewlett Packard Co * Stephane Eranian * David Mosberger-Tang */ @@ -230,9 +230,15 @@ unsigned int protected:1; /* allow access to creator of context only */ unsigned int using_dbreg:1; /* using range restrictions (debug registers) */ unsigned int excl_idle:1; /* exclude idle task in system wide session */ - unsigned int reserved:23; + unsigned int trap_reason:2; /* reason for going into pfm_block_ovfl_reset() */ + unsigned int reserved:21; } pfm_context_flags_t; +#define PFM_TRAP_REASON_NONE 0x0 /* default value */ +#define PFM_TRAP_REASON_BLOCKSIG 0x1 /* we need to block on overflow and signal user */ +#define PFM_TRAP_REASON_SIG 0x2 /* we simply need to signal user */ +#define PFM_TRAP_REASON_RESET 0x3 /* we need to reset PMDs */ + /* * perfmon context: encapsulates all the state of a monitoring session * XXX: probably need to change layout @@ -277,6 +283,7 @@ #define ctx_fl_protected ctx_flags.protected #define ctx_fl_using_dbreg ctx_flags.using_dbreg #define ctx_fl_excl_idle ctx_flags.excl_idle +#define ctx_fl_trap_reason ctx_flags.trap_reason /* * global information about all sessions @@ -1225,6 +1232,8 @@ ctx->ctx_fl_system = (ctx_flags & PFM_FL_SYSTEM_WIDE) ? 1: 0; ctx->ctx_fl_excl_idle = (ctx_flags & PFM_FL_EXCL_IDLE) ? 1: 0; ctx->ctx_fl_frozen = 0; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; + /* * setting this flag to 0 here means, that the creator or the task that the * context is being attached are granted access. Given that a context can only @@ -1505,7 +1514,7 @@ unsigned long value, hw_value; unsigned int cnum; int i; - int ret = 0; + int ret = -EINVAL; /* we don't quite support this right now */ if (task != current) return -EINVAL; @@ -1514,10 +1523,10 @@ * Cannot do anything before PMU is enabled */ if (!CTX_IS_ENABLED(ctx)) return -EINVAL; + preempt_disable(); /* XXX: ctx locking may be required here */ - ret = -EINVAL; for (i = 0; i < count; i++, req++) { @@ -1591,10 +1600,12 @@ ctx->ctx_used_pmds[0], ctx->ctx_soft_pmds[cnum].reset_pmds[0])); } - + preempt_enable(); return 0; abort_mission: + preempt_enable(); + /* * for now, we have only one possibility for error */ @@ -1639,6 +1650,7 @@ DBprintk(("ctx_last_cpu=%d for [%d]\n", atomic_read(&ctx->ctx_last_cpu), task->pid)); for (i = 0; i < count; i++, req++) { + int me; #if __GNUC__ < 3 foo = __get_user(cnum, &req->reg_num); if (foo) return -EFAULT; @@ -1666,13 +1678,16 @@ * PMU state is still in the local live register due to lazy ctxsw. * If true, then we read directly from the registers. */ - if (atomic_read(&ctx->ctx_last_cpu) == smp_processor_id()){ + me = get_cpu(); + if (atomic_read(&ctx->ctx_last_cpu) == me){ ia64_srlz_d(); val = ia64_get_pmd(cnum); DBprintk(("reading pmd[%u]=0x%lx from hw\n", cnum, val)); } else { val = th->pmd[cnum]; } + + if (PMD_IS_COUNTING(cnum)) { /* * XXX: need to check for overflow @@ -1694,6 +1709,8 @@ PFM_REG_RETFLAG_SET(reg_flags, ret); + put_cpu(); + DBprintk(("read pmd[%u] ret=%d value=0x%lx pmc=0x%lx\n", cnum, ret, val, ia64_get_pmc(cnum))); @@ -1831,6 +1848,7 @@ ctx->ctx_fl_frozen, ctx->ctx_ovfl_regs[0])); + preempt_disable(); pfm_reset_regs(ctx, ctx->ctx_ovfl_regs, PFM_PMD_LONG_RESET); ctx->ctx_ovfl_regs[0] = 0UL; @@ -1849,6 +1867,8 @@ /* simply unfreeze */ pfm_unfreeze_pmu(); + preempt_enable(); + return 0; } /* restart on another task */ @@ -1906,6 +1926,7 @@ ctx->ctx_fl_system, PMU_OWNER(), current)); + preempt_disable(); /* simply stop monitoring but not the PMU */ if (ctx->ctx_fl_system) { @@ -1933,6 +1954,7 @@ */ ia64_psr(regs)->up = 0; } + preempt_enable(); return 0; } @@ -1945,6 +1967,7 @@ if (!CTX_IS_ENABLED(ctx)) return -EINVAL; + preempt_disable(); /* * stop monitoring, freeze PMU, and save state in context * this call will clear IA64_THREAD_PM_VALID for per-task sessions. @@ -1965,6 +1988,7 @@ DBprintk(("enabling psr.sp for [%d]\n", current->pid)); ctx->ctx_flags.state = PFM_CTX_DISABLED; + preempt_enable(); return 0; } @@ -2314,6 +2338,7 @@ return -EINVAL; } + preempt_disable(); if (ctx->ctx_fl_system) { PFM_CPUINFO_SET(PFM_CPUINFO_DCR_PP); @@ -2331,6 +2356,7 @@ } else { if ((task->thread.flags & IA64_THREAD_PM_VALID) == 0) { + preempt_enable(); printk(KERN_DEBUG "perfmon: pfm_start task flag not set for [%d]\n", task->pid); return -EINVAL; @@ -2344,6 +2370,7 @@ ia64_srlz_i(); } + preempt_enable(); return 0; } @@ -2351,9 +2378,13 @@ pfm_enable(struct task_struct *task, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) { + int me; + /* we don't quite support this right now */ if (task != current) return -EINVAL; + me = get_cpu(); /* make sure we're not migrated or preempted */ + if (ctx->ctx_fl_system == 0 && PMU_OWNER() && PMU_OWNER() != current) pfm_lazy_save_regs(PMU_OWNER()); @@ -2397,11 +2428,13 @@ SET_PMU_OWNER(task); ctx->ctx_flags.state = PFM_CTX_ENABLED; - atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); + atomic_set(&ctx->ctx_last_cpu, me); /* simply unfreeze */ pfm_unfreeze_pmu(); + put_cpu(); + return 0; } @@ -2547,6 +2580,10 @@ task = find_task_by_pid(pid); + if (task) get_task_struct(task); + + read_unlock(&tasklist_lock); + if (!task) goto abort_call; ret = -EPERM; @@ -2584,16 +2621,116 @@ ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(task, ctx, arg, count, regs); abort_call: - if (task != current) read_unlock(&tasklist_lock); + if (task && task != current) put_task_struct(task); return ret; } +/* + * send SIGPROF to register task, must be invoked when it + * is safe to send a signal, e.g., not holding any runqueue + * related locks. + */ +static int +pfm_notify_user(pfm_context_t *ctx) +{ + struct siginfo si; + int ret; + + if (ctx->ctx_notify_task == NULL) { + DBprintk(("[%d] no notifier\n", current->pid)); + return -EINVAL; + } + + si.si_errno = 0; + si.si_addr = NULL; + si.si_pid = current->pid; /* who is sending */ + si.si_signo = SIGPROF; + si.si_code = PROF_OVFL; + + si.si_pfm_ovfl[0] = ctx->ctx_ovfl_regs[0]; + + /* + * when the target of the signal is not ourself, we have to be more + * careful. The notify_task may being cleared by the target task itself + * in release_thread(). We must ensure mutual exclusion here such that + * the signal is delivered (even to a dying task) safely. + */ + + if (ctx->ctx_notify_task != current) { + /* + * grab the notification lock for this task + * This guarantees that the sequence: test + send_signal + * is atomic with regards to the ctx_notify_task field. + * + * We need a spinlock and not just an atomic variable for this. + * + */ + spin_lock(&ctx->ctx_lock); + + /* + * now notify_task cannot be modified until we're done + * if NULL, they it got modified while we were in the handler + */ + if (ctx->ctx_notify_task == NULL) { + + spin_unlock(&ctx->ctx_lock); + + /* + * If we've lost the notified task, then we will run + * to completion wbut keep the PMU frozen. Results + * will be incorrect anyway. We do not kill task + * to leave it possible to attach perfmon context + * to already running task. + */ + printk("perfmon: pfm_notify_user() lost notify_task\n"); + DBprintk_ovfl(("notification task has disappeared !\n")); + + /* we cannot afford to block now */ + ctx->ctx_fl_block = 0; + + return -EINVAL; + } + + /* + * required by send_sig_info() to make sure the target + * task does not disappear on us. + */ + read_lock(&tasklist_lock); + } + /* + * in this case, we don't stop the task, we let it go on. It will + * necessarily go to the signal handler (if any) when it goes back to + * user mode. + */ + DBprintk_ovfl(("[%d] sending notification to [%d]\n", + current->pid, ctx->ctx_notify_task->pid)); + + /* + * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock + */ + ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); + if (ret) { + printk("perfmon: send_sig_info(process %d, SIGPROF)=%d\n", + ctx->ctx_notify_task->pid, ret); + } + + /* + * now undo the protections in order + */ + if (ctx->ctx_notify_task != current) { + read_unlock(&tasklist_lock); + spin_unlock(&ctx->ctx_lock); + } + return ret; +} + void pfm_ovfl_block_reset(void) { struct thread_struct *th = ¤t->thread; pfm_context_t *ctx = current->thread.pfm_context; + unsigned int reason; int ret; /* @@ -2609,8 +2746,31 @@ printk(KERN_DEBUG "perfmon: [%d] has no PFM context\n", current->pid); return; } + /* + * extract reason for being here and clear + */ + reason = ctx->ctx_fl_trap_reason; + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; - if (CTX_OVFL_NOBLOCK(ctx)) goto non_blocking; + DBprintk(("[%d] reason=%d\n", current->pid, reason)); + + /* + * just here for a reset (non-blocking context only) + */ + if (reason == PFM_TRAP_REASON_RESET) goto non_blocking; + + /* + * first notify user. This can fail if notify_task has disappeared. + */ + if (reason == PFM_TRAP_REASON_SIG || reason == PFM_TRAP_REASON_BLOCKSIG) { + ret = pfm_notify_user(ctx); + if (ret) return; + } + + /* + * came here just to signal (non-blocking) + */ + if (reason == PFM_TRAP_REASON_SIG) return; DBprintk(("[%d] before sleeping\n", current->pid)); @@ -2691,7 +2851,7 @@ * initialize entry header */ h->pid = current->pid; - h->cpu = smp_processor_id(); + h->cpu = get_cpu(); h->last_reset_value = ovfl_mask ? ctx->ctx_soft_pmds[ffz(~ovfl_mask)].lval : 0UL; h->ip = regs ? regs->cr_iip | ((regs->cr_ipsr >> 41) & 0x3): 0x0UL; h->regs = ovfl_mask; /* which registers overflowed */ @@ -2718,7 +2878,7 @@ DBprintk_ovfl(("e=%p pmd%d =0x%lx\n", (void *)e, j, *e)); e++; } - pfm_stats[smp_processor_id()].pfm_recorded_samples_count++; + pfm_stats[h->cpu].pfm_recorded_samples_count++; /* * make the new entry visible to user, needs to be atomic @@ -2735,9 +2895,11 @@ /* * XXX: must reset buffer in blocking mode and lost notified */ - pfm_stats[smp_processor_id()].pfm_full_smpl_buffer_count++; + pfm_stats[h->cpu].pfm_full_smpl_buffer_count++; + put_cpu(); return 1; } + put_cpu(); return 0; } @@ -2756,7 +2918,6 @@ unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL; int i; int ret = 1; - struct siginfo si; /* * It is never safe to access the task for which the overflow interrupt is destinated * using the current variable as the interrupt may occur in the middle of a context switch @@ -2770,6 +2931,8 @@ * valid one, i.e. the one that caused the interrupt. */ + preempt_disable(); + t = &task->thread; /* @@ -2779,6 +2942,7 @@ if ((t->flags & IA64_THREAD_PM_VALID) == 0 && ctx->ctx_fl_system == 0) { printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d not " "using perfmon\n", task->pid); + preempt_enable_no_resched(); return 0x1; } /* @@ -2787,6 +2951,7 @@ if ((pmc0 & 0x1) == 0) { printk(KERN_DEBUG "perfmon: pid %d pmc0=0x%lx assumption error for freeze bit\n", task->pid, pmc0); + preempt_enable_no_resched(); return 0x0; } @@ -2869,7 +3034,8 @@ if (ovfl_notify == 0UL) { if (ovfl_pmds) pfm_reset_regs(ctx, &ovfl_pmds, PFM_PMD_SHORT_RESET); - return 0x0; + preempt_enable_no_resched(); + return 0x0UL; } /* @@ -2877,142 +3043,35 @@ */ ctx->ctx_ovfl_regs[0] = ovfl_pmds; - /* - * we have come to this point because there was an overflow and that notification - * was requested. The notify_task may have disappeared, in which case notify_task - * is NULL. - */ - if (ctx->ctx_notify_task) { - - si.si_errno = 0; - si.si_addr = NULL; - si.si_pid = task->pid; /* who is sending */ - - si.si_signo = SIGPROF; - si.si_code = PROF_OVFL; /* indicates a perfmon SIGPROF signal */ - /* - * Shift the bitvector such that the user sees bit 4 for PMD4 and so on. - * We only use smpl_ovfl[0] for now. It should be fine for quite a while - * until we have more than 61 PMD available. - */ - si.si_pfm_ovfl[0] = ovfl_notify; - - /* - * when the target of the signal is not ourself, we have to be more - * careful. The notify_task may being cleared by the target task itself - * in release_thread(). We must ensure mutual exclusion here such that - * the signal is delivered (even to a dying task) safely. - */ - - if (ctx->ctx_notify_task != current) { - /* - * grab the notification lock for this task - * This guarantees that the sequence: test + send_signal - * is atomic with regards to the ctx_notify_task field. - * - * We need a spinlock and not just an atomic variable for this. - * - */ - spin_lock(&ctx->ctx_lock); - - /* - * now notify_task cannot be modified until we're done - * if NULL, they it got modified while we were in the handler - */ - if (ctx->ctx_notify_task == NULL) { - - spin_unlock(&ctx->ctx_lock); + DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", + ctx->ctx_fl_block, + ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, + current->pid )); - /* - * If we've lost the notified task, then we will run - * to completion wbut keep the PMU frozen. Results - * will be incorrect anyway. We do not kill task - * to leave it possible to attach perfmon context - * to already running task. - */ - goto lost_notify; - } - /* - * required by send_sig_info() to make sure the target - * task does not disappear on us. - */ - read_lock(&tasklist_lock); - } - /* - * in this case, we don't stop the task, we let it go on. It will - * necessarily go to the signal handler (if any) when it goes back to - * user mode. - */ - DBprintk_ovfl(("[%d] sending notification to [%d]\n", - task->pid, ctx->ctx_notify_task->pid)); - - - /* - * this call is safe in an interrupt handler, so does read_lock() on tasklist_lock - */ - ret = send_sig_info(SIGPROF, &si, ctx->ctx_notify_task); - if (ret != 0) - printk(KERN_DEBUG "send_sig_info(process %d, SIGPROF)=%d\n", - ctx->ctx_notify_task->pid, ret); - /* - * now undo the protections in order - */ - if (ctx->ctx_notify_task != current) { - read_unlock(&tasklist_lock); - spin_unlock(&ctx->ctx_lock); - } - - /* - * if we block set the pfm_must_block bit - * when in block mode, we can effectively block only when the notified - * task is not self, otherwise we would deadlock. - * in this configuration, the notification is sent, the task will not - * block on the way back to user mode, but the PMU will be kept frozen - * until PFM_RESTART. - * Note that here there is still a race condition with notify_task - * possibly being nullified behind our back, but this is fine because - * it can only be changed to NULL which by construction, can only be - * done when notify_task != current. So if it was already different - * before, changing it to NULL will still maintain this invariant. - * Of course, when it is equal to current it cannot change at this point. - */ - DBprintk_ovfl(("block=%d notify [%d] current [%d]\n", - ctx->ctx_fl_block, - ctx->ctx_notify_task ? ctx->ctx_notify_task->pid: -1, - current->pid )); - - if (!CTX_OVFL_NOBLOCK(ctx) && ctx->ctx_notify_task != task) { - t->pfm_ovfl_block_reset = 1; /* will cause blocking */ - } + /* + * ctx_notify_task could already be NULL, checked in pfm_notify_user() + */ + if (CTX_OVFL_NOBLOCK(ctx) == 0 && ctx->ctx_notify_task != task) { + t->pfm_ovfl_block_reset = 1; /* will cause blocking */ + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_BLOCKSIG; } else { -lost_notify: /* XXX: more to do here, to convert to non-blocking (reset values) */ - - DBprintk_ovfl(("notification task has disappeared !\n")); - /* - * for a non-blocking context, we make sure we do not fall into the - * pfm_overflow_notify() trap. Also in the case of a blocking context with lost - * notify process, then we do not want to block either (even though it is - * interruptible). In this case, the PMU will be kept frozen and the process will - * run to completion without monitoring enabled. - * - * Of course, we cannot loose notify process when self-monitoring. - */ - t->pfm_ovfl_block_reset = 0; - + t->pfm_ovfl_block_reset = 1; /* will cause blocking */ + ctx->ctx_fl_trap_reason = PFM_TRAP_REASON_SIG; } + /* - * If notification was successful, then we rely on the pfm_restart() - * call to unfreeze and reset (in both blocking or non-blocking mode). - * - * If notification failed, then we will keep the PMU frozen and run - * the task to completion + * keep the PMU frozen until either pfm_restart() or + * task completes (non-blocking or notify_task gone). */ ctx->ctx_fl_frozen = 1; - DBprintk_ovfl(("return pmc0=0x%x must_block=%ld\n", - ctx->ctx_fl_frozen ? 0x1 : 0x0, t->pfm_ovfl_block_reset)); + DBprintk_ovfl(("return pmc0=0x%x must_block=%ld reason=%d\n", + ctx->ctx_fl_frozen ? 0x1 : 0x0, + t->pfm_ovfl_block_reset, + ctx->ctx_fl_trap_reason)); - return ctx->ctx_fl_frozen ? 0x1 : 0x0; + preempt_enable_no_resched(); + return 0x1UL; } static void @@ -3022,13 +3081,14 @@ struct task_struct *task; pfm_context_t *ctx; - pfm_stats[smp_processor_id()].pfm_ovfl_intr_count++; + pfm_stats[get_cpu()].pfm_ovfl_intr_count++; /* * if an alternate handler is registered, just bypass the default one */ if (pfm_alternate_intr_handler) { (*pfm_alternate_intr_handler->handler)(irq, arg, regs); + put_cpu(); return; } @@ -3053,6 +3113,7 @@ if (!ctx) { printk(KERN_DEBUG "perfmon: Spurious overflow interrupt: process %d has " "no PFM context\n", task->pid); + put_cpu(); return; } @@ -3060,17 +3121,25 @@ * assume PMC[0].fr = 1 at this point */ pmc0 = pfm_overflow_handler(task, ctx, pmc0, regs); - /* - * We always clear the overflow status bits and either unfreeze - * or keep the PMU frozen. + * we can only update pmc0 when the overflow + * is for the current context. In UP the current + * task may not be the one owning the PMU */ - ia64_set_pmc(0, pmc0); - ia64_srlz_d(); - + if (task == current) { + /* + * We always clear the overflow status bits and either unfreeze + * or keep the PMU frozen. + */ + ia64_set_pmc(0, pmc0); + ia64_srlz_d(); + } else { + task->thread.pmc[0] = pmc0; + } } else { pfm_stats[smp_processor_id()].pfm_spurious_ovfl_intr_count++; } + put_cpu_no_resched(); } /* for debug only */ @@ -3141,6 +3210,7 @@ unsigned long dcr; unsigned long dcr_pp; + preempt_disable(); dcr_pp = info & PFM_CPUINFO_DCR_PP ? 1 : 0; /* @@ -3151,6 +3221,7 @@ regs = (struct pt_regs *)((unsigned long) task + IA64_STK_OFFSET); regs--; ia64_psr(regs)->pp = is_ctxswin ? dcr_pp : 0; + preempt_enable(); return; } /* @@ -3166,6 +3237,7 @@ ia64_set_dcr(dcr & ~IA64_DCR_PP); pfm_clear_psr_pp(); ia64_srlz_i(); + preempt_enable(); return; } /* @@ -3179,6 +3251,7 @@ pfm_set_psr_pp(); ia64_srlz_i(); } + preempt_enable(); } void @@ -3189,6 +3262,8 @@ u64 psr; int i; + preempt_disable(); + ctx = task->thread.pfm_context; @@ -3242,6 +3317,7 @@ */ atomic_set(&ctx->ctx_last_cpu, -1); #endif + preempt_enable(); } static void @@ -3252,6 +3328,7 @@ unsigned long mask; int i; + preempt_disable(); DBprintk(("on [%d] by [%d]\n", task->pid, current->pid)); t = &task->thread; @@ -3278,6 +3355,7 @@ /* not owned by this CPU */ atomic_set(&ctx->ctx_last_cpu, -1); + preempt_enable(); } void @@ -3290,11 +3368,14 @@ u64 psr; int i; + preempt_disable(); + owner = PMU_OWNER(); ctx = task->thread.pfm_context; t = &task->thread; if (ctx == NULL) { + preempt_enable(); printk("perfmon: pfm_load_regs: null ctx for [%d]\n", task->pid); return; } @@ -3333,7 +3414,7 @@ psr = ctx->ctx_saved_psr; pfm_set_psr_l(psr); - + preempt_enable(); return; } @@ -3373,16 +3454,20 @@ if (mask & 0x1) ia64_set_pmc(i, t->pmc[i]); } + /* + * manually invoke core interrupt handler + * if the task had a pending overflow when it was ctxsw out. + * Side effect on ctx_fl_frozen is possible. + */ if (t->pmc[0] & ~0x1) { - pfm_overflow_handler(task, ctx, t->pmc[0], NULL); + t->pmc[0] = pfm_overflow_handler(task, ctx, t->pmc[0], NULL); } /* - * fl_frozen==1 when we are in blocking mode waiting for restart + * unfreeze PMU if possible */ - if (ctx->ctx_fl_frozen == 0) { - pfm_unfreeze_pmu(); - } + if (ctx->ctx_fl_frozen == 0) pfm_unfreeze_pmu(); + atomic_set(&ctx->ctx_last_cpu, smp_processor_id()); SET_PMU_OWNER(task); @@ -3391,6 +3476,7 @@ * restore the psr we changed in pfm_save_regs() */ psr = ctx->ctx_saved_psr; + preempt_enable(); pfm_set_psr_l(psr); } @@ -3408,6 +3494,7 @@ printk("perfmon: invalid task in pfm_reset_pmu()\n"); return; } + preempt_disable(); /* Let's make sure the PMU is frozen */ pfm_freeze_pmu(); @@ -3490,6 +3577,7 @@ ctx->ctx_used_dbrs[0] = 0UL; ia64_srlz_d(); + preempt_enable(); } /* @@ -3519,6 +3607,7 @@ */ if (ctx->ctx_flags.state == PFM_CTX_DISABLED) return; + preempt_disable(); /* * stop monitoring: * This is the only way to stop monitoring without destroying overflow @@ -3646,7 +3735,7 @@ * indicates that context has been saved */ atomic_set(&ctx->ctx_last_cpu, -1); - + preempt_enable(); } @@ -3669,6 +3758,7 @@ ctx = task->thread.pfm_context; thread = &task->thread; + preempt_disable(); /* * make sure child cannot mess up the monitoring session */ @@ -3723,6 +3813,8 @@ */ ia64_psr(regs)->up = 0; + preempt_enable(); + /* copy_thread() clears IA64_THREAD_PM_VALID */ return 0; } @@ -3770,8 +3862,9 @@ } } - nctx->ctx_fl_frozen = 0; - nctx->ctx_ovfl_regs[0] = 0UL; + nctx->ctx_fl_frozen = 0; + nctx->ctx_ovfl_regs[0] = 0UL; + nctx->ctx_fl_trap_reason = PFM_TRAP_REASON_NONE; atomic_set(&nctx->ctx_last_cpu, -1); /* @@ -3827,6 +3920,8 @@ thread->flags |= IA64_THREAD_PM_VALID; } + preempt_enable(); + return 0; } @@ -3848,6 +3943,7 @@ /* * check sampling buffer */ + preempt_disable(); if (ctx->ctx_psb) { pfm_smpl_buffer_desc_t *psb = ctx->ctx_psb; @@ -3940,6 +4036,7 @@ } UNLOCK_CTX(ctx); + preempt_enable(); pfm_unreserve_session(task, ctx->ctx_fl_system, 1UL << ctx->ctx_cpu); @@ -4118,17 +4215,27 @@ { int ret; + /* some sanity checks */ - if (hdl == NULL || hdl->handler == NULL) return -EINVAL; + if (hdl == NULL || hdl->handler == NULL) { + return -EINVAL; + } /* do the easy test first */ - if (pfm_alternate_intr_handler) return -EBUSY; + if (pfm_alternate_intr_handler) { + return -EBUSY; + } + preempt_disable(); /* reserve our session */ ret = pfm_reserve_session(NULL, 1, cpu_online_map); - if (ret) return ret; + if (ret) { + preempt_enable(); + return ret; + } if (pfm_alternate_intr_handler) { + preempt_enable(); printk(KERN_DEBUG "perfmon: install_alternate, intr_handler not NULL " "after reserve\n"); return -EINVAL; @@ -4136,17 +4243,21 @@ pfm_alternate_intr_handler = hdl; + preempt_enable(); return 0; } int pfm_remove_alternate_syswide_subsystem(pfm_intr_handler_desc_t *hdl) { - if (hdl == NULL) return -EINVAL; + if (hdl == NULL) + return -EINVAL; /* cannot remove someone else's handler! */ - if (pfm_alternate_intr_handler != hdl) return -EINVAL; + if (pfm_alternate_intr_handler != hdl) + return -EINVAL; + preempt_disable(); pfm_alternate_intr_handler = NULL; /* @@ -4154,6 +4265,8 @@ */ pfm_unreserve_session(NULL, 1, cpu_online_map); + preempt_enable(); + return 0; } @@ -4234,8 +4347,9 @@ pfm_init_percpu(void) { int i; + int me = get_cpu(); - if (smp_processor_id() == 0) + if (me == 0) register_percpu_irq(IA64_PERFMON_VECTOR, &perfmon_irqaction); ia64_set_pmv(IA64_PERFMON_VECTOR); @@ -4259,6 +4373,7 @@ if (PMD_IS_IMPL(i) == 0) continue; ia64_set_pmd(i, 0UL); } + put_cpu(); pfm_freeze_pmu(); } diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c --- a/arch/ia64/kernel/process.c Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/kernel/process.c Sat Mar 15 18:40:41 2003 @@ -746,7 +746,7 @@ memcpy(tsk, orig, sizeof(struct task_struct) + sizeof(struct thread_info)); tsk->thread_info = (struct thread_info *) ((char *) tsk + IA64_TASK_SIZE); - atomic_set(&tsk->usage, 1); + atomic_set(&tsk->usage, 2); return tsk; } diff -Nru a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c --- a/arch/ia64/kernel/ptrace.c Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/kernel/ptrace.c Sat Mar 15 18:40:44 2003 @@ -1,7 +1,7 @@ /* * Kernel support for the ptrace() and syscall tracing interfaces. * - * Copyright (C) 1999-2002 Hewlett-Packard Co + * Copyright (C) 1999-2003 Hewlett-Packard Co * David Mosberger-Tang * * Derived from the x86 and Alpha versions. Most of the code in here @@ -1235,19 +1235,12 @@ ret = 0; goto out_tsk; - case PTRACE_GETSIGINFO: - ret = -EIO; - if (!access_ok(VERIFY_WRITE, data, sizeof (siginfo_t)) || !child->thread.siginfo) - goto out_tsk; - ret = copy_siginfo_to_user((siginfo_t *) data, child->thread.siginfo); + case PTRACE_OLD_GETSIGINFO: /* for backwards-compatibility */ + ret = ptrace_request(child, PTRACE_GETSIGINFO, addr, data); goto out_tsk; - case PTRACE_SETSIGINFO: - ret = -EIO; - if (!access_ok(VERIFY_READ, data, sizeof (siginfo_t)) - || child->thread.siginfo == 0) - goto out_tsk; - ret = copy_siginfo_from_user(child->thread.siginfo, (siginfo_t *) data); + case PTRACE_OLD_SETSIGINFO: /* for backwards-compatibility */ + ret = ptrace_request(child, PTRACE_SETSIGINFO, addr, data); goto out_tsk; case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ @@ -1349,15 +1342,12 @@ * The 0x80 provides a way for the tracing parent to distinguish between a syscall * stop and SIGTRAP delivery. */ - current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0); - set_current_state(TASK_STOPPED); - notify_parent(current, SIGCHLD); - schedule(); + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + /* - * This isn't the same as continuing with a signal, but it - * will do for normal use. strace only continues with a - * signal if the stopping signal is not SIGTRAP. -brl + * This isn't the same as continuing with a signal, but it will do for normal use. + * strace only continues with a signal if the stopping signal is not SIGTRAP. + * -brl */ if (current->exit_code) { send_sig(current->exit_code, current, 1); diff -Nru a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c --- a/arch/ia64/kernel/setup.c Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/kernel/setup.c Sat Mar 15 18:40:40 2003 @@ -363,7 +363,7 @@ #ifdef CONFIG_ACPI_BOOT /* Initialize the ACPI boot-time table parser */ - acpi_table_init(*cmdline_p); + acpi_table_init(); # ifdef CONFIG_ACPI_NUMA acpi_numa_init(); # endif @@ -422,7 +422,7 @@ cpu_init(); /* initialize the bootstrap CPU */ #ifdef CONFIG_ACPI_BOOT - acpi_boot_init(*cmdline_p); + acpi_boot_init(); #endif #ifdef CONFIG_SERIAL_HCDP if (efi.hcdp) { diff -Nru a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h --- a/arch/ia64/kernel/sigframe.h Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/kernel/sigframe.h Sat Mar 15 18:40:44 2003 @@ -1,6 +1,6 @@ struct sigscratch { unsigned long scratch_unat; /* ar.unat for the general registers saved in pt */ - unsigned long pad; + unsigned long ar_pfs; /* for syscalls, the user-level function-state */ struct pt_regs pt; }; diff -Nru a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c --- a/arch/ia64/kernel/signal.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/kernel/signal.c Sat Mar 15 18:40:42 2003 @@ -315,7 +315,7 @@ static long setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) { - unsigned long flags = 0, ifs, nat; + unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; @@ -325,7 +325,9 @@ if ((ifs & (1UL << 63)) == 0) { /* if cr_ifs isn't valid, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; - } + cfm = scr->ar_pfs & ((1UL << 38) - 1); + } else + cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; @@ -344,6 +346,7 @@ err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); + err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); @@ -422,6 +425,15 @@ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ + /* + * Force the interruption function mask to zero. This has no effect when a + * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is + * ignored), but it has the desirable effect of making it possible to deliver a + * signal with an incomplete register frame (which happens when a mandatory RSE + * load faults). Furthermore, it has no negative effect on the getting the user's + * dirty partition preserved, because that's governed by scr->pt.loadrs. + */ + scr->pt.cr_ifs = (1UL << 63); /* * Note: this affects only the NaT bits of the scratch regs (the ones saved in @@ -522,7 +534,7 @@ if (signr <= 0) break; - ka = ¤t->sig->action[signr - 1]; + ka = ¤t->sighand->action[signr - 1]; if (restart) { switch (errno) { diff -Nru a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c --- a/arch/ia64/kernel/smp.c Sat Mar 15 18:40:45 2003 +++ b/arch/ia64/kernel/smp.c Sat Mar 15 18:40:45 2003 @@ -90,7 +90,7 @@ void handle_IPI (int irq, void *dev_id, struct pt_regs *regs) { - int this_cpu = smp_processor_id(); + int this_cpu = get_cpu(); unsigned long *pending_ipis = &__get_cpu_var(ipi_operation); unsigned long ops; @@ -146,8 +146,12 @@ } while (ops); mb(); /* Order data access and bit testing. */ } + put_cpu(); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_single (int dest_cpu, int op) { @@ -155,6 +159,9 @@ platform_send_ipi(dest_cpu, IA64_IPI_VECTOR, IA64_IPI_DM_INT, 0); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_allbutself (int op) { @@ -166,6 +173,9 @@ } } +/* + * Called with preeemption disabled + */ static inline void send_IPI_all (int op) { @@ -176,12 +186,18 @@ send_IPI_single(i, op); } +/* + * Called with preeemption disabled + */ static inline void send_IPI_self (int op) { send_IPI_single(smp_processor_id(), op); } +/* + * Called with preeemption disabled + */ void smp_send_reschedule (int cpu) { @@ -197,12 +213,15 @@ smp_send_reschedule_all (void) { int i; + int cpu = get_cpu(); /* disable preemption */ for (i = 0; i < NR_CPUS; i++) - if (cpu_online(i) && i != smp_processor_id()) + if (cpu_online(i) && i != cpu) smp_send_reschedule(i); + put_cpu(); } + void smp_flush_tlb_all (void) { @@ -247,9 +266,11 @@ { struct call_data_struct data; int cpus = 1; + int me = get_cpu(); /* prevent preemption and reschedule on another processor */ - if (cpuid == smp_processor_id()) { + if (cpuid == me) { printk("%s: trying to call self\n", __FUNCTION__); + put_cpu(); return -EBUSY; } @@ -276,6 +297,7 @@ call_data = NULL; spin_unlock_bh(&call_lock); + put_cpu(); return 0; } diff -Nru a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c --- a/arch/ia64/kernel/sys_ia64.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/kernel/sys_ia64.c Sat Mar 15 18:40:42 2003 @@ -33,17 +33,8 @@ return -ENOMEM; #ifdef CONFIG_HUGETLB_PAGE -#define COLOR_HALIGN(addr) ((addr + HPAGE_SIZE - 1) & ~(HPAGE_SIZE - 1)) -#define TASK_HPAGE_BASE ((REGION_HPAGE << REGION_SHIFT) | HPAGE_SIZE) - if (filp && is_file_hugepages(filp)) { - if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE -1))) - addr = TASK_HPAGE_BASE; - addr = COLOR_HALIGN(addr); - } - else { - if (REGION_NUMBER(addr) == REGION_HPAGE) - addr = 0; - } + if (REGION_NUMBER(addr) == REGION_HPAGE) + addr = 0; #endif if (!addr) addr = TASK_UNMAPPED_BASE; diff -Nru a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c --- a/arch/ia64/kernel/time.c Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/kernel/time.c Sat Mar 15 18:40:40 2003 @@ -25,7 +25,7 @@ #include extern unsigned long wall_jiffies; -extern unsigned long last_time_offset; +extern unsigned long last_nsec_offset; u64 jiffies_64 = INITIAL_JIFFIES; @@ -74,13 +74,13 @@ - (lost + 1)*cpu_data(time_keeper_id)->itm_delta); now = ia64_get_itc(); - if ((long) (now - last_tick) < 0) { + if (unlikely((long) (now - last_tick) < 0)) { printk(KERN_ERR "CPU %d: now < last_tick (now=0x%lx,last_tick=0x%lx)!\n", smp_processor_id(), now, last_tick); - return last_time_offset; + return last_nsec_offset; } elapsed_cycles = now - last_tick; - return (elapsed_cycles*local_cpu_data->usec_per_cyc) >> IA64_USEC_PER_CYC_SHIFT; + return (elapsed_cycles*local_cpu_data->nsec_per_cyc) >> IA64_NSEC_PER_CYC_SHIFT; } void @@ -115,30 +115,55 @@ void do_gettimeofday (struct timeval *tv) { - unsigned long seq, usec, sec, old; + unsigned long seq, nsec, usec, sec, old, offset; - do { + while (1) { seq = read_seqbegin(&xtime_lock); - usec = gettimeoffset(); - + { + old = last_nsec_offset; + offset = gettimeoffset(); + sec = xtime.tv_sec; + nsec = xtime.tv_nsec; + } + if (unlikely(read_seqretry(&xtime_lock, seq))) + continue; /* - * Ensure time never goes backwards, even when ITC on - * different CPUs are not perfectly synchronized. + * Ensure that for any pair of causally ordered gettimeofday() calls, time + * never goes backwards (even when ITC on different CPUs are not perfectly + * synchronized). (A pair of concurrent calls to gettimeofday() is by + * definition non-causal and hence it makes no sense to talk about + * time-continuity for such calls.) + * + * Doing this in a lock-free and race-free manner is tricky. Here is why + * it works (most of the time): read_seqretry() just succeeded, which + * implies we calculated a consistent (valid) value for "offset". If the + * cmpxchg() below succeeds, we further know that last_nsec_offset still + * has the same value as at the beginning of the loop, so there was + * presumably no timer-tick or other updates to last_nsec_offset in the + * meantime. This isn't 100% true though: there _is_ a possibility of a + * timer-tick occurring right right after read_seqretry() and then getting + * zero or more other readers which will set last_nsec_offset to the same + * value as the one we read at the beginning of the loop. If this + * happens, we'll end up returning a slightly newer time than we ought to + * (the jump forward is at most "offset" nano-seconds). There is no + * danger of causing time to go backwards, though, so we are safe in that + * sense. We could make the probability of this unlucky case occurring + * arbitrarily small by encoding a version number in last_nsec_offset, but + * even without versioning, the probability of this unlucky case should be + * so small that we won't worry about it. */ - do { - old = last_time_offset; - if (usec <= old) { - usec = old; - break; - } - } while (cmpxchg(&last_time_offset, old, usec) != old); - - sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqend(&xtime_lock, seq)); + if (offset <= old) { + offset = old; + break; + } else if (likely(cmpxchg(&last_nsec_offset, old, offset) == old)) + break; + + /* someone else beat us to updating last_nsec_offset; try again */ + } + usec = (nsec + offset) / 1000; - while (usec >= 1000000) { + while (unlikely(usec >= 1000000)) { usec -= 1000000; ++sec; } @@ -278,7 +303,7 @@ local_cpu_data->proc_freq = (platform_base_freq*proc_ratio.num)/proc_ratio.den; local_cpu_data->itc_freq = itc_freq; local_cpu_data->cyc_per_usec = (itc_freq + 500000) / 1000000; - local_cpu_data->usec_per_cyc = ((1000000UL<nsec_per_cyc = ((1000000000UL<> 4) & 0xf) == 2) { /* NaT page consumption */ sig = SIGSEGV; code = SEGV_ACCERR; + addr = (void *) ifa; } else { /* register NaT consumption */ sig = SIGILL; code = ILL_ILLOPN; + addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); } siginfo.si_signo = sig; siginfo.si_code = code; siginfo.si_errno = 0; - siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri); + siginfo.si_addr = addr; siginfo.si_imm = vector; siginfo.si_flags = __ISR_VALID; siginfo.si_isr = isr; diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c --- a/arch/ia64/kernel/unwind.c Sat Mar 15 18:40:45 2003 +++ b/arch/ia64/kernel/unwind.c Sat Mar 15 18:40:45 2003 @@ -51,18 +51,24 @@ #define UNW_LOG_HASH_SIZE (UNW_LOG_CACHE_SIZE + 1) #define UNW_HASH_SIZE (1 << UNW_LOG_HASH_SIZE) -#define UNW_DEBUG 0 #define UNW_STATS 0 /* WARNING: this disabled interrupts for long time-spans!! */ -#if UNW_DEBUG - static long unw_debug_level = 255; -# define debug(level,format...) if (unw_debug_level > level) printk(format) -# define dprintk(format...) printk(format) -# define inline -#else -# define debug(level,format...) -# define dprintk(format...) -#endif +#ifdef UNW_DEBUG + static unsigned int unw_debug_level = UNW_DEBUG; +# ifdef CONFIG_KDB +# include +# define UNW_DEBUG_ON(n) (unw_debug_level >= n && !KDB_IS_RUNNING()) +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) kdb_printf(__VA_ARGS__) +# else /* !CONFIG_KDB */ +# define UNW_DEBUG_ON(n) unw_debug_level >= n + /* Do not code a printk level, not all debug lines end in newline */ +# define UNW_DPRINT(n, ...) if (UNW_DEBUG_ON(n)) printk(__VA_ARGS__) +# endif /* CONFIG_KDB */ +# define inline +#else /* !UNW_DEBUG */ +# define UNW_DEBUG_ON(n) 0 +# define UNW_DPRINT(n, ...) +#endif /* UNW_DEBUG */ #if UNW_STATS # define STAT(x...) x @@ -111,7 +117,7 @@ /* script cache: */ struct unw_script cache[UNW_CACHE_SIZE]; -# if UNW_DEBUG +# ifdef UNW_DEBUG const char *preg_name[UNW_NUM_REGS]; # endif # if UNW_STATS @@ -190,7 +196,7 @@ struct_offset(struct unw_frame_info, fr_loc[31 - 16])/8, }, .hash = { [0 ... UNW_HASH_SIZE - 1] = -1 }, -#if UNW_DEBUG +#ifdef UNW_DEBUG .preg_name = { "pri_unat_gr", "pri_unat_mem", "bsp", "bspstore", "ar.pfs", "ar.rnat", "psp", "rp", "r4", "r5", "r6", "r7", @@ -223,10 +229,22 @@ else if (reg <= 31) off = struct_offset(struct pt_regs, r16) + 8*(reg - 16); else - dprintk("unwind: bad scratch reg r%lu\n", reg); + UNW_DPRINT(0, "unwind.%s: bad scratch reg r%lu\n", __FUNCTION__, reg); return off; } +static inline struct pt_regs * +get_scratch_regs (struct unw_frame_info *info) +{ + if (!info->pt) { + /* This should not happen with valid unwind info. */ + UNW_DPRINT(0, "unwind.%s: bad unwind info: resetting info->pt\n", __FUNCTION__); + info->pt = info->sp - 16; + } + UNW_DPRINT(3, "unwind.%s: sp 0x%lx pt 0x%lx\n", __FUNCTION__, info->sp, info->pt); + return (struct pt_regs *) info->pt; +} + int unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char *nat, int write) { @@ -235,7 +253,8 @@ struct pt_regs *pt; if ((unsigned) regnum - 1 >= 127) { - dprintk("unwind: trying to access non-existent r%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent r%u\n", + __FUNCTION__, regnum); return -1; } @@ -280,8 +299,9 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: %p outside of regstk " - "[0x%lx-0x%lx)\n", (void *) addr, + UNW_DPRINT(0, "unwind.%s: %p outside of regstk " + "[0x%lx-0x%lx)\n", + __FUNCTION__, (void *) addr, info->regstk.limit, info->regstk.top); return -1; @@ -298,11 +318,13 @@ } } else { /* access a scratch register */ - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - addr = (unsigned long *) ((long) pt + pt_regs_off(regnum)); + if (!info->pt) { + UNW_DPRINT(0, "unwind.%s: no pt-regs; cannot access r%d\n", + __FUNCTION__, regnum); + return -1; + } + pt = get_scratch_regs(info); + addr = (unsigned long *) (pt + pt_regs_off(regnum)); if (info->pri_unat_loc) nat_addr = info->pri_unat_loc; else @@ -316,7 +338,8 @@ if ((unsigned long) addr < info->regstk.limit || (unsigned long) addr >= info->regstk.top) { - dprintk("unwind: ignoring attempt to access register outside of rbs\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to access register outside " + "of rbs\n", __FUNCTION__); return -1; } if ((unsigned long) nat_addr >= info->regstk.top) @@ -348,10 +371,7 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; + pt = get_scratch_regs(info); switch (regnum) { /* scratch: */ case 0: addr = &pt->b0; break; @@ -366,7 +386,8 @@ break; default: - dprintk("unwind: trying to access non-existent b%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent b%u\n", + __FUNCTION__, regnum); return -1; } if (write) @@ -383,14 +404,12 @@ struct pt_regs *pt; if ((unsigned) (regnum - 2) >= 126) { - dprintk("unwind: trying to access non-existent f%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent f%u\n", + __FUNCTION__, regnum); return -1; } - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; + pt = get_scratch_regs(info); if (regnum <= 5) { addr = *(&info->f2_loc + (regnum - 2)); @@ -428,11 +447,7 @@ unsigned long *addr; struct pt_regs *pt; - if (info->flags & UNW_FLAG_INTERRUPT_FRAME) - pt = (struct pt_regs *) info->psp - 1; - else - pt = (struct pt_regs *) info->sp - 1; - + pt = get_scratch_regs(info); switch (regnum) { case UNW_AR_BSP: addr = info->bsp_loc; @@ -495,7 +510,8 @@ break; default: - dprintk("unwind: trying to access non-existent ar%u\n", regnum); + UNW_DPRINT(0, "unwind.%s: trying to access non-existent ar%u\n", + __FUNCTION__, regnum); return -1; } @@ -612,7 +628,7 @@ default: break; } - dprintk("unwind: bad abreg=0x%x\n", abreg); + UNW_DPRINT(0, "unwind.%s: bad abreg=0x%x\n", __FUNCTION__, abreg); return UNW_REG_LC; } @@ -652,7 +668,7 @@ return; } } - dprintk("unwind: excess spill!\n"); + UNW_DPRINT(0, "unwind.%s: excess spill!\n", __FUNCTION__); } static inline void @@ -720,7 +736,7 @@ desc_prologue (int body, unw_word rlen, unsigned char mask, unsigned char grsave, struct unw_state_record *sr) { - int i; + int i, region_start; if (!(sr->in_body || sr->first_region)) finish_prologue(sr); @@ -732,19 +748,20 @@ return; } + region_start = sr->region_start + sr->region_len; + for (i = 0; i < sr->epilogue_count; ++i) pop(sr); sr->epilogue_count = 0; sr->epilogue_start = UNW_WHEN_NEVER; - if (!body) - push(sr); - - sr->region_start += sr->region_len; + sr->region_start = region_start; sr->region_len = rlen; sr->in_body = body; if (!body) { + push(sr); + for (i = 0; i < 4; ++i) { if (mask & 0x8) set_reg(sr->curr.reg + unw.save_order[i], UNW_WHERE_GR, @@ -765,10 +782,13 @@ static inline void desc_abi (unsigned char abi, unsigned char context, struct unw_state_record *sr) { - if (abi == 0 && context == 'i') + if (abi == 0 && context == 'i') { sr->flags |= UNW_FLAG_INTERRUPT_FRAME; + UNW_DPRINT(3, "unwind.%s: interrupt frame\n", __FUNCTION__); + } else - dprintk("unwind: ignoring unwabi(abi=0x%x,context=0x%x)\n", abi, context); + UNW_DPRINT(0, "unwind%s: ignoring unwabi(abi=0x%x,context=0x%x)\n", + __FUNCTION__, abi, context); } static inline void @@ -1136,6 +1156,9 @@ unsigned short index; unsigned long ip, pr; + if (UNW_DEBUG_ON(0)) + return 0; /* Always regenerate scripts in debug mode */ + STAT(++unw.stat.cache.lookups); ip = info->ip; @@ -1260,8 +1283,8 @@ script_emit (struct unw_script *script, struct unw_insn insn) { if (script->count >= UNW_MAX_SCRIPT_LEN) { - dprintk("unwind: script exceeds maximum size of %u instructions!\n", - UNW_MAX_SCRIPT_LEN); + UNW_DPRINT(0, "unwind.%s: script exceeds maximum size of %u instructions!\n", + __FUNCTION__, UNW_MAX_SCRIPT_LEN); return; } script->insn[script->count++] = insn; @@ -1302,7 +1325,8 @@ break; default: - dprintk("unwind: don't know how to emit nat info for where = %u\n", r->where); + UNW_DPRINT(0, "unwind.%s: don't know how to emit nat info for where = %u\n", + __FUNCTION__, r->where); return; } insn.opc = opc; @@ -1339,8 +1363,9 @@ } val = unw.preg_index[UNW_REG_R4 + (rval - 4)]; } else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs) + pt_regs_off(rval); + /* register got spilled to a scratch register */ + opc = UNW_INSN_MOVE_SCRATCH; + val = pt_regs_off(rval); } break; @@ -1350,12 +1375,12 @@ else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval <= 9) - val += struct_offset(struct pt_regs, f6) + 16*(rval - 6); + val = struct_offset(struct pt_regs, f6) + 16*(rval - 6); else - dprintk("unwind: kernel may not touch f%lu\n", rval); + UNW_DPRINT(0, "unwind.%s: kernel may not touch f%lu\n", + __FUNCTION__, rval); } break; @@ -1363,14 +1388,13 @@ if (rval >= 1 && rval <= 5) val = unw.preg_index[UNW_REG_B1 + (rval - 1)]; else { - opc = UNW_INSN_ADD_SP; - val = -sizeof(struct pt_regs); + opc = UNW_INSN_MOVE_SCRATCH; if (rval == 0) - val += struct_offset(struct pt_regs, b0); + val = struct_offset(struct pt_regs, b0); else if (rval == 6) - val += struct_offset(struct pt_regs, b6); + val = struct_offset(struct pt_regs, b6); else - val += struct_offset(struct pt_regs, b7); + val = struct_offset(struct pt_regs, b7); } break; @@ -1383,7 +1407,8 @@ break; default: - dprintk("unwind: register %u has unexpected `where' value of %u\n", i, r->where); + UNW_DPRINT(0, "unwind%s: register %u has unexpected `where' value of %u\n", + __FUNCTION__, i, r->where); break; } insn.opc = opc; @@ -1456,9 +1481,10 @@ r->when = UNW_WHEN_NEVER; sr.pr_val = info->pr; + UNW_DPRINT(3, "unwind.%s: ip 0x%lx\n", __FUNCTION__, ip); script = script_new(ip); if (!script) { - dprintk("unwind: failed to create unwind script\n"); + UNW_DPRINT(0, "unwind.%s: failed to create unwind script\n", __FUNCTION__); STAT(unw.stat.script.build_time += ia64_get_itc() - start); return 0; } @@ -1476,8 +1502,8 @@ } if (!e) { /* no info, return default unwinder (leaf proc, no mem stack, no saved regs) */ - dprintk("unwind: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", ip, - unw.cache[info->prev_script].ip); + UNW_DPRINT(1, "unwind.%s: no unwind info for ip=0x%lx (prev ip=0x%lx)\n", + __FUNCTION__, ip, unw.cache[info->prev_script].ip); sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = 0; @@ -1525,26 +1551,32 @@ sr.curr.reg[UNW_REG_RP].where = UNW_WHERE_BR; sr.curr.reg[UNW_REG_RP].when = -1; sr.curr.reg[UNW_REG_RP].val = sr.return_link_reg; + UNW_DPRINT(1, "unwind.%s: using default for rp at ip=0x%lx where=%d val=0x%lx\n", + __FUNCTION__, ip, sr.curr.reg[UNW_REG_RP].where, + sr.curr.reg[UNW_REG_RP].val); } -#if UNW_DEBUG - printk("unwind: state record for func 0x%lx, t=%u:\n", - table->segment_base + e->start_offset, sr.when_target); +#ifdef UNW_DEBUG + UNW_DPRINT(1, "unwind.%s: state record for func 0x%lx, t=%u:\n", + __FUNCTION__, table->segment_base + e->start_offset, sr.when_target); for (r = sr.curr.reg; r < sr.curr.reg + UNW_NUM_REGS; ++r) { if (r->where != UNW_WHERE_NONE || r->when != UNW_WHEN_NEVER) { - printk(" %s <- ", unw.preg_name[r - sr.curr.reg]); + UNW_DPRINT(1, " %s <- ", unw.preg_name[r - sr.curr.reg]); switch (r->where) { - case UNW_WHERE_GR: printk("r%lu", r->val); break; - case UNW_WHERE_FR: printk("f%lu", r->val); break; - case UNW_WHERE_BR: printk("b%lu", r->val); break; - case UNW_WHERE_SPREL: printk("[sp+0x%lx]", r->val); break; - case UNW_WHERE_PSPREL: printk("[psp+0x%lx]", r->val); break; + case UNW_WHERE_GR: UNW_DPRINT(1, "r%lu", r->val); break; + case UNW_WHERE_FR: UNW_DPRINT(1, "f%lu", r->val); break; + case UNW_WHERE_BR: UNW_DPRINT(1, "b%lu", r->val); break; + case UNW_WHERE_SPREL: UNW_DPRINT(1, "[sp+0x%lx]", r->val); break; + case UNW_WHERE_PSPREL: UNW_DPRINT(1, "[psp+0x%lx]", r->val); break; case UNW_WHERE_NONE: - printk("%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + UNW_DPRINT(1, "%s+0x%lx", unw.preg_name[r - sr.curr.reg], r->val); + break; + + default: + UNW_DPRINT(1, "BADWHERE(%d)", r->where); break; - default: printk("BADWHERE(%d)", r->where); break; } - printk("\t\t%d\n", r->when); + UNW_DPRINT(1, "\t\t%d\n", r->when); } } #endif @@ -1642,6 +1674,16 @@ s[dst] = s[val]; break; + case UNW_INSN_MOVE_SCRATCH: + if (state->pt) { + s[dst] = (unsigned long) get_scratch_regs(state) + val; + } else { + s[dst] = 0; + UNW_DPRINT(0, "unwind.%s: no state->pt, dst=%ld, val=%ld\n", + __FUNCTION__, dst, val); + } + break; + case UNW_INSN_MOVE_STACKED: s[dst] = (unsigned long) ia64_rse_skip_regs((unsigned long *)state->bsp, val); @@ -1667,11 +1709,12 @@ break; case UNW_INSN_LOAD: -#if UNW_DEBUG +#ifdef UNW_DEBUG if ((s[val] & (local_cpu_data->unimpl_va_mask | 0x7)) != 0 || s[val] < TASK_SIZE) { - debug(1, "unwind: rejecting bad psp=0x%lx\n", s[val]); + UNW_DPRINT(0, "unwind.%s: rejecting bad psp=0x%lx\n", + __FUNCTION__, s[val]); break; } #endif @@ -1704,7 +1747,8 @@ if ((info->ip & (local_cpu_data->unimpl_va_mask | 0xf)) || info->ip < TASK_SIZE) { /* don't let obviously bad addresses pollute the cache */ - debug(1, "unwind: rejecting bad ip=0x%lx\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: rejecting bad ip=0x%lx\n", __FUNCTION__, info->ip); info->rp_loc = 0; return -1; } @@ -1713,8 +1757,9 @@ if (!scr) { scr = build_script(info); if (!scr) { - dprintk("unwind: failed to locate/build unwind script for ip %lx\n", - info->ip); + UNW_DPRINT(0, + "unwind.%s: failed to locate/build unwind script for ip %lx\n", + __FUNCTION__, info->ip); return -1; } have_write_lock = 1; @@ -1747,7 +1792,9 @@ /* restore the ip */ if (!info->rp_loc) { - debug(1, "unwind: failed to locate return link (ip=0x%lx)!\n", info->ip); + /* FIXME: should really be level 0 but it occurs too often. KAO */ + UNW_DPRINT(1, "unwind.%s: failed to locate return link (ip=0x%lx)!\n", + __FUNCTION__, info->ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1757,14 +1804,14 @@ * We don't have unwind info for the gate page, so we consider that part * of user-space for the purpose of unwinding. */ - debug(1, "unwind: reached user-space (ip=0x%lx)\n", ip); + UNW_DPRINT(2, "unwind.%s: reached user-space (ip=0x%lx)\n", __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } /* restore the cfm: */ if (!info->pfs_loc) { - dprintk("unwind: failed to locate ar.pfs!\n"); + UNW_DPRINT(0, "unwind.%s: failed to locate ar.pfs!\n", __FUNCTION__); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1774,16 +1821,18 @@ pr = info->pr; num_regs = 0; if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) { + info->pt = info->sp + 16; if ((pr & (1UL << pNonSys)) != 0) num_regs = *info->cfm_loc & 0x7f; /* size of frame */ info->pfs_loc = - (unsigned long *) (info->sp + 16 + struct_offset(struct pt_regs, ar_pfs)); + (unsigned long *) (info->pt + struct_offset(struct pt_regs, ar_pfs)); + UNW_DPRINT(3, "unwind.%s: interrupt_frame pt 0x%lx\n", __FUNCTION__, info->pt); } else num_regs = (*info->cfm_loc >> 7) & 0x7f; /* size of locals */ info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->bsp, -num_regs); if (info->bsp < info->regstk.limit || info->bsp > info->regstk.top) { - dprintk("unwind: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->bsp, info->regstk.limit, info->regstk.top); + UNW_DPRINT(0, "unwind.%s: bsp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->bsp, info->regstk.limit, info->regstk.top); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1791,14 +1840,15 @@ /* restore the sp: */ info->sp = info->psp; if (info->sp < info->memstk.top || info->sp > info->memstk.limit) { - dprintk("unwind: sp (0x%lx) out of range [0x%lx-0x%lx]\n", - info->sp, info->memstk.top, info->memstk.limit); + UNW_DPRINT(0, "unwind.%s: sp (0x%lx) out of range [0x%lx-0x%lx]\n", + __FUNCTION__, info->sp, info->memstk.top, info->memstk.limit); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } if (info->ip == prev_ip && info->sp == prev_sp && info->bsp == prev_bsp) { - dprintk("unwind: ip, sp, bsp remain unchanged; stopping here (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: ip, sp, bsp unchanged; stopping here (ip=0x%lx)\n", + __FUNCTION__, ip); STAT(unw.stat.api.unwind_time += ia64_get_itc() - start; local_irq_restore(flags)); return -1; } @@ -1822,7 +1872,8 @@ while (unw_unwind(info) >= 0) { if (unw_get_rp(info, &ip) < 0) { unw_get_ip(info, &ip); - dprintk("unwind: failed to read return pointer (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n", + __FUNCTION__, ip); return -1; } /* @@ -1833,7 +1884,7 @@ return 0; } unw_get_ip(info, &ip); - dprintk("unwind: failed to unwind to user-level (ip=0x%lx)\n", ip); + UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); return -1; } @@ -1874,11 +1925,30 @@ info->task = t; info->sw = sw; info->sp = info->psp = (unsigned long) (sw + 1) - 16; + info->pt = 0; info->cfm_loc = &sw->ar_pfs; sol = (*info->cfm_loc >> 7) & 0x7f; info->bsp = (unsigned long) ia64_rse_skip_regs((unsigned long *) info->regstk.top, -sol); info->ip = sw->b0; info->pr = sw->pr; + UNW_DPRINT(3, + "unwind.%s\n" + " rbslimit 0x%lx\n" + " rbstop 0x%lx\n" + " stklimit 0x%lx\n" + " stktop 0x%lx\n" + " task 0x%lx\n" + " sw 0x%lx\n", + __FUNCTION__, rbslimit, rbstop, stklimit, stktop, + (unsigned long)(info->task), + (unsigned long)(info->sw)); + UNW_DPRINT(3, + " sp/psp 0x%lx\n" + " sol 0x%lx\n" + " bsp 0x%lx\n" + " ip 0x%lx\n" + " pr 0x%lx\n", + info->sp, sol, info->bsp, info->ip, info->pr); find_save_locs(info); STAT(unw.stat.api.init_time += ia64_get_itc() - start; local_irq_restore(flags)); @@ -1889,6 +1959,7 @@ { struct switch_stack *sw = (struct switch_stack *) (t->thread.ksp + 16); + UNW_DPRINT(1, "unwind.%s\n", __FUNCTION__); unw_init_frame_info(info, t, sw); } @@ -1916,7 +1987,8 @@ unsigned long flags; if (end - start <= 0) { - dprintk("unwind: ignoring attempt to insert empty unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to insert empty unwind table\n", + __FUNCTION__); return 0; } @@ -1946,13 +2018,15 @@ long index; if (!handle) { - dprintk("unwind: ignoring attempt to remove non-existent unwind table\n"); + UNW_DPRINT(0, "unwind.%s: ignoring attempt to remove non-existent unwind table\n", + __FUNCTION__); return; } table = handle; if (table == &unw.kernel_table) { - dprintk("unwind: sorry, freeing the kernel's unwind table is a no-can-do!\n"); + UNW_DPRINT(0, "unwind.%s: sorry, freeing the kernel's unwind table is a " + "no-can-do!\n", __FUNCTION__); return; } @@ -1964,7 +2038,8 @@ if (prev->next == table) break; if (!prev) { - dprintk("unwind: failed to find unwind table %p\n", (void *) table); + UNW_DPRINT(0, "unwind.%s: failed to find unwind table %p\n", + __FUNCTION__, (void *) table); spin_unlock_irqrestore(&unw.lock, flags); return; } diff -Nru a/arch/ia64/kernel/unwind_i.h b/arch/ia64/kernel/unwind_i.h --- a/arch/ia64/kernel/unwind_i.h Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/kernel/unwind_i.h Sat Mar 15 18:40:41 2003 @@ -137,7 +137,8 @@ UNW_INSN_SETNAT_MEMSTK, /* s[dst+1].nat.type = MEMSTK; s[dst+1].nat.off = *s.pri_unat - s[dst] */ UNW_INSN_SETNAT_TYPE, /* s[dst+1].nat.type = val */ - UNW_INSN_LOAD /* s[dst] = *s[val] */ + UNW_INSN_LOAD, /* s[dst] = *s[val] */ + UNW_INSN_MOVE_SCRATCH, /* s[dst] = scratch reg "val" */ }; struct unw_insn { diff -Nru a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c --- a/arch/ia64/mm/fault.c Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/mm/fault.c Sat Mar 15 18:40:44 2003 @@ -55,7 +55,7 @@ /* * 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); @@ -79,7 +79,7 @@ # if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \ || (1 << VM_EXEC_BIT) != VM_EXEC) -# error File is out of sync with . Pleaes update. +# error File is out of sync with . Please update. # endif mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c --- a/arch/ia64/mm/hugetlbpage.c Sat Mar 15 18:40:42 2003 +++ b/arch/ia64/mm/hugetlbpage.c Sat Mar 15 18:40:42 2003 @@ -19,6 +19,8 @@ #include +#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT) + static long htlbpagemem; int htlbpage_max; static long htlbzone_pages; @@ -98,7 +100,6 @@ set_pte(page_table, entry); return; } - /* * This function checks for proper alignment of input addr and len parameters. */ @@ -108,6 +109,20 @@ return -EINVAL; if (addr & ~HPAGE_MASK) return -EINVAL; + if (REGION_NUMBER(addr) != REGION_HPAGE) + return -EINVAL; + + return 0; +} +/* This function checks if the address and address+len falls out of HugeTLB region. It + * return -EINVAL if any part of address range falls in HugeTLB region. + */ +int is_invalid_hugepage_range(unsigned long addr, unsigned long len) +{ + if (REGION_NUMBER(addr) == REGION_HPAGE) + return -EINVAL; + if (REGION_NUMBER(addr+len) == REGION_HPAGE) + return -EINVAL; return 0; } @@ -173,6 +188,39 @@ return i; } +struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long addr) +{ + if (mm->used_hugetlb) { + if (REGION_NUMBER(addr) == REGION_HPAGE) { + struct vm_area_struct *vma = find_vma(mm, addr); + if (vma && is_vm_hugetlb_page(vma)) + return vma; + } + } + return NULL; +} + +struct page *follow_huge_addr(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, int write) +{ + struct page *page; + pte_t *ptep; + + ptep = huge_pte_offset(mm, addr); + page = pte_page(*ptep); + page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT); + get_page(page); + return page; +} +int pmd_huge(pmd_t pmd) +{ + return 0; +} +struct page * +follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write) +{ + return NULL; +} + void free_huge_page(struct page *page) { BUG_ON(page_count(page)); @@ -204,8 +252,6 @@ BUG_ON(start & (HPAGE_SIZE - 1)); BUG_ON(end & (HPAGE_SIZE - 1)); - spin_lock(&htlbpage_lock); - spin_unlock(&htlbpage_lock); for (address = start; address < end; address += HPAGE_SIZE) { pte = huge_pte_offset(mm, address); if (pte_none(*pte)) @@ -257,8 +303,12 @@ ret = -ENOMEM; goto out; } - add_to_page_cache(page, mapping, idx, GFP_ATOMIC); + ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC); unlock_page(page); + if (ret) { + free_huge_page(page); + goto out; + } } set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE); } @@ -267,6 +317,29 @@ return ret; } +unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, + unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct *vmm; + + if (len > RGN_MAP_LIMIT) + return -ENOMEM; + if (len & ~HPAGE_MASK) + return -EINVAL; + /* This code assumes that REGION_HPAGE != 0. */ + if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1))) + addr = TASK_HPAGE_BASE; + else + addr = ALIGN(addr, HPAGE_SIZE); + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (REGION_OFFSET(addr) + len > RGN_MAP_LIMIT) + return -ENOMEM; + if (!vmm || (addr + len) <= vmm->vm_start) + return addr; + addr = ALIGN(vmm->vm_end, HPAGE_SIZE); + } +} void update_and_free_page(struct page *page) { int j; @@ -302,8 +375,8 @@ break; } page = list_entry(p, struct page, list); - if ((page_zone(page))->name[0] != 'H') // Look for non-Highmem - map = page; + if (!PageHighMem(page)) + map = page; } if (map) { list_del(&map->list); @@ -317,8 +390,8 @@ int set_hugetlb_mem_size(int count) { - int j, lcount; - struct page *page, *map; + int lcount; + struct page *page ; extern long htlbzone_pages; extern struct list_head htlbpage_freelist; @@ -417,5 +490,4 @@ struct vm_operations_struct hugetlb_vm_ops = { .nopage = hugetlb_nopage, - .close = zap_hugetlb_resources, }; diff -Nru a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c --- a/arch/ia64/mm/tlb.c Sat Mar 15 18:40:43 2003 +++ b/arch/ia64/mm/tlb.c Sat Mar 15 18:40:43 2003 @@ -81,9 +81,13 @@ } read_unlock(&tasklist_lock); /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ - for (i = 0; i < NR_CPUS; ++i) - if (i != smp_processor_id()) - per_cpu(ia64_need_tlb_flush, i) = 1; + { + int cpu = get_cpu(); /* prevent preemption/migration */ + for (i = 0; i < NR_CPUS; ++i) + if (i != cpu) + per_cpu(ia64_need_tlb_flush, i) = 1; + put_cpu(); + } local_flush_tlb_all(); } diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Sat Mar 15 18:40:41 2003 +++ b/arch/ia64/pci/pci.c Sat Mar 15 18:40:41 2003 @@ -272,3 +272,76 @@ return 0; } + +/** + * pci_cacheline_size - determine cacheline size for PCI devices + * @dev: void + * + * We want to use the line-size of the outer-most cache. We assume + * that this line-size is the same for all CPUs. + * + * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info(). + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +static unsigned long +pci_cacheline_size (void) +{ + u64 levels, unique_caches; + s64 status; + pal_cache_config_info_t cci; + static u8 cacheline_size; + + if (cacheline_size) + return cacheline_size; + + status = ia64_pal_cache_summary(&levels, &unique_caches); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + + status = ia64_pal_cache_config_info(levels - 1, /* cache_type (data_or_unified)= */ 2, + &cci); + if (status != 0) { + printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed (status=%ld)\n", + __FUNCTION__, status); + return SMP_CACHE_BYTES; + } + cacheline_size = 1 << cci.pcci_line_size; + return cacheline_size; +} + +/** + * pcibios_prep_mwi - helper function for drivers/pci/pci.c:pci_set_mwi() + * @dev: the PCI device for which MWI is enabled + * + * For ia64, we can get the cacheline sizes from PAL. + * + * RETURNS: An appropriate -ERRNO error value on eror, or zero for success. + */ +int +pcibios_prep_mwi (struct pci_dev *dev) +{ + unsigned long desired_linesize, current_linesize; + int rc = 0; + u8 pci_linesize; + + desired_linesize = pci_cacheline_size(); + + pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &pci_linesize); + current_linesize = 4 * pci_linesize; + if (desired_linesize != current_linesize) { + printk(KERN_WARNING "PCI: slot %s has incorrect PCI cache line size of %lu bytes,", + dev->slot_name, current_linesize); + if (current_linesize > desired_linesize) { + printk(" expected %lu bytes instead\n", desired_linesize); + rc = -EINVAL; + } else { + printk(" correcting to %lu\n", desired_linesize); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, desired_linesize / 4); + } + } + return rc; +} diff -Nru a/arch/ia64/sn/io/Makefile b/arch/ia64/sn/io/Makefile --- a/arch/ia64/sn/io/Makefile Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/sn/io/Makefile Sat Mar 15 18:40:40 2003 @@ -17,6 +17,6 @@ hcl.o labelcl.o invent.o sgi_io_sim.o \ klgraph_hack.o hcl_util.o cdl.o hubdev.o hubspc.o \ alenlist.o pci.o pci_dma.o ate_utils.o \ - ifconfig_net.o io.o ifconfig_bus.o + ifconfig_net.o io.o ioconfig_bus.o obj-$(CONFIG_PCIBA) += pciba.o diff -Nru a/arch/ia64/sn/io/ioconfig_bus.c b/arch/ia64/sn/io/ioconfig_bus.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/ioconfig_bus.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,402 @@ +/* $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. + * + * ioconfig_bus - SGI's Persistent PCI Bus Numbering. + * + * 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 + +#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING" +#define SGI_IOCONFIG_BUS_VERSION "1.0" + +/* + * Some Global definitions. + */ +devfs_handle_t ioconfig_bus_handle = NULL; +unsigned long ioconfig_bus_debug = 0; + +#ifdef IOCONFIG_BUS_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +u64 ioconfig_file = 0; +u64 ioconfig_file_size = 0; +u64 ioconfig_activated = 0; +char ioconfig_kernopts[128]; + +/* + * For debugging purpose .. hardcode a table .. + */ +struct ascii_moduleid *ioconfig_bus_table; +u64 ioconfig_bus_table_size = 0; + + +int free_entry = 0; +int new_entry = 0; + +int next_basebus_number = 0; + +void +ioconfig_get_busnum(char *io_moduleid, int *bus_num) +{ + struct ascii_moduleid *temp; + int index; + + DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid); + + *bus_num = -1; + temp = ioconfig_bus_table; + for (index = 0; index < free_entry; temp++, index++) { + if ( (io_moduleid[0] == temp->io_moduleid[0]) && + (io_moduleid[1] == temp->io_moduleid[1]) && + (io_moduleid[2] == temp->io_moduleid[2]) && + (io_moduleid[4] == temp->io_moduleid[4]) && + (io_moduleid[5] == temp->io_moduleid[5]) ) { + *bus_num = index * 0x10; + return; + } + } + + /* + * New IO Brick encountered. + */ + if (((int)io_moduleid[0]) == 0) { + DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid); + return; + } + + io_moduleid[3] = '#'; + strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid); + *bus_num = free_entry * 0x10; + free_entry++; +} + +void +dump_ioconfig_table() +{ + + int index = 0; + struct ascii_moduleid *temp; + + temp = ioconfig_bus_table; + while (index < free_entry) { + DBG("ASSCI Module ID %s\n", temp->io_moduleid); + temp++; + index++; + } +} + +/* + * nextline + * This routine returns the nextline in the buffer. + */ +int nextline(char *buffer, char **next, char *line) +{ + + char *temp; + + if (buffer[0] == 0x0) { + return(0); + } + + temp = buffer; + while (*temp != 0) { + *line = *temp; + if (*temp != '\n'){ + *line = *temp; + temp++; line++; + } else + break; + } + + if (*temp == 0) + *next = temp; + else + *next = ++temp; + + return(1); +} + +/* + * build_pcibus_name + * This routine parses the ioconfig contents read into + * memory by ioconfig command in EFI and builds the + * persistent pci bus naming table. + */ +void +build_moduleid_table(char *file_contents, struct ascii_moduleid *table) +{ + /* + * Read the whole file into memory. + */ + int rc; + char *name; + char *temp; + char *next; + char *current; + char *line; + struct ascii_moduleid *moduleid; + + line = kmalloc(256, GFP_KERNEL); + memset(line, 0,256); + name = kmalloc(125, GFP_KERNEL); + memset(name, 0, 125); + moduleid = table; + current = file_contents; + while (nextline(current, &next, line)){ + + DBG("current 0x%lx next 0x%lx\n", current, next); + + temp = line; + /* + * Skip all leading Blank lines .. + */ + while (isspace(*temp)) + if (*temp != '\n') + temp++; + else + break; + + if (*temp == '\n') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Skip comment lines + */ + if (*temp == '#') { + current = next; + memset(line, 0, 256); + continue; + } + + /* + * Get the next free entry in the table. + */ + rc = sscanf(temp, "%s", name); + strcpy(&moduleid->io_moduleid[0], name); + DBG("Found %s\n", name); + moduleid++; + free_entry++; + current = next; + memset(line, 0, 256); + } + + new_entry = free_entry; + kfree(line); + kfree(name); + + return; +} + +void +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; + } + } + + 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); + + /* + * If ioconfig options are given on the bootline .. take it. + */ + if (*ioconfig_kernopts != '\0') { + /* + * ioconfig="..." kernel options given. + */ + DBG("ioconfig_bus_init: Kernel Options given.\n"); + (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table); + (void) dump_ioconfig_table(ioconfig_bus_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(ioconfig_bus_table); + } else { + DBG("ioconfig_bus_init: ioconfig command not executed in prom\n"); + } + +} + +void +ioconfig_bus_new_entries(void) +{ + + + int index = 0; + struct ascii_moduleid *temp; + + if ((ioconfig_activated) && (free_entry > new_entry)) { + printk("### Please add the following new IO Bricks Module ID \n"); + printk("### to your Persistent Bus Numbering Config File\n"); + } else + return; + + index = new_entry; + temp = &ioconfig_bus_table[index]; + while (index < free_entry) { + printk("%s\n", temp); + temp++; + index++; + } + printk("### End\n"); + +} +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)); + 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)); + + return 0; +} + +/* + * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_open(struct inode * inode, struct file * filp) +{ + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_open called.\n"); + } + + return(0); + +} + +/* + * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus". + */ +static int ioconfig_bus_close(struct inode * inode, struct file * filp) +{ + + if (ioconfig_bus_debug) { + DBG("ioconfig_bus_close called.\n"); + } + + return(0); +} + +struct file_operations ioconfig_bus_fops = { + ioctl:ioconfig_bus_ioctl, + open:ioconfig_bus_open, /* open */ + release:ioconfig_bus_close /* release */ +}; + + +/* + * init_ifconfig_bus() - Boot time initialization. Ensure that it is called + * after devfs has been initialized. + * + */ +int init_ioconfig_bus(void) +{ + ioconfig_bus_handle = NULL; + ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus", + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &ioconfig_bus_fops, NULL); + + if (ioconfig_bus_handle == NULL) { + panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n"); + } + + return(0); + +} + +static int __init ioconfig_bus_setup (char *str) +{ + + char *temp; + + DBG("ioconfig_bus_setup: Kernel Options %s\n", str); + + temp = (char *)ioconfig_kernopts; + memset(temp, 0, 128); + while ( (*str != '\0') && !isspace (*str) ) { + if (*str == ',') { + *temp = '\n'; + temp++; + str++; + continue; + } + *temp = *str; + temp++; + str++; + } + + return(0); + +} +__setup("ioconfig=", ioconfig_bus_setup); diff -Nru a/arch/ia64/sn/io/sn2/Makefile b/arch/ia64/sn/io/sn2/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/Makefile Sat Mar 15 18:40:45 2003 @@ -0,0 +1,19 @@ +# +# 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. +# +# Makefile for the sn2 specific io routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +obj-y += bte_error.o geo_op.o klconflib.o klgraph.o l1.o \ + l1_command.o ml_iograph.o ml_SN_init.o ml_SN_intr.o module.o \ + pci_bus_cvlink.o pciio.o pic.o sgi_io_init.o shub.o shuberror.o \ + shub_intr.o shubio.o xbow.o xtalk.o + +obj-$(CONFIG_KDB) += kdba_io.o + +obj-$(CONFIG_SHUB_1_0_SPECIFIC) += efi-rtc.o diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/geo_op.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,314 @@ +/* $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. + */ + +/* + * @doc file m:hwcfg + * DESCRIPTION: + * + * This file contains routines for manipulating and generating + * Geographic IDs. They are in a file by themself since they have + * no dependencies on other modules. + * + * ORIGIN: + * + * New for SN2 + */ + +#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 + +/********** Global functions and data (visible outside the module) ***********/ + +/* + * @doc gf:geo_module + * + * moduleid_t geo_module(geoid_t g) + * + * DESCRIPTION: + * + * Return the moduleid component of a geoid. + * + * INTERNALS: + * + * Return INVALID_MODULE for an invalid geoid. Otherwise extract the + * moduleid from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +moduleid_t +geo_module(geoid_t g) +{ + if (g.any.type == GEO_TYPE_INVALID) + return INVALID_MODULE; + else + return g.any.module; +} + + +/* + * @doc gf:geo_slab + * + * slabid_t geo_slab(geoid_t g) + * + * DESCRIPTION: + * + * Return the slabid component of a geoid. + * + * INTERNALS: + * + * Return INVALID_SLAB for an invalid geoid. Otherwise extract the + * slabid from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +slabid_t +geo_slab(geoid_t g) +{ + if (g.any.type == GEO_TYPE_INVALID) + return INVALID_SLAB; + else + return g.any.slab; +} + + +/* + * @doc gf:geo_type + * + * geo_type_t geo_type(geoid_t g) + * + * DESCRIPTION: + * + * Return the type component of a geoid. + * + * INTERNALS: + * + * Extract the type from the structure, and return it. + * + * ORIGIN: + * + * New for SN2 + */ + +geo_type_t +geo_type(geoid_t g) +{ + return g.any.type; +} + + +/* + * @doc gf:geo_valid + * + * int geo_valid(geoid_t g) + * + * DESCRIPTION: + * + * Return nonzero if g has a valid geoid type. + * + * INTERNALS: + * + * Test the type against GEO_TYPE_INVALID, and return the result. + * + * ORIGIN: + * + * New for SN2 + */ + +int +geo_valid(geoid_t g) +{ + return g.any.type != GEO_TYPE_INVALID; +} + + +/* + * @doc gf:geo_cmp + * + * int geo_cmp(geoid_t g0, geoid_t g1) + * + * DESCRIPTION: + * + * Compare two geoid_t values, from the coarsest field to the finest. + * The comparison should be consistent with the physical locations of + * of the hardware named by the geoids. + * + * INTERNALS: + * + * First compare the module, then the slab, type, and type-specific fields. + * + * ORIGIN: + * + * New for SN2 + */ + +int +geo_cmp(geoid_t g0, geoid_t g1) +{ + int rv; + + /* Compare the common fields */ + rv = MODULE_CMP(geo_module(g0), geo_module(g1)); + if (rv != 0) + return rv; + + rv = geo_slab(g0) - geo_slab(g1); + if (rv != 0) + return rv; + + /* Within a slab, sort by type */ + rv = geo_type(g0) - geo_type(g1); + if (rv != 0) + return rv; + + switch(geo_type(g0)) { + case GEO_TYPE_CPU: + rv = g0.cpu.slice - g1.cpu.slice; + break; + + case GEO_TYPE_IOCARD: + rv = g0.pcicard.bus - g1.pcicard.bus; + if (rv) break; + rv = SLOTNUM_GETSLOT(g0.pcicard.slot) - + SLOTNUM_GETSLOT(g1.pcicard.slot); + break; + + case GEO_TYPE_MEM: + rv = g0.mem.membus - g1.mem.membus; + if (rv) break; + rv = g0.mem.memslot - g1.mem.memslot; + break; + + default: + rv = 0; + } + + return rv; +} + + +/* + * @doc gf:geo_new + * + * geoid_t geo_new(geo_type_t type, ...) + * + * DESCRIPTION: + * + * Generate a new geoid_t value of the given type from its components. + * Expected calling sequences: + * \@itemize \@bullet + * \@item + * \@code\{geo_new(GEO_TYPE_INVALID)\} + * \@item + * \@code\{geo_new(GEO_TYPE_MODULE, moduleid_t m)\} + * \@item + * \@code\{geo_new(GEO_TYPE_NODE, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_RTR, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_IOCNTL, moduleid_t m, slabid_t s)\} + * \@item + * \@code\{geo_new(GEO_TYPE_IOCARD, moduleid_t m, slabid_t s, char bus, slotid_t slot)\} + * \@item + * \@code\{geo_new(GEO_TYPE_CPU, moduleid_t m, slabid_t s, char slice)\} + * \@item + * \@code\{geo_new(GEO_TYPE_MEM, moduleid_t m, slabid_t s, char membus, char slot)\} + * \@end itemize + * + * Invalid types return a GEO_TYPE_INVALID geoid_t. + * + * INTERNALS: + * + * Use the type to determine which fields to expect. Write the fields into + * a new geoid_t and return it. Note: scalars smaller than an "int" are + * promoted to "int" by the "..." operator, so we need extra casts on "char", + * "slotid_t", and "slabid_t". + * + * ORIGIN: + * + * New for SN2 + */ + +geoid_t +geo_new(geo_type_t type, ...) +{ + va_list al; + geoid_t g; + memset(&g, 0, sizeof(g)); + + va_start(al, type); + + /* Make sure the type is sane */ + if (type >= GEO_TYPE_MAX) + type = GEO_TYPE_INVALID; + + g.any.type = type; + if (type == GEO_TYPE_INVALID) + goto done; /* invalid geoids have no components at all */ + + g.any.module = va_arg(al, moduleid_t); + if (type == GEO_TYPE_MODULE) + goto done; + + g.any.slab = (slabid_t)va_arg(al, int); + + /* Some types have additional components */ + switch(type) { + case GEO_TYPE_CPU: + g.cpu.slice = (char)va_arg(al, int); + break; + + case GEO_TYPE_IOCARD: + g.pcicard.bus = (char)va_arg(al, int); + g.pcicard.slot = (slotid_t)va_arg(al, int); + break; + + case GEO_TYPE_MEM: + g.mem.membus = (char)va_arg(al, int); + g.mem.memslot = (char)va_arg(al, int); + break; + + default: + break; + } + + done: + va_end(al); + return g; +} diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/klconflib.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,933 @@ +/* $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 +#include +#include +#include + +#define printf printk +int hasmetarouter; + +#define LDEBUG 0 +#define NIC_UNKNOWN ((nic_t) -1) + +#undef DEBUG_KLGRAPH +#ifdef DEBUG_KLGRAPH +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_KLGRAPH */ + +static void sort_nic_names(lboard_t *) ; + +u64 klgraph_addr[MAX_COMPACT_NODES]; +int module_number = 0; + +lboard_t * +find_lboard(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (start->brd_type == brd_type) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +klinfo_t * +find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) +{ + int index, j; + + if (kli == (klinfo_t *)NULL) { + index = 0; + } else { + for (j = 0; j < KLCF_NUM_COMPS(brd); j++) { + if (kli == KLCF_COMP(brd, j)) + break; + } + index = j; + if (index == KLCF_NUM_COMPS(brd)) { + DBG("find_component: Bad pointer: 0x%p\n", kli); + return (klinfo_t *)NULL; + } + index++; /* next component */ + } + + for (; index < KLCF_NUM_COMPS(brd); index++) { + kli = KLCF_COMP(brd, index); + DBG("find_component: brd %p kli %p request type = 0x%x kli type 0x%x\n", brd, kli, kli->struct_type, KLCF_COMP_TYPE(kli)); + if (KLCF_COMP_TYPE(kli) == struct_type) + return kli; + } + + /* Didn't find it. */ + return (klinfo_t *)NULL; +} + +klinfo_t * +find_first_component(lboard_t *brd, unsigned char struct_type) +{ + return find_component(brd, (klinfo_t *)NULL, struct_type); +} + +lboard_t * +find_lboard_modslot(lboard_t *start, geoid_t geoid) +{ + /* Search all boards stored on this node. */ + while (start) { + if (geo_cmp(start->brd_geoid, geoid)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module(lboard_t *start, geoid_t geoid) +{ + /* Search all boards stored on this node. */ + while (start) { + if (geo_cmp(start->brd_geoid, geoid)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * +find_lboard_module_class(lboard_t *start, geoid_t geoid, + unsigned char brd_type) +{ + while (start) { + DBG("find_lboard_module_class: lboard 0x%p, start->brd_geoid 0x%x, mod 0x%x, start->brd_type 0x%x, brd_type 0x%x\n", start, start->brd_geoid, geoid, start->brd_type, brd_type); + + if (geo_cmp(start->brd_geoid, geoid) && + (KLCLASS(start->brd_type) == KLCLASS(brd_type))) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +/* + * Convert a NIC name to a name for use in the hardware graph. + */ +void +nic_name_convert(char *old_name, char *new_name) +{ + int i; + char c; + char *compare_ptr; + + if ((old_name[0] == '\0') || (old_name[1] == '\0')) { + strcpy(new_name, EDGE_LBL_XWIDGET); + } else { + for (i = 0; i < strlen(old_name); i++) { + c = old_name[i]; + + if (isalpha(c)) + new_name[i] = tolower(c); + else if (isdigit(c)) + new_name[i] = c; + else + new_name[i] = '_'; + } + new_name[i] = '\0'; + } + + /* XXX - + * Since a bunch of boards made it out with weird names like + * IO6-fibbbed and IO6P2, we need to look for IO6 in a name and + * replace it with "baseio" to avoid confusion in the field. + * We also have to make sure we don't report media_io instead of + * baseio. + */ + + /* Skip underscores at the beginning of the name */ + for (compare_ptr = new_name; (*compare_ptr) == '_'; compare_ptr++) + ; + + /* + * Check for some names we need to replace. Early boards + * had junk following the name so check only the first + * characters. + */ + if (!strncmp(new_name, "io6", 3) || + !strncmp(new_name, "mio", 3) || + !strncmp(new_name, "media_io", 8)) + strcpy(new_name, "baseio"); + else if (!strncmp(new_name, "divo", 4)) + strcpy(new_name, "divo") ; + +} + +/* + * Find the lboard structure and get the board name. + * If we can't find the structure or it's too low a revision, + * use default name. + */ +lboard_t * +get_board_name(nasid_t nasid, geoid_t geoid, slotid_t slot, char *name) +{ + lboard_t *brd; + + brd = find_lboard_modslot((lboard_t *)KL_CONFIG_INFO(nasid), + geoid); + +#ifndef _STANDALONE + { + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + + if (!brd && (NODEPDA(cnode)->xbow_peer != INVALID_NASID)) + brd = find_lboard_modslot((lboard_t *) + KL_CONFIG_INFO(NODEPDA(cnode)->xbow_peer), + geoid); + } +#endif + + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, name); + } + + /* + * PV # 540860 + * If the name is not 'baseio' + * get the lowest of all the names in the nic string. + * This is needed for boards like divo, which can have + * a bunch of daughter cards, but would like to be called + * divo. We could do this for baseio + * but it has some special case names that we would not + * like to disturb at this point. + */ + + /* gfx boards don't need any of this name scrambling */ + if (brd && (KLCLASS(brd->brd_type) == KLCLASS_GFX)) { + return(brd); + } + + if (!(!strcmp(name, "baseio") )) { + if (brd) { + sort_nic_names(brd) ; + /* Convert to small case, '-' to '_' etc */ + nic_name_convert(brd->brd_name, name) ; + } + } + + return(brd); +} + +/* + * get_actual_nasid + * + * Completely disabled brds have their klconfig on + * some other nasid as they have no memory. But their + * actual nasid is hidden in the klconfig. Use this + * routine to get it. Works for normal boards too. + */ +nasid_t +get_actual_nasid(lboard_t *brd) +{ + klhub_t *hub ; + + if (!brd) + return INVALID_NASID ; + + /* find out if we are a completely disabled brd. */ + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + if (!hub) + return INVALID_NASID ; + if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ + return hub->hub_info.physid ; + else + return brd->brd_nasid ; +} + +int +xbow_port_io_enabled(nasid_t nasid, int link) +{ + lboard_t *brd; + klxbow_t *xbow_p; + + /* + * look for boards that might contain an xbow or xbridge + */ + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW); + if (brd == NULL) return 0; + + if ((xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW)) + == NULL) + return 0; + + if (!XBOW_PORT_TYPE_IO(xbow_p, link) || !XBOW_PORT_IS_ENABLED(xbow_p, link)) + return 0; + + return 1; +} + +void +board_to_path(lboard_t *brd, char *path) +{ + moduleid_t modnum; + char *board_name; + char buffer[16]; + + ASSERT(brd); + + switch (KLCLASS(brd->brd_type)) { + + case KLCLASS_NODE: + board_name = EDGE_LBL_NODE; + break; + case KLCLASS_ROUTER: + if (brd->brd_type == KLTYPE_META_ROUTER) { + board_name = EDGE_LBL_META_ROUTER; + hasmetarouter++; + } else if (brd->brd_type == KLTYPE_REPEATER_ROUTER) { + board_name = EDGE_LBL_REPEATER_ROUTER; + hasmetarouter++; + } else + board_name = EDGE_LBL_ROUTER; + break; + case KLCLASS_MIDPLANE: + board_name = EDGE_LBL_MIDPLANE; + break; + case KLCLASS_IO: + board_name = EDGE_LBL_IO; + break; + case KLCLASS_IOBRICK: + 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 + board_name = EDGE_LBL_IOBRICK; + break; + default: + board_name = EDGE_LBL_UNKNOWN; + } + + modnum = geo_module(brd->brd_geoid); + memset(buffer, 0, 16); + format_module_id(buffer, modnum, MODULE_FORMAT_BRIEF); + 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 + + +/* Get the canonical hardware graph name for the given pci component + * on the given io board. + */ +void +device_component_canonical_name_get(lboard_t *brd, + klinfo_t *component, + char *name) +{ + slotid_t slot; + char board_name[20]; + + ASSERT(brd); + + /* Convert the [ CLASS | TYPE ] kind of slotid + * into a string + */ + slot = brd->brd_slot; + + /* Get the io board name */ + if (!brd || (brd->brd_sversion < 2)) { + strcpy(name, EDGE_LBL_XWIDGET); + } else { + nic_name_convert(brd->brd_name, board_name); + } + + /* Give out the canonical name of the pci device*/ + sprintf(name, + "/dev/hw/"EDGE_LBL_MODULE "/%x/"EDGE_LBL_SLAB"/%d/" + EDGE_LBL_SLOT"/%s/"EDGE_LBL_PCI"/%d", + geo_module(brd->brd_geoid), geo_slab(brd->brd_geoid), + board_name, KLCF_BRIDGE_W_ID(component)); +} + +/* + * Get the serial number of the main component of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + * Assumptions: Nic manufacturing string has the following format + * *Serial:;* + */ +static int +component_serial_number_get(lboard_t *board, + klconf_off_t mfg_nic_offset, + char *serial_number, + char *key_pattern) +{ + + char *mfg_nic_string; + char *serial_string,*str; + int i; + char *serial_pattern = "Serial:"; + + /* We have an error on a null mfg nic offset */ + if (!mfg_nic_offset) + return(1); + /* Get the hub's manufacturing nic information + * which is in the form of a pre-formatted string + */ + mfg_nic_string = + (char *)NODE_OFFSET_TO_K0(NASID_GET(board), + mfg_nic_offset); + /* There is no manufacturing nic info */ + if (!mfg_nic_string) + return(1); + + str = mfg_nic_string; + /* Look for the key pattern first (if it is specified) + * and then print the serial number corresponding to that. + */ + if (strcmp(key_pattern,"") && + !(str = strstr(mfg_nic_string,key_pattern))) + return(1); + + /* There is no serial number info in the manufacturing + * nic info + */ + if (!(serial_string = strstr(str,serial_pattern))) + return(1); + + serial_string = serial_string + strlen(serial_pattern); + /* Copy the serial number information from the klconfig */ + i = 0; + while (serial_string[i] != ';') { + serial_number[i] = serial_string[i]; + i++; + } + serial_number[i] = 0; + + return(0); +} +/* + * Get the serial number of a board + * Returns 0 if a valid serial number is found + * 1 otherwise. + */ + +int +board_serial_number_get(lboard_t *board,char *serial_number) +{ + ASSERT(board && serial_number); + if (!board || !serial_number) + return(1); + + strcpy(serial_number,""); + switch(KLCLASS(board->brd_type)) { + case KLCLASS_CPU: { /* Node board */ + klhub_t *hub; + + /* Get the hub component information */ + hub = (klhub_t *)find_first_component(board, + KLSTRUCT_HUB); + /* If we don't have a hub component on an IP27 + * then we have a weird klconfig. + */ + if (!hub) + return(1); + /* Get the serial number information from + * the hub's manufacturing nic info + */ + if (component_serial_number_get(board, + hub->hub_mfg_nic, + serial_number, + "IP37")) + return(1); + break; + } + case KLCLASS_IO: { /* IO board */ + if (KLTYPE(board->brd_type) == KLTYPE_TPU) { + /* Special case for TPU boards */ + kltpu_t *tpu; + + /* 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, + 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; + } + } + case KLCLASS_ROUTER: { /* Router board */ + klrou_t *router; + + /* Get the router component information */ + router = (klrou_t *)find_first_component(board, + KLSTRUCT_ROU); + /* If we don't have a router component on a router board + * then we have a weird klconfig. + */ + if (!router) + return(1); + /* Get the serial number information from + * the router's manufacturing nic info + */ + if (component_serial_number_get(board, + router->rou_mfg_nic, + serial_number, + "")) + return(1); + break; + } + case KLCLASS_GFX: { /* Gfx board */ + klgfx_t *graphics; + + /* Get the graphics component information */ + graphics = (klgfx_t *)find_first_component(board, KLSTRUCT_GFX); + /* If we don't have a gfx component on a gfx board + * then we have a weird klconfig. + */ + if (!graphics) + return(1); + /* Get the serial number information from + * the graphics's manufacturing nic info + */ + if (component_serial_number_get(board, + graphics->gfx_mfg_nic, + serial_number, + "")) + return(1); + break; + } + default: + strcpy(serial_number,""); + break; + } + return(0); +} + +#include "asm/sn/sn_private.h" + +xwidgetnum_t +nodevertex_widgetnum_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + return(hubinfo_p->h_widgetid); +} + +devfs_handle_t +nodevertex_xbow_peer_get(devfs_handle_t node_vtx) +{ + hubinfo_t hubinfo_p; + nasid_t xbow_peer_nasid; + cnodeid_t xbow_peer; + + hwgraph_info_get_LBL(node_vtx, INFO_LBL_NODE_INFO, + (arbitrary_info_t *) &hubinfo_p); + xbow_peer_nasid = hubinfo_p->h_nodepda->xbow_peer; + if(xbow_peer_nasid == INVALID_NASID) + return ( (devfs_handle_t)-1); + xbow_peer = NASID_TO_COMPACT_NODEID(xbow_peer_nasid); + return(NODEPDA(xbow_peer)->node_vertex); +} + +/* NIC Sorting Support */ + +#define MAX_NICS_PER_STRING 32 +#define MAX_NIC_NAME_LEN 32 + +static char * +get_nic_string(lboard_t *lb) +{ + int i; + klinfo_t *k = NULL ; + klconf_off_t mfg_off = 0 ; + char *mfg_nic = NULL ; + + for (i = 0; i < KLCF_NUM_COMPS(lb); i++) { + k = KLCF_COMP(lb, i) ; + switch(k->struct_type) { + case KLSTRUCT_BRI: + mfg_off = ((klbri_t *)k)->bri_mfg_nic ; + break ; + + case KLSTRUCT_HUB: + mfg_off = ((klhub_t *)k)->hub_mfg_nic ; + break ; + + case KLSTRUCT_ROU: + mfg_off = ((klrou_t *)k)->rou_mfg_nic ; + break ; + + case KLSTRUCT_GFX: + mfg_off = ((klgfx_t *)k)->gfx_mfg_nic ; + break ; + + case KLSTRUCT_TPU: + mfg_off = ((kltpu_t *)k)->tpu_mfg_nic ; + break ; + + case KLSTRUCT_GSN_A: + case KLSTRUCT_GSN_B: + mfg_off = ((klgsn_t *)k)->gsn_mfg_nic ; + break ; + + case KLSTRUCT_XTHD: + mfg_off = ((klxthd_t *)k)->xthd_mfg_nic ; + break; + + default: + mfg_off = 0 ; + break ; + } + if (mfg_off) + break ; + } + + if ((mfg_off) && (k)) + mfg_nic = (char *)NODE_OFFSET_TO_K0(k->nasid, mfg_off) ; + + return mfg_nic ; +} + +char * +get_first_string(char **ptrs, int n) +{ + int i ; + char *tmpptr ; + + if ((ptrs == NULL) || (n == 0)) + return NULL ; + + tmpptr = ptrs[0] ; + + if (n == 1) + return tmpptr ; + + for (i = 0 ; i < n ; i++) { + if (strcmp(tmpptr, ptrs[i]) > 0) + tmpptr = ptrs[i] ; + } + + return tmpptr ; +} + +int +get_ptrs(char *idata, char **ptrs, int n, char *label) +{ + int i = 0 ; + char *tmp = idata ; + + if ((ptrs == NULL) || (idata == NULL) || (label == NULL) || (n == 0)) + return 0 ; + + while ( (tmp = strstr(tmp, label)) ){ + tmp += strlen(label) ; + /* check for empty name field, and last NULL ptr */ + if ((i < (n-1)) && (*tmp != ';')) { + ptrs[i++] = tmp ; + } + } + + ptrs[i] = NULL ; + + return i ; +} + +/* + * sort_nic_names + * + * Does not really do sorting. Find the alphabetically lowest + * name among all the nic names found in a nic string. + * + * Return: + * Nothing + * + * Side Effects: + * + * lb->brd_name gets the new name found + */ + +static void +sort_nic_names(lboard_t *lb) +{ + char *nic_str ; + char *ptrs[MAX_NICS_PER_STRING] ; + char name[MAX_NIC_NAME_LEN] ; + char *tmp, *tmp1 ; + + *name = 0 ; + + /* Get the nic pointer from the lb */ + + if ((nic_str = get_nic_string(lb)) == NULL) + return ; + + tmp = get_first_string(ptrs, + get_ptrs(nic_str, ptrs, MAX_NICS_PER_STRING, "Name:")) ; + + if (tmp == NULL) + return ; + + if ( (tmp1 = strchr(tmp, ';')) ){ + strncpy(name, tmp, tmp1-tmp) ; + name[tmp1-tmp] = 0 ; + } else { + strncpy(name, tmp, (sizeof(name) -1)) ; + name[sizeof(name)-1] = 0 ; + } + + strcpy(lb->brd_name, name) ; +} + + + +char brick_types[MAX_BRICK_TYPES + 1] = "crikxdpn%#012345"; + +/* + * Format a module id for printing. + */ +void +format_module_id(char *buffer, moduleid_t m, int fmt) +{ + int rack, position; + char brickchar; + + rack = MODULE_GET_RACK(m); + ASSERT(MODULE_GET_BTYPE(m) < MAX_BRICK_TYPES); + brickchar = MODULE_GET_BTCHAR(m); + position = MODULE_GET_BPOS(m); + + if (fmt == MODULE_FORMAT_BRIEF) { + /* Brief module number format, eg. 002c15 */ + + /* Decompress the rack number */ + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + /* Add the brick type */ + *buffer++ = brickchar; + } + else if (fmt == MODULE_FORMAT_LONG) { + /* Fuller hwgraph format, eg. rack/002/bay/15 */ + + strcpy(buffer, EDGE_LBL_RACK "/"); buffer += strlen(buffer); + + *buffer++ = '0' + RACK_GET_CLASS(rack); + *buffer++ = '0' + RACK_GET_GROUP(rack); + *buffer++ = '0' + RACK_GET_NUM(rack); + + strcpy(buffer, "/" EDGE_LBL_RPOS "/"); buffer += strlen(buffer); + } + + /* Add the bay position, using at least two digits */ + if (position < 10) + *buffer++ = '0'; + sprintf(buffer, "%d", position); + +} + +/* + * Parse a module id, in either brief or long form. + * Returns < 0 on error. + * The long form does not include a brick type, so it defaults to 0 (CBrick) + */ +int +parse_module_id(char *buffer) +{ + unsigned int v, rack, bay, type, form; + moduleid_t m; + char c; + + if (strstr(buffer, EDGE_LBL_RACK "/") == buffer) { + form = MODULE_FORMAT_LONG; + buffer += strlen(EDGE_LBL_RACK "/"); + + /* A long module ID must be exactly 5 non-template chars. */ + if (strlen(buffer) != strlen("/" EDGE_LBL_RPOS "/") + 5) + return -1; + } + else { + form = MODULE_FORMAT_BRIEF; + + /* A brief module id must be exactly 6 characters */ + if (strlen(buffer) != 6) + return -2; + } + + /* The rack number must be exactly 3 digits */ + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && isdigit(buffer[2]))) + return -3; + + rack = 0; + v = *buffer++ - '0'; + if (v > RACK_CLASS_MASK(rack) >> RACK_CLASS_SHFT(rack)) + return -4; + RACK_ADD_CLASS(rack, v); + + v = *buffer++ - '0'; + if (v > RACK_GROUP_MASK(rack) >> RACK_GROUP_SHFT(rack)) + return -5; + RACK_ADD_GROUP(rack, v); + + v = *buffer++ - '0'; + /* rack numbers are 1-based */ + if (v-1 > RACK_NUM_MASK(rack) >> RACK_NUM_SHFT(rack)) + return -6; + RACK_ADD_NUM(rack, v); + + if (form == MODULE_FORMAT_BRIEF) { + /* Next should be a module type character. Accept ucase or lcase. */ + c = *buffer++; + if (!isalpha(c)) + return -7; + + /* strchr() returns a pointer into brick_types[], or NULL */ + type = (unsigned int)(strchr(brick_types, tolower(c)) - brick_types); + if (type > MODULE_BTYPE_MASK >> MODULE_BTYPE_SHFT) + return -8; + } + else { + /* Hardcode the module type, and skip over the boilerplate */ + type = MODULE_CBRICK; + + if (strstr(buffer, "/" EDGE_LBL_RPOS "/") != buffer) + return -9; + + buffer += strlen("/" EDGE_LBL_RPOS "/"); + } + + /* The bay number is last. Make sure it's exactly two digits */ + + if (!(isdigit(buffer[0]) && isdigit(buffer[1]) && !buffer[2])) + return -10; + + bay = 10 * (buffer[0] - '0') + (buffer[1] - '0'); + + if (bay > MODULE_BPOS_MASK >> MODULE_BPOS_SHFT) + return -11; + + m = RBT_TO_MODULE(rack, bay, type); + + /* avoid sign extending the moduleid_t */ + return (int)(unsigned short)m; +} diff -Nru a/arch/ia64/sn/io/sn2/klgraph.c b/arch/ia64/sn/io/sn2/klgraph.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/klgraph.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,866 @@ +/* $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. + */ + +/* + * klgraph.c- + * This file specifies the interface between the kernel and the PROM's + * configuration data structures. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #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(devfs_handle_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(devfs_handle_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(devfs_handle_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(devfs_handle_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)); +} + +char *hub_rev[] = { + "0.0", + "1.0", + "2.0", + "2.1", + "2.2", + "2.3" +}; + +/* + * Add detailed cpu inventory info to the hardware graph. + */ +void +klhwg_hub_invent_info(devfs_handle_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 +klhwg_add_hub(devfs_handle_t node_vertex, klhub_t *hub, cnodeid_t cnode) +{ + devfs_handle_t myhubv; + devfs_handle_t hub_mon; + 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); + rc = device_master_set(myhubv, node_vertex); + hub_mon = hwgraph_register(myhubv, EDGE_LBL_PERFMON, + 0, DEVFS_FL_AUTO_DEVNUM, + 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, + &shub_mon_fops, (void *)(long)cnode); +} + +/* ARGSUSED */ +void +klhwg_add_disabled_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu, slotid_t slot) +{ + devfs_handle_t my_cpu; + char name[120]; + cpuid_t cpu_id; + nasid_t nasid; + + 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); + (void) hwgraph_path_add(node_vertex, name, &my_cpu); + + 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 +klhwg_add_cpu(devfs_handle_t node_vertex, cnodeid_t cnode, klcpu_t *cpu) +{ + devfs_handle_t my_cpu, cpu_dir; + char name[120]; + cpuid_t cpu_id; + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + cpu_id = nasid_slice_to_cpuid(nasid, cpu->cpu_info.physid); + + sprintf(name, "%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); + 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); + (void) hwgraph_edge_add(cpu_dir, my_cpu, name); + } + + klhwg_cpu_invent_info(my_cpu, cnode, cpu); +} + + +void +klhwg_add_xbow(cnodeid_t cnode, nasid_t nasid) +{ + lboard_t *brd; + klxbow_t *xbow_p; + nasid_t hub_nasid; + cnodeid_t hub_cnode; + int widgetnum; + devfs_handle_t xbow_v, hubv; + /*REFERENCED*/ + graph_error_t err; + + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IOBRICK_XBOW)) == NULL) + return; + + 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; + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + if (!XBOW_PORT_TYPE_HUB(xbow_p, widgetnum)) + continue; + + hub_nasid = XBOW_PORT_NASID(xbow_p, widgetnum); + if (hub_nasid == INVALID_NASID) { + printk(KERN_WARNING "hub widget %d, skipping xbow graph\n", widgetnum); + continue; + } + + hub_cnode = NASID_TO_COMPACT_NODEID(hub_nasid); + + if (is_specified(arg_maxnodes) && hub_cnode == INVALID_CNODEID) { + continue; + } + + hubv = cnodeid_to_vertex(hub_cnode); + + err = hwgraph_path_add(hubv, EDGE_LBL_XTALK, &xbow_v); + if (err != GRAPH_SUCCESS) { + if (err == GRAPH_DUP) + printk(KERN_WARNING "klhwg_add_xbow: Check for " + "working routers and router links!"); + + PRINT_PANIC("klhwg_add_xbow: Failed to add " + "edge: vertex 0x%p to vertex 0x%p," + "error %d\n", + (void *)hubv, (void *)xbow_v, err); + } + xswitch_vertex_init(xbow_v); + + NODEPDA(hub_cnode)->xbow_vhdl = xbow_v; + + /* + * XXX - This won't work is we ever hook up two hubs + * by crosstown through a crossbow. + */ + if (hub_nasid != nasid) { + NODEPDA(hub_cnode)->xbow_peer = nasid; + 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 +klhwg_add_node(devfs_handle_t hwgraph_root, cnodeid_t cnode, gda_t *gdap) +{ + nasid_t nasid; + lboard_t *brd; + klhub_t *hub; + devfs_handle_t node_vertex = NULL; + char path_buffer[100]; + int rv; + char *s; + int board_disabled = 0; + klcpu_t *cpu; + + 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 { + devfs_handle_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); + + 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)); + } + + /* 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. + */ + 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_enabled(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); + else + break; + } while(brd); +} + + +/* ARGSUSED */ +void +klhwg_add_all_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + devfs_handle_t node_vertex; + char path_buffer[100]; + int rv; + + 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); + + if (!brd) + /* No routers stored in this node's memory */ + continue; + + 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) + 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 +klhwg_connect_one_router(devfs_handle_t hwgraph_root, lboard_t *brd, + cnodeid_t cnode, nasid_t nasid) +{ + klrou_t *router; + char path_buffer[50]; + char dest_path[50]; + devfs_handle_t router_hndl; + devfs_handle_t dest_hndl; + int rc; + 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; + } + + /* Generate a hardware graph path for this board. */ + board_to_path(brd, path_buffer); + + rc = hwgraph_traverse(hwgraph_root, path_buffer, &router_hndl); + + if (rc != GRAPH_SUCCESS && is_specified(arg_maxnodes)) + return; + + if (rc != GRAPH_SUCCESS) + printk(KERN_WARNING "Can't find router: %s", path_buffer); + + /* 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", + brd->brd_numcompts); + return; + } + + + /* Convert component 0 to klrou_t ptr */ + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), + brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + /* See if the port's active */ + if (router->rou_port[port].port_nasid == INVALID_NASID) { + GRPRINTF(("klhwg_connect_one_router: port %d inactive.\n", + port)); + continue; + } + if (is_specified(arg_maxnodes) && NASID_TO_COMPACT_NODEID(router->rou_port[port].port_nasid) + == INVALID_CNODEID) { + continue; + } + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + PRINT_PANIC("Can't find router: %s", dest_path); + } + GRPRINTF(("klhwg_connect_one_router: Link from %s/%d to %s\n", + path_buffer, port, dest_path)); + + sprintf(dest_path, "%d", port); + + rc = hwgraph_edge_add(router_hndl, dest_hndl, dest_path); + + if (rc == GRAPH_DUP) { + GRPRINTF(("Skipping port %d. nasid %d %s/%s\n", + port, router->rou_port[port].port_nasid, + path_buffer, dest_path)); + 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", + path_buffer, dest_path, (void *)dest_hndl, rc); + + } +} + + +void +klhwg_connect_routers(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + + 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); + + if (!brd) + continue; + + do { + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + klhwg_connect_one_router(hwgraph_root, brd, + cnode, nasid); + + /* Find the rest of the routers stored on this node. */ + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + + + +void +klhwg_connect_hubs(devfs_handle_t hwgraph_root) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd; + klhub_t *hub; + lboard_t *dest_brd; + devfs_handle_t hub_hndl; + devfs_handle_t dest_hndl; + char path_buffer[50]; + char dest_path[50]; + graph_error_t rc; + int port; + + for (cnode = 0; cnode < numnodes; 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); + + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + 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; + } + + if (is_specified(arg_maxnodes) && 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) + printk(KERN_WARNING "Can't find hub: %s", path_buffer); + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + hub->hub_port[port].port_nasid, + hub->hub_port[port].port_offset); + + /* Generate a hardware graph path for this board. */ + board_to_path(dest_brd, dest_path); + + rc = hwgraph_traverse(hwgraph_root, dest_path, &dest_hndl); + + if (rc != GRAPH_SUCCESS) { + if (is_specified(arg_maxnodes) && KL_CONFIG_DUPLICATE_BOARD(dest_brd)) + continue; + PRINT_PANIC("Can't find board: %s", dest_path); + } 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); + 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); + + } + } + } +} + +/* Store the pci/vme disabled board information as extended administrative + * hints which can later be used by the drivers using the device/driver + * admin interface. + */ +void +klhwg_device_disable_hints_add(void) +{ + cnodeid_t cnode; /* node we are looking at */ + nasid_t nasid; /* nasid of the node */ + lboard_t *board; /* board we are looking at */ + int comp_index; /* component index */ + klinfo_t *component; /* component in the board we are + * looking at + */ + char device_name[MAXDEVNAME]; + + for(cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + board = (lboard_t *)KL_CONFIG_INFO(nasid); + /* Check out all the board info stored on a node */ + while(board) { + /* No need to look at duplicate boards or non-io + * boards + */ + if (KL_CONFIG_DUPLICATE_BOARD(board) || + KLCLASS(board->brd_type) != KLCLASS_IO) { + board = KLCF_NEXT(board); + continue; + } + /* Check out all the components of a board */ + for (comp_index = 0; + comp_index < KLCF_NUM_COMPS(board); + comp_index++) { + component = KLCF_COMP(board,comp_index); + /* If the component is enabled move on to + * the next component + */ + if (KLCONFIG_INFO_ENABLED(component)) + continue; + /* NOTE : Since the prom only supports + * the disabling of pci devices the following + * piece of code makes sense. + * Make sure that this assumption is valid + */ + /* This component is disabled. Store this + * hint in the extended device admin table + */ + /* Get the canonical name of the pci device */ + device_component_canonical_name_get(board, + component, + device_name); +#ifdef DEBUG + printf("%s DISABLED\n",device_name); +#endif + } + /* go to the next board info stored on this + * node + */ + board = KLCF_NEXT(board); + } + } +} + +void +klhwg_add_all_modules(devfs_handle_t hwgraph_root) +{ + cmoduleid_t cm; + char name[128]; + devfs_handle_t vhdl; + devfs_handle_t module_vhdl; + int rc; + char buffer[16]; + + /* Add devices under each module */ + + for (cm = 0; cm < nummodules; cm++) { + /* Use module as module vertex fastinfo */ + + memset(buffer, 0, 16); + format_module_id(buffer, modules[cm]->id, MODULE_FORMAT_BRIEF); + sprintf(name, EDGE_LBL_MODULE "/%s", buffer); + + rc = hwgraph_path_add(hwgraph_root, name, &module_vhdl); + ASSERT(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_fastinfo_set(module_vhdl, (arbitrary_info_t) modules[cm]); + + /* Add system controller */ + sprintf(name, + EDGE_LBL_MODULE "/%s/" EDGE_LBL_L1, + buffer); + + rc = hwgraph_path_add(hwgraph_root, name, &vhdl); + ASSERT_ALWAYS(rc == GRAPH_SUCCESS); + rc = rc; + + hwgraph_info_add_LBL(vhdl, + INFO_LBL_ELSC, + (arbitrary_info_t) (__psint_t) 1); + + } +} + +void +klhwg_add_all_nodes(devfs_handle_t hwgraph_root) +{ + cnodeid_t cnode; + + for (cnode = 0; cnode < numnodes; cnode++) { + klhwg_add_node(hwgraph_root, cnode, NULL); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + klhwg_add_xbow(cnode, cnodeid_to_nasid(cnode)); + } + + /* + * As for router hardware inventory information, we set this + * up in router.c. + */ + + klhwg_add_all_routers(hwgraph_root); + klhwg_connect_routers(hwgraph_root); + klhwg_connect_hubs(hwgraph_root); + + /* Go through the entire system's klconfig + * to figure out which pci components have been disabled + */ + klhwg_device_disable_hints_add(); + +} diff -Nru a/arch/ia64/sn/io/sn2/l1.c b/arch/ia64/sn/io/sn2/l1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/l1.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,244 @@ +/* $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. + */ + +/* In general, this file is organized in a hierarchy from lower-level + * to higher-level layers, as follows: + * + * UART routines + * Bedrock/L1 "PPP-like" protocol implementation + * System controller "message" interface (allows multiplexing + * of various kinds of requests and responses with + * console I/O) + * Console interface: + * "l1_cons", the glue that allows the L1 to act + * as the system console for the stdio libraries + * + * Routines making use of the system controller "message"-style interface + * can be found in l1_command.c. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define UART_BAUD_RATE 57600 + +int +get_L1_baud(void) +{ + return UART_BAUD_RATE; +} + + + +/* Return the current interrupt level */ +int +l1_get_intr_value( void ) +{ + return(0); +} + +/* Disconnect the callup functions - throw away interrupts */ + +void +l1_unconnect_intr(void) +{ +} + +/* Set up uart interrupt handling for this node's uart */ + +void +l1_connect_intr(void *rx_notify, void *tx_notify) +{ +#if 0 + // Will need code here for sn2 - something like this + console_nodepda = NODEPDA(NASID_TO_COMPACT_NODEID(get_master_nasid()); + intr_connect_level(console_nodepda->node_first_cpu, + SGI_UART_VECTOR, INTPEND0_MAXMASK, + dummy_intr_func); + request_irq(SGI_UART_VECTOR | (console_nodepda->node_first_cpu << 8), + intr_func, SA_INTERRUPT | SA_SHIRQ, + "l1_protocol_driver", (void *)sc); +#endif +} + + +/* These are functions to use from serial_in/out when in protocol + * mode to send and receive uart control regs. These are external + * interfaces into the protocol driver. + */ + +void +l1_control_out(int offset, int value) +{ + /* quietly ignore unless simulator */ + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + if ( master_node_bedrock_address != (u64)0 ) { + writeb(value, (unsigned long)master_node_bedrock_address + + (offset<< 3)); + } + return; + } +} + +/* Console input exported interface. Return a register value. */ + +int +l1_control_in_polled(int offset) +{ + static int l1_control_in_local(int); + + return(l1_control_in_local(offset)); +} + +int +l1_control_in(int offset) +{ + static int l1_control_in_local(int); + + return(l1_control_in_local(offset)); +} + +static int +l1_control_in_local(int offset) +{ + int sal_call_status = 0, input; + int ret = 0; + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + ret = readb((unsigned long)master_node_bedrock_address + + (offset<< 3)); + return(ret); + } + if ( offset == REG_LSR ) { + ret = (LSR_XHRE | LSR_XSRE); /* can send anytime */ + sal_call_status = ia64_sn_console_check(&input); + if ( !sal_call_status && input ) { + /* input pending */ + ret |= LSR_RCA; + } + } + return(ret); +} + +/* + * Console input exported interface. Return a character (if one is available) + */ + +int +l1_serial_in_polled(void) +{ + static int l1_serial_in_local(void); + + return(l1_serial_in_local()); +} + +int +l1_serial_in(void) +{ + static int l1_serial_in_local(void); + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3))); + } + return(l1_serial_in_local()); +} + +static int +l1_serial_in_local(void) +{ + int ch; + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + return(readb((unsigned long)master_node_bedrock_address + (REG_DAT<< 3))); + } + + if ( !(ia64_sn_console_getc(&ch)) ) + return(ch); + else + return(0); +} + +/* Console output exported interface. Write message to the console. */ + +int +l1_serial_out( char *str, int len ) +{ + int counter = len; + + /* Ignore empty messages */ + if ( len == 0 ) + return(len); + +#if defined(CONFIG_IA64_EARLY_PRINTK) + /* Need to setup SAL calls so the PROM calls will work */ + { + static int inited; + void early_sn_setup(void); + if(!inited) { + inited=1; + early_sn_setup(); + } + } +#endif + + if ( IS_RUNNING_ON_SIMULATOR() ) { + extern u64 master_node_bedrock_address; + void early_sn_setup(void); + if (!master_node_bedrock_address) + early_sn_setup(); + if ( master_node_bedrock_address != (u64)0 ) { +#ifdef FLAG_DIRECT_CONSOLE_WRITES + /* This is an easy way to pre-pend the output to know whether the output + * was done via sal or directly */ + writeb('[', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb('+', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb(']', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + writeb(' ', (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); +#endif /* FLAG_DIRECT_CONSOLE_WRITES */ + while ( counter > 0 ) { + writeb(*str, (unsigned long)master_node_bedrock_address + (REG_DAT<< 3)); + counter--; + str++; + } + } + return(len); + } + + /* Attempt to write things out thru the sal */ + if ( ia64_sn_console_putb(str, len) ) + return(0); + + return((counter <= 0) ? 0 : (len - counter)); +} diff -Nru a/arch/ia64/sn/io/sn2/l1_command.c b/arch/ia64/sn/io/sn2/l1_command.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/l1_command.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,207 @@ +/* $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 +#include +#include +#include +#include +#include +#include + +#define ELSC_TIMEOUT 1000000 /* ELSC response timeout (usec) */ +#define LOCK_TIMEOUT 5000000 /* Hub lock timeout (usec) */ + +#define hub_cpu_get() 0 + +#define LBYTE(caddr) (*(char *) caddr) + +extern char *bcopy(const char * src, char * dest, int count); + +#define LDEBUG 0 + +/* + * ELSC data is in NVRAM page 7 at the following offsets. + */ + +#define NVRAM_MAGIC_AD 0x700 /* magic number used for init */ +#define NVRAM_PASS_WD 0x701 /* password (4 bytes in length) */ +#define NVRAM_DBG1 0x705 /* virtual XOR debug switches */ +#define NVRAM_DBG2 0x706 /* physical XOR debug switches */ +#define NVRAM_CFG 0x707 /* ELSC Configuration info */ +#define NVRAM_MODULE 0x708 /* system module number */ +#define NVRAM_BIST_FLG 0x709 /* BIST flags (2 bits per nodeboard) */ +#define NVRAM_PARTITION 0x70a /* module's partition id */ +#define NVRAM_DOMAIN 0x70b /* module's domain id */ +#define NVRAM_CLUSTER 0x70c /* module's cluster id */ +#define NVRAM_CELL 0x70d /* module's cellid */ + +#define NVRAM_MAGIC_NO 0x37 /* value of magic number */ +#define NVRAM_SIZE 16 /* 16 bytes in nvram */ + + +/* elsc_display_line writes up to 12 characters to either the top or bottom + * line of the L1 display. line points to a buffer containing the message + * to be displayed. The zero-based line number is specified by lnum (so + * lnum == 0 specifies the top line and lnum == 1 specifies the bottom). + * Lines longer than 12 characters, or line numbers not less than + * L1_DISPLAY_LINES, cause elsc_display_line to return an error. + */ +int elsc_display_line(nasid_t nasid, char *line, int lnum) +{ + return 0; +} + +/* + * iobrick routines + */ + +/* iobrick_rack_bay_type_get fills in the three int * arguments with the + * rack number, bay number and brick type of the L1 being addressed. Note + * that if the L1 operation fails and this function returns an error value, + * garbage may be written to brick_type. + */ + + +int iobrick_rack_bay_type_get( nasid_t nasid, uint *rack, + uint *bay, uint *brick_type ) +{ + int result = 0; + + if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) + return( ELSC_ERROR_CMD_SEND ); + + *rack = (result & L1_ADDR_RACK_MASK) >> L1_ADDR_RACK_SHFT; + *bay = (result & L1_ADDR_BAY_MASK) >> L1_ADDR_BAY_SHFT; + *brick_type = (result & L1_ADDR_TYPE_MASK) >> L1_ADDR_TYPE_SHFT; + *brick_type = toupper(*brick_type); + + return 0; +} + + +int iomoduleid_get(nasid_t nasid) +{ + + int result = 0; + + if ( ia64_sn_sysctl_iobrick_module_get(nasid, &result) ) + return( ELSC_ERROR_CMD_SEND ); + + 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 'I': + brick_type = MODULE_IBRICK; break; + case 'P': + brick_type = MODULE_PBRICK; break; + case '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) +{ + uint rack, bay, type; + int t, ret; + extern char brick_types[]; + + if ((ret = iobrick_rack_bay_type_get(nasid, &rack, &bay, &type)) < 0) { + return ret; + } + + /* 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; /* unknown brick */ +} + +int iobrick_module_get_nasid(nasid_t nasid) +{ + int io_moduleid; + +#ifdef PIC_LATER + uint rack, bay; + + if (PEBRICK_NODE(nasid)) { + if (peer_iobrick_rack_bay_get(nasid, &rack, &bay)) { + printf("Could not read rack and bay location " + "of PEBrick at nasid %d\n", nasid); + } + + io_moduleid = peer_iobrick_module_get(sc, rack, bay); + } +#endif /* PIC_LATER */ + io_moduleid = iobrick_module_get(nasid); + return io_moduleid; +} diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/ml_SN_init.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,160 @@ +/* $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 +#include + +extern int numcpus; +extern char arg_maxnodes[]; +extern cpuid_t master_procid; + +extern int hasmetarouter; + +int maxcpus; +cpumask_t boot_cpumask; +hubreg_t region_mask = 0; + + +extern xwidgetnum_t hub_widget_id(nasid_t); + +extern int valid_icache_reasons; /* Reasons to flush the icache */ +extern int valid_dcache_reasons; /* Reasons to flush the dcache */ +extern u_char miniroot; +extern volatile int need_utlbmiss_patch; +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(); + + /* Initialize Hub Pseudodriver Management */ + hubdev_init(); +} + + +/* XXX - Move the meat of this to intr.c ? */ +/* + * Set up the platform-dependent fields in the nodepda. + */ +void init_platform_nodepda(nodepda_t *npda, cnodeid_t node) +{ + hubinfo_t hubinfo; + + 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)); + + 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; + + /* + * Initialize the linked list of + * router info pointers to the dependent routers + */ + npda->npda_rip_first = NULL; + + /* + * npda_rip_last always points to the place + * where the next element is to be inserted + * into the list + */ + npda->npda_rip_last = &npda->npda_rip_first; + npda->geoid.any.type = GEO_TYPE_INVALID; + + mutex_init_locked(&npda->xbow_sema); /* init it locked? */ +} + +/* XXX - Move the interrupt stuff to intr.c ? */ +/* + * Set up the platform-dependent fields in the processor pda. + * Must be done _after_ init_platform_nodepda(). + * If we need a lock here, something else is wrong! + */ +void init_platform_pda(cpuid_t cpu) +{ +} + +void +update_node_information(cnodeid_t cnodeid) +{ + nodepda_t *npda = NODEPDA(cnodeid); + nodepda_router_info_t *npda_rip; + + /* Go through the list of router info + * structures and copy some frequently + * accessed info from the info hanging + * off the corresponding router vertices + */ + npda_rip = npda->npda_rip_first; + while(npda_rip) { + if (npda_rip->router_infop) { + npda_rip->router_portmask = + npda_rip->router_infop->ri_portmask; + npda_rip->router_slot = + npda_rip->router_infop->ri_slotnum; + } else { + /* No router, no ports. */ + npda_rip->router_portmask = 0; + } + npda_rip = npda_rip->router_next; + } +} diff -Nru a/arch/ia64/sn/io/sn2/ml_iograph.c b/arch/ia64/sn/io/sn2/ml_iograph.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/ml_iograph.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,1395 @@ +/* $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* #define IOGRAPH_DEBUG */ +#ifdef IOGRAPH_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* IOGRAPH_DEBUG */ + +/* #define PROBE_TEST */ + +/* At most 2 hubs can be connected to an xswitch */ +#define NUM_XSWITCH_VOLUNTEER 2 + +extern unsigned char Is_pic_on_this_nasid[512]; + +/* + * Track which hubs have volunteered to manage devices hanging off of + * a Crosstalk Switch (e.g. xbow). This structure is allocated, + * initialized, and hung off the xswitch vertex early on when the + * xswitch vertex is created. + */ +typedef struct xswitch_vol_s { + mutex_t xswitch_volunteer_mutex; + int xswitch_volunteer_count; + devfs_handle_t xswitch_volunteer[NUM_XSWITCH_VOLUNTEER]; +} *xswitch_vol_t; + +void +xswitch_vertex_init(devfs_handle_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, + (arbitrary_info_t)xvolinfo); + ASSERT(rc == GRAPH_SUCCESS); rc = rc; +} + + +/* + * When assignment of hubs to widgets is complete, we no longer need the + * xswitch volunteer structure hanging around. Destroy it. + */ +static void +xswitch_volunteer_delete(devfs_handle_t xswitch) +{ + 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)); +} +/* + * A Crosstalk master volunteers to manage xwidgets on the specified xswitch. + */ +/* ARGSUSED */ +static void +volunteer_for_widgets(devfs_handle_t xswitch, devfs_handle_t master) +{ + xswitch_vol_t xvolinfo = NULL; + devfs_handle_t hubv; + hubinfo_t hubinfo; + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { + if (!is_headless_node_vertex(master)) + printk(KERN_WARNING + "volunteer for widgets: vertex 0x%p has no info label", + (void *)xswitch); + return; + } + + mutex_lock(&xvolinfo->xswitch_volunteer_mutex); + ASSERT(xvolinfo->xswitch_volunteer_count < NUM_XSWITCH_VOLUNTEER); + xvolinfo->xswitch_volunteer[xvolinfo->xswitch_volunteer_count] = master; + xvolinfo->xswitch_volunteer_count++; + + /* + * if dual ported, make the lowest widgetid always be + * xswitch_volunteer[0]. + */ + if (xvolinfo->xswitch_volunteer_count == NUM_XSWITCH_VOLUNTEER) { + hubv = xvolinfo->xswitch_volunteer[0]; + hubinfo_get(hubv, &hubinfo); + if (hubinfo->h_widgetid != XBOW_HUBLINK_LOW) { + xvolinfo->xswitch_volunteer[0] = + xvolinfo->xswitch_volunteer[1]; + xvolinfo->xswitch_volunteer[1] = hubv; + } + } + mutex_unlock(&xvolinfo->xswitch_volunteer_mutex); +} + +extern int xbow_port_io_enabled(nasid_t nasid, int widgetnum); + +/* + * Assign all the xwidgets hanging off the specified xswitch to the + * Crosstalk masters that have volunteered for xswitch duty. + */ +/* ARGSUSED */ +static void +assign_widgets_to_volunteers(devfs_handle_t xswitch, devfs_handle_t hubv) +{ + xswitch_info_t xswitch_info; + xswitch_vol_t xvolinfo = NULL; + xwidgetnum_t widgetnum; + int num_volunteer; + nasid_t nasid; + hubinfo_t hubinfo; + extern int iobrick_type_get_nasid(nasid_t); + + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + xswitch_info = xswitch_info_get(xswitch); + ASSERT(xswitch_info != NULL); + + (void)hwgraph_info_get_LBL(xswitch, + INFO_LBL_XSWITCH_VOL, + (arbitrary_info_t *)&xvolinfo); + if (xvolinfo == NULL) { + if (!is_headless_node_vertex(hubv)) + printk(KERN_WARNING + "assign_widgets_to_volunteers:vertex 0x%p has " + " no info label", + (void *)xswitch); + return; + } + + num_volunteer = xvolinfo->xswitch_volunteer_count; + ASSERT(num_volunteer > 0); + + /* Assign master hub for xswitch itself. */ + if (HUB_WIDGET_ID_MIN > 0) { + hubv = xvolinfo->xswitch_volunteer[0]; + xswitch_info_master_assignment_set(xswitch_info, (xwidgetnum_t)0, hubv); + } + + /* + * TBD: Use administrative information to alter assignment of + * widgets to hubs. + */ + 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; + + /* + * If this is the master IO board, assign it to the same + * hub that owned it in the prom. + */ + if (is_master_baseio_nasid_widget(nasid, widgetnum)) { + extern nasid_t 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()) + goto do_assignment; + } + PRINT_PANIC("Nasid == %d, console nasid == %d", + nasid, get_master_baseio_nasid()); + } + + /* + * Assuming that we're dual-hosted and that PCI cards + * are naturally placed left-to-right, alternate PCI + * buses across both Cbricks. For Pbricks, and Ibricks, + * io_brick_map_widget() returns the PCI bus number + * associated with the given brick type and widget number. + * For Xbricks, it returns the XIO slot number. + */ + + i = 0; + if (num_volunteer > 1) { + int bt; + + bt = iobrick_type_get_nasid(nasid); + if (bt >= 0) { + /* + * PXBRICK has two busses per widget so this + * algorithm wouldn't work (all busses would + * be assigned to one volunteer). Change the + * bricktype to PBRICK whose mapping is setup + * suchthat 2 of the PICs will be assigned to + * one volunteer and the other one will be + * assigned to the other volunteer. + */ + if (bt == MODULE_PXBRICK) + bt = MODULE_PBRICK; + + i = io_brick_map_widget(bt, widgetnum) & 1; + } + } + + hubv = xvolinfo->xswitch_volunteer[i]; + +do_assignment: + /* + * At this point, we want to make hubv the master of widgetnum. + */ + xswitch_info_master_assignment_set(xswitch_info, widgetnum, hubv); + } + + 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); + } + } + + hubio_init(); +} + +/* + * Let boot processor know that we're done initializing our node's IO + * and then exit. + */ +/* ARGSUSED */ +static void +io_init_done(cnodeid_t cnodeid,cpu_cookie_t c) +{ + /* Let boot processor know that we're done. */ +} + +/* + * Probe to see if this hub's xtalk link is active. If so, + * return the Crosstalk Identification of the widget that we talk to. + * This is called before any of the Crosstalk infrastructure for + * this hub is set up. It's usually called on the node that we're + * probing, but not always. + * + * TBD: Prom code should actually do this work, and pass through + * hwid for our use. + */ +static void +early_probe_for_widget(devfs_handle_t hubv, xwidget_hwid_t hwid) +{ + hubreg_t llp_csr_reg; + nasid_t nasid; + hubinfo_t hubinfo; + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + + llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); + /* + * If link is up, read the widget's part number. + * A direct connect widget must respond to widgetnum=0. + */ + if (llp_csr_reg & IIO_LLP_CSR_IS_UP) { + /* TBD: Put hub into "indirect" mode */ + /* + * We're able to read from a widget because our hub's + * WIDGET_ID was set up earlier. + */ + widgetreg_t widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + + DBG("early_probe_for_widget: Hub Vertex 0x%p is UP widget_id = 0x%x Register 0x%p\n", hubv, widget_id, + (volatile widgetreg_t *)(RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID) ); + + hwid->part_num = XWIDGET_PART_NUM(widget_id); + hwid->rev_num = XWIDGET_REV_NUM(widget_id); + hwid->mfg_num = XWIDGET_MFG_NUM(widget_id); + + /* TBD: link reset */ + } else { + + hwid->part_num = XWIDGET_PART_NUM_NONE; + hwid->rev_num = XWIDGET_REV_NUM_NONE; + hwid->mfg_num = XWIDGET_MFG_NUM_NONE; + } +} + +/* Add inventory information to the widget vertex + * Right now (module,slot,revision) is being + * added as inventory information. + */ +static void +xwidget_inventory_add(devfs_handle_t widgetv, + lboard_t *board, + struct xwidget_hwid_s hwid) +{ + if (!board) + return; + /* Donot add inventory information for the baseio + * on a speedo with an xbox. It has already been + * taken care of in SN00_vmc. + * Speedo with xbox's baseio comes in at slot io1 (widget 9) + */ + device_inventory_add(widgetv,INV_IOBD,board->brd_type, + geo_module(board->brd_geoid), + SLOTNUM_GETSLOT(board->brd_slot), + hwid.rev_num); +} + +/* + * io_xswitch_widget_init + * + */ + +void +io_xswitch_widget_init(devfs_handle_t xswitchv, + devfs_handle_t hubv, + xwidgetnum_t widgetnum, + async_attach_t aa) +{ + xswitch_info_t xswitch_info; + xwidgetnum_t hub_widgetid; + devfs_handle_t widgetv; + cnodeid_t cnode; + widgetreg_t widget_id; + nasid_t nasid, peer_nasid; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + /*REFERENCED*/ + int rc; + char pathname[128]; + lboard_t *board = NULL; + char buffer[16]; + char bt; + moduleid_t io_module; + slotid_t get_widget_slotnum(int xbow, int widget); + + DBG("\nio_xswitch_widget_init: hubv 0x%p, xswitchv 0x%p, widgetnum 0x%x\n", hubv, xswitchv, widgetnum); + + /* + * Verify that xswitchv is indeed an attached xswitch. + */ + xswitch_info = xswitch_info_get(xswitchv); + ASSERT(xswitch_info != NULL); + + hubinfo_get(hubv, &hubinfo); + nasid = hubinfo->h_nasid; + cnode = NASID_TO_COMPACT_NODEID(nasid); + hub_widgetid = hubinfo->h_widgetid; + + /* + * Check that the widget is an io widget and is enabled + * on this nasid or the `peer' nasid. The peer nasid + * is the other hub/bedrock connected to the xbow. + */ + peer_nasid = NODEPDA(cnode)->xbow_peer; + if (peer_nasid == INVALID_NASID) + /* If I don't have a peer, use myself. */ + peer_nasid = nasid; + if (!xbow_port_io_enabled(nasid, widgetnum) && + !xbow_port_io_enabled(peer_nasid, widgetnum)) { + return; + } + + if (xswitch_info_link_ok(xswitch_info, widgetnum)) { + char name[4]; + lboard_t dummy; + + /* + * If the current hub is not supposed to be the master + * for this widgetnum, then skip this widget. + */ + if (xswitch_info_master_assignment_get(xswitch_info, + widgetnum) != hubv) { + return; + } + + board = find_lboard_class( + (lboard_t *)KL_CONFIG_INFO(nasid), + KLCLASS_IOBRICK); + if (!board && NODEPDA(cnode)->xbow_peer != INVALID_NASID) { + board = find_lboard_class( + (lboard_t *)KL_CONFIG_INFO( NODEPDA(cnode)->xbow_peer), + KLCLASS_IOBRICK); + } + + if (board) { + DBG("io_xswitch_widget_init: Found KLTYPE_IOBRICK Board 0x%p brd_type 0x%x\n", board, board->brd_type); + } else { + DBG("io_xswitch_widget_init: FIXME did not find IOBOARD\n"); + board = &dummy; + } + + + /* Copy over the nodes' geoid info */ + { + lboard_t *brd; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + if ( brd != (lboard_t *)0 ) { + board->brd_geoid = brd->brd_geoid; + } + } + + /* + * Make sure we really want to say xbrick, pbrick, + * etc. rather than XIO, graphics, etc. + */ + + memset(buffer, 0, 16); + format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); + sprintf(pathname, EDGE_LBL_MODULE "/%s/" EDGE_LBL_SLAB "/%d" "/%cbrick" "/%s/%d", + buffer, + geo_slab(board->brd_geoid), + (board->brd_type == KLTYPE_IBRICK) ? 'I' : + (board->brd_type == KLTYPE_PBRICK) ? 'P' : + (board->brd_type == KLTYPE_XBRICK) ? 'X' : '?', + EDGE_LBL_XTALK, widgetnum); + + DBG("io_xswitch_widget_init: path= %s\n", pathname); + rc = hwgraph_path_add(hwgraph_root, pathname, &widgetv); + + ASSERT(rc == GRAPH_SUCCESS); + + /* This is needed to let the user programs to map the + * module,slot numbers to the corresponding widget numbers + * on the crossbow. + */ + device_master_set(hwgraph_connectpt_get(widgetv), hubv); + sprintf(name, "%d", widgetnum); + DBG("io_xswitch_widget_init: FIXME hwgraph_edge_add %s xswitchv 0x%p, widgetv 0x%p\n", name, xswitchv, widgetv); + rc = hwgraph_edge_add(xswitchv, widgetv, name); + + /* + * crosstalk switch code tracks which + * widget is attached to each link. + */ + xswitch_info_vhdl_set(xswitch_info, widgetnum, widgetv); + + /* + * Peek at the widget to get its crosstalk part and + * mfgr numbers, then present it to the generic xtalk + * bus provider to have its driver attach routine + * called (or not). + */ + widget_id = XWIDGET_ID_READ(nasid, widgetnum); + hwid.part_num = XWIDGET_PART_NUM(widget_id); + hwid.rev_num = XWIDGET_REV_NUM(widget_id); + hwid.mfg_num = XWIDGET_MFG_NUM(widget_id); + /* Store some inventory information about + * the xwidget in the hardware graph. + */ + xwidget_inventory_add(widgetv,board,hwid); + + (void)xwidget_register(&hwid, widgetv, widgetnum, + hubv, hub_widgetid, + aa); + + ia64_sn_sysctl_iobrick_module_get(nasid, &io_module); + + if (io_module >= 0) { + char buffer[16]; + devfs_handle_t to, from; + + memset(buffer, 0, 16); + format_module_id(buffer, geo_module(board->brd_geoid), MODULE_FORMAT_BRIEF); + + bt = toupper(MODULE_GET_BTCHAR(io_module)); + /* Add a helper vertex so xbow monitoring + * can identify the brick type. It's simply + * an edge from the widget 0 vertex to the + * brick vertex. + */ + + sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + EDGE_LBL_SLAB "/%d/" + EDGE_LBL_NODE "/" EDGE_LBL_XTALK "/" + "0", + buffer, geo_slab(board->brd_geoid)); + from = hwgraph_path_to_vertex(pathname); + ASSERT_ALWAYS(from); + sprintf(pathname, "/dev/hw/" EDGE_LBL_MODULE "/%s/" + EDGE_LBL_SLAB "/%d/" + "%cbrick", + buffer, geo_slab(board->brd_geoid), bt); + + to = hwgraph_path_to_vertex(pathname); + ASSERT_ALWAYS(to); + rc = hwgraph_edge_add(from, to, + EDGE_LBL_INTERCONNECT); + if (rc == -EEXIST) + goto link_done; + if (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 + } +} + + +static void +io_init_xswitch_widgets(devfs_handle_t xswitchv, cnodeid_t cnode) +{ + xwidgetnum_t widgetnum; + async_attach_t aa; + + aa = async_attach_new(); + + DBG("io_init_xswitch_widgets: xswitchv 0x%p for cnode %d\n", xswitchv, cnode); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; + widgetnum++) { + io_xswitch_widget_init(xswitchv, + cnodeid_to_vertex(cnode), + widgetnum, aa); + } + /* + * Wait for parallel attach threads, if any, to complete. + */ + async_attach_waitall(aa); + async_attach_free(aa); +} + +/* + * 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(devfs_handle_t xswitchv, cnodeid_t cnodeid) +{ + xwidgetnum_t widgetnum; + char pathname[128]; + devfs_handle_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; + } + + if ( Is_pic_on_this_nasid[nasid] ) { + /* 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; + } + } + else { + sprintf(pathname, "%d/"EDGE_LBL_PCI, 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 +io_init_node(cnodeid_t cnodeid) +{ + /*REFERENCED*/ + devfs_handle_t hubv, switchv, widgetv; + struct xwidget_hwid_s hwid; + hubinfo_t hubinfo; + int is_xswitch; + nodepda_t *npdap; + struct semaphore *peer_sema = 0; + uint32_t widget_partnum; + nodepda_router_info_t *npda_rip; + cpu_cookie_t c = 0; + extern int hubdev_docallouts(devfs_handle_t); + + npdap = NODEPDA(cnodeid); + + /* + * Get the "top" vertex for this node's hardware + * graph; it will carry the per-hub hub-specific + * data, and act as the crosstalk provider master. + * It's canonical path is probably something of the + * form /hw/module/%M/slot/%d/node + */ + hubv = cnodeid_to_vertex(cnodeid); + DBG("io_init_node: Initialize IO for cnode %d hubv(node) 0x%p npdap 0x%p\n", cnodeid, hubv, npdap); + + ASSERT(hubv != GRAPH_VERTEX_NONE); + + hubdev_docallouts(hubv); + + /* + * Set up the dependent routers if we have any. + */ + npda_rip = npdap->npda_rip_first; + + while(npda_rip) { + /* If the router info has not been initialized + * then we need to do the router initialization + */ + if (!npda_rip->router_infop) { + router_init(cnodeid,0,npda_rip); + } + npda_rip = npda_rip->router_next; + } + + /* + * 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 + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + + DBG("**** io_init_node: Node's 0x%p hub widget has XWIDGET_PART_NUM_NONE ****\n", hubv); + return; + /* NOTREACHED */ + } + + /* + * attach our hub_provider information to hubv, + * so we can use it as a crosstalk provider "master" + * vertex. + */ + xtalk_provider_register(hubv, &hub_provider); + xtalk_provider_startup(hubv); + + /* + * Create a vertex to represent the crosstalk bus + * attached to this hub, and a vertex to be used + * as the connect point for whatever is out there + * on the other side of our crosstalk connection. + * + * Crosstalk Switch drivers "climb up" from their + * connection point to try and take over the switch + * point. + * + * Of course, the edges and verticies may already + * exist, in which case our net effect is just to + * associate the "xtalk_" driver with the connection + * point for the device. + */ + + (void)hwgraph_path_add(hubv, EDGE_LBL_XTALK, &switchv); + + DBG("io_init_node: Created 'xtalk' entry to '../node/' xtalk vertex 0x%p\n", switchv); + + ASSERT(switchv != GRAPH_VERTEX_NONE); + + (void)hwgraph_edge_add(hubv, switchv, EDGE_LBL_IO); + + DBG("io_init_node: Created symlink 'io' from ../node/io to ../node/xtalk \n"); + + /* + * We need to find the widget id and update the basew_id field + * 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; + + 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) || + (widget_partnum == XXBOW_WIDGET_PART_NUM) || + (widget_partnum == PXBOW_WIDGET_PART_NUM) ) { + /* + * Xbow control register does not have the widget ID field. + * So, hard code the widget ID to be zero. + */ + DBG("io_init_node: Found XBOW widget_partnum= 0x%x\n", widget_partnum); + 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); + + 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); + + /*NOTREACHED*/ + } + { + char widname[10]; + sprintf(widname, "%x", npdap->basew_id); + (void)hwgraph_path_add(switchv, widname, &widgetv); + DBG("io_init_node: Created '%s' to '..node/xtalk/' vertex 0x%p\n", widname, widgetv); + ASSERT(widgetv != GRAPH_VERTEX_NONE); + } + + nodepda->basew_xc = widgetv; + + is_xswitch = xwidget_hwid_is_xswitch(&hwid); + + /* + * Try to become the master of the widget. If this is an xswitch + * with multiple hubs connected, only one will succeed. Mastership + * of an xswitch is used only when touching registers on that xswitch. + * The slave xwidgets connected to the xswitch can be owned by various + * masters. + */ + if (device_master_set(widgetv, hubv) == 0) { + + /* Only one hub (thread) per Crosstalk device or switch makes + * it to here. + */ + + /* + * Initialize whatever xwidget is hanging off our hub. + * Whatever it is, it's accessible through widgetnum 0. + */ + hubinfo_get(hubv, &hubinfo); + + (void)xwidget_register(&hwid, widgetv, npdap->basew_id, hubv, hubinfo->h_widgetid, NULL); + + if (!is_xswitch) { + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + /* NOTREACHED */ + } + + /* + * Special handling for Crosstalk Switches (e.g. xbow). + * We need to do things in roughly the following order: + * 1) Initialize xswitch hardware (done above) + * 2) Determine which hubs are available to be widget masters + * 3) Discover which links are active from the xswitch + * 4) Assign xwidgets hanging off the xswitch to hubs + * 5) Initialize all xwidgets on the xswitch + */ + + volunteer_for_widgets(switchv, hubv); + + /* If there's someone else on this crossbow, recognize him */ + if (npdap->xbow_peer != INVALID_NASID) { + nodepda_t *peer_npdap = NODEPDA(NASID_TO_COMPACT_NODEID(npdap->xbow_peer)); + peer_sema = &peer_npdap->xbow_sema; + volunteer_for_widgets(switchv, peer_npdap->node_vertex); + } + + assign_widgets_to_volunteers(switchv, hubv); + + /* Signal that we're done */ + if (peer_sema) { + mutex_unlock(peer_sema); + } + + } + else { + /* Wait 'til master is done assigning widgets. */ + mutex_lock(&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); + + /* io_init_done takes cpu cookie as 2nd argument + * to do a restorenoderun for the setnoderun done + * at the start of this thread + */ + io_init_done(cnodeid,c); + + DBG("\nio_init_node: DONE INITIALIZED ALL I/O FOR CNODEID %d\n\n", cnodeid); +} + + +#define IOINIT_STKSZ (16 * 1024) + +#define __DEVSTR1 "/../.master/" +#define __DEVSTR2 "/target/" +#define __DEVSTR3 "/lun/0/disk/partition/" +#define __DEVSTR4 "/../ef" + +/* + * ioconfig starts numbering SCSI's at NUM_BASE_IO_SCSI_CTLR. + */ +#define NUM_BASE_IO_SCSI_CTLR 6 +/* + * This tells ioconfig where it can start numbering scsi controllers. + * Below this base number, platform-specific handles the numbering. + * XXX Irix legacy..controller numbering should be part of devfsd's job + */ +int num_base_io_scsi_ctlr = 2; /* used by syssgi */ +devfs_handle_t base_io_scsi_ctlr_vhdl[NUM_BASE_IO_SCSI_CTLR]; +static devfs_handle_t baseio_enet_vhdl,baseio_console_vhdl; + +/* + * Put the logical controller number information in the + * scsi controller vertices for each scsi controller that + * is in a "fixed position". + */ +static void +scsi_ctlr_nums_add(devfs_handle_t pci_vhdl) +{ + { + int i; + + num_base_io_scsi_ctlr = NUM_BASE_IO_SCSI_CTLR; + + /* Initialize base_io_scsi_ctlr_vhdl array */ + for (i=0; i +devfs_handle_t sys_critical_graph_root = GRAPH_VERTEX_NONE; + +/* Define the system critical vertices and connect them through + * a canonical parent-child relationships for easy traversal + * during io error handling. + */ +static void +sys_critical_graph_init(void) +{ + devfs_handle_t bridge_vhdl,master_node_vhdl; + devfs_handle_t xbow_vhdl = GRAPH_VERTEX_NONE; + extern devfs_handle_t hwgraph_root; + devfs_handle_t pci_slot_conn; + int slot; + devfs_handle_t baseio_console_conn; + + DBG("sys_critical_graph_init: FIXME.\n"); + baseio_console_conn = hwgraph_connectpt_get(baseio_console_vhdl); + + if (baseio_console_conn == NULL) { + return; + } + + /* Get the vertex handle for the baseio bridge */ + bridge_vhdl = device_master_get(baseio_console_conn); + + /* Get the master node of the baseio card */ + master_node_vhdl = cnodeid_to_vertex( + master_node_get(baseio_console_vhdl)); + + /* Add the "root->node" part of the system critical graph */ + + sys_critical_graph_vertex_add(hwgraph_root,master_node_vhdl); + + /* Check if we have a crossbow */ + if (hwgraph_traverse(master_node_vhdl, + EDGE_LBL_XTALK"/0", + &xbow_vhdl) == GRAPH_SUCCESS) { + /* We have a crossbow.Add "node->xbow" part of the system + * critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,xbow_vhdl); + + /* Add "xbow->baseio bridge" of the system critical graph */ + sys_critical_graph_vertex_add(xbow_vhdl,bridge_vhdl); + + hwgraph_vertex_unref(xbow_vhdl); + } else + /* We donot have a crossbow. Add "node->baseio_bridge" + * part of the system critical graph. + */ + sys_critical_graph_vertex_add(master_node_vhdl,bridge_vhdl); + + /* Add all the populated PCI slot vertices to the system critical + * graph with the bridge vertex as the parent. + */ + for (slot = 0 ; slot < 8; slot++) { + char slot_edge[10]; + + sprintf(slot_edge,"%d",slot); + if (hwgraph_traverse(bridge_vhdl,slot_edge, &pci_slot_conn) + != GRAPH_SUCCESS) + continue; + sys_critical_graph_vertex_add(bridge_vhdl,pci_slot_conn); + hwgraph_vertex_unref(pci_slot_conn); + } + + hwgraph_vertex_unref(bridge_vhdl); + + /* Add the "ioc3 pci connection point -> console ioc3" part + * of the system critical graph + */ + + if (hwgraph_traverse(baseio_console_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_console_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "ethernet pci connection point -> base ethernet" part of + * the system critical graph + */ + if (hwgraph_traverse(baseio_enet_vhdl,"..",&pci_slot_conn) == + GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + baseio_enet_vhdl); + hwgraph_vertex_unref(pci_slot_conn); + } + + /* Add the "scsi controller pci connection point -> base scsi + * controller" part of the system critical graph + */ + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[0], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[0]); + hwgraph_vertex_unref(pci_slot_conn); + } + if (hwgraph_traverse(base_io_scsi_ctlr_vhdl[1], + "../..",&pci_slot_conn) == GRAPH_SUCCESS) { + sys_critical_graph_vertex_add(pci_slot_conn, + base_io_scsi_ctlr_vhdl[1]); + hwgraph_vertex_unref(pci_slot_conn); + } + hwgraph_vertex_unref(baseio_console_conn); + +} + +static void +baseio_ctlr_num_set(void) +{ + char name[MAXDEVNAME]; + devfs_handle_t console_vhdl, pci_vhdl, enet_vhdl; + devfs_handle_t ioc3_console_vhdl_get(void); + + + DBG("baseio_ctlr_num_set; FIXME\n"); + console_vhdl = ioc3_console_vhdl_get(); + if (console_vhdl == GRAPH_VERTEX_NONE) + return; + /* Useful for setting up the system critical graph */ + baseio_console_vhdl = console_vhdl; + + vertex_to_name(console_vhdl,name,MAXDEVNAME); + + strcat(name,__DEVSTR1); + pci_vhdl = hwgraph_path_to_vertex(name); + scsi_ctlr_nums_add(pci_vhdl); + /* Unref the pci_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(pci_vhdl); + + vertex_to_name(console_vhdl, name, MAXDEVNAME); + strcat(name, __DEVSTR4); + enet_vhdl = hwgraph_path_to_vertex(name); + + /* Useful for setting up the system critical graph */ + baseio_enet_vhdl = enet_vhdl; + + device_controller_num_set(enet_vhdl, 0); + /* Unref the enet_vhdl due to the reference by hwgraph_path_to_vertex + */ + hwgraph_vertex_unref(enet_vhdl); +} +/* #endif */ + +/* + * Initialize all I/O devices. Starting closest to nodes, probe and + * initialize outward. + */ +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++) { + 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++) + /* + * Update information generated by IO init. + */ + update_node_information(cnodeid); + + baseio_ctlr_num_set(); + /* Setup the system critical graph (which is a subgraph of the + * main hwgraph). This information is useful during io error + * handling. + */ + sys_critical_graph_init(); + +#if HWG_PRINT + hwgraph_print(); +#endif + +} + +#define toint(x) ((int)(x) - (int)('0')) + +void +devnamefromarcs(char *devnm) +{ + int val; + char tmpnm[MAXDEVNAME]; + char *tmp1, *tmp2; + + val = strncmp(devnm, "dks", 3); + if (val != 0) + return; + tmp1 = devnm + 3; + if (!isdigit(*tmp1)) + return; + + val = 0; + while (isdigit(*tmp1)) { + val = 10*val+toint(*tmp1); + tmp1++; + } + + if(*tmp1 != 'd') + return; + else + tmp1++; + + if ((val < 0) || (val >= num_base_io_scsi_ctlr)) { + int i; + int viable_found = 0; + + DBG("Only controller numbers 0..%d are supported for\n", NUM_BASE_IO_SCSI_CTLR-1); + DBG("prom \"root\" variables of the form dksXdXsX.\n"); + DBG("To use another disk you must use the full hardware graph path\n\n"); + DBG("Possible controller numbers for use in 'dksXdXsX' on this system: "); + for (i=0; i XBOW_PORT_F) + return 0; + + /* Find "brick" in the path name */ + bp = strstr(hw_path_name, "brick"); + if (bp == NULL) + return 0; + + /* Find preceding slash */ + sp = bp; + while (sp > hw_path_name) { + sp--; + if (*sp == '/') + break; + } + + /* Invalid if no preceding slash */ + if (!sp) + return 0; + + /* Bump slash pointer to "brick" prefix */ + sp++; + /* + * Verify "brick" prefix length; valid exaples: + * 'I' from "/Ibrick" + * 'P' from "/Pbrick" + * 'X' from "/Xbrick" + */ + if ((bp - sp) != 1) + return 0; + + return (io_brick_map_widget((int)*sp, widget_num)); + +} diff -Nru a/arch/ia64/sn/io/sn2/module.c b/arch/ia64/sn/io/sn2/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/module.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,280 @@ +/* $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 +#include +#include +#include +#include +#include + + +/* #define LDEBUG 1 */ + +#ifdef LDEBUG +#define DPRINTF printk +#define printf printk +#else +#define DPRINTF(x...) +#endif + +module_t *modules[MODULE_MAX]; +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 +encode_str_serial(const char *src, char *dest) +{ + int i; + + for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) { + + dest[i] = src[MAX_SERIAL_NUM_SIZE/2 + + ((i%2) ? ((i/2 * -1) - 1) : (i/2))] + + SN0_SERIAL_FUDGE; + } +} + +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) +{ + int i; + + for (i = 0; i < nummodules; i++) + if (modules[i]->id == id) { + DPRINTF("module_lookup: found m=0x%p\n", modules[i]); + return modules[i]; + } + + return NULL; +} + +/* + * module_add_node + * + * The first time a new module number is seen, a module structure is + * inserted into the module list in order sorted by module number + * and the structure is initialized. + * + * The node number is added to the list of nodes in the module. + */ + +module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid) +{ + module_t *m; + int i; + char buffer[16]; + moduleid_t moduleid; + + memset(buffer, 0, 16); + moduleid = geo_module(geoid); + format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF); + DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid); + + if ((m = module_lookup(moduleid)) == 0) { + m = kmalloc(sizeof (module_t), GFP_KERNEL); + memset(m, 0 , sizeof(module_t)); + ASSERT_ALWAYS(m); + + 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--) + modules[i] = modules[i - 1]; + + modules[i] = m; + nummodules++; + } + + m->nodes[m->nodecnt] = cnodeid; + m->geoid[m->nodecnt] = geoid; + m->nodecnt++; + + DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt); + + return m; +} + +int module_probe_snum(module_t *m, nasid_t nasid) +{ + lboard_t *board; + klmod_serial_num_t *comp; + char * bcopy(const char * src, char * dest, int count); + char serial_number[16]; + + /* + * record brick serial number + */ + board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA); + + if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) + { +#if LDEBUG + printf ("module_probe_snum: no IP35 board found!\n"); +#endif + return 0; + } + + board_serial_number_get( board, serial_number ); + if( serial_number[0] != '\0' ) { + 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); + + if (! board || KL_CONFIG_DUPLICATE_BOARD(board)) + return 0; + + 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') { + bcopy(comp->snum.snum_str, + m->sys_snum, + MAX_SERIAL_NUM_SIZE); + m->sys_snum_valid = 1; + } + } + + if (m->sys_snum_valid) + return 1; + else { + DPRINTF("Invalid serial number for module %d, " + "possible missing or invalid NIC.", m->id); + return 0; + } +} + +void +io_module_init(void) +{ + cnodeid_t node; + lboard_t *board; + nasid_t nasid; + int nserial; + module_t *m; + + DPRINTF("*******module_init\n"); + + nserial = 0; + + 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); + + if (! m->snum_valid && module_probe_snum(m, 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"); +} + +int +get_kmod_info(cmoduleid_t cmod, module_info_t *mod_info) +{ + if (cmod < 0 || cmod >= nummodules) + return -EINVAL; + + mod_info->mod_num = modules[cmod]->id; + + ia64_sn_sys_serial_get(mod_info->serial_str); + + mod_info->serial_num = ia64_sn_partition_serial_get(); + + return 0; +} diff -Nru a/arch/ia64/sn/io/sn2/pci_bus_cvlink.c b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pci_bus_cvlink.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,725 @@ +/* $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 +#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; + +devfs_handle_t busnum_to_pcibr_vhdl[MAX_PCI_XWIDGET]; +nasid_t busnum_to_nid[MAX_PCI_XWIDGET]; +void * busnum_to_atedmamaps[MAX_PCI_XWIDGET]; +unsigned char num_bridges; +static int done_probing = 0; + +static int pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid); +devfs_handle_t devfn_to_vertex(unsigned char busnum, unsigned int devfn); + +extern unsigned char Is_pic_on_this_nasid[512]; + +extern void sn_init_irq_desc(void); +extern void register_pcibr_intr(int irq, pcibr_intr_t intr); + + +/* + * For the given device, initialize whether it is a PIC device. + */ +static void +set_isPIC(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);; +} + +/* + * pci_bus_cvlink_init() - To be called once during initialization before + * SGI IO Infrastructure init is called. + */ +void +pci_bus_cvlink_init(void) +{ + + extern void ioconfig_bus_init(void); + + memset(busnum_to_pcibr_vhdl, 0x0, sizeof(devfs_handle_t) * MAX_PCI_XWIDGET); + memset(busnum_to_nid, 0x0, sizeof(nasid_t) * MAX_PCI_XWIDGET); + + memset(busnum_to_atedmamaps, 0x0, sizeof(void *) * MAX_PCI_XWIDGET); + + num_bridges = 0; + + ioconfig_bus_init(); +} + +/* + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci bus vertex from the SGI IO Infrastructure. + */ +devfs_handle_t +pci_bus_to_vertex(unsigned char busnum) +{ + + devfs_handle_t pci_bus = NULL; + + + /* + * First get the xwidget vertex. + */ + pci_bus = busnum_to_pcibr_vhdl[busnum]; + return(pci_bus); +} + +/* + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * and function numbers. + */ +devfs_handle_t +devfn_to_vertex(unsigned char busnum, unsigned int devfn) +{ + + int slot = 0; + int func = 0; + char name[16]; + devfs_handle_t pci_bus = NULL; + devfs_handle_t device_vertex = (devfs_handle_t)NULL; + + /* + * Go get the pci bus vertex. + */ + pci_bus = pci_bus_to_vertex(busnum); + if (!pci_bus) { + /* + * During probing, the Linux pci code invents non existant + * bus numbers and pci_dev structures and tries to access + * them to determine existance. Don't crib during probing. + */ + if (done_probing) + printk("devfn_to_vertex: Invalid bus number %d given.\n", busnum); + return(NULL); + } + + + /* + * Go get the slot&function vertex. + * Should call pciio_slot_func_to_name() when ready. + */ + slot = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* + * For a NON Multi-function card the name of the device looks like: + * ../pci/1, ../pci/2 .. + */ + if (func == 0) { + sprintf(name, "%d", slot); + if (hwgraph_traverse(pci_bus, name, &device_vertex) == + GRAPH_SUCCESS) { + if (device_vertex) { + return(device_vertex); + } + } + } + + /* + * This maybe a multifunction card. It's names look like: + * ../pci/1a, ../pci/1b, etc. + */ + sprintf(name, "%d%c", slot, 'a'+func); + if (hwgraph_traverse(pci_bus, name, &device_vertex) != GRAPH_SUCCESS) { + if (!device_vertex) { + return(NULL); + } + } + + 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 + +} + +/* + * Most drivers currently do not properly tell the arch specific pci dma + * interfaces whether they can handle A64. Here is where we privately + * keep track of this. + */ +static void __init +set_sn_pci64(struct pci_dev *dev) +{ + unsigned short vendor = dev->vendor; + unsigned short device = dev->device; + + if (vendor == PCI_VENDOR_ID_QLOGIC) { + if ((device == PCI_DEVICE_ID_QLOGIC_ISP2100) || + (device == PCI_DEVICE_ID_QLOGIC_ISP2200)) { + SET_PCIA64(dev); + return; + } + } + + if (vendor == PCI_VENDOR_ID_SGI) { + if (device == PCI_DEVICE_ID_SGI_IOC3) { + SET_PCIA64(dev); + return; + } + } + +} + +/* + * sn_pci_fixup() - This routine is called when platform_pci_fixup() is + * invoked at the end of pcibios_init() to link the Linux pci + * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c + * + * Other platform specific fixup can also be done here. + */ +void +sn_pci_fixup(int arg) +{ + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *device_dev = NULL; + struct sn_widget_sysdata *widget_sysdata; + struct sn_device_sysdata *device_sysdata; + pciio_intr_t intr_handle; + int cpuid, bit; + devfs_handle_t device_vertex; + pciio_intr_line_t lines; + extern void sn_pci_find_bios(void); + extern int numnodes; + int cnode; + extern void io_sh_swapper(int, int); + + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 0); + } + + if (arg == 0) { +#ifdef CONFIG_PROC_FS + extern void register_sn_procfs(void); +#endif + + sn_init_irq_desc(); + sn_pci_find_bios(); + for (cnode = 0; cnode < numnodes; cnode++) { + extern void intr_init_vecblk(nodepda_t *npda, cnodeid_t, int); + intr_init_vecblk(NODEPDA(cnode), cnode, 0); + } + + /* + * When we return to generic Linux, Swapper is always on .. + */ + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 1); + } +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif + return; + } + + + done_probing = 1; + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), + GFP_KERNEL); + widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number); + pci_bus->sysdata = (void *)widget_sysdata; + } + + /* + * 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; + + /* + * Set the root start and end for Mem Resource. + */ + iomem_resource.start = 0; + iomem_resource.end = 0xffffffffffffffff; + + /* + * Initialize the device vertex in the pci_dev struct. + */ + pci_for_each_dev(device_dev) { + unsigned int irq; + int idx; + u16 cmd; + devfs_handle_t vhdl; + unsigned long size; + extern int bit_pos_to_irq(int); + + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3) { + extern void pci_fixup_ioc3(struct pci_dev *d); + pci_fixup_ioc3(device_dev); + } + + /* Set the device vertex */ + + device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), + GFP_KERNEL); + device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); + device_sysdata->isa64 = 0; + /* + * Set the xbridge Device(X) Write Buffer Flush and Xbow Flush + * register addresses. + */ + (void) set_flush_addresses(device_dev, device_sysdata); + + device_dev->sysdata = (void *) device_sysdata; + set_sn_pci64(device_dev); + set_isPIC(device_sysdata); + + pci_read_config_word(device_dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure .. + */ + vhdl = device_sysdata->vhdl; + 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(vhdl, 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; + + device_dev->resource[idx].end = + device_dev->resource[idx].start + size; + + if (device_dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + + if (device_dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } +#if 0 + /* + * Software WAR for a Software BUG. + * This is only temporary. + * See PV 872791 + */ + + /* + * Now handle the ROM resource .. + */ + size = device_dev->resource[PCI_ROM_RESOURCE].end - + device_dev->resource[PCI_ROM_RESOURCE].start; + + if (size) { + device_dev->resource[PCI_ROM_RESOURCE].start = + (unsigned long) pciio_pio_addr(vhdl, 0, PCIIO_SPACE_ROM, 0, + size, 0, (IS_PIC_DEVICE(device_dev)) ? 0 : PCIIO_BYTE_STREAM); + device_dev->resource[PCI_ROM_RESOURCE].start |= __IA64_UNCACHED_OFFSET; + device_dev->resource[PCI_ROM_RESOURCE].end = + device_dev->resource[PCI_ROM_RESOURCE].start + size; + } +#endif + + /* + * Update the Command Word on the Card. + */ + 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); + if (device_dev->vendor == PCI_VENDOR_ID_SGI && + device_dev->device == PCI_DEVICE_ID_SGI_IOC3 ) { + lines = 1; + } + + device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; + device_vertex = device_sysdata->vhdl; + + intr_handle = pciio_intr_alloc(device_vertex, NULL, lines, device_vertex); + + bit = intr_handle->pi_irq; + cpuid = intr_handle->pi_cpu; + irq = bit; + irq = irq + (cpuid << 8); + pciio_intr_connect(intr_handle, (intr_func_t)0, (intr_arg_t)0); + device_dev->irq = irq; + register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); +#ifdef ajmtestintr + { + int slot = PCI_SLOT(device_dev->devfn); + static int timer_set = 0; + pcibr_intr_t pcibr_intr = (pcibr_intr_t)intr_handle; + pcibr_soft_t pcibr_soft = pcibr_intr->bi_soft; + extern void intr_test_handle_intr(int, void*, struct pt_regs *); + + if (!timer_set) { + intr_test_set_timer(); + timer_set = 1; + } + intr_test_register_irq(irq, pcibr_soft, slot); + request_irq(irq, intr_test_handle_intr,0,NULL, NULL); + } +#endif + + } + + for (cnode = 0; cnode < numnodes; cnode++) { + if ( !Is_pic_on_this_nasid[cnodeid_to_nasid(cnode)] ) + io_sh_swapper((cnodeid_to_nasid(cnode)), 1); + } +} + +/* + * linux_bus_cvlink() Creates a link between the Linux PCI Bus number + * to the actual hardware component that it represents: + * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * + * The bus vertex, when called to devfs_generate_path() returns: + * hw/module/001c01/slab/0/Ibrick/xtalk/15/pci + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/0 + * hw/module/001c01/slab/1/Pbrick/xtalk/12/pci-x/1 + */ +void +linux_bus_cvlink(void) +{ + char name[8]; + int index; + + for (index=0; index < MAX_PCI_XWIDGET; index++) { + if (!busnum_to_pcibr_vhdl[index]) + continue; + + sprintf(name, "%x", index); + (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], + name); + } +} + +/* + * pci_bus_map_create() - Called by pci_bus_to_hcl_cvlink() to finish the job. + * + * Linux PCI Bus numbers are assigned from lowest module_id numbers + * (rack/slot etc.) starting from HUB_WIDGET_ID_MAX down to + * HUB_WIDGET_ID_MIN: + * widgetnum 15 gets lower Bus Number than widgetnum 14 etc. + * + * Given 2 modules 001c01 and 001c02 we get the following mappings: + * 001c01, widgetnum 15 = Bus number 0 + * 001c01, widgetnum 14 = Bus number 1 + * 001c02, widgetnum 15 = Bus number 3 + * 001c02, widgetnum 14 = Bus number 4 + * etc. + * + * The rational for starting Bus Number 0 with Widget number 15 is because + * the system boot disks are always connected via Widget 15 Slot 0 of the + * I-brick. Linux creates /dev/sd* devices(naming) strating from Bus Number 0 + * Therefore, /dev/sda1 will be the first disk, on Widget 15 of the lowest + * module id(Master Cnode) of the system. + * + */ +static int +pci_bus_map_create(devfs_handle_t xtalk, char * io_moduleid) +{ + + devfs_handle_t master_node_vertex = NULL; + devfs_handle_t xwidget = NULL; + devfs_handle_t pci_bus = NULL; + hubinfo_t hubinfo = NULL; + xwidgetnum_t widgetnum; + char pathname[128]; + graph_error_t rv; + int bus; + int basebus_num; + int bus_number; + + /* + * Loop throught this vertex and get the Xwidgets .. + */ + + + /* PCI devices */ + + for (widgetnum = HUB_WIDGET_ID_MAX; widgetnum >= HUB_WIDGET_ID_MIN; widgetnum--) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + sprintf(pathname, "%d/"EDGE_LBL_PCI, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; +} + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + num_bridges++; + busnum_to_pcibr_vhdl[num_bridges - 1] = pci_bus; + + /* + * Get the master node and from there get the NASID. + */ + master_node_vertex = device_master_get(xwidget); + if (!master_node_vertex) { + printk("WARNING: pci_bus_map_create: Unable to get .master for vertex 0x%p\n", (void *)xwidget); + } + + hubinfo_get(master_node_vertex, &hubinfo); + if (!hubinfo) { + printk("WARNING: pci_bus_map_create: Unable to get hubinfo for master node vertex 0x%p\n", (void *)master_node_vertex); + return(1); + } else { + busnum_to_nid[num_bridges - 1] = hubinfo->h_nasid; + } + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[num_bridges - 1] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[num_bridges - 1]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[num_bridges - 1], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + + } + + /* + * PCIX devices + * We number busses differently for PCI-X devices. + * We start from Lowest Widget on up .. + */ + + (void) ioconfig_get_busnum((char *)io_moduleid, &basebus_num); + + for (widgetnum = HUB_WIDGET_ID_MIN; widgetnum <= HUB_WIDGET_ID_MAX; widgetnum++) { + + /* Do both buses */ + for ( bus = 0; bus < 2; bus++ ) { + sprintf(pathname, "%d", widgetnum); + xwidget = NULL; + + /* + * Example - /hw/module/001c16/Pbrick/xtalk/8 is the xwidget + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0 is the bus + * /hw/module/001c16/Pbrick/xtalk/8/pci-x/0/1 is device + */ + rv = hwgraph_traverse(xtalk, pathname, &xwidget); + if ( (rv != GRAPH_SUCCESS) ) { + if (!xwidget) { + continue; + } + } + + if ( bus == 0 ) + sprintf(pathname, "%d/"EDGE_LBL_PCIX_0, widgetnum); + else + sprintf(pathname, "%d/"EDGE_LBL_PCIX_1, widgetnum); + pci_bus = NULL; + if (hwgraph_traverse(xtalk, pathname, &pci_bus) != GRAPH_SUCCESS) + if (!pci_bus) { + continue; + } + + /* + * Assign the correct bus number and also the nasid of this + * pci Xwidget. + * + * Should not be any race here ... + */ + bus_number = basebus_num + bus + io_brick_map_widget(MODULE_PXBRICK, widgetnum); +#ifdef DEBUG + printk("bus_number %d basebus_num %d bus %d io %d\n", + bus_number, basebus_num, bus, + io_brick_map_widget(MODULE_PXBRICK, widgetnum)); +#endif + busnum_to_pcibr_vhdl[bus_number] = pci_bus; + + /* + * Pre assign DMA maps needed for 32 Bits Page Map DMA. + */ + busnum_to_atedmamaps[bus_number] = (void *) kmalloc( + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS, GFP_KERNEL); + if (!busnum_to_atedmamaps[bus_number]) + printk("WARNING: pci_bus_map_create: Unable to precreate ATE DMA Maps for busnum %d vertex 0x%p\n", num_bridges - 1, (void *)xwidget); + + memset(busnum_to_atedmamaps[bus_number], 0x0, + sizeof(struct sn_dma_maps_s) * MAX_ATE_MAPS); + } + } + + return(0); +} + +/* + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * initialization has completed to set up the mappings between Xbridge + * and logical pci bus numbers. We also set up the NASID for each of these + * xbridges. + * + * Must be called before pci_init() is invoked. + */ +int +pci_bus_to_hcl_cvlink(void) +{ + + devfs_handle_t devfs_hdl = NULL; + devfs_handle_t xtalk = NULL; + int rv = 0; + char name[256]; + char tmp_name[256]; + int i, ii; + + /* + * Figure out which IO Brick is connected to the Compute Bricks. + */ + for (i = 0; i < nummodules; i++) { + extern int iomoduleid_get(nasid_t); + moduleid_t iobrick_id; + nasid_t nasid = -1; + int nodecnt; + int n = 0; + + nodecnt = modules[i]->nodecnt; + for ( n = 0; n < nodecnt; n++ ) { + nasid = cnodeid_to_nasid(modules[i]->nodes[n]); + iobrick_id = iomoduleid_get(nasid); + if ((int)iobrick_id > 0) { /* Valid module id */ + char name[12]; + memset(name, 0, 12); + format_module_id((char *)&(modules[i]->io[n].moduleid), iobrick_id, MODULE_FORMAT_BRIEF); + } + } + } + + devfs_hdl = hwgraph_path_to_vertex("/dev/hw/module"); + for (i = 0; i < nummodules ; i++) { + for ( ii = 0; ii < 2 ; ii++ ) { + memset(name, 0, 256); + memset(tmp_name, 0, 256); + format_module_id(name, modules[i]->id, MODULE_FORMAT_BRIEF); + sprintf(tmp_name, "/slab/%d/Pbrick/xtalk", geo_slab(modules[i]->geoid[ii])); + strcat(name, tmp_name); + xtalk = NULL; + rv = hwgraph_edge_get(devfs_hdl, name, &xtalk); + pci_bus_map_create(xtalk, (char *)&(modules[i]->io[ii].moduleid)); + } + } + + /* + * Create the Linux PCI bus number vertex link. + */ + (void)linux_bus_cvlink(); + (void)ioconfig_bus_new_entries(); + + return(0); +} diff -Nru a/arch/ia64/sn/io/sn2/pcibr/Makefile b/arch/ia64/sn/io/sn2/pcibr/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pcibr/Makefile Sat Mar 15 18:40:45 2003 @@ -0,0 +1,19 @@ +# +# 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. +# +# Makefile for the sn2 specific pci bridge routines. + +EXTRA_CFLAGS := -DLITTLE_ENDIAN + +ifdef CONFIG_IA64_SGI_SN2 +EXTRA_CFLAGS += -DSHUB_SWAP_WAR +endif + +obj-$(CONFIG_IA64_SGI_SN2) += pcibr_dvr.o pcibr_ate.o pcibr_config.o \ + pcibr_dvr.o pcibr_hints.o \ + pcibr_intr.o pcibr_rrb.o pcibr_slot.o \ + pcibr_error.o diff -Nru a/arch/ia64/sn/io/sn2/pciio.c b/arch/ia64/sn/io/sn2/pciio.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pciio.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,1877 @@ +/* $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. + */ + +#define USRPCI 0 + +#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 +#include + +#ifdef __ia64 +#define rmallocmap atemapalloc +#define rmfreemap atemapfree +#define rmfree atefree +#define rmalloc atealloc +#endif + +#define DEBUG_PCIIO +#undef DEBUG_PCIIO /* turn this on for yet more console output */ + + +#define GET_NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DO_DEL(ptr) (kfree(ptr)) + +char pciio_info_fingerprint[] = "pciio_info"; + +cdl_p pciio_registry = NULL; + +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) { + nasid_t tmp; + + 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(devfs_handle_t xconn_vhdl) +{ + return(0); +} + +int +hub_error_devenable(devfs_handle_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 + * platform-independent interface for PCI devices. This layer + * switches among the possible implementations of a PCI adapter. + */ + +/* ===================================================================== + * 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(devfs_handle_t dev); +#endif + +pciio_piomap_t pciio_piomap_alloc(devfs_handle_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(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned); +caddr_t pciio_pio_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, pciio_piomap_t *, unsigned); + +iopaddr_t pciio_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t); +void pciio_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t); + +pciio_dmamap_t pciio_dmamap_alloc(devfs_handle_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); +alenlist_t pciio_dmamap_list(pciio_dmamap_t, alenlist_t, unsigned); +void pciio_dmamap_done(pciio_dmamap_t); +iopaddr_t pciio_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t pciio_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void pciio_dmamap_drain(pciio_dmamap_t); +void pciio_dmaaddr_drain(devfs_handle_t, paddr_t, size_t); +void pciio_dmalist_drain(devfs_handle_t, alenlist_t); +iopaddr_t pciio_dma_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, pciio_dmamap_t *, unsigned); + +pciio_intr_t pciio_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_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); +devfs_handle_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(devfs_handle_t); +void pciio_provider_shutdown(devfs_handle_t); + +pciio_endian_t pciio_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t); +pciio_priority_t pciio_priority_set(devfs_handle_t, pciio_priority_t); +devfs_handle_t pciio_intr_dev_get(pciio_intr_t); + +devfs_handle_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); + +devfs_handle_t pciio_dma_dev_get(pciio_dmamap_t); +pciio_slot_t pciio_dma_slot_get(pciio_dmamap_t); + +pciio_info_t pciio_info_chk(devfs_handle_t); +pciio_info_t pciio_info_get(devfs_handle_t); +void pciio_info_set(devfs_handle_t, pciio_info_t); +devfs_handle_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); +devfs_handle_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); + +void pciio_init(void); +int pciio_attach(devfs_handle_t); + +void pciio_provider_register(devfs_handle_t, pciio_provider_t *pciio_fns); +void pciio_provider_unregister(devfs_handle_t); +pciio_provider_t *pciio_provider_fns_get(devfs_handle_t); + +int pciio_driver_register(pciio_vendor_id_t, pciio_device_id_t, char *driver_prefix, unsigned); +void pciio_driver_unregister(char *driver_prefix); + +devfs_handle_t pciio_device_register(devfs_handle_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); + +void pciio_device_unregister(devfs_handle_t); +pciio_info_t pciio_device_info_new(pciio_info_t, devfs_handle_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t); +void pciio_device_info_free(pciio_info_t); +devfs_handle_t pciio_device_info_register(devfs_handle_t, pciio_info_t); +void pciio_device_info_unregister(devfs_handle_t, pciio_info_t); +int pciio_device_attach(devfs_handle_t, int); +int pciio_device_detach(devfs_handle_t, int); +void pciio_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t); + +int pciio_reset(devfs_handle_t); +int pciio_write_gather_flush(devfs_handle_t); +int pciio_slot_inuse(devfs_handle_t); + +/* ===================================================================== + * Provider Function Location + * + * If there is more than one possible provider for + * this platform, we need to examine the master + * vertex of the current vertex for a provider + * function structure, and indirect through the + * appropriately named member. + */ + +#if !defined(DEV_FUNC) + +static pciio_provider_t * +pciio_to_provider_fns(devfs_handle_t dev) +{ + pciio_info_t card_info; + pciio_provider_t *provider_fns; + + /* + * We're called with two types of vertices, one is + * the bridge vertex (ends with "pci") and the other is the + * pci slot vertex (ends with "pci/[0-8]"). For the first type + * we need to get the provider from the PFUNCS label. For + * the second we get it from fastinfo/c_pops. + */ + provider_fns = pciio_provider_fns_get(dev); + if (provider_fns == NULL) { + card_info = pciio_info_get(dev); + if (card_info != NULL) { + provider_fns = pciio_info_pops_get(card_info); + } + } + + 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 + + return provider_fns; + +} + +#define DEV_FUNC(dev,func) pciio_to_provider_fns(dev)->func +#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 + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC((map)->pp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC((map)->pd_dev,func) +#define INTR_FUNC(intr_hdl,func) DEV_FUNC((intr_hdl)->pi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * pciio space on a specified card + */ + +pciio_piomap_t +pciio_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* lowest address (or offset in window) */ + size_t byte_count, /* size of region containing our mappings */ + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (pciio_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, space, addr, byte_count, byte_count_max, flags); +} + +void +pciio_piomap_free(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_free) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piomap_addr(pciio_piomap_t pciio_piomap, /* mapping resources */ + iopaddr_t pciio_addr, /* map for this pciio address */ + size_t byte_count) +{ /* map this many bytes */ + pciio_piomap->pp_kvaddr = PIOMAP_FUNC(pciio_piomap, piomap_addr) + (CAST_PIOMAP(pciio_piomap), pciio_addr, byte_count); + + return pciio_piomap->pp_kvaddr; +} + +void +pciio_piomap_done(pciio_piomap_t pciio_piomap) +{ + PIOMAP_FUNC(pciio_piomap, piomap_done) + (CAST_PIOMAP(pciio_piomap)); +} + +caddr_t +pciio_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, space, addr, byte_count, flags); +} + +caddr_t +pciio_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_space_t space, /* CFG, MEM, IO, or a device-decoded window */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + pciio_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + pciio_piomap_t map = 0; + int errfree = 0; + caddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_piotrans_addr + (dev, dev_desc, space, addr, byte_count, flags); + if (res) + return res; /* pciio_piotrans worked */ + + if (!map) { + map = pciio_piomap_alloc + (dev, dev_desc, space, addr, byte_count, byte_count, flags); + if (!map) + return res; /* pciio_piomap_alloc failed */ + errfree = 1; + } + + res = pciio_piomap_addr + (map, addr, byte_count); + if (!res) { + if (errfree) + pciio_piomap_free(map); + return res; /* pciio_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_piomap_addr succeeded */ +} + +iopaddr_t +pciio_piospace_alloc(devfs_handle_t dev, /* Device requiring space */ + device_desc_t dev_desc, /* Device descriptor */ + pciio_space_t space, /* MEM32/MEM64/IO */ + size_t byte_count, /* Size of mapping */ + size_t align) +{ /* Alignment needed */ + if (align < NBPP) + align = NBPP; + return DEV_FUNC(dev, piospace_alloc) + (dev, dev_desc, space, byte_count, align); +} + +void +pciio_piospace_free(devfs_handle_t dev, /* Device freeing space */ + pciio_space_t space, /* Type of space */ + iopaddr_t pciaddr, /* starting address */ + size_t byte_count) +{ /* Range of address */ + DEV_FUNC(dev, piospace_free) + (dev, space, pciaddr, byte_count); +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from pci space to system + * physical space. + */ + +pciio_dmamap_t +pciio_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + +void +pciio_dmamap_free(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_free) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(pciio_dmamap, dmamap_addr) + (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); +} + +alenlist_t +pciio_dmamap_list(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(pciio_dmamap, dmamap_list) + (CAST_DMAMAP(pciio_dmamap), alenlist, flags); +} + +void +pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_done) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +pciio_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + +alenlist_t +pciio_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +iopaddr_t +pciio_dma_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + pciio_dmamap_t *mapp, /* map to use, then map we used */ + unsigned flags) +{ /* PIO flags */ + pciio_dmamap_t map = 0; + int errfree = 0; + iopaddr_t res; + + if (mapp) { + map = *mapp; /* possible pre-allocated map */ + *mapp = 0; /* record "no map used" */ + } + + res = pciio_dmatrans_addr + (dev, dev_desc, paddr, byte_count, flags); + if (res) + return res; /* pciio_dmatrans worked */ + + if (!map) { + map = pciio_dmamap_alloc + (dev, dev_desc, byte_count, flags); + if (!map) + return res; /* pciio_dmamap_alloc failed */ + errfree = 1; + } + + res = pciio_dmamap_addr + (map, paddr, byte_count); + if (!res) { + if (errfree) + pciio_dmamap_free(map); + return res; /* pciio_dmamap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* pciio_dmamap_addr succeeded */ +} + +void +pciio_dmamap_drain(pciio_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +pciio_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +pciio_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +pciio_intr_t +pciio_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + pciio_intr_line_t lines, /* INTR line(s) to attach */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (pciio_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, lines, owner_dev); +} + +/* + * Free resources consumed by intr_alloc. + */ +void +pciio_intr_free(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + +/* + * Associate resources allocated with a previous pciio_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +pciio_intr_connect(pciio_intr_t intr_hdl, + intr_func_t intr_func, intr_arg_t intr_arg) /* pciio intr resource handle */ +{ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg); +} + +/* + * Disassociate handler with the specified interrupt. + */ +void +pciio_intr_disconnect(pciio_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +pciio_intr_cpu_get(pciio_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + +void +pciio_slot_func_to_name(char *name, + pciio_slot_t slot, + pciio_function_t func) +{ + /* + * standard connection points: + * + * PCIIO_SLOT_NONE: .../pci/direct + * PCIIO_FUNC_NONE: .../pci/ ie. .../pci/3 + * multifunction: .../pci/ ie. .../pci/3c + */ + + if (slot == PCIIO_SLOT_NONE) + sprintf(name, EDGE_LBL_DIRECT); + else if (func == PCIIO_FUNC_NONE) + sprintf(name, "%d", slot); + else + sprintf(name, "%d%c", slot, 'a'+func); +} + +/* + * pciio_cardinfo_get + * + * Get the pciio info structure corresponding to the + * specified PCI "slot" (we like it when the same index + * number is used for the PCI IDSEL, the REQ/GNT pair, + * and the interrupt line being used for INTA. We like + * it so much we call it the slot number). + */ +static pciio_info_t +pciio_cardinfo_get( + devfs_handle_t pciio_vhdl, + pciio_slot_t pci_slot) +{ + char namebuf[16]; + pciio_info_t info = 0; + devfs_handle_t conn; + + pciio_slot_func_to_name(namebuf, pci_slot, PCIIO_FUNC_NONE); + if (GRAPH_SUCCESS == + hwgraph_traverse(pciio_vhdl, namebuf, &conn)) { + info = pciio_info_chk(conn); + hwgraph_vertex_unref(conn); + } + + return info; +} + + +/* + * pciio_error_handler: + * dispatch an error to the appropriate + * pciio connection point, or process + * it as a generic pci error. + * Yes, the first parameter is the + * provider vertex at the middle of + * the bus; we get to the pciio connect + * point using the ioerror widgetdev field. + * + * This function is called by the + * specific PCI provider, after it has figured + * out where on the PCI bus (including which slot, + * if it can tell) the error came from. + */ +/*ARGSUSED */ +int +pciio_error_handler( + devfs_handle_t pciio_vhdl, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + pciio_info_t pciio_info; + devfs_handle_t pconn_vhdl; +#if USRPCI + devfs_handle_t usrpci_v; +#endif + pciio_slot_t slot; + + int retval; +#ifdef EHE_ENABLE + error_state_t e_state; +#endif /* EHE_ENABLE */ + +#if DEBUG && ERROR_DEBUG + printk("%v: pciio_error_handler\n", pciio_vhdl); +#endif + + IOERR_PRINTF(printk(KERN_NOTICE "%v: PCI Bus Error: Error code: %d Error mode: %d\n", + pciio_vhdl, error_code, mode)); + + /* If there is an error handler sitting on + * the "no-slot" connection point, give it + * first crack at the error. NOTE: it is + * quite possible that this function may + * do further refining of the ioerror. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, PCIIO_SLOT_NONE); + if (pciio_info && pciio_info->c_efunc) { + pconn_vhdl = pciio_info_dev_get(pciio_info); + +#ifdef EHE_ENABLE + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif + + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + + /* Is the error associated with a particular slot? + */ + if (IOERROR_FIELDVALID(ioerror, widgetdev)) { + short widgetdev; + /* + * NOTE : + * widgetdev is a 4byte value encoded as slot in the higher order + * 2 bytes and function in the lower order 2 bytes. + */ + IOERROR_GETVALUE(widgetdev, ioerror, widgetdev); + slot = pciio_widgetdev_slot_get(widgetdev); + + /* If this slot has an error handler, + * deliver the error to it. + */ + pciio_info = pciio_cardinfo_get(pciio_vhdl, slot); + if (pciio_info != NULL) { + if (pciio_info->c_efunc != NULL) { + + pconn_vhdl = pciio_info_dev_get(pciio_info); + +#ifdef EHE_ENABLE + e_state = error_state_get(pciio_vhdl); + + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(pciio_vhdl, ERROR_STATE_NONE); + + if (error_state_set(pconn_vhdl,e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); +#endif /* EHE_ENABLE */ + + retval = pciio_info->c_efunc + (pciio_info->c_einfo, error_code, mode, ioerror); + if (retval != IOERROR_UNHANDLED) + return retval; + } + +#if USRPCI + /* If the USRPCI driver is available and + * knows about this connection point, + * deliver the error to it. + * + * OK to use pconn_vhdl here, even though we + * have already UNREF'd it, since we know that + * it is not going away. + */ + pconn_vhdl = pciio_info_dev_get(pciio_info); + if (GRAPH_SUCCESS == hwgraph_traverse(pconn_vhdl, EDGE_LBL_USRPCI, &usrpci_v)) { + iopaddr_t busaddr; + IOERROR_GETVALUE(busaddr, ioerror, busaddr); + retval = usrpci_error_handler (usrpci_v, error_code, busaddr); + hwgraph_vertex_unref(usrpci_v); + if (retval != IOERROR_UNHANDLED) { + /* + * This unref is not needed. If this code is called often enough, + * the system will crash, due to vertex reference count reaching 0, + * causing vertex to be unallocated. -jeremy + * hwgraph_vertex_unref(pconn_vhdl); + */ + return retval; + } + } +#endif + } + } + + return (mode == MODE_DEVPROBE) + ? IOERROR_HANDLED /* probes are OK */ + : IOERROR_UNHANDLED; /* otherwise, foo! */ +} + +/* ===================================================================== + * CONFIGURATION MANAGEMENT + */ + +/* + * Startup a crosstalk provider + */ +void +pciio_provider_startup(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_startup) + (pciio_provider); +} + +/* + * Shutdown a crosstalk provider + */ +void +pciio_provider_shutdown(devfs_handle_t pciio_provider) +{ + DEV_FUNC(pciio_provider, provider_shutdown) + (pciio_provider); +} + +/* + * 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(devfs_handle_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(devfs_handle_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 +pciio_config_get(devfs_handle_t dev, + unsigned reg, + unsigned size) +{ + uint64_t value = 0; + unsigned shift = 0; + + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + value |= DEV_FUNC(dev, config_get) + (dev, reg, biw) << shift; + + shift += 8*biw; + reg += biw; + size -= biw; + } + return value; +} + +/* + * Change value of configuration register + */ +void +pciio_config_set(devfs_handle_t dev, + unsigned reg, + unsigned size, + uint64_t value) +{ + /* handle accesses that cross words here, + * since that's common code between all + * possible providers. + */ + while (size > 0) { + unsigned biw = 4 - (reg&3); + if (biw > size) + biw = size; + + DEV_FUNC(dev, config_set) + (dev, reg, biw, value); + reg += biw; + size -= biw; + value >>= biw * 8; + } +} + +/* ===================================================================== + * GENERIC PCI SUPPORT FUNCTIONS + */ + +/* + * Issue a hardware reset to a card. + */ +int +pciio_reset(devfs_handle_t dev) +{ + return DEV_FUNC(dev, reset) (dev); +} + +/* + * flush write gather buffers + */ +int +pciio_write_gather_flush(devfs_handle_t dev) +{ + return DEV_FUNC(dev, write_gather_flush) (dev); +} + +devfs_handle_t +pciio_intr_dev_get(pciio_intr_t pciio_intr) +{ + return (pciio_intr->pi_dev); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_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 ******/ +devfs_handle_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 +pciio_info_chk(devfs_handle_t pciio) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(pciio, INFO_LBL_PCIIO, &ainfo); + return (pciio_info_t) ainfo; +} + +pciio_info_t +pciio_info_get(devfs_handle_t pciio) +{ + pciio_info_t pciio_info; + + pciio_info = (pciio_info_t) hwgraph_fastinfo_get(pciio); + +#ifdef DEBUG_PCIIO + { + int pos; + char dname[256]; + pos = devfs_generate_path(pciio, dname, 256); + printk("%s : path= %s\n", __FUNCTION__, &dname[pos]); + } +#endif /* DEBUG_PCIIO */ + + if ((pciio_info != NULL) && + (pciio_info->c_fingerprint != pciio_info_fingerprint) + && (pciio_info->c_fingerprint != NULL)) { + + return((pciio_info_t)-1); /* Should panic .. */ + } + + + return pciio_info; +} + +void +pciio_info_set(devfs_handle_t pciio, pciio_info_t pciio_info) +{ + if (pciio_info != NULL) + pciio_info->c_fingerprint = pciio_info_fingerprint; + hwgraph_fastinfo_set(pciio, (arbitrary_info_t) pciio_info); + + /* Also, mark this vertex as a PCI slot + * and use the pciio_info, so pciio_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(pciio, INFO_LBL_PCIIO, + (arbitrary_info_t) pciio_info); +} + +devfs_handle_t +pciio_info_dev_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vertex); +} + +pciio_slot_t +pciio_info_slot_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_slot); +} + +pciio_function_t +pciio_info_function_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_func); +} + +pciio_vendor_id_t +pciio_info_vendor_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_vendor); +} + +pciio_device_id_t +pciio_info_device_id_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_device); +} + +devfs_handle_t +pciio_info_master_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_master); +} + +arbitrary_info_t +pciio_info_mfast_get(pciio_info_t pciio_info) +{ + return (pciio_info->c_mfast); +} + +pciio_provider_t * +pciio_info_pops_get(pciio_info_t pciio_info) +{ + 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) +{ + return info->c_window[win].w_base; +} + +size_t +pciio_info_bar_size_get(pciio_info_t info, int win) +{ + return info->c_window[win].w_size; +} + +iopaddr_t +pciio_info_rom_base_get(pciio_info_t info) +{ + return info->c_rbase; +} + +size_t +pciio_info_rom_size_get(pciio_info_t info) +{ + return info->c_rsize; +} + + +/* ===================================================================== + * GENERIC PCI INITIALIZATION FUNCTIONS + */ + +/* + * pciioinit: called once during device driver + * initializtion if this driver is configured into + * the system. + */ +void +pciio_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("pciio_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (pciio_registry == NULL) { + cp = cdl_new(EDGE_LBL_PCI, "vendor", "device"); + if (!compare_and_swap_ptr((void **) &pciio_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(pciio_registry != NULL); +} + +/* + * pciioattach: called for each vertex in the graph + * that is a PCI provider. + */ +/*ARGSUSED */ +int +pciio_attach(devfs_handle_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 +#endif + return 0; +} + +/* + * Associate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_register(devfs_handle_t provider, pciio_provider_t *pciio_fns) +{ + hwgraph_info_add_LBL(provider, INFO_LBL_PFUNCS, (arbitrary_info_t) pciio_fns); +} + +/* + * Disassociate a set of pciio_provider functions with a vertex. + */ +void +pciio_provider_unregister(devfs_handle_t provider) +{ + arbitrary_info_t ainfo; + + hwgraph_info_remove_LBL(provider, INFO_LBL_PFUNCS, (long *) &ainfo); +} + +/* + * Obtain a pointer to the pciio_provider functions for a specified Crosstalk + * provider. + */ +pciio_provider_t * +pciio_provider_fns_get(devfs_handle_t provider) +{ + arbitrary_info_t ainfo = 0; + + (void) hwgraph_info_get_LBL(provider, INFO_LBL_PFUNCS, &ainfo); + 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) +{ + /* a driver's init routine might call + * pciio_driver_register before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + return cdl_add_driver(pciio_registry, + vendor_id, device_id, + driver_prefix, flags, NULL); +} + +/* + * Remove an initialization function. + */ +void +pciio_driver_unregister( + char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called register; so + * we can assume we have a registry here. + */ + ASSERT(pciio_registry != NULL); + + cdl_del_driver(pciio_registry, driver_prefix, NULL); +} + +/* + * Set the slot status for a device supported by the + * driver being registered. + */ +void +pciio_driver_reg_callback( + devfs_handle_t pconn_vhdl, + int key1, + int key2, + int error) +{ +} + +/* + * Set the slot status for a device supported by the + * driver being unregistered. + */ +void +pciio_driver_unreg_callback( + devfs_handle_t pconn_vhdl, + int key1, + int key2, + int error) +{ +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +pciio_iterate(char *driver_prefix, + pciio_iter_f * func) +{ + /* a driver's init routine might call + * pciio_iterate before the + * system calls pciio_init; so we + * make the init call ourselves here. + */ + if (pciio_registry == NULL) + pciio_init(); + + ASSERT(pciio_registry != NULL); + + cdl_iterate(pciio_registry, driver_prefix, (cdl_iter_f *) func); +} + +devfs_handle_t +pciio_device_register( + devfs_handle_t connectpt, /* vertex for /hw/.../pciio/%d */ + devfs_handle_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(devfs_handle_t pconn) +{ + DEV_FUNC(pconn,device_unregister)(pconn); +} + +pciio_info_t +pciio_device_info_new( + pciio_info_t pciio_info, + devfs_handle_t master, + pciio_slot_t slot, + pciio_function_t func, + pciio_vendor_id_t vendor_id, + pciio_device_id_t device_id) +{ + if (!pciio_info) + GET_NEW(pciio_info); + ASSERT(pciio_info != NULL); + + pciio_info->c_slot = slot; + pciio_info->c_func = func; + pciio_info->c_vendor = vendor_id; + pciio_info->c_device = device_id; + pciio_info->c_master = master; + pciio_info->c_mfast = hwgraph_fastinfo_get(master); + pciio_info->c_pops = pciio_provider_fns_get(master); + pciio_info->c_efunc = 0; + pciio_info->c_einfo = 0; + + return pciio_info; +} + +void +pciio_device_info_free(pciio_info_t pciio_info) +{ + /* 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)); +} + +devfs_handle_t +pciio_device_info_register( + devfs_handle_t connectpt, /* vertex at center of bus */ + pciio_info_t pciio_info) /* details about the connectpt */ +{ + char name[32]; + devfs_handle_t pconn; + int device_master_set(devfs_handle_t, devfs_handle_t); + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + if (GRAPH_SUCCESS != + hwgraph_path_add(connectpt, name, &pconn)) + return pconn; + + pciio_info->c_vertex = pconn; + pciio_info_set(pconn, pciio_info); +#ifdef DEBUG_PCIIO + { + int pos; + char dname[256]; + pos = devfs_generate_path(pconn, dname, 256); + printk("%s : pconn path= %s \n", __FUNCTION__, &dname[pos]); + } +#endif /* DEBUG_PCIIO */ + + /* + * create link to our pci provider + */ + + device_master_set(pconn, pciio_info->c_master); + +#if USRPCI + /* + * Call into usrpci provider to let it initialize for + * the given slot. + */ + if (pciio_info->c_slot != PCIIO_SLOT_NONE) + usrpci_device_register(pconn, pciio_info->c_master, pciio_info->c_slot); +#endif + + return pconn; +} + +void +pciio_device_info_unregister(devfs_handle_t connectpt, + pciio_info_t pciio_info) +{ + char name[32]; + devfs_handle_t pconn; + + if (!pciio_info) + return; + + pciio_slot_func_to_name(name, + pciio_info->c_slot, + pciio_info->c_func); + + hwgraph_edge_remove(connectpt,name,&pconn); + pciio_info_set(pconn,0); + + /* Remove the link to our pci provider */ + hwgraph_edge_remove(pconn, EDGE_LBL_MASTER, NULL); + + + hwgraph_vertex_unref(pconn); + hwgraph_vertex_destroy(pconn); + +} +/* Add the pci card inventory information to the hwgraph + */ +static void +pciio_device_inventory_add(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + + /* Donot add inventory for non-existent devices */ + if ((pciio_info->c_vendor == PCIIO_VENDOR_ID_NONE) || + (pciio_info->c_device == PCIIO_DEVICE_ID_NONE)) + return; + device_inventory_add(pconn_vhdl,INV_IOBD,INV_PCIADAP, + pciio_info->c_vendor,pciio_info->c_device, + pciio_info->c_slot); +} + +/*ARGSUSED */ +int +pciio_device_attach(devfs_handle_t pconn, + int drv_flags) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + + pciio_device_inventory_add(pconn); + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + return(cdl_add_connpt(pciio_registry, vendor_id, device_id, pconn, drv_flags)); +} + +int +pciio_device_detach(devfs_handle_t pconn, + int drv_flags) +{ + pciio_info_t pciio_info; + pciio_vendor_id_t vendor_id; + pciio_device_id_t device_id; + + pciio_info = pciio_info_get(pconn); + + vendor_id = pciio_info->c_vendor; + device_id = pciio_info->c_device; + + /* we don't start attaching things until + * all the driver init routines (including + * pciio_init) have been called; so we + * can assume here that we have a registry. + */ + ASSERT(pciio_registry != NULL); + + return(cdl_del_connpt(pciio_registry, vendor_id, device_id, + pconn, drv_flags)); + +} + +/* SN2 */ +/* + * Allocate (if necessary) and initialize a PCI window mapping structure. + */ +pciio_win_map_t +pciio_device_win_map_new(pciio_win_map_t win_map, + size_t region_size, + size_t page_size) +{ + ASSERT((page_size & (page_size - 1)) == 0); + ASSERT((region_size & (page_size - 1)) == 0); + + if (win_map == NULL) + NEW(win_map); + + /* + * The map array tracks the free ``pages'' in the region. The worst + * case scenario is when every other page in the region is free -- + * e.i. maximum fragmentation. This leads to (max pages + 1) / 2 + 1 + * map entries. The first "+1" handles the divide by 2 rounding; the + * second handles the need for an end marker sentinel. + */ + win_map->wm_map = rmallocmap((region_size / page_size + 1) / 2 + 1); + win_map->wm_page_size = page_size; + ASSERT(win_map->wm_map != NULL); + + return win_map; +} + +/* + * Free resources associated with a PCI window mapping structure. + */ +extern void +pciio_device_win_map_free(pciio_win_map_t win_map) +{ + rmfreemap(win_map->wm_map); + bzero(win_map, sizeof *win_map); +} + +/* + * Populate window map with specified free range. + */ +void +pciio_device_win_populate(pciio_win_map_t win_map, + iopaddr_t ioaddr, + size_t size) +{ + ASSERT((size & (win_map->wm_page_size - 1)) == 0); + ASSERT((ioaddr & (win_map->wm_page_size - 1)) == 0); + + rmfree(win_map->wm_map, + size / win_map->wm_page_size, + (unsigned long)ioaddr / win_map->wm_page_size); + +} +/* + * Allocate space from the specified PCI window mapping resource. On + * success record information about the allocation in the supplied window + * allocation cookie (if non-NULL) and return the address of the allocated + * window. On failure return NULL. + * + * The "size" parameter is usually from a PCI device's Base Address Register + * (BAR) decoder. As such, the allocation must be aligned to be a multiple of + * that. The "align" parameter acts as a ``minimum alignment'' allocation + * constraint. The alignment contraint reflects system or device addressing + * restrictions such as the inability to share higher level ``windows'' + * between devices, etc. The returned PCI address allocation will be a + * multiple of the alignment constraint both in alignment and size. Thus, the + * returned PCI address block is aligned to the maximum of the requested size + * and alignment. + */ +iopaddr_t +pciio_device_win_alloc(pciio_win_map_t win_map, + pciio_win_alloc_t win_alloc, + size_t start, size_t size, size_t align) +{ + unsigned long base; + +#ifdef PIC_LATER + ASSERT((size & (size - 1)) == 0); + ASSERT((align & (align - 1)) == 0); + + /* + * Convert size and alignment to pages. If size is greated than the + * requested alignment, we bump the alignment up to size; otherwise + * convert the size into a multiple of the alignment request. + */ + size = (size + win_map->wm_page_size - 1) / win_map->wm_page_size; + align = align / win_map->wm_page_size; + if (size > align) + align = size; + else + size = (size + align - 1) & ~(align - 1); + + /* XXXX */ + base = rmalloc_align(win_map->wm_map, size, align, VM_NOSLEEP); + if (base == RMALLOC_FAIL) + return((iopaddr_t)NULL); +#else + int index_page, index_page_align; + int align_pages, size_pages; + int alloc_pages, free_pages; + int addr_align; + + /* Convert PCI bus alignment from bytes to pages */ + align_pages = align / win_map->wm_page_size; + + /* Convert PCI request from bytes to pages */ + size_pages = (size / win_map->wm_page_size) + + ((size % win_map->wm_page_size) ? 1 : 0); + + /* Align address with the larger of the size or the requested slot align */ + if (size_pages > align_pages) + align_pages = size_pages; + + /* + * Avoid wasting space by aligning - 1; this will prevent crossing + * another alignment boundary. + */ + alloc_pages = size_pages + (align_pages - 1); + + /* Allocate PCI bus space in pages */ + index_page = (int) rmalloc(win_map->wm_map, + (size_t) alloc_pages); + + /* Error if no PCI bus address space available */ + if (!index_page) + return 0; + + /* PCI bus address index starts at 0 */ + index_page--; + + /* Align the page offset as requested */ + index_page_align = (index_page + (align_pages - 1)) - + ((index_page + (align_pages - 1)) % align_pages); + + free_pages = (align_pages - 1) - (index_page_align - index_page); + + /* Free unused PCI bus pages adjusting the index to start at 1 */ + rmfree(win_map->wm_map, + free_pages, + (index_page_align + 1) + size_pages); + + /* Return aligned PCI bus space in bytes */ + addr_align = (index_page_align * win_map->wm_page_size); + base = index_page; + size = alloc_pages - free_pages; +#endif /* PIC_LATER */ + + /* + * If a window allocation cookie has been supplied, use it to keep + * track of all the allocated space assigned to this window. + */ + if (win_alloc) { + win_alloc->wa_map = win_map; + win_alloc->wa_base = base; + win_alloc->wa_pages = size; + } + + return base * win_map->wm_page_size; +} + +/* + * Free the specified window allocation back into the PCI window mapping + * resource. As noted above, we keep page addresses offset by 1 ... + */ +void +pciio_device_win_free(pciio_win_alloc_t win_alloc) +{ + if (win_alloc->wa_pages) + rmfree(win_alloc->wa_map->wm_map, + win_alloc->wa_pages, + win_alloc->wa_base); +} + +/* + * pciio_error_register: + * arrange for a function to be called with + * a specified first parameter plus other + * information when an error is encountered + * and traced to the pci slot corresponding + * to the connection point pconn. + * + * may also be called with a null function + * pointer to "unregister" the error handler. + * + * NOTE: subsequent calls silently overwrite + * previous data for this vertex. We assume that + * cooperating drivers, well, cooperate ... + */ +void +pciio_error_register(devfs_handle_t pconn, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + pciio_info_t pciio_info; + + pciio_info = pciio_info_get(pconn); + ASSERT(pciio_info != NULL); + pciio_info->c_efunc = efunc; + pciio_info->c_einfo = einfo; +} + +/* + * Check if any device has been found in this slot, and return + * true or false + * vhdl is the vertex for the slot + */ +int +pciio_slot_inuse(devfs_handle_t pconn_vhdl) +{ + pciio_info_t pciio_info = pciio_info_get(pconn_vhdl); + + ASSERT(pciio_info); + ASSERT(pciio_info->c_vertex == pconn_vhdl); + if (pciio_info->c_vendor) { + /* + * Non-zero value for vendor indicate + * a board being found in this slot. + */ + return 1; + } + return 0; +} + +int +pciio_dma_enabled(devfs_handle_t pconn_vhdl) +{ + return DEV_FUNC(pconn_vhdl, dma_enabled)(pconn_vhdl); +} + +int +pciio_info_type1_get(pciio_info_t pci_info) +{ + return(0); +} + + +/* + * These are complementary Linux interfaces that takes in a pci_dev * as the + * first arguement instead of devfs_handle_t. + */ +iopaddr_t snia_pciio_dmatrans_addr(struct pci_dev *, device_desc_t, paddr_t, size_t, unsigned); +pciio_dmamap_t snia_pciio_dmamap_alloc(struct pci_dev *, device_desc_t, size_t, unsigned); +void snia_pciio_dmamap_free(pciio_dmamap_t); +iopaddr_t snia_pciio_dmamap_addr(pciio_dmamap_t, paddr_t, size_t); +void snia_pciio_dmamap_done(pciio_dmamap_t); +pciio_endian_t snia_pciio_endian_set(struct pci_dev *pci_dev, pciio_endian_t device_end, + pciio_endian_t desired_end); + +#include +EXPORT_SYMBOL(snia_pciio_dmatrans_addr); +EXPORT_SYMBOL(snia_pciio_dmamap_alloc); +EXPORT_SYMBOL(snia_pciio_dmamap_free); +EXPORT_SYMBOL(snia_pciio_dmamap_addr); +EXPORT_SYMBOL(snia_pciio_dmamap_done); +EXPORT_SYMBOL(snia_pciio_endian_set); + +int +snia_pcibr_rrb_alloc(struct pci_dev *pci_dev, + int *count_vchan0, + int *count_vchan1) +{ + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + return pcibr_rrb_alloc(dev, count_vchan0, count_vchan1); +} +EXPORT_SYMBOL(snia_pcibr_rrb_alloc); + +pciio_endian_t +snia_pciio_endian_set(struct pci_dev *pci_dev, + pciio_endian_t device_end, + pciio_endian_t desired_end) +{ + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + return DEV_FUNC(dev, endian_set) + (dev, device_end, desired_end); +} + +iopaddr_t +snia_pciio_dmatrans_addr(struct pci_dev *pci_dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + /* + * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be + * set. Otherwise, it must not be set. This applies to SN1 and SN2. + */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM); +} + +pciio_dmamap_t +snia_pciio_dmamap_alloc(struct pci_dev *pci_dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + + devfs_handle_t dev = PCIDEV_VERTEX(pci_dev); + + /* + * If the device is not a PIC, we always want the PCIIO_BYTE_STREAM to be + * set. Otherwise, it must not be set. This applies to SN1 and SN2. + */ + return (pciio_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, (IS_PIC_DEVICE(pci_dev)) ? (flags & ~PCIIO_BYTE_STREAM) : flags | PCIIO_BYTE_STREAM); +} + +void +snia_pciio_dmamap_free(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_free) + (CAST_DMAMAP(pciio_dmamap)); +} + +iopaddr_t +snia_pciio_dmamap_addr(pciio_dmamap_t pciio_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(pciio_dmamap, dmamap_addr) + (CAST_DMAMAP(pciio_dmamap), paddr, byte_count); +} + +void +snia_pciio_dmamap_done(pciio_dmamap_t pciio_dmamap) +{ + DMAMAP_FUNC(pciio_dmamap, dmamap_done) + (CAST_DMAMAP(pciio_dmamap)); +} + diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/pic.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,325 @@ +/* + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char *bcopy(const char * src, char * dest, int count); + + +#define PCI_BUS_NO_1 1 + +int pic_devflag = D_MP; + +extern int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t, int, pcibr_soft_t *); +extern void pcibr_driver_reg_callback(devfs_handle_t, int, int, int); +extern void pcibr_driver_unreg_callback(devfs_handle_t, int, int, int); + + +void +pic_init(void) +{ + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pic_init()\n")); + + xwidget_driver_register(PIC_WIDGET_PART_NUM_BUS0, + PIC_WIDGET_MFGR_NUM, + "pic_", + 0); +} + +/* + * copy inventory_t from conn_v to peer_conn_v + */ +int +pic_bus1_inventory_dup(devfs_handle_t conn_v, devfs_handle_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); + bcopy(pinv, peer_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 ", + conn_v); + return 0; +} + +/* + * copy xwidget_info_t from conn_v to peer_conn_v + */ +int +pic_bus1_widget_info_dup(devfs_handle_t conn_v, devfs_handle_t peer_conn_v, + cnodeid_t xbow_peer) +{ + xwidget_info_t widget_info, peer_widget_info; + char peer_path[256]; + char *p; + devfs_handle_t peer_hubv; + hubinfo_t peer_hub_info; + + /* get the peer hub's widgetid */ + peer_hubv = NODEPDA(xbow_peer)->node_vertex; + peer_hub_info = NULL; + hubinfo_get(peer_hubv, &peer_hub_info); + if (peer_hub_info == NULL) + return 0; + + 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; + /* 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_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); + return 0; + } + + xwidget_info_set(peer_conn_v, peer_widget_info); + + return 1; + } + + printk("pic_bus1_widget_info_dup: " + "cannot get INFO_LBL_XWIDGET from 0x%lx\n", conn_v); + return 0; +} + +/* + * If this PIC is attached to two Cbricks ("dual-ported") then + * attach each bus to opposite Cbricks. + * + * If successful, return a new vertex suitable for attaching the PIC bus. + * If not successful, return zero and both buses will attach to the + * vertex passed into pic_attach(). + */ +devfs_handle_t +pic_bus1_redist(nasid_t nasid, devfs_handle_t conn_v) +{ + cnodeid_t cnode = NASID_TO_COMPACT_NODEID(nasid); + cnodeid_t xbow_peer = -1; + char pathname[256], peer_path[256], tmpbuf[256]; + char *p; + int rc; + devfs_handle_t peer_conn_v; + int pos; + slabid_t slab; + + if (NODEPDA(cnode)->xbow_peer >= 0) { /* if dual-ported */ + /* create a path for this widget on the peer Cbrick */ + /* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */ + /* sprintf(pathname, "%v", conn_v); */ + xbow_peer = NASID_TO_COMPACT_NODEID(NODEPDA(cnode)->xbow_peer); + pos = devfs_generate_path(conn_v, tmpbuf, 256); + strcpy(pathname, &tmpbuf[pos]); + p = pathname + strlen("hw/module/001c01/slab/0/"); + + memset(tmpbuf, 0, 16); + format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF); + slab = geo_slab((NODEPDA(xbow_peer))->geoid); + sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); + + /* Look for vertex for this widget on the peer Cbrick. + * Expect GRAPH_NOT_FOUND. + */ + rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v); + if (GRAPH_SUCCESS == rc) + printk("pic_attach: found unexpected vertex: 0x%lx\n", + peer_conn_v); + else if (GRAPH_NOT_FOUND != rc) { + printk("pic_attach: hwgraph_traverse unexpectedly" + " returned 0x%x\n", rc); + } else { + /* try to add the widget vertex to the peer Cbrick */ + rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v); + + if (GRAPH_SUCCESS != rc) + printk("pic_attach: hwgraph_path_add" + " failed with 0x%x\n", rc); + else { + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_bus1_redist: added vertex %v\n", peer_conn_v)); + + /* Now hang appropiate stuff off of the new + * vertex. We bail out if we cannot add something. + * In that case, we don't remove the newly added + * 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; + + return peer_conn_v; + } + } + } + return 0; +} + + +int +pic_attach(devfs_handle_t conn_v) +{ + int rc; + bridge_t *bridge0, *bridge1 = (bridge_t *)0; + devfs_handle_t pcibr_vhdl0, pcibr_vhdl1 = (devfs_handle_t)0; + pcibr_soft_t bus0_soft, bus1_soft = (pcibr_soft_t)0; + devfs_handle_t conn_v0, conn_v1, peer_conn_v; + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n")); + + bridge0 = (bridge_t *) xtalk_piotrans_addr(conn_v, NULL, + 0, sizeof(bridge_t), 0); + 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", + 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)) + conn_v1 = peer_conn_v; + + /* + * Create the vertex for the PCI buses, which week + * will also use to hold the pcibr_soft and + * which will be the "master" vertex for all the + * pciio connection points we will hang off it. + * This needs to happen before we call nic_bridge_vertex_info + * as we are some of the *_vmc functions need access to the edges. + * + * 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); + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_attach: pcibr_vhdl0=%v, pcibr_vhdl1=%v\n", + pcibr_vhdl0, pcibr_vhdl1)); + + /* register pci provider array */ + pciio_provider_register(pcibr_vhdl0, &pci_pic_provider); + pciio_provider_register(pcibr_vhdl1, &pci_pic_provider); + + pciio_provider_startup(pcibr_vhdl0); + pciio_provider_startup(pcibr_vhdl1); + + pcibr_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft); + pcibr_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft); + + /* save a pointer to the PIC's other bus's soft struct */ + bus0_soft->bs_peers_soft = bus1_soft; + bus1_soft->bs_peers_soft = bus0_soft; + bus0_soft->bs_peers_soft = (pcibr_soft_t)0; + + PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, + "pic_attach: bus0_soft=0x%x, bus1_soft=0x%x\n", + bus0_soft, bus1_soft)); + + return 0; +} + +/* + * pci provider functions + * + * mostly in pcibr.c but if any are needed here then + * this might be a way to get them here. + */ +pciio_provider_t pci_pic_provider = +{ + (pciio_piomap_alloc_f *) pcibr_piomap_alloc, + (pciio_piomap_free_f *) pcibr_piomap_free, + (pciio_piomap_addr_f *) pcibr_piomap_addr, + (pciio_piomap_done_f *) pcibr_piomap_done, + (pciio_piotrans_addr_f *) pcibr_piotrans_addr, + (pciio_piospace_alloc_f *) pcibr_piospace_alloc, + (pciio_piospace_free_f *) pcibr_piospace_free, + + (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc, + (pciio_dmamap_free_f *) pcibr_dmamap_free, + (pciio_dmamap_addr_f *) pcibr_dmamap_addr, + (pciio_dmamap_list_f *) pcibr_dmamap_list, + (pciio_dmamap_done_f *) pcibr_dmamap_done, + (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr, + (pciio_dmatrans_list_f *) pcibr_dmatrans_list, + (pciio_dmamap_drain_f *) pcibr_dmamap_drain, + (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain, + (pciio_dmalist_drain_f *) pcibr_dmalist_drain, + + (pciio_intr_alloc_f *) pcibr_intr_alloc, + (pciio_intr_free_f *) pcibr_intr_free, + (pciio_intr_connect_f *) pcibr_intr_connect, + (pciio_intr_disconnect_f *) pcibr_intr_disconnect, + (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get, + + (pciio_provider_startup_f *) pcibr_provider_startup, + (pciio_provider_shutdown_f *) pcibr_provider_shutdown, + (pciio_reset_f *) pcibr_reset, + (pciio_write_gather_flush_f *) pcibr_write_gather_flush, + (pciio_endian_set_f *) pcibr_endian_set, + (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 -Nru a/arch/ia64/sn/io/sn2/sgi_io_init.c b/arch/ia64/sn/io/sn2/sgi_io_init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/sgi_io_init.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,226 @@ +/* $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 mlreset(void); +extern int init_hcl(void); +extern void klgraph_hack_init(void); +extern void hubspc_init(void); +extern void pciio_init(void); +extern void pcibr_init(void); +extern void xtalk_init(void); +extern void xbow_init(void); +extern void xbmon_init(void); +extern void pciiox_init(void); +extern void pic_init(void); +extern void usrpci_init(void); +extern void ioc3_init(void); +extern void initialize_io(void); +extern void klhwg_add_all_modules(devfs_handle_t); +extern void klhwg_add_all_nodes(devfs_handle_t); + +void sn_mp_setup(void); +extern devfs_handle_t hwgraph_root; +extern void io_module_init(void); +extern void pci_bus_cvlink_init(void); +extern void temp_hack(void); + +extern int pci_bus_to_hcl_cvlink(void); + +/* #define DEBUG_IO_INIT 1 */ +#ifdef DEBUG_IO_INIT +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif /* DEBUG_IO_INIT */ + +/* + * per_hub_init + * + * This code is executed once for each Hub chip. + */ +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; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + ASSERT(nasid != INVALID_NASID); + ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode); + + npdap = NODEPDA(cnode); + + REMOTE_HUB_S(nasid, IIO_IWEIM, 0x8000); + + /* + * Set the total number of CRBs that can be used. + */ + ii_icmr.ii_icmr_regval= 0x0; + ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf; + REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval); + + /* + * 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_fld_s.i_count = 0x8; + REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval); + + /* + * Set CRB timeout to be 10ms. + */ +#ifdef BRINGUP2 + REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff ); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); + //REMOTE_HUB_S(nasid, IIO_IWI, 0x00FF00FF00FFFFFF); +#endif + + /* 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 +sgi_master_io_infr_init(void) +{ + int cnode; + extern void kdba_io_init(); + + /* + * Do any early init stuff .. einit_tbl[] etc. + */ + init_hcl(); /* Sets up the hwgraph compatibility layer with devfs */ + + /* + * initialize the Linux PCI to xwidget vertexes .. + */ + pci_bus_cvlink_init(); + + kdba_io_init(); + +#ifdef BRINGUP + /* + * Hack to provide statically initialzed klgraph entries. + */ + DBG("--> sgi_master_io_infr_init: calling klgraph_hack_init()\n"); + klgraph_hack_init(); +#endif /* BRINGUP */ + + /* + * This is the Master CPU. Emulate mlsetup and main.c in Irix. + */ + mlreset(); + + /* + * allowboot() is called by kern/os/main.c in main() + * Emulate allowboot() ... + * per_cpu_init() - only need per_hub_init() + * cpu_io_setup() - Nothing to do. + * + */ + sn_mp_setup(); + + for (cnode = 0; cnode < numnodes; cnode++) { + per_hub_init(cnode); + } + + /* We can do headless hub cnodes here .. */ + + /* + * io_init[] stuff. + * + * Get SGI IO Infrastructure drivers to init and register with + * each other etc. + */ + + hubspc_init(); + pciio_init(); + pcibr_init(); + pic_init(); + xtalk_init(); + xbow_init(); + xbmon_init(); + pciiox_init(); + usrpci_init(); + ioc3_init(); + + /* + * + * Our IO Infrastructure drivers are in place .. + * Initialize the whole IO Infrastructure .. xwidget/device probes. + * + */ + initialize_io(); + pci_bus_to_hcl_cvlink(); + +#ifdef CONFIG_PCIBA + DBG("--> sgi_master_io_infr_init: calling pciba_init()\n"); +#ifndef BRINGUP2 + pciba_init(); +#endif +#endif +} + +/* + * One-time setup for MP SN. + * Allocate per-node data, slurp prom klconfig information and + * convert it to hwgraph information. + */ +void +sn_mp_setup(void) +{ + cpuid_t cpu; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + /* Skip holes in CPU space */ + if (cpu_enabled(cpu)) { + init_platform_pda(cpu); + } + } + + /* + * 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); +} diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/shub.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,233 @@ +/* $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. + */ + +#ident "$Revision: 1.167 $" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 + +static uint32_t shub_perf_counts[SHUB_NUM_ECF_REGISTERS]; + +static shubreg_t shub_perf_counts_regs[SHUB_NUM_ECF_REGISTERS] = { + SH_PERFORMANCE_COUNTER0, + SH_PERFORMANCE_COUNTER1, + SH_PERFORMANCE_COUNTER2, + SH_PERFORMANCE_COUNTER3, + SH_PERFORMANCE_COUNTER4, + SH_PERFORMANCE_COUNTER5, + SH_PERFORMANCE_COUNTER6, + SH_PERFORMANCE_COUNTER7 +}; + +static inline void +shub_mmr_write(cnodeid_t cnode, shubreg_t reg, uint64_t val) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint64_t *addr = (uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + + *addr = val; + __ia64_mf_a(); +} + +static inline void +shub_mmr_write32(cnodeid_t cnode, shubreg_t reg, uint32_t val) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint32_t *addr = (uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + + *addr = val; + __ia64_mf_a(); +} + +static inline uint64_t +shub_mmr_read(cnodeid_t cnode, shubreg_t reg) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint64_t val; + + val = *(uint64_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + __ia64_mf_a(); + + return val; +} + +static inline uint32_t +shub_mmr_read32(cnodeid_t cnode, shubreg_t reg) +{ + int nasid = cnodeid_to_nasid(cnode); + volatile uint32_t val; + + val = *(uint32_t *)(GLOBAL_MMR_ADDR(nasid, reg)); + __ia64_mf_a(); + + return val; +} + +static int +reset_shub_stats(cnodeid_t cnode) +{ + int i; + + for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) { + shub_perf_counts[i] = 0; + shub_mmr_write32(cnode, shub_perf_counts_regs[i], 0); + } + return 0; +} + +static int +configure_shub_stats(cnodeid_t cnode, unsigned long arg) +{ + uint64_t *p = (uint64_t *)arg; + uint64_t i; + uint64_t regcnt; + uint64_t regval[2]; + + if (copy_from_user((void *)®cnt, p, sizeof(regcnt))) + return -EFAULT; + + for (p++, i=0; i < regcnt; i++, p += 2) { + if (copy_from_user((void *)regval, (void *)p, sizeof(regval))) + return -EFAULT; + if (regval[0] & 0x7) { + printk("Error: configure_shub_stats: unaligned address 0x%016lx\n", regval[0]); + return -EINVAL; + } + shub_mmr_write(cnode, (shubreg_t)regval[0], regval[1]); + } + return 0; +} + +static int +capture_shub_stats(cnodeid_t cnode, uint32_t *counts) +{ + int i; + + for (i=0; i < SHUB_NUM_ECF_REGISTERS; i++) { + counts[i] = shub_mmr_read32(cnode, shub_perf_counts_regs[i]); + } + return 0; +} + +static int +shubstats_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + cnodeid_t cnode; + uint64_t longarg; + devfs_handle_t d; + int nasid; + + if ((d = devfs_get_handle_from_inode(inode)) == NULL) + return -ENODEV; + cnode = (cnodeid_t)hwgraph_fastinfo_get(d); + + switch (cmd) { + case SNDRV_SHUB_CONFIGURE: + return configure_shub_stats(cnode, arg); + break; + + case SNDRV_SHUB_RESETSTATS: + reset_shub_stats(cnode); + break; + + case SNDRV_SHUB_INFOSIZE: + longarg = sizeof(shub_perf_counts); + if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) { + return -EFAULT; + } + break; + + case SNDRV_SHUB_GETSTATS: + capture_shub_stats(cnode, shub_perf_counts); + if (copy_to_user((void *)arg, shub_perf_counts, + sizeof(shub_perf_counts))) { + return -EFAULT; + } + break; + + case SNDRV_SHUB_GETNASID: + nasid = cnodeid_to_nasid(cnode); + if (copy_to_user((void *)arg, &nasid, + sizeof(nasid))) { + return -EFAULT; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +struct file_operations shub_mon_fops = { + ioctl: shubstats_ioctl, +}; diff -Nru a/arch/ia64/sn/io/sn2/shubio.c b/arch/ia64/sn/io/sn2/shubio.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/shubio.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,510 @@ +/* $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. + * + * Copyright (C) 1992 - 1997, 2000,2002-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 + + +error_state_t error_state_get(devfs_handle_t v); +error_return_code_t error_state_set(devfs_handle_t v,error_state_t new_state); + + +/* + * Get the xtalk provider function pointer for the + * specified hub. + */ + +/*ARGSUSED*/ +int +hub_xp_error_handler( + devfs_handle_t hub_v, + nasid_t nasid, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + /*REFERENCED*/ + hubreg_t iio_imem; + devfs_handle_t xswitch; + error_state_t e_state; + cnodeid_t cnode; + + /* + * Before walking down to the next level, check if + * the I/O link is up. If it's been disabled by the + * hub ii for some reason, we can't even touch the + * widget registers. + */ + iio_imem = REMOTE_HUB_L(nasid, IIO_IMEM); + + if (!(iio_imem & (IIO_IMEM_B0ESD|IIO_IMEM_W0ESD))){ + /* + * IIO_IMEM_B0ESD getting set, indicates II shutdown + * on HUB0 parts.. Hopefully that's not true for + * Hub1 parts.. + * + * + * If either one of them is shut down, can't + * go any further. + */ + return IOERROR_XTALKLEVEL; + } + + /* Get the error state of the hub */ + e_state = error_state_get(hub_v); + + cnode = NASID_TO_COMPACT_NODEID(nasid); + + xswitch = NODEPDA(cnode)->basew_xc; + + /* Set the error state of the crosstalk device to that of + * hub. + */ + if (error_state_set(xswitch , e_state) == + ERROR_RETURN_CODE_CANNOT_SET_STATE) + return(IOERROR_UNHANDLED); + + /* Clean the error state of the hub if we are in the action handling + * phase. + */ + if (e_state == ERROR_STATE_ACTION) + (void)error_state_set(hub_v, ERROR_STATE_NONE); + /* hand the error off to the switch or the directly + * connected crosstalk device. + */ + return xtalk_error_handler(xswitch, + error_code, mode, ioerror); + +} + +/* + * Check if the widget in error has been enabled for PIO accesses + */ +int +is_widget_pio_enabled(ioerror_t *ioerror) +{ + cnodeid_t src_node; + nasid_t src_nasid; + hubreg_t ii_iowa; + xwidgetnum_t widget; + iopaddr_t p; + + /* Get the node where the PIO error occurred */ + IOERROR_GETVALUE(p,ioerror, srcnode); + src_node = p; + if (src_node == CNODEID_NONE) + return(0); + + /* Get the nasid for the cnode */ + src_nasid = COMPACT_TO_NASID_NODEID(src_node); + if (src_nasid == INVALID_NASID) + return(0); + + /* Read the Outbound widget access register for this hub */ + ii_iowa = REMOTE_HUB_L(src_nasid, IIO_IOWA); + IOERROR_GETVALUE(p,ioerror, widgetnum); + widget = p; + + /* Check if the PIOs to the widget with PIO error have been + * enabled. + */ + if (ii_iowa & IIO_IOWA_WIDGET(widget)) + return(1); + + return(0); +} + +/* + * Hub IO error handling. + * + * Gets invoked for different types of errors found at the hub. + * Typically this includes situations from bus error or due to + * an error interrupt (mostly generated at the hub). + */ +int +hub_ioerror_handler( + devfs_handle_t hub_v, + int error_code, + int mode, + struct io_error_s *ioerror) +{ + hubinfo_t hinfo; /* Hub info pointer */ + nasid_t nasid; + int retval = 0; + /*REFERENCED*/ + iopaddr_t p; + + IOERROR_DUMP("hub_ioerror_handler", error_code, mode, ioerror); + + hubinfo_get(hub_v, &hinfo); + + if (!hinfo){ + /* Print an error message and return */ + goto end; + } + nasid = hinfo->h_nasid; + + switch(error_code) { + + case PIO_READ_ERROR: + /* + * Cpu got a bus error while accessing IO space. + * hubaddr field in ioerror structure should have + * the IO address that caused access error. + */ + + /* + * Identify if the physical address in hub_error_data + * corresponds to small/large window, and accordingly, + * get the xtalk address. + */ + + /* + * Evaluate the widget number and the widget address that + * caused the error. Use 'vaddr' if it's there. + * This is typically true either during probing + * or a kernel driver getting into trouble. + * Otherwise, use paddr to figure out widget details + * This is typically true for user mode bus errors while + * accessing I/O space. + */ + IOERROR_GETVALUE(p,ioerror,vaddr); + if (p){ + /* + * If neither in small window nor in large window range, + * outright reject it. + */ + IOERROR_GETVALUE(p,ioerror,vaddr); + if (NODE_SWIN_ADDR(nasid, (paddr_t)p)){ + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + widgetnum = SWIN_WIDGETNUM(hubaddr); + xtalkaddr = SWIN_WIDGETADDR(hubaddr); + /* + * differentiate local register vs IO space access + */ + IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); + IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); + + + } else if (NODE_BWIN_ADDR(nasid, (paddr_t)p)){ + /* + * Address corresponds to large window space. + * Convert it to xtalk address. + */ + int bigwin; + hub_piomap_t bw_piomap; + xtalk_piomap_t xt_pmap = NULL; + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + + /* + * Have to loop to find the correct xtalk_piomap + * because the're not allocated on a one-to-one + * basis to the window number. + */ + for (bigwin=0; bigwin < HUB_NUM_BIG_WINDOW; bigwin++) { + bw_piomap = hubinfo_bwin_piomap_get(hinfo, + bigwin); + + if (bw_piomap->hpio_bigwin_num == + (BWIN_WINDOWNUM(hubaddr) - 1)) { + xt_pmap = hub_piomap_xt_piomap(bw_piomap); + break; + } + } + + ASSERT(xt_pmap); + + widgetnum = xtalk_pio_target_get(xt_pmap); + xtalkaddr = xtalk_pio_xtalk_addr_get(xt_pmap) + BWIN_WIDGETADDR(hubaddr); + + IOERROR_SETVALUE(ioerror,widgetnum,widgetnum); + IOERROR_SETVALUE(ioerror,xtalkaddr,xtalkaddr); + + /* + * Make sure that widgetnum doesnot map to hub + * register widget number, as we never use + * big window to access hub registers. + */ + ASSERT(widgetnum != HUB_REGISTER_WIDGET); + } + } else if (IOERROR_FIELDVALID(ioerror,hubaddr)) { + iopaddr_t hubaddr; + xwidgetnum_t widgetnum; + iopaddr_t xtalkaddr; + + IOERROR_GETVALUE(p,ioerror,hubaddr); + hubaddr = p; + if (BWIN_WINDOWNUM(hubaddr)){ + int window = BWIN_WINDOWNUM(hubaddr) - 1; + hubreg_t itte; + itte = (hubreg_t)HUB_L(IIO_ITTE_GET(nasid, window)); + widgetnum = (itte >> IIO_ITTE_WIDGET_SHIFT) & + IIO_ITTE_WIDGET_MASK; + xtalkaddr = (((itte >> IIO_ITTE_OFFSET_SHIFT) & + IIO_ITTE_OFFSET_MASK) << + BWIN_SIZE_BITS) + + BWIN_WIDGETADDR(hubaddr); + } else { + widgetnum = SWIN_WIDGETNUM(hubaddr); + xtalkaddr = SWIN_WIDGETADDR(hubaddr); + } + 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")); + + return IOERROR_INVALIDADDR; + } + + + IOERROR_GETVALUE(p,ioerror,widgetnum); + if ((p) == HUB_REGISTER_WIDGET) { + /* + * Error in accessing Hub local register + * This should happen mostly in SABLE mode.. + */ + retval = 0; + } else { + /* Make sure that the outbound widget access for this + * 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); + } + + + retval = hub_xp_error_handler( + hub_v, nasid, error_code, mode, ioerror); + + } + + IOERR_PRINTF(printk( + "hub_ioerror_handler:PIO_READ_ERROR return: %d", + retval)); + + break; + + case PIO_WRITE_ERROR: + /* + * This hub received an interrupt indicating a widget + * attached to this hub got a timeout. + * widgetnum field should be filled to indicate the + * widget that caused error. + * + * NOTE: This hub may have nothing to do with this error. + * We are here since the widget attached to the xbow + * gets its PIOs through this hub. + * + * There is nothing that can be done at this level. + * Just invoke the xtalk error handling mechanism. + */ + IOERROR_GETVALUE(p,ioerror,widgetnum); + if ((p) == HUB_REGISTER_WIDGET) { + } else { + /* Make sure that the outbound widget access for this + * 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); + } + + retval = hub_xp_error_handler( + hub_v, nasid, error_code, mode, ioerror); + } + break; + + case DMA_READ_ERROR: + /* + * DMA Read error always ends up generating an interrupt + * at the widget level, and never at the hub level. So, + * we don't expect to come here any time + */ + ASSERT(0); + retval = IOERROR_UNHANDLED; + break; + + case DMA_WRITE_ERROR: + /* + * DMA Write error is generated when a write by an I/O + * device could not be completed. Problem is, device is + * totally unaware of this problem, and would continue + * writing to system memory. So, hub has a way to send + * an error interrupt on the first error, and bitbucket + * all further write transactions. + * Coming here indicates that hub detected one such error, + * and we need to handle it. + * + * Hub interrupt handler would have extracted physaddr, + * widgetnum, and widgetdevice from the CRB + * + * There is nothing special to do here, since gathering + * data from crb's is done elsewhere. Just pass the + * error to xtalk layer. + */ + retval = hub_xp_error_handler(hub_v, nasid, error_code, mode, + ioerror); + break; + + default: + ASSERT(0); + return IOERROR_BADERRORCODE; + + } + + /* + * If error was not handled, we may need to take certain action + * based on the error code. + * For e.g. in case of PIO_READ_ERROR, we may need to release the + * PIO Read entry table (they are sticky after errors). + * Similarly other cases. + * + * Further Action TBD + */ +end: + if (retval == IOERROR_HWGRAPH_LOOKUP) { + /* + * If we get errors very early, we can't traverse + * the path using hardware graph. + * To handle this situation, we need a functions + * which don't depend on the hardware graph vertex to + * handle errors. This break the modularity of the + * existing code. Instead we print out the reason for + * not handling error, and return. On return, all the + * info collected would be dumped. This should provide + * sufficient info to analyse the error. + */ + printk("Unable to handle IO error: hardware graph not setup\n"); + } + + return retval; +} + +#define L_BITSMINOR 18 +#define L_MAXMAJ 0x1ff +#define emajor(x) (int )(((unsigned )(x)>>L_BITSMINOR) & L_MAXMAJ) +#define dev_is_vertex(dev) (emajor((dev_t)(dev)) == 0) + +#define INFO_LBL_ERROR_STATE "error_state" + +#define v_error_state_get(v,s) \ +(hwgraph_info_get_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t *)&s)) + +#define v_error_state_set(v,s,replace) \ +(replace ? \ +hwgraph_info_replace_LBL(v,INFO_LBL_ERROR_STATE,(arbitrary_info_t)s,0) :\ +hwgraph_info_add_LBL(v,INFO_LBL_ERROR_STATE, (arbitrary_info_t)s)) + + +#define v_error_state_clear(v) \ +(hwgraph_info_remove_LBL(v,INFO_LBL_ERROR_STATE,0)) + +/* + * error_state_get + * Get the state of the vertex. + * Returns ERROR_STATE_INVALID on failure + * current state otherwise + */ +error_state_t +error_state_get(devfs_handle_t v) +{ + error_state_t s; + + /* Check if we have a valid hwgraph vertex */ + if (!dev_is_vertex(v)) + return(ERROR_STATE_NONE); + + /* Get the labelled info hanging off the vertex which corresponds + * to the state. + */ + if (v_error_state_get(v, s) != GRAPH_SUCCESS) { + return(ERROR_STATE_NONE); + } + return(s); +} + + +/* + * error_state_set + * Set the state of the vertex + * Returns ERROR_RETURN_CODE_CANNOT_SET_STATE on failure + * ERROR_RETURN_CODE_SUCCESS otherwise + */ +error_return_code_t +error_state_set(devfs_handle_t v,error_state_t new_state) +{ + error_state_t old_state; + boolean_t replace = B_TRUE; + + /* Check if we have a valid hwgraph vertex */ + if (!dev_is_vertex(v)) + return(ERROR_RETURN_CODE_GENERAL_FAILURE); + + + /* This means that the error state needs to be cleaned */ + if (new_state == ERROR_STATE_NONE) { + /* Make sure that we have an error state */ + if (v_error_state_get(v,old_state) == GRAPH_SUCCESS) + v_error_state_clear(v); + return(ERROR_RETURN_CODE_SUCCESS); + } + + /* Check if the state information has been set at least once + * for this vertex. + */ + if (v_error_state_get(v,old_state) != GRAPH_SUCCESS) + replace = B_FALSE; + + if (v_error_state_set(v,new_state,replace) != GRAPH_SUCCESS) { + return(ERROR_RETURN_CODE_CANNOT_SET_STATE); + } + return(ERROR_RETURN_CODE_SUCCESS); +} diff -Nru a/arch/ia64/sn/io/sn2/xbow.c b/arch/ia64/sn/io/sn2/xbow.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/xbow.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,1681 @@ +/* $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 +#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 NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +int xbow_devflag = D_MP; + +/* + * This file supports the Xbow chip. Main functions: initializtion, + * error handling, and GBR. + */ + +/* + * each vertex corresponding to an xbow chip + * has a "fastinfo" pointer pointing at one + * of these things. + */ +typedef struct xbow_soft_s *xbow_soft_t; + +struct xbow_soft_s { + devfs_handle_t conn; /* our connection point */ + devfs_handle_t vhdl; /* xbow's private vertex */ + devfs_handle_t busv; /* the xswitch vertex */ + 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))) + +/* + * Function Table of Contents + */ + +void xbow_mlreset(xbow_t *); +void xbow_init(void); +int xbow_attach(devfs_handle_t); + +int xbow_open(devfs_handle_t *, int, int, cred_t *); +int xbow_close(devfs_handle_t, int, int, cred_t *); + +int xbow_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint); +int xbow_unmap(devfs_handle_t, vhandl_t *); +int xbow_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *); + +int xbow_widget_present(xbow_t *, int); +static int xbow_link_alive(xbow_t *, int); +devfs_handle_t xbow_widget_lookup(devfs_handle_t, int); + +void xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t); + + + +void xbow_update_perf_counters(devfs_handle_t); +xbow_perf_link_t *xbow_get_perf_counters(devfs_handle_t); +int xbow_enable_perf_counter(devfs_handle_t, int, int, int); +xbow_link_status_t *xbow_get_llp_status(devfs_handle_t); +void xbow_update_llp_status(devfs_handle_t); + +int xbow_disable_llp_monitor(devfs_handle_t); +int xbow_enable_llp_monitor(devfs_handle_t); +int xbow_prio_bw_alloc(devfs_handle_t, xwidgetnum_t, xwidgetnum_t, + unsigned long long, unsigned long long); +static void xbow_setwidint(xtalk_intr_t); +void idbg_xbowregs(int64_t); + +xswitch_reset_link_f xbow_reset_link; + +xswitch_provider_t xbow_provider = +{ + xbow_reset_link, +}; + +/* + * This is the file operation table for the pcibr driver. + * As each of the functions are implemented, put the + * appropriate function name below. + */ +static int xbow_mmap(struct file * file, struct vm_area_struct * vma); +struct file_operations xbow_fops = { + owner: THIS_MODULE, + llseek: NULL, + read: NULL, + write: NULL, + readdir: NULL, + poll: NULL, + ioctl: NULL, + mmap: xbow_mmap, + open: xbow_open, + flush: NULL, + release: NULL, + fsync: NULL, + fasync: NULL, + lock: NULL, + readv: NULL, + writev: NULL, + sendpage: NULL, + get_unmapped_area: NULL +}; + +static int +xbow_mmap(struct file * file, struct vm_area_struct * vma) +{ + unsigned long phys_addr; + int error = 0; + + 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, vma->vm_start, phys_addr, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); + return(error); +} + + +/* + * 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) +{ +} + +/* + * xbow_init: called with the rest of the device + * driver XXX_init routines. This platform *might* + * have a Crossbow chip, or even several, but it + * might have none. Register with the crosstalk + * generic provider so when we encounter the chip + * the right magic happens. + */ +void +xbow_init(void) +{ + +#if DEBUG && ATTACH_DEBUG + printk("xbow_init\n"); +#endif + + xwidget_driver_register(PXBOW_WIDGET_PART_NUM, + 0, /* XXBOW_WIDGET_MFGR_NUM, */ + "xbow_", + CDL_PRI_HI); /* attach before friends */ + + + xwidget_driver_register(XXBOW_WIDGET_PART_NUM, + 0, /* XXBOW_WIDGET_MFGR_NUM, */ + "xbow_", + CDL_PRI_HI); /* attach before friends */ + + xwidget_driver_register(XBOW_WIDGET_PART_NUM, + XBOW_WIDGET_MFGR_NUM, + "xbow_", + CDL_PRI_HI); /* attach before friends */ +} + +#ifdef XBRIDGE_REGS_SIM +/* xbow_set_simulated_regs: sets xbow regs as needed + * for powering through the boot + */ +void +xbow_set_simulated_regs(xbow_t *xbow, int port) +{ + /* + * turn on link + */ + xbow->xb_link(port).link_status = (1<<31); + /* + * and give it a live widget too + */ + xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT; + /* + * zero the link control reg + */ + xbow->xb_link(port).link_control = 0x0; +} +#endif /* XBRIDGE_REGS_SIM */ + +/* + * xbow_attach: the crosstalk provider has + * determined that there is a crossbow widget + * present, and has handed us the connection + * point for that vertex. + * + * We not only add our own vertex, but add + * some "xtalk switch" data to the switch + * vertex (at the connect point's parent) if + * it does not have any. + */ + +/*ARGSUSED */ +int +xbow_attach(devfs_handle_t conn) +{ + /*REFERENCED */ + devfs_handle_t vhdl; + devfs_handle_t busv; + xbow_t *xbow; + xbow_soft_t soft; + int port; + xswitch_info_t info; + xtalk_intr_t intr_hdl; + char devnm[MAXDEVNAME], *s; + xbowreg_t id; + int rev; + int i; + int xbow_num; + 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 +#endif + + /* + * Get a PIO pointer to the base of the crossbow + * chip. + */ +#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); + /* + * turn on ports e and f like in a real live ibrick + */ + xbow_set_simulated_regs(xbow, 0xe); + xbow_set_simulated_regs(xbow, 0xf); +#else + xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0); +#endif /* XBRIDGE_REGS_SIM */ + + /* + * Locate the "switch" vertex: it is the parent + * of our connection point. + */ + busv = hwgraph_connectpt_get(conn); +#if DEBUG && ATTACH_DEBUG + printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow); +#endif + + ASSERT(busv != GRAPH_VERTEX_NONE); + + /* + * Create our private vertex, and connect our + * driver information to it. This makes it possible + * for diagnostic drivers to open the crossbow + * vertex for access to registers. + */ + + /* + * Register a xbow driver with devfs. + * file ops. + */ + vhdl = NULL; + vhdl = devfs_register(conn, EDGE_LBL_XBOW, + DEVFS_FL_AUTO_DEVNUM, 0, 0, + S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, + &xbow_fops, (void *)xbow); + if (!vhdl) { + printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n", + (void *)conn); + } + + /* + * Allocate the soft state structure and attach + * it to the xbow's vertex + */ + NEW(soft); + soft->conn = conn; + soft->vhdl = vhdl; + soft->busv = busv; + soft->base = xbow; + /* does the universe really need another macro? */ + /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */ + /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */ + +#define XBOW_NUM_SUFFIX_FORMAT "[xbow# %d]" + + /* Add xbow number as a suffix to the hwgraph name of the xbow. + * This is helpful while looking at the error/warning messages. + */ + xbow_num = 0; + + /* + * get the name of this xbow vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(vhdl, devnm, MAXDEVNAME); + soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, + GFP_KERNEL); + sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num); + +#ifdef XBRIDGE_REGS_SIM + /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined + * as 0xd000, so I'm using that for the partnum bitfield. + */ + printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n"); + id = 0x2d000049; +#else + id = xbow->xb_wid_id; +#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 */ + for (i = 0; i < MAX_XBOW_PORTS; i++) { + soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX; /* for now */ + soft->bw_cur_used[i] = 0; + } + + /* + * attach the crossbow error interrupt. + */ + intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl); + ASSERT(intr_hdl != NULL); + + xtalk_intr_connect(intr_hdl, + (intr_func_t) xbow_errintr_handler, + (intr_arg_t) soft, + (xtalk_intr_setfunc_t) xbow_setwidint, + (void *) xbow); + + request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, + ((hub_intr_t)intr_hdl)->i_bit), + (intr_func_t)xbow_errintr_handler, 0, "XBOW error", + (intr_arg_t) soft); + +#ifdef BUS_INT_WAR_NOT_YET + { + void sn_add_polled_interrupt(int, int); + sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)intr_hdl)->i_cpuid, + ((hub_intr_t)intr_hdl)->i_bit), 5000); + } +#endif + + + /* + * Enable xbow error interrupts + */ + xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE); + + /* + * take a census of the widgets present, + * leaving notes at the switch vertex. + */ + info = xswitch_info_new(busv); + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; ++port) { + if (!xbow_link_alive(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is not alive\n", + (void *)busv, port); +#endif + continue; + } + if (!xbow_widget_present(xbow, port)) { +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", (void *)busv, port); +#endif + continue; + } +#if DEBUG && XBOW_DEBUG + printk(KERN_INFO "0x%p link %d has a widget\n", + (void *)busv, port); +#endif + + xswitch_info_link_is_ok(info, port); + /* + * Turn some error interrupts on + * and turn others off. The PROM has + * some things turned on we don't + * want to see (bandwidth allocation + * errors for instance); so if it + * is not listed here, it is not on. + */ + xbow->xb_link(port).link_control = + ( (xbow->xb_link(port).link_control + /* + * Turn off these bits; they are non-fatal, + * but we might want to save some statistics + * on the frequency of these errors. + * XXX FIXME XXX + */ + & ~XB_CTRL_RCV_CNT_OFLOW_IE + & ~XB_CTRL_XMT_CNT_OFLOW_IE + & ~XB_CTRL_BNDWDTH_ALLOC_IE + & ~XB_CTRL_RCV_IE) + /* + * These are the ones we want to turn on. + */ + | (XB_CTRL_ILLEGAL_DST_IE + | XB_CTRL_OALLOC_IBUF_IE + | XB_CTRL_XMT_MAX_RTRY_IE + | XB_CTRL_MAXREQ_TOUT_IE + | XB_CTRL_XMT_RTRY_IE + | XB_CTRL_SRC_TOUT_IE) ); + } + + xswitch_provider_register(busv, &xbow_provider); + + return 0; /* attach successful */ +} + +/*ARGSUSED */ +int +xbow_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp) +{ + return 0; +} + +/*ARGSUSED */ +int +xbow_close(devfs_handle_t dev, int oflag, int otyp, cred_t *crp) +{ + return 0; +} + +/*ARGSUSED */ +int +xbow_map(devfs_handle_t dev, vhandl_t *vt, off_t off, size_t len, uint prot) +{ + devfs_handle_t vhdl = dev_to_vhdl(dev); + xbow_soft_t soft = xbow_soft_get(vhdl); + int error; + + ASSERT(soft); + len = ctob(btoc(len)); + /* XXX- this ignores the offset!!! */ + error = v_mapphys(vt, (void *) soft->base, len); + return error; +} + +/*ARGSUSED */ +int +xbow_unmap(devfs_handle_t dev, vhandl_t *vt) +{ + return 0; +} + +/* 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(devfs_handle_t dev) +{ + devfs_handle_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; +} + +int +xbow_ioctl(devfs_handle_t dev, + int cmd, + void *arg, + int flag, + struct cred *cr, + int *rvalp) +{ + devfs_handle_t vhdl; + int error = 0; + +#if defined (DEBUG) + int rc; + devfs_handle_t conn; + struct xwidget_info_s *xwidget_info; + xbow_soft_t xbow_soft; +#endif + *rvalp = 0; + + vhdl = dev_to_vhdl(dev); +#if defined (DEBUG) + xbow_soft = xbow_soft_get(vhdl); + conn = xbow_soft->conn; + + xwidget_info = xwidget_info_get(conn); + ASSERT_ALWAYS(xwidget_info != NULL); + + rc = xwidget_hwid_is_xswitch(&xwidget_info->w_hwid); + ASSERT_ALWAYS(rc != 0); +#endif + switch (cmd) { + + case XBOWIOC_LLP_ERROR_ENABLE: + if ((error = xbow_enable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + + case XBOWIOC_LLP_ERROR_DISABLE: + + if ((error = xbow_disable_llp_monitor(vhdl)) != 0) + error = EINVAL; + + break; + + default: + break; + + } + return error; +} + +/* + * xbow_widget_present: See if a device is present + * on the specified port of this crossbow. + */ +int +xbow_widget_present(xbow_t *xbow, int port) +{ + if ( IS_RUNNING_ON_SIMULATOR() ) { + if ( (port == 14) || (port == 15) ) { + return 1; + } + else { + return 0; + } + } + else { + /* WAR: port 0xf on PIC is missing present bit */ + if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) && + IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) { + return 1; + } + return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT; + } +} + +static int +xbow_link_alive(xbow_t * xbow, int port) +{ + xbwX_stat_t xbow_linkstat; + + xbow_linkstat.linkstatus = xbow->xb_link(port).link_status; + return (xbow_linkstat.link_alive); +} + +/* + * xbow_widget_lookup + * Lookup the edges connected to the xbow specified, and + * retrieve the handle corresponding to the widgetnum + * specified. + * If not found, return 0. + */ +devfs_handle_t +xbow_widget_lookup(devfs_handle_t vhdl, + int widgetnum) +{ + xswitch_info_t xswitch_info; + devfs_handle_t conn; + + xswitch_info = xswitch_info_get(vhdl); + conn = xswitch_info_vhdl_get(xswitch_info, widgetnum); + return conn; +} + +/* + * xbow_setwidint: called when xtalk + * is establishing or migrating our + * interrupt service. + */ +static void +xbow_setwidint(xtalk_intr_t intr) +{ + xwidgetnum_t targ = xtalk_intr_target_get(intr); + iopaddr_t addr = xtalk_intr_addr_get(intr); + xtalk_intr_vector_t vect = xtalk_intr_vector_get(intr); + xbow_t *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr); + + xbow_intr_preset((void *) xbow, 0, targ, addr, vect); +} + +/* + * xbow_intr_preset: called during mlreset time + * if the platform specific code needs to route + * an xbow interrupt before the xtalk infrastructure + * is available for use. + * + * Also called from xbow_setwidint, so we don't + * replicate the guts of the routine. + * + * XXX- probably should be renamed xbow_wid_intr_set or + * something to reduce confusion. + */ +/*ARGSUSED3 */ +void +xbow_intr_preset(void *which_widget, + int which_widget_intr, + xwidgetnum_t targ, + iopaddr_t addr, + xtalk_intr_vector_t vect) +{ + xbow_t *xbow = (xbow_t *) which_widget; + + xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) | + (0x000F0000 & (targ << 16)) | + XTALK_ADDR_TO_UPPER(addr)); + xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr); + +} + +#define XEM_ADD_STR(s) printk("%s", (s)) +#define XEM_ADD_NVAR(n,v) printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v)) +#define XEM_ADD_VAR(v) XEM_ADD_NVAR(#v,(v)) +#define XEM_ADD_IOEF(p,n) if (IOERROR_FIELDVALID(ioe,n)) { \ + IOERROR_GETVALUE(p,ioe,n); \ + XEM_ADD_NVAR("ioe." #n, p); \ + } + +#ifdef LATER +static void +xem_add_ioe(ioerror_t *ioe) +{ + union tmp { + ushort stmp; + unsigned long long lltmp; + cpuid_t cputmp; + cnodeid_t cntmp; + iopaddr_t iotmp; + caddr_t catmp; + paddr_t patmp; + } tmp; + + XEM_ADD_IOEF(tmp.stmp, errortype); + XEM_ADD_IOEF(tmp.stmp, widgetnum); + XEM_ADD_IOEF(tmp.stmp, widgetdev); + XEM_ADD_IOEF(tmp.cputmp, srccpu); + XEM_ADD_IOEF(tmp.cntmp, srcnode); + XEM_ADD_IOEF(tmp.cntmp, errnode); + XEM_ADD_IOEF(tmp.iotmp, sysioaddr); + XEM_ADD_IOEF(tmp.iotmp, xtalkaddr); + XEM_ADD_IOEF(tmp.iotmp, busspace); + XEM_ADD_IOEF(tmp.iotmp, busaddr); + XEM_ADD_IOEF(tmp.catmp, vaddr); + XEM_ADD_IOEF(tmp.patmp, memaddr); + XEM_ADD_IOEF(tmp.catmp, epc); + XEM_ADD_IOEF(tmp.catmp, ef); + XEM_ADD_IOEF(tmp.stmp, tnum); +} + +#define XEM_ADD_IOE() (xem_add_ioe(ioe)) +#endif /* LATER */ + +int xbow_xmit_retry_errors = 0; + +int +xbow_xmit_retry_error(xbow_soft_t soft, + int port) +{ + xswitch_info_t info; + devfs_handle_t vhdl; + widget_cfg_t *wid; + widgetreg_t id; + int part; + int mfgr; + + wid = soft->wpio[port - BASE_XBOW_PORT]; + if (wid == NULL) { + /* If we can't track down a PIO + * pointer to our widget yet, + * leave our caller knowing that + * we are interested in this + * interrupt if it occurs in + * the future. + */ + info = xswitch_info_get(soft->busv); + if (!info) + return 1; + vhdl = xswitch_info_vhdl_get(info, port); + if (vhdl == GRAPH_VERTEX_NONE) + return 1; + wid = (widget_cfg_t *) xtalk_piotrans_addr + (vhdl, 0, 0, sizeof *wid, 0); + if (!wid) + return 1; + soft->wpio[port - BASE_XBOW_PORT] = wid; + } + id = wid->w_id; + 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; +} + +/* + * xbow_errintr_handler will be called if the xbow + * sends an interrupt request to report an error. + */ +static void +xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep) +{ + ioerror_t ioe[1]; + xbow_soft_t soft = (xbow_soft_t) arg; + xbow_t *xbow = soft->base; + xbowreg_t wid_control; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + w_err_cmd_word_u wid_err; + unsigned long long wid_err_addr; + + int fatal = 0; + int dump_ioe = 0; + static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *); + + wid_control = xbow->xb_wid_control; + wid_stat = xbow->xb_wid_stat_clr; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + xbow->xb_wid_err_cmdword = 0; + + wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32); + + if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) { + int port; + + wid_err.r = wid_err_cmdword; + + for (port = MAX_PORT_NUM - MAX_XBOW_PORTS; + port < MAX_PORT_NUM; port++) { + if (wid_stat & XB_WID_STAT_LINK_INTR(port)) { + xb_linkregs_t *link = &(xbow->xb_link(port)); + xbowreg_t link_control = link->link_control; + xbowreg_t link_status = link->link_status_clr; + xbowreg_t link_aux_status = link->link_aux_status; + xbowreg_t link_pend; + + link_pend = link_status & link_control & + (XB_STAT_ILLEGAL_DST_ERR + | XB_STAT_OALLOC_IBUF_ERR + | XB_STAT_RCV_CNT_OFLOW_ERR + | XB_STAT_XMT_CNT_OFLOW_ERR + | XB_STAT_XMT_MAX_RTRY_ERR + | XB_STAT_RCV_ERR + | XB_STAT_XMT_RTRY_ERR + | XB_STAT_MAXREQ_TOUT_ERR + | XB_STAT_SRC_TOUT_ERR + ); + + if (link_pend & XB_STAT_ILLEGAL_DST_ERR) { + if (wid_err.f.sidn == port) { + IOERROR_INIT(ioe); + IOERROR_SETVALUE(ioe, widgetnum, port); + IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr); + if (IOERROR_HANDLED == + xbow_error_handler(soft, + IOECODE_DMA, + MODE_DEVERROR, + ioe)) { + link_pend &= ~XB_STAT_ILLEGAL_DST_ERR; + } else { + dump_ioe++; + } + } + } + /* Xbow/Bridge WAR: + * if the bridge signals an LLP Transmitter Retry, + * rewrite its control register. + * If someone else triggers this interrupt, + * ignore (and disable) the interrupt. + */ + if (link_pend & XB_STAT_XMT_RTRY_ERR) { + if (!xbow_xmit_retry_error(soft, port)) { + link_control &= ~XB_CTRL_XMT_RTRY_IE; + link->link_control = link_control; + link->link_control; /* stall until written */ + } + link_pend &= ~XB_STAT_XMT_RTRY_ERR; + } + if (link_pend) { + devfs_handle_t xwidget_vhdl; + char *xwidget_name; + + /* Get the widget name corresponding to the current + * xbow link. + */ + xwidget_vhdl = xbow_widget_lookup(soft->busv,port); + xwidget_name = xwidget_name_get(xwidget_vhdl); + + printk("%s port %X[%s] XIO Bus Error", + soft->name, port, xwidget_name); + if (link_status & XB_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Errors\n"); + if (link_status & XB_STAT_ILLEGAL_DST_ERR) + XEM_ADD_STR("\tInvalid Packet Destination\n"); + if (link_status & XB_STAT_OALLOC_IBUF_ERR) + XEM_ADD_STR("\tInput Overallocation Error\n"); + if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP receive error counter overflow\n"); + if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR) + XEM_ADD_STR("\tLLP transmit retry counter overflow\n"); + if (link_status & XB_STAT_XMT_MAX_RTRY_ERR) + XEM_ADD_STR("\tLLP Max Transmitter Retry\n"); + if (link_status & XB_STAT_RCV_ERR) + XEM_ADD_STR("\tLLP Receiver error\n"); + if (link_status & XB_STAT_XMT_RTRY_ERR) + XEM_ADD_STR("\tLLP Transmitter Retry\n"); + if (link_status & XB_STAT_MAXREQ_TOUT_ERR) + XEM_ADD_STR("\tMaximum Request Timeout\n"); + if (link_status & XB_STAT_SRC_TOUT_ERR) + XEM_ADD_STR("\tSource Timeout Error\n"); + + { + int other_port; + + for (other_port = 8; other_port < 16; ++other_port) { + if (link_aux_status & (1 << other_port)) { + /* XXX- need to go to "other_port" + * and clean up after the timeout? + */ + XEM_ADD_VAR(other_port); + } + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); + +#ifdef LATER + if (dump_ioe) { + XEM_ADD_IOE(); + dump_ioe = 0; + } +#endif +#if !DEBUG + } +#endif + fatal++; + } + } + } + } + if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) { + /* we have a "widget zero" problem */ + + if (wid_stat & (XB_WID_STAT_MULTI_ERR + | XB_WID_STAT_XTALK_ERR + | XB_WID_STAT_REG_ACC_ERR)) { + + printk("%s Port 0 XIO Bus Error", + soft->name); + if (wid_stat & XB_WID_STAT_MULTI_ERR) + XEM_ADD_STR("\tMultiple Error\n"); + if (wid_stat & XB_WID_STAT_XTALK_ERR) + XEM_ADD_STR("\tXIO Error\n"); + if (wid_stat & XB_WID_STAT_REG_ACC_ERR) + XEM_ADD_STR("\tRegister Access Error\n"); + + fatal++; + } + } + if (fatal) { + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_control); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + PRINT_PANIC("XIO Bus Error"); + } +} + +/* + * XBOW ERROR Handling routines. + * These get invoked as part of walking down the error handling path + * from hub/heart towards the I/O device that caused the error. + */ + +/* + * xbow_error_handler + * XBow error handling dispatch routine. + * This is the primary interface used by external world to invoke + * in case of an error related to a xbow. + * Only functionality in this layer is to identify the widget handle + * given the widgetnum. Otherwise, xbow does not gathers any error + * data. + */ +static int +xbow_error_handler( + void *einfo, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + int retval = IOERROR_WIDGETLEVEL; + + xbow_soft_t soft = (xbow_soft_t) einfo; + int port; + devfs_handle_t conn; + devfs_handle_t busv; + + xbow_t *xbow = soft->base; + xbowreg_t wid_stat; + xbowreg_t wid_err_cmdword; + xbowreg_t wid_err_upper; + xbowreg_t wid_err_lower; + unsigned long long wid_err_addr; + + xb_linkregs_t *link; + xbowreg_t link_control; + xbowreg_t link_status; + xbowreg_t link_aux_status; + + ASSERT(soft != 0); + busv = soft->busv; + +#if DEBUG && ERROR_DEBUG + printk("%s: xbow_error_handler\n", soft->name, busv); +#endif + + IOERROR_GETVALUE(port, ioerror, widgetnum); + + if (port == 0) { + /* error during access to xbow: + * do NOT attempt to access xbow regs. + */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on Crossbow at %s\n" + "\tbut Crosbow never initiates DMA!", + soft->name); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO controller\n" + "\twith offset 0x%lx", + soft->name, tmp); + } + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* + * error not on port zero: + * safe to read xbow registers. + */ + wid_stat = xbow->xb_wid_stat; + wid_err_cmdword = xbow->xb_wid_err_cmdword; + wid_err_upper = xbow->xb_wid_err_upper; + wid_err_lower = xbow->xb_wid_err_lower; + + wid_err_addr = + wid_err_lower + | (((iopaddr_t) wid_err_upper + & WIDGET_ERR_UPPER_ADDR_ONLY) + << 32); + + if ((port < BASE_XBOW_PORT) || + (port >= MAX_PORT_NUM)) { + + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on XIO port at %s/%d\n" + "\tbut Crossbow does not support that port", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which Crossbow does not support)" + "\twith offset 0x%lx", + soft->name, port, tmp); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); +#if !DEBUG + } +#endif + + /* caller will dump contents of ioerror + * in DEBUG and kdebug kernels. + */ + + return retval; + } + /* access to valid port: + * ok to check port status. + */ + + link = &(xbow->xb_link(port)); + link_control = link->link_control; + link_status = link->link_status; + link_aux_status = link->link_aux_status; + + /* Check that there is something present + * in that XIO port. + */ + /* WAR: PIC widget 0xf is missing prescense bit */ + 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)) { + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (error_code & IOECODE_DMA) { + printk(KERN_ALERT + "DMA error blamed on XIO port at %s/%d\n" + "\tbut there is no device connected there.", + soft->name, port); + } + if (error_code & IOECODE_PIO) { + iopaddr_t tmp; + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + printk(KERN_ALERT + "PIO Error on XIO Bus %s\n" + "\tattempting to access XIO port %d\n" + "\t(which has no device connected)" + "\twith offset 0x%lx", + soft->name, port, tmp); + } +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + return retval; + + } + /* Check that the link is alive. + */ + if (!(link_status & XB_STAT_LINKALIVE)) { + iopaddr_t tmp; + /* nobody connected. */ + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + printk(KERN_ALERT + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + printk("\tAccess attempted to offset 0x%lx\n", tmp); + } + if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD) + XEM_ADD_STR("\tLink never came out of reset\n"); + else + XEM_ADD_STR("\tLink failed while transferring data\n"); + + } + /* get the connection point for the widget + * involved in this error; if it exists and + * is not our connectpoint, cycle back through + * xtalk_error_handler to deliver control to + * the proper handler (or to report a generic + * crosstalk error). + * + * If the downstream handler won't handle + * the problem, we let our upstream caller + * deal with it, after (in DEBUG and kdebug + * kernels) dumping the xbow state for this + * port. + */ + conn = xbow_widget_lookup(busv, port); + if ((conn != GRAPH_VERTEX_NONE) && + (conn != soft->conn)) { + retval = xtalk_error_handler(conn, error_code, mode, ioerror); + if (retval == IOERROR_HANDLED) + return IOERROR_HANDLED; + } + if (mode == MODE_DEVPROBE) + return IOERROR_HANDLED; + + if (retval == IOERROR_UNHANDLED) { + iopaddr_t tmp; + retval = IOERROR_PANIC; + + printk(KERN_ALERT + "%s%sError on XIO Bus %s port %d", + (error_code & IOECODE_DMA) ? "DMA " : "", + (error_code & IOECODE_PIO) ? "PIO " : "", + soft->name, port); + + IOERROR_GETVALUE(tmp, ioerror, xtalkaddr); + if ((error_code & IOECODE_PIO) && + (IOERROR_FIELDVALID(ioerror, xtalkaddr))) { + printk("\tAccess attempted to offset 0x%lx\n", tmp); + } + } + +#if !DEBUG + if (kdebug) { +#endif + XEM_ADD_STR("Raw status values for Crossbow:\n"); + XEM_ADD_VAR(wid_stat); + XEM_ADD_VAR(wid_err_cmdword); + XEM_ADD_VAR(wid_err_upper); + XEM_ADD_VAR(wid_err_lower); + XEM_ADD_VAR(wid_err_addr); + XEM_ADD_VAR(port); + XEM_ADD_VAR(link_control); + XEM_ADD_VAR(link_status); + XEM_ADD_VAR(link_aux_status); +#if !DEBUG + } +#endif + /* caller will dump raw ioerror data + * in DEBUG and kdebug kernels. + */ + + return retval; +} + +void +xbow_update_perf_counters(devfs_handle_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(devfs_handle_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(devfs_handle_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(devfs_handle_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(devfs_handle_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; + devfs_handle_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(devfs_handle_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(devfs_handle_t vhdl) +{ + xbow_soft_t xbow_soft = xbow_soft_get(vhdl); + + xbow_soft->link_monitor = 1; + return 0; +} + + +int +xbow_reset_link(devfs_handle_t xconn_vhdl) +{ + xwidget_info_t widget_info; + xwidgetnum_t port; + 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; + } + widget_info = xwidget_info_get(xconn_vhdl); + port = xwidget_info_id_get(widget_info); + +#ifdef XBOW_K1PTR /* defined if we only have one xbow ... */ + xbow = XBOW_K1PTR; +#else + { + devfs_handle_t xbow_vhdl; + xbow_soft_t xbow_soft; + + hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl); + xbow_soft = xbow_soft_get(xbow_vhdl); + xbow = xbow_soft->base; + } +#endif + + /* + * This requires three PIOs (reset the link, check for the + * reset, restore the control register for the link) plus + * 10us to wait for the reset. We allow up to 1ms for the + * widget to come out of reset before giving up and + * returning a failure. + */ + ctrl = xbow->xb_link(port).link_control; + xbow->xb_link(port).link_reset = 0; + itick = get_timestamp(); + while (1) { + stat.linkstatus = xbow->xb_link(port).link_status; + if (stat.link_alive) + break; + dtick = get_timestamp() - itick; + if (dtick > ticks_per_ms) { + return -1; /* never came out of reset */ + } + DELAY(2); /* don't beat on link_status */ + } + xbow->xb_link(port).link_control = ctrl; + return 0; +} + +/* + * Dump xbow registers. + * input parameter is either a pointer to + * the xbow chip or the vertex handle for + * an xbow vertex. + */ +void +idbg_xbowregs(int64_t regs) +{ + xbow_t *xbow; + int i; + xb_linkregs_t *link; + + xbow = (xbow_t *) regs; + +#ifdef LATER + qprintf("Printing xbow registers starting at 0x%x\n", xbow); + qprintf("wid %x status %x erruppr %x errlower %x control %x timeout %x\n", + xbow->xb_wid_id, xbow->xb_wid_stat, xbow->xb_wid_err_upper, + xbow->xb_wid_err_lower, xbow->xb_wid_control, + xbow->xb_wid_req_timeout); + qprintf("intr uppr %x lower %x errcmd %x llp ctrl %x arb_reload %x\n", + xbow->xb_wid_int_upper, xbow->xb_wid_int_lower, + xbow->xb_wid_err_cmdword, xbow->xb_wid_llp, + xbow->xb_wid_arb_reload); +#endif + + for (i = 8; i <= 0xf; i++) { + link = &xbow->xb_link(i); +#ifdef LATER + qprintf("Link %d registers\n", i); + qprintf("\tctrl %x stat %x arbuppr %x arblowr %x auxstat %x\n", + link->link_control, link->link_status, + link->link_arb_upper, link->link_arb_lower, + link->link_aux_status); +#endif + } +} + + +#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(devfs_handle_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 -Nru a/arch/ia64/sn/io/sn2/xtalk.c b/arch/ia64/sn/io/sn2/xtalk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/io/sn2/xtalk.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,1087 @@ +/* $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 +#include +#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. + * + * On platforms with only one possible xtalk provider, macros can be + * set up at the top that cause the table lookups and indirections to + * completely disappear. + */ + +#define NEW(ptr) (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL)) +#define DEL(ptr) (kfree(ptr)) + +char widget_info_fingerprint[] = "widget_info"; + +cdl_p xtalk_registry = NULL; + +#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 + */ +xtalk_piomap_t xtalk_piomap_alloc(devfs_handle_t, device_desc_t, iopaddr_t, size_t, size_t, unsigned); +void xtalk_piomap_free(xtalk_piomap_t); +caddr_t xtalk_piomap_addr(xtalk_piomap_t, iopaddr_t, size_t); +void xtalk_piomap_done(xtalk_piomap_t); +caddr_t xtalk_piotrans_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, unsigned); +caddr_t xtalk_pio_addr(devfs_handle_t, device_desc_t, iopaddr_t, size_t, xtalk_piomap_t *, unsigned); +void xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *); +caddr_t xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +static caddr_t null_xtalk_early_piotrans_addr(xwidget_part_num_t, xwidget_mfg_num_t, int, iopaddr_t, size_t, unsigned); +xtalk_dmamap_t xtalk_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned); +void xtalk_dmamap_free(xtalk_dmamap_t); +iopaddr_t xtalk_dmamap_addr(xtalk_dmamap_t, paddr_t, size_t); +alenlist_t xtalk_dmamap_list(xtalk_dmamap_t, alenlist_t, unsigned); +void xtalk_dmamap_done(xtalk_dmamap_t); +iopaddr_t xtalk_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned); +alenlist_t xtalk_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned); +void xtalk_dmamap_drain(xtalk_dmamap_t); +void xtalk_dmaaddr_drain(devfs_handle_t, iopaddr_t, size_t); +void xtalk_dmalist_drain(devfs_handle_t, alenlist_t); +xtalk_intr_t xtalk_intr_alloc(devfs_handle_t, device_desc_t, devfs_handle_t); +xtalk_intr_t xtalk_intr_alloc_nothd(devfs_handle_t, device_desc_t, devfs_handle_t); +void xtalk_intr_free(xtalk_intr_t); +int xtalk_intr_connect(xtalk_intr_t, intr_func_t, intr_arg_t, xtalk_intr_setfunc_t, void *); +void xtalk_intr_disconnect(xtalk_intr_t); +devfs_handle_t xtalk_intr_cpu_get(xtalk_intr_t); +int xtalk_error_handler(devfs_handle_t, int, ioerror_mode_t, ioerror_t *); +int xtalk_error_devenable(devfs_handle_t, int, int); +void xtalk_provider_startup(devfs_handle_t); +void xtalk_provider_shutdown(devfs_handle_t); +devfs_handle_t xtalk_intr_dev_get(xtalk_intr_t); +xwidgetnum_t xtalk_intr_target_get(xtalk_intr_t); +xtalk_intr_vector_t xtalk_intr_vector_get(xtalk_intr_t); +iopaddr_t xtalk_intr_addr_get(struct xtalk_intr_s *); +void *xtalk_intr_sfarg_get(xtalk_intr_t); +devfs_handle_t xtalk_pio_dev_get(xtalk_piomap_t); +xwidgetnum_t xtalk_pio_target_get(xtalk_piomap_t); +iopaddr_t xtalk_pio_xtalk_addr_get(xtalk_piomap_t); +ulong xtalk_pio_mapsz_get(xtalk_piomap_t); +caddr_t xtalk_pio_kvaddr_get(xtalk_piomap_t); +devfs_handle_t xtalk_dma_dev_get(xtalk_dmamap_t); +xwidgetnum_t xtalk_dma_target_get(xtalk_dmamap_t); +xwidget_info_t xwidget_info_chk(devfs_handle_t); +xwidget_info_t xwidget_info_get(devfs_handle_t); +void xwidget_info_set(devfs_handle_t, xwidget_info_t); +devfs_handle_t xwidget_info_dev_get(xwidget_info_t); +xwidgetnum_t xwidget_info_id_get(xwidget_info_t); +devfs_handle_t xwidget_info_master_get(xwidget_info_t); +xwidgetnum_t xwidget_info_masterid_get(xwidget_info_t); +xwidget_part_num_t xwidget_info_part_num_get(xwidget_info_t); +xwidget_mfg_num_t xwidget_info_mfg_num_get(xwidget_info_t); +char *xwidget_info_name_get(xwidget_info_t); +void xtalk_init(void); +void xtalk_provider_register(devfs_handle_t, xtalk_provider_t *); +void xtalk_provider_unregister(devfs_handle_t); +xtalk_provider_t *xtalk_provider_fns_get(devfs_handle_t); +int xwidget_driver_register(xwidget_part_num_t, + xwidget_mfg_num_t, + char *, unsigned); +void xwidget_driver_unregister(char *); +int xwidget_register(xwidget_hwid_t, devfs_handle_t, + xwidgetnum_t, devfs_handle_t, + xwidgetnum_t, async_attach_t); +int xwidget_unregister(devfs_handle_t); +void xwidget_reset(devfs_handle_t); +char *xwidget_name_get(devfs_handle_t); +#if !defined(DEV_FUNC) +/* + * There is more than one possible provider + * for this platform. We need to examine the + * master vertex of the current vertex for + * a provider function structure, and indirect + * through the appropriately named member. + */ +#define DEV_FUNC(dev,func) xwidget_to_provider_fns(dev)->func +#define CAST_PIOMAP(x) ((xtalk_piomap_t)(x)) +#define CAST_DMAMAP(x) ((xtalk_dmamap_t)(x)) +#define CAST_INTR(x) ((xtalk_intr_t)(x)) + +static xtalk_provider_t * +xwidget_to_provider_fns(devfs_handle_t xconn) +{ + xwidget_info_t widget_info; + xtalk_provider_t *provider_fns; + + widget_info = xwidget_info_get(xconn); + ASSERT(widget_info != NULL); + + provider_fns = xwidget_info_pops_get(widget_info); + ASSERT(provider_fns != NULL); + + return (provider_fns); +} +#endif + +/* + * Many functions are not passed their vertex + * information directly; rather, they must + * dive through a resource map. These macros + * are available to coordinate this detail. + */ +#define PIOMAP_FUNC(map,func) DEV_FUNC(map->xp_dev,func) +#define DMAMAP_FUNC(map,func) DEV_FUNC(map->xd_dev,func) +#define INTR_FUNC(intr,func) DEV_FUNC(intr_hdl->xi_dev,func) + +/* ===================================================================== + * PIO MANAGEMENT + * + * For mapping system virtual address space to + * xtalk space on a specified widget + */ + +xtalk_piomap_t +xtalk_piomap_alloc(devfs_handle_t dev, /* set up mapping for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* map for this xtalk_addr range */ + size_t byte_count, + size_t byte_count_max, /* maximum size of a mapping */ + unsigned flags) +{ /* defined in sys/pio.h */ + return (xtalk_piomap_t) DEV_FUNC(dev, piomap_alloc) + (dev, dev_desc, xtalk_addr, byte_count, byte_count_max, flags); +} + + +void +xtalk_piomap_free(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_free) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piomap_addr(xtalk_piomap_t xtalk_piomap, /* mapping resources */ + iopaddr_t xtalk_addr, /* map for this xtalk address */ + size_t byte_count) +{ /* map this many bytes */ + return PIOMAP_FUNC(xtalk_piomap, piomap_addr) + (CAST_PIOMAP(xtalk_piomap), xtalk_addr, byte_count); +} + + +void +xtalk_piomap_done(xtalk_piomap_t xtalk_piomap) +{ + PIOMAP_FUNC(xtalk_piomap, piomap_done) + (CAST_PIOMAP(xtalk_piomap)); +} + + +caddr_t +xtalk_piotrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t xtalk_addr, /* Crosstalk address */ + size_t byte_count, /* map this many bytes */ + unsigned flags) +{ /* (currently unused) */ + return DEV_FUNC(dev, piotrans_addr) + (dev, dev_desc, xtalk_addr, byte_count, flags); +} + +caddr_t +xtalk_pio_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + iopaddr_t addr, /* starting address (or offset in window) */ + size_t byte_count, /* map this many bytes */ + xtalk_piomap_t *mapp, /* where to return the map pointer */ + unsigned flags) +{ /* PIO flags */ + xtalk_piomap_t map = 0; + caddr_t res; + + if (mapp) + *mapp = 0; /* record "no map used" */ + + res = xtalk_piotrans_addr + (dev, dev_desc, addr, byte_count, flags); + if (res) + return res; /* xtalk_piotrans worked */ + + map = xtalk_piomap_alloc + (dev, dev_desc, addr, byte_count, byte_count, flags); + if (!map) + return res; /* xtalk_piomap_alloc failed */ + + res = xtalk_piomap_addr + (map, addr, byte_count); + if (!res) { + xtalk_piomap_free(map); + return res; /* xtalk_piomap_addr failed */ + } + if (mapp) + *mapp = map; /* pass back map used */ + + return res; /* xtalk_piomap_addr succeeded */ +} + +/* ===================================================================== + * EARLY PIOTRANS SUPPORT + * + * There are places where drivers (mgras, for instance) + * need to get PIO translations before the infrastructure + * is extended to them (setting up textports, for + * instance). These drivers should call + * xtalk_early_piotrans_addr with their xtalk ID + * information, a sequence number (so we can use the second + * mgras for instance), and the usual piotrans parameters. + * + * Machine specific code should provide an implementation + * of early_piotrans_addr, and present a pointer to this + * function to xtalk_set_early_piotrans_addr so it can be + * used by clients without the clients having to know what + * platform or what xtalk provider is in use. + */ + +static xtalk_early_piotrans_addr_f null_xtalk_early_piotrans_addr; + +xtalk_early_piotrans_addr_f *impl_early_piotrans_addr = null_xtalk_early_piotrans_addr; + +/* xtalk_set_early_piotrans_addr: + * specify the early_piotrans_addr implementation function. + */ +void +xtalk_set_early_piotrans_addr(xtalk_early_piotrans_addr_f *impl) +{ + impl_early_piotrans_addr = impl; +} + +/* xtalk_early_piotrans_addr: + * figure out a PIO address for the "nth" crosstalk 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 + * checked, and definitions of the ordering of the search across + * the crosstalk slots, are defined by the platform. + */ +caddr_t +xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ + return impl_early_piotrans_addr + (part_num, mfg_num, which, xtalk_addr, byte_count, flags); +} + +/* null_xtalk_early_piotrans_addr: + * used as the early_piotrans_addr implementation until and + * unless a real implementation is provided. In DEBUG kernels, + * we want to know who is calling before the implementation is + * registered; in non-DEBUG kernels, return NULL representing + * lack of mapping support. + */ +/*ARGSUSED */ +static caddr_t +null_xtalk_early_piotrans_addr(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + int which, + iopaddr_t xtalk_addr, + size_t byte_count, + unsigned flags) +{ +#if DEBUG + PRINT_PANIC("null_xtalk_early_piotrans_addr"); +#endif + return NULL; +} + +/* ===================================================================== + * DMA MANAGEMENT + * + * For mapping from crosstalk space to system + * physical space. + */ + +xtalk_dmamap_t +xtalk_dmamap_alloc(devfs_handle_t dev, /* set up mappings for this device */ + device_desc_t dev_desc, /* device descriptor */ + size_t byte_count_max, /* max size of a mapping */ + unsigned flags) +{ /* defined in dma.h */ + return (xtalk_dmamap_t) DEV_FUNC(dev, dmamap_alloc) + (dev, dev_desc, byte_count_max, flags); +} + + +void +xtalk_dmamap_free(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_free) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmamap_addr(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + paddr_t paddr, /* map for this address */ + size_t byte_count) +{ /* map this many bytes */ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_addr) + (CAST_DMAMAP(xtalk_dmamap), paddr, byte_count); +} + + +alenlist_t +xtalk_dmamap_list(xtalk_dmamap_t xtalk_dmamap, /* use these mapping resources */ + alenlist_t alenlist, /* map this Address/Length List */ + unsigned flags) +{ + return DMAMAP_FUNC(xtalk_dmamap, dmamap_list) + (CAST_DMAMAP(xtalk_dmamap), alenlist, flags); +} + + +void +xtalk_dmamap_done(xtalk_dmamap_t xtalk_dmamap) +{ + DMAMAP_FUNC(xtalk_dmamap, dmamap_done) + (CAST_DMAMAP(xtalk_dmamap)); +} + + +iopaddr_t +xtalk_dmatrans_addr(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + paddr_t paddr, /* system physical address */ + size_t byte_count, /* length */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_addr) + (dev, dev_desc, paddr, byte_count, flags); +} + + +alenlist_t +xtalk_dmatrans_list(devfs_handle_t dev, /* translate for this device */ + device_desc_t dev_desc, /* device descriptor */ + alenlist_t palenlist, /* system address/length list */ + unsigned flags) +{ /* defined in dma.h */ + return DEV_FUNC(dev, dmatrans_list) + (dev, dev_desc, palenlist, flags); +} + +void +xtalk_dmamap_drain(xtalk_dmamap_t map) +{ + DMAMAP_FUNC(map, dmamap_drain) + (CAST_DMAMAP(map)); +} + +void +xtalk_dmaaddr_drain(devfs_handle_t dev, paddr_t addr, size_t size) +{ + DEV_FUNC(dev, dmaaddr_drain) + (dev, addr, size); +} + +void +xtalk_dmalist_drain(devfs_handle_t dev, alenlist_t list) +{ + DEV_FUNC(dev, dmalist_drain) + (dev, list); +} + +/* ===================================================================== + * INTERRUPT MANAGEMENT + * + * Allow crosstalk devices to establish interrupts + */ + +/* + * Allocate resources required for an interrupt as specified in intr_desc. + * Return resource handle in intr_hdl. + */ +xtalk_intr_t +xtalk_intr_alloc(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) +{ /* owner of this interrupt */ + return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc) + (dev, dev_desc, owner_dev); +} + +/* + * Allocate resources required for an interrupt as specified in dev_desc. + * Unconditionally setup resources to be non-threaded. + * Return resource handle in intr_hdl. + */ +xtalk_intr_t +xtalk_intr_alloc_nothd(devfs_handle_t dev, /* which Crosstalk device */ + device_desc_t dev_desc, /* device descriptor */ + devfs_handle_t owner_dev) /* owner of this interrupt */ +{ + return (xtalk_intr_t) DEV_FUNC(dev, intr_alloc_nothd) + (dev, dev_desc, owner_dev); +} + +/* + * Free resources consumed by intr_alloc. + */ +void +xtalk_intr_free(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_free) + (CAST_INTR(intr_hdl)); +} + + +/* + * Associate resources allocated with a previous xtalk_intr_alloc call with the + * described handler, arg, name, etc. + * + * Returns 0 on success, returns <0 on failure. + */ +int +xtalk_intr_connect(xtalk_intr_t intr_hdl, /* xtalk intr resource handle */ + intr_func_t intr_func, /* xtalk intr handler */ + intr_arg_t intr_arg, /* arg to intr handler */ + xtalk_intr_setfunc_t setfunc, /* func to set intr hw */ + void *setfunc_arg) /* arg to setfunc */ +{ + return INTR_FUNC(intr_hdl, intr_connect) + (CAST_INTR(intr_hdl), intr_func, intr_arg, setfunc, setfunc_arg); +} + + +/* + * Disassociate handler with the specified interrupt. + */ +void +xtalk_intr_disconnect(xtalk_intr_t intr_hdl) +{ + INTR_FUNC(intr_hdl, intr_disconnect) + (CAST_INTR(intr_hdl)); +} + + +/* + * Return a hwgraph vertex that represents the CPU currently + * targeted by an interrupt. + */ +devfs_handle_t +xtalk_intr_cpu_get(xtalk_intr_t intr_hdl) +{ + return INTR_FUNC(intr_hdl, intr_cpu_get) + (CAST_INTR(intr_hdl)); +} + + +/* + * ===================================================================== + * ERROR MANAGEMENT + */ + +/* + * xtalk_error_handler: + * pass this error on to the handler registered + * at the specified xtalk connecdtion point, + * or complain about it here if there is no handler. + * + * 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 + * to the agent. + * + * If there is a switch, it will generally look at the + * widget number stashed in the ioerror structure; and, + * if the error came from some widget other than the + * switch, it will call back into xtalk_error_handler + * with the connection point of the offending port. + */ +int +xtalk_error_handler( + devfs_handle_t xconn, + int error_code, + ioerror_mode_t mode, + ioerror_t *ioerror) +{ + xwidget_info_t xwidget_info; + + xwidget_info = xwidget_info_get(xconn); + /* Make sure that xwidget_info is a valid pointer before derefencing it. + * We could come in here during very early initialization. + */ + if (xwidget_info && xwidget_info->w_efunc) + return xwidget_info->w_efunc + (xwidget_info->w_einfo, + error_code, mode, ioerror); + /* + * no error handler registered for + * the offending port. it's not clear + * what needs to be done, but reporting + * it would be a good thing, unless it + * is a mode that requires nothing. + */ + if ((mode == MODE_DEVPROBE) || (mode == MODE_DEVUSERERROR) || + (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", xconn); +#endif + ioerror_dump("xtalk", error_code, mode, ioerror); + + return IOERROR_UNHANDLED; +} + +int +xtalk_error_devenable(devfs_handle_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 + */ +void +xtalk_provider_startup(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_startup) + (xtalk_provider); +} + + +/* + * Shutdown a crosstalk provider + */ +void +xtalk_provider_shutdown(devfs_handle_t xtalk_provider) +{ + DEV_FUNC(xtalk_provider, provider_shutdown) + (xtalk_provider); +} + +/* + * Enable a device on a xtalk widget + */ +void +xtalk_widgetdev_enable(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_enable) (xconn_vhdl, devnum); +} + +/* + * Shutdown a device on a xtalk widget + */ +void +xtalk_widgetdev_shutdown(devfs_handle_t xconn_vhdl, int devnum) +{ + DEV_FUNC(xconn_vhdl, widgetdev_shutdown) (xconn_vhdl, devnum); +} + +int +xtalk_dma_enabled(devfs_handle_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 crosstalk interrupt interfaces ******/ +devfs_handle_t +xtalk_intr_dev_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_dev); +} + +xwidgetnum_t +xtalk_intr_target_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_target); +} + +xtalk_intr_vector_t +xtalk_intr_vector_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_vector); +} + +iopaddr_t +xtalk_intr_addr_get(struct xtalk_intr_s *xtalk_intr) +{ + return (xtalk_intr->xi_addr); +} + +void * +xtalk_intr_sfarg_get(xtalk_intr_t xtalk_intr) +{ + return (xtalk_intr->xi_sfarg); +} + +/****** Generic crosstalk pio interfaces ******/ +devfs_handle_t +xtalk_pio_dev_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_dev); +} + +xwidgetnum_t +xtalk_pio_target_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_target); +} + +iopaddr_t +xtalk_pio_xtalk_addr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_xtalk_addr); +} + +ulong +xtalk_pio_mapsz_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_mapsz); +} + +caddr_t +xtalk_pio_kvaddr_get(xtalk_piomap_t xtalk_piomap) +{ + return (xtalk_piomap->xp_kvaddr); +} + + +/****** Generic crosstalk dma interfaces ******/ +devfs_handle_t +xtalk_dma_dev_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_dev); +} + +xwidgetnum_t +xtalk_dma_target_get(xtalk_dmamap_t xtalk_dmamap) +{ + return (xtalk_dmamap->xd_target); +} + + +/****** Generic crosstalk widget information interfaces ******/ + +/* xwidget_info_chk: + * check to see if this vertex is a widget; + * if so, return its widget_info (if any). + * if not, return NULL. + */ +xwidget_info_t +xwidget_info_chk(devfs_handle_t xwidget) +{ + arbitrary_info_t ainfo = 0; + + hwgraph_info_get_LBL(xwidget, INFO_LBL_XWIDGET, &ainfo); + return (xwidget_info_t) ainfo; +} + + +xwidget_info_t +xwidget_info_get(devfs_handle_t xwidget) +{ + xwidget_info_t widget_info; + + widget_info = (xwidget_info_t) + hwgraph_fastinfo_get(xwidget); + +#ifdef LATER + if ((widget_info != NULL) && + (widget_info->w_fingerprint != widget_info_fingerprint)) +#ifdef SUPPORT_PRINTING_V_FORMAT + PRINT_PANIC("%v bad xwidget_info", xwidget); +#else + PRINT_PANIC("%x bad xwidget_info", xwidget); +#endif +#endif /* LATER */ + + return (widget_info); +} + +void +xwidget_info_set(devfs_handle_t xwidget, xwidget_info_t widget_info) +{ + if (widget_info != NULL) + widget_info->w_fingerprint = widget_info_fingerprint; + + hwgraph_fastinfo_set(xwidget, (arbitrary_info_t) widget_info); + + /* Also, mark this vertex as an xwidget, + * and use the widget_info, so xwidget_info_chk + * can work (and be fairly efficient). + */ + hwgraph_info_add_LBL(xwidget, INFO_LBL_XWIDGET, + (arbitrary_info_t) widget_info); +} + +devfs_handle_t +xwidget_info_dev_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_vertex); +} + +xwidgetnum_t +xwidget_info_id_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_id); +} + + +devfs_handle_t +xwidget_info_master_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_master); +} + +xwidgetnum_t +xwidget_info_masterid_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_masterid); +} + +xwidget_part_num_t +xwidget_info_part_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.part_num); +} + +xwidget_mfg_num_t +xwidget_info_mfg_num_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget_info"); + return (xwidget_info->w_hwid.mfg_num); +} +/* Extract the widget name from the widget information + * for the xtalk widget. + */ +char * +xwidget_info_name_get(xwidget_info_t xwidget_info) +{ + if (xwidget_info == NULL) + panic("null xwidget info"); + return(xwidget_info->w_name); +} +/****** Generic crosstalk initialization interfaces ******/ + +/* + * One-time initialization needed for systems that support crosstalk. + */ +void +xtalk_init(void) +{ + cdl_p cp; + +#if DEBUG && ATTACH_DEBUG + printf("xtalk_init\n"); +#endif + /* Allocate the registry. + * We might already have one. + * If we don't, go get one. + * MPness: someone might have + * set one up for us while we + * were not looking; use an atomic + * compare-and-swap to commit to + * using the new registry if and + * only if nobody else did first. + * If someone did get there first, + * toss the one we allocated back + * into the pool. + */ + if (xtalk_registry == NULL) { + cp = cdl_new(EDGE_LBL_XIO, "part", "mfgr"); + if (!compare_and_swap_ptr((void **) &xtalk_registry, NULL, (void *) cp)) { + cdl_del(cp); + } + } + ASSERT(xtalk_registry != NULL); +} + +/* + * Associate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_register(devfs_handle_t provider, xtalk_provider_t *xtalk_fns) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t) xtalk_fns); +} + +/* + * Disassociate a set of xtalk_provider functions with a vertex. + */ +void +xtalk_provider_unregister(devfs_handle_t provider) +{ + hwgraph_fastinfo_set(provider, (arbitrary_info_t)NULL); +} + +/* + * Obtain a pointer to the xtalk_provider functions for a specified Crosstalk + * provider. + */ +xtalk_provider_t * +xtalk_provider_fns_get(devfs_handle_t provider) +{ + return ((xtalk_provider_t *) hwgraph_fastinfo_get(provider)); +} + +/* + * Announce a driver for a particular crosstalk part. + * Returns 0 on success or -1 on failure. Failure occurs if the + * specified hardware already has a driver. + */ +/*ARGSUSED4 */ +int +xwidget_driver_register(xwidget_part_num_t part_num, + xwidget_mfg_num_t mfg_num, + char *driver_prefix, + unsigned flags) +{ + /* a driver's init routine could call + * xwidget_driver_register before the + * system calls xtalk_init; so, we + * make the call here. + */ + if (xtalk_registry == NULL) + xtalk_init(); + + return cdl_add_driver(xtalk_registry, + part_num, mfg_num, + driver_prefix, flags, NULL); +} + +/* + * Inform xtalk infrastructure that a driver is no longer available for + * handling any widgets. + */ +void +xwidget_driver_unregister(char *driver_prefix) +{ + /* before a driver calls unregister, + * it must have called registger; so we + * can assume we have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + cdl_del_driver(xtalk_registry, driver_prefix, NULL); +} + +/* + * Call some function with each vertex that + * might be one of this driver's attach points. + */ +void +xtalk_iterate(char *driver_prefix, + xtalk_iter_f *func) +{ + ASSERT(xtalk_registry != NULL); + + cdl_iterate(xtalk_registry, driver_prefix, (cdl_iter_f *)func); +} + +/* + * xwidget_register: + * Register a xtalk device (xwidget) by doing the following. + * -allocate and initialize xwidget_info data + * -allocate a hwgraph vertex with name based on widget number (id) + * -look up the widget's initialization function and call it, + * or remember the vertex for later initialization. + * + */ +int +xwidget_register(xwidget_hwid_t hwid, /* widget's hardware ID */ + devfs_handle_t widget, /* widget to initialize */ + xwidgetnum_t id, /* widget's target id (0..f) */ + devfs_handle_t master, /* widget's master vertex */ + xwidgetnum_t targetid, /* master's target id (9/a) */ + async_attach_t aa) +{ + xwidget_info_t widget_info; + char *s,devnm[MAXDEVNAME]; + + /* Allocate widget_info and associate it with widget vertex */ + NEW(widget_info); + + /* Initialize widget_info */ + widget_info->w_vertex = widget; + widget_info->w_id = id; + widget_info->w_master = master; + widget_info->w_masterid = targetid; + widget_info->w_hwid = *hwid; /* structure copy */ + widget_info->w_efunc = 0; + widget_info->w_einfo = 0; + /* + * get the name of this xwidget vertex and keep the info. + * This is needed during errors and interupts, but as + * long as we have it, we can use it elsewhere. + */ + s = dev_to_name(widget,devnm,MAXDEVNAME); + widget_info->w_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + strcpy(widget_info->w_name,s); + + xwidget_info_set(widget, widget_info); + + device_master_set(widget, master); + + /* All the driver init routines (including + * xtalk_init) are called before we get into + * attaching devices, so we can assume we + * have a registry here. + */ + ASSERT(xtalk_registry != NULL); + + /* + * Add pointer to async attach info -- tear down will be done when + * the particular descendant is done with the info. + */ + if (aa) + async_attach_add_info(widget, aa); + + return cdl_add_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, + widget, 0); +} + +/* + * xwidget_unregister : + * Unregister the xtalk device and detach all its hwgraph namespace. + */ +int +xwidget_unregister(devfs_handle_t widget) +{ + xwidget_info_t widget_info; + xwidget_hwid_t hwid; + + /* Make sure that we have valid widget information initialized */ + 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); + + cdl_del_connpt(xtalk_registry, hwid->part_num, hwid->mfg_num, + widget, 0); + + /* Clean out the xwidget information */ + (void)kfree(widget_info->w_name); + BZERO((void *)widget_info, sizeof(widget_info)); + DEL(widget_info); + + return(0); +} + +void +xwidget_error_register(devfs_handle_t xwidget, + error_handler_f *efunc, + error_handler_arg_t einfo) +{ + xwidget_info_t xwidget_info; + + xwidget_info = xwidget_info_get(xwidget); + ASSERT(xwidget_info != NULL); + xwidget_info->w_efunc = efunc; + xwidget_info->w_einfo = einfo; +} + +/* + * Issue a link reset to a widget. + */ +void +xwidget_reset(devfs_handle_t xwidget) +{ + xswitch_reset_link(xwidget); + +} + + +void +xwidget_gfx_reset(devfs_handle_t xwidget) +{ + xwidget_info_t info; + + xswitch_reset_link(xwidget); + info = xwidget_info_get(xwidget); +#ifdef LATER + ASSERT_ALWAYS(info != NULL); +#endif + + /* + * Enable this for other architectures once we add widget_reset to the + * xtalk provider interface. + */ + DEV_FUNC(xtalk_provider, widget_reset) + (xwidget_info_master_get(info), xwidget_info_id_get(info)); +} + +#define ANON_XWIDGET_NAME "No Name" /* Default Widget Name */ + +/* Get the canonical hwgraph name of xtalk widget */ +char * +xwidget_name_get(devfs_handle_t xwidget_vhdl) +{ + xwidget_info_t info; + + /* If we have a bogus widget handle then return + * a default anonymous widget name. + */ + if (xwidget_vhdl == GRAPH_VERTEX_NONE) + return(ANON_XWIDGET_NAME); + /* Read the widget name stored in the widget info + * for the widget setup during widget initialization. + */ + info = xwidget_info_get(xwidget_vhdl); + ASSERT(info != NULL); + return(xwidget_info_name_get(info)); +} diff -Nru a/arch/ia64/sn/kernel/iomv.c b/arch/ia64/sn/kernel/iomv.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/kernel/iomv.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#include +#include + +extern void * sn_io_addr(unsigned long port); /* defined in sn[12]/iomv.c */ + +/** + * sn_inb - read a byte from a port + * @port: port to read from + * + * Reads a byte from @port and returns it to the caller. + */ +unsigned int +sn_inb (unsigned long port) +{ + volatile unsigned char *addr = sn_io_addr(port); + unsigned char ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_inw - read a word from a port + * @port: port to read from + * + * Reads a word from @port and returns it to the caller. + */ +unsigned int +sn_inw (unsigned long port) +{ + volatile unsigned short *addr = sn_io_addr(port); + unsigned short ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_inl - read a word from a port + * @port: port to read from + * + * Reads a word from @port and returns it to the caller. + */ +unsigned int +sn_inl (unsigned long port) +{ + volatile unsigned int *addr = sn_io_addr(port); + unsigned int ret; + + ret = *addr; + __ia64_mf_a(); + return ret; +} + +/** + * sn_outb - write a byte to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outb (unsigned char val, unsigned long port) +{ + volatile unsigned char *addr = sn_io_addr(port); + + *addr = val; +} + +/** + * sn_outw - write a word to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outw (unsigned short val, unsigned long port) +{ + volatile unsigned short *addr = sn_io_addr(port); + + *addr = val; +} + +/** + * sn_outl - write a word to a port + * @port: port to write to + * @val: value to write + * + * Writes @val to @port. + */ +void +sn_outl (unsigned int val, unsigned long port) +{ + volatile unsigned int *addr = sn_io_addr(port); + + *addr = val; +} + +EXPORT_SYMBOL(sn_inb); +EXPORT_SYMBOL(sn_inw); +EXPORT_SYMBOL(sn_inl); +EXPORT_SYMBOL(sn_outb); +EXPORT_SYMBOL(sn_outw); +EXPORT_SYMBOL(sn_outl); diff -Nru a/arch/ia64/sn/kernel/mca.c b/arch/ia64/sn/kernel/mca.c --- a/arch/ia64/sn/kernel/mca.c Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/sn/kernel/mca.c Sat Mar 15 18:40:40 2003 @@ -40,7 +40,10 @@ #include #include #include +#include +#ifdef CONFIG_KDB #include +#endif #include #include @@ -53,7 +56,6 @@ #include #include -#include #include #include diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Sat Mar 15 18:40:40 2003 +++ b/arch/ia64/sn/kernel/setup.c Sat Mar 15 18:40:40 2003 @@ -267,7 +267,7 @@ /* PROM has wrong value on SN1 */ sn_rtc_cycles_per_second = 990177; #endif - sn_rtc_usec_per_cyc = ((1000000UL< + +#define ZEROVAL 0x3f // "zero" value for outstanding PIO requests +#define DEADLOCKBIT SH_PIO_WRITE_STATUS_0_WRITE_DEADLOCK_SHFT +#define WRITECOUNT SH_PIO_WRITE_STATUS_0_PENDING_WRITE_COUNT_SHFT +#define ALIAS_OFFSET (SH_PIO_WRITE_STATUS_0_ALIAS-SH_PIO_WRITE_STATUS_0) + + + .global sn2_ptc_deadlock_recovery_core + .proc sn2_ptc_deadlock_recovery_core + +sn2_ptc_deadlock_recovery_core: + .regstk 5,0,0,0 + + ptc0 = in0 + data0 = in1 + ptc1 = in2 + data1 = in3 + piowc = in4 + piowcphy = r30 + psrsave = r2 + zeroval = r3 + scr1 = r16 + scr2 = r17 + + + extr.u piowcphy=piowc,0,61;; // Convert piowc to uncached physical address + dep piowcphy=-1,piowcphy,63,1 + + mov zeroval=ZEROVAL // "zero" value for PIO write count + +1: + add scr2=ALIAS_OFFSET,piowc // Address of WRITE_STATUS alias register + mov scr1=7;; // Clear DEADLOCK, WRITE_ERROR, MULTI_WRITE_ERROR + st8.rel [scr2]=scr1;; + +5: ld8.acq scr1=[piowc];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b + + + + ////////////// BEGIN PHYSICAL MODE //////////////////// + mov psrsave=psr // Disable IC (no PMIs) + rsm psr.i | psr.dt | psr.ic;; + srlz.i;; + + st8.rel [ptc0]=data0 // Write PTC0 & wait for completion. + +5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b;; + + tbit.nz p8,p7=scr1,DEADLOCKBIT;;// Test for DEADLOCK + +(p7) st8.rel [ptc1]=data1;; // Now write PTC1. + +5: ld8.acq scr1=[piowcphy];; // Wait for PIOs to complete. + extr.u scr2=scr1,WRITECOUNT,7;;// PIO count + cmp.ne p6,p0=zeroval,scr2 +(p6) br.cond.sptk 5b + + tbit.nz p8,p0=scr1,DEADLOCKBIT;;// Test for DEADLOCK + + mov psr.l=psrsave;; // Reenable IC + srlz.i;; + ////////////// END PHYSICAL MODE //////////////////// + +(p8) br.cond.spnt 1b;; // Repeat if DEADLOCK occurred. + + br.ret.sptk rp + .endp sn2_ptc_deadlock_recovery_core diff -Nru a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,145 @@ +/* + * + * 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 + +#ifdef CONFIG_PROC_FS +#include +#include + + +static int partition_id_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + + return sprintf(page, "%d\n", sn_local_partid()); +} + +struct proc_dir_entry * sgi_proc_dir = NULL; + +void +register_sn_partition_id(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("partition_id", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = partition_id_read_proc; + entry->write_proc = NULL; + } +} + +static int +system_serial_number_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + return sprintf(page, "%s\n", sn_system_serial_number()); +} + +static int +licenseID_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + return sprintf(page, "0x%lx\n",sn_partition_serial_number_val()); +} + +void +register_sn_serial_numbers(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("system_serial_number", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = system_serial_number_read_proc; + entry->write_proc = NULL; + } + entry = create_proc_entry("licenseID", 0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = licenseID_read_proc; + entry->write_proc = NULL; + } +} + +// Disable forced interrupts, but leave the code in, just in case. +int sn_force_interrupt_flag = 0; + +static int +sn_force_interrupt_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) { + if (sn_force_interrupt_flag) { + return sprintf(page, "Force interrupt is enabled\n"); + } + return sprintf(page, "Force interrupt is disabled\n"); +} + +static int +sn_force_interrupt_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + if (*buffer == '0') { + sn_force_interrupt_flag = 0; + } else { + sn_force_interrupt_flag = 1; + } + return 1; +} + +void +register_sn_force_interrupt(void) { + struct proc_dir_entry *entry; + + if (!sgi_proc_dir) { + sgi_proc_dir = proc_mkdir("sgi_sn", 0); + } + entry = create_proc_entry("sn_force_interrupt",0444, sgi_proc_dir); + if (entry) { + entry->nlink = 1; + entry->data = 0; + entry->read_proc = sn_force_interrupt_read_proc; + entry->write_proc = sn_force_interrupt_write_proc; + } +} +void +register_sn_procfs(void) { + register_sn_partition_id(); + register_sn_serial_numbers(); + register_sn_force_interrupt(); +} + +#endif /* CONFIG_PROC_FS */ diff -Nru a/arch/ia64/tools/print_offsets.c b/arch/ia64/tools/print_offsets.c --- a/arch/ia64/tools/print_offsets.c Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/tools/print_offsets.c Sat Mar 15 18:40:44 2003 @@ -10,7 +10,7 @@ * gets translated into an assembly file which, in turn, is processed * by awk to generate offsets.h. So if you make any changes to this * file, be sure to verify that the awk procedure still works (see - * prin_offsets.awk). + * print_offsets.awk). */ #include @@ -170,6 +170,12 @@ /* for assembly files which can't include sched.h: */ { "IA64_CLONE_VFORK", CLONE_VFORK }, { "IA64_CLONE_VM", CLONE_VM }, + /* used by fsys_gettimeofday in arch/ia64/kernel/fsys.S */ + { "IA64_CPUINFO_ITM_DELTA_OFFSET", offsetof (struct cpuinfo_ia64, itm_delta) }, + { "IA64_CPUINFO_ITM_NEXT_OFFSET", offsetof (struct cpuinfo_ia64, itm_next) }, + { "IA64_CPUINFO_NSEC_PER_CYC_OFFSET", offsetof (struct cpuinfo_ia64, nsec_per_cyc) }, + { "IA64_TIMESPEC_TV_NSEC_OFFSET", offsetof (struct timespec, tv_nsec) }, + }; static const char *tabs = "\t\t\t\t\t\t\t\t\t\t"; diff -Nru a/arch/ia64/vmlinux.lds.S b/arch/ia64/vmlinux.lds.S --- a/arch/ia64/vmlinux.lds.S Sat Mar 15 18:40:44 2003 +++ b/arch/ia64/vmlinux.lds.S Sat Mar 15 18:40:44 2003 @@ -133,6 +133,10 @@ *(.initcall7.init) __initcall_end = .; } + __con_initcall_start = .; + .con_initcall.init : AT(ADDR(.con_initcall.init) - PAGE_OFFSET) + { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(PAGE_SIZE); __init_end = .; diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/m68k/Kconfig Sat Mar 15 18:40:42 2003 @@ -10,10 +10,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c --- a/arch/m68k/atari/stram.c Sat Mar 15 18:40:43 2003 +++ b/arch/m68k/atari/stram.c Sat Mar 15 18:40:43 2003 @@ -1052,8 +1052,7 @@ if (!stram_disk) return -ENOMEM; - if (register_blkdev( STRAM_MAJOR, "stram", &stram_fops)) { - printk(KERN_ERR "stram: Unable to get major %d\n", STRAM_MAJOR); + if (register_blkdev(STRAM_MAJOR, "stram")) { put_disk(stram_disk); return -ENXIO; } diff -Nru a/arch/m68k/vmlinux-std.lds b/arch/m68k/vmlinux-std.lds --- a/arch/m68k/vmlinux-std.lds Sat Mar 15 18:40:44 2003 +++ b/arch/m68k/vmlinux-std.lds Sat Mar 15 18:40:44 2003 @@ -60,6 +60,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/m68k/vmlinux-sun3.lds b/arch/m68k/vmlinux-sun3.lds --- a/arch/m68k/vmlinux-sun3.lds Sat Mar 15 18:40:39 2003 +++ b/arch/m68k/vmlinux-sun3.lds Sat Mar 15 18:40:39 2003 @@ -53,6 +53,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig --- a/arch/m68knommu/Kconfig Sat Mar 15 18:40:43 2003 +++ b/arch/m68knommu/Kconfig Sat Mar 15 18:40:43 2003 @@ -9,10 +9,6 @@ bool default n -config SWAP - bool - default n - config FPU bool default n @@ -106,7 +102,7 @@ really need to know, so you can select the AUTO option. On some boards you need to know the real clock frequency to determine other system timing (for example baud rate dividors, etc). Some processors - have an internal PLL and you can seletc a frequency to set that too. + have an internal PLL and you can select a frequency to run at. You need to know a little about the internals of your processor to set this. If in doubt choose the AUTO option. @@ -679,11 +675,12 @@ config MAGIC_SYSRQ bool "Magic SysRq key" help - Enables console device to interprent special characters as + Enables console device to interpret special characters as commands to dump state information. config HIGHPROFILE bool "Use fast second timer for profiling" + depends on COLDFIRE help Use a fast secondary clock to produce profiling information. @@ -703,7 +700,7 @@ bool "Disable BDM signals" depends on (EXPERIMENTAL && COLDFIRE) help - Disable the CPU's BDM signals. + Disable the ColdFire CPU's BDM signals. endmenu diff -Nru a/arch/m68knommu/kernel/comempci.c b/arch/m68knommu/kernel/comempci.c --- a/arch/m68knommu/kernel/comempci.c Sat Mar 15 18:40:42 2003 +++ b/arch/m68knommu/kernel/comempci.c Sat Mar 15 18:40:42 2003 @@ -3,7 +3,7 @@ /* * comemlite.c -- PCI access code for embedded CO-MEM Lite PCI controller. * - * (C) Copyright 1999-2002, Greg Ungerer (gerg@snapgear.com). + * (C) Copyright 1999-2003, Greg Ungerer (gerg@snapgear.com). * (C) Copyright 2000, Lineo (www.lineo.com) */ @@ -60,8 +60,8 @@ * really assign any resources we like to devices, as long as * they do not clash with other PCI devices. */ -unsigned int pci_iobase = 0x100; /* Arbitary start address */ -unsigned int pci_membase = 0x00010000; /* Arbitary start address */ +unsigned int pci_iobase = PCIBIOS_MIN_IO; /* Arbitary start address */ +unsigned int pci_membase = PCIBIOS_MIN_MEM; /* Arbitary start address */ #define PCI_MINIO 0x100 /* 256 byte minimum I/O */ #define PCI_MINMEM 0x00010000 /* 64k minimum chunk */ @@ -75,7 +75,7 @@ /*****************************************************************************/ -void pci_interrupt(int irq, void *id, struct pt_regs *fp); +void pci_interrupt(int irq, void *id, struct pt_regs *fp); /*****************************************************************************/ @@ -105,7 +105,7 @@ /*****************************************************************************/ -int pcibios_assignres(int slot) +int pcibios_assign_resource_slot(int slot) { volatile unsigned long *rp; volatile unsigned char *ip; @@ -113,7 +113,7 @@ int bar; #ifdef DEBUGPCI - printk("pcibios_assignres(slot=%x)\n", slot); + printk("pcibios_assign_resource_slot(slot=%x)\n", slot); #endif rp = (volatile unsigned long *) COMEM_BASE; @@ -224,7 +224,7 @@ /*****************************************************************************/ -int pcibios_enable(int slot) +int pcibios_enable_slot(int slot) { volatile unsigned long *rp; volatile unsigned short *wp; @@ -232,7 +232,7 @@ unsigned short cmd; #ifdef DEBUGPCI - printk("pcibios_enbale(slot=%x)\n", slot); + printk("pcibios_enbale_slot(slot=%x)\n", slot); #endif rp = (volatile unsigned long *) COMEM_BASE; @@ -256,7 +256,34 @@ /*****************************************************************************/ -unsigned long pcibios_init(unsigned long mem_start, unsigned long mem_end) +void pcibios_assign_resources(void) +{ + volatile unsigned long *rp; + unsigned long sel, id; + int slot; + + rp = (volatile unsigned long *) COMEM_BASE; + + /* + * Do a quick scan of the PCI bus and see what is here. + */ + for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) { + sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); + rp[LREG(COMEM_DAHBASE)] = sel; + rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ + id = rp[LREG(COMEM_PCIBUS)]; + if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) { + printk("PCI: slot=%d id=%08x\n", slot, (int) id); + pci_slotmask |= 0x1 << slot; + pcibios_assign_resource_slot(slot); + pcibios_enable_slot(slot); + } + } +} + +/*****************************************************************************/ + +int pcibios_init(void) { volatile unsigned long *rp; unsigned long sel, id; @@ -276,7 +303,7 @@ rp = (volatile unsigned long *) COMEM_BASE; if ((rp[LREG(COMEM_LBUSCFG)] & 0xff) != 0x50) { printk("PCI: no PCI bus present\n"); - return(mem_start); + return(0); } #ifdef COMEM_BRIDGEDEV @@ -291,34 +318,18 @@ id = rp[LREG(COMEM_PCIBUS)]; if ((id == 0) || ((id & 0xffff0000) == (sel & 0xffff0000))) { printk("PCI: no PCI bus bridge present\n"); - return(mem_start); + return(0); } printk("PCI: bridge device at slot=%d id=%08x\n", slot, (int) id); pci_slotmask |= 0x1 << slot; pci_shmemaddr = pci_membase; - pcibios_assignres(slot); - pcibios_enable(slot); + pcibios_assign_resource_slot(slot); + pcibios_enable_slot(slot); #endif pci_bus_is_present = 1; - /* - * Do a quick scan of the PCI bus and see what is here. - */ - for (slot = COMEM_MINDEV; (slot <= COMEM_MAXDEV); slot++) { - sel = COMEM_DA_CFGRD | COMEM_DA_ADDR(0x1 << (slot + 16)); - rp[LREG(COMEM_DAHBASE)] = sel; - rp[LREG(COMEM_PCIBUS)] = 0; /* Clear bus */ - id = rp[LREG(COMEM_PCIBUS)]; - if ((id != 0) && ((id & 0xffff0000) != (sel & 0xffff0000))) { - printk("PCI: slot=%d id=%08x\n", slot, (int) id); - pci_slotmask |= 0x1 << slot; - pcibios_assignres(slot); - pcibios_enable(slot); - } - } - /* Get PCI irq for local vectoring */ if (request_irq(COMEM_IRQ, pci_interrupt, 0, "PCI bridge", NULL)) { printk("PCI: failed to acquire interrupt %d\n", COMEM_IRQ); @@ -326,18 +337,55 @@ mcf_autovector(COMEM_IRQ); } - return(mem_start); + pcibios_assign_resources(); + + return(0); } /*****************************************************************************/ -unsigned long pcibios_fixup(unsigned long mem_start, unsigned long mem_end) +char *pcibios_setup(char *option) +{ + /* Nothing for us to handle. */ + return(option); +} +/*****************************************************************************/ + +struct pci_fixup pcibios_fixups[] = { { 0 } }; + +void pcibios_fixup_bus(struct pci_bus *b) { - return(mem_start); } /*****************************************************************************/ +void pcibios_align_resource(void *data, struct resource *res, unsigned long size, unsigned long align) +{ +} + +/*****************************************************************************/ + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + int slot; + + slot = PCI_SLOT(dev->devfn); + if ((dev->bus == 0) && (pci_slotmask & (1 << slot))) + pcibios_enable_slot(slot); + return(0); +} + +/*****************************************************************************/ + +void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *r, int resource) +{ + printk("%s(%d): no support for changing PCI resources...\n", + __FILE__, __LINE__); +} + + +/*****************************************************************************/ + /* * Local routines to interrcept the standard I/O and vector handling * code. Don't include this 'till now - initialization code above needs @@ -918,6 +966,26 @@ } printk("\n"); #endif +} + +/*****************************************************************************/ + +void *pci_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_addr) +{ + void *mp; + if ((mp = pci_bmalloc(size)) != NULL) { + dma_addr = mp - (COMEM_BASE + COMEM_SHMEM); + return(mp); + } + *dma_addr = (dma_addr_t) NULL; + return(NULL); +} + +/*****************************************************************************/ + +void pci_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, dma_addr_t dma_addr) +{ + pci_bmfree(cpu_addr, size); } /*****************************************************************************/ diff -Nru a/arch/m68knommu/kernel/entry.S b/arch/m68knommu/kernel/entry.S --- a/arch/m68knommu/kernel/entry.S Sat Mar 15 18:40:42 2003 +++ b/arch/m68knommu/kernel/entry.S Sat Mar 15 18:40:42 2003 @@ -84,6 +84,9 @@ jmp schedule ENTRY(ret_from_fork) + movel %d1,%sp@- + jsr schedule_tail + addql #4,%sp jra ret_from_exception ENTRY(sys_fork) diff -Nru a/arch/m68knommu/platform/5206/config.c b/arch/m68knommu/platform/5206/config.c --- a/arch/m68knommu/platform/5206/config.c Sat Mar 15 18:40:42 2003 +++ b/arch/m68knommu/platform/5206/config.c Sat Mar 15 18:40:42 2003 @@ -25,6 +25,14 @@ /***************************************************************************/ +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +/***************************************************************************/ + /* * DMA channel base address table. */ @@ -33,47 +41,8 @@ MCF_MBAR + MCFDMA_BASE1, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - -/***************************************************************************/ - -void coldfire_tick(void) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - -/***************************************************************************/ - -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - /* Set up TIMER 1 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); - - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; - request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); -} - /***************************************************************************/ -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { volatile unsigned char *mbar; @@ -91,65 +60,35 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) -{ - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -void coldfire_trap_init(void) +void mcf_settimericr(unsigned int timer, unsigned int level) { - int i; - -#ifndef ENABLE_dBUG - mcf_setimr(MCFSIM_IMR_MASKALL); -#endif + volatile unsigned char *icrp; + unsigned int icr, imr; - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif - - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif - - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; + if (timer <= 2) { + switch (timer) { + case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; + default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; + mcf_setimr(mcf_getimr() & ~imr); + } } /***************************************************************************/ void config_BSP(char *commandp, int size) { + mcf_setimr(MCFSIM_IMR_MASKALL); memset(commandp, 0, size); + mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; } /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5206e/config.c b/arch/m68knommu/platform/5206e/config.c --- a/arch/m68knommu/platform/5206e/config.c Sat Mar 15 18:40:41 2003 +++ b/arch/m68knommu/platform/5206e/config.c Sat Mar 15 18:40:41 2003 @@ -20,17 +20,16 @@ #include #include #include - -#ifdef CONFIG_NETtel #include #include -#endif /***************************************************************************/ -#ifdef CONFIG_NETtel -void reset_setupbutton(void); -#endif +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); /***************************************************************************/ @@ -42,53 +41,8 @@ MCF_MBAR + MCFDMA_BASE1, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - -/***************************************************************************/ - -void coldfire_tick(void) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - /***************************************************************************/ -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - /* Set up TIMER 1 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); - -#ifdef CONFIG_NETtel - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; - request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); - reset_setupbutton(); -#else - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; - request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); -#endif - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); -} - -/***************************************************************************/ - -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { volatile unsigned char *mbar; @@ -106,117 +60,29 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) -{ - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -void coldfire_trap_init(void) +void mcf_settimericr(unsigned int timer, unsigned int level) { - int i; -#ifdef MCF_MEMORY_PROTECT - extern unsigned long _end; - extern unsigned long memory_end; -#endif - -#ifndef ENABLE_dBUG - mcf_setimr(MCFSIM_IMR_MASKALL); -#endif - - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif - - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif - - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; -} - -/***************************************************************************/ + volatile unsigned char *icrp; + unsigned int icr, imr; -#ifdef CONFIG_NETtel - -/* - * Routines to support the NETtel software reset button. - */ -void reset_button(int irq, void *dev_id, struct pt_regs *regs) -{ - extern void flash_eraseconfig(void); - static int inbutton = 0; - - /* - * IRQ7 is not maskable by the CPU core. It is possible - * that switch bounce may get us back here before we have - * really serviced the interrupt. - */ - if (inbutton) - return; - inbutton = 1; - /* Disable interrupt at SIM - best we can do... */ - mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7); - /* Try and de-bounce the switch a little... */ - udelay(10000); - - flash_eraseconfig(); - - /* Don't leave here 'till button is no longer pushed! */ - for (;;) { - if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0) - break; + if (timer <= 2) { + switch (timer) { + case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; + default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; + mcf_setimr(mcf_getimr() & ~imr); } - - HARD_RESET_NOW(); - /* Should never get here... */ - - inbutton = 0; - /* Interrupt service done, enable it again */ - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); } /***************************************************************************/ -void reset_setupbutton(void) -{ - mcf_autovector(31); - request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), - "Reset Button", NULL); -} - -#endif /* CONFIG_NETtel */ - -/***************************************************************************/ - void config_BSP(char *commandp, int size) { + mcf_setimr(MCFSIM_IMR_MASKALL); + #ifdef CONFIG_NETtel /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); @@ -227,7 +93,9 @@ mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; } /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5249/config.c b/arch/m68knommu/platform/5249/config.c --- a/arch/m68knommu/platform/5249/config.c Sat Mar 15 18:40:42 2003 +++ b/arch/m68knommu/platform/5249/config.c Sat Mar 15 18:40:42 2003 @@ -25,7 +25,11 @@ /***************************************************************************/ -void coldfire_profile_init(void); +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); /***************************************************************************/ @@ -39,105 +43,8 @@ MCF_MBAR + MCFDMA_BASE3, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - -/***************************************************************************/ - -void coldfire_tick(void) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - -/***************************************************************************/ - -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - /* Set up TIMER 1 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; - request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); - -#ifdef CONFIG_HIGHPROFILE - coldfire_profile_init(); -#endif - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); -} - -/***************************************************************************/ -#ifdef CONFIG_HIGHPROFILE /***************************************************************************/ -#define PROFILEHZ 1013 - -/* - * Use the other timer to provide high accuracy profiling info. - */ - -void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer2 */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long ip = instruction_pointer(regs); - ip -= (unsigned long) &_stext; - ip >>= prof_shift; - if (ip < prof_len) - prof_buffer[ip]++; - } - } -} - -void coldfire_profile_init(void) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); - - /* Set up TIMER 2 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); - - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; - request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), - "Profile Timer", NULL); - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); -} - -/***************************************************************************/ -#endif /* CONFIG_HIGHPROFILE */ -/***************************************************************************/ - -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { volatile unsigned char *mbar; @@ -152,78 +59,35 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) -{ - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -void __init coldfire_trap_init(void) +void mcf_settimericr(unsigned int timer, unsigned int level) { - int i; + volatile unsigned char *icrp; + unsigned int icr, imr; -#ifndef ENABLE_dBUG - mcf_setimr(MCFSIM_IMR_MASKALL); -#endif - - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif - - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif - - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; + if (timer <= 2) { + switch (timer) { + case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; + default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; + mcf_setimr(mcf_getimr() & ~imr); + } } /***************************************************************************/ void config_BSP(char *commandp, int size) { + mcf_setimr(MCFSIM_IMR_MASKALL); memset(commandp, 0, size); mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; } -/***************************************************************************/ -#ifdef TRAP_DBG_INTERRUPT - -asmlinkage void dbginterrupt_c(struct frame *fp) -{ - extern void dump(struct pt_regs *fp); - printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); - dump((struct pt_regs *) fp); - asm("halt"); -} - -#endif /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5272/config.c b/arch/m68knommu/platform/5272/config.c --- a/arch/m68knommu/platform/5272/config.c Sat Mar 15 18:40:41 2003 +++ b/arch/m68knommu/platform/5272/config.c Sat Mar 15 18:40:41 2003 @@ -26,7 +26,15 @@ /***************************************************************************/ -void reset_setupbutton(void); +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +extern unsigned int mcf_timervector; +extern unsigned int mcf_profilevector; +extern unsigned int mcf_timerlevel; /***************************************************************************/ @@ -37,50 +45,21 @@ MCF_MBAR + MCFDMA_BASE0, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - /***************************************************************************/ -void coldfire_tick(void) +void mcf_disableall(void) { - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE4); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - -/***************************************************************************/ - -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; volatile unsigned long *icrp; - /* Set up TIMER 4 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE4); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = 0x0000000d; /* TMR4 with priority 5 */ - request_irq(72, handler, SA_INTERRUPT, "ColdFire Timer", NULL); - -#ifdef CONFIG_RESETSWITCH - /* This is not really the right place to do this... */ - reset_setupbutton(); -#endif + icrp[0] = 0x88888888; + icrp[1] = 0x88888888; + icrp[2] = 0x88888888; + icrp[3] = 0x88888888; } /***************************************************************************/ -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { /* Everything is auto-vectored on the 5272 */ @@ -88,68 +67,20 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) +void mcf_settimericr(int timer, int level) { - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -void coldfire_trap_init(void) -{ - int i; - -#ifndef ENABLE_dBUG - volatile unsigned long *icrp; - - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - icrp[0] = 0x88888888; - icrp[1] = 0x88888888; - icrp[2] = 0x88888888; - icrp[3] = 0x88888888; -#endif - - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif + volatile unsigned long *icrp; + unsigned int icr; - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif - - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; -} - -/***************************************************************************/ + switch (timer) { + case 2: icr = MCFSIM_ICR2; break; + case 3: icr = MCFSIM_ICR3; break; + case 4: icr = MCFSIM_ICR4; break; + default: icr = MCFSIM_ICR1; break; + } -void coldfire_reset(void) -{ - HARD_RESET_NOW(); + icrp = (volatile unsigned long *) (MCF_MBAR + icr); + *icrp = (0x8 | level) << ((4 - timer) * 4); } /***************************************************************************/ @@ -164,8 +95,9 @@ *pivrp = 0x40; #endif -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + mcf_disableall(); + +#if defined(CONFIG_NETtel) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); commandp[size-1] = 0; @@ -177,71 +109,13 @@ memset(commandp, 0, size); #endif + mcf_timervector = 69; + mcf_profilevector = 70; mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; mach_reset = coldfire_reset; } -/***************************************************************************/ -#ifdef CONFIG_RESETSWITCH -/***************************************************************************/ - -/* - * Routines to support the NETtel software reset button. - */ -void reset_button(int irq, void *dev_id, struct pt_regs *regs) -{ - volatile unsigned long *icrp, *isrp; - extern void flash_eraseconfig(void); - static int inbutton = 0; - - /* - * IRQ7 is not maskable by the CPU core. It is possible - * that switch bounce mey get us back here before we have - * really serviced the interrupt. - */ - if (inbutton) - return; - inbutton = 1; - - /* Disable interrupt at SIM - best we can do... */ - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x07777777) | 0x80000000; - - /* Try and de-bounce the switch a little... */ - udelay(10000); - - flash_eraseconfig(); - - /* Don't leave here 'till button is no longer pushed! */ - isrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ISR); - for (;;) { - if (*isrp & 0x80000000) - break; - } - - HARD_RESET_NOW(); - /* Should never get here... */ - - inbutton = 0; - /* Interrupt service done, acknowledge it */ - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x07777777) | 0xf0000000; -} - -/***************************************************************************/ - -void reset_setupbutton(void) -{ - volatile unsigned long *icrp; - - icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1); - *icrp = (*icrp & 0x07777777) | 0xf0000000; - request_irq(65, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), - "Reset Button", NULL); -} - -/***************************************************************************/ -#endif /* CONFIG_RESETSWITCH */ /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5307/Makefile b/arch/m68knommu/platform/5307/Makefile --- a/arch/m68knommu/platform/5307/Makefile Sat Mar 15 18:40:44 2003 +++ b/arch/m68knommu/platform/5307/Makefile Sat Mar 15 18:40:44 2003 @@ -16,7 +16,7 @@ AFLAGS += -DDEBUGGER_COMPATIBLE_CACHE=1 endif -obj-$(CONFIG_COLDFIRE) += entry.o +obj-$(CONFIG_COLDFIRE) += entry.o timers.o vectors.o obj-$(CONFIG_M5307) += config.o ifeq ($(CONFIG_M5307),y) diff -Nru a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c --- a/arch/m68knommu/platform/5307/config.c Sat Mar 15 18:40:40 2003 +++ b/arch/m68knommu/platform/5307/config.c Sat Mar 15 18:40:40 2003 @@ -23,17 +23,19 @@ #include #include #include - -#if defined(CONFIG_eLIA) -#include -#endif - #include /***************************************************************************/ -void reset_setupbutton(void); -void coldfire_profile_init(void); +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +extern unsigned int mcf_timervector; +extern unsigned int mcf_profilevector; +extern unsigned int mcf_timerlevel; /***************************************************************************/ @@ -47,118 +49,8 @@ MCF_MBAR + MCFDMA_BASE3, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - /***************************************************************************/ -void coldfire_tick(void) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - -/***************************************************************************/ - -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - /* Set up TIMER 1 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); - -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ - defined(CONFIG_CLEOPATRA) - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; - request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); -#else - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; - request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); -#endif - -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) - /* This is not really the right place to do this... */ - reset_setupbutton(); -#endif -#ifdef CONFIG_HIGHPROFILE - coldfire_profile_init(); -#endif - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); -} - -/***************************************************************************/ -#ifdef CONFIG_HIGHPROFILE -/***************************************************************************/ - -#define PROFILEHZ 1013 - -/* - * Use the other timer to provide high accuracy profiling info. - */ - -void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer2 */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long ip = instruction_pointer(regs); - ip -= (unsigned long) &_stext; - ip >>= prof_shift; - if (ip < prof_len) - prof_buffer[ip]++; - } - } -} - -void coldfire_profile_init(void) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); - - /* Set up TIMER 2 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); - - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; - request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), - "Profile Timer", NULL); - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); -} - -/***************************************************************************/ -#endif /* CONFIG_HIGHPROFILE */ -/***************************************************************************/ - -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { volatile unsigned char *mbar; @@ -173,165 +65,57 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) -{ - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -#ifdef TRAP_DBG_INTERRUPT -asmlinkage void dbginterrupt(void); -#endif - -void __init coldfire_trap_init(void) -{ - int i; - -#ifndef ENABLE_dBUG - mcf_setimr(MCFSIM_IMR_MASKALL); -#endif - - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif -#ifdef TRAP_DBG_INTERRUPT - _ramvec[12] = dbginterrupt; -#endif - - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif - - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; -#ifdef MCF_BDM_DISABLE - /* Disable the BDM clocking. This also turns off most of the rest of - * the BDM device. This is good for EMC reasons. This option is not - * incompatible with the memory protection option. - */ - wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); -#endif - -} - -/***************************************************************************/ - -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) - -/* - * Routines to support the NETtel software reset button. - */ -void reset_button(int irq, void *dev_id, struct pt_regs *regs) +void mcf_settimericr(unsigned int timer, unsigned int level) { - extern void flash_eraseconfig(void); - static int inbutton = 0; + volatile unsigned char *icrp; + unsigned int icr, imr; - /* - * IRQ7 is not maskable by the CPU core. It is possible - * that switch bounce mey get us back here before we have - * really serviced the interrupt. - */ - if (inbutton) - return; - inbutton = 1; - /* Disable interrupt at SIM - best we can do... */ - mcf_setimr(mcf_getimr() | MCFSIM_IMR_EINT7); - /* Try and de-bounce the switch a little... */ - udelay(10000); - - flash_eraseconfig(); - - /* Don't leave here 'till button is no longer pushed! */ - for (;;) { - if ((mcf_getipr() & MCFSIM_IMR_EINT7) == 0) - break; + if (timer <= 2) { + switch (timer) { + case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; + default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; + mcf_setimr(mcf_getimr() & ~imr); } - - HARD_RESET_NOW(); - /* Should never get here... */ - - inbutton = 0; - /* Interrupt service done, enable it again */ - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); -} - -/***************************************************************************/ - -void reset_setupbutton(void) -{ - volatile unsigned char *mbar; - - mbar = (volatile unsigned char *) MCF_MBAR; - *(mbar + MCFSIM_AVR) |= MCFSIM_IMR_EINT7; - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_EINT7); - request_irq(31, reset_button, (SA_INTERRUPT | IRQ_FLG_FAST), - "Reset Button", NULL); -} - -#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */ - -/***************************************************************************/ - -void coldfire_reset(void) -{ - HARD_RESET_NOW(); } /***************************************************************************/ void config_BSP(char *commandp, int size) { + mcf_setimr(MCFSIM_IMR_MASKALL); + #if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ + defined(CONFIG_CLEOPATRA) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); commandp[size-1] = 0; + /* Different timer setup - to prevent device clash */ + mcf_timervector = 30; + mcf_profilevector = 31; + mcf_timerlevel = 6; #else memset(commandp, 0, size); -#endif /* CONFIG_NETtel || CONFIG_eLIA || CONFIG_DISKtel || CONFIG_SECUREEDGEMP3 */ +#endif mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; mach_reset = coldfire_reset; -} -/***************************************************************************/ -#ifdef TRAP_DBG_INTERRUPT - -asmlinkage void dbginterrupt_c(struct frame *fp) -{ - extern void dump(struct pt_regs *fp); - printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); - dump((struct pt_regs *) fp); - asm("halt"); +#ifdef MCF_BDM_DISABLE + /* + * Disable the BDM clocking. This also turns off most of the rest of + * the BDM device. This is good for EMC reasons. This option is not + * incompatible with the memory protection option. + */ + wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK); +#endif } -#endif /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5307/timers.c b/arch/m68knommu/platform/5307/timers.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/m68knommu/platform/5307/timers.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,127 @@ +/***************************************************************************/ + +/* + * linux/arch/m68knommu/platform/5307/timers.c + * + * Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com) + */ + +/***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************/ + +/* + * Default the timer and vector to use for ColdFire. Some ColdFire + * CPU's and some boards may want different. Their sub-architecture + * startup code (in config.c) can change these if they want. + */ +unsigned int mcf_timervector = 29; +unsigned int mcf_profilevector = 31; +unsigned int mcf_timerlevel = 5; + +static volatile struct mcftimer *mcf_timerp; + +/***************************************************************************/ + +void coldfire_tick(void) +{ + /* Reset the ColdFire timer */ + mcf_timerp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; +} + +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) +{ + /* Set up an internal TIMER as poll clock */ + mcf_timerp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE1); + mcf_timerp->tmr = MCFTIMER_TMR_DISABLE; + + mcf_timerp->trr = (unsigned short) ((MCF_BUSCLK / 16) / HZ); + mcf_timerp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + request_irq(mcf_timervector, handler, SA_INTERRUPT, "timer", NULL); + mcf_settimericr(1, mcf_timerlevel); + +#ifdef CONFIG_HIGHPROFILE + coldfire_profile_init(); +#endif +} + +/***************************************************************************/ + +unsigned long coldfire_timer_offset(void) +{ + unsigned long trr, tcn; + + /* Get the values as longs for accurate calculation. */ + tcn = mcf_timerp->tcn; + trr = mcf_timerp->trr; + return((tcn * (1000000 / HZ)) / trr); +} + +/***************************************************************************/ +#ifdef CONFIG_HIGHPROFILE +/***************************************************************************/ + +/* + * Choose a reasonably fast profile timer. Make it an odd value to + * try and get good coverage of kernal operations. + */ +#define PROFILEHZ 1013 + +static volatile struct mcftimer *mcf_proftp; + +/* + * Use the other timer to provide high accuracy profiling info. + */ + +void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) +{ + /* Reset ColdFire timer2 */ + mcf_proftp->ter = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; + + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long ip = instruction_pointer(regs); + ip -= (unsigned long) &_stext; + ip >>= prof_shift; + if (ip < prof_len) + prof_buffer[ip]++; + } + } +} + +void coldfire_profile_init(void) +{ + printk("PROFILE: lodging TIMER2 @ %dHz as profile timer\n", PROFILEHZ); + + /* Set up TIMER 2 as high speed profile clock */ + mcf_proftp = (volatile struct mcftimer *) (MCF_MBAR + MCFTIMER_BASE2); + mcf_proftp->tmr = MCFTIMER_TMR_DISABLE; + + mcf_proftp->trr = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); + mcf_proftp->tmr = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | + MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; + + request_irq(mcf_profilevector, coldfire_profile_tick, + (SA_INTERRUPT | IRQ_FLG_FAST), "profile timer", NULL); + mcf_settimericr(2, 7); +} + +/***************************************************************************/ +#endif /* CONFIG_HIGHPROFILE */ +/***************************************************************************/ diff -Nru a/arch/m68knommu/platform/5407/config.c b/arch/m68knommu/platform/5407/config.c --- a/arch/m68knommu/platform/5407/config.c Sat Mar 15 18:40:43 2003 +++ b/arch/m68knommu/platform/5407/config.c Sat Mar 15 18:40:43 2003 @@ -26,7 +26,15 @@ /***************************************************************************/ -void coldfire_profile_init(void); +void coldfire_tick(void); +void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)); +unsigned long coldfire_timer_offset(void); +void coldfire_trap_init(void); +void coldfire_reset(void); + +extern unsigned int mcf_timervector; +extern unsigned int mcf_profilevector; +extern unsigned int mcf_timerlevel; /***************************************************************************/ @@ -40,111 +48,8 @@ MCF_MBAR + MCFDMA_BASE3, }; -unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS]; - -/***************************************************************************/ - -void coldfire_tick(void) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; -} - -/***************************************************************************/ - -void coldfire_timer_init(void (*handler)(int, void *, struct pt_regs *)) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - /* Set up TIMER 1 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE1); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / HZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER1ICR); - -#if defined(CONFIG_CLEOPATRA) - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3; - request_irq(30, handler, SA_INTERRUPT, "ColdFire Timer", NULL); -#else - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL5 | MCFSIM_ICR_PRI3; - request_irq(29, handler, SA_INTERRUPT, "ColdFire Timer", NULL); -#endif - -#ifdef CONFIG_HIGHPROFILE - coldfire_profile_init(); -#endif - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER1); -} - -/***************************************************************************/ -#ifdef CONFIG_HIGHPROFILE -/***************************************************************************/ - -#define PROFILEHZ 1013 - -/* - * Use the other timer to provide high accuracy profiling info. - */ - -void coldfire_profile_tick(int irq, void *dummy, struct pt_regs *regs) -{ - volatile unsigned char *timerp; - - /* Reset the ColdFire timer2 */ - timerp = (volatile unsigned char *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TER] = MCFTIMER_TER_CAP | MCFTIMER_TER_REF; - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long ip = instruction_pointer(regs); - ip -= (unsigned long) &_stext; - ip >>= prof_shift; - if (ip < prof_len) - prof_buffer[ip]++; - } - } -} - -void coldfire_profile_init(void) -{ - volatile unsigned short *timerp; - volatile unsigned char *icrp; - - printk("PROFILE: lodging timer2=%d as profile timer\n", PROFILEHZ); - - /* Set up TIMER 2 as poll clock */ - timerp = (volatile unsigned short *) (MCF_MBAR + MCFTIMER_BASE2); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_DISABLE; - - timerp[MCFTIMER_TRR] = (unsigned short) ((MCF_CLK / 16) / PROFILEHZ); - timerp[MCFTIMER_TMR] = MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 | - MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE; - - icrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_TIMER2ICR); - - *icrp = MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3; - request_irq(31, coldfire_profile_tick, (SA_INTERRUPT | IRQ_FLG_FAST), - "Profile Timer", NULL); - mcf_setimr(mcf_getimr() & ~MCFSIM_IMR_TIMER2); -} - -/***************************************************************************/ -#endif /* CONFIG_HIGHPROFILE */ /***************************************************************************/ -/* - * Program the vector to be an auto-vectored. - */ - void mcf_autovector(unsigned int vec) { volatile unsigned char *mbar; @@ -159,78 +64,42 @@ /***************************************************************************/ -extern e_vector *_ramvec; - -void set_evector(int vecnum, void (*handler)(void)) +void mcf_settimericr(unsigned int timer, unsigned int level) { - if (vecnum >= 0 && vecnum <= 255) - _ramvec[vecnum] = handler; -} - -/***************************************************************************/ - -/* assembler routines */ -asmlinkage void buserr(void); -asmlinkage void trap(void); -asmlinkage void system_call(void); -asmlinkage void inthandler(void); - -void __init coldfire_trap_init(void) -{ - int i; - -#ifndef ENABLE_dBUG - mcf_setimr(MCFSIM_IMR_MASKALL); -#endif - - /* - * There is a common trap handler and common interrupt - * handler that handle almost every vector. We treat - * the system call and bus error special, they get their - * own first level handlers. - */ -#ifndef ENABLE_dBUG - for (i = 3; (i <= 23); i++) - _ramvec[i] = trap; - for (i = 33; (i <= 63); i++) - _ramvec[i] = trap; -#endif - - for (i = 24; (i <= 30); i++) - _ramvec[i] = inthandler; -#ifndef ENABLE_dBUG - _ramvec[31] = inthandler; // Disables the IRQ7 button -#endif + volatile unsigned char *icrp; + unsigned int icr, imr; - for (i = 64; (i < 255); i++) - _ramvec[i] = inthandler; - _ramvec[255] = 0; - - _ramvec[2] = buserr; - _ramvec[32] = system_call; + if (timer <= 2) { + switch (timer) { + case 2: icr = MCFSIM_TIMER2ICR; imr = MCFSIM_IMR_TIMER2; break; + default: icr = MCFSIM_TIMER1ICR; imr = MCFSIM_IMR_TIMER1; break; + } + + icrp = (volatile unsigned char *) (MCF_MBAR + icr); + *icrp = MCFSIM_ICR_AUTOVEC | (level << 2) | MCFSIM_ICR_PRI3; + mcf_setimr(mcf_getimr() & ~imr); + } } /***************************************************************************/ void config_BSP(char *commandp, int size) { + mcf_setimr(MCFSIM_IMR_MASKALL); memset(commandp, 0, size); +#if defined(CONFIG_CLEOPATRA) + /* Different timer setup - to prevent device clash */ + mcf_timervector = 30; + mcf_profilevector = 31; + mcf_timerlevel = 6; +#endif + mach_sched_init = coldfire_timer_init; mach_tick = coldfire_tick; + mach_gettimeoffset = coldfire_timer_offset; mach_trap_init = coldfire_trap_init; + mach_reset = coldfire_reset; } -/***************************************************************************/ -#ifdef TRAP_DBG_INTERRUPT - -asmlinkage void dbginterrupt_c(struct frame *fp) -{ - extern void dump(struct pt_regs *fp); - printk("%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__); - dump((struct pt_regs *) fp); - asm("halt"); -} - -#endif /***************************************************************************/ diff -Nru a/arch/m68knommu/platform/68328/entry.S b/arch/m68knommu/platform/68328/entry.S --- a/arch/m68knommu/platform/68328/entry.S Sat Mar 15 18:40:39 2003 +++ b/arch/m68knommu/platform/68328/entry.S Sat Mar 15 18:40:39 2003 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/m68knommu/platform/68328/ints.c b/arch/m68knommu/platform/68328/ints.c --- a/arch/m68knommu/platform/68328/ints.c Sat Mar 15 18:40:41 2003 +++ b/arch/m68knommu/platform/68328/ints.c Sat Mar 15 18:40:41 2003 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/m68knommu/platform/68360/commproc.c b/arch/m68knommu/platform/68360/commproc.c --- a/arch/m68knommu/platform/68360/commproc.c Sat Mar 15 18:40:44 2003 +++ b/arch/m68knommu/platform/68360/commproc.c Sat Mar 15 18:40:44 2003 @@ -71,7 +71,7 @@ static void cpm_error_interrupt(void *); /* prototypes: */ -void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id); +void cpm_install_handler(int vec, void (*handler)(), void *dev_id); void m360_cpm_reset(void); @@ -207,7 +207,7 @@ /* Install a CPM interrupt handler. */ void -cpm_install_handler(int vec, void (*handler)(void *), void *dev_id) +cpm_install_handler(int vec, void (*handler)(), void *dev_id) { request_irq(vec, handler, IRQ_FLG_LOCK, "timer", dev_id); diff -Nru a/arch/m68knommu/platform/68360/entry.S b/arch/m68knommu/platform/68360/entry.S --- a/arch/m68knommu/platform/68360/entry.S Sat Mar 15 18:40:43 2003 +++ b/arch/m68knommu/platform/68360/entry.S Sat Mar 15 18:40:43 2003 @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c --- a/arch/m68knommu/platform/68360/ints.c Sat Mar 15 18:40:39 2003 +++ b/arch/m68knommu/platform/68360/ints.c Sat Mar 15 18:40:39 2003 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/m68knommu/platform/68VZ328/Makefile b/arch/m68knommu/platform/68VZ328/Makefile --- a/arch/m68knommu/platform/68VZ328/Makefile Sat Mar 15 18:40:39 2003 +++ b/arch/m68knommu/platform/68VZ328/Makefile Sat Mar 15 18:40:39 2003 @@ -2,11 +2,5 @@ # Makefile for arch/m68knommu/platform/68VZ328. # -obj-y := $(BOARD)/config.o - -EXTRA_TARGETS := $(BOARD)/bootlogo.rh $(BOARD)/crt0_$(MODEL).o - -$(obj)/$(BOARD)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h - perl $(src)/../68328/bootlogo.pl < $(src)/../68EZ328/bootlogo.h \ - > $(obj)/$(BOARD)/bootlogo.rh +obj-y := $(BOARD)/ diff -Nru a/arch/m68knommu/platform/68VZ328/de2/Makefile b/arch/m68knommu/platform/68VZ328/de2/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/m68knommu/platform/68VZ328/de2/Makefile Sat Mar 15 18:40:45 2003 @@ -0,0 +1,12 @@ +# +# Makefile for arch/m68knommu/platform/68VZ328/de2. +# + +obj-y := config.o + +EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o + +$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h + perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \ + > $(obj)/bootlogo.rh + diff -Nru a/arch/m68knommu/platform/68VZ328/de2/config.c b/arch/m68knommu/platform/68VZ328/de2/config.c --- a/arch/m68knommu/platform/68VZ328/de2/config.c Sat Mar 15 18:40:40 2003 +++ b/arch/m68knommu/platform/68VZ328/de2/config.c Sat Mar 15 18:40:40 2003 @@ -147,5 +147,5 @@ mach_reset = dragen2_reset; mach_gettod = dragen2_gettod; - config_M68VZ328_irq(); + config_M68328_irq(); } diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/Makefile b/arch/m68knommu/platform/68VZ328/ucdimm/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/m68knommu/platform/68VZ328/ucdimm/Makefile Sat Mar 15 18:40:45 2003 @@ -0,0 +1,12 @@ +# +# Makefile for arch/m68knommu/platform/68VZ328/ucdimm. +# + +obj-y := config.o + +EXTRA_TARGETS := bootlogo.rh crt0_$(MODEL).o + +$(obj)/bootlogo.rh: $(src)/../../68EZ328/bootlogo.h + perl $(src)/../../68328/bootlogo.pl < $(src)/../../68EZ328/bootlogo.h \ + > $(obj)/bootlogo.rh + diff -Nru a/arch/m68knommu/platform/68VZ328/ucdimm/config.c b/arch/m68knommu/platform/68VZ328/ucdimm/config.c --- a/arch/m68knommu/platform/68VZ328/ucdimm/config.c Sat Mar 15 18:40:40 2003 +++ b/arch/m68knommu/platform/68VZ328/ucdimm/config.c Sat Mar 15 18:40:40 2003 @@ -115,5 +115,5 @@ mach_gettod = BSP_gettod; mach_reset = BSP_reset; - config_M68VZ328_irq(); + config_M68328_irq(); } diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/mips/Kconfig Sat Mar 15 18:40:42 2003 @@ -10,10 +10,6 @@ bool default y -config SWAP - bool - default y - config SMP bool ---help--- diff -Nru a/arch/mips/arc/arc_con.c b/arch/mips/arc/arc_con.c --- a/arch/mips/arc/arc_con.c Sat Mar 15 18:40:45 2003 +++ b/arch/mips/arc/arc_con.c Sat Mar 15 18:40:45 2003 @@ -63,7 +63,8 @@ * Register console. */ -void __init arc_console_init(void) +static void __init arc_console_init(void) { register_console(&arc_cons); } +console_initcall(arc_console_init); diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c --- a/arch/mips/au1000/common/serial.c Sat Mar 15 18:40:41 2003 +++ b/arch/mips/au1000/common/serial.c Sat Mar 15 18:40:41 2003 @@ -3054,10 +3054,11 @@ /* * Register console. */ -void __init au1000_serial_console_init(void) +static void __init au1000_serial_console_init(void) { register_console(&sercons); } +console_initcall(au1000_serial_console_init); #endif /* diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c --- a/arch/mips/baget/irq.c Sat Mar 15 18:40:43 2003 +++ b/arch/mips/baget/irq.c Sat Mar 15 18:40:43 2003 @@ -146,11 +146,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < BAGET_IRQ_NR ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -161,6 +163,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c --- a/arch/mips/dec/irq.c Sat Mar 15 18:40:42 2003 +++ b/arch/mips/dec/irq.c Sat Mar 15 18:40:42 2003 @@ -97,11 +97,13 @@ { int i; struct irqaction *action; + unsigned long flags; for (i = 0; i < 32; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -112,6 +114,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/ite-boards/generic/irq.c b/arch/mips/ite-boards/generic/irq.c --- a/arch/mips/ite-boards/generic/irq.c Sat Mar 15 18:40:42 2003 +++ b/arch/mips/ite-boards/generic/irq.c Sat Mar 15 18:40:42 2003 @@ -222,6 +222,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jhandler ) - continue; + goto skip; seq_printf(p, "%3d: ", i); seq_printf(p, "%10u ", kstat_irqs(i)); if ( irq_desc[i].handler ) seq_printf(p, " %s ", irq_desc[i].handler->typename ); else seq_puts(p, " None "); + seq_printf(p, " %s",action->name); for (action=action->next; action; action = action->next) { seq_printf(p, ", %s", action->name); } seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "BAD: %10lu\n", spurious_count); return 0; @@ -437,6 +443,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &it8172_irq_type; + spin_lock_init(&irq_desc[i].lock); } /* diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Sat Mar 15 18:40:40 2003 +++ b/arch/mips/kernel/irq.c Sat Mar 15 18:40:40 2003 @@ -73,17 +73,19 @@ int show_interrupts(struct seq_file *p, void *v) { struct irqaction * action; + unsigned long flags; int i; - + seq_puts(p, " "); for (i=0; i < 1 /*smp_num_cpus*/; i++) seq_printf(p, "CPU%d ", i); seq_putc(p, '\n'); for (i = 0 ; i < NR_IRQS ; i++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%3d: ",i); seq_printf(p, "%10u ", kstat_irqs(i)); seq_printf(p, " %14s", irq_desc[i].handler->typename); @@ -92,6 +94,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "ERR: %10lu\n", irq_err_count); return 0; diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c --- a/arch/mips/kernel/old-irq.c Sat Mar 15 18:40:42 2003 +++ b/arch/mips/kernel/old-irq.c Sat Mar 15 18:40:42 2003 @@ -128,11 +128,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < 32 ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -143,6 +145,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c --- a/arch/mips/mips-boards/atlas/atlas_int.c Sat Mar 15 18:40:43 2003 +++ b/arch/mips/mips-boards/atlas/atlas_int.c Sat Mar 15 18:40:43 2003 @@ -99,11 +99,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < ATLASINT_END; i++, num++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -114,6 +116,8 @@ action->name); } seq_printf(p, " [hw0]\n"); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } @@ -243,6 +247,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &atlas_irq_type; + spin_lock_init(&irq_desc[i].lock); } #ifdef CONFIG_REMOTE_DEBUG diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c --- a/arch/mips/philips/nino/irq.c Sat Mar 15 18:40:39 2003 +++ b/arch/mips/philips/nino/irq.c Sat Mar 15 18:40:39 2003 @@ -119,11 +119,13 @@ { int i; struct irqaction *action; + unsigned long flags; for (i = 0; i < NR_IRQS; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -134,6 +136,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S --- a/arch/mips/vmlinux.lds.S Sat Mar 15 18:40:41 2003 +++ b/arch/mips/vmlinux.lds.S Sat Mar 15 18:40:41 2003 @@ -51,6 +51,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); /* Align double page for init_task_union */ __init_end = .; diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig --- a/arch/mips64/Kconfig Sat Mar 15 18:40:40 2003 +++ b/arch/mips64/Kconfig Sat Mar 15 18:40:40 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - source "init/Kconfig" diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c --- a/arch/mips64/kernel/linux32.c Sat Mar 15 18:40:42 2003 +++ b/arch/mips64/kernel/linux32.c Sat Mar 15 18:40:42 2003 @@ -729,12 +729,10 @@ return sys_llseek(fd, offset_high, offset_low, result, origin); } -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -749,7 +747,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -835,7 +833,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -855,7 +853,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1155,48 +1153,6 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) { - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - kfprog.filter = kfilter; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - kfree(kfilter); - return ret; - } - return sys_setsockopt(fd, level, optname, optval, optlen); -} - struct flock32 { short l_type; short l_whence; @@ -1873,256 +1829,3 @@ return ret; } -/* - * Declare the 32-bit version of the msghdr - */ - -struct msghdr32 { - unsigned int msg_name; /* Socket name */ - int msg_namelen; /* Length of name */ - unsigned int msg_iov; /* Data blocks */ - unsigned int msg_iovlen; /* Number of blocks */ - unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ - unsigned int msg_controllen; /* Length of cmsg list */ - unsigned msg_flags; -}; - -static inline int -shape_msg(struct msghdr *mp, struct msghdr32 *mp32) -{ - int ret; - unsigned int i; - - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return(-EFAULT); - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return(ret ? -EFAULT : 0); -} - -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ - -static inline int -verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode) -{ - int size, err, ct; - struct iovec32 *iov32; - - if(m->msg_namelen) - { - if(mode==VERIFY_READ) - { - err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if(err<0) - goto out; - } - - m->msg_name = address; - } else - m->msg_name = NULL; - - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov=iov; - - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: - return err; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - err = -ENOBUFS; - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - err = -EFAULT; - if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len)) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg_sys, total_len, flags); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S --- a/arch/mips64/kernel/scall_o32.S Sat Mar 15 18:40:43 2003 +++ b/arch/mips64/kernel/scall_o32.S Sat Mar 15 18:40:43 2003 @@ -378,8 +378,8 @@ sys sys32_select 5 sys sys_flock 2 sys sys_msync 3 - sys sys32_readv 3 /* 4145 */ - sys sys32_writev 3 + sys compat_sys_readv 3 /* 4145 */ + sys compat_sys_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 sys sys_sysmips 4 @@ -410,11 +410,11 @@ sys sys_listen 2 sys sys_recv 4 /* 4175 */ sys sys_recvfrom 6 - sys sys32_recvmsg 3 + sys compat_sys_recvmsg 3 sys sys_send 4 - sys sys32_sendmsg 3 + sys compat_sys_sendmsg 3 sys sys_sendto 6 /* 4180 */ - sys sys32_setsockopt 5 + sys compat_sys_setsockopt 5 sys sys_shutdown 2 sys sys_socket 3 sys sys_socketpair 4 diff -Nru a/arch/mips64/mips-boards/atlas/atlas_int.c b/arch/mips64/mips-boards/atlas/atlas_int.c --- a/arch/mips64/mips-boards/atlas/atlas_int.c Sat Mar 15 18:40:44 2003 +++ b/arch/mips64/mips-boards/atlas/atlas_int.c Sat Mar 15 18:40:44 2003 @@ -95,11 +95,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < ATLASINT_END; i++, num++) { + spin_lock_irqsave(&irq_desc[i].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto unlock; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -110,6 +112,8 @@ action->name); } seq_puts(p, " [hw0]\n"); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } @@ -239,6 +243,7 @@ irq_desc[i].action = 0; irq_desc[i].depth = 1; irq_desc[i].handler = &atlas_irq_type; + spin_lock_init(&irq_desc[i].lock); } #ifdef CONFIG_REMOTE_DEBUG diff -Nru a/arch/mips64/mips-boards/malta/malta_int.c b/arch/mips64/mips-boards/malta/malta_int.c --- a/arch/mips64/mips-boards/malta/malta_int.c Sat Mar 15 18:40:43 2003 +++ b/arch/mips64/mips-boards/malta/malta_int.c Sat Mar 15 18:40:43 2003 @@ -125,11 +125,13 @@ int i; int num = 0; struct irqaction *action; + unsigned long flags; for (i = 0; i < 8; i++, num++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip_1; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -140,11 +142,14 @@ action->name); } seq_puts(p, " [on-chip]\n"); +skip_1: + local_irq_restore(flags); } for (i = 0; i < MALTAINT_END; i++, num++) { + local_irq_save(flags); action = hw0_irq_action[i]; if (!action) - continue; + goto skip_2; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -155,6 +160,8 @@ action->name); } seq_puts(p, " [hw0]\n"); +skip_2: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c --- a/arch/mips64/sgi-ip22/ip22-int.c Sat Mar 15 18:40:39 2003 +++ b/arch/mips64/sgi-ip22/ip22-int.c Sat Mar 15 18:40:39 2003 @@ -237,11 +237,13 @@ int i; int num = 0; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < 16 ; i++, num++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip_1; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -252,11 +254,14 @@ action->name); } seq_puts(p, " [on-chip]\n"); +skip_1: + local_irq_restore(flags); } for (i = 0 ; i < 24 ; i++, num++) { + local_irq_save(flags); action = local_irq_action[i]; if (!action) - continue; + goto skip_2; seq_printf(p, "%2d: %8d %c %s", num, kstat_cpu(0).irqs[num], (action->flags & SA_INTERRUPT) ? '+' : ' ', @@ -267,6 +272,8 @@ action->name); } seq_puts(p, " [local]\n"); +skip_2: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c --- a/arch/mips64/sgi-ip27/ip27-irq.c Sat Mar 15 18:40:42 2003 +++ b/arch/mips64/sgi-ip27/ip27-irq.c Sat Mar 15 18:40:42 2003 @@ -141,11 +141,13 @@ { int i; struct irqaction * action; + unsigned long flags; for (i = 0 ; i < NR_IRQS ; i++) { + local_irq_save(flags); action = irq_action[i]; if (!action) - continue; + goto skip; seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); @@ -156,6 +158,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S --- a/arch/mips64/vmlinux.lds.S Sat Mar 15 18:40:41 2003 +++ b/arch/mips64/vmlinux.lds.S Sat Mar 15 18:40:41 2003 @@ -50,6 +50,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); /* Align double page for init_task_union */ __init_end = .; diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig --- a/arch/parisc/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/parisc/Kconfig Sat Mar 15 18:40:42 2003 @@ -18,10 +18,6 @@ bool default y -config SWAP - bool - default y - config STACK_GROWSUP bool default y diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c --- a/arch/parisc/kernel/sys_parisc32.c Sat Mar 15 18:40:41 2003 +++ b/arch/parisc/kernel/sys_parisc32.c Sat Mar 15 18:40:41 2003 @@ -316,35 +316,6 @@ return -ENOSYS; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); - -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - long ret; - - if (get_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - KERNEL_SYSCALL(ret, sys_fcntl, fd, cmd, (unsigned long)&f); - if (ret) return ret; - if (f.l_start >= 0x7fffffffUL || - f.l_len >= 0x7fffffffUL || - f.l_start + f.l_len >= 0x7fffffffUL) - return -EOVERFLOW; - if (put_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - return 0; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - #ifdef CONFIG_SYSCTL struct __sysctl_args32 { @@ -919,12 +890,10 @@ /* readv/writev stolen from mips64 */ -struct iovec32 { unsigned int iov_base; int iov_len; }; - typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *); static long -do_readv_writev32(int type, struct file *file, const struct iovec32 *vector, +do_readv_writev32(int type, struct file *file, const struct compat_iovec *vector, u32 count) { unsigned long tot_len; @@ -939,7 +908,7 @@ */ if (!count) return 0; - if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -1025,7 +994,7 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1045,7 +1014,7 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; ssize_t ret; @@ -1063,747 +1032,6 @@ return ret; } -/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/ -#include -#include -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -extern struct socket *sockfd_lookup(int fd, int *err); - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - - -static int do_ipv4_set_replace(int fd, int level, int optname, - char *optval, int optlen) -#if 1 -/* Fields happen to be padded such that this works. -** Don't need to change iptables.h:struct ipt_replace -*/ -{ - struct ipt_replace *repl = (struct ipt_replace *) optval; - unsigned long ptr64; - unsigned int ptr32; - int ret; - - if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32))) - return -EFAULT; - ptr64 = (unsigned long) ptr32; - if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64))) - return -EFAULT; - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - /* Restore 32-bit ptr */ - if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32))) - return -EFAULT; - - return ret; -} -#else -/* This version tries to "do it right". ie allocate kernel buffers for -** everything and copy data in/out. Way too complicated. -** NOT TESTED for correctness! -*/ -{ - struct ipt_replace *kern_repl; - struct ipt_counters *kern_counters; - unsigned int user_counters; - mm_segment_t old_fs; - int ret = 0; - - kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL); - if (!kern_repl) - return -ENOMEM; - - if (copy_from_user(kern_repl, optval, optlen)) { - ret = -EFAULT; - goto err02; - } - - /* 32-bit ptr is in the MSB's */ - user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32); - /* - ** We are going to set_fs() to kernel space - and thus need - ** "relocate" the counters buffer to the kernel space. - */ - kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL); - if (!user_counters) { - ret = -ENOMEM; - goto err02; - } - - if (copy_from_user(kern_counters, (char *) user_counters, optlen)) { - ret = -EFAULT; - goto err01; - } - - /* We can update the kernel ptr now that we have the data. */ - kern_repl->counters = kern_counters; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen); - - set_fs(old_fs); - - /* Copy counters back out to user space */ - if (copy_to_user((char *) user_counters, kern_counters, - kern_repl->num_counters * sizeof(struct ipt_counters))) - { - ret = -EFAULT; - goto err01; - } - - /* restore counters so userspace can consume it */ - kern_repl->counters = NULL; - (unsigned int) kern_repl->counters = user_counters; - - /* Copy repl back out to user space */ - if (copy_to_user(optval, kern_repl, optlen)) - { - ret = -EFAULT; - } - -err01: - kfree(kern_counters); -err02: - kfree(kern_repl); - return ret; -} -#endif - - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, optval, optlen); - - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, optval, optlen); - - /* - ** Beware: IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE - */ - if (level == IPPROTO_IP && optname == IPT_SO_SET_REPLACE) - return do_ipv4_set_replace(fd, level, optname, optval, optlen); - - if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE) -#if 0 - /* FIXME: I don't (yet) use IPV6. -ggg */ - return do_ipv6_set_replace(fd, level, optname, optval, optlen); -#else - { - BUG(); - return -ENXIO; - } -#endif - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - - /*** copied from mips64 ***/ /* * Ooo, nasty. We need here to frob 32-bit unsigned longs to @@ -2041,28 +1269,6 @@ kfree(mb); return err; -} - -/* LFS */ - -extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long); - -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK64: - cmd = F_GETLK; - break; - case F_SETLK64: - cmd = F_SETLK; - break; - case F_SETLKW64: - cmd = F_SETLKW; - break; - default: - break; - } - return sys32_fcntl(fd, cmd, arg); } /* EXPORT/UNEXPORT */ diff -Nru a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S --- a/arch/parisc/kernel/syscall.S Sat Mar 15 18:40:45 2003 +++ b/arch/parisc/kernel/syscall.S Sat Mar 15 18:40:45 2003 @@ -409,8 +409,7 @@ ENTRY_SAME(getpeername) /* This one's a huge ugly mess */ ENTRY_DIFF(ioctl) - /* struct flock? */ - ENTRY_DIFF(fcntl) /* 55 */ + ENTRY_COMP(fcntl) /* 55 */ ENTRY_SAME(socketpair) ENTRY_SAME(setpgid) ENTRY_SAME(send) @@ -589,7 +588,7 @@ ENTRY_OURS(truncate64) ENTRY_OURS(ftruncate64) /* 200 */ ENTRY_SAME(getdents64) - ENTRY_DIFF(fcntl64) + ENTRY_COMP(fcntl64) ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) ENTRY_SAME(ni_syscall) /* 205 */ diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Sat Mar 15 18:40:40 2003 +++ b/arch/parisc/vmlinux.lds.S Sat Mar 15 18:40:40 2003 @@ -73,6 +73,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/ppc/8xx_io/uart.c b/arch/ppc/8xx_io/uart.c --- a/arch/ppc/8xx_io/uart.c Sat Mar 15 18:40:43 2003 +++ b/arch/ppc/8xx_io/uart.c Sat Mar 15 18:40:43 2003 @@ -2522,12 +2522,11 @@ /* * Register console. */ -long __init console_8xx_init(long kmem_start, long kmem_end) +static void __init console_8xx_init(long kmem_start, long kmem_end) { register_console(&sercons); - return kmem_start; } - +console_initcall(console_8xx_init); #endif /* Index in baud rate table of the default console baud rate. diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Sat Mar 15 18:40:44 2003 +++ b/arch/ppc/Kconfig Sat Mar 15 18:40:44 2003 @@ -1126,22 +1126,6 @@ config PIN_TLB bool "Pinned Kernel TLBs (860 ONLY)" depends on ADVANCED_OPTIONS && 8xx - -config SWAP - bool "Enable support for swap" - depends on ADVANCED_OPTIONS - help - This option allows you to turn off support for swapfiles in - the kernel. This can be useful if you know that your system - will never have swap. - - Say Y here unless you know what you are doing. - -config SWAP - bool - depends on !ADVANCED_OPTIONS - default y - endmenu source "drivers/mtd/Kconfig" diff -Nru a/arch/ppc/boot/common/util.S b/arch/ppc/boot/common/util.S --- a/arch/ppc/boot/common/util.S Sat Mar 15 18:40:45 2003 +++ b/arch/ppc/boot/common/util.S Sat Mar 15 18:40:45 2003 @@ -14,7 +14,7 @@ * trini@mvista.com * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -98,7 +98,7 @@ isync mfspr r8,L2CR rlwinm r8,r8,0,1,31 - oris r8,r8,0x0020 + oris r8,r8,L2CR_L2I@h sync isync mtspr L2CR,r8 @@ -106,14 +106,55 @@ isync /* Wait for the invalidation to complete */ -1: mfspr r8,L2CR - rlwinm. r9,r8,0,31,31 + mfspr r8,PVR + srwi r8,r8,16 + cmpli cr0,r8,0x8000 /* 7450 */ + cmpli cr1,r8,0x8001 /* 7455 */ + cmpli cr2,r8,0x8002 /* 7457 */ + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + bne 2f + +1: mfspr r8,L2CR /* On 745x, poll L2I bit (bit 10) */ + rlwinm. r9,r8,0,10,10 bne 1b + b 3f + +2: mfspr r8,L2CR /* On 75x & 74[01]0, poll L2IP bit (bit 31) */ + rlwinm. r9,r8,0,31,31 + bne 2b - rlwinm r8,r8,0,11,9 /* Turn off L2I bit */ +3: rlwinm r8,r8,0,11,9 /* Turn off L2I bit */ sync isync mtspr L2CR,r8 + sync + isync + blr + + .globl _setup_L3CR +_setup_L3CR: + /* Invalidate/disable L3 cache */ + sync + isync + mfspr r8,L3CR + rlwinm r8,r8,0,1,31 + ori r8,r8,L3CR_L3I@l + sync + isync + mtspr L3CR,r8 + sync + isync + + /* Wait for the invalidation to complete */ +1: mfspr r8,L3CR + rlwinm. r9,r8,0,21,21 + bne 1b + + rlwinm r8,r8,0,22,20 /* Turn off L3I bit */ + sync + isync + mtspr L3CR,r8 sync isync blr diff -Nru a/arch/ppc/boot/simple/head.S b/arch/ppc/boot/simple/head.S --- a/arch/ppc/boot/simple/head.S Sat Mar 15 18:40:43 2003 +++ b/arch/ppc/boot/simple/head.S Sat Mar 15 18:40:43 2003 @@ -7,7 +7,7 @@ * trini@mvista.com * Derived from arch/ppc/boot/prep/head.S (Cort Dougan, many others). * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under + * 2001-2003 (c) MontaVista, Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. @@ -74,6 +74,17 @@ #if defined(CONFIG_FORCE) || defined(CONFIG_K2) \ || defined(CONFIG_EV64260) || defined(CONFIG_PAL4) bl _setup_L2CR + + /* If 745x, turn off L3CR as well */ + mfspr r8,PVR + srwi r8,r8,16 + + cmpli cr0,r8,0x8000 /* 7450 */ + cmpli cr1,r8,0x8001 /* 7455 */ + cmpli cr2,r8,0x8002 /* 7457 */ + cror 4*cr0+eq,4*cr0+eq,4*cr1+eq /* Now test if any are true. */ + cror 4*cr0+eq,4*cr0+eq,4*cr2+eq + beql _setup_L3CR #endif #endif diff -Nru a/arch/ppc/boot/simple/rw4/ppc_40x.h b/arch/ppc/boot/simple/rw4/ppc_40x.h --- a/arch/ppc/boot/simple/rw4/ppc_40x.h Sat Mar 15 18:40:40 2003 +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h Sat Mar 15 18:40:40 2003 @@ -42,7 +42,7 @@ #define dccr 0x3fa /* data cache control reg. */ #define dcwr 0x3ba /* data cache write-thru reg */ #define dear 0x3d5 /* data exception address reg */ -#define esr 0x3d4 /* exception syndrome registe */ +#define esr 0x3d4 /* exception syndrome register */ #define evpr 0x3d6 /* exception vector prefix reg */ #define iccr 0x3fb /* instruction cache cntrl re */ #define icdbdr 0x3d3 /* instr cache dbug data reg */ diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Sat Mar 15 18:40:44 2003 +++ b/arch/ppc/kernel/irq.c Sat Mar 15 18:40:44 2003 @@ -346,6 +346,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (j=0; jhandler ) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for (j = 0; j < NR_CPUS; j++) @@ -375,6 +377,8 @@ for (action = action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } #ifdef CONFIG_TAU_INT if (tau_initialized){ @@ -680,7 +684,7 @@ struct proc_dir_entry *entry; char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc[irq].handler == NULL)) + if (!root_irq_dir || (irq_desc[irq].handler == NULL) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); diff -Nru a/arch/ppc/kernel/ppc-stub.c b/arch/ppc/kernel/ppc-stub.c --- a/arch/ppc/kernel/ppc-stub.c Sat Mar 15 18:40:44 2003 +++ b/arch/ppc/kernel/ppc-stub.c Sat Mar 15 18:40:44 2003 @@ -420,18 +420,6 @@ flush_instruction_cache(); } -static inline int get_msr(void) -{ - int msr; - asm volatile("mfmsr %0" : "=r" (msr):); - return msr; -} - -static inline void set_msr(int msr) -{ - asm volatile("mtmsr %0" : : "r" (msr)); -} - /* Set up exception handlers for tracing and breakpoints * [could be called kgdb_init()] */ @@ -598,8 +586,8 @@ kgdb_interruptible(0); lock_kernel(); - msr = get_msr(); - set_msr(msr & ~MSR_EE); /* disable interrupts */ + msr = mfmsr(); + mtmsr(msr & ~MSR_EE); /* disable interrupts */ if (regs->nip == (unsigned long)breakinst) { /* Skip over breakpoint trap insn */ @@ -626,7 +614,7 @@ *ptr++ = hexchars[SP_REGNUM >> 4]; *ptr++ = hexchars[SP_REGNUM & 0xf]; *ptr++ = ':'; - ptr = mem2hex(((char *)®s) + SP_REGNUM*4, ptr, 4); + ptr = mem2hex(((char *)regs) + SP_REGNUM*4, ptr, 4); *ptr++ = ';'; #endif @@ -786,7 +774,7 @@ strcpy(remcomOutBuffer, "OK"); putpacket(remcomOutBuffer); #endif - set_msr(msr); + mtmsr(msr); kgdb_interruptible(1); unlock_kernel(); @@ -802,10 +790,9 @@ #if defined(CONFIG_40x) regs->msr |= MSR_DE; regs->dbcr0 |= (DBCR0_IDM | DBCR0_IC); - set_msr(msr); + mtmsr(msr); #else regs->msr |= MSR_SE; - set_msr(msr | MSR_SE); #endif unlock_kernel(); kgdb_active = 0; diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Sat Mar 15 18:40:41 2003 +++ b/arch/ppc/kernel/process.c Sat Mar 15 18:40:41 2003 @@ -321,6 +321,24 @@ } /* + * 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.. */ int @@ -348,6 +366,8 @@ } else { childregs->gpr[1] = usp; p->thread.regs = childregs; + if (clone_flags & CLONE_SETTLS) + childregs->gpr[2] = childregs->gpr[6]; } childregs->gpr[3] = 0; /* Result from fork() */ sp -= STACK_FRAME_OVERHEAD; @@ -367,29 +387,6 @@ p->thread.ksp = sp; kregs->nip = (unsigned long)ret_from_fork; - /* - * copy fpu info - assume lazy fpu switch now always - * -- Cort - */ - if (regs->msr & MSR_FP) { - giveup_fpu(current); - childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1); - } - memcpy(&p->thread.fpr, ¤t->thread.fpr, sizeof(p->thread.fpr)); - p->thread.fpscr = current->thread.fpscr; - -#ifdef CONFIG_ALTIVEC - /* - * copy altiVec info - assume lazy altiVec switch - * - kumar - */ - if (regs->msr & MSR_VEC) - giveup_altivec(current); - memcpy(&p->thread.vr, ¤t->thread.vr, sizeof(p->thread.vr)); - p->thread.vscr = current->thread.vscr; - childregs->msr &= ~MSR_VEC; -#endif /* CONFIG_ALTIVEC */ - p->thread.last_syscall = -1; return 0; @@ -444,15 +441,17 @@ return put_user(val, (unsigned int *) adr); } -int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6, +int sys_clone(unsigned long clone_flags, unsigned long usp, int *parent_tidp, + void *child_threadptr, int *child_tidp, int p6, struct pt_regs *regs) { struct task_struct *p; CHECK_FULL_REGS(regs); - if (p2 == 0) - p2 = regs->gpr[1]; /* stack pointer for child */ - p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4); + if (usp == 0) + usp = regs->gpr[1]; /* stack pointer for child */ + p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0, + parent_tidp, child_tidp); return IS_ERR(p) ? PTR_ERR(p) : p->pid; } diff -Nru a/arch/ppc/mm/fault.c b/arch/ppc/mm/fault.c --- a/arch/ppc/mm/fault.c Sat Mar 15 18:40:40 2003 +++ b/arch/ppc/mm/fault.c Sat Mar 15 18:40:40 2003 @@ -57,6 +57,41 @@ extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); /* + * Check whether the instruction at regs->nip is a store using + * an update addressing form which will update r1. + */ +static int store_updates_sp(struct pt_regs *regs) +{ + unsigned int inst; + + if (get_user(inst, (unsigned int *)regs->nip)) + return 0; + /* check for 1 in the rA field */ + if (((inst >> 16) & 0x1f) != 1) + return 0; + /* check major opcode */ + switch (inst >> 26) { + case 37: /* stwu */ + case 39: /* stbu */ + case 45: /* sthu */ + case 53: /* stfsu */ + case 55: /* stfdu */ + return 1; + case 31: + /* check minor opcode */ + switch ((inst >> 1) & 0x3ff) { + case 183: /* stwux */ + case 247: /* stbux */ + case 439: /* sthux */ + case 695: /* stfsux */ + case 759: /* stfdux */ + return 1; + } + } + return 0; +} + +/* * For 600- and 800-family processors, the error_code parameter is DSISR * for a data fault, SRR1 for an instruction fault. For 400-family processors * the error_code parameter is ESR for a data fault, 0 for an instruction @@ -112,6 +147,40 @@ goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) goto bad_area; + if (!is_write) + goto bad_area; + + /* + * N.B. The rs6000/xcoff ABI allows programs to access up to + * a few hundred bytes below the stack pointer. + * The kernel signal delivery code writes up to about 1.5kB + * below the stack pointer (r1) before decrementing it. + * The exec code can write slightly over 640kB to the stack + * before setting the user r1. Thus we allow the stack to + * expand to 1MB without further checks. + */ + if (address + 0x100000 < vma->vm_end) { + /* get user regs even if this fault is in kernel mode */ + struct pt_regs *uregs = current->thread.regs; + if (uregs == NULL) + goto bad_area; + + /* + * A user-mode access to an address a long way below + * the stack pointer is only valid if the instruction + * is one which would update the stack pointer to the + * address accessed if the instruction completed, + * i.e. either stwu rs,n(r1) or stwux rs,r1,rb + * (or the byte, halfword, float or double forms). + * + * If we don't check this then any write to the area + * between the last mapped region and the stack will + * expand the stack rather than segfaulting. + */ + if (address + 2048 < uregs->gpr[1] + && (!user_mode(regs) || !store_updates_sp(regs))) + goto bad_area; + } if (expand_stack(vma, address)) goto bad_area; diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c --- a/arch/ppc/mm/init.c Sat Mar 15 18:40:40 2003 +++ b/arch/ppc/mm/init.c Sat Mar 15 18:40:40 2003 @@ -338,6 +338,7 @@ min_low_pfn = start >> PAGE_SHIFT; max_low_pfn = (PPC_MEMSTART + total_lowmem) >> PAGE_SHIFT; + max_pfn = (PPC_MEMSTART + total_memory) >> PAGE_SHIFT; boot_mapsize = init_bootmem_node(&contig_page_data, min_low_pfn, PPC_MEMSTART >> PAGE_SHIFT, max_low_pfn); diff -Nru a/arch/ppc/platforms/lopec_setup.c b/arch/ppc/platforms/lopec_setup.c --- a/arch/ppc/platforms/lopec_setup.c Sat Mar 15 18:40:42 2003 +++ b/arch/ppc/platforms/lopec_setup.c Sat Mar 15 18:40:42 2003 @@ -324,7 +324,7 @@ ROOT_DEV = Root_SDA1; #endif -#ifdef CONFIG_DUMMY_CONSOLE +#ifdef CONFIG_VT conswitchp = &dummy_con; #endif #ifdef CONFIG_PPCBUG_NVRAM @@ -378,7 +378,7 @@ ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; -#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_ID_MODULE) +#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.default_irq = lopec_ide_default_irq; ppc_ide_md.default_io_base = lopec_ide_default_io_base; ppc_ide_md.ide_init_hwif = lopec_ide_init_hwif_ports; diff -Nru a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c --- a/arch/ppc/syslib/open_pic.c Sat Mar 15 18:40:42 2003 +++ b/arch/ppc/syslib/open_pic.c Sat Mar 15 18:40:42 2003 @@ -580,14 +580,19 @@ if (OpenPIC == NULL) return; + /* IPIs are marked SA_INTERRUPT as they must run with irqs disabled */ request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset, - openpic_ipi_action, 0, "IPI0 (call function)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI0 (call function)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+1, - openpic_ipi_action, 0, "IPI1 (reschedule)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI1 (reschedule)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+2, - openpic_ipi_action, 0, "IPI2 (invalidate tlb)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI2 (invalidate tlb)", 0); request_irq(OPENPIC_VEC_IPI+open_pic_irq_offset+3, - openpic_ipi_action, 0, "IPI3 (xmon break)", 0); + openpic_ipi_action, SA_INTERRUPT, + "IPI3 (xmon break)", 0); for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) openpic_enable_ipi(OPENPIC_VEC_IPI+open_pic_irq_offset+i); diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S --- a/arch/ppc/vmlinux.lds.S Sat Mar 15 18:40:45 2003 +++ b/arch/ppc/vmlinux.lds.S Sat Mar 15 18:40:45 2003 @@ -107,6 +107,10 @@ } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + __start___ftr_fixup = .; __ftr_fixup : { *(__ftr_fixup) } __stop___ftr_fixup = .; diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/ppc64/Kconfig Sat Mar 15 18:40:42 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile --- a/arch/ppc64/Makefile Sat Mar 15 18:40:40 2003 +++ b/arch/ppc64/Makefile Sat Mar 15 18:40:40 2003 @@ -18,9 +18,8 @@ LDFLAGS := -m elf64ppc LDFLAGS_vmlinux = -Bstatic -e $(KERNELLOAD) -Ttext $(KERNELLOAD) LDFLAGS_BLOB := --format binary --oformat elf64-powerpc -CFLAGS += -msoft-float -pipe \ - -Wno-uninitialized -mminimal-toc -mtraceback=full \ - -finline-limit-2000 -mcpu=power4 +CFLAGS += -msoft-float -pipe -Wno-uninitialized -mminimal-toc \ + -mtraceback=full -mcpu=power4 head-y := arch/ppc64/kernel/head.o diff -Nru a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c --- a/arch/ppc64/boot/main.c Sat Mar 15 18:40:45 2003 +++ b/arch/ppc64/boot/main.c Sat Mar 15 18:40:45 2003 @@ -12,11 +12,10 @@ #include "ppc32-types.h" #include "zlib.h" #include +#include #include #include #include - -void memmove(void *dst, void *im, int len); extern void *finddevice(const char *); extern int getprop(void *, const char *, void *, int); diff -Nru a/arch/ppc64/kernel/chrp_setup.c b/arch/ppc64/kernel/chrp_setup.c --- a/arch/ppc64/kernel/chrp_setup.c Sat Mar 15 18:40:40 2003 +++ b/arch/ppc64/kernel/chrp_setup.c Sat Mar 15 18:40:40 2003 @@ -72,6 +72,7 @@ extern void find_and_init_phbs(void); extern void pSeries_pcibios_fixup(void); +extern void pSeries_pcibios_fixup_bus(struct pci_bus *bus); extern void iSeries_pcibios_fixup(void); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); @@ -245,6 +246,7 @@ #ifndef CONFIG_PPC_ISERIES ppc_md.pcibios_fixup = pSeries_pcibios_fixup; + ppc_md.pcibios_fixup_bus = pSeries_pcibios_fixup_bus; #else ppc_md.pcibios_fixup = NULL; // ppc_md.pcibios_fixup = iSeries_pcibios_fixup; diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c --- a/arch/ppc64/kernel/eeh.c Sat Mar 15 18:40:43 2003 +++ b/arch/ppc64/kernel/eeh.c Sat Mar 15 18:40:43 2003 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Sat Mar 15 18:40:39 2003 +++ b/arch/ppc64/kernel/entry.S Sat Mar 15 18:40:39 2003 @@ -344,8 +344,8 @@ recheck: mfmsr r10 /* Get current interrupt state */ li r4,0 - ori r4,r4,MSR_EE|MSR_RI - andc r10,r10,r4 /* clear MSR_EE and MSR_RI */ + ori r4,r4,MSR_EE + andc r10,r10,r4 /* clear MSR_EE */ mtmsrd r10,1 /* Update machine state */ #ifdef CONFIG_PPC_ISERIES @@ -396,7 +396,7 @@ mfmsr r0 li r2, MSR_RI andc r0,r0,r2 - mtmsrd r0 + mtmsrd r0,1 ld r0,_MSR(r1) mtspr SRR1,r0 @@ -422,7 +422,7 @@ /* Note: this must change if we start using the TIF_NOTIFY_RESUME bit */ do_work: /* Enable interrupts */ - ori r10,r10,MSR_EE|MSR_RI + ori r10,r10,MSR_EE mtmsrd r10,1 andi. r0,r3,_TIF_NEED_RESCHED diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S --- a/arch/ppc64/kernel/head.S Sat Mar 15 18:40:42 2003 +++ b/arch/ppc64/kernel/head.S Sat Mar 15 18:40:42 2003 @@ -562,7 +562,7 @@ mfmsr r20 li r21, MSR_RI andc r20,r20,r21 - mtmsrd r20 + mtmsrd r20,1 mtspr SRR1,r23 mtspr SRR0,r22 @@ -989,7 +989,7 @@ mfmsr r22 li r23, MSR_RI andc r22,r22,r23 - mtmsrd r22 + mtmsrd r22,1 ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ @@ -1094,7 +1094,7 @@ mfmsr r22 li r23, MSR_RI andc r22,r22,r23 - mtmsrd r22 + mtmsrd r22,1 ld r22,EX_SRR0(r21) /* Get SRR0 from exc. frame */ ld r23,EX_SRR1(r21) /* Get SRR1 from exc. frame */ diff -Nru a/arch/ppc64/kernel/htab.c b/arch/ppc64/kernel/htab.c --- a/arch/ppc64/kernel/htab.c Sat Mar 15 18:40:42 2003 +++ b/arch/ppc64/kernel/htab.c Sat Mar 15 18:40:42 2003 @@ -18,7 +18,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include #include diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Sat Mar 15 18:40:41 2003 +++ b/arch/ppc64/kernel/irq.c Sat Mar 15 18:40:41 2003 @@ -341,6 +341,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jhandler) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifdef CONFIG_SMP for (j = 0; j < NR_CPUS; j++) { @@ -371,6 +373,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts); return 0; @@ -394,81 +398,6 @@ local_irq_disable(); } -#ifdef CONFIG_SMP -extern unsigned long irq_affinity [NR_IRQS]; - -typedef struct { - unsigned long cpu; - unsigned long timestamp; -} ____cacheline_aligned irq_balance_t; - -static irq_balance_t irq_balance[NR_IRQS] __cacheline_aligned - = { [ 0 ... NR_IRQS-1 ] = { 0, 0 } }; - -#define IDLE_ENOUGH(cpu,now) \ - (idle_cpu(cpu) && ((now) - irq_stat[(cpu)].idle_timestamp > 1)) - -#define IRQ_ALLOWED(cpu,allowed_mask) \ - ((1UL << cpu) & (allowed_mask)) - -#define IRQ_BALANCE_INTERVAL (HZ/50) - -static unsigned long move(unsigned long curr_cpu, unsigned long allowed_mask, - unsigned long now, int direction) -{ - int search_idle = 1; - int cpu = curr_cpu; - - goto inside; - - do { - if (unlikely(cpu == curr_cpu)) - search_idle = 0; -inside: - if (direction == 1) { - cpu++; - if (cpu >= NR_CPUS) - cpu = 0; - } else { - cpu--; - if (cpu == -1) - cpu = NR_CPUS-1; - } - } while (!cpu_online(cpu) || !IRQ_ALLOWED(cpu,allowed_mask) || - (search_idle && !IDLE_ENOUGH(cpu,now))); - - return cpu; -} - -static inline void balance_irq(int irq) -{ - irq_balance_t *entry = irq_balance + irq; - unsigned long now = jiffies; - - if (unlikely(time_after(now, entry->timestamp + IRQ_BALANCE_INTERVAL))) { - unsigned long allowed_mask; - unsigned int new_cpu; - unsigned long random_number; - - if (!irq_desc[irq].handler->set_affinity) - return; - - random_number = mftb(); - random_number &= 1; - - allowed_mask = cpu_online_map & irq_affinity[irq]; - entry->timestamp = now; - new_cpu = move(entry->cpu, allowed_mask, now, random_number); - if (entry->cpu != new_cpu) { - entry->cpu = new_cpu; - irq_desc[irq].handler->set_affinity(irq, 1UL << new_cpu); - } - } -} -#else -#define balance_irq(irq) do { } while (0) -#endif - /* * Eventually, this should take an array of interrupts and an array size * so it can dispatch multiple interrupts. @@ -479,10 +408,6 @@ struct irqaction *action; int cpu = smp_processor_id(); irq_desc_t *desc = irq_desc + irq; - - /* XXX This causes bad performance and lockups on XICS - Anton */ - if (naca->interrupt_controller == IC_OPEN_PIC) - balance_irq(irq); kstat_cpu(cpu).irqs[irq]++; spin_lock(&desc->lock); diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S --- a/arch/ppc64/kernel/misc.S Sat Mar 15 18:40:44 2003 +++ b/arch/ppc64/kernel/misc.S Sat Mar 15 18:40:44 2003 @@ -557,7 +557,7 @@ .llong .sys32_umount .llong .sys_ni_syscall /* old lock syscall */ .llong .sys32_ioctl - .llong .sys32_fcntl /* 55 */ + .llong .compat_sys_fcntl /* 55 */ .llong .sys_ni_syscall /* old mpx syscall */ .llong .sys32_setpgid .llong .sys_ni_syscall /* old ulimit syscall */ @@ -604,7 +604,7 @@ .llong .compat_sys_statfs .llong .compat_sys_fstatfs /* 100 */ .llong .sys_ioperm - .llong .sys32_socketcall + .llong .compat_sys_socketcall .llong .sys32_syslog .llong .compat_sys_setitimer .llong .compat_sys_getitimer /* 105 */ @@ -706,7 +706,7 @@ .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root - .llong .sys32_fcntl64 + .llong .compat_sys_fcntl64 .llong .sys_madvise /* 205 */ .llong .sys_mincore .llong .sys_gettid diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Sat Mar 15 18:40:45 2003 +++ b/arch/ppc64/kernel/pSeries_pci.c Sat Mar 15 18:40:45 2003 @@ -43,12 +43,6 @@ #include "open_pic.h" #include "pci.h" -/******************************************************************* - * Forward declares of prototypes. - *******************************************************************/ -struct pci_controller *alloc_phb(struct device_node *dev, char *model, - unsigned int addr_size_words) ; - /* RTAS tokens */ static int read_pci_config; static int write_pci_config; @@ -144,242 +138,173 @@ * openfirmware and sets it in the pci_dev and pci_config line. * ******************************************************************/ -int -pci_read_irq_line(struct pci_dev *Pci_Dev) +int pci_read_irq_line(struct pci_dev *pci_dev) { - u8 InterruptPin; - struct device_node *Node; + u8 intpin; + struct device_node *node; + + pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); - pci_read_config_byte(Pci_Dev, PCI_INTERRUPT_PIN, &InterruptPin); - if (InterruptPin == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n",Pci_Dev->slot_name); + if (intpin == 0) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Interrupt used by device.\n", pci_dev->slot_name); return 0; } - Node = pci_device_to_OF_node(Pci_Dev); - if ( Node == NULL) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n",Pci_Dev->slot_name); + + node = pci_device_to_OF_node(pci_dev); + if (node == NULL) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s Device Node not found.\n", + pci_dev->slot_name); return -1; } - if (Node->n_intrs == 0) { - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n",Pci_Dev->slot_name); + if (node->n_intrs == 0) { + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s No Device OF interrupts defined.\n", pci_dev->slot_name); return -1; } - Pci_Dev->irq = Node->intrs[0].line; + pci_dev->irq = node->intrs[0].line; if (s7a_workaround) { - if (Pci_Dev->irq > 16) - Pci_Dev->irq -= 3; + if (pci_dev->irq > 16) + pci_dev->irq -= 3; } - pci_write_config_byte(Pci_Dev, PCI_INTERRUPT_LINE, Pci_Dev->irq); + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); - PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n",Pci_Dev->slot_name,Pci_Dev->irq); + PPCDBG(PPCDBG_BUSWALK,"\tDevice: %s pci_dev->irq = 0x%02X\n", + pci_dev->slot_name, pci_dev->irq); return 0; } -/****************************************************************** - * Find all PHBs in the system and initialize a set of data - * structures to represent them. - ******************************************************************/ -unsigned long __init -find_and_init_phbs(void) -{ - struct device_node *Pci_Node; - struct pci_controller *phb; - unsigned int root_addr_size_words = 0, this_addr_size_words = 0; - unsigned int this_addr_count = 0, range_stride; - unsigned int *ui_ptr = NULL, *ranges; - char *model; - struct pci_range64 range; +static void __init pci_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, + int primary) +{ + unsigned int *ranges; + unsigned long size; + int rlen = 0; + int memno = 0; struct resource *res; - unsigned int memno, rlen, i, index; - unsigned int *opprop; - int has_isa = 0; - PPCDBG(PPCDBG_PHBINIT, "find_and_init_phbs\n"); + int np, na = prom_n_addr_cells(dev); + unsigned long pci_addr, cpu_phys_addr; - read_pci_config = rtas_token("read-pci-config"); - write_pci_config = rtas_token("write-pci-config"); - ibm_read_pci_config = rtas_token("ibm,read-pci-config"); - ibm_write_pci_config = rtas_token("ibm,write-pci-config"); + np = na + 5; - if (naca->interrupt_controller == IC_OPEN_PIC) { - opprop = (unsigned int *)get_property(find_path_device("/"), - "platform-open-pic", NULL); - } + /* + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + rlen = 0; + hose->io_base_phys = 0; + ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + pci_addr = (unsigned long)ranges[1] << 32 | ranges[2]; + + cpu_phys_addr = ranges[3]; + if (na == 2) + cpu_phys_addr = cpu_phys_addr << 32 | ranges[4]; + + size = (unsigned long)ranges[na+3] << 32 | ranges[na+4]; + + 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); + if (primary) { + pci_io_base = (unsigned long)hose->io_base_virt; + if (find_type_devices("isa")) + isa_io_base = pci_io_base; + } - /* Get the root address word size. */ - ui_ptr = (unsigned int *) get_property(find_path_device("/"), - "#size-cells", NULL); - if (ui_ptr) { - root_addr_size_words = *ui_ptr; - } else { - PPCDBG(PPCDBG_PHBINIT, "\tget #size-cells failed.\n"); - return(-1); + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = pci_addr; + res->start += (unsigned long)hose->io_base_virt - + pci_io_base; + break; + case 2: /* memory space */ + memno = 0; + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + + if (memno == 0) + hose->pci_mem_offset = cpu_phys_addr - pci_addr; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + res->start = cpu_phys_addr; + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; } +} - if (find_type_devices("isa")) { - has_isa = 1; - PPCDBG(PPCDBG_PHBINIT, "\tFound an ISA bus.\n"); - } +static void python_countermeasures(unsigned long addr) +{ + void *chip_regs; + volatile u32 *tmp, i; - index = 0; + /* Python's register file is 1 MB in size. */ + chip_regs = ioremap(addr & ~(0xfffffUL), 0x100000); - /****************************************************************** - * Find all PHB devices and create an object for them. - ******************************************************************/ - for (Pci_Node = find_devices("pci"); Pci_Node != NULL; Pci_Node = Pci_Node->next) { - model = (char *) get_property(Pci_Node, "model", NULL); - if (model != NULL) { - phb = alloc_phb(Pci_Node, model, root_addr_size_words); - if (phb == NULL) return(-1); - } - else { - continue; - } - - /* Get this node's address word size. */ - ui_ptr = (unsigned int *) get_property(Pci_Node, "#size-cells", NULL); - if (ui_ptr) - this_addr_size_words = *ui_ptr; - else - this_addr_size_words = 1; - /* Get this node's address word count. */ - ui_ptr = (unsigned int *) get_property(Pci_Node, "#address-cells", NULL); - if (ui_ptr) - this_addr_count = *ui_ptr; - else - this_addr_count = 3; - - range_stride = this_addr_count + root_addr_size_words + this_addr_size_words; - - memno = 0; - phb->io_base_phys = 0; - - ranges = (unsigned int *) get_property(Pci_Node, "ranges", &rlen); - PPCDBG(PPCDBG_PHBINIT, "\trange_stride = 0x%lx, rlen = 0x%x\n", range_stride, rlen); - - for (i = 0; i < (rlen/sizeof(*ranges)); i+=range_stride) { - /* Put the PCI addr part of the current element into a - * '64' struct. - */ - range = *((struct pci_range64 *)(ranges + i)); - - /* If this is a '32' element, map into a 64 struct. */ - if ((range_stride * sizeof(int)) == - sizeof(struct pci_range32)) { - range.parent_addr = - (unsigned long)(*(ranges + i + 3)); - range.size = - (((unsigned long)(*(ranges + i + 4)))<<32) | - (*(ranges + i + 5)); - } else { - range.parent_addr = - (((unsigned long)(*(ranges + i + 3)))<<32) | - (*(ranges + i + 4)); - range.size = - (((unsigned long)(*(ranges + i + 5)))<<32) | - (*(ranges + i + 6)); - } - - PPCDBG(PPCDBG_PHBINIT, "\trange.parent_addr = 0x%lx\n", - range.parent_addr); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.hi = 0x%lx\n", - range.child_addr.a_hi); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.mid = 0x%lx\n", - range.child_addr.a_mid); - PPCDBG(PPCDBG_PHBINIT, "\trange.child_addr.lo = 0x%lx\n", - range.child_addr.a_lo); - PPCDBG(PPCDBG_PHBINIT, "\trange.size = 0x%lx\n", - range.size); - - res = NULL; - switch ((range.child_addr.a_hi >> 24) & 0x3) { - case 1: /* I/O space */ - PPCDBG(PPCDBG_PHBINIT, "\tIO Space\n"); - phb->io_base_phys = range.parent_addr; - res = &phb->io_resource; - res->name = Pci_Node->full_name; - res->flags = IORESOURCE_IO; - phb->io_base_virt = __ioremap(phb->io_base_phys, range.size, _PAGE_NO_CACHE); - if (!pci_io_base) { - pci_io_base = (unsigned long)phb->io_base_virt; - if (has_isa) - isa_io_base = pci_io_base; - } - res->start = ((((unsigned long) range.child_addr.a_mid) << 32) | (range.child_addr.a_lo)); - res->start += (unsigned long)phb->io_base_virt - pci_io_base; - res->end = res->start + range.size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - phb->pci_io_offset = range.parent_addr - - ((((unsigned long) - range.child_addr.a_mid) << 32) | - (range.child_addr.a_lo)); - PPCDBG(PPCDBG_PHBINIT, "\tpci_io_offset = 0x%lx\n", - phb->pci_io_offset); - break; - case 2: /* mem space */ - PPCDBG(PPCDBG_PHBINIT, "\tMem Space\n"); - phb->pci_mem_offset = range.parent_addr - - ((((unsigned long) - range.child_addr.a_mid) << 32) | - (range.child_addr.a_lo)); - PPCDBG(PPCDBG_PHBINIT, "\tpci_mem_offset = 0x%lx\n", - phb->pci_mem_offset); - if (memno < sizeof(phb->mem_resources)/sizeof(phb->mem_resources[0])) { - res = &(phb->mem_resources[memno]); - ++memno; - res->name = Pci_Node->full_name; - res->flags = IORESOURCE_MEM; - res->start = range.parent_addr; - res->end = range.parent_addr + range.size - 1; - res->parent = NULL; - res->sibling = NULL; - res->child = NULL; - } - break; - } - } - PPCDBG(PPCDBG_PHBINIT, "\tphb->io_base_phys = 0x%lx\n", - phb->io_base_phys); - PPCDBG(PPCDBG_PHBINIT, "\tphb->pci_mem_offset = 0x%lx\n", - phb->pci_mem_offset); + /* + * Firmware doesn't always clear this bit which is critical + * for good performance - Anton + */ - if (naca->interrupt_controller == IC_OPEN_PIC) { - int addr = root_addr_size_words * (index + 2) - 1; - openpic_setup_ISU(index, opprop[addr]); - } - index++; +#define PRG_CL_RESET_VALID 0x00010000 + + tmp = (u32 *)((unsigned long)chip_regs + 0xf6030); + + if (*tmp & PRG_CL_RESET_VALID) { + printk(KERN_INFO "Python workaround: "); + *tmp &= ~PRG_CL_RESET_VALID; + /* + * We must read it back for changes to + * take effect + */ + i = *tmp; + printk("reg0: %x\n", i); } - pci_devs_phb_init(); - return 0; /*Success */ + + iounmap(chip_regs); } -/****************************************************************** - * - * Allocate and partially initialize a structure to represent a PHB. - * - ******************************************************************/ -struct pci_controller * -alloc_phb(struct device_node *dev, char *model, unsigned int addr_size_words) +struct pci_controller *alloc_phb(struct device_node *dev, + unsigned int addr_size_words) { struct pci_controller *phb; unsigned int *ui_ptr = NULL, len; struct reg_property64 reg_struct; int *bus_range; int *buid_vals; + char *model; + enum phb_types phb_type; + + model = (char *)get_property(dev, "model", NULL); + + if (!model) { + printk(KERN_ERR "alloc_phb: phb has no model property\n"); + model = ""; + } - PPCDBG(PPCDBG_PHBINIT, "alloc_phb: %s\n", dev->full_name); - PPCDBG(PPCDBG_PHBINIT, "\tdev = 0x%lx\n", dev); - PPCDBG(PPCDBG_PHBINIT, "\tmodel = 0x%lx\n", model); - PPCDBG(PPCDBG_PHBINIT, "\taddr_size_words = 0x%lx\n", addr_size_words); - /* Found a PHB, now figure out where his registers are mapped. */ ui_ptr = (unsigned int *) get_property(dev, "reg", &len); if (ui_ptr == NULL) { PPCDBG(PPCDBG_PHBINIT, "\tget reg failed.\n"); - return(NULL); + return NULL; } if (addr_size_words == 1) { @@ -389,83 +314,30 @@ reg_struct = *((struct reg_property64 *)ui_ptr); } - PPCDBG(PPCDBG_PHBINIT, "\treg_struct.address = 0x%lx\n", reg_struct.address); - PPCDBG(PPCDBG_PHBINIT, "\treg_struct.size = 0x%lx\n", reg_struct.size); - - /*************************************************************** - * Set chip specific data in the phb, including types & - * register pointers. - ***************************************************************/ - - /**************************************************************** - * Python - ***************************************************************/ if (strstr(model, "Python")) { - void *chip_regs; - volatile u32 *tmp, i; - - PPCDBG(PPCDBG_PHBINIT, "\tCreate python\n"); - - phb = pci_alloc_pci_controller("PHB PY", phb_type_python); - if (phb == NULL) - return NULL; - - /* Python's register file is 1 MB in size. */ - chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), - 0x100000); - - /* - * Firmware doesn't always clear this bit which is critical - * for good performance - Anton - */ - -#define PRG_CL_RESET_VALID 0x00010000 - - tmp = (u32 *)((unsigned long)chip_regs + 0xf6030); - - if (*tmp & PRG_CL_RESET_VALID) { - printk("Python workaround: "); - *tmp &= ~PRG_CL_RESET_VALID; - /* - * We must read it back for changes to - * take effect - */ - i = *tmp; - printk("reg0: %x\n", i); - } + phb_type = phb_type_python; + } else if (strstr(model, "Speedwagon")) { + phb_type = phb_type_speedwagon; + } else if (strstr(model, "Winnipeg")) { + phb_type = phb_type_winnipeg; + } else { + printk(KERN_ERR "alloc_phb: unknown PHB %s\n", model); + phb_type = phb_type_unknown; + } - /*************************************************************** - * Speedwagon - * include Winnipeg as well for the time being. - ***************************************************************/ - } else if ((strstr(model, "Speedwagon")) || - (strstr(model, "Winnipeg"))) { - PPCDBG(PPCDBG_PHBINIT, "\tCreate speedwagon\n"); - phb = pci_alloc_pci_controller("PHB SW", phb_type_speedwagon); - if (phb == NULL) - return NULL; - - phb->local_number = ((reg_struct.address >> 12) & 0xf) - 0x8; - - /*************************************************************** - * Trying to build a known just gets the code in trouble. - ***************************************************************/ - } else { - PPCDBG(PPCDBG_PHBINIT, "\tUnknown PHB Type!\n"); - printk("PCI: Unknown Phb Type!\n"); + phb = pci_alloc_pci_controller(phb_type); + if (phb == NULL) return NULL; - } + + if (phb_type == phb_type_python) + python_countermeasures(reg_struct.address); bus_range = (int *) get_property(dev, "bus-range", &len); if (bus_range == NULL || len < 2 * sizeof(int)) { - PPCDBG(PPCDBG_PHBINIT, "Can't get bus-range for %s\n", dev->full_name); kfree(phb); - return(NULL); + return NULL; } - /*************************************************************** - * Finished with the initialization - ***************************************************************/ phb->first_busno = bus_range[0]; phb->last_busno = bus_range[1]; @@ -473,7 +345,7 @@ phb->ops = &rtas_pci_ops; buid_vals = (int *) get_property(dev, "ibm,fw-phb-id", &len); - + if (buid_vals == NULL) { phb->buid = 0; } else { @@ -486,24 +358,71 @@ panic("pSeries_pci: this system has large bus numbers and the kernel was not\n" "built with the patch that fixes include/linux/pci.h struct pci_bus so\n" "number, primary, secondary and subordinate are ints.\n"); - } - - if (len < 2 * sizeof(int)) - phb->buid = (unsigned long)buid_vals[0]; // Support for new OF that only has 1 integer for buid. - else - phb->buid = (((unsigned long)buid_vals[0]) << 32UL) | - (((unsigned long)buid_vals[1]) & 0xffffffff); - + } + + if (len < 2 * sizeof(int)) + // Support for new OF that only has 1 integer for buid. + phb->buid = (unsigned long)buid_vals[0]; + else + phb->buid = (((unsigned long)buid_vals[0]) << 32UL) | + (((unsigned long)buid_vals[1]) & 0xffffffff); + phb->first_busno += (phb->global_number << 8); phb->last_busno += (phb->global_number << 8); } /* Dump PHB information for Debug */ - PPCDBGCALL(PPCDBG_PHBINIT,dumpPci_Controller(phb) ); + PPCDBGCALL(PPCDBG_PHBINIT, dumpPci_Controller(phb)); return phb; } +unsigned long __init find_and_init_phbs(void) +{ + struct device_node *node; + struct pci_controller *phb; + unsigned int root_size_cells = 0; + unsigned int index; + unsigned int *opprop; + struct device_node *root = find_path_device("/"); + + read_pci_config = rtas_token("read-pci-config"); + write_pci_config = rtas_token("write-pci-config"); + ibm_read_pci_config = rtas_token("ibm,read-pci-config"); + ibm_write_pci_config = rtas_token("ibm,write-pci-config"); + + if (naca->interrupt_controller == IC_OPEN_PIC) { + opprop = (unsigned int *)get_property(root, + "platform-open-pic", NULL); + } + + root_size_cells = prom_n_size_cells(root); + + index = 0; + + for (node = root->child; node != NULL; node = node->sibling) { + if (node->type == NULL || strcmp(node->type, "pci") != 0) + continue; + + phb = alloc_phb(node, root_size_cells); + if (!phb) + continue; + + pci_process_bridge_OF_ranges(phb, node, index == 0); + + if (naca->interrupt_controller == IC_OPEN_PIC) { + int addr = root_size_cells * (index + 2) - 1; + openpic_setup_ISU(index, opprop[addr]); + } + + index++; + } + + pci_devs_phb_init(); + + return 0; +} + void fixup_resources(struct pci_dev *dev) { @@ -581,6 +500,55 @@ } } +void __init pSeries_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *phb = PCI_GET_PHB_PTR(bus); + struct resource *res; + int i; + + if (bus->parent == NULL) { + /* This is a host bridge - fill in its resources */ + phb->bus = bus; + bus->resource[0] = res = &phb->io_resource; + if (!res->flags) + BUG(); /* No I/O resource for this PHB? */ + + for (i = 0; i < 3; ++i) { + res = &phb->mem_resources[i]; + if (!res->flags) { + if (i == 0) + BUG(); /* No memory resource for this PHB? */ + } + bus->resource[i+1] = res; + } + } else { + /* This is a subordinate bridge */ + pci_read_bridge_bases(bus); + + for (i = 0; i < 4; ++i) { + if ((res = bus->resource[i]) == NULL) + continue; + if (!res->flags) + continue; + if (res == pci_find_parent_resource(bus->self, res)) { + /* Transparent resource -- don't try to "fix" it. */ + continue; + } + if (res->flags & IORESOURCE_IO) { + unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; + res->start += offset; + res->end += offset; + } else if (phb->pci_mem_offset + && (res->flags & IORESOURCE_MEM)) { + if (res->start < phb->pci_mem_offset) { + res->start += phb->pci_mem_offset; + res->end += phb->pci_mem_offset; + } + } + } + } +} + static void check_s7a(void) { struct device_node *root; @@ -627,17 +595,6 @@ node=node->parent; } return NULL; -} - -/*********************************************************************** - * ppc64_pcibios_init - * - * Chance to initialize and structures or variable before PCI Bus walk. - * - ***********************************************************************/ -void -pSeries_pcibios_init(void) -{ } /* diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Sat Mar 15 18:40:44 2003 +++ b/arch/ppc64/kernel/pci.c Sat Mar 15 18:40:44 2003 @@ -49,7 +49,6 @@ void fixup_resources(struct pci_dev* dev); void iSeries_pcibios_init(void); -void pSeries_pcibios_init(void); struct pci_controller* hose_head; struct pci_controller** hose_tail = &hose_head; @@ -363,16 +362,33 @@ * Allocate pci_controller(phb) initialized common variables. */ struct pci_controller * __init -pci_alloc_pci_controller(char *model, enum phb_types controller_type) +pci_alloc_pci_controller(enum phb_types controller_type) { struct pci_controller *hose; - PPCDBG(PPCDBG_PHBINIT, "PCI: Allocate pci_controller for %s\n",model); + char *model; + hose = (struct pci_controller *)alloc_bootmem(sizeof(struct pci_controller)); if(hose == NULL) { printk(KERN_ERR "PCI: Allocate pci_controller failed.\n"); return NULL; } memset(hose, 0, sizeof(struct pci_controller)); + + switch(controller_type) { + case phb_type_python: + model = "PHB PY"; + break; + case phb_type_speedwagon: + model = "PHB SW"; + break; + case phb_type_winnipeg: + model = "PHB WP"; + break; + default: + model = "PHB UK"; + break; + } + if(strlen(model) < 8) strcpy(hose->what,model); else @@ -393,9 +409,7 @@ struct pci_bus *bus; int next_busno; -#ifndef CONFIG_PPC_ISERIES - pSeries_pcibios_init(); -#else +#ifdef CONFIG_PPC_ISERIES iSeries_pcibios_init(); #endif @@ -450,54 +464,7 @@ void __init pcibios_fixup_bus(struct pci_bus *bus) { -#ifndef CONFIG_PPC_ISERIES - struct pci_controller *phb = PCI_GET_PHB_PTR(bus); - struct resource *res; - int i; - - if (bus->parent == NULL) { - /* This is a host bridge - fill in its resources */ - phb->bus = bus; - bus->resource[0] = res = &phb->io_resource; - if (!res->flags) - BUG(); /* No I/O resource for this PHB? */ - - for (i = 0; i < 3; ++i) { - res = &phb->mem_resources[i]; - if (!res->flags) { - if (i == 0) - BUG(); /* No memory resource for this PHB? */ - } - bus->resource[i+1] = res; - } - } else { - /* This is a subordinate bridge */ - pci_read_bridge_bases(bus); - - for (i = 0; i < 4; ++i) { - if ((res = bus->resource[i]) == NULL) - continue; - if (!res->flags) - continue; - if (res == pci_find_parent_resource(bus->self, res)) { - /* Transparent resource -- don't try to "fix" it. */ - continue; - } - if (res->flags & IORESOURCE_IO) { - unsigned long offset = (unsigned long)phb->io_base_virt - pci_io_base; - res->start += offset; - res->end += offset; - } else if (phb->pci_mem_offset - && (res->flags & IORESOURCE_MEM)) { - if (res->start < phb->pci_mem_offset) { - res->start += phb->pci_mem_offset; - res->end += phb->pci_mem_offset; - } - } - } - } -#endif - if ( ppc_md.pcibios_fixup_bus ) + if (ppc_md.pcibios_fixup_bus) ppc_md.pcibios_fixup_bus(bus); } diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h --- a/arch/ppc64/kernel/pci.h Sat Mar 15 18:40:39 2003 +++ b/arch/ppc64/kernel/pci.h Sat Mar 15 18:40:39 2003 @@ -14,7 +14,7 @@ extern unsigned long isa_io_base; -extern struct pci_controller* pci_alloc_pci_controller(char *model, enum phb_types controller_type); +extern struct pci_controller* pci_alloc_pci_controller(enum phb_types controller_type); extern struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node); extern struct pci_controller* hose_head; diff -Nru a/arch/ppc64/kernel/pci_dma.c b/arch/ppc64/kernel/pci_dma.c --- a/arch/ppc64/kernel/pci_dma.c Sat Mar 15 18:40:42 2003 +++ b/arch/ppc64/kernel/pci_dma.c Sat Mar 15 18:40:42 2003 @@ -21,6 +21,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Sat Mar 15 18:40:43 2003 +++ b/arch/ppc64/kernel/prom.c Sat Mar 15 18:40:43 2003 @@ -2040,11 +2040,11 @@ if ( bi_recs == NULL || bi_recs->tag != BI_FIRST ) return NULL; - last = (struct bi_record *)bi_recs->data[0]; + last = (struct bi_record *)(long)bi_recs->data[0]; if ( last == NULL || last->tag != BI_LAST ) return NULL; - first = (struct bi_record *)last->data[0]; + first = (struct bi_record *)(long)last->data[0]; if ( first == NULL || first != bi_recs ) return NULL; diff -Nru a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c --- a/arch/ppc64/kernel/rtc.c Sat Mar 15 18:40:42 2003 +++ b/arch/ppc64/kernel/rtc.c Sat Mar 15 18:40:42 2003 @@ -21,6 +21,7 @@ #define RTC_VERSION "1.1" +#include #include #include #include diff -Nru a/arch/ppc64/kernel/sys32.S b/arch/ppc64/kernel/sys32.S --- a/arch/ppc64/kernel/sys32.S Sat Mar 15 18:40:44 2003 +++ b/arch/ppc64/kernel/sys32.S Sat Mar 15 18:40:44 2003 @@ -25,287 +25,3 @@ extsw r4,r4 /* sign extend off_t offset parm */ b .sys_lseek -_GLOBAL(sys32_socketcall) /* r3=call, r4=args */ - cmpwi r3, 1 - blt- .do_einval - cmpwi r3, 17 - bgt- .do_einval - subi r3, r3, 1 /* index into socketcall_table vectors and jmp */ - sldi r3, r3, 3 /* each entry is 8 bytes */ - LOADADDR(r10,.socketcall_table_begin) - ldx r10, r10, r3 - mtctr r10 - bctr - -/* Socket function vectored fix ups for 32 bit */ -_STATIC(do_sys_socket) /* sys_socket(int, int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) - b .sys_socket - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_bind) /* sys_bind(int fd, struct sockaddr *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys_bind - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_connect) /* sys_connect(int, struct sockaddr *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys_connect - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_listen) /* sys_listen(int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) - b .sys_listen - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .previous - -_STATIC(do_sys_accept) /* sys_accept(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_accept - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_getsockname) /* sys_getsockname(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_getsockname - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_getpeername) /* sys_getpeername(int, struct sockaddr *, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) - b .sys_getpeername - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_socketpair) /* sys_socketpair(int, int, int, int *) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) - b .sys_socketpair - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_send) /* sys_send(int, void *, size_t, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) - b .sys_send - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_recv) /* sys_recv(int, void *, size_t, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) - b .sys_recv - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .previous - -_STATIC(do_sys_sendto) /* sys32_sendto(int, u32, compat_size_t, unsigned int, u32, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) -6: lwz r8,20(r10) - b .sys_sendto - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .llong 6b,.do_efault - .previous - -_STATIC(do_sys_recvfrom) /* sys32_recvfrom(int, u32, compat_size_t, unsigned int, u32, u32) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwz r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) -6: lwz r8,20(r10) - b .sys_recvfrom - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .llong 6b,.do_efault - .previous - -_STATIC(do_sys_shutdown) /* sys_shutdown(int, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) - b .sys_shutdown - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .previous - -_STATIC(do_sys_setsockopt) /* sys32_setsockopt(int, int, int, char *, int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) -5: lwa r7,16(r10) - b .sys32_setsockopt - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .previous - -_STATIC(do_sys_getsockopt) /* sys32_getsockopt(int, int, int, u32, u32) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwa r4,4(r10) -3: lwa r5,8(r10) -4: lwz r6,12(r10) -5: lwz r7,16(r10) - b .sys32_getsockopt - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .llong 4b,.do_efault - .llong 5b,.do_efault - .previous - -_STATIC(do_sys_sendmsg) /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys32_sendmsg - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_sys_recvmsg) /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ - mr r10,r4 -1: lwa r3,0(r10) -2: lwz r4,4(r10) -3: lwa r5,8(r10) - b .sys32_recvmsg - .section __ex_table,"a" - .align 3 - .llong 1b,.do_efault - .llong 2b,.do_efault - .llong 3b,.do_efault - .previous - -_STATIC(do_einval) - li r3,-EINVAL - blr - -_STATIC(do_efault) - li r3,-EFAULT - blr - - .balign 8 -_GLOBAL(socketcall_table_begin) - .llong .do_sys_socket - .llong .do_sys_bind - .llong .do_sys_connect - .llong .do_sys_listen - .llong .do_sys_accept - .llong .do_sys_getsockname - .llong .do_sys_getpeername - .llong .do_sys_socketpair - .llong .do_sys_send - .llong .do_sys_recv - .llong .do_sys_sendto - .llong .do_sys_recvfrom - .llong .do_sys_shutdown - .llong .do_sys_setsockopt - .llong .do_sys_getsockopt - .llong .do_sys_sendmsg - .llong .do_sys_recvmsg -_GLOBAL(socketcall_table_end) diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Sat Mar 15 18:40:43 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Sat Mar 15 18:40:43 2003 @@ -15,7 +15,6 @@ */ #include -#include #include #include #include @@ -74,13 +73,11 @@ #include #include -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -114,7 +111,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -206,7 +203,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -227,7 +224,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -248,32 +245,6 @@ return ret; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if(get_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if(put_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - return ret; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - struct ncp_mount_data32_v3 { int version; unsigned int ncp_fd; @@ -2135,708 +2106,6 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, char* optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -struct msghdr32 -{ - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 -{ - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if (kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if (kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if (kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while (ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if (kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if (copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if (copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - *ptr_time32 = *ptr_time; - *(ptr_time32+1) = *(ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32* user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if (uaddr != NULL && err >= 0 && kern_msg.msg_namelen) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - - return len; -} - /* * count32() counts the number of arguments/envelopes */ @@ -3550,13 +2819,6 @@ asmlinkage long sys32_umount(char * name, u32 flags) { return sys_umount(name, (int)flags); -} - -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) - return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg); - return sys32_fcntl(fd, cmd, arg); } struct __sysctl_args32 { diff -Nru a/arch/ppc64/mm/extable.c b/arch/ppc64/mm/extable.c --- a/arch/ppc64/mm/extable.c Sat Mar 15 18:40:41 2003 +++ b/arch/ppc64/mm/extable.c Sat Mar 15 18:40:41 2003 @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include #include #include #include diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S --- a/arch/ppc64/vmlinux.lds.S Sat Mar 15 18:40:43 2003 +++ b/arch/ppc64/vmlinux.lds.S Sat Mar 15 18:40:43 2003 @@ -97,6 +97,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Sat Mar 15 18:40:44 2003 +++ b/arch/ppc64/xmon/xmon.c Sat Mar 15 18:40:44 2003 @@ -1381,16 +1381,23 @@ char *p, *q; n = 0; - if( setjmp(bus_error_jmp) == 0 ){ + if (setjmp(bus_error_jmp) == 0) { debugger_fault_handler = handle_fault; sync(); - p = (char *) adrs; - q = (char *) buf; + p = (char *)adrs; + q = (char *)buf; switch (size) { - case 2: *(short *)q = *(short *)p; break; - case 4: *(int *)q = *(int *)p; break; + case 2: + *(short *)q = *(short *)p; + break; + case 4: + *(int *)q = *(int *)p; + break; + case 8: + *(long *)q = *(long *)p; + break; default: - for( ; n < size; ++n ) { + for( ; n < size; ++n) { *q++ = *p++; sync(); } @@ -1411,16 +1418,23 @@ char *p, *q; n = 0; - if( setjmp(bus_error_jmp) == 0 ){ + if (setjmp(bus_error_jmp) == 0) { debugger_fault_handler = handle_fault; sync(); p = (char *) adrs; q = (char *) buf; switch (size) { - case 2: *(short *)p = *(short *)q; break; - case 4: *(int *)p = *(int *)q; break; + case 2: + *(short *)p = *(short *)q; + break; + case 4: + *(int *)p = *(int *)q; + break; + case 8: + *(long *)p = *(long *)q; + break; default: - for( ; n < size; ++n ) { + for ( ; n < size; ++n) { *p++ = *q++; sync(); } diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Sat Mar 15 18:40:41 2003 +++ b/arch/s390/Kconfig Sat Mar 15 18:40:41 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/s390/vmlinux.lds.S b/arch/s390/vmlinux.lds.S --- a/arch/s390/vmlinux.lds.S Sat Mar 15 18:40:41 2003 +++ b/arch/s390/vmlinux.lds.S Sat Mar 15 18:40:41 2003 @@ -78,6 +78,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(256); __initramfs_start = .; .init.ramfs : { *(.init.initramfs) } diff -Nru a/arch/s390x/Kconfig b/arch/s390x/Kconfig --- a/arch/s390x/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/s390x/Kconfig Sat Mar 15 18:40:42 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config RWSEM_GENERIC_SPINLOCK bool diff -Nru a/arch/s390x/kernel/entry.S b/arch/s390x/kernel/entry.S --- a/arch/s390x/kernel/entry.S Sat Mar 15 18:40:40 2003 +++ b/arch/s390x/kernel/entry.S Sat Mar 15 18:40:40 2003 @@ -452,7 +452,7 @@ .long SYSCALL(sys_umount,sys32_umount_wrapper) .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old lock syscall */ .long SYSCALL(sys_ioctl,sys32_ioctl_wrapper) - .long SYSCALL(sys_fcntl,sys32_fcntl_wrapper) /* 55 */ + .long SYSCALL(sys_fcntl,compat_sys_fcntl_wrapper) /* 55 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* intel mpx syscall */ .long SYSCALL(sys_setpgid,sys32_setpgid_wrapper) .long SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old ulimit syscall */ @@ -499,7 +499,7 @@ .long SYSCALL(sys_statfs,compat_sys_statfs_wrapper) .long SYSCALL(sys_fstatfs,compat_sys_fstatfs_wrapper) /* 100 */ .long SYSCALL(sys_ni_syscall,sys_ni_syscall) - .long SYSCALL(sys_socketcall,sys32_socketcall_wrapper) + .long SYSCALL(sys_socketcall,compat_sys_socketcall_wrapper) .long SYSCALL(sys_syslog,sys32_syslog_wrapper) .long SYSCALL(sys_setitimer,compat_sys_setitimer_wrapper) .long SYSCALL(sys_getitimer,compat_sys_getitimer_wrapper) /* 105 */ @@ -618,7 +618,7 @@ .long SYSCALL(sys_mincore,sys32_mincore_wrapper) .long SYSCALL(sys_madvise,sys32_madvise_wrapper) .long SYSCALL(sys_getdents64,sys32_getdents64_wrapper)/* 220 */ - .long SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper) + .long SYSCALL(sys_ni_syscall,compat_sys_fcntl64_wrapper) .long SYSCALL(sys_readahead,sys32_readahead) .long SYSCALL(sys_ni_syscall,sys32_sendfile64) .long SYSCALL(sys_setxattr,sys32_setxattr_wrapper) diff -Nru a/arch/s390x/kernel/linux32.c b/arch/s390x/kernel/linux32.c --- a/arch/s390x/kernel/linux32.c Sat Mar 15 18:40:43 2003 +++ b/arch/s390x/kernel/linux32.c Sat Mar 15 18:40:43 2003 @@ -834,57 +834,6 @@ return err; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); - -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if(get_compat_flock(&f, (struct compat_flock *)A(arg))) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if (ret) return ret; - if (f.l_start >= 0x7fffffffUL || - f.l_start + f.l_len >= 0x7fffffffUL) - return -EOVERFLOW; - if(put_compat_flock(&f, (struct compat_flock *)A(arg))) - return -EFAULT; - return 0; - } - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if(get_compat_flock(&f, (struct compat_flock *)A(arg))) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if (ret) return ret; - return 0; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) - return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg); - return sys32_fcntl(fd, cmd, arg); -} - extern asmlinkage long sys_truncate(const char * path, unsigned long length); extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); @@ -904,13 +853,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { unsigned long tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -925,7 +872,7 @@ */ if (!count) return 0; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) return -EFAULT; if (count > UIO_MAXIOV) return -EINVAL; @@ -996,7 +943,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; long ret = -EBADF; @@ -1014,7 +961,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret = -EBADF; @@ -1867,740 +1814,6 @@ return ret; } -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - switch (kcmsg32->cmsg_type) { - /* - * The timestamp type's data needs to be converted - * from 64-bit time values to 32-bit time values - */ - case SO_TIMESTAMP: { - compat_time_t* ptr_time32 = CMSG32_DATA(kcmsg32); - __kernel_time_t* ptr_time = CMSG_DATA(ucmsg); - get_user(*ptr_time32, ptr_time); - get_user(*(ptr_time32+1), ptr_time+1); - kcmsg32->cmsg_len -= 2*(sizeof(__kernel_time_t) - - sizeof(compat_time_t)); - } - default:; - } - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(kcmsg32->cmsg_len)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -/* - * BSD sendmsg interface - */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; - } - else if (ctl_len < sizeof(struct cmsghdr)) - { - /* to get same error message as on 31 bit native */ - err = EOPNOTSUPP; - goto out_freeiov; - } - err = -EFAULT; - if (cmsghdr_from_user32_to_kern(&msg_sys, ctl_buf, ctl_len)) - goto out_freectl; -// msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -static __inline__ void -scm_recv32(struct socket *sock, struct msghdr *msg, - struct scm_cookie *scm, int flags, unsigned long cmsg_ptr) -{ - if(!msg->msg_control) - { - if(sock->passcred || scm->fp) - msg->msg_flags |= MSG_CTRUNC; - scm_destroy(scm); - return; - } - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) msg->msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(msg, cmsg_ptr); - /* Wheee... */ - if(sock->passcred) - put_cmsg32(msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(scm->creds), &scm->creds); - if(!scm->fp) - return; - - scm_detach_fds32(msg, scm); -} - -static int -sock_recvmsg32(struct socket *sock, struct msghdr *msg, int size, int flags, - unsigned long cmsg_ptr) -{ - struct sock_iocb *si; - struct kiocb iocb; - - init_sync_kiocb(&iocb, NULL); - - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = msg; - si->size = size; - si->flags = flags; - - memset(si->scm, 0, sizeof(*si->scm)); - - size = sock->ops->recvmsg(&iocb, sock, msg, size, flags, si->scm); - if (size >= 0) - scm_recv32(sock, msg, si->scm, flags, cmsg_ptr); - - if (-EIOCBQUEUED == size) - size = wait_on_sync_kiocb(&iocb); - - return size; -} - -/* - * BSD recvmsg interface - */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; - - err=-EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; - - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; - - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg32(sock, &msg_sys, total_len, flags, cmsg_ptr); - if (err < 0) - goto out_freeiov; - len = err; - - if (uaddr != NULL && - /* in order to get same error message as on native 31 bit */ - msg_sys.msg_namelen > 0) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((compat_size_t) ((unsigned long)msg_sys.msg_control - cmsg_ptr), &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - if (level == SOL_SOCKET && - (optname == SO_SNDTIMEO || optname == SO_RCVTIMEO)) { - long ret; - struct timeval tmp; - mm_segment_t old_fs; - - if (get_tv32(&tmp, (struct compat_timeval *)optval )) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, (char *) &tmp, sizeof(struct timeval)); - set_fs(old_fs); - return ret; - } - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - extern void check_pending(int signum); /* @@ -3663,104 +2876,6 @@ error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; -} - -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen); -extern asmlinkage long sys_listen(int fd, int backlog); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]); -extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags, - struct sockaddr *addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags, - struct sockaddr *addr, int *addr_len); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen); - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - - if (call < SYS_SOCKET || call > SYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - switch(call) { - case SYS_SOCKET: - ret = sys_socket(a[0], a[1], a[2]); - break; - case SYS_BIND: - ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a[0], a[1]); - break; - case SYS_ACCEPT: - ret = sys_accept(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]), - (int *) A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]); - break; - case SYS_RECV: - ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) ); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a[0], a[1]); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) ); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]), - a[2]); - break; - default: - ret = EINVAL; - break; - } - return ret; } extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, diff -Nru a/arch/s390x/kernel/linux32.h b/arch/s390x/kernel/linux32.h --- a/arch/s390x/kernel/linux32.h Sat Mar 15 18:40:44 2003 +++ b/arch/s390x/kernel/linux32.h Sat Mar 15 18:40:44 2003 @@ -21,10 +21,6 @@ __s32 msgtyp; }; -#define F_GETLK64 12 -#define F_SETLK64 13 -#define F_SETLKW64 14 - struct old_sigaction32 { __u32 sa_handler; /* Really a pointer, but need to deal with 32 bits */ compat_old_sigset_t sa_mask; /* A 32 bit mask */ diff -Nru a/arch/s390x/kernel/wrapper32.S b/arch/s390x/kernel/wrapper32.S --- a/arch/s390x/kernel/wrapper32.S Sat Mar 15 18:40:44 2003 +++ b/arch/s390x/kernel/wrapper32.S Sat Mar 15 18:40:44 2003 @@ -227,12 +227,12 @@ llgfr %r4,%r4 # unsigned int jg sys32_ioctl # branch to system call - .globl sys32_fcntl_wrapper -sys32_fcntl_wrapper: + .globl compat_sys_fcntl_wrapper +compat_sys_fcntl_wrapper: llgfr %r2,%r2 # unsigned int llgfr %r3,%r3 # unsigned int llgfr %r4,%r4 # unsigned long - jg sys32_fcntl # branch to system call + jg compat_sys_fcntl # branch to system call .globl sys32_setpgid_wrapper sys32_setpgid_wrapper: @@ -452,11 +452,11 @@ llgtr %r3,%r3 # struct compat_statfs * jg compat_sys_fstatfs # branch to system call - .globl sys32_socketcall_wrapper -sys32_socketcall_wrapper: + .globl compat_sys_socketcall_wrapper +compat_sys_socketcall_wrapper: lgfr %r2,%r2 # int llgtr %r3,%r3 # u32 * - jg sys32_socketcall # branch to system call + jg compat_sys_socketcall # branch to system call .globl sys32_syslog_wrapper sys32_syslog_wrapper: @@ -1050,12 +1050,12 @@ llgfr %r4,%r4 # unsigned int jg sys_getdents64 # branch to system call - .globl sys32_fcntl64_wrapper -sys32_fcntl64_wrapper: + .globl compat_sys_fcntl64_wrapper +compat_sys_fcntl64_wrapper: llgfr %r2,%r2 # unsigned int llgfr %r3,%r3 # unsigned int llgfr %r4,%r4 # unsigned long - jg sys32_fcntl64 # branch to system call + jg compat_sys_fcntl64 # branch to system call .globl sys32_stat64_wrapper sys32_stat64_wrapper: diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Sat Mar 15 18:40:41 2003 +++ b/arch/s390x/vmlinux.lds.S Sat Mar 15 18:40:41 2003 @@ -78,6 +78,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(256); __initramfs_start = .; .init.ramfs : { *(.init.initramfs) } diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Sat Mar 15 18:40:45 2003 +++ b/arch/sh/Kconfig Sat Mar 15 18:40:45 2003 @@ -18,10 +18,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c --- a/arch/sh/kernel/irq.c Sat Mar 15 18:40:41 2003 +++ b/arch/sh/kernel/irq.c Sat Mar 15 18:40:41 2003 @@ -90,6 +90,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (j=0; jtypename); @@ -108,6 +110,8 @@ for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +unlock: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } return 0; } diff -Nru a/arch/sh/vmlinux.lds.S b/arch/sh/vmlinux.lds.S --- a/arch/sh/vmlinux.lds.S Sat Mar 15 18:40:42 2003 +++ b/arch/sh/vmlinux.lds.S Sat Mar 15 18:40:42 2003 @@ -68,6 +68,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; __machvec_start = .; .machvec.init : { *(.machvec.init) } __machvec_end = .; diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Sat Mar 15 18:40:39 2003 +++ b/arch/sparc/Kconfig Sat Mar 15 18:40:39 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool default y diff -Nru a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c --- a/arch/sparc/kernel/irq.c Sat Mar 15 18:40:39 2003 +++ b/arch/sparc/kernel/irq.c Sat Mar 15 18:40:39 2003 @@ -104,6 +104,7 @@ { int i; struct irqaction * action; + unsigned long flags; #ifdef CONFIG_SMP int j; #endif @@ -114,9 +115,10 @@ return show_sun4d_interrupts(p, v); } for (i = 0 ; i < NR_IRQS ; i++) { + local_irq_save(flags); action = *(i + irq_action); if (!action) - continue; + goto skip; seq_printf(p, "%3d: ", i); #ifndef CONFIG_SMP seq_printf(p, "%10u ", kstat_irqs(i)); @@ -136,6 +138,8 @@ action->name); } seq_putc(p, '\n'); +skip: + local_irq_restore(flags); } return 0; } diff -Nru a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c --- a/arch/sparc/kernel/sys_sunos.c Sat Mar 15 18:40:41 2003 +++ b/arch/sparc/kernel/sys_sunos.c Sat Mar 15 18:40:41 2003 @@ -1107,38 +1107,16 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, struct sockaddr *sa, int *addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd,sa,addrlen),fd); if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Sat Mar 15 18:40:42 2003 +++ b/arch/sparc/kernel/systbls.S Sat Mar 15 18:40:42 2003 @@ -110,7 +110,7 @@ .long sys_getitimer, sys_gethostname, sys_sethostname .long sunos_getdtablesize, sys_dup2, sunos_nop .long sys_fcntl, sunos_select, sunos_nop - .long sys_fsync, sys_setpriority, sunos_socket + .long sys_fsync, sys_setpriority, sys_socket .long sys_connect, sunos_accept /*100*/ .long sys_getpriority, sunos_send, sunos_recv .long sunos_nosys, sys_bind, sunos_setsockopt diff -Nru a/arch/sparc/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S --- a/arch/sparc/vmlinux.lds.S Sat Mar 15 18:40:39 2003 +++ b/arch/sparc/vmlinux.lds.S Sat Mar 15 18:40:39 2003 @@ -55,6 +55,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Sat Mar 15 18:40:44 2003 +++ b/arch/sparc64/Kconfig Sat Mar 15 18:40:44 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - source "init/Kconfig" @@ -151,9 +147,14 @@ If in doubt, say N. config CPU_FREQ_TABLE - tristate + tristate "CPU frequency table helpers" + depends on CPU_FREQ default y + help + Many CPUFreq drivers use these helpers, so only say N here if + the CPUFreq driver of your choice doesn't need these helpers. + If in doubt, say Y. config US3_FREQ tristate "UltraSPARC-III CPU Frequency driver" diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Sat Mar 15 18:40:41 2003 +++ b/arch/sparc64/defconfig Sat Mar 15 18:40:41 2003 @@ -39,9 +39,11 @@ # CONFIG_PREEMPT is not set CONFIG_NR_CPUS=4 CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_PROC_INTF=y CONFIG_CPU_FREQ_TABLE=y CONFIG_US3_FREQ=m +CONFIG_CPU_FREQ_PROC_INTF=y +CONFIG_CPU_FREQ_GOV_USERSPACE=m +# CONFIG_CPU_FREQ_24_API is not set CONFIG_SPARC64=y CONFIG_HOTPLUG=y CONFIG_HAVE_DEC_LOCK=y @@ -354,6 +356,8 @@ CONFIG_XFRM_USER=m CONFIG_IPV6=m CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m # # SCTP Configuration (EXPERIMENTAL) @@ -872,6 +876,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set CONFIG_USB_WACOM=m +CONFIG_USB_KBTAB=m # CONFIG_USB_POWERMATE is not set # CONFIG_USB_XPAD is not set @@ -928,6 +933,7 @@ # CONFIG_USB_SERIAL_EDGEPORT_TI is not set CONFIG_USB_SERIAL_KEYSPAN_PDA=m CONFIG_USB_SERIAL_KEYSPAN=m +# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set # CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set @@ -938,6 +944,7 @@ # CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set # CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set +# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set CONFIG_USB_SERIAL_KLSI=m # CONFIG_USB_SERIAL_KOBIL_SCT is not set CONFIG_USB_SERIAL_MCT_U232=m diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c --- a/arch/sparc64/kernel/ioctl32.c Sat Mar 15 18:40:44 2003 +++ b/arch/sparc64/kernel/ioctl32.c Sat Mar 15 18:40:44 2003 @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -4850,6 +4851,7 @@ COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) /* DEVFS */ COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV) COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK) diff -Nru a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c --- a/arch/sparc64/kernel/pci_common.c Sat Mar 15 18:40:40 2003 +++ b/arch/sparc64/kernel/pci_common.c Sat Mar 15 18:40:40 2003 @@ -78,20 +78,6 @@ return 0; } -/* Remove a PCI device from the device trees, then - * free it up. Note that this must run before - * the device's resources are registered because we - * do not handle unregistering them here. - */ -static void pci_device_delete(struct pci_dev *pdev) -{ - list_del(&pdev->global_list); - list_del(&pdev->bus_list); - - /* Ok, all references are gone, free it up. */ - kfree(pdev); -} - /* Older versions of OBP on PCI systems encode 64-bit MEM * space assignments incorrectly, this fixes them up. We also * take the opportunity here to hide other kinds of bogus @@ -164,7 +150,7 @@ * second EBUS/HappyMeal pair if the external * connector for it is not present. */ - pci_device_delete(pdev); + pci_remove_bus_device(pdev); return; } diff -Nru a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c --- a/arch/sparc64/kernel/smp.c Sat Mar 15 18:40:39 2003 +++ b/arch/sparc64/kernel/smp.c Sat Mar 15 18:40:39 2003 @@ -1137,16 +1137,16 @@ do { sparc64_do_profile(regs); if (!--prof_counter(cpu)) { - if (cpu == boot_cpu_id) { - irq_enter(); + irq_enter(); + if (cpu == boot_cpu_id) { kstat_cpu(cpu).irqs[0]++; timer_tick_interrupt(regs); - - irq_exit(); } update_process_times(user); + + irq_exit(); prof_counter(cpu) = prof_multiplier(cpu); } diff -Nru a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c --- a/arch/sparc64/kernel/sparc64_ksyms.c Sat Mar 15 18:40:44 2003 +++ b/arch/sparc64/kernel/sparc64_ksyms.c Sat Mar 15 18:40:44 2003 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,11 @@ EXPORT_SYMBOL_NOVERS(mcount); #endif +/* Uniprocessor clock frequency */ +#ifndef CONFIG_SMP +EXPORT_SYMBOL(up_clock_tick); +#endif + /* Per-CPU information table */ EXPORT_SYMBOL(cpu_data); @@ -243,6 +249,7 @@ /* Solaris/SunOS binary compatibility */ EXPORT_SYMBOL(_sigpause_common); +EXPORT_SYMBOL(verify_compat_iovec); /* Should really be in linux/kernel/ksyms.c */ EXPORT_SYMBOL(dump_thread); diff -Nru a/arch/sparc64/kernel/sys32.S b/arch/sparc64/kernel/sys32.S --- a/arch/sparc64/kernel/sys32.S Sat Mar 15 18:40:40 2003 +++ b/arch/sparc64/kernel/sys32.S Sat Mar 15 18:40:40 2003 @@ -202,38 +202,38 @@ nop nop nop -do_sys_setsockopt: /* sys32_setsockopt(int, int, int, char *, int) */ +do_sys_setsockopt: /* compat_sys_setsockopt(int, int, int, char *, int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_setsockopt), %g1 + sethi %hi(compat_sys_setsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 ldswa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_setsockopt), %g0 + jmpl %g1 + %lo(compat_sys_setsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_getsockopt: /* sys32_getsockopt(int, int, int, u32, u32) */ +do_sys_getsockopt: /* compat_sys_getsockopt(int, int, int, u32, u32) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_getsockopt), %g1 + sethi %hi(compat_sys_getsockopt), %g1 ldswa [%o1 + 0x8] %asi, %o2 lduwa [%o1 + 0xc] %asi, %o3 lduwa [%o1 + 0x10] %asi, %o4 - jmpl %g1 + %lo(sys32_getsockopt), %g0 + jmpl %g1 + %lo(compat_sys_getsockopt), %g0 ldswa [%o1 + 0x4] %asi, %o1 nop -do_sys_sendmsg: /* sys32_sendmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_sendmsg: /* compat_sys_sendmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_sendmsg), %g1 + sethi %hi(compat_sys_sendmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_sendmsg), %g0 + jmpl %g1 + %lo(compat_sys_sendmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop nop -do_sys_recvmsg: /* sys32_recvmsg(int, struct msghdr32 *, unsigned int) */ +do_sys_recvmsg: /* compat_sys_recvmsg(int, struct compat_msghdr *, unsigned int) */ ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys32_recvmsg), %g1 + sethi %hi(compat_sys_recvmsg), %g1 lduwa [%o1 + 0x8] %asi, %o2 - jmpl %g1 + %lo(sys32_recvmsg), %g0 + jmpl %g1 + %lo(compat_sys_recvmsg), %g0 lduwa [%o1 + 0x4] %asi, %o1 nop nop diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Sat Mar 15 18:40:42 2003 +++ b/arch/sparc64/kernel/sys_sparc32.c Sat Mar 15 18:40:42 2003 @@ -63,8 +63,6 @@ #include #include -#include - /* Use this to get at 32-bit user passed pointers. */ /* Things to consider: the low-level assembly stub does srl x, 0, x for first four arguments, so if you have @@ -806,41 +804,6 @@ return err; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); - -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if (get_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if (ret) return ret; - if (put_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - return 0; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - if (cmd >= F_GETLK64 && cmd <= F_SETLKW64) - return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg); - return sys32_fcntl(fd, cmd, arg); -} - extern asmlinkage long sys_truncate(const char * path, unsigned long length); extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); @@ -860,13 +823,11 @@ return sys_ftruncate(fd, (high << 32) | low); } -struct iovec32 { u32 iov_base; compat_size_t iov_len; }; - typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); static long do_readv_writev32(int type, struct file *file, - const struct iovec32 *vector, u32 count) + const struct compat_iovec *vector, u32 count) { compat_ssize_t tot_len; struct iovec iovstack[UIO_FASTIOV]; @@ -900,7 +861,7 @@ goto out; } retval = -EFAULT; - if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count)) + if (verify_area(VERIFY_READ, vector, sizeof(struct compat_iovec)*count)) goto out; /* @@ -992,7 +953,7 @@ return retval; } -asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1015,7 +976,7 @@ return ret; } -asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count) +asmlinkage long sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct file *file; int ret; @@ -1905,773 +1866,6 @@ set_fs (old_fs); if (put_rusage (ru, &r)) return -EFAULT; return ret; -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct msghdr32 { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - compat_size_t msg_iovlen; - u32 msg_control; - compat_size_t msg_controllen; - unsigned msg_flags; -}; - -struct cmsghdr32 { - compat_size_t cmsg_len; - int cmsg_level; - int cmsg_type; -}; - -/* Bleech... */ -#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) -#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) - -#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) - -#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) -#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) -#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) - -#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ - (struct cmsghdr32 *)(ctl) : \ - (struct cmsghdr32 *)NULL) -#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) - -__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, - struct cmsghdr32 *__cmsg, int __cmsg_len) -{ - struct cmsghdr32 * __ptr; - - __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + - CMSG32_ALIGN(__cmsg_len)); - if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) - return NULL; - - return __ptr; -} - -__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, - struct cmsghdr32 *__cmsg, - int __cmsg_len) -{ - return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, - __cmsg, __cmsg_len); -} - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - if (kcmsg32->cmsg_level == SOL_SOCKET && - kcmsg32->cmsg_type == SO_TIMESTAMP) { - struct timeval tv; - struct compat_timeval *tv32; - - if (clen64 != CMSG_LEN(sizeof(struct timeval))) { - kfree(workbuf); - goto fail; - } - copy_from_user(&tv, CMSG_DATA(ucmsg), sizeof(tv)); - tv32 = (struct compat_timeval *) CMSG32_DATA(kcmsg32); - tv32->tv_sec = tv.tv_sec; - tv32->tv_usec = tv.tv_usec; - clen32 = sizeof(*tv32) + - CMSG32_ALIGN(sizeof(struct cmsghdr32)); - } else { - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - } - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_netfilter_replace(int fd, int level, int optname, - char *optval, int optlen) -{ - struct ipt_replace32 { - char name[IPT_TABLE_MAXNAMELEN]; - __u32 valid_hooks; - __u32 num_entries; - __u32 size; - __u32 hook_entry[NF_IP_NUMHOOKS]; - __u32 underflow[NF_IP_NUMHOOKS]; - __u32 num_counters; - __u32 counters; - struct ipt_entry entries[0]; - } *repl32 = (struct ipt_replace32 *)optval; - struct ipt_replace *krepl; - struct ipt_counters *counters32; - __u32 origsize; - unsigned int kreplsize, kcountersize; - mm_segment_t old_fs; - int ret; - - if (optlen < sizeof(repl32)) - return -EINVAL; - - if (copy_from_user(&origsize, - &repl32->size, - sizeof(origsize))) - return -EFAULT; - - kreplsize = sizeof(*krepl) + origsize; - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - - /* Hack: Causes ipchains to give correct error msg --RR */ - if (optlen != kreplsize) - return -ENOPROTOOPT; - - krepl = (struct ipt_replace *)kmalloc(kreplsize, GFP_KERNEL); - if (krepl == NULL) - return -ENOMEM; - - if (copy_from_user(krepl, optval, kreplsize)) { - kfree(krepl); - return -EFAULT; - } - - counters32 = (struct ipt_counters *)AA( - ((struct ipt_replace32 *)krepl)->counters); - - kcountersize = krepl->num_counters * sizeof(struct ipt_counters); - krepl->counters = (struct ipt_counters *)kmalloc( - kcountersize, GFP_KERNEL); - if (krepl->counters == NULL) { - kfree(krepl); - return -ENOMEM; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)krepl, kreplsize); - set_fs(old_fs); - - if (ret == 0 && - copy_to_user(counters32, krepl->counters, kcountersize)) - ret = -EFAULT; - - kfree(krepl->counters); - kfree(krepl); - - return ret; -} - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage int sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == IPT_SO_SET_REPLACE) - return do_netfilter_replace(fd, level, optname, - optval, optlen); - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - char *optval, int *optlen); - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage int sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); } extern void check_pending(int signum); diff -Nru a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c --- a/arch/sparc64/kernel/sys_sunos32.c Sat Mar 15 18:40:42 2003 +++ b/arch/sparc64/kernel/sys_sunos32.c Sat Mar 15 18:40:42 2003 @@ -54,6 +54,7 @@ #include /* For SOCKET_I */ +#include #include /* Use this to get at 32-bit user passed pointers. */ @@ -1253,26 +1254,9 @@ return ret; } -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -asmlinkage int sunos_socket(int family, int type, int protocol) -{ - int ret, one = 1; - - ret = sys_socket(family, type, protocol); - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: - return ret; -} - asmlinkage int sunos_accept(int fd, u32 sa, u32 addrlen) { - int ret, one = 1; + int ret; while (1) { ret = check_nonblock(sys_accept(fd, (struct sockaddr *)A(sa), @@ -1280,12 +1264,6 @@ if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) break; } - if (ret < 0) - goto out; - - sys_setsockopt(ret, SOL_SOCKET, SO_BSDCOMPAT, - (char *)&one, sizeof(one)); -out: return ret; } @@ -1324,8 +1302,6 @@ extern asmlinkage int sys_setsockopt(int fd, int level, int optname, char *optval, int optlen); -extern asmlinkage int sys32_getsockopt(int fd, int level, int optname, - u32 optval, u32 optlen); asmlinkage int sunos_setsockopt(int fd, int level, int optname, u32 optval, int optlen) @@ -1353,6 +1329,6 @@ if (tr_opt >=2 && tr_opt <= 6) tr_opt += 30; } - ret = sys32_getsockopt(fd, level, tr_opt, optval, optlen); + ret = compat_sys_getsockopt(fd, level, tr_opt, (void*)(unsigned long)optval, (void*)(unsigned long)optlen); return ret; } diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Sat Mar 15 18:40:41 2003 +++ b/arch/sparc64/kernel/systbls.S Sat Mar 15 18:40:41 2003 @@ -37,7 +37,7 @@ .word sys_madvise, sys_vhangup, sys32_truncate64, sys_mincore, sys32_getgroups16 /*80*/ .word sys32_setgroups16, sys_getpgrp, sys_setgroups, compat_sys_setitimer, sys32_ftruncate64 .word sys_swapon, compat_sys_getitimer, sys_setuid, sys_sethostname, sys_setgid -/*90*/ .word sys_dup2, sys_setfsuid, sys32_fcntl, sys32_select, sys_setfsgid +/*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid .word sys_fsync, sys_setpriority32, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall /*100*/ .word sys_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending .word sys32_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid @@ -50,7 +50,7 @@ /*140*/ .word sys32_sendfile64, sys_nis_syscall, compat_sys_futex, sys_gettid, sys32_getrlimit .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write /*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_getdents64 - .word sys32_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount + .word compat_sys_fcntl64, sys_ni_syscall, compat_sys_statfs, compat_sys_fstatfs, sys_oldumount /*160*/ .word sys32_sched_setaffinity, sys32_sched_getaffinity, sys_getdomainname, sys_setdomainname, sys_nis_syscall .word sys_quotactl, sys_set_tid_address, sys32_mount, sys_ustat, sys_setxattr /*170*/ .word sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr, sys32_getdents @@ -172,14 +172,14 @@ .word compat_sys_setitimer, sunos_nosys, sys_swapon .word compat_sys_getitimer, sys_gethostname, sys_sethostname .word sunos_getdtablesize, sys_dup2, sunos_nop - .word sys32_fcntl, sunos_select, sunos_nop - .word sys_fsync, sys_setpriority32, sunos_socket + .word compat_sys_fcntl, sunos_select, sunos_nop + .word sys_fsync, sys_setpriority32, sys_socket .word sys_connect, sunos_accept /*100*/ .word sys_getpriority, sunos_send, sunos_recv .word sunos_nosys, sys_bind, sunos_setsockopt .word sys_listen, sunos_nosys, sunos_sigaction .word sunos_sigblock, sunos_sigsetmask, sys_sigpause - .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg + .word sys32_sigstack, compat_sys_recvmsg, compat_sys_sendmsg .word sunos_nosys, sys32_gettimeofday, sys32_getrusage .word sunos_getsockopt, sunos_nosys, sunos_readv .word sunos_writev, sys32_settimeofday, sys32_fchown16 diff -Nru a/arch/sparc64/kernel/us3_cpufreq.c b/arch/sparc64/kernel/us3_cpufreq.c --- a/arch/sparc64/kernel/us3_cpufreq.c Sat Mar 15 18:40:39 2003 +++ b/arch/sparc64/kernel/us3_cpufreq.c Sat Mar 15 18:40:39 2003 @@ -79,9 +79,9 @@ void *data) { struct cpufreq_freqs *freq = data; +#ifdef CONFIG_SMP unsigned int cpu = freq->cpu; -#ifdef CONFIG_SMP if (!us3_freq_table[cpu].ref_freq) { us3_freq_table[cpu].ref_freq = freq->old; us3_freq_table[cpu].udelay_val_ref = cpu_data[cpu].udelay_val; @@ -276,6 +276,7 @@ driver->target = us3freq_target; driver->init = us3freq_cpu_init; driver->exit = us3freq_cpu_exit; + driver->owner = THIS_MODULE, strcpy(driver->name, "UltraSPARC-III"); cpufreq_us3_driver = driver; diff -Nru a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c --- a/arch/sparc64/solaris/socket.c Sat Mar 15 18:40:43 2003 +++ b/arch/sparc64/solaris/socket.c Sat Mar 15 18:40:43 2003 @@ -267,35 +267,6 @@ unsigned char cmsg_data[0]; }; -struct iovec32 { - u32 iov_base; - u32 iov_len; -}; - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, struct sol_nmsghdr *umsg) { @@ -321,42 +292,6 @@ return err; } -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr *user_msg, unsigned user_flags) { struct socket *sock; @@ -371,7 +306,7 @@ return -EFAULT; if(kern_msg.msg_iovlen > UIO_MAXIOV) return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + err = verify_compat_iovec(&kern_msg, iov, address, VERIFY_READ); if (err < 0) goto out; total_len = err; @@ -439,7 +374,7 @@ uaddr = kern_msg.msg_name; uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); + err = verify_compat_iovec(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) goto out; total_len = err; diff -Nru a/arch/sparc64/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Sat Mar 15 18:40:44 2003 +++ b/arch/sparc64/vmlinux.lds.S Sat Mar 15 18:40:44 2003 @@ -61,6 +61,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(8192); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/arch/um/Kconfig b/arch/um/Kconfig --- a/arch/um/Kconfig Sat Mar 15 18:40:42 2003 +++ b/arch/um/Kconfig Sat Mar 15 18:40:42 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - mainmenu "Linux/Usermode Kernel Configuration" config ISA diff -Nru a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c --- a/arch/um/drivers/stdio_console.c Sat Mar 15 18:40:40 2003 +++ b/arch/um/drivers/stdio_console.c Sat Mar 15 18:40:40 2003 @@ -214,12 +214,13 @@ console_device, console_setup, CON_PRINTBUFFER); -void stdio_console_init(void) +static void __init stdio_console_init(void) { INIT_LIST_HEAD(&vts[0].chan_list); list_add(&init_console_chan.list, &vts[0].chan_list); register_console(&stdiocons); } +console_initcall(stdio_console_init); static int console_chan_setup(char *str) { diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c --- a/arch/um/drivers/ubd_kern.c Sat Mar 15 18:40:42 2003 +++ b/arch/um/drivers/ubd_kern.c Sat Mar 15 18:40:42 2003 @@ -673,7 +673,7 @@ static int ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); - return(0); + return 0; } __initcall(ubd_mc_init); @@ -682,29 +682,24 @@ { int i; - ubd_dir_handle = devfs_mk_dir (NULL, "ubd", NULL); - if(register_blkdev(MAJOR_NR, "ubd", &ubd_blops)){ - printk(KERN_ERR "ubd: unable to get major %d\n", MAJOR_NR); + ubd_dir_handle = devfs_mk_dir(NULL, "ubd", NULL); + if (register_blkdev(MAJOR_NR, "ubd")) return -1; - } blk_init_queue(&ubd_queue, do_ubd_request, &ubd_io_lock); elevator_init(&ubd_queue, &elevator_noop); - if(fake_major != 0){ + if (fake_major != 0) { char name[sizeof("ubd_nnn\0")]; snprintf(name, sizeof(name), "ubd_%d", fake_major); ubd_fake_dir_handle = devfs_mk_dir(NULL, name, NULL); - if(register_blkdev(fake_major, "ubd", &ubd_blops)){ - printk(KERN_ERR "ubd: unable to get major %d\n", - fake_major); + if (register_blkdev(fake_major, "ubd")) return -1; - } } - for(i = 0; i < MAX_DEV; i++) + for (i = 0; i < MAX_DEV; i++) ubd_add(i); - return(0); + return 0; } late_initcall(ubd_init); diff -Nru a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c --- a/arch/um/kernel/mem.c Sat Mar 15 18:40:41 2003 +++ b/arch/um/kernel/mem.c Sat Mar 15 18:40:41 2003 @@ -154,8 +154,8 @@ unsigned long vaddr; vaddr = start; - i = __pgd_offset(vaddr); - j = __pmd_offset(vaddr); + i = pgd_index(vaddr); + j = pmd_index(vaddr); pgd = pgd_base + i; for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) { @@ -257,7 +257,7 @@ vaddr = PKMAP_BASE; fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, swapper_pg_dir); - pgd = swapper_pg_dir + __pgd_offset(vaddr); + pgd = swapper_pg_dir + pgd_index(vaddr); pmd = pmd_offset(pgd, vaddr); pte = pte_offset_kernel(pmd, vaddr); pkmap_page_table = pte; diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Sat Mar 15 18:40:41 2003 +++ b/arch/v850/Kconfig Sat Mar 15 18:40:41 2003 @@ -10,9 +10,6 @@ config MMU bool default n -config SWAP - bool - default n config UID16 bool default n diff -Nru a/arch/v850/kernel/irq.c b/arch/v850/kernel/irq.c --- a/arch/v850/kernel/irq.c Sat Mar 15 18:40:43 2003 +++ b/arch/v850/kernel/irq.c Sat Mar 15 18:40:43 2003 @@ -78,6 +78,7 @@ { int i; struct irqaction * action; + unsigned long flags; seq_puts(p, " "); for (i=0; i < 1 /*smp_num_cpus*/; i++) @@ -87,10 +88,10 @@ for (i = 0 ; i < NR_IRQS ; i++) { int j, count, num; const char *type_name = irq_desc[i].handler->typename; - + spin_lock_irqsave(&irq_desc[j].lock, flags); action = irq_desc[i].action; if (!action) - continue; + goto skip; count = 0; num = -1; @@ -108,11 +109,13 @@ seq_printf(p, " %*s%d", 14 - prec, type_name, num); } else seq_printf(p, " %14s", type_name); + seq_printf(p, " %s", action->name); - for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[j].lock, flags); } seq_printf(p, "ERR: %10lu\n", irq_err_count); return 0; diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Sat Mar 15 18:40:44 2003 +++ b/arch/x86_64/Kconfig Sat Mar 15 18:40:44 2003 @@ -24,10 +24,6 @@ bool default y -config SWAP - bool - default y - config ISA bool diff -Nru a/arch/x86_64/boot/Makefile b/arch/x86_64/boot/Makefile --- a/arch/x86_64/boot/Makefile Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/boot/Makefile Sat Mar 15 18:40:41 2003 @@ -62,33 +62,33 @@ # Set this if you want to pass append arguments to the zdisk/fdimage kernel FDARGS = -$(obj)/mtools.conf: $(obj)/mtools.conf.in +$(obj)/mtools.conf: $(src)/mtools.conf.in sed -e 's|@OBJ@|$(obj)|g' < $< > $@ # This requires write access to /dev/fd0 zdisk: $(BOOTIMAGE) $(obj)/mtools.conf - MTOOLSRC=$(src)/mtools.conf mformat a: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat a: ; sync syslinux /dev/fd0 ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - a:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync -# These require being root or having syslinux run setuid -fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 - MTOOLSRC=$(src)/mtools.conf mformat v: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat v: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - v:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - v:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) v:linux ; sync -fdimage288: $(BOOTIMAGE) $(src)/mtools.conf +fdimage288: $(BOOTIMAGE) $(obj)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 - MTOOLSRC=$(src)/mtools.conf mformat w: ; sync + MTOOLSRC=$(obj)/mtools.conf mformat w: ; sync syslinux $(obj)/fdimage ; sync echo 'default linux $(FDARGS)' | \ - MTOOLSRC=$(src)/mtools.conf mcopy - w:syslinux.cfg - MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync + MTOOLSRC=$(obj)/mtools.conf mcopy - w:syslinux.cfg + MTOOLSRC=$(obj)/mtools.conf mcopy $(BOOTIMAGE) w:linux ; sync zlilo: $(BOOTIMAGE) if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S --- a/arch/x86_64/boot/setup.S Sat Mar 15 18:40:44 2003 +++ b/arch/x86_64/boot/setup.S Sat Mar 15 18:40:44 2003 @@ -829,13 +829,6 @@ .word 0x9200 # data read/write .word 0x00CF # granularity = 4096, 386 # (+5th nibble of limit) -# this is 64bit descriptor for code - .word 0xFFFF - .word 0 - .word 0x9A00 # code read/exec - .word 0x00AF # as above, but it is long mode and with D=0 - # it does not seem to do the trick. - idt_48: .word 0 # idt limit = 0 .word 0, 0 # idt base = 0L diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile --- a/arch/x86_64/ia32/Makefile Sat Mar 15 18:40:40 2003 +++ b/arch/x86_64/ia32/Makefile Sat Mar 15 18:40:40 2003 @@ -3,5 +3,5 @@ # obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_ioctl.o \ - ia32_signal.o \ - ia32_binfmt.o fpu32.o socket32.o ptrace32.o ipc32.o syscall32.o + ia32_signal.o tls32.o \ + ia32_binfmt.o fpu32.o ptrace32.o ipc32.o syscall32.o diff -Nru a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c --- a/arch/x86_64/ia32/ia32_signal.c Sat Mar 15 18:40:44 2003 +++ b/arch/x86_64/ia32/ia32_signal.c Sat Mar 15 18:40:44 2003 @@ -106,20 +106,24 @@ stack_t uss,uoss; int ret; mm_segment_t seg; + if (uss_ptr) { + u32 ptr; if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) || - __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __get_user((u32)uss.ss_size, &uss_ptr->ss_size)) + __get_user(ptr, &uss_ptr->ss_sp) || + __get_user(uss.ss_flags, &uss_ptr->ss_flags) || + __get_user(uss.ss_size, &uss_ptr->ss_size)) return -EFAULT; + uss.ss_sp = (void *)(u64)ptr; + } seg = get_fs(); set_fs(KERNEL_DS); - ret = do_sigaltstack(&uss, &uoss, regs.rsp); + ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs.rsp); set_fs(seg); if (ret >= 0 && uoss_ptr) { - if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) || - __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) || - __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) || - __put_user((u32)uss.ss_size, &uss_ptr->ss_size)) + if (!access_ok(VERIFY_WRITE,uoss_ptr,sizeof(stack_ia32_t)) || + __put_user((u32)(u64)uss.ss_sp, &uoss_ptr->ss_sp) || + __put_user(uss.ss_flags, &uoss_ptr->ss_flags) || + __put_user(uss.ss_size, &uoss_ptr->ss_size)) ret = -EFAULT; } return ret; diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/ia32/ia32entry.S Sat Mar 15 18:40:41 2003 @@ -255,7 +255,7 @@ .quad sys_umount /* new_umount */ .quad ni_syscall /* old lock syscall holder */ .quad sys32_ioctl - .quad sys32_fcntl64 /* 55 */ + .quad compat_sys_fcntl64 /* 55 */ .quad ni_syscall /* old mpx syscall holder */ .quad sys_setpgid .quad ni_syscall /* old ulimit syscall holder */ @@ -302,7 +302,7 @@ .quad compat_sys_statfs .quad compat_sys_fstatfs /* 100 */ .quad sys_ioperm - .quad sys32_socketcall + .quad compat_sys_socketcall .quad sys_syslog .quad compat_sys_setitimer .quad compat_sys_getitimer /* 105 */ @@ -421,7 +421,7 @@ .quad sys_mincore .quad sys_madvise .quad sys_getdents64 /* 220 getdents64 */ - .quad sys32_fcntl64 + .quad compat_sys_fcntl64 .quad sys_ni_syscall /* tux */ .quad sys_ni_syscall /* security */ .quad sys_gettid @@ -443,8 +443,8 @@ .quad compat_sys_futex /* 240 */ .quad sys32_sched_setaffinity .quad sys32_sched_getaffinity - .quad sys_set_thread_area - .quad sys_get_thread_area + .quad sys32_set_thread_area + .quad sys32_get_thread_area .quad sys32_io_setup .quad sys_io_destroy .quad sys32_io_getevents diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Sat Mar 15 18:40:40 2003 +++ b/arch/x86_64/ia32/ptrace32.c Sat Mar 15 18:40:40 2003 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include diff -Nru a/arch/x86_64/ia32/socket32.c b/arch/x86_64/ia32/socket32.c --- a/arch/x86_64/ia32/socket32.c Sat Mar 15 18:40:40 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,756 +0,0 @@ -/* - * 32bit Socket syscall emulation. Based on arch/sparc64/kernel/sys_sparc32.c. - * - * Copyright (C) 2000 VA Linux Co - * Copyright (C) 2000 Don Dugger - * Copyright (C) 1999 Arun Sharma - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 2000 Hewlett-Packard Co. - * Copyright (C) 2000 David Mosberger-Tang - * Copyright (C) 2000,2001 Andi Kleen, SuSE Labs - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define A(__x) ((unsigned long)(__x)) -#define AA(__x) ((unsigned long)(__x)) - -extern asmlinkage long sys_getsockopt(int fd, int level, int optname, - void * optval, int *optlen); - - -static inline int iov_from_user32_to_kern(struct iovec *kiov, - struct iovec32 *uiov32, - int niov) -{ - int tot_len = 0; - - while(niov > 0) { - u32 len, buf; - - if(get_user(len, &uiov32->iov_len) || - get_user(buf, &uiov32->iov_base)) { - tot_len = -EFAULT; - break; - } - tot_len += len; - kiov->iov_base = (void *)A(buf); - kiov->iov_len = (__kernel_size_t) len; - uiov32++; - kiov++; - niov--; - } - return tot_len; -} - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct msghdr32 *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = (void *)A(tmp1); - kmsg->msg_iov = (struct iovec *)A(tmp2); - kmsg->msg_control = (void *)A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - return err; -} - -/* I've named the args so it is easy to tell whose space the pointers are in. */ -static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, - char *kern_address, int mode) -{ - int tot_len; - - if(kern_msg->msg_namelen) { - if(mode==VERIFY_READ) { - int err = move_addr_to_kernel(kern_msg->msg_name, - kern_msg->msg_namelen, - kern_address); - if(err < 0) - return err; - } - kern_msg->msg_name = kern_address; - } else - kern_msg->msg_name = NULL; - - if(kern_msg->msg_iovlen > UIO_FASTIOV) { - kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), - GFP_KERNEL); - if(!kern_iov) - return -ENOMEM; - } - - tot_len = iov_from_user32_to_kern(kern_iov, - (struct iovec32 *)kern_msg->msg_iov, - kern_msg->msg_iovlen); - if(tot_len >= 0) - kern_msg->msg_iov = kern_iov; - else if(kern_msg->msg_iovlen > UIO_FASTIOV) - kfree(kern_iov); - - return tot_len; -} - -/* There is a lot of hair here because the alignment rules (and - * thus placement) of cmsg headers and length are different for - * 32-bit apps. -DaveM - */ -static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, - unsigned char *stackbuf, int stackbuf_size) -{ - struct cmsghdr32 *ucmsg; - struct cmsghdr *kcmsg, *kcmsg_base; - compat_size_t ucmlen; - __kernel_size_t kcmlen, tmp; - - kcmlen = 0; - kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - if(get_user(ucmlen, &ucmsg->cmsg_len)) - return -EFAULT; - - /* Catch bogons. */ - if(CMSG32_ALIGN(ucmlen) < - CMSG32_ALIGN(sizeof(struct cmsghdr32))) - return -EINVAL; - if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) - + ucmlen) > kmsg->msg_controllen) - return -EINVAL; - - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmlen += tmp; - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - if(kcmlen == 0) - return -EINVAL; - - /* The kcmlen holds the 64-bit version of the control length. - * It may not be modified as we do not stick it into the kmsg - * until we have successfully copied over all of the data - * from the user. - */ - if(kcmlen > stackbuf_size) - kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); - if(kcmsg == NULL) - return -ENOBUFS; - - /* Now copy them over neatly. */ - memset(kcmsg, 0, kcmlen); - ucmsg = CMSG32_FIRSTHDR(kmsg); - while(ucmsg != NULL) { - __get_user(ucmlen, &ucmsg->cmsg_len); - tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + - CMSG_ALIGN(sizeof(struct cmsghdr))); - kcmsg->cmsg_len = tmp; - __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); - - /* Copy over the data. */ - if(copy_from_user(CMSG_DATA(kcmsg), - CMSG32_DATA(ucmsg), - (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) - goto out_free_efault; - - /* Advance. */ - kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); - ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); - } - - /* Ok, looks like we made it. Hook it up and return success. */ - kmsg->msg_control = kcmsg_base; - kmsg->msg_controllen = kcmlen; - return 0; - -out_free_efault: - if(kcmsg_base != (struct cmsghdr *)stackbuf) - kfree(kcmsg_base); - return -EFAULT; -} - -static void put_cmsg32(struct msghdr *kmsg, int level, int type, - int len, void *data) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - struct cmsghdr32 cmhdr; - int cmlen = CMSG32_LEN(len); - - if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { - kmsg->msg_flags |= MSG_CTRUNC; - return; - } - - if(kmsg->msg_controllen < cmlen) { - kmsg->msg_flags |= MSG_CTRUNC; - cmlen = kmsg->msg_controllen; - } - cmhdr.cmsg_level = level; - cmhdr.cmsg_type = type; - cmhdr.cmsg_len = cmlen; - - if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) - return; - if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) - return; - cmlen = CMSG32_SPACE(len); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; -} - -static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) -{ - struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; - int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); - int fdnum = scm->fp->count; - struct file **fp = scm->fp->fp; - int *cmfptr; - int err = 0, i; - - if (fdnum < fdmax) - fdmax = fdnum; - - for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { - int new_fd; - err = get_unused_fd(); - if (err < 0) - break; - new_fd = err; - err = put_user(new_fd, cmfptr); - if (err) { - put_unused_fd(new_fd); - break; - } - /* Bump the usage count and install the file. */ - get_file(fp[i]); - fd_install(new_fd, fp[i]); - } - - if (i > 0) { - int cmlen = CMSG32_LEN(i * sizeof(int)); - if (!err) - err = put_user(SOL_SOCKET, &cm->cmsg_level); - if (!err) - err = put_user(SCM_RIGHTS, &cm->cmsg_type); - if (!err) - err = put_user(cmlen, &cm->cmsg_len); - if (!err) { - cmlen = CMSG32_SPACE(i * sizeof(int)); - kmsg->msg_control += cmlen; - kmsg->msg_controllen -= cmlen; - } - } - if (i < fdnum) - kmsg->msg_flags |= MSG_CTRUNC; - - /* - * All of the files that fit in the message have had their - * usage counts incremented, so we just free the list. - */ - __scm_destroy(scm); -} - -/* In these cases we (currently) can just copy to data over verbatim - * because all CMSGs created by the kernel have well defined types which - * have the same layout in both the 32-bit and 64-bit API. One must add - * some special cased conversions here if we start sending control messages - * with incompatible types. - * - * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after - * we do our work. The remaining cases are: - * - * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean - * IP_TTL int 32-bit clean - * IP_TOS __u8 32-bit clean - * IP_RECVOPTS variable length 32-bit clean - * IP_RETOPTS variable length 32-bit clean - * (these last two are clean because the types are defined - * by the IPv4 protocol) - * IP_RECVERR struct sock_extended_err + - * struct sockaddr_in 32-bit clean - * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + - * struct sockaddr_in6 32-bit clean - * IPV6_PKTINFO struct in6_pktinfo 32-bit clean - * IPV6_HOPLIMIT int 32-bit clean - * IPV6_FLOWINFO u32 32-bit clean - * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean - * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean - * IPV6_RTHDR ipv6 routing exthdr 32-bit clean - * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean - */ -static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) -{ - unsigned char *workbuf, *wp; - unsigned long bufsz, space_avail; - struct cmsghdr *ucmsg; - - bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; - space_avail = kmsg->msg_controllen + bufsz; - wp = workbuf = kmalloc(bufsz, GFP_KERNEL); - if(workbuf == NULL) - goto fail; - - /* To make this more sane we assume the kernel sends back properly - * formatted control messages. Because of how the kernel will truncate - * the cmsg_len for MSG_TRUNC cases, we need not check that case either. - */ - ucmsg = (struct cmsghdr *) orig_cmsg_uptr; - while(((unsigned long)ucmsg) <= - (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { - struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; - int clen64, clen32; - - /* UCMSG is the 64-bit format CMSG entry in user-space. - * KCMSG32 is within the kernel space temporary buffer - * we use to convert into a 32-bit style CMSG. - */ - __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); - __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); - __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); - - clen64 = kcmsg32->cmsg_len; - copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), - clen64 - CMSG_ALIGN(sizeof(*ucmsg))); - clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + - CMSG32_ALIGN(sizeof(struct cmsghdr32))); - kcmsg32->cmsg_len = clen32; - - ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); - wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); - } - - /* Copy back fixed up data, and adjust pointers. */ - bufsz = (wp - workbuf); - copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); - - kmsg->msg_control = (struct cmsghdr *) - (((char *)orig_cmsg_uptr) + bufsz); - kmsg->msg_controllen = space_avail - bufsz; - - kfree(workbuf); - return; - -fail: - /* If we leave the 64-bit format CMSG chunks in there, - * the application could get confused and crash. So to - * ensure greater recovery, we report no CMSGs. - */ - kmsg->msg_controllen += bufsz; - kmsg->msg_control = (void *) orig_cmsg_uptr; -} - -asmlinkage long sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iov[UIO_FASTIOV]; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr kern_msg; - int err, total_len; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); - if (err < 0) - goto out; - total_len = err; - - if(kern_msg.msg_controllen) { - err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); - if(err) - goto out_freeiov; - ctl_buf = kern_msg.msg_control; - } - kern_msg.msg_flags = user_flags; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - if (sock->file->f_flags & O_NONBLOCK) - kern_msg.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &kern_msg, total_len); - sockfd_put(sock); - } - - /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ - if(ctl_buf != ctl) - kfree(ctl_buf); -out_freeiov: - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - return err; -} - -asmlinkage long sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) -{ - struct iovec iovstack[UIO_FASTIOV]; - struct msghdr kern_msg; - char addr[MAX_SOCK_ADDR]; - struct socket *sock; - struct iovec *iov = iovstack; - struct sockaddr *uaddr; - int *uaddr_len; - unsigned long cmsg_ptr; - int err, total_len, len = 0; - - if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) - return -EFAULT; - if(kern_msg.msg_iovlen > UIO_MAXIOV) - return -EINVAL; - - uaddr = kern_msg.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out; - total_len = err; - - cmsg_ptr = (unsigned long) kern_msg.msg_control; - kern_msg.msg_flags = 0; - - sock = sockfd_lookup(fd, &err); - if (sock != NULL) { - struct sock_iocb *si; - struct kiocb iocb; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - init_sync_kiocb(&iocb, NULL); - si = kiocb_to_siocb(&iocb); - si->sock = sock; - si->scm = &si->async_scm; - si->msg = &kern_msg; - si->size = total_len; - si->flags = user_flags; - memset(si->scm, 0, sizeof(*si->scm)); - - err = sock->ops->recvmsg(&iocb, sock, &kern_msg, total_len, - user_flags, si->scm); - if (-EIOCBQUEUED == err) - err = wait_on_sync_kiocb(&iocb); - - if(err >= 0) { - len = err; - if(!kern_msg.msg_control) { - if(sock->passcred || si->scm->fp) - kern_msg.msg_flags |= MSG_CTRUNC; - if(si->scm->fp) - __scm_destroy(si->scm); - } else { - /* If recvmsg processing itself placed some - * control messages into user space, it's is - * using 64-bit CMSG processing, so we need - * to fix it up before we tack on more stuff. - */ - if((unsigned long) kern_msg.msg_control != cmsg_ptr) - cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); - - /* Wheee... */ - if(sock->passcred) - put_cmsg32(&kern_msg, - SOL_SOCKET, SCM_CREDENTIALS, - sizeof(si->scm->creds), - &si->scm->creds); - if(si->scm->fp != NULL) - scm_detach_fds32(&kern_msg, si->scm); - } - } - sockfd_put(sock); - } - - if(uaddr != NULL && err >= 0) - err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); - if(cmsg_ptr != 0 && err >= 0) { - unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); - compat_size_t uclen = (compat_size_t) (ucmsg_ptr - cmsg_ptr); - err |= __put_user(uclen, &user_msg->msg_controllen); - } - if(err >= 0) - err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); - if(kern_msg.msg_iov != iov) - kfree(kern_msg.msg_iov); -out: - if(err < 0) - return err; - return len; -} - -extern asmlinkage int sys_setsockopt(int fd, int level, int optname, - char *optval, int optlen); - -static int do_set_attach_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct sock_fprog32 { - __u16 len; - __u32 filter; - } *fprog32 = (struct sock_fprog32 *)optval; - struct sock_fprog kfprog; - struct sock_filter *kfilter; - unsigned int fsize; - mm_segment_t old_fs; - __u32 uptr; - int ret; - - if (get_user(kfprog.len, &fprog32->len) || - __get_user(uptr, &fprog32->filter)) - return -EFAULT; - - kfprog.filter = (struct sock_filter *)A(uptr); - fsize = kfprog.len * sizeof(struct sock_filter); - - kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL); - if (kfilter == NULL) - return -ENOMEM; - - if (copy_from_user(kfilter, kfprog.filter, fsize)) { - kfree(kfilter); - return -EFAULT; - } - - kfprog.filter = kfilter; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *)&kfprog, sizeof(kfprog)); - set_fs(old_fs); - - kfree(kfilter); - - return ret; -} - -static int do_set_icmpv6_filter(int fd, int level, int optname, - char *optval, int optlen) -{ - struct icmp6_filter kfilter; - mm_segment_t old_fs; - int ret, i; - - if (copy_from_user(&kfilter, optval, sizeof(kfilter))) - return -EFAULT; - - - for (i = 0; i < 8; i += 2) { - u32 tmp = kfilter.data[i]; - - kfilter.data[i] = kfilter.data[i + 1]; - kfilter.data[i + 1] = tmp; - } - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_setsockopt(fd, level, optname, - (char *) &kfilter, sizeof(kfilter)); - set_fs(old_fs); - - return ret; -} - -static int do_set_sock_timeout(int fd, int level, int optname, char *optval, int optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int err; - - if (optlen < sizeof(*up)) - return -EINVAL; - if (get_user(ktime.tv_sec, &up->tv_sec) || - __get_user(ktime.tv_usec, &up->tv_usec)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_setsockopt(fd, level, optname, (char *) &ktime, sizeof(ktime)); - set_fs(old_fs); - - return err; -} - -asmlinkage long sys32_setsockopt(int fd, int level, int optname, - char *optval, int optlen) -{ - if (optname == SO_ATTACH_FILTER) - return do_set_attach_filter(fd, level, optname, - optval, optlen); - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_set_sock_timeout(fd, level, optname, optval, optlen); - if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER) - return do_set_icmpv6_filter(fd, level, optname, - optval, optlen); - - return sys_setsockopt(fd, level, optname, optval, optlen); -} - -static int do_get_sock_timeout(int fd, int level, int optname, char *optval, int *optlen) -{ - struct compat_timeval *up = (struct compat_timeval *) optval; - struct timeval ktime; - mm_segment_t old_fs; - int len, err; - - if (get_user(len, optlen)) - return -EFAULT; - if (len < sizeof(*up)) - return -EINVAL; - len = sizeof(ktime); - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_getsockopt(fd, level, optname, (char *) &ktime, &len); - set_fs(old_fs); - - if (!err) { - if (put_user(sizeof(*up), optlen) || - put_user(ktime.tv_sec, &up->tv_sec) || - __put_user(ktime.tv_usec, &up->tv_usec)) - err = -EFAULT; - } - return err; -} - -asmlinkage long sys32_getsockopt(int fd, int level, int optname, - char *optval, int *optlen) -{ - if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) - return do_get_sock_timeout(fd, level, optname, optval, optlen); - return sys_getsockopt(fd, level, optname, optval, optlen); -} - -/* Argument list sizes for sys_socketcall */ -#define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), - AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), - AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; -#undef AL - -extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen); -extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, - int addrlen); -extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, - int *upeer_addrlen); -extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, - int *usockaddr_len); -extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags); -extern asmlinkage long sys_sendto(int fd, u32 buff, compat_size_t len, - unsigned flags, u32 addr, int addr_len); -extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags); -extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, compat_size_t size, - unsigned flags, u32 addr, u32 addr_len); -extern asmlinkage long sys_socket(int family, int type, int protocol); -extern asmlinkage long sys_socketpair(int family, int type, int protocol, - int usockvec[2]); -extern asmlinkage long sys_shutdown(int fd, int how); -extern asmlinkage long sys_listen(int fd, int backlog); - -asmlinkage long sys32_socketcall(int call, u32 *args) -{ - int ret; - u32 a[6]; - u32 a0,a1; - - if (callSYS_RECVMSG) - return -EINVAL; - if (copy_from_user(a, args, nas[call])) - return -EFAULT; - a0=a[0]; - a1=a[1]; - - switch(call) - { - case SYS_SOCKET: - ret = sys_socket(a0, a1, a[2]); - break; - case SYS_BIND: - ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_CONNECT: - ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]); - break; - case SYS_LISTEN: - ret = sys_listen(a0, a1); - break; - case SYS_ACCEPT: - ret = sys_accept(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETSOCKNAME: - ret = sys_getsockname(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_GETPEERNAME: - ret = sys_getpeername(a0, (struct sockaddr *)A(a1), - (int *)A(a[2])); - break; - case SYS_SOCKETPAIR: - ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3])); - break; - case SYS_SEND: - ret = sys_send(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_SENDTO: - ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_RECV: - ret = sys_recv(a0, (void *)A(a1), a[2], a[3]); - break; - case SYS_RECVFROM: - ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]); - break; - case SYS_SHUTDOWN: - ret = sys_shutdown(a0,a1); - break; - case SYS_SETSOCKOPT: - ret = sys32_setsockopt(a0, a1, a[2], (char *)A(a[3]), - a[4]); - break; - case SYS_GETSOCKOPT: - ret = sys32_getsockopt(a0, a1, a[2], (char *)(u64)a[3], (int *)(u64)a[4]); - break; - case SYS_SENDMSG: - ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - case SYS_RECVMSG: - ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1), - a[2]); - break; - default: - ret = -EINVAL; - break; - } - return ret; -} diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Sat Mar 15 18:40:41 2003 @@ -738,7 +738,7 @@ asmlinkage ssize_t sys_writev(unsigned long,const struct iovec *,unsigned long); static struct iovec * -get_iovec32(struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) +get_compat_iovec(struct compat_iovec *iov32, struct iovec *iov_buf, u32 count, int type, int *errp) { int i; u32 buf, len; @@ -751,7 +751,7 @@ return 0; if (count > UIO_MAXIOV) return(struct iovec *)0; - if(verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count)) + if(verify_area(VERIFY_READ, iov32, sizeof(struct compat_iovec)*count)) return(struct iovec *)0; if (count > UIO_FASTIOV) { *errp = -ENOMEM; @@ -792,14 +792,14 @@ } asmlinkage long -sys32_readv(int fd, struct iovec32 *vector, u32 count) +sys32_readv(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_WRITE, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_readv(fd, iov, count); @@ -810,14 +810,14 @@ } asmlinkage long -sys32_writev(int fd, struct iovec32 *vector, u32 count) +sys32_writev(int fd, struct compat_iovec *vector, u32 count) { struct iovec iovstack[UIO_FASTIOV]; struct iovec *iov; int ret; mm_segment_t old_fs = get_fs(); - if ((iov = get_iovec32(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) + if ((iov = get_compat_iovec(vector, iovstack, count, VERIFY_READ, &ret)) == NULL) return ret; set_fs(KERNEL_DS); ret = sys_writev(fd, iov, count); @@ -1016,102 +1016,6 @@ return ret; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg); - - -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if (get_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if (ret) return ret; - if (put_compat_flock(&f, (struct compat_flock *)arg)) - return -EFAULT; - return 0; - } - case F_GETLK64: - case F_SETLK64: - case F_SETLKW64: - return sys32_fcntl64(fd,cmd,arg); - - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - -static inline int get_flock64(struct ia32_flock64 *fl32, struct flock *fl64) -{ - if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) { - int ret = __get_user(fl64->l_type, &fl32->l_type); - ret |= __get_user(fl64->l_whence, &fl32->l_whence); - ret |= __get_user(fl64->l_start, &fl32->l_start); - ret |= __get_user(fl64->l_len, &fl32->l_len); - ret |= __get_user(fl64->l_pid, &fl32->l_pid); - return ret; - } - return -EFAULT; -} - -static inline int put_flock64(struct ia32_flock64 *fl32, struct flock *fl64) -{ - if (access_ok(fl32, sizeof(struct ia32_flock64), VERIFY_WRITE)) { - int ret = __put_user(fl64->l_type, &fl32->l_type); - ret |= __put_user(fl64->l_whence, &fl32->l_whence); - ret |= __put_user(fl64->l_start, &fl32->l_start); - ret |= __put_user(fl64->l_len, &fl32->l_len); - ret |= __put_user(fl64->l_pid, &fl32->l_pid); - return ret; - } - return -EFAULT; -} - -asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct flock fl64; - mm_segment_t oldfs = get_fs(); - int ret = 0; - int oldcmd = cmd; - unsigned long oldarg = arg; - - switch (cmd) { - case F_GETLK64: - cmd = F_GETLK; - goto cnv; - case F_SETLK64: - cmd = F_SETLK; - goto cnv; - case F_SETLKW64: - cmd = F_SETLKW; - cnv: - ret = get_flock64((struct ia32_flock64 *)arg, &fl64); - arg = (unsigned long)&fl64; - set_fs(KERNEL_DS); - break; - case F_GETLK: - case F_SETLK: - case F_SETLKW: - return sys32_fcntl(fd,cmd,arg); - } - if (!ret) - ret = sys_fcntl(fd, cmd, arg); - set_fs(oldfs); - if (oldcmd == F_GETLK64 && !ret) - ret = put_flock64((struct ia32_flock64 *)oldarg, &fl64); - return ret; -} - int sys32_ni_syscall(int call) { printk(KERN_INFO "IA32 syscall %d from %s not implemented\n", call, @@ -1261,8 +1165,8 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t,si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: @@ -1299,8 +1203,9 @@ if (s->si_signo >= SIGRTMIN) { d->si_pid = s->si_pid; d->si_uid = s->si_uid; - /* XXX: Ouch, how to find this out??? */ - d->si_int = s->si_int; + memcpy(&d->si_int, + &s->si_int, + sizeof(siginfo_t) - offsetof(siginfo_t, si_int)); } else switch (s->si_signo) { /* XXX: What about POSIX1.b timers */ case SIGCHLD: diff -Nru a/arch/x86_64/ia32/tls32.c b/arch/x86_64/ia32/tls32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/x86_64/ia32/tls32.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,162 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * sys_alloc_thread_area: get a yet unused TLS descriptor index. + */ +static int get_free_idx(void) +{ + struct thread_struct *t = ¤t->thread; + int idx; + + for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) + if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) + return idx + GDT_ENTRY_TLS_MIN; + return -ESRCH; +} + +/* + * Set a given TLS descriptor: + * When you want addresses > 32bit use arch_prctl() + */ +int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int cpu, idx; + + if (copy_from_user(&info, u_info, sizeof(info))) + return -EFAULT; + + idx = info.entry_number; + + /* + * index -1 means the kernel should try to find and + * allocate an empty descriptor: + */ + if (idx == -1) { + idx = get_free_idx(); + if (idx < 0) + return idx; + if (put_user(idx, &u_info->entry_number)) + return -EFAULT; + } + + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + /* + * We must not get preempted while modifying the TLS. + */ + cpu = get_cpu(); + + if (LDT_empty(&info)) { + desc->a = 0; + desc->b = 0; + } else { + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + } + if (t == ¤t->thread) + load_TLS(t, cpu); + + put_cpu(); + return 0; +} + +asmlinkage long sys32_set_thread_area(struct user_desc *u_info) +{ + return do_set_thread_area(¤t->thread, u_info); +} + + +/* + * Get the current Thread-Local Storage area: + */ + +#define GET_BASE(desc) ( \ + (((desc)->a >> 16) & 0x0000ffff) | \ + (((desc)->b << 16) & 0x00ff0000) | \ + ( (desc)->b & 0xff000000) ) + +#define GET_LIMIT(desc) ( \ + ((desc)->a & 0x0ffff) | \ + ((desc)->b & 0xf0000) ) + +#define GET_32BIT(desc) (((desc)->b >> 23) & 1) +#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) +#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) +#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) +#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) +#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) +#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) + +int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) +{ + struct user_desc info; + struct n_desc_struct *desc; + int idx; + + if (get_user(idx, &u_info->entry_number)) + return -EFAULT; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; + + memset(&info, 0, sizeof(struct user_desc)); + info.entry_number = idx; + info.base_addr = GET_BASE(desc); + info.limit = GET_LIMIT(desc); + info.seg_32bit = GET_32BIT(desc); + info.contents = GET_CONTENTS(desc); + info.read_exec_only = !GET_WRITABLE(desc); + info.limit_in_pages = GET_LIMIT_PAGES(desc); + info.seg_not_present = !GET_PRESENT(desc); + info.useable = GET_USEABLE(desc); + info.lm = GET_LONGMODE(desc); + + if (copy_to_user(u_info, &info, sizeof(info))) + return -EFAULT; + return 0; +} + +asmlinkage long sys32_get_thread_area(struct user_desc *u_info) +{ + return do_get_thread_area(¤t->thread, u_info); +} + + +int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs) +{ + struct n_desc_struct *desc; + struct user_desc info, *cp; + int idx; + + cp = (void *)childregs->rsi; + if (copy_from_user(&info, cp, sizeof(info))) + return -EFAULT; + if (LDT_empty(&info)) + return -EINVAL; + + idx = info.entry_number; + if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) + return -EINVAL; + + desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; + desc->a = LDT_entry_a(&info); + desc->b = LDT_entry_b(&info); + + return 0; +} diff -Nru a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c --- a/arch/x86_64/kernel/apic.c Sat Mar 15 18:40:40 2003 +++ b/arch/x86_64/kernel/apic.c Sat Mar 15 18:40:40 2003 @@ -981,9 +981,6 @@ asmlinkage void smp_spurious_interrupt(void) { unsigned int v; - static unsigned long last_warning; - static unsigned long skipped; - irq_enter(); /* * Check if this really is a spurious interrupt and ACK it @@ -994,8 +991,12 @@ if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) ack_APIC_irq(); +#if 0 + static unsigned long last_warning; + static unsigned long skipped; + /* see sw-dev-man vol 3, chapter 7.4.13.5 */ - if (last_warning+30*HZ < jiffies) { + if (time_before(last_warning+30*HZ,jiffies)) { printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n", smp_processor_id(), skipped); last_warning = jiffies; @@ -1003,6 +1004,7 @@ } else { skipped++; } +#endif irq_exit(); } diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c --- a/arch/x86_64/kernel/head64.c Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/kernel/head64.c Sat Mar 15 18:40:41 2003 @@ -79,6 +79,9 @@ clear_bss(); pda_init(0); copy_bootdata(real_mode_data); + /* default console: */ + if (!strstr(saved_command_line, "console=")) + strcat(saved_command_line, " console=tty0"); s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) setup_early_printk(s+12); diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Sat Mar 15 18:40:42 2003 +++ b/arch/x86_64/kernel/io_apic.c Sat Mar 15 18:40:42 2003 @@ -1110,7 +1110,7 @@ */ static int __init timer_irq_works(void) { - unsigned int t1 = jiffies; + unsigned long t1 = jiffies; local_irq_enable(); /* Let ten ticks pass... */ @@ -1123,6 +1123,8 @@ * might have cached one ExtINT interrupt. Finally, at * least one tick may be lost due to delays. */ + + /* jiffies wrap? */ if (jiffies - t1 > 4) return 1; return 0; diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/kernel/irq.c Sat Mar 15 18:40:41 2003 @@ -135,6 +135,7 @@ { int i, j; struct irqaction * action; + unsigned long flags; seq_printf(p, " "); for (j=0; jtypename); - seq_printf(p, " %s", action->name); + seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); } seq_printf(p, "NMI: "); for (j = 0; j < NR_CPUS; j++) diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Sat Mar 15 18:40:42 2003 +++ b/arch/x86_64/kernel/process.c Sat Mar 15 18:40:42 2003 @@ -19,46 +19,37 @@ #define __KERNEL_SYSCALLS__ #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 asmlinkage extern void ret_from_fork(void); -int sys_arch_prctl(int code, unsigned long addr); unsigned long kernel_thread_flags = CLONE_VM | CLONE_UNTRACED; @@ -245,10 +236,36 @@ } } +static inline void set_32bit_tls(struct task_struct *t, int tls, u32 addr) +{ + struct user_desc ud = { + .base_addr = addr, + .limit = 0xfffff, + .seg_32bit = 1, + .limit_in_pages = 1, + .useable = 1, + }; + struct n_desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + desc->a = LDT_entry_a(&ud); + desc->b = LDT_entry_b(&ud); +} + +static inline u32 read_32bit_tls(struct task_struct *t, int tls) +{ + struct desc_struct *desc = (void *)t->thread.tls_array; + desc += tls; + return desc->base0 | + (((u32)desc->base1) << 16) | + (((u32)desc->base2) << 24); +} + + int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { + int err; struct pt_regs * childregs; struct task_struct *me = current; @@ -265,7 +282,7 @@ p->thread.rsp = (unsigned long) childregs; p->thread.rsp0 = (unsigned long) (childregs+1); - p->thread.userrsp = current->thread.userrsp; + p->thread.userrsp = me->thread.userrsp; p->thread.rip = (unsigned long) ret_from_fork; @@ -277,8 +294,8 @@ asm("movl %%es,%0" : "=m" (p->thread.es)); asm("movl %%ds,%0" : "=m" (p->thread.ds)); - unlazy_fpu(current); - p->thread.i387 = current->thread.i387; + unlazy_fpu(me); + p->thread.i387 = me->thread.i387; if (unlikely(me->thread.io_bitmap_ptr != NULL)) { p->thread.io_bitmap_ptr = kmalloc((IO_BITMAP_SIZE+1)*4, GFP_KERNEL); @@ -292,27 +309,20 @@ * Set a new TLS for the child thread? */ if (clone_flags & CLONE_SETTLS) { - struct n_desc_struct *desc; - struct user_desc info; - int idx; - - if (copy_from_user(&info, test_thread_flag(TIF_IA32) ? - (void *)childregs->rsi : - (void *)childregs->rdx, sizeof(info))) - return -EFAULT; - if (LDT_empty(&info)) - return -EINVAL; - - idx = info.entry_number; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = (struct n_desc_struct *)(p->thread.tls_array) + idx - GDT_ENTRY_TLS_MIN; - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - - return 0; +#ifdef CONFIG_IA32_EMULATION + if (test_thread_flag(TIF_IA32)) + err = ia32_child_tls(p, childregs); + else +#endif + err = do_arch_prctl(p, ARCH_SET_FS, childregs->r10); + if (err) + goto out; + } + err = 0; +out: + if (err && p->thread.io_bitmap_ptr) + kfree(p->thread.io_bitmap_ptr); + return err; } /* @@ -422,7 +432,7 @@ if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { if (next->io_bitmap_ptr) { /* - * 4 cachelines copy ... not good, but not that + * 2 cachelines copy ... not good, but not that * bad either. Anyone got something better? * This only affects processes which use ioperm(). */ @@ -537,19 +547,35 @@ #undef last_sched #undef first_sched -int sys_arch_prctl(int code, unsigned long addr) +long do_arch_prctl(struct task_struct *task, int code, unsigned long addr) { int ret = 0; + int doit = task == current; + int cpu; switch (code) { case ARCH_SET_GS: if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, GS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + load_gs_index(GS_TLS_SEL); + } + task->thread.gsindex = GS_TLS_SEL; + task->thread.gs = 0; + } else { + task->thread.gsindex = 0; + task->thread.gs = addr; + if (doit) { load_gs_index(0); - current->thread.gsindex = 0; - current->thread.gs = addr; ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr); + } + } put_cpu(); break; case ARCH_SET_FS: @@ -557,22 +583,51 @@ with gs */ if (addr >= TASK_SIZE) return -EPERM; - get_cpu(); + cpu = get_cpu(); + /* handle small bases via the GDT because that's faster to + switch. */ + if (addr <= 0xffffffff) { + set_32bit_tls(task, FS_TLS, addr); + if (doit) { + load_TLS(&task->thread, cpu); + asm volatile("movl %0,%%fs" :: "r" (FS_TLS_SEL)); + } + task->thread.fsindex = FS_TLS_SEL; + task->thread.fs = 0; + } else { + task->thread.fsindex = 0; + task->thread.fs = addr; + if (doit) { + /* set the selector to 0 to not confuse + __switch_to */ asm volatile("movl %0,%%fs" :: "r" (0)); - current->thread.fsindex = 0; - current->thread.fs = addr; ret = checking_wrmsrl(MSR_FS_BASE, addr); + } + } put_cpu(); break; - - /* Returned value may not be correct when the user changed fs/gs */ - case ARCH_GET_FS: - ret = put_user(current->thread.fs, (unsigned long *)addr); + case ARCH_GET_FS: { + unsigned long base; + if (task->thread.fsindex == FS_TLS_SEL) + base = read_32bit_tls(task, FS_TLS); + else if (doit) { + rdmsrl(MSR_FS_BASE, base); + } else + base = task->thread.fs; + ret = put_user(base, (unsigned long *)addr); break; - - case ARCH_GET_GS: - ret = put_user(current->thread.gs, (unsigned long *)addr); + } + case ARCH_GET_GS: { + unsigned long base; + if (task->thread.gsindex == GS_TLS_SEL) + base = read_32bit_tls(task, GS_TLS); + else if (doit) { + rdmsrl(MSR_KERNEL_GS_BASE, base); + } else + base = task->thread.gs; + ret = put_user(base, (unsigned long *)addr); break; + } default: ret = -EINVAL; @@ -582,131 +637,9 @@ return ret; } -/* - * sys_alloc_thread_area: get a yet unused TLS descriptor index. - */ -static int get_free_idx(void) -{ - struct thread_struct *t = ¤t->thread; - int idx; - - for (idx = 0; idx < GDT_ENTRY_TLS_ENTRIES; idx++) - if (desc_empty((struct n_desc_struct *)(t->tls_array) + idx)) - return idx + GDT_ENTRY_TLS_MIN; - return -ESRCH; -} - -/* - * Set a given TLS descriptor: - * When you want addresses > 32bit use arch_prctl() - */ -int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int cpu, idx; - - if (copy_from_user(&info, u_info, sizeof(info))) - return -EFAULT; - - idx = info.entry_number; - - /* - * index -1 means the kernel should try to find and - * allocate an empty descriptor: - */ - if (idx == -1) { - idx = get_free_idx(); - if (idx < 0) - return idx; - if (put_user(idx, &u_info->entry_number)) - return -EFAULT; - } - - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - /* - * We must not get preempted while modifying the TLS. - */ - cpu = get_cpu(); - - if (LDT_empty(&info)) { - desc->a = 0; - desc->b = 0; - } else { - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } - if (t == ¤t->thread) - load_TLS(t, cpu); - - put_cpu(); - return 0; -} - -asmlinkage int sys_set_thread_area(struct user_desc *u_info) -{ - return do_set_thread_area(¤t->thread, u_info); -} - - -/* - * Get the current Thread-Local Storage area: - */ - -#define GET_BASE(desc) ( \ - (((desc)->a >> 16) & 0x0000ffff) | \ - (((desc)->b << 16) & 0x00ff0000) | \ - ( (desc)->b & 0xff000000) ) - -#define GET_LIMIT(desc) ( \ - ((desc)->a & 0x0ffff) | \ - ((desc)->b & 0xf0000) ) - -#define GET_32BIT(desc) (((desc)->b >> 23) & 1) -#define GET_CONTENTS(desc) (((desc)->b >> 10) & 3) -#define GET_WRITABLE(desc) (((desc)->b >> 9) & 1) -#define GET_LIMIT_PAGES(desc) (((desc)->b >> 23) & 1) -#define GET_PRESENT(desc) (((desc)->b >> 15) & 1) -#define GET_USEABLE(desc) (((desc)->b >> 20) & 1) -#define GET_LONGMODE(desc) (((desc)->b >> 21) & 1) - -int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info) -{ - struct user_desc info; - struct n_desc_struct *desc; - int idx; - - if (get_user(idx, &u_info->entry_number)) - return -EFAULT; - if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) - return -EINVAL; - - desc = ((struct n_desc_struct *)t->tls_array) + idx - GDT_ENTRY_TLS_MIN; - - memset(&info, 0, sizeof(struct user_desc)); - info.entry_number = idx; - info.base_addr = GET_BASE(desc); - info.limit = GET_LIMIT(desc); - info.seg_32bit = GET_32BIT(desc); - info.contents = GET_CONTENTS(desc); - info.read_exec_only = !GET_WRITABLE(desc); - info.limit_in_pages = GET_LIMIT_PAGES(desc); - info.seg_not_present = !GET_PRESENT(desc); - info.useable = GET_USEABLE(desc); - info.lm = GET_LONGMODE(desc); - - if (copy_to_user(u_info, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -asmlinkage int sys_get_thread_area(struct user_desc *u_info) +long sys_arch_prctl(int code, unsigned long addr) { - return do_get_thread_area(¤t->thread, u_info); + return do_arch_prctl(current, code, addr); } /* diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c --- a/arch/x86_64/kernel/ptrace.c Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/kernel/ptrace.c Sat Mar 15 18:40:41 2003 @@ -26,6 +26,7 @@ #include #include #include +#include /* * does not yet catch signals sent when the child dies. @@ -322,6 +323,13 @@ wake_up_process(child); ret = 0; break; + } + +#ifdef CONFIG_IA32_EMULATION + /* This makes only sense with 32bit programs. Allow a + 64bit debugger to fully examine them too. Better + don't use it against 64bit processes, use + PTRACE_ARCH_PRCTL instead. */ case PTRACE_SET_THREAD_AREA: { int old; get_user(old, &((struct user_desc *)data)->entry_number); @@ -338,7 +346,13 @@ put_user(old, &((struct user_desc *)data)->entry_number); break; } - } +#endif + /* normal 64bit interface to access TLS data. + Works just like arch_prctl, except that the arguments + are reversed. */ + case PTRACE_ARCH_PRCTL: + ret = do_arch_prctl(child, data, addr); + break; /* * make the child exit. Best I can do is send it a sigkill. diff -Nru a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c --- a/arch/x86_64/kernel/setup64.c Sat Mar 15 18:40:40 2003 +++ b/arch/x86_64/kernel/setup64.c Sat Mar 15 18:40:40 2003 @@ -22,6 +22,7 @@ #include #include #include +#include char x86_boot_params[2048] __initdata = {0,}; @@ -29,9 +30,6 @@ struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; -extern void system_call(void); -extern void ia32_cstar_target(void); - extern struct task_struct init_task; extern unsigned char __per_cpu_start[], __per_cpu_end[]; @@ -130,6 +128,24 @@ #define EXCEPTION_STK_ORDER 0 /* >= N_EXCEPTION_STACKS*EXCEPTION_STKSZ */ char boot_exception_stacks[N_EXCEPTION_STACKS*EXCEPTION_STKSZ]; +void syscall_init(void) +{ + /* + * LSTAR and STAR live in a bit strange symbiosis. + * They both write to the same internal register. STAR allows to set CS/DS + * but only a 32bit target. LSTAR sets the 64bit rip. + */ + wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); + wrmsrl(MSR_LSTAR, system_call); + +#ifdef CONFIG_IA32_EMULATION + wrmsrl(MSR_CSTAR, ia32_cstar_target); +#endif + + /* Flags to clear on syscall */ + wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); +} + /* * cpu_init() initializes state that is per-CPU. Some data is already * initialized (naturally) in the bootstrap process, such as the GDT @@ -188,20 +204,7 @@ asm volatile("pushfq ; popq %%rax ; btr $14,%%rax ; pushq %%rax ; popfq" ::: "eax"); - /* - * LSTAR and STAR live in a bit strange symbiosis. - * They both write to the same internal register. STAR allows to set CS/DS - * but only a 32bit target. LSTAR sets the 64bit rip. - */ - wrmsrl(MSR_STAR, ((u64)__USER32_CS)<<48 | ((u64)__KERNEL_CS)<<32); - wrmsrl(MSR_LSTAR, system_call); - -#ifdef CONFIG_IA32_EMULATION - wrmsrl(MSR_CSTAR, ia32_cstar_target); -#endif - - /* Flags to clear on syscall */ - wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); + syscall_init(); wrmsrl(MSR_FS_BASE, 0); wrmsrl(MSR_KERNEL_GS_BASE, 0); diff -Nru a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c --- a/arch/x86_64/kernel/signal.c Sat Mar 15 18:40:43 2003 +++ b/arch/x86_64/kernel/signal.c Sat Mar 15 18:40:43 2003 @@ -96,14 +96,6 @@ #define COPY(x) err |= __get_user(regs->x, &sc->x) - { - unsigned int seg; - err |= __get_user(seg, &sc->gs); - load_gs_index(seg); - err |= __get_user(seg, &sc->fs); - loadsegment(fs,seg); - } - COPY(rdi); COPY(rsi); COPY(rbp); COPY(rsp); COPY(rbx); COPY(rdx); COPY(rcx); COPY(rip); COPY(r8); @@ -189,13 +181,10 @@ static inline int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask, struct task_struct *me) { - int tmp, err = 0; + int err = 0; - tmp = 0; - __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->gs); - __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); - err |= __put_user(tmp, (unsigned int *)&sc->fs); + err |= __put_user(0, &sc->gs); + err |= __put_user(0, &sc->fs); err |= __put_user(regs->rdi, &sc->rdi); err |= __put_user(regs->rsi, &sc->rsi); diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c --- a/arch/x86_64/kernel/suspend.c Sat Mar 15 18:40:42 2003 +++ b/arch/x86_64/kernel/suspend.c Sat Mar 15 18:40:42 2003 @@ -26,6 +26,7 @@ #include #include #include +#include static struct saved_context saved_context; @@ -58,10 +59,9 @@ asm volatile ("movw %%gs, %0" : "=m" (saved_context.gs)); asm volatile ("movw %%ss, %0" : "=m" (saved_context.ss)); - asm volatile ("swapgs"); - rdmsrl(0xc0000100, saved_context.fs_base); - rdmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + rdmsrl(MSR_FS_BASE, saved_context.fs_base); + rdmsrl(MSR_GS_BASE, saved_context.gs_base); + rdmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * control registers @@ -99,10 +99,9 @@ load_gs_index(saved_context.gs); asm volatile ("movw %0, %%ss" :: "r" (saved_context.ss)); - asm volatile ("swapgs"); - wrmsrl(0xc0000100, saved_context.fs_base); - wrmsrl(0xc0000101, saved_context.gs_base); - asm volatile ("swapgs"); + wrmsrl(MSR_FS_BASE, saved_context.fs_base); + wrmsrl(MSR_GS_BASE, saved_context.gs_base); + wrmsrl(MSR_KERNEL_GS_BASE, saved_context.gs_kernel_base); /* * now restore the descriptor tables to their proper values diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c Sat Mar 15 18:40:43 2003 +++ b/arch/x86_64/kernel/time.c Sat Mar 15 18:40:43 2003 @@ -30,7 +30,7 @@ #include #endif -u64 jiffies_64; +u64 jiffies_64 = INITIAL_JIFFIES; extern int using_apic_timer; @@ -47,8 +47,8 @@ struct hpet_data __hpet __section_hpet; /* address, quotient, trigger, hz */ -volatile unsigned long __jiffies __section_jiffies; -unsigned long __wall_jiffies __section_wall_jiffies; +volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES; +unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES; struct timespec __xtime __section_xtime; struct timezone __sys_tz __section_sys_tz; diff -Nru a/arch/x86_64/lib/getuser.S b/arch/x86_64/lib/getuser.S --- a/arch/x86_64/lib/getuser.S Sat Mar 15 18:40:39 2003 +++ b/arch/x86_64/lib/getuser.S Sat Mar 15 18:40:39 2003 @@ -30,7 +30,7 @@ #include .text - .p2align + .p2align 4 .globl __get_user_1 __get_user_1: GET_THREAD_INFO(%rbx) @@ -40,7 +40,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_2 __get_user_2: GET_THREAD_INFO(%rbx) @@ -52,7 +52,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_4 __get_user_4: GET_THREAD_INFO(%rbx) @@ -64,7 +64,7 @@ xorq %rax,%rax ret - .p2align + .p2align 4 .globl __get_user_8 __get_user_8: GET_THREAD_INFO(%rbx) diff -Nru a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c --- a/arch/x86_64/mm/pageattr.c Sat Mar 15 18:40:42 2003 +++ b/arch/x86_64/mm/pageattr.c Sat Mar 15 18:40:42 2003 @@ -53,7 +53,7 @@ static void flush_kernel_map(void *address) { - if (address && cpu_has_clflush) { + if (0 && address && cpu_has_clflush) { /* is this worth it? */ int i; for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) diff -Nru a/arch/x86_64/pci/direct.c b/arch/x86_64/pci/direct.c --- a/arch/x86_64/pci/direct.c Sat Mar 15 18:40:45 2003 +++ b/arch/x86_64/pci/direct.c Sat Mar 15 18:40:45 2003 @@ -196,21 +196,35 @@ static int __devinit pci_sanity_check(struct pci_ops *o) { u32 x = 0; - struct pci_bus bus; /* Fake bus and device */ - struct pci_dev dev; + int retval = 0; + struct pci_bus *bus; /* Fake bus and device */ + struct pci_dev *dev; if (pci_probe & PCI_NO_CHECKS) return 1; - bus.number = 0; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++) - if ((!o->read(&bus, dev.devfn, PCI_CLASS_DEVICE, 2, &x) && + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + + bus->number = 0; + dev->bus = bus; + for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++) + if ((!o->read(bus, dev->devfn, PCI_CLASS_DEVICE, 2, &x) && (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || - (!o->read(&bus, dev.devfn, PCI_VENDOR_ID, 2, &x) && - (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) - return 1; + (!o->read(bus, dev->devfn, PCI_VENDOR_ID, 2, &x) && + (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) { + retval = 1; + goto exit; + } DBG("PCI: Sanity check failed\n"); - return 0; +exit: + kfree(dev); + kfree(bus); + return retval; } static int __init pci_direct_init(void) @@ -218,7 +232,7 @@ unsigned int tmp; unsigned long flags; - local_save_flags(flags); local_irq_disable(); + local_irq_save(flags); /* * Check if configuration type 1 works. @@ -261,7 +275,6 @@ } local_irq_restore(flags); - pci_root_ops = NULL; return 0; } diff -Nru a/arch/x86_64/pci/irq.c b/arch/x86_64/pci/irq.c --- a/arch/x86_64/pci/irq.c Sat Mar 15 18:40:42 2003 +++ b/arch/x86_64/pci/irq.c Sat Mar 15 18:40:42 2003 @@ -109,7 +109,7 @@ */ if (busmap[i] && pci_scan_bus(i, pci_root_bus->ops, NULL)) printk(KERN_INFO "PCI: Discovered primary peer bus %02x [IRQ]\n", i); - pcibios_last_bus = -1; + //pcibios_last_bus = -1; } /* @@ -291,14 +291,14 @@ { irq = read_config_nybble(router, 0x56, pirq - 1); } - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d get irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d get irq : %2d\n", dev->vendor, dev->device, pirq, irq); return irq; } static int pirq_amd756_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) { - printk(KERN_INFO "AMD: dev %04x:%04x, router pirq : %d SET irq : %2d\n", + printk(KERN_INFO "AMD756: dev %04x:%04x, router pirq : %d SET irq : %2d\n", dev->vendor, dev->device, pirq, irq); if (pirq <= 4) { diff -Nru a/arch/x86_64/pci/legacy.c b/arch/x86_64/pci/legacy.c --- a/arch/x86_64/pci/legacy.c Sat Mar 15 18:40:39 2003 +++ b/arch/x86_64/pci/legacy.c Sat Mar 15 18:40:39 2003 @@ -1,8 +1,8 @@ /* * legacy.c - traditional, old school PCI bus probing */ -#include #include +#include #include "pci.h" /* @@ -12,28 +12,39 @@ void __devinit pcibios_fixup_peer_bridges(void) { int n; - struct pci_bus bus; - struct pci_dev dev; + struct pci_bus *bus; + struct pci_dev *dev; u16 l; - if (pcibios_last_bus <= 0 || pcibios_last_bus > 0xff) + if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) return; DBG("PCI: Peer bridge fixup\n"); + + bus = kmalloc(sizeof(*bus), GFP_ATOMIC); + dev = kmalloc(sizeof(*dev), GFP_ATOMIC); + if (!bus || !dev) { + printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); + goto exit; + } + for (n=0; n <= pcibios_last_bus; n++) { if (pci_bus_exists(&pci_root_buses, 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) && + 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) { - DBG("Found device at %02x:%02x [%04x]\n", n, dev.devfn, l); + DBG("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; } } +exit: + kfree(dev); + kfree(bus); } static int __init pci_legacy_init(void) diff -Nru a/arch/x86_64/pci/pci.h b/arch/x86_64/pci/pci.h --- a/arch/x86_64/pci/pci.h Sat Mar 15 18:40:41 2003 +++ b/arch/x86_64/pci/pci.h Sat Mar 15 18:40:41 2003 @@ -67,7 +67,6 @@ extern int pcibios_scanned; extern spinlock_t pci_config_lock; -void pcibios_fixup_irqs(void); int pirq_enable_irq(struct pci_dev *dev); extern int (*pcibios_enable_irq)(struct pci_dev *dev); diff -Nru a/arch/x86_64/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Sat Mar 15 18:40:39 2003 +++ b/arch/x86_64/vmlinux.lds.S Sat Mar 15 18:40:39 2003 @@ -98,6 +98,9 @@ *(.initcall7.init) } __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; . = ALIGN(4096); __initramfs_start = .; .init.ramfs : { *(.init.ramfs) } diff -Nru a/crypto/api.c b/crypto/api.c --- a/crypto/api.c Sat Mar 15 18:40:44 2003 +++ b/crypto/api.c Sat Mar 15 18:40:44 2003 @@ -128,8 +128,6 @@ memset(tfm, 0, sizeof(*tfm)); - tfm->crt_ctx = (void*) &tfm[1]; - tfm->__crt_alg = alg; if (crypto_init_flags(tfm, flags)) diff -Nru a/crypto/cipher.c b/crypto/cipher.c --- a/crypto/cipher.c Sat Mar 15 18:40:42 2003 +++ b/crypto/cipher.c Sat Mar 15 18:40:42 2003 @@ -23,7 +23,8 @@ #include "internal.h" typedef void (cryptfn_t)(void *, u8 *, const u8 *); -typedef void (procfn_t)(struct crypto_tfm *, u8 *, u8*, cryptfn_t, int enc); +typedef void (procfn_t)(struct crypto_tfm *, u8 *, + u8*, cryptfn_t, int enc, void *); struct scatter_walk { struct scatterlist *sg; @@ -34,6 +35,13 @@ unsigned int offset; }; +enum km_type crypto_km_types[] = { + KM_USER0, + KM_USER1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, +}; + static inline void xor_64(u8 *a, const u8 *b) { ((u32 *)a)[0] ^= ((u32 *)b)[0]; @@ -159,7 +167,8 @@ static int crypt(struct crypto_tfm *tfm, struct scatterlist *dst, struct scatterlist *src, - unsigned int nbytes, cryptfn_t crfn, procfn_t prfn, int enc) + unsigned int nbytes, cryptfn_t crfn, + procfn_t prfn, int enc, void *info) { struct scatter_walk walk_in, walk_out; const unsigned int bsize = crypto_tfm_alg_blocksize(tfm); @@ -189,7 +198,7 @@ copy_chunks(src_p, &walk_in, bsize, 0); - prfn(tfm, dst_p, src_p, crfn, enc); + prfn(tfm, dst_p, src_p, crfn, enc, info); scatter_done(&walk_in, 0, nbytes); @@ -204,35 +213,35 @@ } static void cbc_process(struct crypto_tfm *tfm, - u8 *dst, u8 *src, cryptfn_t fn, int enc) + u8 *dst, u8 *src, cryptfn_t fn, int enc, void *info) { + u8 *iv = info; + /* Null encryption */ - if (!tfm->crt_cipher.cit_iv) + if (!iv) return; if (enc) { - tfm->crt_u.cipher.cit_xor_block(tfm->crt_cipher.cit_iv, src); - fn(tfm->crt_ctx, dst, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, dst, - crypto_tfm_alg_blocksize(tfm)); + tfm->crt_u.cipher.cit_xor_block(iv, src); + fn(crypto_tfm_ctx(tfm), dst, iv); + memcpy(iv, dst, crypto_tfm_alg_blocksize(tfm)); } else { const int need_stack = (src == dst); u8 stack[need_stack ? crypto_tfm_alg_blocksize(tfm) : 0]; u8 *buf = need_stack ? stack : dst; - fn(tfm->crt_ctx, buf, src); - tfm->crt_u.cipher.cit_xor_block(buf, tfm->crt_cipher.cit_iv); - memcpy(tfm->crt_cipher.cit_iv, src, - crypto_tfm_alg_blocksize(tfm)); + fn(crypto_tfm_ctx(tfm), buf, src); + tfm->crt_u.cipher.cit_xor_block(buf, iv); + memcpy(iv, src, crypto_tfm_alg_blocksize(tfm)); if (buf != dst) memcpy(dst, buf, crypto_tfm_alg_blocksize(tfm)); } } static void ecb_process(struct crypto_tfm *tfm, u8 *dst, u8 *src, - cryptfn_t fn, int enc) + cryptfn_t fn, int enc, void *info) { - fn(tfm->crt_ctx, dst, src); + fn(crypto_tfm_ctx(tfm), dst, src); } static int setkey(struct crypto_tfm *tfm, const u8 *key, unsigned int keylen) @@ -243,7 +252,7 @@ tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; return -EINVAL; } else - return cia->cia_setkey(tfm->crt_ctx, key, keylen, + return cia->cia_setkey(crypto_tfm_ctx(tfm), key, keylen, &tfm->crt_flags); } @@ -252,7 +261,8 @@ struct scatterlist *src, unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + ecb_process, 1, NULL); } static int ecb_decrypt(struct crypto_tfm *tfm, @@ -261,7 +271,8 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, ecb_process, 1); + tfm->__crt_alg->cra_cipher.cia_decrypt, + ecb_process, 1, NULL); } static int cbc_encrypt(struct crypto_tfm *tfm, @@ -270,7 +281,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_encrypt, cbc_process, 1); + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, tfm->crt_cipher.cit_iv); +} + +static int cbc_encrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_encrypt, + cbc_process, 1, iv); } static int cbc_decrypt(struct crypto_tfm *tfm, @@ -279,7 +301,18 @@ unsigned int nbytes) { return crypt(tfm, dst, src, nbytes, - tfm->__crt_alg->cra_cipher.cia_decrypt, cbc_process, 0); + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, tfm->crt_cipher.cit_iv); +} + +static int cbc_decrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return crypt(tfm, dst, src, nbytes, + tfm->__crt_alg->cra_cipher.cia_decrypt, + cbc_process, 0, iv); } static int nocrypt(struct crypto_tfm *tfm, @@ -290,6 +323,14 @@ return -ENOSYS; } +static int nocrypt_iv(struct crypto_tfm *tfm, + struct scatterlist *dst, + struct scatterlist *src, + unsigned int nbytes, u8 *iv) +{ + return -ENOSYS; +} + int crypto_init_cipher_flags(struct crypto_tfm *tfm, u32 flags) { u32 mode = flags & CRYPTO_TFM_MODE_MASK; @@ -318,16 +359,22 @@ case CRYPTO_TFM_MODE_CBC: ops->cit_encrypt = cbc_encrypt; ops->cit_decrypt = cbc_decrypt; + ops->cit_encrypt_iv = cbc_encrypt_iv; + ops->cit_decrypt_iv = cbc_decrypt_iv; break; case CRYPTO_TFM_MODE_CFB: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; case CRYPTO_TFM_MODE_CTR: ops->cit_encrypt = nocrypt; ops->cit_decrypt = nocrypt; + ops->cit_encrypt_iv = nocrypt_iv; + ops->cit_decrypt_iv = nocrypt_iv; break; default: diff -Nru a/crypto/digest.c b/crypto/digest.c --- a/crypto/digest.c Sat Mar 15 18:40:39 2003 +++ b/crypto/digest.c Sat Mar 15 18:40:39 2003 @@ -19,7 +19,7 @@ static void init(struct crypto_tfm *tfm) { - tfm->__crt_alg->cra_digest.dia_init(tfm->crt_ctx); + tfm->__crt_alg->cra_digest.dia_init(crypto_tfm_ctx(tfm)); } static void update(struct crypto_tfm *tfm, @@ -29,7 +29,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); @@ -38,7 +38,7 @@ static void final(struct crypto_tfm *tfm, u8 *out) { - tfm->__crt_alg->cra_digest.dia_final(tfm->crt_ctx, out); + tfm->__crt_alg->cra_digest.dia_final(crypto_tfm_ctx(tfm), out); } static void digest(struct crypto_tfm *tfm, @@ -50,7 +50,7 @@ for (i = 0; i < nsg; i++) { char *p = crypto_kmap(sg[i].page, 0) + sg[i].offset; - tfm->__crt_alg->cra_digest.dia_update(tfm->crt_ctx, + tfm->__crt_alg->cra_digest.dia_update(crypto_tfm_ctx(tfm), p, sg[i].length); crypto_kunmap(p, 0); crypto_yield(tfm); diff -Nru a/crypto/internal.h b/crypto/internal.h --- a/crypto/internal.h Sat Mar 15 18:40:39 2003 +++ b/crypto/internal.h Sat Mar 15 18:40:39 2003 @@ -18,18 +18,12 @@ #include #include -static enum km_type km_types[] = { - KM_USER0, - KM_USER1, - KM_SOFTIRQ0, - KM_SOFTIRQ1, -}; +extern enum km_type crypto_km_types[]; static inline enum km_type crypto_kmap_type(int out) { - return km_types[(in_softirq() ? 2 : 0) + out]; + return crypto_km_types[(in_softirq() ? 2 : 0) + out]; } - static inline void *crypto_kmap(struct page *page, int out) { @@ -50,6 +44,11 @@ static inline u32 crypto_cipher_flags(u32 flags) { return flags & (CRYPTO_TFM_MODE_MASK|CRYPTO_TFM_REQ_WEAK_KEY); +} + +static inline void *crypto_tfm_ctx(struct crypto_tfm *tfm) +{ + return (void *)&tfm[1]; } struct crypto_alg *crypto_alg_lookup(const char *name); diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Sat Mar 15 18:40:44 2003 +++ b/drivers/Makefile Sat Mar 15 18:40:44 2003 @@ -11,9 +11,13 @@ # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so obj-$(CONFIG_PNP) += pnp/ + +# char/ comes before serial/ etc so that the VT console is the boot-time +# default. +obj-y += char/ obj-y += serial/ obj-$(CONFIG_PARPORT) += parport/ -obj-y += base/ char/ block/ misc/ net/ media/ +obj-y += base/ block/ misc/ net/ media/ obj-$(CONFIG_NUBUS) += nubus/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_IDE) += ide/ diff -Nru a/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Sat Mar 15 18:40:41 2003 +++ b/drivers/acorn/block/fd1772.c Sat Mar 15 18:40:41 2003 @@ -1539,11 +1539,9 @@ goto err_disk; } - err = register_blkdev(MAJOR_NR, "fd", &floppy_fops); - if (err) { - printk("Unable to get major %d for floppy\n", MAJOR_NR); + err = register_blkdev(MAJOR_NR, "fd"); + if (err) goto err_disk; - } err = -EBUSY; if (request_dma(FLOPPY_DMA, "fd1772")) { diff -Nru a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c --- a/drivers/acorn/block/mfmhd.c Sat Mar 15 18:40:40 2003 +++ b/drivers/acorn/block/mfmhd.c Sat Mar 15 18:40:40 2003 @@ -1267,11 +1267,9 @@ if (!request_region (mfm_addr, 10, "mfm")) goto out1; - ret = register_blkdev(MAJOR_NR, "mfm", &mfm_fops); - if (ret) { - printk("mfm_init: unable to get major number %d\n", MAJOR_NR); + ret = register_blkdev(MAJOR_NR, "mfm"); + if (ret) goto out2; - } /* Stuff for the assembler routines to get to */ hdc63463_baseaddress = ioaddr(mfm_addr); diff -Nru a/drivers/acorn/net/ether1.c b/drivers/acorn/net/ether1.c --- a/drivers/acorn/net/ether1.c Sat Mar 15 18:40:42 2003 +++ b/drivers/acorn/net/ether1.c Sat Mar 15 18:40:42 2003 @@ -973,23 +973,6 @@ return &priv->stats; } -static int -ether1_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Set or clear the multicast filter for this adaptor. * num_addrs == -1 Promiscuous mode, receive all packets. @@ -1062,7 +1045,6 @@ dev->hard_start_xmit = ether1_sendpacket; dev->get_stats = ether1_getstats; dev->set_multicast_list = ether1_setmulticastlist; - dev->set_mac_address = ether1_set_mac_address; dev->tx_timeout = ether1_timeout; dev->watchdog_timeo = 5 * HZ / 100; diff -Nru a/drivers/acorn/net/ether3.c b/drivers/acorn/net/ether3.c --- a/drivers/acorn/net/ether3.c Sat Mar 15 18:40:44 2003 +++ b/drivers/acorn/net/ether3.c Sat Mar 15 18:40:44 2003 @@ -461,23 +461,6 @@ return &priv->stats; } -static int -ether3_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Set or clear promiscuous/multicast mode filter for this adaptor. * @@ -903,7 +886,6 @@ dev->hard_start_xmit = ether3_sendpacket; dev->get_stats = ether3_getstats; dev->set_multicast_list = ether3_setmulticastlist; - dev->set_mac_address = ether3_set_mac_address; dev->tx_timeout = ether3_timeout; dev->watchdog_timeo = 5 * HZ / 100; diff -Nru a/drivers/acorn/net/etherh.c b/drivers/acorn/net/etherh.c --- a/drivers/acorn/net/etherh.c Sat Mar 15 18:40:44 2003 +++ b/drivers/acorn/net/etherh.c Sat Mar 15 18:40:44 2003 @@ -482,23 +482,6 @@ return 0; } -static int -etherh_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - if (netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - /* - * We'll set the MAC address on the chip when we open it. - */ - - return 0; -} - /* * Initialisation */ @@ -585,7 +568,6 @@ dev->open = etherh_open; dev->stop = etherh_close; - dev->set_mac_address = etherh_set_mac_address; dev->set_config = etherh_set_config; dev->irq = ec->irq; dev->base_addr = ecard_address(ec, ECARD_MEMC, 0); diff -Nru a/drivers/atm/Makefile b/drivers/atm/Makefile --- a/drivers/atm/Makefile Sat Mar 15 18:40:39 2003 +++ b/drivers/atm/Makefile Sat Mar 15 18:40:39 2003 @@ -46,7 +46,7 @@ ifeq ($(CONFIG_ATM_FORE200E_SBA),y) fore_200e-objs += fore200e_sba_fw.o ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y) - CONFIG_ATM_FORE200E_SBA_FW := sba200e_ecd.bin2 + CONFIG_ATM_FORE200E_SBA_FW := $(obj)/sba200e_ecd.bin2 endif endif diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c --- a/drivers/atm/firestream.c Sat Mar 15 18:40:40 2003 +++ b/drivers/atm/firestream.c Sat Mar 15 18:40:40 2003 @@ -1792,7 +1792,7 @@ write_fs (dev, RAC, 0); /* Manual (AN9, page 6) says ASF1=0 means compare Utopia address - * too. I can't find ASF1 anywhere. Anyway, we AND with just hte + * too. I can't find ASF1 anywhere. Anyway, we AND with just the * other bits, then compare with 0, which is exactly what we * want. */ write_fs (dev, RAM, (1 << (28 - FS155_VPI_BITS - FS155_VCI_BITS)) - 1); diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c --- a/drivers/base/bus.c Sat Mar 15 18:40:40 2003 +++ b/drivers/base/bus.c Sat Mar 15 18:40:40 2003 @@ -282,23 +282,25 @@ * Walk the list of drivers that the bus has and call bus_match() * for each pair. If a compatible pair is found, break out and return. */ -static void device_attach(struct device * dev) +static int device_attach(struct device * dev) { struct bus_type * bus = dev->bus; struct list_head * entry; if (dev->driver) { device_bind_driver(dev); - return; + return 1; } if (bus->match) { list_for_each(entry,&bus->drivers.list) { struct device_driver * drv = to_drv(entry); if (!bus_match(dev,drv)) - break; + return 1; } } + + return 0; } @@ -476,6 +478,38 @@ } } + +/* Helper for bus_rescan_devices's iter */ +static int bus_rescan_devices_helper(struct device *dev, void *data) +{ + int *count = data; + + if (!dev->driver && device_attach(dev)) + (*count)++; + + return 0; +} + + +/** + * bus_rescan_devices - rescan devices on the bus for possible drivers + * @bus: the bus to scan. + * + * This function will look for devices on the bus with no driver + * attached and rescan it against existing drivers to see if it + * matches any. Calls device_attach(). Returns the number of devices + * that were sucessfully bound to a driver. + */ +int bus_rescan_devices(struct bus_type * bus) +{ + int count = 0; + + bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); + + return count; +} + + struct bus_type * get_bus(struct bus_type * bus) { return bus ? container_of(subsys_get(&bus->subsys),struct bus_type,subsys) : NULL; @@ -560,6 +594,7 @@ EXPORT_SYMBOL(bus_remove_device); EXPORT_SYMBOL(bus_register); EXPORT_SYMBOL(bus_unregister); +EXPORT_SYMBOL(bus_rescan_devices); EXPORT_SYMBOL(get_bus); EXPORT_SYMBOL(put_bus); EXPORT_SYMBOL(find_bus); diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c --- a/drivers/base/platform.c Sat Mar 15 18:40:40 2003 +++ b/drivers/base/platform.c Sat Mar 15 18:40:40 2003 @@ -9,7 +9,7 @@ #include #include -static struct device legacy_bus = { +struct device legacy_bus = { .name = "legacy bus", .bus_id = "legacy", }; @@ -59,12 +59,9 @@ static int platform_match(struct device * dev, struct device_driver * drv) { - char name[BUS_ID_SIZE]; + struct platform_device *pdev = container_of(dev, struct platform_device, dev); - if (sscanf(dev->bus_id,"%s",name)) - return (strcmp(name,drv->name) == 0); - - return 0; + return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); } struct bus_type platform_bus_type = { @@ -78,5 +75,7 @@ return bus_register(&platform_bus_type); } +EXPORT_SYMBOL(legacy_bus); +EXPORT_SYMBOL(platform_bus_type); EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_unregister); diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Sat Mar 15 18:40:43 2003 +++ b/drivers/block/DAC960.c Sat Mar 15 18:40:43 2003 @@ -13,9 +13,6 @@ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for complete details. - The author respectfully requests that any modifications to this software be - sent directly to him for evaluation and testing. - */ @@ -2381,13 +2378,9 @@ /* Register the Block Device Major Number for this DAC960 Controller. */ - if (register_blkdev(MajorNumber, "dac960", - &DAC960_BlockDeviceOperations) < 0) - { - DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", - Controller, MajorNumber); + if (register_blkdev(MajorNumber, "dac960") < 0) return false; - } + /* Initialize the I/O Request Queue. */ diff -Nru a/drivers/block/acsi.c b/drivers/block/acsi.c --- a/drivers/block/acsi.c Sat Mar 15 18:40:45 2003 +++ b/drivers/block/acsi.c Sat Mar 15 18:40:45 2003 @@ -1613,7 +1613,6 @@ int acsi_init( void ) - { int err = 0; int i, target, lun; @@ -1623,8 +1622,7 @@ #endif if (!MACH_IS_ATARI || !ATARIHW_PRESENT(ACSI)) return 0; - if (register_blkdev( ACSI_MAJOR, "ad", &acsi_fops )) { - printk( KERN_ERR "Unable to get major %d for ACSI\n", ACSI_MAJOR ); + if (register_blkdev(ACSI_MAJOR, "ad")) { err = -EBUSY; goto out1; } diff -Nru a/drivers/block/amiflop.c b/drivers/block/amiflop.c --- a/drivers/block/amiflop.c Sat Mar 15 18:40:41 2003 +++ b/drivers/block/amiflop.c Sat Mar 15 18:40:41 2003 @@ -1754,10 +1754,9 @@ if (!AMIGAHW_PRESENT(AMI_FLOPPY)) return -ENXIO; - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk("fd: Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - } + /* * We request DSKPTR, DSKLEN and DSKDATA only, because the other * floppy registers are too spreaded over the custom register space diff -Nru a/drivers/block/ataflop.c b/drivers/block/ataflop.c --- a/drivers/block/ataflop.c Sat Mar 15 18:40:40 2003 +++ b/drivers/block/ataflop.c Sat Mar 15 18:40:40 2003 @@ -1929,10 +1929,8 @@ /* Hades doesn't have Atari-compatible floppy */ return -ENXIO; - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk(KERN_ERR "Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) return -EBUSY; - } for (i = 0; i < FD_MAX_UNITS; i++) { unit[i].disk = alloc_disk(1); diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c --- a/drivers/block/cciss.c Sat Mar 15 18:40:44 2003 +++ b/drivers/block/cciss.c Sat Mar 15 18:40:44 2003 @@ -2064,7 +2064,7 @@ unchar cache_line_size, latency_timer; unchar irq, revision; uint addr[6]; - __u32 board_id; + __u32 board_id, scratchpad = 0; int cfg_offset; int cfg_base_addr; int cfg_base_addr_index; @@ -2156,6 +2156,20 @@ #endif /* CCISS_DEBUG */ c->vaddr = remap_pci_mem(c->paddr, 200); + /* Wait for the board to become ready. (PCI hotplug needs this.) + * We poll for up to 120 secs, once per 100ms. */ + for (i=0; i < 1200; i++) { + scratchpad = readl(c->vaddr + SA5_SCRATCHPAD_OFFSET); + if (scratchpad == CCISS_FIRMWARE_READY) + break; + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(HZ / 10); /* wait 100ms */ + } + if (scratchpad != CCISS_FIRMWARE_READY) { + printk(KERN_WARNING "cciss: Board not ready. Timed out.\n"); + return -1; + } + /* get the address index number */ cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET); /* I am not prepared to deal with a 64 bit address value */ @@ -2437,14 +2451,12 @@ return -ENODEV; } - if( register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname, &cciss_fops)) - { - printk(KERN_ERR "cciss: Unable to get major number " - "%d for %s\n", COMPAQ_CISS_MAJOR+i, hba[i]->devname); + if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) { release_io_mem(hba[i]); free_hba(i); - return(-1); + return -1; } + /* make sure the board interrupts are off */ hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF); if( request_irq(hba[i]->intr, do_cciss_intr, diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h --- a/drivers/block/cciss.h Sat Mar 15 18:40:39 2003 +++ b/drivers/block/cciss.h Sat Mar 15 18:40:39 2003 @@ -95,6 +95,7 @@ #define SA5_REPLY_INTR_MASK_OFFSET 0x34 #define SA5_REPLY_PORT_OFFSET 0x44 #define SA5_INTR_STATUS 0x30 +#define SA5_SCRATCHPAD_OFFSET 0xB0 #define SA5_CTCFG_OFFSET 0xB4 #define SA5_CTMEM_OFFSET 0xB8 @@ -104,6 +105,7 @@ #define SA5_INTR_PENDING 0x08 #define SA5B_INTR_PENDING 0x04 #define FIFO_EMPTY 0xffffffff +#define CCISS_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */ #define CISS_ERROR_BIT 0x02 diff -Nru a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c --- a/drivers/block/cpqarray.c Sat Mar 15 18:40:40 2003 +++ b/drivers/block/cpqarray.c Sat Mar 15 18:40:40 2003 @@ -339,11 +339,9 @@ for(i=0; i < nr_ctlr; i++) { /* If this successful it should insure that we are the only */ /* instance of the driver */ - if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname, &ida_fops)) { - printk(KERN_ERR "cpqarray: Unable to get major number %d for ida\n", - COMPAQ_SMART2_MAJOR+i); + if (register_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname)) continue; - } + hba[i]->access.set_intr_mask(hba[i], 0); if (request_irq(hba[i]->intr, do_ida_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i])) { diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c --- a/drivers/block/floppy.c Sat Mar 15 18:40:40 2003 +++ b/drivers/block/floppy.c Sat Mar 15 18:40:40 2003 @@ -4232,8 +4232,7 @@ } devfs_mk_dir (NULL, "floppy", NULL); - if (register_blkdev(FLOPPY_MAJOR,"fd",&floppy_fops)) { - printk("Unable to get major %d for floppy\n",FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR,"fd")) { err = -EBUSY; goto out; } diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Sat Mar 15 18:40:41 2003 +++ b/drivers/block/genhd.c Sat Mar 15 18:40:41 2003 @@ -14,10 +14,16 @@ #include #include +#define MAX_PROBE_HASH 255 /* random */ static struct subsystem block_subsys; -#define MAX_PROBE_HASH 23 /* random */ +/* Can be merged with blk_probe or deleted altogether. Later. */ +static struct blk_major_name { + struct blk_major_name *next; + int major; + char name[16]; +} *major_names[MAX_PROBE_HASH]; static struct blk_probe { struct blk_probe *next; @@ -30,9 +36,125 @@ } *probes[MAX_PROBE_HASH]; /* index in the above - for now: assume no multimajor ranges */ +static inline int major_to_index(int major) +{ + return major % MAX_PROBE_HASH; +} + static inline int dev_to_index(dev_t dev) { - return MAJOR(dev) % MAX_PROBE_HASH; + return major_to_index(MAJOR(dev)); +} + +const char *__bdevname(dev_t dev) +{ + static char buffer[40]; + char *name = "unknown-block"; + unsigned int major = MAJOR(dev); + unsigned int minor = MINOR(dev); + int index = major_to_index(major); + struct blk_major_name *n; + + down_read(&block_subsys.rwsem); + for (n = major_names[index]; n; n = n->next) + if (n->major == major) + break; + if (n) + name = &(n->name[0]); + sprintf(buffer, "%s(%u,%u)", name, major, minor); + up_read(&block_subsys.rwsem); + + return buffer; +} + +/* get block device names in somewhat random order */ +int get_blkdev_list(char *p) +{ + struct blk_major_name *n; + int i, len; + + len = sprintf(p, "\nBlock devices:\n"); + + down_read(&block_subsys.rwsem); + for (i = 0; i < ARRAY_SIZE(major_names); i++) { + for (n = major_names[i]; n; n = n->next) + len += sprintf(p+len, "%3d %s\n", + n->major, n->name); + } + up_read(&block_subsys.rwsem); + + return len; +} + +int register_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n, *p; + int index, ret = 0; + + /* temporary */ + if (major == 0) { + down_read(&block_subsys.rwsem); + for (index = ARRAY_SIZE(major_names)-1; index > 0; index--) + if (major_names[index] == NULL) + break; + up_read(&block_subsys.rwsem); + + if (index == 0) { + printk("register_blkdev: failed to get major for %s\n", + name); + return -EBUSY; + } + ret = major = index; + } + + p = kmalloc(sizeof(struct blk_major_name), GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + + p->major = major; + strncpy(p->name, name, sizeof(p->name)-1); + p->name[sizeof(p->name)-1] = 0; + p->next = 0; + index = major_to_index(major); + + down_write(&block_subsys.rwsem); + for (n = &major_names[index]; *n; n = &(*n)->next) + if ((*n)->major == major) + break; + if (!*n) + *n = p; + else + ret = -EBUSY; + up_write(&block_subsys.rwsem); + + if (ret < 0) + printk("register_blkdev: cannot get major %d for %s\n", + major, name); + + return ret; +} + +/* todo: make void - error printk here */ +int unregister_blkdev(unsigned int major, const char *name) +{ + struct blk_major_name **n, *p; + int index = major_to_index(major); + int ret = 0; + + down_write(&block_subsys.rwsem); + for (n = &major_names[index]; *n; n = &(*n)->next) + if ((*n)->major == major) + break; + if (!*n || strcmp((*n)->name, name)) + ret = -EINVAL; + else { + p = *n; + *n = p->next; + kfree(p); + } + up_write(&block_subsys.rwsem); + + return ret; } /* @@ -48,6 +170,9 @@ struct blk_probe *p = kmalloc(sizeof(struct blk_probe), GFP_KERNEL); struct blk_probe **s; + if (p == NULL) + return; + p->owner = module; p->get = probe; p->lock = lock; @@ -98,9 +223,9 @@ /** * add_gendisk - add partitioning information to kernel list - * @gp: per-device partitioning information + * @disk: per-device partitioning information * - * This function registers the partitioning information in @gp + * This function registers the partitioning information in @disk * with the kernel. */ void add_disk(struct gendisk *disk) @@ -318,7 +443,7 @@ return (jif / HZ) * 1000 + (jif % HZ) * 1000 / HZ; #endif } -static ssize_t disk_stat_read(struct gendisk * disk, char *page) +static ssize_t disk_stats_read(struct gendisk * disk, char *page) { disk_round_stats(disk); return sprintf(page, @@ -326,14 +451,16 @@ "%8u %8u %8llu %8u " "%8u %8u %8u" "\n", - disk->reads, disk->read_merges, - (unsigned long long)disk->read_sectors, - jiffies_to_msec(disk->read_ticks), - disk->writes, disk->write_merges, - (unsigned long long)disk->write_sectors, - jiffies_to_msec(disk->write_ticks), - disk->in_flight, jiffies_to_msec(disk->io_ticks), - jiffies_to_msec(disk->time_in_queue)); + disk_stat_read(disk, reads), disk_stat_read(disk, read_merges), + (unsigned long long)disk_stat_read(disk, read_sectors), + jiffies_to_msec(disk_stat_read(disk, read_ticks)), + disk_stat_read(disk, writes), + disk_stat_read(disk, write_merges), + (unsigned long long)disk_stat_read(disk, write_sectors), + jiffies_to_msec(disk_stat_read(disk, write_ticks)), + disk_stat_read(disk, in_flight), + jiffies_to_msec(disk_stat_read(disk, io_ticks)), + jiffies_to_msec(disk_stat_read(disk, time_in_queue))); } static struct disk_attribute disk_attr_dev = { .attr = {.name = "dev", .mode = S_IRUGO }, @@ -349,7 +476,7 @@ }; static struct disk_attribute disk_attr_stat = { .attr = {.name = "stat", .mode = S_IRUGO }, - .show = disk_stat_read + .show = disk_stats_read }; static struct attribute * default_attrs[] = { @@ -365,6 +492,7 @@ struct gendisk *disk = to_disk(kobj); kfree(disk->random); kfree(disk->part); + free_disk_stats(disk); kfree(disk); } @@ -384,6 +512,10 @@ struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL); if (disk) { memset(disk, 0, sizeof(struct gendisk)); + if (!init_disk_stats(disk)) { + kfree(disk); + return NULL; + } if (minors > 1) { int size = (minors - 1) * sizeof(struct hd_struct); disk->part = kmalloc(size, GFP_KERNEL); diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c --- a/drivers/block/ll_rw_blk.c Sat Mar 15 18:40:39 2003 +++ b/drivers/block/ll_rw_blk.c Sat Mar 15 18:40:40 2003 @@ -1040,7 +1040,8 @@ static void blk_unplug_work(void *data) { - generic_unplug_device(data); + request_queue_t *q = data; + q->unplug_fn(q); } static void blk_unplug_timeout(unsigned long data) @@ -1475,17 +1476,17 @@ return; if (rw == READ) { - rq->rq_disk->read_sectors += nr_sectors; + disk_stat_add(rq->rq_disk, read_sectors, nr_sectors); if (!new_io) - rq->rq_disk->read_merges++; + disk_stat_inc(rq->rq_disk, read_merges); } else if (rw == WRITE) { - rq->rq_disk->write_sectors += nr_sectors; + disk_stat_add(rq->rq_disk, write_sectors, nr_sectors); if (!new_io) - rq->rq_disk->write_merges++; + disk_stat_inc(rq->rq_disk, write_merges); } if (new_io) { disk_round_stats(rq->rq_disk); - rq->rq_disk->in_flight++; + disk_stat_inc(rq->rq_disk, in_flight); } } @@ -1525,11 +1526,12 @@ { unsigned long now = jiffies; - disk->time_in_queue += disk->in_flight * (now - disk->stamp); + disk_stat_add(disk, time_in_queue, + disk_stat_read(disk, in_flight) * (now - disk->stamp)); disk->stamp = now; - if (disk->in_flight) - disk->io_ticks += (now - disk->stamp_idle); + if (disk_stat_read(disk, in_flight)) + disk_stat_add(disk, io_ticks, (now - disk->stamp_idle)); disk->stamp_idle = now; } @@ -1647,7 +1649,7 @@ if (req->rq_disk) { disk_round_stats(req->rq_disk); - req->rq_disk->in_flight--; + disk_stat_dec(req->rq_disk, in_flight); } __blk_put_request(q, next); @@ -2199,16 +2201,16 @@ unsigned long duration = jiffies - req->start_time; switch (rq_data_dir(req)) { case WRITE: - disk->writes++; - disk->write_ticks += duration; + disk_stat_inc(disk, writes); + disk_stat_add(disk, write_ticks, duration); break; case READ: - disk->reads++; - disk->read_ticks += duration; + disk_stat_inc(disk, reads); + disk_stat_add(disk, read_ticks, duration); break; } disk_round_stats(disk); - disk->in_flight--; + disk_stat_dec(disk, in_flight); } __blk_put_request(req->q, req); } diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Sat Mar 15 18:40:42 2003 +++ b/drivers/block/loop.c Sat Mar 15 18:40:42 2003 @@ -1017,11 +1017,8 @@ max_loop = 8; } - if (register_blkdev(LOOP_MAJOR, "loop", &lo_fops)) { - printk(KERN_WARNING "Unable to get major number %d for loop" - " device\n", LOOP_MAJOR); + if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; - } devfs_mk_dir(NULL, "loop", NULL); diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Sat Mar 15 18:40:40 2003 +++ b/drivers/block/nbd.c Sat Mar 15 18:40:40 2003 @@ -564,9 +564,7 @@ nbd_dev[i].disk = disk; } - if (register_blkdev(NBD_MAJOR, "nbd", &nbd_fops)) { - printk("Unable to get major number %d for NBD\n", - NBD_MAJOR); + if (register_blkdev(NBD_MAJOR, "nbd")) { err = -EIO; goto out; } diff -Nru a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c --- a/drivers/block/paride/pcd.c Sat Mar 15 18:40:44 2003 +++ b/drivers/block/paride/pcd.c Sat Mar 15 18:40:44 2003 @@ -942,8 +942,7 @@ /* get the atapi capabilities page */ pcd_probe_capabilities(); - if (register_blkdev(major, name, &pcd_bdops)) { - printk("pcd: unable to get major number %d\n", major); + if (register_blkdev(major, name)) { for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) put_disk(cd->disk); return -1; diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c --- a/drivers/block/paride/pd.c Sat Mar 15 18:40:44 2003 +++ b/drivers/block/paride/pd.c Sat Mar 15 18:40:44 2003 @@ -890,10 +890,9 @@ { if (disable) return -1; - if (register_blkdev(major, name, &pd_fops)) { - printk("%s: unable to get major number %d\n", name, major); + if (register_blkdev(major, name)) return -1; - } + blk_init_queue(&pd_queue, do_pd_request, &pd_lock); blk_queue_max_sectors(&pd_queue, cluster); diff -Nru a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c --- a/drivers/block/paride/pf.c Sat Mar 15 18:40:43 2003 +++ b/drivers/block/paride/pf.c Sat Mar 15 18:40:43 2003 @@ -957,8 +957,7 @@ return -1; pf_busy = 0; - if (register_blkdev(major, name, &pf_fops)) { - printk("pf_init: unable to get major number %d\n", major); + if (register_blkdev(major, name)) { for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) put_disk(pf->disk); return -1; @@ -969,6 +968,7 @@ for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) { struct gendisk *disk = pf->disk; + if (!pf->present) continue; disk->private_data = pf; diff -Nru a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c --- a/drivers/block/ps2esdi.c Sat Mar 15 18:40:39 2003 +++ b/drivers/block/ps2esdi.c Sat Mar 15 18:40:39 2003 @@ -146,13 +146,10 @@ int error = 0; - /* register the device - pass the name, major number and operations - vector . */ - if (register_blkdev(PS2ESDI_MAJOR, "ed", &ps2esdi_fops)) { - printk("%s: Unable to get major number %d\n", DEVICE_NAME, - PS2ESDI_MAJOR); + /* register the device - pass the name and major number */ + if (register_blkdev(PS2ESDI_MAJOR, "ed")) return -1; - } + /* set up some global information - indicating device specific info */ blk_init_queue(&ps2esdi_queue, do_ps2esdi_request, &ps2esdi_lock); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Sat Mar 15 18:40:42 2003 +++ b/drivers/block/rd.c Sat Mar 15 18:40:42 2003 @@ -409,8 +409,7 @@ goto out; } - if (register_blkdev(RAMDISK_MAJOR, "ramdisk", &rd_bd_op)) { - printk("RAMDISK: Could not get major %d", RAMDISK_MAJOR); + if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) { err = -EIO; goto out; } diff -Nru a/drivers/block/swim3.c b/drivers/block/swim3.c --- a/drivers/block/swim3.c Sat Mar 15 18:40:41 2003 +++ b/drivers/block/swim3.c Sat Mar 15 18:40:41 2003 @@ -1004,9 +1004,7 @@ goto out; } - if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) { - printk(KERN_ERR"Unable to get major %d for floppy\n", - FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR, "fd")) { err = -EBUSY; goto out; } diff -Nru a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c --- a/drivers/block/swim_iop.c Sat Mar 15 18:40:39 2003 +++ b/drivers/block/swim_iop.c Sat Mar 15 18:40:39 2003 @@ -137,13 +137,12 @@ current_req = NULL; floppy_count = 0; - if (!iop_ism_present) return -ENODEV; + if (!iop_ism_present) + return -ENODEV; - if (register_blkdev(FLOPPY_MAJOR, "fd", &floppy_fops)) { - printk(KERN_ERR "SWIM-IOP: Unable to get major %d for floppy\n", - FLOPPY_MAJOR); + if (register_blkdev(FLOPPY_MAJOR, "fd")) return -EBUSY; - } + blk_init_queue(&swim_queue, do_fd_request, &swim_iop_lock); printk("SWIM-IOP: %s by Joshua M. Thompson (funaho@jurai.org)\n", DRIVER_VERSION); diff -Nru a/drivers/block/umem.c b/drivers/block/umem.c --- a/drivers/block/umem.c Sat Mar 15 18:40:45 2003 +++ b/drivers/block/umem.c Sat Mar 15 18:40:45 2003 @@ -1145,11 +1145,9 @@ if (retval) return -ENOMEM; - err = major_nr = register_blkdev(0, "umem", &mm_fops); - if (err < 0) { - printk(KERN_ERR "MM: Could not register block device\n"); + err = major_nr = register_blkdev(0, "umem"); + if (err < 0) return -EIO; - } for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); diff -Nru a/drivers/block/xd.c b/drivers/block/xd.c --- a/drivers/block/xd.c Sat Mar 15 18:40:44 2003 +++ b/drivers/block/xd.c Sat Mar 15 18:40:44 2003 @@ -154,9 +154,9 @@ #ifdef MODULE for (i = 4; i > 0; i--) - if(((xd[i] = xd[i-1]) >= 0) && !count) + if (((xd[i] = xd[i-1]) >= 0) && !count) count = i; - if((xd[0] = count)) + if ((xd[0] = count)) do_xd_setup(xd); #endif @@ -170,10 +170,9 @@ } err = -EBUSY; - if (register_blkdev(XT_DISK_MAJOR,"xd",&xd_fops)) { - printk("xd: Unable to get major number %d\n",XT_DISK_MAJOR); + if (register_blkdev(XT_DISK_MAJOR, "xd")) goto out1; - } + devfs_mk_dir(NULL, "xd", NULL); blk_init_queue(&xd_queue, do_xd_request, &xd_lock); if (xd_detect(&controller,&address)) { diff -Nru a/drivers/block/z2ram.c b/drivers/block/z2ram.c --- a/drivers/block/z2ram.c Sat Mar 15 18:40:43 2003 +++ b/drivers/block/z2ram.c Sat Mar 15 18:40:43 2003 @@ -331,21 +331,18 @@ static struct request_queue z2_queue; int __init -z2_init( void ) +z2_init(void) { - if ( !MACH_IS_AMIGA ) + if (!MACH_IS_AMIGA) return -ENXIO; - if ( register_blkdev( Z2RAM_MAJOR, DEVICE_NAME, &z2_fops ) ) - { - printk( KERN_ERR DEVICE_NAME ": Unable to get major %d\n", - Z2RAM_MAJOR ); + if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME)) return -EBUSY; - } + z2ram_gendisk = alloc_disk(1); if (!z2ram_gendisk) { - unregister_blkdev( Z2RAM_MAJOR, DEVICE_NAME ); + unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME); return -ENOMEM; } z2ram_gendisk->major = Z2RAM_MAJOR; diff -Nru a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c --- a/drivers/cdrom/aztcd.c Sat Mar 15 18:40:44 2003 +++ b/drivers/cdrom/aztcd.c Sat Mar 15 18:40:44 2003 @@ -1910,12 +1910,12 @@ azt_disk = alloc_disk(1); if (!azt_disk) goto err_out; - if (register_blkdev(MAJOR_NR, "aztcd", &azt_fops) != 0) { - printk(KERN_WARNING "aztcd: Unable to get major %d for Aztech" - " CD-ROM\n", MAJOR_NR); + + if (register_blkdev(MAJOR_NR, "aztcd")) { ret = -EIO; goto err_out2; } + blk_init_queue(&azt_queue, do_aztcd_request, &aztSpin); blk_queue_hardsect_size(&azt_queue, 2048); azt_disk->major = MAJOR_NR; @@ -1931,7 +1931,7 @@ azt_invalidate_buffers(); aztPresent = 1; aztCloseDoor(); - return (0); + return 0; err_out2: put_disk(azt_disk); err_out: diff -Nru a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c --- a/drivers/cdrom/cdu31a.c Sat Mar 15 18:40:43 2003 +++ b/drivers/cdrom/cdu31a.c Sat Mar 15 18:40:43 2003 @@ -3368,11 +3368,8 @@ if (!request_region(cdu31a_port, 4, "cdu31a")) goto errout3; - if (register_blkdev(MAJOR_NR, "cdu31a", &scd_bdops)) { - printk("Unable to get major %d for CDU-31a\n", - MAJOR_NR); + if (register_blkdev(MAJOR_NR, "cdu31a")) goto errout2; - } disk = alloc_disk(1); if (!disk) diff -Nru a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c --- a/drivers/cdrom/cm206.c Sat Mar 15 18:40:44 2003 +++ b/drivers/cdrom/cm206.c Sat Mar 15 18:40:44 2003 @@ -1489,10 +1489,10 @@ goto out_probe; } printk(".\n"); - if (register_blkdev(MAJOR_NR, "cm206", &cm206_bdops) != 0) { - printk(KERN_INFO "Cannot register for major %d!\n", MAJOR_NR); + + if (register_blkdev(MAJOR_NR, "cm206")) goto out_blkdev; - } + disk = alloc_disk(1); if (!disk) goto out_disk; diff -Nru a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c --- a/drivers/cdrom/gscd.c Sat Mar 15 18:40:39 2003 +++ b/drivers/cdrom/gscd.c Sat Mar 15 18:40:39 2003 @@ -959,12 +959,11 @@ gscd_disk->fops = &gscd_fops; sprintf(gscd_disk->disk_name, "gscd"); - if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) { - printk(KERN_WARNING "GSCD: Unable to get major %d for GoldStar " - "CD-ROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "gscd")) { ret = -EIO; goto err_out2; } + devfs_register(NULL, "gscd", DEVFS_FL_DEFAULT, MAJOR_NR, 0, S_IFBLK | S_IRUGO | S_IWUGO, &gscd_fops, NULL); diff -Nru a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c --- a/drivers/cdrom/mcd.c Sat Mar 15 18:40:42 2003 +++ b/drivers/cdrom/mcd.c Sat Mar 15 18:40:42 2003 @@ -1068,8 +1068,7 @@ put_disk(disk); return -EIO; } - if (register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) { - printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "mcd")) { put_disk(disk); return -EIO; } diff -Nru a/drivers/cdrom/mcdx.c b/drivers/cdrom/mcdx.c --- a/drivers/cdrom/mcdx.c Sat Mar 15 18:40:41 2003 +++ b/drivers/cdrom/mcdx.c Sat Mar 15 18:40:41 2003 @@ -1193,11 +1193,9 @@ } xtrace(INIT, "init() register blkdev\n"); - if (register_blkdev(MAJOR_NR, "mcdx", &mcdx_bdops) != 0) { + if (register_blkdev(MAJOR_NR, "mcdx")) { release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE); - xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n", - MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR); kfree(stuffp); put_disk(disk); return 1; diff -Nru a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c --- a/drivers/cdrom/optcd.c Sat Mar 15 18:40:40 2003 +++ b/drivers/cdrom/optcd.c Sat Mar 15 18:40:40 2003 @@ -2047,8 +2047,7 @@ put_disk(optcd_disk); return -EIO; } - if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0) { - printk(KERN_ERR "optcd: unable to get major %d\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "optcd")) { release_region(optcd_port, 4); put_disk(optcd_disk); return -EIO; diff -Nru a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c --- a/drivers/cdrom/sbpcd.c Sat Mar 15 18:40:40 2003 +++ b/drivers/cdrom/sbpcd.c Sat Mar 15 18:40:40 2003 @@ -5795,15 +5795,14 @@ OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ #endif /* SOUND_BASE */ - if (register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) - { - msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, major_name)) { #ifdef MODULE return -EIO; #else goto init_done; #endif /* MODULE */ } + blk_init_queue(&sbpcd_queue, do_sbpcd_request, &sbpcd_lock); devfs_mk_dir (NULL, "sbp", NULL); diff -Nru a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c --- a/drivers/cdrom/sjcd.c Sat Mar 15 18:40:43 2003 +++ b/drivers/cdrom/sjcd.c Sat Mar 15 18:40:43 2003 @@ -1677,11 +1677,8 @@ printk("SJCD: sjcd=0x%x: ", sjcd_base); #endif - if (register_blkdev(MAJOR_NR, "sjcd", &sjcd_fops) != 0) { - printk("SJCD: Unable to get major %d for Sanyo CD-ROM\n", - MAJOR_NR); - return (-EIO); - } + if (register_blkdev(MAJOR_NR, "sjcd")) + return -EIO; blk_init_queue(&sjcd_queue, do_sjcd_request, &sjcd_lock); blk_queue_hardsect_size(&sjcd_queue, 2048); diff -Nru a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c --- a/drivers/cdrom/sonycd535.c Sat Mar 15 18:40:41 2003 +++ b/drivers/cdrom/sonycd535.c Sat Mar 15 18:40:41 2003 @@ -1546,9 +1546,7 @@ printk("IRQ%d, ", tmp_irq); printk("using %d byte buffer\n", sony_buffer_size); - if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { - printk("Unable to get major %d for %s\n", - MAJOR_NR, CDU535_MESSAGE_NAME); + if (register_blkdev(MAJOR_NR, CDU535_HANDLE)) { err = -EIO; goto out1; } diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Sat Mar 15 18:40:39 2003 +++ b/drivers/char/Kconfig Sat Mar 15 18:40:39 2003 @@ -709,39 +709,20 @@ If you're not sure, say N. -config INTEL_RNG - tristate "Intel i8x0 Random Number Generator support" +config HW_RANDOM + tristate "Intel/AMD/VIA HW Random Number Generator support" depends on (X86 || IA64) && PCI ---help--- This driver provides kernel-side support for the Random Number - Generator hardware found on Intel i8xx-based motherboards. + Generator hardware found on Intel i8xx-based motherboards, + AMD 76x-based motherboards, and Via Nehemiah CPUs. - Both a character driver, used to read() entropy data, and a timer - function which automatically adds entropy directly into the - kernel pool, are exported by this driver. + Provides a character driver, used to read() entropy data. To compile this driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read . The module will be called - i810_rng. - - If unsure, say N. - -config AMD_RNG - tristate "AMD 768 Random Number Generator support" - depends on X86 && PCI - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on AMD 76x based motherboards. - - Both a character driver, used to read() entropy data, and a timer - function which automatically adds entropy directly into the - kernel pool, are exported by this driver. - - To compile this driver as a module ( = code which can be inserted in - and removed from the running kernel whenever you want), say M here - and read . The module will be called - amd768_rng. + hw_random. If unsure, say N. diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile --- a/drivers/char/Makefile Sat Mar 15 18:40:44 2003 +++ b/drivers/char/Makefile Sat Mar 15 18:40:44 2003 @@ -59,8 +59,7 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o -obj-$(CONFIG_INTEL_RNG) += i810_rng.o -obj-$(CONFIG_AMD_RNG) += amd768_rng.o +obj-$(CONFIG_HW_RANDOM) += hw_random.o obj-$(CONFIG_QIC02_TAPE) += tpqic02.o obj-$(CONFIG_FTAPE) += ftape/ obj-$(CONFIG_H8) += h8.o diff -Nru a/drivers/char/amd768_rng.c b/drivers/char/amd768_rng.c --- a/drivers/char/amd768_rng.c Sat Mar 15 18:40:41 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,295 +0,0 @@ -/* - Hardware driver for the AMD 768 Random Number Generator (RNG) - (c) Copyright 2001 Red Hat Inc - - derived from - - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik - Copyright 2000,2001 Philipp Rumpf - - Please read Documentation/i810_rng.txt for details on use. - - ---------------------------------------------------------- - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * core module and version information - */ -#define RNG_VERSION "0.1.0" -#define RNG_MODULE_NAME "amd768_rng" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " - - -/* - * debugging macros - */ -#undef RNG_DEBUG /* define to enable copious debugging info */ - -#ifdef RNG_DEBUG -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - -#undef RNG_NDEBUG /* define to disable lightweight runtime checks */ -#ifdef RNG_NDEBUG -#define assert(expr) -#else -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - -#define RNG_MISCDEV_MINOR 183 /* official */ - -/* - * various RNG status variables. they are globals - * as we only support a single RNG device - */ - -static u32 pmbase; /* PMxx I/O base */ -static struct semaphore rng_open_sem; /* Semaphore for serializing rng_open/release */ - - -/* - * inlined helper functions for accessing RNG registers - */ - -static inline int rng_data_present (void) -{ - return inl(pmbase+0xF4) & 1; -} - - -static inline int rng_data_read (void) -{ - return inl(pmbase+0xF0); -} - -static int rng_dev_open (struct inode *inode, struct file *filp) -{ - if ((filp->f_mode & FMODE_READ) == 0) - return -EINVAL; - if (filp->f_mode & FMODE_WRITE) - return -EINVAL; - - /* wait for device to become free */ - if (filp->f_flags & O_NONBLOCK) { - if (down_trylock (&rng_open_sem)) - return -EAGAIN; - } else { - if (down_interruptible (&rng_open_sem)) - return -ERESTARTSYS; - } - return 0; -} - - -static int rng_dev_release (struct inode *inode, struct file *filp) -{ - up(&rng_open_sem); - return 0; -} - - -static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, - loff_t * offp) -{ - static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; - int have_data; - u32 data = 0; - ssize_t ret = 0; - - while (size) { - spin_lock(&rng_lock); - - have_data = 0; - if (rng_data_present()) { - data = rng_data_read(); - have_data = 4; - } - - spin_unlock (&rng_lock); - - while (have_data > 0) { - if (put_user((u8)data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - have_data--; - data>>=8; - } - - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; - - if(need_resched()) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - else - udelay(200); /* FIXME: We could poll for 250uS ?? */ - - if (signal_pending (current)) - return ret ? : -ERESTARTSYS; - } - return ret; -} - - -static struct file_operations rng_chrdev_ops = { - .owner = THIS_MODULE, - .open = rng_dev_open, - .release = rng_dev_release, - .read = rng_dev_read, -}; - - -static struct miscdevice rng_miscdev = { - RNG_MISCDEV_MINOR, - RNG_MODULE_NAME, - &rng_chrdev_ops, -}; - - -/* - * rng_init_one - look for and attempt to init a single RNG - */ -static int __init rng_init_one (struct pci_dev *dev) -{ - int rc; - u8 rnen; - - DPRINTK ("ENTER\n"); - - rc = misc_register (&rng_miscdev); - if (rc) { - printk (KERN_ERR PFX "cannot register misc device\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out; - } - - pci_read_config_dword(dev, 0x58, &pmbase); - - pmbase&=0x0000FF00; - - if(pmbase == 0) - { - printk (KERN_ERR PFX "power management base not set\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out_free_miscdev; - } - - pci_read_config_byte(dev, 0x40, &rnen); - rnen|=(1<<7); /* RNG on */ - pci_write_config_byte(dev, 0x40, rnen); - - pci_read_config_byte(dev, 0x41, &rnen); - rnen|=(1<<7); /* PMIO enable */ - pci_write_config_byte(dev, 0x41, rnen); - - printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase); - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_free_miscdev: - misc_deregister (&rng_miscdev); -err_out: - return rc; -} - - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id rng_pci_tbl[] __initdata = { - { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); - - -MODULE_AUTHOR("Alan Cox, Jeff Garzik, Philipp Rumpf, Matt Sottek"); -MODULE_DESCRIPTION("AMD 768 Random Number Generator (RNG) driver"); -MODULE_LICENSE("GPL"); - - -/* - * rng_init - initialize RNG module - */ -static int __init rng_init (void) -{ - int rc; - struct pci_dev *pdev; - - DPRINTK ("ENTER\n"); - - init_MUTEX (&rng_open_sem); - - pci_for_each_dev(pdev) { - if (pci_match_device (rng_pci_tbl, pdev) != NULL) - goto match; - } - - DPRINTK ("EXIT, returning -ENODEV\n"); - return -ENODEV; - -match: - rc = rng_init_one (pdev); - if (rc) - return rc; - - printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -/* - * rng_init - shutdown RNG module - */ -static void __exit rng_cleanup (void) -{ - DPRINTK ("ENTER\n"); - misc_deregister (&rng_miscdev); - DPRINTK ("EXIT\n"); -} - - -module_init (rng_init); -module_exit (rng_cleanup); diff -Nru a/drivers/char/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Sat Mar 15 18:40:45 2003 +++ b/drivers/char/amiserial.c Sat Mar 15 18:40:45 2003 @@ -2320,10 +2320,11 @@ /* * Register console. */ -void __init serial_console_init(void) +static void __init amiserial_console_init(void) { register_console(&sercons); } +console_initcall(amiserial_console_init); #endif MODULE_LICENSE("GPL"); diff -Nru a/drivers/char/decserial.c b/drivers/char/decserial.c --- a/drivers/char/decserial.c Sat Mar 15 18:40:39 2003 +++ b/drivers/char/decserial.c Sat Mar 15 18:40:39 2003 @@ -75,7 +75,7 @@ /* serial_console_init handles the special case of starting * up the console on the serial port */ -void __init serial_console_init(void) +static void __init decserial_console_init(void) { #if defined(CONFIG_ZS) && defined(CONFIG_DZ) if (IOASIC) @@ -94,5 +94,6 @@ #endif } +console_initcall(decserial_console_init); #endif diff -Nru a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c --- a/drivers/char/hvc_console.c Sat Mar 15 18:40:44 2003 +++ b/drivers/char/hvc_console.c Sat Mar 15 18:40:44 2003 @@ -346,11 +346,12 @@ .index = -1, }; -int __init hvc_console_init(void) +static int __init hvc_console_init(void) { register_console(&hvc_con_driver); return 0; } +console_initcall(hvc_console_init); module_init(hvc_init); module_exit(hvc_exit); diff -Nru a/drivers/char/hw_random.c b/drivers/char/hw_random.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/hw_random.c Sat Mar 15 18:40:41 2003 @@ -0,0 +1,630 @@ +/* + Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG) + (c) Copyright 2003 Red Hat Inc + + derived from + + Hardware driver for the AMD 768 Random Number Generator (RNG) + (c) Copyright 2001 Red Hat Inc + + derived from + + Hardware driver for Intel i810 Random Number Generator (RNG) + Copyright 2000,2001 Jeff Garzik + Copyright 2000,2001 Philipp Rumpf + + Please read Documentation/hw_random.txt for details on use. + + ---------------------------------------------------------- + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __i386__ +#include +#include +#endif + +#include +#include + + +/* + * core module and version information + */ +#define RNG_VERSION "0.9.0" +#define RNG_MODULE_NAME "hw_random" +#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION +#define PFX RNG_MODULE_NAME ": " + + +/* + * debugging macros + */ +#undef RNG_DEBUG /* define to enable copious debugging info */ + +#ifdef RNG_DEBUG +/* note: prints function name for you */ +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define RNG_NDEBUG /* define to disable lightweight runtime checks */ +#ifdef RNG_NDEBUG +#define assert(expr) +#else +#define assert(expr) \ + if(!(expr)) { \ + printk( "Assertion failed! %s,%s,%s,line=%d\n", \ + #expr,__FILE__,__FUNCTION__,__LINE__); \ + } +#endif + +#define RNG_MISCDEV_MINOR 183 /* official */ + +static int rng_dev_open (struct inode *inode, struct file *filp); +static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, + loff_t * offp); + +static int __init intel_init (struct pci_dev *dev); +static void intel_cleanup(void); +static unsigned int intel_data_present (void); +static u32 intel_data_read (void); + +static int __init amd_init (struct pci_dev *dev); +static void amd_cleanup(void); +static unsigned int amd_data_present (void); +static u32 amd_data_read (void); + +static int __init via_init(struct pci_dev *dev); +static void via_cleanup(void); +static unsigned int via_data_present (void); +static u32 via_data_read (void); + +struct rng_operations { + int (*init) (struct pci_dev *dev); + void (*cleanup) (void); + unsigned int (*data_present) (void); + u32 (*data_read) (void); + unsigned int n_bytes; /* number of bytes per ->data_read */ +}; +static struct rng_operations *rng_ops; + +static struct file_operations rng_chrdev_ops = { + .owner = THIS_MODULE, + .open = rng_dev_open, + .read = rng_dev_read, +}; + + +static struct miscdevice rng_miscdev = { + RNG_MISCDEV_MINOR, + RNG_MODULE_NAME, + &rng_chrdev_ops, +}; + +enum { + rng_hw_none, + rng_hw_intel, + rng_hw_amd, + rng_hw_via, +}; + +static struct rng_operations rng_vendor_ops[] __initdata = { + /* rng_hw_none */ + { }, + + /* rng_hw_intel */ + { intel_init, intel_cleanup, intel_data_present, + intel_data_read, 1 }, + + /* rng_hw_amd */ + { amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 }, + + /* rng_hw_via */ + { via_init, via_cleanup, via_data_present, via_data_read, 1 }, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id rng_pci_tbl[] __initdata = { + { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd }, + + { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel }, + + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE (pci, rng_pci_tbl); + + +/*********************************************************************** + * + * Intel RNG operations + * + */ + +/* + * RNG registers (offsets from rng_mem) + */ +#define INTEL_RNG_HW_STATUS 0 +#define INTEL_RNG_PRESENT 0x40 +#define INTEL_RNG_ENABLED 0x01 +#define INTEL_RNG_STATUS 1 +#define INTEL_RNG_DATA_PRESENT 0x01 +#define INTEL_RNG_DATA 2 + +/* + * Magic address at which Intel PCI bridges locate the RNG + */ +#define INTEL_RNG_ADDR 0xFFBC015F +#define INTEL_RNG_ADDR_LEN 3 + +/* token to our ioremap'd RNG register area */ +static void *rng_mem; + +static inline u8 intel_hwstatus (void) +{ + assert (rng_mem != NULL); + return readb (rng_mem + INTEL_RNG_HW_STATUS); +} + +static inline u8 intel_hwstatus_set (u8 hw_status) +{ + assert (rng_mem != NULL); + writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS); + return intel_hwstatus (); +} + +static unsigned int intel_data_present(void) +{ + assert (rng_mem != NULL); + + return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ? + 1 : 0; +} + +static u32 intel_data_read(void) +{ + assert (rng_mem != NULL); + + return readb (rng_mem + INTEL_RNG_DATA); +} + +static int __init intel_init (struct pci_dev *dev) +{ + int rc; + u8 hw_status; + + DPRINTK ("ENTER\n"); + + rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); + if (rng_mem == NULL) { + printk (KERN_ERR PFX "cannot ioremap RNG Memory\n"); + rc = -EBUSY; + goto err_out; + } + + /* Check for Intel 82802 */ + hw_status = intel_hwstatus (); + if ((hw_status & INTEL_RNG_PRESENT) == 0) { + printk (KERN_ERR PFX "RNG not detected\n"); + rc = -ENODEV; + goto err_out_free_map; + } + + /* turn RNG h/w on, if it's off */ + if ((hw_status & INTEL_RNG_ENABLED) == 0) + hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED); + if ((hw_status & INTEL_RNG_ENABLED) == 0) { + printk (KERN_ERR PFX "cannot enable RNG, aborting\n"); + rc = -EIO; + goto err_out_free_map; + } + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out_free_map: + iounmap (rng_mem); + rng_mem = NULL; +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + +static void intel_cleanup(void) +{ + u8 hw_status; + + hw_status = intel_hwstatus (); + if (hw_status & INTEL_RNG_ENABLED) + intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED); + else + printk(KERN_WARNING PFX "unusual: RNG already disabled\n"); + iounmap(rng_mem); + rng_mem = NULL; +} + +/*********************************************************************** + * + * AMD RNG operations + * + */ + +static u32 pmbase; /* PMxx I/O base */ +static struct pci_dev *amd_dev; + +static unsigned int amd_data_present (void) +{ + return inl(pmbase + 0xF4) & 1; +} + + +static u32 amd_data_read (void) +{ + return inl(pmbase + 0xF0); +} + +static int __init amd_init (struct pci_dev *dev) +{ + int rc; + u8 rnen; + + DPRINTK ("ENTER\n"); + + pci_read_config_dword(dev, 0x58, &pmbase); + + pmbase &= 0x0000FF00; + + if (pmbase == 0) + { + printk (KERN_ERR PFX "power management base not set\n"); + rc = -EIO; + goto err_out; + } + + pci_read_config_byte(dev, 0x40, &rnen); + rnen |= (1 << 7); /* RNG on */ + pci_write_config_byte(dev, 0x40, rnen); + + pci_read_config_byte(dev, 0x41, &rnen); + rnen |= (1 << 7); /* PMIO enable */ + pci_write_config_byte(dev, 0x41, rnen); + + printk(KERN_INFO PFX "AMD768 system management I/O registers at 0x%X.\n", pmbase); + + amd_dev = dev; + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + +static void amd_cleanup(void) +{ + u8 rnen; + + pci_read_config_byte(amd_dev, 0x40, &rnen); + rnen &= ~(1 << 7); /* RNG off */ + pci_write_config_byte(amd_dev, 0x40, rnen); + + /* FIXME: twiddle pmio, also? */ +} + +/*********************************************************************** + * + * VIA RNG operations + * + */ + +enum { + VIA_STRFILT_CNT_SHIFT = 16, + VIA_STRFILT_FAIL = (1 << 15), + VIA_STRFILT_ENABLE = (1 << 14), + VIA_RAWBITS_ENABLE = (1 << 13), + VIA_RNG_ENABLE = (1 << 6), + VIA_XSTORE_CNT_MASK = 0x0F, + + VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */ + VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF, + VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_2_MASK = 0xFFFF, + VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */ + VIA_RNG_CHUNK_1_MASK = 0xFF, +}; + +u32 via_rng_datum; + +/* + * Investigate using the 'rep' prefix to obtain 32 bits of random data + * in one insn. The upside is potentially better performance. The + * downside is that the instruction becomes no longer atomic. Due to + * this, just like familiar issues with /dev/random itself, the worst + * case of a 'rep xstore' could potentially pause a cpu for an + * unreasonably long time. In practice, this condition would likely + * only occur when the hardware is failing. (or so we hope :)) + * + * Another possible performance boost may come from simply buffering + * until we have 4 bytes, thus returning a u32 at a time, + * instead of the current u8-at-a-time. + */ + +static inline u32 xstore(u32 *addr, u32 edx_in) +{ + u32 eax_out; + + asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */" + :"=m"(*addr), "=a"(eax_out) + :"D"(addr), "d"(edx_in)); + + return eax_out; +} + +static unsigned int via_data_present(void) +{ + u32 bytes_out; + + /* We choose the recommended 1-byte-per-instruction RNG rate, + * for greater randomness at the expense of speed. Larger + * values 2, 4, or 8 bytes-per-instruction yield greater + * speed at lesser randomness. + * + * If you change this to another VIA_CHUNK_n, you must also + * change the ->n_bytes values in rng_vendor_ops[] tables. + * VIA_CHUNK_8 requires further code changes. + * + * A copy of MSR_VIA_RNG is placed in eax_out when xstore + * completes. + */ + via_rng_datum = 0; /* paranoia, not really necessary */ + bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK; + if (bytes_out == 0) + return 0; + + return 1; +} + +static u32 via_data_read(void) +{ + return via_rng_datum; +} + +static int __init via_init(struct pci_dev *dev) +{ + u32 lo, hi, old_lo; + + /* Control the RNG via MSR. Tread lightly and pay very close + * close attention to values written, as the reserved fields + * are documented to be "undefined and unpredictable"; but it + * does not say to write them as zero, so I make a guess that + * we restore the values we find in the register. + */ + rdmsr(MSR_VIA_RNG, lo, hi); + + old_lo = lo; + lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT); + lo &= ~VIA_XSTORE_CNT_MASK; + lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE); + lo |= VIA_RNG_ENABLE; + + if (lo != old_lo) + wrmsr(MSR_VIA_RNG, lo, hi); + + /* perhaps-unnecessary sanity check; remove after testing if + unneeded */ + rdmsr(MSR_VIA_RNG, lo, hi); + if ((lo & VIA_RNG_ENABLE) == 0) { + printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n"); + return -ENODEV; + } + + return 0; +} + +static void via_cleanup(void) +{ + u32 lo, hi; + + rdmsr(MSR_VIA_RNG, lo, hi); + lo &= ~VIA_RNG_ENABLE; + wrmsr(MSR_VIA_RNG, lo, hi); +} + + +/*********************************************************************** + * + * /dev/hwrandom character device handling (major 10, minor 183) + * + */ + +static int rng_dev_open (struct inode *inode, struct file *filp) +{ + /* enforce read-only access to this chrdev */ + if ((filp->f_mode & FMODE_READ) == 0) + return -EINVAL; + if (filp->f_mode & FMODE_WRITE) + return -EINVAL; + + return 0; +} + + +static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, + loff_t * offp) +{ + static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; + unsigned int have_data; + u32 data = 0; + ssize_t ret = 0; + + while (size) { + spin_lock(&rng_lock); + + have_data = 0; + if (rng_ops->data_present()) { + data = rng_ops->data_read(); + have_data = rng_ops->n_bytes; + } + + spin_unlock (&rng_lock); + + while (have_data > 0) { + if (put_user((u8)data, buf++)) { + ret = ret ? : -EFAULT; + break; + } + size--; + ret++; + have_data--; + data>>=8; + } + + if (filp->f_flags & O_NONBLOCK) + return ret ? : -EAGAIN; + + if(need_resched()) + { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(1); + } + else + udelay(200); /* FIXME: We could poll for 250uS ?? */ + + if (signal_pending (current)) + return ret ? : -ERESTARTSYS; + } + return ret; +} + + + +/* + * rng_init_one - look for and attempt to init a single RNG + */ +static int __init rng_init_one (struct pci_dev *dev) +{ + int rc; + + DPRINTK ("ENTER\n"); + + assert(rng_ops != NULL); + + rc = rng_ops->init(dev); + if (rc) + goto err_out; + + rc = misc_register (&rng_miscdev); + if (rc) { + printk (KERN_ERR PFX "misc device register failed\n"); + goto err_out_cleanup_hw; + } + + DPRINTK ("EXIT, returning 0\n"); + return 0; + +err_out_cleanup_hw: + rng_ops->cleanup(); +err_out: + DPRINTK ("EXIT, returning %d\n", rc); + return rc; +} + + + +MODULE_AUTHOR("The Linux Kernel team"); +MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver"); +MODULE_LICENSE("GPL"); + + +/* + * rng_init - initialize RNG module + */ +static int __init rng_init (void) +{ + int rc; + struct pci_dev *pdev; + const struct pci_device_id *ent; + + DPRINTK ("ENTER\n"); + + /* Probe for Intel, AMD RNGs */ + pci_for_each_dev(pdev) { + ent = pci_match_device (rng_pci_tbl, pdev); + if (ent) { + rng_ops = &rng_vendor_ops[ent->driver_data]; + goto match; + } + } + +#ifdef __i386__ + /* Probe for VIA RNG */ + if (cpu_has_xstore) { + rng_ops = &rng_vendor_ops[rng_hw_via]; + pdev = NULL; + goto match; + } +#endif + + DPRINTK ("EXIT, returning -ENODEV\n"); + return -ENODEV; + +match: + rc = rng_init_one (pdev); + if (rc) + return rc; + + printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); + + DPRINTK ("EXIT, returning 0\n"); + return 0; +} + + +/* + * rng_init - shutdown RNG module + */ +static void __exit rng_cleanup (void) +{ + DPRINTK ("ENTER\n"); + + misc_deregister (&rng_miscdev); + + if (rng_ops->cleanup) + rng_ops->cleanup(); + + DPRINTK ("EXIT\n"); +} + + +module_init (rng_init); +module_exit (rng_cleanup); diff -Nru a/drivers/char/i810_rng.c b/drivers/char/i810_rng.c --- a/drivers/char/i810_rng.c Sat Mar 15 18:40:41 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,404 +0,0 @@ -/* - - Hardware driver for Intel i810 Random Number Generator (RNG) - Copyright 2000,2001 Jeff Garzik - Copyright 2000,2001 Philipp Rumpf - - Driver Web site: http://sourceforge.net/projects/gkernel/ - - Please read Documentation/i810_rng.txt for details on use. - - ---------------------------------------------------------- - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -/* - * core module and version information - */ -#define RNG_VERSION "0.9.8" -#define RNG_MODULE_NAME "i810_rng" -#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION -#define PFX RNG_MODULE_NAME ": " - - -/* - * debugging macros - */ -#undef RNG_DEBUG /* define to enable copious debugging info */ - -#ifdef RNG_DEBUG -/* note: prints function name for you */ -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - -#undef RNG_NDEBUG /* define to disable lightweight runtime checks */ -#ifdef RNG_NDEBUG -#define assert(expr) -#else -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#endif - - -/* - * RNG registers (offsets from rng_mem) - */ -#define RNG_HW_STATUS 0 -#define RNG_PRESENT 0x40 -#define RNG_ENABLED 0x01 -#define RNG_STATUS 1 -#define RNG_DATA_PRESENT 0x01 -#define RNG_DATA 2 - -/* - * Magic address at which Intel PCI bridges locate the RNG - */ -#define RNG_ADDR 0xFFBC015F -#define RNG_ADDR_LEN 3 - -#define RNG_MISCDEV_MINOR 183 /* official */ - -/* - * various RNG status variables. they are globals - * as we only support a single RNG device - */ -static void *rng_mem; /* token to our ioremap'd RNG register area */ -static struct semaphore rng_open_sem; /* Semaphore for serializing rng_open/release */ - - -/* - * inlined helper functions for accessing RNG registers - */ -static inline u8 rng_hwstatus (void) -{ - assert (rng_mem != NULL); - return readb (rng_mem + RNG_HW_STATUS); -} - -static inline u8 rng_hwstatus_set (u8 hw_status) -{ - assert (rng_mem != NULL); - writeb (hw_status, rng_mem + RNG_HW_STATUS); - return rng_hwstatus (); -} - - -static inline int rng_data_present (void) -{ - assert (rng_mem != NULL); - - return (readb (rng_mem + RNG_STATUS) & RNG_DATA_PRESENT) ? 1 : 0; -} - - -static inline int rng_data_read (void) -{ - assert (rng_mem != NULL); - - return readb (rng_mem + RNG_DATA); -} - -/* - * rng_enable - enable the RNG hardware - */ - -static int rng_enable (void) -{ - int rc = 0; - u8 hw_status, new_status; - - DPRINTK ("ENTER\n"); - - hw_status = rng_hwstatus (); - - if ((hw_status & RNG_ENABLED) == 0) { - new_status = rng_hwstatus_set (hw_status | RNG_ENABLED); - - if (new_status & RNG_ENABLED) - printk (KERN_INFO PFX "RNG h/w enabled\n"); - else { - printk (KERN_ERR PFX "Unable to enable the RNG\n"); - rc = -EIO; - } - } - - DPRINTK ("EXIT, returning %d\n", rc); - return rc; -} - -/* - * rng_disable - disable the RNG hardware - */ - -static void rng_disable(void) -{ - u8 hw_status, new_status; - - DPRINTK ("ENTER\n"); - - hw_status = rng_hwstatus (); - - if (hw_status & RNG_ENABLED) { - new_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED); - - if ((new_status & RNG_ENABLED) == 0) - printk (KERN_INFO PFX "RNG h/w disabled\n"); - else { - printk (KERN_ERR PFX "Unable to disable the RNG\n"); - } - } - - DPRINTK ("EXIT\n"); -} - -static int rng_dev_open (struct inode *inode, struct file *filp) -{ - int rc; - - if ((filp->f_mode & FMODE_READ) == 0) - return -EINVAL; - if (filp->f_mode & FMODE_WRITE) - return -EINVAL; - - /* wait for device to become free */ - if (filp->f_flags & O_NONBLOCK) { - if (down_trylock (&rng_open_sem)) - return -EAGAIN; - } else { - if (down_interruptible (&rng_open_sem)) - return -ERESTARTSYS; - } - - rc = rng_enable (); - if (rc) { - up (&rng_open_sem); - return rc; - } - - return 0; -} - - -static int rng_dev_release (struct inode *inode, struct file *filp) -{ - rng_disable (); - up (&rng_open_sem); - return 0; -} - - -static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size, - loff_t * offp) -{ - static spinlock_t rng_lock = SPIN_LOCK_UNLOCKED; - int have_data; - u8 data = 0; - ssize_t ret = 0; - - while (size) { - spin_lock (&rng_lock); - - have_data = 0; - if (rng_data_present ()) { - data = rng_data_read (); - have_data = 1; - } - - spin_unlock (&rng_lock); - - if (have_data) { - if (put_user (data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - } - - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; - - if (need_resched()) - { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - else - udelay(200); - - if (signal_pending (current)) - return ret ? : -ERESTARTSYS; - } - - return ret; -} - - -static struct file_operations rng_chrdev_ops = { - .owner = THIS_MODULE, - .open = rng_dev_open, - .release = rng_dev_release, - .read = rng_dev_read, -}; - - -static struct miscdevice rng_miscdev = { - RNG_MISCDEV_MINOR, - RNG_MODULE_NAME, - &rng_chrdev_ops, -}; - - -/* - * rng_init_one - look for and attempt to init a single RNG - */ -static int __init rng_init_one (struct pci_dev *dev) -{ - int rc; - u8 hw_status; - - DPRINTK ("ENTER\n"); - - rc = misc_register (&rng_miscdev); - if (rc) { - printk (KERN_ERR PFX "cannot register misc device\n"); - DPRINTK ("EXIT, returning %d\n", rc); - goto err_out; - } - - rng_mem = ioremap (RNG_ADDR, RNG_ADDR_LEN); - if (rng_mem == NULL) { - printk (KERN_ERR PFX "cannot ioremap RNG Memory\n"); - DPRINTK ("EXIT, returning -EBUSY\n"); - rc = -EBUSY; - goto err_out_free_miscdev; - } - - /* Check for Intel 82802 */ - hw_status = rng_hwstatus (); - if ((hw_status & RNG_PRESENT) == 0) { - printk (KERN_ERR PFX "RNG not detected\n"); - DPRINTK ("EXIT, returning -ENODEV\n"); - rc = -ENODEV; - goto err_out_free_map; - } - - /* turn RNG h/w off, if it's on */ - if (hw_status & RNG_ENABLED) - hw_status = rng_hwstatus_set (hw_status & ~RNG_ENABLED); - if (hw_status & RNG_ENABLED) { - printk (KERN_ERR PFX "cannot disable RNG, aborting\n"); - goto err_out_free_map; - } - - DPRINTK ("EXIT, returning 0\n"); - return 0; - -err_out_free_map: - iounmap (rng_mem); -err_out_free_miscdev: - misc_deregister (&rng_miscdev); -err_out: - return rc; -} - - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id rng_pci_tbl[] __initdata = { - { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, rng_pci_tbl); - - -MODULE_AUTHOR("Jeff Garzik, Philipp Rumpf, Matt Sottek"); -MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver"); -MODULE_LICENSE("GPL"); - - -/* - * rng_init - initialize RNG module - */ -static int __init rng_init (void) -{ - int rc; - struct pci_dev *pdev; - - DPRINTK ("ENTER\n"); - - init_MUTEX (&rng_open_sem); - - pci_for_each_dev(pdev) { - if (pci_match_device (rng_pci_tbl, pdev) != NULL) - goto match; - } - - DPRINTK ("EXIT, returning -ENODEV\n"); - return -ENODEV; - -match: - rc = rng_init_one (pdev); - if (rc) - return rc; - - printk (KERN_INFO RNG_DRIVER_NAME " loaded\n"); - - DPRINTK ("EXIT, returning 0\n"); - return 0; -} - - -/* - * rng_init - shutdown RNG module - */ -static void __exit rng_cleanup (void) -{ - DPRINTK ("ENTER\n"); - - misc_deregister (&rng_miscdev); - - iounmap (rng_mem); - - DPRINTK ("EXIT\n"); -} - - -module_init (rng_init); -module_exit (rng_cleanup); diff -Nru a/drivers/char/random.c b/drivers/char/random.c --- a/drivers/char/random.c Sat Mar 15 18:40:39 2003 +++ b/drivers/char/random.c Sat Mar 15 18:40:39 2003 @@ -1228,10 +1228,8 @@ * at which point we do a "catastrophic reseeding". */ static inline void xfer_secondary_pool(struct entropy_store *r, - size_t nbytes) + size_t nbytes, __u32 *tmp) { - __u32 tmp[TMP_BUF_SIZE]; - if (r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo.POOLBITS) { int nwords = min_t(int, @@ -1284,7 +1282,7 @@ r->entropy_count = r->poolinfo.POOLBITS; if (flags & EXTRACT_ENTROPY_SECONDARY) - xfer_secondary_pool(r, nbytes); + xfer_secondary_pool(r, nbytes, tmp); DEBUG_ENT("%s has %d bits, want %d bits\n", r == sec_random_state ? "secondary" : diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Sat Mar 15 18:40:42 2003 +++ b/drivers/char/raw.c Sat Mar 15 18:40:42 2003 @@ -19,14 +19,16 @@ #include +#define MAX_RAW_MINORS 256 + struct raw_device_data { struct block_device *binding; int inuse; }; -static struct raw_device_data raw_devices[256]; +static struct raw_device_data raw_devices[MAX_RAW_MINORS]; static DECLARE_MUTEX(raw_mutex); -static struct file_operations raw_ctl_fops; +static struct file_operations raw_ctl_fops; /* forward declaration */ /* * Open/close code for raw IO. @@ -85,11 +87,16 @@ { const int minor= minor(inode->i_rdev); struct block_device *bdev; - + down(&raw_mutex); bdev = raw_devices[minor].binding; raw_devices[minor].inuse--; up(&raw_mutex); + + /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ + inode->i_mapping = &inode->i_data; + inode->i_mapping->backing_dev_info = &default_backing_dev_info; + bd_release(bdev); blkdev_put(bdev, BDEV_RAW); return 0; @@ -130,11 +137,13 @@ goto out; err = -EINVAL; - if (rq.raw_minor < 0 || rq.raw_minor > MINORMASK) + if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) goto out; rawdev = &raw_devices[rq.raw_minor]; if (command == RAW_SETBIND) { + dev_t dev; + /* * This is like making block devices, so demand the * same capability @@ -151,9 +160,10 @@ */ err = -EINVAL; + dev = MKDEV(rq.block_major, rq.block_minor); if ((rq.block_major == 0 && rq.block_minor != 0) || - rq.block_major > MAX_BLKDEV || - rq.block_minor > MINORMASK) + MAJOR(dev) != rq.block_major || + MINOR(dev) != rq.block_minor) goto out; down(&raw_mutex); @@ -170,10 +180,7 @@ /* unbind */ rawdev->binding = NULL; } else { - kdev_t kdev; - - kdev = mk_kdev(rq.block_major, rq.block_minor); - rawdev->binding = bdget(kdev_t_to_nr(kdev)); + rawdev->binding = bdget(dev); MOD_INC_USE_COUNT; } up(&raw_mutex); diff -Nru a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c --- a/drivers/char/rio/rio_linux.c Sat Mar 15 18:40:42 2003 +++ b/drivers/char/rio/rio_linux.c Sat Mar 15 18:40:42 2003 @@ -59,7 +59,6 @@ #include #include -#include #include #if BITS_PER_LONG != 32 @@ -725,14 +724,14 @@ switch (cmd) { #if 0 case TIOCGSOFTCAR: - rc = Put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), + rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned int *) arg); break; #endif case TIOCSSOFTCAR: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0); @@ -784,7 +783,7 @@ case TIOCMBIS: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : -1), ((ival & TIOCM_RTS) ? 1 : -1)); } @@ -792,7 +791,7 @@ case TIOCMBIC: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 0 : -1), ((ival & TIOCM_RTS) ? 0 : -1)); } @@ -800,7 +799,7 @@ case TIOCMSET: if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned int))) == 0) { - Get_user(ival, (unsigned int *) arg); + get_user(ival, (unsigned int *) arg); rio_setsignals(port, ((ival & TIOCM_DTR) ? 1 : 0), ((ival & TIOCM_RTS) ? 1 : 0)); } @@ -1126,7 +1125,7 @@ t, CNTRL_REG_GOODVALUE); writel (CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET); } - my_iounmap (hwbase, rebase); + iounmap((char*) rebase); } #endif @@ -1201,7 +1200,7 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; - hp->Ivec = get_irq (pdev); + hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->CardP = (struct DpRam *) @@ -1234,8 +1233,7 @@ p->RIONumHosts++; found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } #ifdef TWO_ZERO @@ -1272,7 +1270,7 @@ hp = &p->RIOHosts[p->RIONumHosts]; hp->PaddrP = tint & PCI_BASE_ADDRESS_MEM_MASK; - hp->Ivec = get_irq (pdev); + hp->Ivec = pdev->irq; if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0; hp->Ivec |= 0x8000; /* Mark as non-sharable */ @@ -1307,8 +1305,7 @@ p->RIONumHosts++; found++; } else { - my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, - p->RIOHosts[p->RIONumHosts].Caddr); + iounmap((char*) (p->RIOHosts[p->RIONumHosts].Caddr)); } #else printk (KERN_ERR "Found an older RIO PCI card, but the driver is not " @@ -1361,7 +1358,7 @@ } if (!okboard) - my_iounmap (hp->PaddrP, hp->Caddr); + iounmap ((char*) (hp->Caddr)); } } diff -Nru a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c --- a/drivers/char/rio/rioboot.c Sat Mar 15 18:40:40 2003 +++ b/drivers/char/rio/rioboot.c Sat Mar 15 18:40:40 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riocmd.c b/drivers/char/rio/riocmd.c --- a/drivers/char/rio/riocmd.c Sat Mar 15 18:40:41 2003 +++ b/drivers/char/rio/riocmd.c Sat Mar 15 18:40:41 2003 @@ -47,7 +47,6 @@ #include #include -#include #include #include "linux_compat.h" diff -Nru a/drivers/char/rio/rioctrl.c b/drivers/char/rio/rioctrl.c --- a/drivers/char/rio/rioctrl.c Sat Mar 15 18:40:41 2003 +++ b/drivers/char/rio/rioctrl.c Sat Mar 15 18:40:41 2003 @@ -47,7 +47,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c --- a/drivers/char/rio/rioinit.c Sat Mar 15 18:40:40 2003 +++ b/drivers/char/rio/rioinit.c Sat Mar 15 18:40:40 2003 @@ -47,7 +47,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riointr.c b/drivers/char/rio/riointr.c --- a/drivers/char/rio/riointr.c Sat Mar 15 18:40:39 2003 +++ b/drivers/char/rio/riointr.c Sat Mar 15 18:40:39 2003 @@ -48,7 +48,6 @@ #include #include -#include #include #include diff -Nru a/drivers/char/rio/rioparam.c b/drivers/char/rio/rioparam.c --- a/drivers/char/rio/rioparam.c Sat Mar 15 18:40:45 2003 +++ b/drivers/char/rio/rioparam.c Sat Mar 15 18:40:45 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c --- a/drivers/char/rio/rioroute.c Sat Mar 15 18:40:42 2003 +++ b/drivers/char/rio/rioroute.c Sat Mar 15 18:40:42 2003 @@ -46,7 +46,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c --- a/drivers/char/rio/riotable.c Sat Mar 15 18:40:44 2003 +++ b/drivers/char/rio/riotable.c Sat Mar 15 18:40:44 2003 @@ -48,7 +48,6 @@ #include #include -#include #include diff -Nru a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c --- a/drivers/char/rio/riotty.c Sat Mar 15 18:40:41 2003 +++ b/drivers/char/rio/riotty.c Sat Mar 15 18:40:41 2003 @@ -51,7 +51,6 @@ #include -#include #include diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c --- a/drivers/char/rtc.c Sat Mar 15 18:40:41 2003 +++ b/drivers/char/rtc.c Sat Mar 15 18:40:41 2003 @@ -152,6 +152,9 @@ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ #if RTC_IRQ +/* + * rtc_task_lock nests inside rtc_lock. + */ static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED; static rtc_task_t *rtc_callback = NULL; #endif @@ -746,13 +749,15 @@ #else unsigned char tmp; - spin_lock_irq(&rtc_task_lock); + spin_lock_irq(&rtc_lock); + spin_lock(&rtc_task_lock); if (rtc_callback != task) { - spin_unlock_irq(&rtc_task_lock); + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); return -ENXIO; } rtc_callback = NULL; - spin_lock(&rtc_lock); + /* disable controls */ tmp = CMOS_READ(RTC_CONTROL); tmp &= ~RTC_PIE; @@ -765,8 +770,8 @@ del_timer(&rtc_irq_timer); } rtc_status &= ~RTC_IS_OPEN; - spin_unlock(&rtc_lock); - spin_unlock_irq(&rtc_task_lock); + spin_unlock(&rtc_task_lock); + spin_unlock_irq(&rtc_lock); return 0; #endif } diff -Nru a/drivers/char/serial167.c b/drivers/char/serial167.c --- a/drivers/char/serial167.c Sat Mar 15 18:40:41 2003 +++ b/drivers/char/serial167.c Sat Mar 15 18:40:41 2003 @@ -2836,7 +2836,7 @@ }; -void __init serial167_console_init(void) +static void __init serial167_console_init(void) { if (vme_brdtype == VME_TYPE_MVME166 || vme_brdtype == VME_TYPE_MVME167 || @@ -2845,6 +2845,7 @@ register_console(&sercons); } } +console_initcall(serial167_console_init); #ifdef CONFIG_REMOTE_DEBUG void putDebugChar (int c) diff -Nru a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c --- a/drivers/char/serial_tx3912.c Sat Mar 15 18:40:42 2003 +++ b/drivers/char/serial_tx3912.c Sat Mar 15 18:40:42 2003 @@ -1054,9 +1054,10 @@ .index = -1 }; -void __init tx3912_console_init(void) +static void __init tx3912_console_init(void) { register_console(&sercons); } +console_initcall(tx3912_console_init); #endif diff -Nru a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c --- a/drivers/char/sh-sci.c Sat Mar 15 18:40:44 2003 +++ b/drivers/char/sh-sci.c Sat Mar 15 18:40:44 2003 @@ -1275,7 +1275,7 @@ extern void sh_console_unregister (void); #endif -void __init sci_console_init(void) +static void __init sci_console_init(void) { register_console(&sercons); #ifdef CONFIG_SH_EARLY_PRINTK @@ -1285,4 +1285,6 @@ sh_console_unregister(); #endif } +console_initcall(sci_console_init); + #endif /* CONFIG_SERIAL_CONSOLE */ diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c --- a/drivers/char/tty_io.c Sat Mar 15 18:40:42 2003 +++ b/drivers/char/tty_io.c Sat Mar 15 18:40:42 2003 @@ -113,7 +113,15 @@ #define TTY_PARANOIA_CHECK 1 #define CHECK_TTY_COUNT 1 -struct termios tty_std_termios; /* for the benefit of tty drivers */ +struct termios tty_std_termios = { /* for the benefit of tty drivers */ + .c_iflag = ICRNL | IXON, + .c_oflag = OPOST | ONLCR, + .c_cflag = B38400 | CS8 | CREAD | HUPCL, + .c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | + ECHOCTL | ECHOKE | IEXTEN, + .c_cc = INIT_C_CC +}; + LIST_HEAD(tty_drivers); /* linked list of tty drivers */ struct tty_ldisc ldiscs[NR_LDISCS]; /* line disc dispatch table */ @@ -141,26 +149,13 @@ unsigned int cmd, unsigned long arg); static int tty_fasync(int fd, struct file * filp, int on); extern int vme_scc_init (void); -extern long vme_scc_console_init(void); extern int serial167_init(void); -extern long serial167_console_init(void); -extern void console_8xx_init(void); extern int rs_8xx_init(void); -extern void mac_scc_console_init(void); -extern void sclp_console_init(void); -extern void sclp_tty_init(void); -extern void con3215_init(void); -extern void tub3270_con_init(void); +extern void hwc_tty_init(void); +extern void tty3215_init(void); extern void tub3270_init(void); -extern void uart_console_init(void); -extern void sgi_serial_console_init(void); -extern void sci_console_init(void); -extern void m68328_console_init(void); -extern void mcfrs_console_init(void); extern void rs_360_init(void); -extern void tx3912_console_init(void); extern void tx3912_rs_init(void); -extern void hvc_console_init(void); static struct tty_struct *alloc_tty_struct(void) { @@ -306,13 +301,9 @@ if (tty->ldisc.open) retval = (tty->ldisc.open)(tty); if (retval < 0) { - module_put(tty->ldisc.owner); - tty->ldisc = o_ldisc; tty->termios->c_line = tty->ldisc.num; if (tty->ldisc.open && (tty->ldisc.open(tty) < 0)) { - module_put(tty->ldisc.owner); - tty->ldisc = ldiscs[N_TTY]; tty->termios->c_line = N_TTY; if (tty->ldisc.open) { @@ -2206,91 +2197,28 @@ */ void __init console_init(void) { + initcall_t *call; + /* Setup the default TTY line discipline. */ - memset(ldiscs, 0, sizeof(ldiscs)); (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); /* - * Set up the standard termios. Individual tty drivers may - * deviate from this; this is used as a template. - */ - memset(&tty_std_termios, 0, sizeof(struct termios)); - memcpy(tty_std_termios.c_cc, INIT_C_CC, NCCS); - tty_std_termios.c_iflag = ICRNL | IXON; - tty_std_termios.c_oflag = OPOST | ONLCR; - tty_std_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL; - tty_std_termios.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK | - ECHOCTL | ECHOKE | IEXTEN; - - /* * set up the console device so that later boot sequences can * inform about problems etc.. */ #ifdef CONFIG_EARLY_PRINTK disable_early_printk(); #endif -#ifdef CONFIG_VT - con_init(); -#endif -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - au1000_serial_console_init(); -#endif -#ifdef CONFIG_SERIAL_CONSOLE -#if (defined(CONFIG_8xx) || defined(CONFIG_8260)) - console_8xx_init(); -#elif defined(CONFIG_MAC_SERIAL) - mac_scc_console_init(); -#elif defined(CONFIG_PARISC) - pdc_console_init(); -#elif defined(CONFIG_SERIAL) - serial_console_init(); -#endif /* CONFIG_8xx */ -#ifdef CONFIG_SGI_SERIAL - sgi_serial_console_init(); -#endif -#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC) - vme_scc_console_init(); -#endif -#if defined(CONFIG_SERIAL167) - serial167_console_init(); -#endif -#if defined(CONFIG_SH_SCI) - sci_console_init(); -#endif -#endif -#ifdef CONFIG_TN3270_CONSOLE - tub3270_con_init(); -#endif -#ifdef CONFIG_TN3215_CONSOLE - con3215_init(); -#endif -#ifdef CONFIG_SCLP_CONSOLE - sclp_console_init(); -#endif -#ifdef CONFIG_STDIO_CONSOLE - stdio_console_init(); -#endif -#ifdef CONFIG_SERIAL_CORE_CONSOLE - uart_console_init(); -#endif -#ifdef CONFIG_ARC_CONSOLE - arc_console_init(); -#endif -#ifdef CONFIG_SERIAL_68328 - m68328_console_init(); -#endif -#ifdef CONFIG_SERIAL_COLDFIRE - mcfrs_console_init(); -#endif #ifdef CONFIG_SERIAL_68360 - rs_360_init(); -#endif -#ifdef CONFIG_SERIAL_TX3912_CONSOLE - tx3912_console_init(); -#endif -#ifdef CONFIG_HVC_CONSOLE - hvc_console_init(); -#endif + /* This is not a console initcall. I know not what it's doing here. + So I haven't moved it. dwmw2 */ + rs_360_init(); +#endif + call = &__con_initcall_start; + while (call < &__con_initcall_end) { + (*call)(); + call++; + } } static struct tty_driver dev_tty_driver, dev_syscons_driver; @@ -2307,14 +2235,19 @@ }; EXPORT_SYMBOL(tty_devclass); +static int __init tty_devclass_init(void) +{ + return devclass_register(&tty_devclass); +} + +postcore_initcall(tty_devclass_init); + /* * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ void __init tty_init(void) { - devclass_register(&tty_devclass); - /* * dev_tty_driver and dev_console_driver are actually magic * devices which get redirected at open time. Nevertheless, diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Sat Mar 15 18:40:39 2003 +++ b/drivers/char/vme_scc.c Sat Mar 15 18:40:39 2003 @@ -1091,7 +1091,7 @@ }; -void __init vme_scc_console_init(void) +static void __init vme_scc_console_init(void) { if (vme_brdtype == VME_TYPE_MVME147 || vme_brdtype == VME_TYPE_MVME162 || @@ -1100,4 +1100,4 @@ vme_brdtype == VME_TYPE_BVME6000) register_console(&sercons); } - +console_initcall(vme_scc_console_init); diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Sat Mar 15 18:40:44 2003 +++ b/drivers/char/vt.c Sat Mar 15 18:40:44 2003 @@ -747,8 +747,10 @@ screenbuf_size = new_screen_size; err = resize_screen(currcons, new_cols, new_rows); - if (err) + if (err) { + kfree(newscreen); return err; + } rlth = min(old_row_size, new_row_size); rrem = new_row_size - rlth; @@ -2443,7 +2445,7 @@ struct tty_driver console_driver; static int console_refcount; -void __init con_init(void) +static int __init con_init(void) { const char *display_desc = NULL; unsigned int currcons = 0; @@ -2452,7 +2454,7 @@ display_desc = conswitchp->con_startup(); if (!display_desc) { fg_console = 0; - return; + return 0; } init_timer(&console_timer); @@ -2491,7 +2493,9 @@ #ifdef CONFIG_VT_CONSOLE register_console(&vt_console_driver); #endif + return 0; } +console_initcall(con_init); int __init vty_init(void) { diff -Nru a/drivers/char/watchdog/amd7xx_tco.c b/drivers/char/watchdog/amd7xx_tco.c --- a/drivers/char/watchdog/amd7xx_tco.c Sat Mar 15 18:40:40 2003 +++ b/drivers/char/watchdog/amd7xx_tco.c Sat Mar 15 18:40:40 2003 @@ -1,6 +1,6 @@ /* * AMD 766/768 TCO Timer Driver - * (c) Copyright 2002 Zwane Mwaikambo + * (c) Copyright 2002 Zwane Mwaikambo * All Rights Reserved. * * Parts from; @@ -34,35 +34,48 @@ #include #include -#define AMDTCO_MODULE_VER "build 20020601" +#define AMDTCO_MODULE_VER "build 20021116" #define AMDTCO_MODULE_NAME "amd7xx_tco" #define PFX AMDTCO_MODULE_NAME ": " -#define MAX_TIMEOUT 38 /* max of 38 seconds */ +#define MAX_TIMEOUT 38 /* max of 38 seconds, although the system will only + * reset itself after the second timeout */ /* pmbase registers */ -#define GLOBAL_SMI_REG 0x2a -#define TCO_EN (1 << 1) /* bit 1 in global SMI register */ #define TCO_RELOAD_REG 0x40 /* bits 0-5 are current count, 6-7 are reserved */ #define TCO_INITVAL_REG 0x41 /* bits 0-5 are value to load, 6-7 are reserved */ #define TCO_TIMEOUT_MASK 0x3f +#define TCO_STATUS1_REG 0x44 #define TCO_STATUS2_REG 0x46 #define NDTO_STS2 (1 << 1) /* we're interested in the second timeout */ #define BOOT_STS (1 << 2) /* will be set if NDTO_STS2 was set before reboot */ #define TCO_CTRL1_REG 0x48 #define TCO_HALT (1 << 11) +#define NO_REBOOT (1 << 10) /* in DevB:3x48 */ -static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER; -static int timeout = 38; +static char banner[] __initdata = KERN_INFO PFX AMDTCO_MODULE_VER "\n"; +static int timeout = MAX_TIMEOUT; static u32 pmbase; /* PMxx I/O base */ static struct pci_dev *dev; static struct semaphore open_sem; -spinlock_t amdtco_lock; /* only for device access */ +static spinlock_t amdtco_lock; /* only for device access */ static int expect_close = 0; MODULE_PARM(timeout, "i"); MODULE_PARM_DESC(timeout, "range is 0-38 seconds, default is 38"); +static inline u8 seconds_to_ticks(int seconds) +{ + /* the internal timer is stored as ticks which decrement + * every 0.6 seconds */ + return (seconds * 10) / 6; +} + +static inline int ticks_to_seconds(u8 ticks) +{ + return (ticks * 6) / 10; +} + static inline int amdtco_status(void) { u16 reg; @@ -81,28 +94,19 @@ static inline void amdtco_ping(void) { - u8 reg; - - spin_lock(&amdtco_lock); - reg = inb(pmbase+TCO_RELOAD_REG); - outb(1 | reg, pmbase+TCO_RELOAD_REG); - spin_unlock(&amdtco_lock); + outb(1, pmbase+TCO_RELOAD_REG); } static inline int amdtco_gettimeout(void) { - return inb(TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; + u8 reg = inb(pmbase+TCO_RELOAD_REG) & TCO_TIMEOUT_MASK; + return ticks_to_seconds(reg); } static inline void amdtco_settimeout(unsigned int timeout) { - u8 reg; - - spin_lock(&amdtco_lock); - reg = inb(pmbase+TCO_INITVAL_REG); - reg |= timeout & TCO_TIMEOUT_MASK; + u8 reg = seconds_to_ticks(timeout) & TCO_TIMEOUT_MASK; outb(reg, pmbase+TCO_INITVAL_REG); - spin_unlock(&amdtco_lock); } static inline void amdtco_global_enable(void) @@ -110,9 +114,12 @@ u16 reg; spin_lock(&amdtco_lock); - reg = inw(pmbase+GLOBAL_SMI_REG); - reg |= TCO_EN; - outw(reg, pmbase+GLOBAL_SMI_REG); + + /* clear NO_REBOOT on DevB:3x48 p97 */ + pci_read_config_word(dev, 0x48, ®); + reg &= ~NO_REBOOT; + pci_write_config_word(dev, 0x48, reg); + spin_unlock(&amdtco_lock); } @@ -146,10 +153,12 @@ if (timeout > MAX_TIMEOUT) timeout = MAX_TIMEOUT; + amdtco_disable(); amdtco_settimeout(timeout); amdtco_global_enable(); + amdtco_enable(); amdtco_ping(); - printk(KERN_INFO PFX "Watchdog enabled, timeout = %d/%d seconds", + printk(KERN_INFO PFX "Watchdog enabled, timeout = %ds of %ds\n", amdtco_gettimeout(), timeout); return 0; @@ -198,7 +207,7 @@ case WDIOC_GETTIMEOUT: return put_user(amdtco_gettimeout(), (int *)arg); - + case WDIOC_SETOPTIONS: if (copy_from_user(&tmp, (int *)arg, sizeof tmp)) return -EFAULT; @@ -221,7 +230,7 @@ printk(KERN_INFO PFX "Watchdog disabled\n"); } else { amdtco_ping(); - printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds)\n", timeout); + printk(KERN_CRIT PFX "Unexpected close!, timeout in %d seconds\n", timeout); } up(&open_sem); @@ -249,10 +258,9 @@ } #endif amdtco_ping(); - return len; } - return 0; + return len; } @@ -357,6 +365,9 @@ if (ints[0] > 0) timeout = ints[1]; + if (!timeout || timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; + return 1; } @@ -366,8 +377,7 @@ module_init(amdtco_init); module_exit(amdtco_exit); -MODULE_AUTHOR("Zwane Mwaikambo "); +MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); MODULE_LICENSE("GPL"); -EXPORT_NO_SYMBOLS; diff -Nru a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c --- a/drivers/cpufreq/freq_table.c Sat Mar 15 18:40:44 2003 +++ b/drivers/cpufreq/freq_table.c Sat Mar 15 18:40:44 2003 @@ -77,56 +77,6 @@ EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify); -int cpufreq_frequency_table_setpolicy(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table, - unsigned int *index) -{ - struct cpufreq_frequency_table optimal = { .index = ~0, }; - unsigned int i; - - switch (policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - optimal.frequency = 0; - break; - case CPUFREQ_POLICY_POWERSAVE: - optimal.frequency = ~0; - break; - } - - if (!cpu_online(policy->cpu)) - return -EINVAL; - - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - if ((freq < policy->min) || (freq > policy->max)) - continue; - switch(policy->policy) { - case CPUFREQ_POLICY_PERFORMANCE: - if (optimal.frequency <= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - case CPUFREQ_POLICY_POWERSAVE: - if (optimal.frequency >= freq) { - optimal.frequency = freq; - optimal.index = i; - } - break; - } - } - if (optimal.index > i) - return -EINVAL; - - *index = optimal.index; - - return 0; -} -EXPORT_SYMBOL_GPL(cpufreq_frequency_table_setpolicy); - - int cpufreq_frequency_table_target(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int target_freq, @@ -196,6 +146,56 @@ return 0; } EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target); + +static struct cpufreq_frequency_table *show_table[NR_CPUS]; +/** + * show_scaling_governor - show the current policy for the specified CPU + */ +static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) +{ + unsigned int i = 0; + unsigned int cpu = policy->cpu; + ssize_t count = 0; + struct cpufreq_frequency_table *table; + + if (!show_table[cpu]) + return -ENODEV; + + table = show_table[cpu]; + + for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + if (table[i].frequency == CPUFREQ_ENTRY_INVALID) + continue; + count += sprintf(&buf[count], "%d ", table[i].frequency); + } + count += sprintf(&buf[count], "\n"); + + return count; + +} + +struct freq_attr cpufreq_freq_attr_scaling_available_freqs = { + .attr = { .name = "scaling_available_frequencies", .mode = 0444 }, + .show = show_available_freqs, +}; +EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); + +/* + * if you use these, you must assure that the frequency table is valid + * all the time between get_attr and put_attr! + */ +void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, + unsigned int cpu) +{ + show_table[cpu] = table; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr); + +void cpufreq_frequency_table_put_attr(unsigned int cpu) +{ + show_table[cpu] = NULL; +} +EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr); MODULE_AUTHOR ("Dominik Brodowski "); diff -Nru a/drivers/cpufreq/userspace.c b/drivers/cpufreq/userspace.c --- a/drivers/cpufreq/userspace.c Sat Mar 15 18:40:40 2003 +++ b/drivers/cpufreq/userspace.c Sat Mar 15 18:40:40 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -112,7 +113,7 @@ if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target_l(¤t_policy[cpu], freq, + ret = cpufreq_driver_target(¤t_policy[cpu], freq, CPUFREQ_RELATION_L); err: @@ -465,23 +466,14 @@ /************************** sysfs interface ************************/ -static inline int to_cpu_nr (struct device *dev) +static ssize_t show_speed (struct cpufreq_policy *policy, char *buf) { - struct sys_device * cpu_sys_dev = container_of(dev, struct sys_device, dev); - return (cpu_sys_dev->id); -} - -static ssize_t show_speed (struct device *dev, char *buf) -{ - unsigned int cpu = to_cpu_nr(dev); - - return sprintf (buf, "%u\n", cpu_cur_freq[cpu]); + return sprintf (buf, "%u\n", cpu_cur_freq[policy->cpu]); } static ssize_t -store_speed (struct device *dev, const char *buf, size_t count) +store_speed (struct cpufreq_policy *policy, const char *buf, size_t count) { - unsigned int cpu = to_cpu_nr(dev); unsigned int freq = 0; unsigned int ret; @@ -489,13 +481,16 @@ if (ret != 1) return -EINVAL; - cpufreq_set(freq, cpu); + cpufreq_set(freq, policy->cpu); return count; } -static DEVICE_ATTR(scaling_setspeed, (S_IRUGO | S_IWUSR), show_speed, store_speed); - +static struct freq_attr freq_attr_scaling_setspeed = { + .attr = { .name = "scaling_setspeed", .mode = 0644 }, + .show = show_speed, + .store = store_speed, +}; static int cpufreq_governor_userspace(struct cpufreq_policy *policy, unsigned int event) @@ -511,7 +506,7 @@ cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max; cpu_cur_freq[cpu] = policy->cur; - device_create_file (policy->intf.dev, &dev_attr_scaling_setspeed); + sysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); up(&userspace_sem); break; @@ -520,7 +515,7 @@ cpu_is_managed[cpu] = 0; cpu_min_freq[cpu] = 0; cpu_max_freq[cpu] = 0; - device_remove_file (policy->intf.dev, &dev_attr_scaling_setspeed); + sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr); up(&userspace_sem); module_put(THIS_MODULE); break; diff -Nru a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c --- a/drivers/eisa/eisa-bus.c Sat Mar 15 18:40:40 2003 +++ b/drivers/eisa/eisa-bus.c Sat Mar 15 18:40:40 2003 @@ -83,8 +83,10 @@ return 0; while (strlen (eids->sig)) { - if (!strcmp (eids->sig, edev->id.sig)) + if (!strcmp (eids->sig, edev->id.sig)) { + edev->id.driver_data = eids->driver_data; return 1; + } eids++; } diff -Nru a/drivers/eisa/virtual_root.c b/drivers/eisa/virtual_root.c --- a/drivers/eisa/virtual_root.c Sat Mar 15 18:40:43 2003 +++ b/drivers/eisa/virtual_root.c Sat Mar 15 18:40:43 2003 @@ -13,14 +13,19 @@ #include #include -/* The default EISA device parent (virtual root device). */ -static struct device eisa_root_dev = { - .name = "Virtual EISA Bridge", - .bus_id = "eisa", +/* The default EISA device parent (virtual root device). + * Now use a platform device, since that's the obvious choice. */ + +static struct platform_device eisa_root_dev = { + .name = "eisa", + .id = 0, + .dev = { + .name = "Virtual EISA Bridge", + }, }; static struct eisa_root_device eisa_bus_root = { - .dev = &eisa_root_dev, + .dev = &eisa_root_dev.dev, .bus_base_addr = 0, .res = &ioport_resource, .slots = EISA_MAX_SLOTS, @@ -30,16 +35,16 @@ { int r; - if ((r = device_register (&eisa_root_dev))) { + if ((r = platform_device_register (&eisa_root_dev))) { return r; } - eisa_root_dev.driver_data = &eisa_bus_root; + eisa_root_dev.dev.driver_data = &eisa_bus_root; if (eisa_root_register (&eisa_bus_root)) { /* A real bridge may have been registered before * us. So quietly unregister. */ - device_unregister (&eisa_root_dev); + platform_device_unregister (&eisa_root_dev); return -1; } diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c --- a/drivers/hotplug/acpiphp_glue.c Sat Mar 15 18:40:41 2003 +++ b/drivers/hotplug/acpiphp_glue.c Sat Mar 15 18:40:41 2003 @@ -801,7 +801,7 @@ static int enable_device (struct acpiphp_slot *slot) { u8 bus; - struct pci_dev dev0, *dev; + struct pci_dev *dev; struct pci_bus *child; struct list_head *l; struct acpiphp_func *func; @@ -824,16 +824,8 @@ if (retval) goto err_exit; - memset(&dev0, 0, sizeof (struct pci_dev)); - - dev0.bus = slot->bridge->pci_bus; - dev0.devfn = PCI_DEVFN(slot->device, 0); - dev0.sysdata = dev0.bus->sysdata; - dev0.dev.parent = dev0.bus->dev; - dev0.dev.bus = &pci_bus_type; - /* returned `dev' is the *first function* only! */ - dev = pci_scan_slot (&dev0); + dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); if (!dev) { err("No new device found\n"); diff -Nru a/drivers/hotplug/cpci_hotplug_pci.c b/drivers/hotplug/cpci_hotplug_pci.c --- a/drivers/hotplug/cpci_hotplug_pci.c Sat Mar 15 18:40:42 2003 +++ b/drivers/hotplug/cpci_hotplug_pci.c Sat Mar 15 18:40:42 2003 @@ -574,19 +574,13 @@ /* Still NULL? Well then scan for it! */ if(slot->dev == NULL) { - struct pci_dev dev0; - dbg("pci_dev still null"); - memset(&dev0, 0, sizeof (struct pci_dev)); - dev0.bus = slot->bus; - dev0.devfn = slot->devfn; - dev0.sysdata = slot->bus->self->sysdata; /* * This will generate pci_dev structures for all functions, but * we will only call this case when lookup fails. */ - slot->dev = pci_scan_slot(&dev0); + slot->dev = pci_scan_slot(slot->bus, slot->devfn); if(slot->dev == NULL) { err("Could not find PCI device for slot %02x", slot->number); return 0; diff -Nru a/drivers/hotplug/cpqphp_pci.c b/drivers/hotplug/cpqphp_pci.c --- a/drivers/hotplug/cpqphp_pci.c Sat Mar 15 18:40:44 2003 +++ b/drivers/hotplug/cpqphp_pci.c Sat Mar 15 18:40:44 2003 @@ -84,24 +84,19 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) { unsigned char bus; - struct pci_dev dev0; struct pci_bus *child; int rc = 0; - memset(&dev0, 0, sizeof(struct pci_dev)); - if (func->pci_dev == NULL) func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); //Still NULL ? Well then scan for it ! if (func->pci_dev == NULL) { dbg("INFO: pci_dev still null\n"); - dev0.bus = ctrl->pci_dev->bus; - dev0.devfn = (func->device << 3) + (func->function & 0x7); - dev0.sysdata = ctrl->pci_dev->sysdata; //this will generate pci_dev structures for all functions, but we will only call this case when lookup fails - func->pci_dev = pci_scan_slot(&dev0); + func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus, + (func->device << 3) + (func->function & 0x7)); if (func->pci_dev == NULL) { dbg("ERROR: pci_dev still null\n"); return 0; diff -Nru a/drivers/hotplug/ibmphp_core.c b/drivers/hotplug/ibmphp_core.c --- a/drivers/hotplug/ibmphp_core.c Sat Mar 15 18:40:45 2003 +++ b/drivers/hotplug/ibmphp_core.c Sat Mar 15 18:40:45 2003 @@ -845,26 +845,22 @@ static int ibm_configure_device (struct pci_func *func) { unsigned char bus; - struct pci_dev dev0; struct pci_bus *child; int rc = 0; int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ - memset (&dev0, 0, sizeof (struct pci_dev)); - if (!(bus_structure_fixup (func->busno))) flag = 1; if (func->dev == NULL) func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); if (func->dev == NULL) { - dev0.bus = ibmphp_find_bus (func->busno); - if (!dev0.bus) + struct pci_bus *bus = ibmphp_find_bus (func->busno); + if (!bus) return 0; - dev0.devfn = ((func->device << 3) + (func->function & 0x7)); - dev0.sysdata = dev0.bus->sysdata; - func->dev = pci_scan_slot (&dev0); + func->dev = pci_scan_slot(bus, + (func->device << 3) + (func->function & 0x7)); if (func->dev == NULL) { err ("ERROR... : pci_dev still NULL \n"); diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig --- a/drivers/i2c/busses/Kconfig Sat Mar 15 18:40:44 2003 +++ b/drivers/i2c/busses/Kconfig Sat Mar 15 18:40:44 2003 @@ -5,6 +5,20 @@ menu "I2C Hardware Sensors Mainboard support" +config I2C_ALI15X3 + tristate " ALI 15x3" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. + + This can also be built as a module. If so, the module will be + called i2c-ali15x3. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + config I2C_AMD756 tristate " AMD 756/766" depends on I2C && I2C_PROC @@ -34,6 +48,52 @@ say M here and read . The module will be called i2c-amd8111. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + +config I2C_I801 + tristate " Intel 801" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the Intel + 801 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset is supported: + 82801AA + 82801AB + 82801BA + 82801CA/CAM + 82801DB + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read . + + The module will be called i2c-i801. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + +config I2C_PIIX4 + tristate " Intel PIIX4" + depends on I2C && I2C_PROC && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the Intel + PIIX4 family of mainboard I2C interfaces. Specifically, the following + versions of the chipset is supported: + Intel PIIX4 + Intel 440MX + Serverworks OSB4 + Serverworks CSB5 + SMSC Victory66 + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read . + + The module will be called i2c-piix4. You will also need the latest user-space utilties: you can find them in the lm_sensors package, which you can download at diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile --- a/drivers/i2c/busses/Makefile Sat Mar 15 18:40:39 2003 +++ b/drivers/i2c/busses/Makefile Sat Mar 15 18:40:39 2003 @@ -2,5 +2,8 @@ # Makefile for the kernel hardware sensors bus drivers. # +obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o +obj-$(CONFIG_I2C_I801) += i2c-i801.o +obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/busses/i2c-ali15x3.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,575 @@ +/* + ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1999 Frodo Looijaard and + Philip Edelbrock and + Mark D. Studebaker + + 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + This is the driver for the SMB Host controller on + Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. + + The M1543C is a South bridge for desktop systems. + The M1533 is a South bridge for portable systems. + They are part of the following ALI chipsets: + "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin V": Includes the M1541 Socket 7 North bridge + with AGP and 100MHz CPU Front Side bus + "Aladdin IV": Includes the M1541 Socket 7 North bridge + with host bus up to 83.3 MHz. + For an overview of these chips see http://www.acerlabs.com + + The M1533/M1543C devices appear as FOUR separate devices + on the PCI bus. An output of lspci will show something similar + to the following: + + 00:02.0 USB Controller: Acer Laboratories Inc. M5237 + 00:03.0 Bridge: Acer Laboratories Inc. M7101 + 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 + 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 + + The SMB controller is part of the 7101 device, which is an + ACPI-compliant Power Management Unit (PMU). + + The whole 7101 device has to be enabled for the SMB to work. + You can't just enable the SMB alone. + The SMB and the ACPI have separate I/O spaces. + We make sure that the SMB is enabled. We leave the ACPI alone. + + This driver controls the SMB Host only. + The SMB Slave controller on the M15X3 is not enabled. + + This driver does not use interrupts. +*/ + +/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ALI15X3 SMBus address offsets */ +#define SMBHSTSTS (0 + ali15x3_smba) +#define SMBHSTCNT (1 + ali15x3_smba) +#define SMBHSTSTART (2 + ali15x3_smba) +#define SMBHSTCMD (7 + ali15x3_smba) +#define SMBHSTADD (3 + ali15x3_smba) +#define SMBHSTDAT0 (4 + ali15x3_smba) +#define SMBHSTDAT1 (5 + ali15x3_smba) +#define SMBBLKDAT (6 + ali15x3_smba) + +/* PCI Address Constants */ +#define SMBCOM 0x004 +#define SMBBA 0x014 +#define SMBATPC 0x05B /* used to unlock xxxBA registers */ +#define SMBHSTCFG 0x0E0 +#define SMBSLVC 0x0E1 +#define SMBCLK 0x0E2 +#define SMBREV 0x008 + +/* Other settings */ +#define MAX_TIMEOUT 200 /* times 1/100 sec */ +#define ALI15X3_SMB_IOSIZE 32 + +/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. + We don't use these here. If the bases aren't set to some value we + tell user to upgrade BIOS and we fail. +*/ +#define ALI15X3_SMB_DEFAULTBASE 0xE800 + +/* ALI15X3 address lock bits */ +#define ALI15X3_LOCK 0x06 + +/* ALI15X3 command constants */ +#define ALI15X3_ABORT 0x02 +#define ALI15X3_T_OUT 0x04 +#define ALI15X3_QUICK 0x00 +#define ALI15X3_BYTE 0x10 +#define ALI15X3_BYTE_DATA 0x20 +#define ALI15X3_WORD_DATA 0x30 +#define ALI15X3_BLOCK_DATA 0x40 +#define ALI15X3_BLOCK_CLR 0x80 + +/* ALI15X3 status register bits */ +#define ALI15X3_STS_IDLE 0x04 +#define ALI15X3_STS_BUSY 0x08 +#define ALI15X3_STS_DONE 0x10 +#define ALI15X3_STS_DEV 0x20 /* device error */ +#define ALI15X3_STS_COLL 0x40 /* collision or no response */ +#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ +#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ + + +/* If force_addr is set to anything different from 0, we forcibly enable + the device at the given address. */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Initialize the base address of the i2c controller"); + + +static void ali15x3_do_pause(unsigned int amount); +static int ali15x3_transaction(void); + +static unsigned short ali15x3_smba = 0; + +int ali15x3_setup(struct pci_dev *ALI15X3_dev) +{ + u16 a; + unsigned char temp; + +/* Check the following things: + - SMB I/O address is initialized + - Device is enabled + - We can use the addresses +*/ + +/* Unlock the register. + The data sheet says that the address registers are read-only + if the lock bits are 1, but in fact the address registers + are zero unless you clear the lock bits. +*/ + pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); + if (temp & ALI15X3_LOCK) { + temp &= ~ALI15X3_LOCK; + pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); + } + +/* Determine the address of the SMBus area */ + pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); + ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); + if (ali15x3_smba == 0 && force_addr == 0) { + printk + ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + + if(force_addr) + ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); + + if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) { + printk + ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n", + ali15x3_smba); + return -ENODEV; + } + + if(force_addr) { + printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba); + if (PCIBIOS_SUCCESSFUL != + pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) + return -ENODEV; + if (PCIBIOS_SUCCESSFUL != + pci_read_config_word(ALI15X3_dev, SMBBA, &a)) + return -ENODEV; + if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { + /* make sure it works */ + printk("i2c-ali15x3.o: force address failed - not supported?\n"); + return -ENODEV; + } + } +/* check if whole device is enabled */ + pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); + if ((temp & 1) == 0) { + printk("i2c-ali15x3: enabling SMBus device\n"); + pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); + } + +/* Is SMB Host controller enabled? */ + pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); + if ((temp & 1) == 0) { + printk("i2c-ali15x3: enabling SMBus controller\n"); + pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); + } + +/* set SMB clock to 74KHz as recommended in data sheet */ + pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); + + /* Everything is happy, let's grab the memory and set things up. */ + request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb"); + +#ifdef DEBUG +/* + The interrupt routing for SMB is set up in register 0x77 in the + 1533 ISA Bridge device, NOT in the 7101 device. + Don't bother with finding the 1533 device and reading the register. + if ((....... & 0x0F) == 1) + printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n"); +*/ + pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); + printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp); + printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba); +#endif /* DEBUG */ + + return 0; +} + + +/* Internally used pause function */ +void ali15x3_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +/* Another internally used function */ +int ali15x3_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); +#endif + + /* get status */ + temp = inb_p(SMBHSTSTS); + + /* Make sure the SMBus host is ready to start transmitting */ + /* Check the busy bit first */ + if (temp & ALI15X3_STS_BUSY) { +/* + If the host controller is still busy, it may have timed out in the previous transaction, + resulting in a "SMBus Timeout" printk. + I've tried the following to reset a stuck busy bit. + 1. Reset the controller with an ABORT command. + (this doesn't seem to clear the controller if an external device is hung) + 2. Reset the controller and the other SMBus devices with a T_OUT command. + (this clears the host busy bit if an external device is hung, + but it comes back upon a new access to a device) + 3. Disable and reenable the controller in SMBHSTCFG + Worst case, nothing seems to work except power reset. +*/ +/* Abort - reset the host controller */ +/* +#ifdef DEBUG + printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp); +#endif + outb_p(ALI15X3_ABORT, SMBHSTCNT); + temp = inb_p(SMBHSTSTS); + if (temp & ALI15X3_STS_BUSY) { +*/ + +/* + Try resetting entire SMB bus, including other devices - + This may not work either - it clears the BUSY bit but + then the BUSY bit may come back on when you try and use the chip again. + If that's the case you are stuck. +*/ + printk + ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n", + temp); + outb_p(ALI15X3_T_OUT, SMBHSTCNT); + temp = inb_p(SMBHSTSTS); + } +/* + } +*/ + + /* now check the error bits and the busy bit */ + if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* do a clear-on-write */ + outb_p(0xFF, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) & + (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { + /* this is probably going to be correctable only by a power reset + as one of the bits now appears to be stuck */ + /* This may be a bus or device with electrical problems. */ + printk + ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n", + temp); + return -1; + } + } else { + /* check and clear done bit */ + if (temp & ALI15X3_STS_DONE) { + outb_p(temp, SMBHSTSTS); + } + } + + /* start the transaction by writing anything to the start register */ + outb_p(0xFF, SMBHSTSTART); + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + ali15x3_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; + printk("i2c-ali15x3.o: SMBus Timeout!\n"); + } + + if (temp & ALI15X3_STS_TERM) { + result = -1; +#ifdef DEBUG + printk("i2c-ali15x3.o: Error: Failed bus transaction\n"); +#endif + } + +/* + Unfortunately the ALI SMB controller maps "no response" and "bus collision" + into a single bit. No reponse is the usual case so don't + do a printk. + This means that bus collisions go unreported. +*/ + if (temp & ALI15X3_STS_COLL) { + result = -1; +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n", + inb_p(SMBHSTADD)); +#endif + } + +/* haven't ever seen this */ + if (temp & ALI15X3_STS_DEV) { + result = -1; + printk("i2c-ali15x3.o: Error: device error\n"); + } +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* Return -1 on error. */ +s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data * data) +{ + int i, len; + int temp; + int timeout; + +/* clear all the bits (clear-on-write) */ + outb_p(0xFF, SMBHSTSTS); +/* make sure SMBus is idle */ + temp = inb_p(SMBHSTSTS); + for (timeout = 0; + (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); + timeout++) { + ali15x3_do_pause(1); + temp = inb_p(SMBHSTSTS); + } + if (timeout >= MAX_TIMEOUT) { + printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n", + temp); + } + + switch (size) { + case I2C_SMBUS_PROC_CALL: + printk + ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n"); + return -1; + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI15X3_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + size = ALI15X3_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + size = ALI15X3_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + size = ALI15X3_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) { + len = 0; + data->block[0] = len; + } + if (len > 32) { + len = 32; + data->block[0] = len; + } + outb_p(len, SMBHSTDAT0); + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + size = ALI15X3_BLOCK_DATA; + break; + } + + outb_p(size, SMBHSTCNT); /* output command */ + + if (ali15x3_transaction()) /* Error in transaction */ + return -1; + + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) + return 0; + + + switch (size) { + case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI15X3_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case ALI15X3_BLOCK_DATA: + len = inb_p(SMBHSTDAT0); + if (len > 32) + len = 32; + data->block[0] = len; + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= data->block[0]; i++) { + data->block[i] = inb_p(SMBBLKDAT); +#ifdef DEBUG + printk + ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n", + len, i, data->block[i]); +#endif /* DEBUG */ + } + break; + } + return 0; +} + + +u32 ali15x3_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = ali15x3_access, + .functionality = ali15x3_func, +}; + +static struct i2c_adapter ali15x3_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id ali15x3_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_AL, + .device = PCI_DEVICE_ID_AL_M7101, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, } +}; + +static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + if (ali15x3_setup(dev)) { + printk + ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n"); + + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + ali15x3_adapter.dev.parent = &dev->dev; + + sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x", + ali15x3_smba); + return i2c_add_adapter(&ali15x3_adapter); +} + +static void __devexit ali15x3_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&ali15x3_adapter); +} + +static struct pci_driver ali15x3_driver = { + .name = "ali15x3 smbus", + .id_table = ali15x3_ids, + .probe = ali15x3_probe, + .remove = __devexit_p(ali15x3_remove), +}; + +static int __init i2c_ali15x3_init(void) +{ + printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&ali15x3_driver); +} + + +static void __exit i2c_ali15x3_exit(void) +{ + pci_unregister_driver(&ali15x3_driver); + release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker "); +MODULE_DESCRIPTION("ALI15X3 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_ali15x3_init); +module_exit(i2c_ali15x3_exit); diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c --- a/drivers/i2c/busses/i2c-amd756.c Sat Mar 15 18:40:44 2003 +++ b/drivers/i2c/busses/i2c-amd756.c Sat Mar 15 18:40:44 2003 @@ -375,6 +375,9 @@ printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport); #endif + /* set up the driverfs linkage to our parent device */ + amd756_adapter.dev.parent = &pdev->dev; + sprintf(amd756_adapter.name, "SMBus AMD75x adapter at %04x", amd756_ioport); diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c --- a/drivers/i2c/busses/i2c-amd8111.c Sat Mar 15 18:40:44 2003 +++ b/drivers/i2c/busses/i2c-amd8111.c Sat Mar 15 18:40:44 2003 @@ -363,6 +363,9 @@ smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo_data = smbus; + /* set up the driverfs linkage to our parent device */ + smbus->adapter.dev.parent = &dev->dev; + error = i2c_add_adapter(&smbus->adapter); if (error) goto out_release_region; @@ -389,7 +392,7 @@ } static struct pci_driver amd8111_driver = { - .name = "amd8111 smbus 2.0", + .name = "amd8111 smbus", .id_table = amd8111_ids, .probe = amd8111_probe, .remove = __devexit_p(amd8111_remove), diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/busses/i2c-i801.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,715 @@ +/* + i801.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1998 - 2002 Frodo Looijaard , + Philip Edelbrock , and Mark D. Studebaker + + + 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + SUPPORTED DEVICES PCI ID + 82801AA 2413 + 82801AB 2423 + 82801BA 2443 + 82801CA/CAM 2483 + 82801DB 24C3 (HW PEC supported, 32 byte buffer not supported) + + This driver supports several versions of Intel's I/O Controller Hubs (ICH). + For SMBus support, they are similar to the PIIX4 and are part + of Intel's '810' and other chipsets. + See the doc/busses/i2c-i801 file for details. + I2C Block Read and Process Call are not supported. +*/ + +/* Note: we assume there can only be one I801, with one SMBus interface */ + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC +#define HAVE_PEC +#endif + +#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS +#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS 0x2483 +#endif + +#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS +#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS 0x24C3 +#endif + +static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3, + PCI_DEVICE_ID_INTEL_82801AB_3, + PCI_DEVICE_ID_INTEL_82801BA_2, + PCI_DEVICE_ID_INTEL_82801CA_SMBUS, + PCI_DEVICE_ID_INTEL_82801DB_SMBUS, + 0 }; + +/* I801 SMBus address offsets */ +#define SMBHSTSTS (0 + i801_smba) +#define SMBHSTCNT (2 + i801_smba) +#define SMBHSTCMD (3 + i801_smba) +#define SMBHSTADD (4 + i801_smba) +#define SMBHSTDAT0 (5 + i801_smba) +#define SMBHSTDAT1 (6 + i801_smba) +#define SMBBLKDAT (7 + i801_smba) +#define SMBPEC (8 + i801_smba) /* ICH4 only */ +#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ +#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ + +/* PCI Address Constants */ +#define SMBBA 0x020 +#define SMBHSTCFG 0x040 +#define SMBREV 0x008 + +/* Host configuration bits for SMBHSTCFG */ +#define SMBHSTCFG_HST_EN 1 +#define SMBHSTCFG_SMB_SMI_EN 2 +#define SMBHSTCFG_I2C_EN 4 + +/* Other settings */ +#define MAX_TIMEOUT 100 +#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ + +/* I801 command constants */ +#define I801_QUICK 0x00 +#define I801_BYTE 0x04 +#define I801_BYTE_DATA 0x08 +#define I801_WORD_DATA 0x0C +#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ +#define I801_BLOCK_DATA 0x14 +#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ +#define I801_BLOCK_LAST 0x34 +#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ +#define I801_START 0x40 +#define I801_PEC_EN 0x80 /* ICH4 only */ + +/* insmod parameters */ + +/* If force_addr is set to anything different from 0, we forcibly enable + the I801 at the given address. VERY DANGEROUS! */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Forcibly enable the I801 at the given address. " + "EXTREMELY DANGEROUS!"); + + + + + +static void i801_do_pause(unsigned int amount); +static int i801_transaction(void); +static int i801_block_transaction(union i2c_smbus_data *data, + char read_write, int command); + +static unsigned short i801_smba; +static struct pci_dev *I801_dev; +static int isich4; + +static int i801_setup(struct pci_dev *dev) +{ + int error_return = 0; + int *num = supported; + unsigned char temp; + + /* Note: we keep on searching until we have found 'function 3' */ + if(PCI_FUNC(dev->devfn) != 3) + return -ENODEV; + + I801_dev = dev; + isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS; + +/* Determine the address of the SMBus areas */ + if (force_addr) { + i801_smba = force_addr & 0xfff0; + } else { + pci_read_config_word(I801_dev, SMBBA, &i801_smba); + i801_smba &= 0xfff0; + if(i801_smba == 0) { + printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + } + + if (check_region(i801_smba, (isich4 ? 16 : 8))) { + printk + (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n", + i801_smba); + error_return = -ENODEV; + goto END; + } + + pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); + temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ + pci_write_config_byte(I801_dev, SMBHSTCFG, temp); +/* If force_addr is set, we program the new address here. Just to make + sure, we disable the device first. */ + if (force_addr) { + pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); + pci_write_config_word(I801_dev, SMBBA, i801_smba); + pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); + printk + (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new " + "address %04x!\n", i801_smba); + } else if ((temp & 1) == 0) { + pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); + printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n"); + } + + request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus"); + +#ifdef DEBUG + if (temp & 0x02) + printk + (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n"); + else + printk + (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n"); + + pci_read_config_byte(I801_dev, SMBREV, &temp); + printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp); + printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba); +#endif /* DEBUG */ + + END: + return error_return; +} + + +void i801_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +int i801_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp); +#endif + return -1; + } else { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Successfull!\n"); +#endif + } + } + + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + + /* We will always wait for a fraction of a second! */ + do { + i801_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); + result = -1; +#endif + } + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); +#endif + } + + if (temp & 0x08) { + result = -1; + printk + (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n" + "reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + } + + if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); +#endif + } + + if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) + outb_p(inb(SMBHSTSTS), SMBHSTSTS); + + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n", + temp); +#endif + } +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* All-inclusive block transaction function */ +int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command) +{ + int i, len; + int smbcmd; + int temp; + int result = 0; + int timeout; + unsigned char hostc, errmask; + + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + printk("i2c-i801.o: " + "I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); + return -1; + } + } + + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 1) + len = 1; + if (len > 32) + len = 32; + outb_p(len, SMBHSTDAT0); + outb_p(data->block[1], SMBBLKDAT); + } else { + len = 32; /* max for reads */ + } + + if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { + /* set 32 byte buffer */ + } + + for (i = 1; i <= len; i++) { + if (i == len && read_write == I2C_SMBUS_READ) + smbcmd = I801_BLOCK_LAST; + else + smbcmd = I801_BLOCK_DATA; +#if 0 /* now using HW PEC */ + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) + smbcmd |= I801_PEC_EN; +#endif + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBBLKDAT)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + temp = inb_p(SMBHSTSTS); + if (i == 1) { + /* Erronenous conditions before transaction: + * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + errmask=0x9f; + } else { + /* Erronenous conditions during transaction: + * Failed, Bus_Err, Dev_Err, Intr */ + errmask=0x1e; + } + if (temp & errmask) { +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { + printk + (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n", + temp); + result = -1; + goto END; + } + if (i != 1) { + result = -1; /* if die in middle of block transaction, fail */ + goto END; + } + } + + if (i == 1) { +#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */ + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { + if(read_write == I2C_SMBUS_WRITE) + outb_p(data->block[len + 1], SMBPEC); + } +#endif + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + } + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + i801_do_pause(1); + } + while ((!(temp & 0x80)) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); +#endif + } + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); +#endif + } else if (temp & 0x08) { + result = -1; + printk(KERN_ERR "i2c-i801.o: Bus collision!\n"); + } else if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); +#endif + } + + if (i == 1 && read_write == I2C_SMBUS_READ) { + len = inb_p(SMBHSTDAT0); + if (len < 1) + len = 1; + if (len > 32) + len = 32; + data->block[0] = len; + } + + /* Retrieve/store value in SMBBLKDAT */ + if (read_write == I2C_SMBUS_READ) + data->block[i] = inb_p(SMBBLKDAT); + if (read_write == I2C_SMBUS_WRITE && i+1 <= len) + outb_p(data->block[i+1], SMBBLKDAT); + if ((temp & 0x9e) != 0x00) + outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ + +#ifdef DEBUG + if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { + printk + (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n", + temp); + } + printk + (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBBLKDAT)); +#endif + + if (result < 0) + goto END; + } + +#ifdef HAVE_PEC + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { + /* wait for INTR bit as advised by Intel */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + i801_do_pause(1); + } while ((!(temp & 0x02)) + && (timeout++ < MAX_TIMEOUT)); + + if (timeout >= MAX_TIMEOUT) { + printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n"); + } +#if 0 /* now using HW PEC */ + if(read_write == I2C_SMBUS_READ) { + data->block[len + 1] = inb_p(SMBPEC); + } +#endif + outb_p(temp, SMBHSTSTS); + } +#endif + result = 0; +END: + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + /* restore saved configuration register value */ + pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); + } + return result; +} + +/* Return -1 on error. */ +s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, + char read_write, u8 command, int size, + union i2c_smbus_data * data) +{ + int hwpec = 0; + int block = 0; + int ret, xact = 0; + +#ifdef HAVE_PEC + if(isich4) + hwpec = (flags & I2C_CLIENT_PEC) != 0; +#endif + + switch (size) { + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + xact = I801_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + xact = I801_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + xact = I801_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + xact = I801_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_I2C_BLOCK_DATA: +#ifdef HAVE_PEC + case I2C_SMBUS_BLOCK_DATA_PEC: + if(hwpec && size == I2C_SMBUS_BLOCK_DATA) + size = I2C_SMBUS_BLOCK_DATA_PEC; +#endif + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + block = 1; + break; + case I2C_SMBUS_PROC_CALL: + default: + printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size); + return -1; + } + +#ifdef HAVE_PEC + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + outb_p(1, SMBAUXCTL); /* enable HW PEC */ + } +#endif + if(block) + ret = i801_block_transaction(data, read_write, size); + else { + outb_p(xact | ENABLE_INT9, SMBHSTCNT); + ret = i801_transaction(); + } + +#ifdef HAVE_PEC + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + outb_p(0, SMBAUXCTL); + } +#endif + + if(block) + return ret; + if(ret) + return -1; + if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) + return 0; + + switch (xact & 0x7f) { + case I801_BYTE: /* Result put in SMBHSTDAT0 */ + case I801_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case I801_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + } + return 0; +} + + +u32 i801_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK +#ifdef HAVE_PEC + | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC | + I2C_FUNC_SMBUS_HWPEC_CALC + : 0) +#endif + ; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = i801_access, + .functionality = i801_func, +}; + +static struct i2c_adapter i801_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id i801_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AA_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801AB_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801BA_2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_SMBUS, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_SMBUS, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { 0, } +}; + +static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + + if (i801_setup(dev)) { + printk + (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n"); + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + i801_adapter.dev.parent = &dev->dev; + + sprintf(i801_adapter.name, "SMBus I801 adapter at %04x", + i801_smba); + return i2c_add_adapter(&i801_adapter); +} + +static void __devexit i801_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&i801_adapter); +} + +static struct pci_driver i801_driver = { + .name = "i801 smbus", + .id_table = i801_ids, + .probe = i801_probe, + .remove = __devexit_p(i801_remove), +}; + +static int __init i2c_i801_init(void) +{ + printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&i801_driver); +} + + +static void __exit i2c_i801_exit(void) +{ + pci_unregister_driver(&i801_driver); + release_region(i801_smba, (isich4 ? 16 : 8)); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker "); +MODULE_DESCRIPTION("I801 SMBus driver"); + +module_init(i2c_i801_init); +module_exit(i2c_i801_exit); diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/busses/i2c-piix4.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,521 @@ +/* + piix4.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1998 - 2002 Frodo Looijaard and + Philip Edelbrock + + 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + Supports: + Intel PIIX4, 440MX + Serverworks OSB4, CSB5 + SMSC Victory66 + + Note: we assume there can only be one device, with one SMBus interface. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct sd { + const unsigned short mfr; + const unsigned short dev; + const unsigned char fn; + const char *name; +}; + +/* PIIX4 SMBus address offsets */ +#define SMBHSTSTS (0 + piix4_smba) +#define SMBHSLVSTS (1 + piix4_smba) +#define SMBHSTCNT (2 + piix4_smba) +#define SMBHSTCMD (3 + piix4_smba) +#define SMBHSTADD (4 + piix4_smba) +#define SMBHSTDAT0 (5 + piix4_smba) +#define SMBHSTDAT1 (6 + piix4_smba) +#define SMBBLKDAT (7 + piix4_smba) +#define SMBSLVCNT (8 + piix4_smba) +#define SMBSHDWCMD (9 + piix4_smba) +#define SMBSLVEVT (0xA + piix4_smba) +#define SMBSLVDAT (0xC + piix4_smba) + +/* PCI Address Constants */ +#define SMBBA 0x090 +#define SMBHSTCFG 0x0D2 +#define SMBSLVC 0x0D3 +#define SMBSHDW1 0x0D4 +#define SMBSHDW2 0x0D5 +#define SMBREV 0x0D6 + +/* Other settings */ +#define MAX_TIMEOUT 500 +#define ENABLE_INT9 0 + +/* PIIX4 constants */ +#define PIIX4_QUICK 0x00 +#define PIIX4_BYTE 0x04 +#define PIIX4_BYTE_DATA 0x08 +#define PIIX4_WORD_DATA 0x0C +#define PIIX4_BLOCK_DATA 0x14 + +/* insmod parameters */ + +/* If force is set to anything different from 0, we forcibly enable the + PIIX4. DANGEROUS! */ +static int force = 0; +MODULE_PARM(force, "i"); +MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!"); + +/* If force_addr is set to anything different from 0, we forcibly enable + the PIIX4 at the given address. VERY DANGEROUS! */ +static int force_addr = 0; +MODULE_PARM(force_addr, "i"); +MODULE_PARM_DESC(force_addr, + "Forcibly enable the PIIX4 at the given address. " + "EXTREMELY DANGEROUS!"); + +static void piix4_do_pause(unsigned int amount); +static int piix4_transaction(void); + + +static unsigned short piix4_smba = 0; + +/* + * Get DMI information. + */ +static int ibm_dmi_probe(void) +{ +#ifdef CONFIG_X86 + extern int is_unsafe_smbus; + return is_unsafe_smbus; +#else + return 0; +#endif +} + +static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id) +{ + int error_return = 0; + unsigned char temp; + + /* match up the function */ + if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) + return -ENODEV; + + printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name); + + if(ibm_dmi_probe()) { + printk + (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n"); + printk + (KERN_ERR " your serial eeprom! Refusing to load module!\n"); + error_return = -EPERM; + goto END; + } + +/* Determine the address of the SMBus areas */ + if (force_addr) { + piix4_smba = force_addr & 0xfff0; + force = 0; + } else { + pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); + piix4_smba &= 0xfff0; + if(piix4_smba == 0) { + printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + return -ENODEV; + } + } + + if (check_region(piix4_smba, 8)) { + printk + (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n", + piix4_smba); + error_return = -ENODEV; + goto END; + } + + pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); +/* If force_addr is set, we program the new address here. Just to make + sure, we disable the PIIX4 first. */ + if (force_addr) { + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); + pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); + printk + (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new " + "address %04x!\n", piix4_smba); + } else if ((temp & 1) == 0) { + if (force) { +/* This should never need to be done, but has been noted that + many Dell machines have the SMBus interface on the PIIX4 + disabled!? NOTE: This assumes I/O space and other allocations WERE + done by the Bios! Don't complain if your hardware does weird + things after enabling this. :') Check for Bios updates before + resorting to this. */ + pci_write_config_byte(PIIX4_dev, SMBHSTCFG, + temp | 1); + printk + (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY " + "ENABLED!\n"); + } else { + printk + (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n"); + error_return = -ENODEV; + goto END; + } + } + + /* Everything is happy, let's grab the memory and set things up. */ + request_region(piix4_smba, 8, "piix4-smbus"); + +#ifdef DEBUG + if ((temp & 0x0E) == 8) + printk + (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n"); + else if ((temp & 0x0E) == 0) + printk + (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n"); + else + printk + (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out " + "of date)!\n"); + + pci_read_config_byte(PIIX4_dev, SMBREV, &temp); + printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp); + printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba); +#endif /* DEBUG */ + + END: + return error_return; +} + + +/* Internally used pause function */ +static void piix4_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +/* Another internally used function */ +static int piix4_transaction(void) +{ + int temp; + int result = 0; + int timeout = 0; + +#ifdef DEBUG + printk + (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " + "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + + /* Make sure the SMBus host is ready to start transmitting */ + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n", + temp); +#endif + outb_p(temp, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp); +#endif + return -1; + } else { +#ifdef DEBUG + printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n"); +#endif + } + } + + /* start the transaction by setting bit 6 */ + outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); + + /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ + do { + piix4_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); + +#ifdef DEBUG + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n"); + result = -1; + } +#endif + + if (temp & 0x10) { + result = -1; +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n"); +#endif + } + + if (temp & 0x08) { + result = -1; + printk + (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n" + "reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ + } + + if (temp & 0x04) { + result = -1; +#ifdef DEBUG + printk(KERN_ERR "i2c-piix4.o: Error: no response!\n"); +#endif + } + + if (inb_p(SMBHSTSTS) != 0x00) + outb_p(inb(SMBHSTSTS), SMBHSTSTS); + +#ifdef DEBUG + if ((temp = inb_p(SMBHSTSTS)) != 0x00) { + printk + (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n", + temp); + } + printk + (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " + "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); +#endif + return result; +} + +/* Return -1 on error. */ +static s32 piix4_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data * data) +{ + int i, len; + + switch (size) { + case I2C_SMBUS_PROC_CALL: + printk + (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n"); + return -1; + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = PIIX4_QUICK; + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + size = PIIX4_BYTE; + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + size = PIIX4_BYTE_DATA; + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + size = PIIX4_WORD_DATA; + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) + len = 0; + if (len > 32) + len = 32; + outb_p(len, SMBHSTDAT0); + i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + size = PIIX4_BLOCK_DATA; + break; + } + + outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); + + if (piix4_transaction()) /* Error in transaction */ + return -1; + + if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) + return 0; + + + switch (size) { + case PIIX4_BYTE: /* Where is the result put? I assume here it is in + SMBHSTDAT0 but it might just as well be in the + SMBHSTCMD. No clue in the docs */ + + data->byte = inb_p(SMBHSTDAT0); + break; + case PIIX4_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case PIIX4_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case PIIX4_BLOCK_DATA: + data->block[0] = inb_p(SMBHSTDAT0); + i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= data->block[0]; i++) + data->block[i] = inb_p(SMBBLKDAT); + break; + } + return 0; +} + + +static u32 piix4_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-I2C SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = piix4_access, + .functionality = piix4_func, +}; + +static struct i2c_adapter piix4_adapter = { + .owner = THIS_MODULE, + .name = "unset", + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4, + .algo = &smbus_algorithm, +}; + + + +static struct pci_device_id piix4_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371AB_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 3 + }, + { + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_OSB4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { + .vendor = PCI_VENDOR_ID_SERVERWORKS, + .device = PCI_DEVICE_ID_SERVERWORKS_CSB5, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82443MX_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 3, + }, + { + .vendor = PCI_VENDOR_ID_EFAR, + .device = PCI_DEVICE_ID_EFAR_SLC90E66_3, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = 0, + }, + { 0, } +}; + +static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int retval; + + retval = piix4_setup(dev, id); + if (retval) + return retval; + + /* set up the driverfs linkage to our parent device */ + piix4_adapter.dev.parent = &dev->dev; + + sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x", + piix4_smba); + + retval = i2c_add_adapter(&piix4_adapter); + + return retval; +} + +static void __devexit piix4_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&piix4_adapter); +} + + +static struct pci_driver piix4_driver = { + .name = "piix4 smbus", + .id_table = piix4_ids, + .probe = piix4_probe, + .remove = __devexit_p(piix4_remove), +}; + +static int __init i2c_piix4_init(void) +{ + printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&piix4_driver); +} + + +static void __exit i2c_piix4_exit(void) +{ + pci_unregister_driver(&piix4_driver); + release_region(piix4_smba, 8); +} + + + +MODULE_AUTHOR + ("Frodo Looijaard and Philip Edelbrock "); +MODULE_DESCRIPTION("PIIX4 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_piix4_init); +module_exit(i2c_piix4_exit); diff -Nru a/drivers/i2c/i2c-algo-bit.c b/drivers/i2c/i2c-algo-bit.c --- a/drivers/i2c/i2c-algo-bit.c Sat Mar 15 18:40:42 2003 +++ b/drivers/i2c/i2c-algo-bit.c Sat Mar 15 18:40:42 2003 @@ -41,27 +41,13 @@ #define DEBPROTO(x) if (i2c_debug>=9) { x; } /* debug the protocol by showing transferred bits */ -/* debugging - slow down transfer to have a look at the data .. */ -/* I use this with two leds&resistors, each one connected to sda,scl */ -/* respectively. This makes sure that the algorithm works. Some chips */ -/* might not like this, as they have an internal timeout of some mils */ -/* -#define SLO_IO jif=jiffies;while(time_before_eq(jiffies, jif+i2c_table[minor].veryslow))\ - cond_resched(); -*/ - /* ----- global variables --------------------------------------------- */ -#ifdef SLO_IO - int jif; -#endif - /* module parameters: */ static int i2c_debug; static int bit_test; /* see if the line-setting functions work */ -static int bit_scan; /* have a look at what's hanging 'round */ /* --- setting states on the bus with the right timing: --------------- */ @@ -86,9 +72,6 @@ { setscl(adap,0); udelay(adap->udelay); -#ifdef SLO_IO - SLO_IO -#endif } /* @@ -97,32 +80,28 @@ */ static inline int sclhi(struct i2c_algo_bit_data *adap) { - int start=jiffies; + unsigned long start; setscl(adap,1); - udelay(adap->udelay); - /* Not all adapters have scl sense line... */ if (adap->getscl == NULL ) return 0; - while (! getscl(adap) ) { + start=jiffies; + while (! getscl(adap) ) { /* the hw knows how to read the clock line, * so we wait until it actually gets high. * This is safer as some chips may hold it low * while they are processing data internally. */ - setscl(adap,1); if (time_after_eq(jiffies, start+adap->timeout)) { return -ETIMEDOUT; } cond_resched(); } DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start)); -#ifdef SLO_IO - SLO_IO -#endif + udelay(adap->udelay); return 0; } @@ -175,7 +154,6 @@ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; /* assert: scl is low */ - DEB2(printk(KERN_DEBUG " i2c_outb:%2.2X\n",c&0xff)); for ( i=7 ; i>=0 ; i-- ) { sb = c & ( 1 << i ); setsda(adap,sb); @@ -183,6 +161,7 @@ DEBPROTO(printk(KERN_DEBUG "%d",sb!=0)); if (sclhi(adap)<0) { /* timed out */ sdahi(adap); /* we don't want to block the net */ + DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i)); return -ETIMEDOUT; }; /* do arbitration here: @@ -193,11 +172,12 @@ } sdahi(adap); if (sclhi(adap)<0){ /* timeout */ - return -ETIMEDOUT; + DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff)); + return -ETIMEDOUT; }; /* read ack: SDA should be pulled down by slave */ ack=getsda(adap); /* ack: sda is pulled low ->success. */ - DEB2(printk(KERN_DEBUG " i2c_outb: getsda() = 0x%2.2x\n", ~ack )); + DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack)); DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) ); DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") ); @@ -216,11 +196,10 @@ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; /* assert: scl is low */ - DEB2(printk(KERN_DEBUG "i2c_inb.\n")); - sdahi(adap); for (i=0;i<8;i++) { if (sclhi(adap)<0) { /* timeout */ + DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i)); return -ETIMEDOUT; }; indata *= 2; @@ -229,7 +208,9 @@ scllo(adap); } /* assert: scl is low */ - DEBPROTO(printk(KERN_DEBUG " %2.2x", indata & 0xff)); + DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff)); + + DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff)); return (int) (indata & 0xff); } @@ -337,30 +318,35 @@ i2c_start(adap); udelay(adap->udelay); } - DEB2(if (i) printk(KERN_DEBUG "i2c-algo-bit.o: needed %d retries for %d\n", - i,addr)); + DEB2(if (i) + printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n", + i+1, addr & 1 ? "read" : "write", addr>>1, + ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" ) + ); return ret; } -static int sendbytes(struct i2c_adapter *i2c_adap,const char *buf, int count) +static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { struct i2c_algo_bit_data *adap = i2c_adap->algo_data; char c; - const char *temp = buf; + const char *temp = msg->buf; + int count = msg->len; + unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; int retval; int wrcount=0; while (count > 0) { c = *temp; - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s i2c_write: writing %2.2X\n", + DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: %s sendbytes: writing %2.2X\n", i2c_adap->name, c&0xff)); retval = i2c_outb(i2c_adap,c); - if (retval>0) { + if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ count--; temp++; wrcount++; } else { /* arbitration or no acknowledge */ - printk(KERN_ERR "i2c-algo-bit.o: %s i2c_write: error - bailout.\n", + printk(KERN_ERR "i2c-algo-bit.o: %s sendbytes: error - bailout.\n", i2c_adap->name); i2c_stop(adap); return (retval<0)? retval : -EFAULT; @@ -374,12 +360,13 @@ return wrcount; } -static inline int readbytes(struct i2c_adapter *i2c_adap,char *buf,int count) +static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { - char *temp = buf; int inval; int rdcount=0; /* counts bytes read */ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; + char *temp = msg->buf; + int count = msg->len; while (count > 0) { inval = i2c_inb(i2c_adap); @@ -388,7 +375,7 @@ *temp = inval; rdcount++; } else { /* read timed out */ - printk(KERN_ERR "i2c-algo-bit.o: i2c_read: i2c_inb timed out.\n"); + printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n"); break; } @@ -401,7 +388,7 @@ } if (sclhi(adap)<0) { /* timeout */ sdahi(adap); - printk(KERN_ERR "i2c-algo-bit.o: i2c_read: Timeout at ack\n"); + printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n"); return -ETIMEDOUT; }; scllo(adap); @@ -416,31 +403,34 @@ * try_address) and transmits the address in the necessary format to handle * reads, writes as well as 10bit-addresses. * returns: - * 0 everything went okay, the chip ack'ed + * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set * -x an error occurred (like: -EREMOTEIO if the device did not answer, or * -ETIMEDOUT, for example if the lines are stuck...) */ -static inline int bit_doAddress(struct i2c_adapter *i2c_adap, - struct i2c_msg *msg, int retries) +static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) { unsigned short flags = msg->flags; + unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; struct i2c_algo_bit_data *adap = i2c_adap->algo_data; unsigned char addr; - int ret; + int ret, retries; + + retries = nak_ok ? 0 : i2c_adap->retries; + if ( (flags & I2C_M_TEN) ) { /* a ten bit address */ addr = 0xf0 | (( msg->addr >> 7) & 0x03); DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); /* try extended address code...*/ ret = try_address(i2c_adap, addr, retries); - if (ret!=1) { + if ((ret != 1) && !nak_ok) { printk(KERN_ERR "died at extended address code.\n"); return -EREMOTEIO; } /* the remaining 8 bit address */ ret = i2c_outb(i2c_adap,msg->addr & 0x7f); - if (ret != 1) { + if ((ret != 1) && !nak_ok) { /* the chip did not ack / xmission error occurred */ printk(KERN_ERR "died at 2nd address code.\n"); return -EREMOTEIO; @@ -450,7 +440,7 @@ /* okay, now switch into reading mode */ addr |= 0x01; ret = try_address(i2c_adap, addr, retries); - if (ret!=1) { + if ((ret!=1) && !nak_ok) { printk(KERN_ERR "died at extended address code.\n"); return -EREMOTEIO; } @@ -462,10 +452,10 @@ if (flags & I2C_M_REV_DIR_ADDR ) addr ^= 1; ret = try_address(i2c_adap, addr, retries); - if (ret!=1) { + if ((ret!=1) && !nak_ok) return -EREMOTEIO; - } } + return 0; } @@ -476,31 +466,33 @@ struct i2c_algo_bit_data *adap = i2c_adap->algo_data; int i,ret; + unsigned short nak_ok; i2c_start(adap); for (i=0;iflags & I2C_M_IGNORE_NAK; if (!(pmsg->flags & I2C_M_NOSTART)) { if (i) { i2c_repstart(adap); } - ret = bit_doAddress(i2c_adap,pmsg,i2c_adap->retries); - if (ret != 0) { - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device adr %#2x msg #%d\n" - ,msgs[i].addr,i)); - return (ret<0) ? ret : -EREMOTEIO; + ret = bit_doAddress(i2c_adap, pmsg); + if ((ret != 0) && !nak_ok) { + DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" + ,msgs[i].addr,i)); + return (ret<0) ? ret : -EREMOTEIO; } } if (pmsg->flags & I2C_M_RD ) { /* read bytes into buffer*/ - ret = readbytes(i2c_adap,pmsg->buf,pmsg->len); + ret = readbytes(i2c_adap, pmsg); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); if (ret < pmsg->len ) { return (ret<0)? ret : -EREMOTEIO; } } else { /* write bytes from buffer */ - ret = sendbytes(i2c_adap,pmsg->buf,pmsg->len); + ret = sendbytes(i2c_adap, pmsg); DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); if (ret < pmsg->len ) { return (ret<0) ? ret : -EREMOTEIO; @@ -511,12 +503,6 @@ return num; } -static int algo_control(struct i2c_adapter *adapter, - unsigned int cmd, unsigned long arg) -{ - return 0; -} - static u32 bit_func(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | @@ -530,7 +516,6 @@ .name = "Bit-shift algorithm", .id = I2C_ALGO_BIT, .master_xfer = bit_xfer, - .algo_control = algo_control, .functionality = bit_func, }; @@ -539,7 +524,6 @@ */ int i2c_bit_add_bus(struct i2c_adapter *adap) { - int i; struct i2c_algo_bit_data *bit_adap = adap->algo_data; if (bit_test) { @@ -559,23 +543,6 @@ adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ - /* scan bus */ - if (bit_scan) { - int ack; - printk(KERN_INFO " i2c-algo-bit.o: scanning bus %s.\n", - adap->name); - for (i = 0x00; i < 0xff; i+=2) { - i2c_start(bit_adap); - ack = i2c_outb(adap,i); - i2c_stop(bit_adap); - if (ack>0) { - printk("(%02x)",i>>1); - } else - printk("."); - } - printk("\n"); - } - i2c_add_adapter(adap); return 0; } @@ -583,14 +550,7 @@ int i2c_bit_del_bus(struct i2c_adapter *adap) { - int res; - - if ((res = i2c_del_adapter(adap)) < 0) - return res; - - DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: adapter unregistered: %s\n",adap->name)); - - return 0; + return i2c_del_adapter(adap); } EXPORT_SYMBOL(i2c_bit_add_bus); @@ -601,10 +561,8 @@ MODULE_LICENSE("GPL"); MODULE_PARM(bit_test, "i"); -MODULE_PARM(bit_scan, "i"); MODULE_PARM(i2c_debug,"i"); MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck"); -MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus"); MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol"); + "debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol"); diff -Nru a/drivers/i2c/i2c-algo-ibm_ocp.c b/drivers/i2c/i2c-algo-ibm_ocp.c --- a/drivers/i2c/i2c-algo-ibm_ocp.c Sat Mar 15 18:40:43 2003 +++ b/drivers/i2c/i2c-algo-ibm_ocp.c Sat Mar 15 18:40:43 2003 @@ -55,20 +55,12 @@ #include #include #include -#include #include -#include -#include #include #include - #include -#include "i2c-algo-ibm_ocp.h" -//ACC#include - -#ifdef MODULE_LICENSE -MODULE_LICENSE("GPL"); -#endif +#include +#include /* ----- global defines ----------------------------------------------- */ @@ -79,26 +71,13 @@ /* debug the protocol by showing transferred bits */ #define DEF_TIMEOUT 5 -/* debugging - slow down transfer to have a look at the data .. */ -/* I use this with two leds&resistors, each one connected to sda,scl */ -/* respectively. This makes sure that the algorithm works. Some chips */ -/* might not like this, as they have an internal timeout of some mils */ -/* -#define SLO_IO jif=jiffies;while(time_before_eq(jiffies,jif+i2c_table[minor].veryslow))\ - if (need_resched) schedule(); -*/ - /* ----- global variables --------------------------------------------- */ -#ifdef SLO_IO - int jif; -#endif /* module parameters: */ static int i2c_debug=0; -static int iic_scan=0; /* have a look at what's hanging 'round */ /* --- setting states on the bus with the right timing: --------------- */ @@ -758,7 +737,7 @@ // Check to see if the bus is busy // ret = iic_inb(adap, iic->extsts); - // Mask off the irrelevant bits + // Mask off the irrelevent bits ret = ret & 0x70; // When the bus is free, the BCS bits in the EXTSTS register are 0b100 if(ret != 0x40) return IIC_ERR_LOST_ARB; @@ -858,17 +837,13 @@ /* -----exported algorithm data: ------------------------------------- */ static struct i2c_algorithm iic_algo = { - "IBM on-chip IIC algorithm", - I2C_ALGO_OCP, - iic_xfer, - NULL, - NULL, /* slave_xmit */ - NULL, /* slave_recv */ - algo_control, /* ioctl */ - iic_func, /* functionality */ + .name = "IBM on-chip IIC algorithm", + .id = I2C_ALGO_OCP, + .master_xfer = iic_xfer, + .algo_control = algo_control, + .functionality = iic_func, }; - /* * registering functions to load algorithms at runtime */ @@ -892,19 +867,8 @@ adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - iic_init(iic_adap); i2c_add_adapter(adap); - - /* scan bus */ - /* By default scanning the bus is turned off. */ - if (iic_scan) { - printk(KERN_INFO " i2c-algo-iic.o: scanning bus %s.\n", - adap->name); - } return 0; } @@ -914,31 +878,7 @@ // int i2c_ocp_del_bus(struct i2c_adapter *adap) { - int res; - if ((res = i2c_del_adapter(adap)) < 0) - return res; - DEB2(printk(KERN_DEBUG "i2c-algo-iic.o: adapter unregistered: %s\n",adap->name)); - -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return 0; -} - - -// -// Done -// -int __init i2c_algo_iic_init (void) -{ - printk(KERN_INFO "IBM On-chip iic (i2c) algorithm module 2002.27.03\n"); - return 0; -} - - -void i2c_algo_iic_exit(void) -{ - return; + return i2c_del_adapter(adap); } @@ -951,16 +891,10 @@ // MODULE_AUTHOR("MontaVista Software "); MODULE_DESCRIPTION("PPC 405 iic algorithm"); +MODULE_LICENSE("GPL"); -MODULE_PARM(iic_test, "i"); -MODULE_PARM(iic_scan, "i"); MODULE_PARM(i2c_debug,"i"); -MODULE_PARM_DESC(iic_test, "Test if the I2C bus is available"); -MODULE_PARM_DESC(iic_scan, "Scan for active chips on the bus"); MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 iic-protocol"); - -module_init(i2c_algo_iic_init); -module_exit(i2c_algo_iic_exit); diff -Nru a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c --- a/drivers/i2c/i2c-algo-pcf.c Sat Mar 15 18:40:43 2003 +++ b/drivers/i2c/i2c-algo-pcf.c Sat Mar 15 18:40:43 2003 @@ -49,7 +49,6 @@ /* module parameters: */ static int i2c_debug=0; -static int pcf_scan=0; /* have a look at what's hanging 'round */ /* --- setting states on the bus with the right timing: --------------- */ @@ -423,12 +422,6 @@ return (i); } -static int algo_control(struct i2c_adapter *adapter, - unsigned int cmd, unsigned long arg) -{ - return 0; -} - static u32 pcf_func(struct i2c_adapter *adap) { return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | @@ -438,14 +431,10 @@ /* -----exported algorithm data: ------------------------------------- */ static struct i2c_algorithm pcf_algo = { - "PCF8584 algorithm", - I2C_ALGO_PCF, - pcf_xfer, - NULL, - NULL, /* slave_xmit */ - NULL, /* slave_recv */ - algo_control, /* ioctl */ - pcf_func, /* functionality */ + .name = "PCF8584 algorithm", + .id = I2C_ALGO_PCF, + .master_xfer = pcf_xfer, + .functionality = pcf_func, }; /* @@ -453,8 +442,8 @@ */ int i2c_pcf_add_bus(struct i2c_adapter *adap) { - int i, status; struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; + int rval; DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: hw routines for %s registered.\n", adap->name)); @@ -467,36 +456,10 @@ adap->timeout = 100; /* default values, should */ adap->retries = 3; /* be replaced by defines */ - if ((i = pcf_init_8584(pcf_adap))) { - return i; - } - - i2c_add_adapter(adap); - - /* scan bus */ - if (pcf_scan) { - printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s.\n", - adap->name); - for (i = 0x00; i < 0xff; i+=2) { - if (wait_for_bb(pcf_adap)) { - printk(KERN_INFO " i2c-algo-pcf.o: scanning bus %s - TIMEOUTed.\n", - adap->name); - break; - } - i2c_outb(pcf_adap, i); - i2c_start(pcf_adap); - if ((wait_for_pin(pcf_adap, &status) >= 0) && - ((status & I2C_PCF_LRB) == 0)) { - printk("(%02x)",i>>1); - } else { - printk("."); - } - i2c_stop(pcf_adap); - udelay(pcf_adap->udelay); - } - printk("\n"); - } - return 0; + rval = pcf_init_8584(pcf_adap); + if (!rval) + i2c_add_adapter(adap); + return rval; } @@ -512,9 +475,6 @@ MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); MODULE_LICENSE("GPL"); -MODULE_PARM(pcf_scan, "i"); MODULE_PARM(i2c_debug,"i"); - -MODULE_PARM_DESC(pcf_scan, "Scan for active chips on the bus"); MODULE_PARM_DESC(i2c_debug, "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c --- a/drivers/i2c/i2c-core.c Sat Mar 15 18:40:40 2003 +++ b/drivers/i2c/i2c-core.c Sat Mar 15 18:40:40 2003 @@ -21,69 +21,35 @@ All SMBus-related things are written by Frodo Looijaard SMBus 2.0 support by Mark Studebaker */ -/* $Id: i2c-core.c,v 1.89 2002/11/03 16:47:16 mds Exp $ */ +/* $Id: i2c-core.c,v 1.95 2003/01/22 05:25:08 kmalkki Exp $ */ #include #include #include #include #include -#include #include - -/* ----- compatibility stuff ----------------------------------------------- */ - -#include #include - +#include #include -/* ----- global defines ---------------------------------------------------- */ - -/* exclusive access to the bus */ -#define I2C_LOCK(adap) down(&adap->lock) -#define I2C_UNLOCK(adap) up(&adap->lock) - -#define ADAP_LOCK() down(&adap_lock) -#define ADAP_UNLOCK() up(&adap_lock) - -#define DRV_LOCK() down(&driver_lock) -#define DRV_UNLOCK() up(&driver_lock) #define DEB(x) if (i2c_debug>=1) x; #define DEB2(x) if (i2c_debug>=2) x; -/* ----- global variables -------------------------------------------------- */ - -/**** lock for writing to global variables: the adapter & driver list */ -static DECLARE_MUTEX(adap_lock); -static DECLARE_MUTEX(driver_lock); - -/**** adapter list */ static struct i2c_adapter *adapters[I2C_ADAP_MAX]; - -/**** drivers list */ static struct i2c_driver *drivers[I2C_DRIVER_MAX]; +static DECLARE_MUTEX(core_lists); /**** debug level */ static int i2c_debug; -/* --------------------------------------------------- - * /proc entry declarations - *---------------------------------------------------- - */ - #ifdef CONFIG_PROC_FS -static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos); -static int read_bus_i2c(char *buf, char **start, off_t offset, int len, - int *eof , void *private); - -/* To implement the dynamic /proc/bus/i2c-? files, we need our own - implementation of the read hook */ -static struct file_operations i2cproc_operations = { - .read = i2cproc_bus_read, -}; +static int i2cproc_register(struct i2c_adapter *adap, int bus); +static void i2cproc_remove(int bus); +#else +# define i2cproc_register(adap, bus) 0 +# define i2cproc_remove(bus) do { } while (0) #endif /* CONFIG_PROC_FS */ @@ -99,9 +65,9 @@ */ int i2c_add_adapter(struct i2c_adapter *adap) { - int i,j,res; + int res = 0, i, j; - ADAP_LOCK(); + down(&core_lists); for (i = 0; i < I2C_ADAP_MAX; i++) if (NULL == adapters[i]) break; @@ -110,66 +76,50 @@ " i2c-core.o: register_adapter(%s) - enlarge I2C_ADAP_MAX.\n", adap->name); res = -ENOMEM; - goto ERROR0; + goto out_unlock; } - adapters[i] = adap; - ADAP_UNLOCK(); - - /* init data types */ - init_MUTEX(&adap->lock); + res = i2cproc_register(adap, i); + if (res) + goto out_unlock; -#ifdef CONFIG_PROC_FS - { - char name[8]; - struct proc_dir_entry *proc_entry; - - sprintf(name,"i2c-%d", i); + adapters[i] = adap; - proc_entry = create_proc_entry(name,0,proc_bus); - if (! proc_entry) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", - name); - res = -ENOENT; - goto ERROR1; - } + init_MUTEX(&adap->bus); + init_MUTEX(&adap->list); - proc_entry->proc_fops = &i2cproc_operations; - proc_entry->owner = THIS_MODULE; - adap->inode = proc_entry->low_ino; - } -#endif /* def CONFIG_PROC_FS */ + /* Add the adapter to the driver core. + * If the parent pointer is not set up, + * we add this adapter to the legacy bus. + */ + if (adap->dev.parent == NULL) + adap->dev.parent = &legacy_bus; + sprintf(adap->dev.bus_id, "i2c-%d", i); + strcpy(adap->dev.name, "i2c controller"); + device_register(&adap->dev); /* inform drivers of new adapters */ - DRV_LOCK(); for (j=0;jflags&(I2C_DF_NOTIFY|I2C_DF_DUMMY))) /* We ignore the return code; if it fails, too bad */ drivers[j]->attach_adapter(adap); - DRV_UNLOCK(); + up(&core_lists); DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n", adap->name,i)); - return 0; - - -ERROR1: - ADAP_LOCK(); - adapters[i] = NULL; -ERROR0: - ADAP_UNLOCK(); - return res; + out_unlock: + up(&core_lists); + return res;; } int i2c_del_adapter(struct i2c_adapter *adap) { - int i,j,res; - - ADAP_LOCK(); + int res = 0, i, j; + down(&core_lists); for (i = 0; i < I2C_ADAP_MAX; i++) if (adap == adapters[i]) break; @@ -177,7 +127,7 @@ printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n", adap->name); res = -ENODEV; - goto ERROR0; + goto out_unlock; } /* DUMMY drivers do not register their clients, so we have to @@ -185,23 +135,20 @@ * *detach* it! Of course, each dummy driver should know about * this or hell will break loose... */ - DRV_LOCK(); for (j = 0; j < I2C_DRIVER_MAX; j++) if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY)) if ((res = drivers[j]->attach_adapter(adap))) { printk(KERN_WARNING "i2c-core.o: can't detach adapter %s " "while detaching driver %s: driver not " "detached!",adap->name,drivers[j]->name); - goto ERROR1; + goto out_unlock; } - DRV_UNLOCK(); - /* detach any active clients. This must be done first, because * it can fail; in which case we give upp. */ for (j=0;jclients[j]; - if (client!=NULL) + if (client!=NULL) { /* detaching devices is unconditional of the set notify * flag, as _all_ clients that reside on the adapter * must be deleted, as this would cause invalid states. @@ -211,28 +158,22 @@ "unregistered, because client at " "address %02x can't be detached. ", adap->name, client->addr); - goto ERROR0; + goto out_unlock; } + } } -#ifdef CONFIG_PROC_FS - { - char name[8]; - sprintf(name,"i2c-%d", i); - remove_proc_entry(name, proc_bus); - } -#endif /* def CONFIG_PROC_FS */ + + i2cproc_remove(i); + + /* clean up the sysfs representation */ + device_unregister(&adap->dev); adapters[i] = NULL; - - ADAP_UNLOCK(); + DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name)); - return 0; -ERROR0: - ADAP_UNLOCK(); - return res; -ERROR1: - DRV_UNLOCK(); + out_unlock: + up(&core_lists); return res; } @@ -245,8 +186,9 @@ int i2c_add_driver(struct i2c_driver *driver) { - int i; - DRV_LOCK(); + int res = 0, i; + + down(&core_lists); for (i = 0; i < I2C_DRIVER_MAX; i++) if (NULL == drivers[i]) break; @@ -255,35 +197,34 @@ " i2c-core.o: register_driver(%s) " "- enlarge I2C_DRIVER_MAX.\n", driver->name); - DRV_UNLOCK(); - return -ENOMEM; + res = -ENOMEM; + goto out_unlock; } drivers[i] = driver; - DRV_UNLOCK(); /* driver was successfully added */ - DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); - ADAP_LOCK(); - /* now look for instances of driver on our adapters */ if (driver->flags& (I2C_DF_NOTIFY|I2C_DF_DUMMY)) { - for (i=0;iattach_adapter(adapters[i]); + } } - ADAP_UNLOCK(); - return 0; + + out_unlock: + up(&core_lists); + return res; } int i2c_del_driver(struct i2c_driver *driver) { - int i,j,k,res; + int res = 0, i, j, k; - DRV_LOCK(); + down(&core_lists); for (i = 0; i < I2C_DRIVER_MAX; i++) if (driver == drivers[i]) break; @@ -291,19 +232,20 @@ printk(KERN_WARNING " i2c-core.o: unregister_driver: " "[%s] not found\n", driver->name); - DRV_UNLOCK(); - return -ENODEV; + res = -ENODEV; + goto out_unlock; } + /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. */ DEB2(printk(KERN_DEBUG "i2c-core.o: unregister_driver - looking for clients.\n")); + /* removing clients does not depend on the notify flag, else * invalid operation might (will!) result, when using stale client * pointers. */ - ADAP_LOCK(); /* should be moved inside the if statement... */ for (k=0;kname, adap->name); - ADAP_UNLOCK(); - return res; + goto out_unlock; } } else { for (j=0;jname, client->addr, adap->name); - ADAP_UNLOCK(); - return res; + goto out_unlock; } } } } } - ADAP_UNLOCK(); drivers[i] = NULL; - DRV_UNLOCK(); DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name)); + + out_unlock: + up(&core_lists); return 0; } -int i2c_check_addr (struct i2c_adapter *adapter, int addr) +static int __i2c_check_addr(struct i2c_adapter *adapter, int addr) { int i; - for (i = 0; i < I2C_CLIENT_MAX ; i++) + + for (i = 0; i < I2C_CLIENT_MAX ; i++) if (adapter->clients[i] && (adapter->clients[i]->addr == addr)) return -EBUSY; + return 0; } +int i2c_check_addr(struct i2c_adapter *adapter, int addr) +{ + int rval; + + down(&adapter->list); + rval = __i2c_check_addr(adapter, addr); + up(&adapter->list); + + return rval; +} + int i2c_attach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; int i; - if (i2c_check_addr(client->adapter,client->addr)) - return -EBUSY; + down(&adapter->list); + if (__i2c_check_addr(client->adapter, client->addr)) + goto out_unlock_list; - for (i = 0; i < I2C_CLIENT_MAX; i++) - if (NULL == adapter->clients[i]) - break; - if (I2C_CLIENT_MAX == i) { - printk(KERN_WARNING - " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", - client->name); - return -ENOMEM; + for (i = 0; i < I2C_CLIENT_MAX; i++) { + if (!adapter->clients[i]) + goto free_slot; } + printk(KERN_WARNING + " i2c-core.o: attach_client(%s) - enlarge I2C_CLIENT_MAX.\n", + client->name); + + out_unlock_list: + up(&adapter->list); + return -EBUSY; + + free_slot: adapter->clients[i] = client; - adapter->client_count++; + up(&adapter->list); - if (adapter->client_register) - if (adapter->client_register(client)) - printk(KERN_DEBUG "i2c-core.o: warning: client_register seems " + if (adapter->client_register) { + if (adapter->client_register(client)) { + printk(KERN_DEBUG + "i2c-core.o: warning: client_register seems " "to have failed for client %02x at adapter %s\n", - client->addr,adapter->name); - DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n", - client->name, adapter->name,i)); + client->addr, adapter->name); + } + } - if(client->flags & I2C_CLIENT_ALLOW_USE) + DEB(printk(KERN_DEBUG + "i2c-core.o: client [%s] registered to adapter [%s] " + "(pos. %d).\n", client->name, adapter->name, i)); + + if (client->flags & I2C_CLIENT_ALLOW_USE) client->usage_count = 0; - return 0; } @@ -409,34 +372,38 @@ int i2c_detach_client(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - int i,res; - - for (i = 0; i < I2C_CLIENT_MAX; i++) - if (client == adapter->clients[i]) - break; - if (I2C_CLIENT_MAX == i) { - printk(KERN_WARNING " i2c-core.o: unregister_client " - "[%s] not found\n", - client->name); - return -ENODEV; - } + int res = 0, i; - if( (client->flags & I2C_CLIENT_ALLOW_USE) && - (client->usage_count>0)) + if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0)) return -EBUSY; - - if (adapter->client_unregister != NULL) - if ((res = adapter->client_unregister(client))) { - printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, " - "client not detached",client->name); - return res; + + if (adapter->client_unregister) { + res = adapter->client_unregister(client); + if (res) { + printk(KERN_ERR + "i2c-core.o: client_unregister [%s] failed, " + "client not detached", client->name); + goto out; } + } - adapter->clients[i] = NULL; - adapter->client_count--; + down(&adapter->list); + for (i = 0; i < I2C_CLIENT_MAX; i++) { + if (client == adapter->clients[i]) { + adapter->clients[i] = NULL; + goto out_unlock; + } + } - DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] unregistered.\n",client->name)); - return 0; + printk(KERN_WARNING + " i2c-core.o: unregister_client [%s] not found\n", + client->name); + res = -ENODEV; + + out_unlock: + up(&adapter->list); + out: + return res; } static int i2c_inc_use_client(struct i2c_client *client) @@ -495,44 +462,12 @@ return 0; } -/* ---------------------------------------------------- - * The /proc functions - * ---------------------------------------------------- - */ - #ifdef CONFIG_PROC_FS - -/* This function generates the output for /proc/bus/i2c */ -int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, - void *private) -{ - int i; - int nr = 0; - /* Note that it is safe to write a `little' beyond len. Yes, really. */ - for (i = 0; (i < I2C_ADAP_MAX) && (nr < len); i++) - if (adapters[i]) { - nr += sprintf(buf+nr, "i2c-%d\t", i); - if (adapters[i]->algo->smbus_xfer) { - if (adapters[i]->algo->master_xfer) - nr += sprintf(buf+nr,"smbus/i2c"); - else - nr += sprintf(buf+nr,"smbus "); - } else if (adapters[i]->algo->master_xfer) - nr += sprintf(buf+nr,"i2c "); - else - nr += sprintf(buf+nr,"dummy "); - nr += sprintf(buf+nr,"\t%-32s\t%-32s\n", - adapters[i]->name, - adapters[i]->algo->name); - } - return nr; -} - /* This function generates the output for /proc/bus/i2c-? */ -ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, - loff_t *ppos) +static ssize_t i2cproc_bus_read(struct file *file, char *buf, + size_t count, loff_t *ppos) { - struct inode * inode = file->f_dentry->d_inode; + struct inode *inode = file->f_dentry->d_inode; char *kbuf; struct i2c_client *client; int i,j,k,order_nr,len=0; @@ -593,31 +528,133 @@ return -ENOENT; } -static int i2cproc_init(void) +static struct file_operations i2cproc_operations = { + .read = i2cproc_bus_read, +}; + +/* This function generates the output for /proc/bus/i2c */ +static int bus_i2c_show(struct seq_file *s, void *p) { + int i; - struct proc_dir_entry *proc_bus_i2c; + down(&core_lists); + for (i = 0; i < I2C_ADAP_MAX; i++) { + struct i2c_adapter *adapter = adapters[i]; + + if (!adapter) + continue; - proc_bus_i2c = create_proc_entry("i2c",0,proc_bus); - if (!proc_bus_i2c) { - printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c"); - return -ENOENT; - } + seq_printf(s, "i2c-%d\t", i); + + if (adapter->algo->smbus_xfer) { + if (adapter->algo->master_xfer) + seq_printf(s, "smbus/i2c"); + else + seq_printf(s, "smbus "); + } else if (adapter->algo->master_xfer) + seq_printf(s ,"i2c "); + else + seq_printf(s, "dummy "); + + seq_printf(s, "\t%-32s\t%-32s\n", + adapter->name, adapter->algo->name); + } + up(&core_lists); - proc_bus_i2c->read_proc = &read_bus_i2c; - proc_bus_i2c->owner = THIS_MODULE; return 0; } -static void __exit i2cproc_cleanup(void) +static int bus_i2c_open(struct inode *inode, struct file *file) { + return single_open(file, bus_i2c_show, NULL); +} + +static struct file_operations bus_i2c_fops = { + .open = bus_i2c_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + }; + +static int i2cproc_register(struct i2c_adapter *adap, int bus) +{ + struct proc_dir_entry *proc_entry; + char name[8]; + + sprintf(name, "i2c-%d", bus); + + proc_entry = create_proc_entry(name, 0, proc_bus); + if (!proc_entry) + goto fail; + + proc_entry->proc_fops = &i2cproc_operations; + proc_entry->owner = adap->owner; + adap->inode = proc_entry->low_ino; + return 0; + fail: + printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n", name); + return -ENOENT; +} + +static void i2cproc_remove(int bus) +{ + char name[8]; + + sprintf(name,"i2c-%d", bus); + remove_proc_entry(name, proc_bus); +} + +static int __init i2cproc_init(void) +{ + struct proc_dir_entry *proc_bus_i2c; + + proc_bus_i2c = create_proc_entry("i2c", 0, proc_bus); + if (!proc_bus_i2c) + goto fail; + proc_bus_i2c->proc_fops = &bus_i2c_fops; + proc_bus_i2c->owner = THIS_MODULE; + return 0; + fail: + printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c"); + return -ENOENT; +} + +static void __exit i2cproc_cleanup(void) +{ remove_proc_entry("i2c",proc_bus); } +#else +static int __init i2cproc_init(void) { return 0; } +static void __exit i2cproc_cleanup(void) { } +#endif /* CONFIG_PROC_FS */ + +/* match always succeeds, as we want the probe() to tell if we really accept this match */ +static int i2c_device_match(struct device *dev, struct device_driver *drv) +{ + return 1; +} + +struct bus_type i2c_bus_type = { + .name = "i2c", + .match = i2c_device_match, +}; + + +static int __init i2c_init(void) +{ + bus_register(&i2c_bus_type); + return i2cproc_init(); +} + +static void __exit i2c_exit(void) +{ + i2cproc_cleanup(); + bus_unregister(&i2c_bus_type); +} -module_init(i2cproc_init); -module_exit(i2cproc_cleanup); -#endif /* def CONFIG_PROC_FS */ +module_init(i2c_init); +module_exit(i2c_exit); /* ---------------------------------------------------- * the functional interface to the i2c busses. @@ -632,9 +669,9 @@ DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n", adap->name,num)); - I2C_LOCK(adap); + down(&adap->bus); ret = adap->algo->master_xfer(adap,msgs,num); - I2C_UNLOCK(adap); + up(&adap->bus); return ret; } else { @@ -659,9 +696,9 @@ DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n", count,client->adapter->name)); - I2C_LOCK(adap); + down(&adap->bus); ret = adap->algo->master_xfer(adap,&msg,1); - I2C_UNLOCK(adap); + up(&adap->bus); /* if everything went ok (i.e. 1 msg transmitted), return #bytes * transmitted, else error code. @@ -689,9 +726,9 @@ DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n", count,client->adapter->name)); - I2C_LOCK(adap); + down(&adap->bus); ret = adap->algo->master_xfer(adap,&msg,1); - I2C_UNLOCK(adap); + up(&adap->bus); DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n", ret, count, client->addr)); @@ -1306,10 +1343,10 @@ } if (adapter->algo->smbus_xfer) { - I2C_LOCK(adapter); + down(&adapter->bus); res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, command,size,data); - I2C_UNLOCK(adapter); + up(&adapter->bus); } else res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, command,size,data); diff -Nru a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c --- a/drivers/i2c/i2c-proc.c Sat Mar 15 18:40:42 2003 +++ b/drivers/i2c/i2c-proc.c Sat Mar 15 18:40:42 2003 @@ -35,8 +35,6 @@ #include #include -static int i2c_create_name(char **name, const char *prefix, - struct i2c_adapter *adapter, int addr); static int i2c_parse_reals(int *nrels, void *buffer, int bufsize, long *results, int magnitude); static int i2c_write_reals(int nrels, void *buffer, size_t *bufsize, @@ -54,15 +52,6 @@ static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX]; -static ctl_table sysctl_table[] = { - {CTL_DEV, "dev", NULL, 0, 0555}, - {0}, - {DEV_SENSORS, "sensors", NULL, 0, 0555}, - {0}, - {0, NULL, NULL, 0, 0555}, - {0} -}; - static ctl_table i2c_proc_dev_sensors[] = { {SENSORS_CHIPS, "chips", NULL, 0, 0644, NULL, &i2c_proc_chips, &i2c_sysctl_chips}, @@ -87,36 +76,40 @@ (for a LM78 chip on the ISA bus at port 0x310), or lm75-i2c-3-4e (for a LM75 chip on the third i2c bus at address 0x4e). name is allocated first. */ -static int i2c_create_name(char **name, const char *prefix, - struct i2c_adapter *adapter, int addr) +static char *generate_name(struct i2c_client *client, const char *prefix) { - char name_buffer[50]; - int id, i, end; - if (i2c_is_isa_adapter(adapter)) + struct i2c_adapter *adapter = client->adapter; + int addr = client->addr; + char name_buffer[50], *name; + + if (i2c_is_isa_adapter(adapter)) { sprintf(name_buffer, "%s-isa-%04x", prefix, addr); - else if (!adapter->algo->smbus_xfer && !adapter->algo->master_xfer) { - /* dummy adapter, generate prefix */ + } else if (adapter->algo->smbus_xfer || adapter->algo->master_xfer) { + int id = i2c_adapter_id(adapter); + if (id < 0) + return ERR_PTR(-ENOENT); + sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr); + } else { /* dummy adapter, generate prefix */ + int end, i; + sprintf(name_buffer, "%s-", prefix); end = strlen(name_buffer); - for(i = 0; i < 32; i++) { - if(adapter->algo->name[i] == ' ') + + for (i = 0; i < 32; i++) { + if (adapter->algo->name[i] == ' ') break; name_buffer[end++] = tolower(adapter->algo->name[i]); } + name_buffer[end] = 0; sprintf(name_buffer + end, "-%04x", addr); - } else { - if ((id = i2c_adapter_id(adapter)) < 0) - return -ENOENT; - sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr); - } - *name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); - if (!*name) { - printk (KERN_WARNING "i2c_create_name: not enough memory\n"); - return -ENOMEM; } - strcpy(*name, name_buffer); - return 0; + + name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL); + if (unlikely(!name)) + return ERR_PTR(-ENOMEM); + strcpy(name, name_buffer); + return name; } /* This rather complex function must be called when you want to add an entry @@ -127,93 +120,80 @@ If any driver wants subdirectories within the newly created directory, this function must be updated! */ int i2c_register_entry(struct i2c_client *client, const char *prefix, - ctl_table * ctl_template) + struct ctl_table *leaf) { - int i, res, len, id; - ctl_table *new_table, *client_tbl, *tbl; - char *name; - struct ctl_table_header *new_header; - - if ((res = i2c_create_name(&name, prefix, client->adapter, - client->addr))) return res; - - for (id = 0; id < SENSORS_ENTRY_MAX; id++) - if (!i2c_entries[id]) { - break; - } - if (id == SENSORS_ENTRY_MAX) { - kfree(name); - return -ENOMEM; - } - - id += 256; - - len = 0; - while (ctl_template[len].procname) - len++; - if (!(new_table = kmalloc(sizeof(sysctl_table) + sizeof(ctl_table) * (len + 1), - GFP_KERNEL))) { - kfree(name); - return -ENOMEM; - } - - memcpy(new_table, sysctl_table, sizeof(sysctl_table)); - tbl = new_table; /* sys/ */ - tbl = tbl->child = tbl + 2; /* dev/ */ - tbl = tbl->child = tbl + 2; /* sensors/ */ - client_tbl = tbl->child = tbl + 2; /* XX-chip-YY-ZZ/ */ - - client_tbl->procname = name; - client_tbl->ctl_name = id; - client_tbl->child = client_tbl + 2; - - /* Next the client sysctls. --km */ - tbl = client_tbl->child; - memcpy(tbl, ctl_template, sizeof(ctl_table) * (len+1)); - for (i = 0; i < len; i++) - tbl[i].extra2 = client; - - if (!(new_header = register_sysctl_table(new_table, 0))) { - printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n"); - kfree(new_table); - kfree(name); - return -EPERM; - } - - i2c_entries[id - 256] = new_header; - - i2c_clients[id - 256] = client; - -#ifdef DEBUG - if (!new_header || !new_header->ctl_table || - !new_header->ctl_table->child || - !new_header->ctl_table->child->child || - !new_header->ctl_table->child->child->de ) { - printk - (KERN_ERR "i2c-proc.o: NULL pointer when trying to install fill_inode fix!\n"); - return id; - } -#endif /* DEBUG */ - client_tbl->de->owner = client->driver->owner; - return id; + struct { struct ctl_table root[2], dev[2], sensors[2]; } *tbl; + struct ctl_table_header *hdr; + struct ctl_table *tmp; + const char *name; + int id; + + name = generate_name(client, prefix); + if (IS_ERR(name)) + return PTR_ERR(name); + + for (id = 0; id < SENSORS_ENTRY_MAX; id++) { + if (!i2c_entries[id]) + goto free_slot; + } + + goto out_free_name; + + free_slot: + tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); + if (unlikely(!tbl)) + goto out_free_name; + memset(tbl, 0, sizeof(*tbl)); + + for (tmp = leaf; tmp->ctl_name; tmp++) + tmp->extra2 = client; + + tbl->sensors->ctl_name = id+256; + tbl->sensors->procname = name; + tbl->sensors->mode = 0555; + tbl->sensors->child = leaf; + + tbl->dev->ctl_name = DEV_SENSORS; + tbl->dev->procname = "sensors"; + tbl->dev->mode = 0555; + tbl->dev->child = tbl->sensors; + + tbl->root->ctl_name = CTL_DEV; + tbl->root->procname = "dev"; + tbl->root->mode = 0555; + tbl->root->child = tbl->dev; + + hdr = register_sysctl_table(tbl->root, 0); + if (unlikely(!hdr)) + goto out_free_tbl; + + i2c_entries[id] = hdr; + i2c_clients[id] = client; + + return (id + 256); /* XXX(hch) why?? */ + + out_free_tbl: + kfree(tbl); + out_free_name: + kfree(name); + return -ENOMEM; } void i2c_deregister_entry(int id) { - ctl_table *table; - char *temp; + id -= 256; - id -= 256; if (i2c_entries[id]) { - table = i2c_entries[id]->ctl_table; - unregister_sysctl_table(i2c_entries[id]); - /* 2-step kfree needed to keep gcc happy about const points */ - (const char *) temp = table[4].procname; - kfree(temp); - kfree(table); - i2c_entries[id] = NULL; - i2c_clients[id] = NULL; + struct ctl_table_header *hdr = i2c_entries[id]; + struct ctl_table *tbl = hdr->ctl_table; + + unregister_sysctl_table(hdr); + kfree(tbl->child->child->procname); + kfree(tbl); /* actually the whole anonymous struct */ } + + i2c_entries[id] = NULL; + i2c_clients[id] = NULL; } static int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp, diff -Nru a/drivers/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Sat Mar 15 18:40:42 2003 +++ b/drivers/ide/Makefile Sat Mar 15 18:40:42 2003 @@ -28,3 +28,4 @@ endif obj-$(CONFIG_BLK_DEV_IDE) += legacy/ ppc/ arm/ +obj-$(CONFIG_BLK_DEV_HD) += legacy/ diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Sat Mar 15 18:40:41 2003 +++ b/drivers/ide/ide-disk.c Sat Mar 15 18:40:41 2003 @@ -38,9 +38,11 @@ * Version 1.15 convert all calls to ide_raw_taskfile * since args will return register content. * Version 1.16 added suspend-resume-checkpower + * Version 1.17 do flush on standy, do flush on ATA < ATA6 + * fix wcache setup. */ -#define IDEDISK_VERSION "1.16" +#define IDEDISK_VERSION "1.17" #undef REALLY_SLOW_IO /* most systems can safely undef this */ @@ -140,7 +142,7 @@ static ide_startstop_t read_intr (ide_drive_t *drive) { ide_hwif_t *hwif = HWIF(drive); - int i = 0, nsect = 0, msect = drive->mult_count; + u32 i = 0, nsect = 0, msect = drive->mult_count; struct request *rq; unsigned long flags; u8 stat; @@ -157,7 +159,7 @@ ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); return ide_started; } - + read_next: rq = HWGROUP(drive)->rq; if (msect) { @@ -203,7 +205,7 @@ ide_hwgroup_t *hwgroup = HWGROUP(drive); ide_hwif_t *hwif = HWIF(drive); struct request *rq = hwgroup->rq; - int i = 0; + u32 i = 0; u8 stat; if (!OK_STAT(stat = hwif->INB(IDE_STATUS_REG), @@ -506,14 +508,10 @@ if (drive->using_dma && !hwif->ide_dma_read(drive)) return ide_started; - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &read_intr, WAIT_CMD, NULL); - command = ((drive->mult_count) ? ((lba48) ? WIN_MULTREAD_EXT : WIN_MULTREAD) : ((lba48) ? WIN_READ_EXT : WIN_READ)); - hwif->OUTB(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &read_intr, WAIT_CMD, NULL); return ide_started; } else if (rq_data_dir(rq) == WRITE) { ide_startstop_t startstop; @@ -628,11 +626,7 @@ static task_ioreg_t get_command (ide_drive_t *drive, int cmd) { - int lba48bit = (drive->id->cfs_enable_2 & 0x0400) ? 1 : 0; - -#if 1 - lba48bit = (drive->addressing == 1) ? 1 : 0; -#endif + int lba48bit = (drive->addressing == 1) ? 1 : 0; if ((cmd == READ) && drive->using_tcq) return lba48bit ? WIN_READDMA_QUEUED_EXT : WIN_READDMA_QUEUED; @@ -1412,32 +1406,6 @@ return call_idedisk_standby(drive, 0); } -#if 0 -static int call_idedisk_checkpower (ide_drive_t *drive, int arg) -{ - ide_task_t args; - u8 ckpw = (arg) ? WIN_CHECKPOWERMODE2 : WIN_CHECKPOWERMODE1; - memset(&args, 0, sizeof(ide_task_t)); - args.tfRegister[IDE_COMMAND_OFFSET] = ckpw; - args.command_type = ide_cmd_type_parser(&args); - ide_raw_taskfile(drive, &args, NULL); -#if 0 -if (errno != EIO || args[0] != 0 || args[1] != 0) - state = "unknown"; -else - state = "sleeping"; -} else { - state = (args[2] == 255) ? "active/idle" : "standby"; -#endif - return 0; -} - -static int do_idedisk_checkpower (ide_drive_t *drive) -{ - return call_idedisk_checkpower(drive, 0); -} -#endif - static int do_idedisk_flushcache (ide_drive_t *drive) { ide_task_t args; @@ -1596,13 +1564,8 @@ drive->doorlocking = 1; } } -#if 1 + (void) probe_lba_addressing(drive, 1); -#else - /* if using 48-bit addressing bump the request size up */ - if (probe_lba_addressing(drive, 1)) - blk_queue_max_sectors(&drive->queue, 2048); -#endif /* Extract geometry if we did not already have one for the drive */ if (!drive->cyl || !drive->head || !drive->sect) { @@ -1675,13 +1638,9 @@ static int idedisk_cleanup (ide_drive_t *drive) { + static int ide_cacheflush_p(ide_drive_t *drive); struct gendisk *g = drive->disk; - - do_idedisk_standby(drive); - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); if (ide_unregister_subdriver(drive)) return 1; del_gendisk(g); @@ -1725,6 +1684,7 @@ drive->usage++; if (drive->removable && drive->usage == 1) { ide_task_t args; + u8 cf; memset(&args, 0, sizeof(ide_task_t)); args.tfRegister[IDE_COMMAND_OFFSET] = WIN_DOORLOCK; args.command_type = ide_cmd_type_parser(&args); @@ -1736,6 +1696,32 @@ */ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; + drive->wcache = 0; + /* Cache enabled ? */ + if (drive->id->csfo & 1) + drive->wcache = 1; + /* Cache command set available ? */ + if (drive->id->cfs_enable_1 & (1<<5)) + drive->wcache = 1; + /* ATA6 cache extended commands */ + cf = drive->id->command_set_2 >> 24; + if((cf & 0xC0) == 0x40 && (cf & 0x30) != 0) + drive->wcache = 1; + } + return 0; +} + +static int ide_cacheflush_p(ide_drive_t *drive) +{ + if(drive->wcache) + { + if (do_idedisk_flushcache(drive)) + { + printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", + drive->name); + return -EIO; + } + return 1; } return 0; } @@ -1752,10 +1738,7 @@ if (drive->doorlocking && ide_raw_taskfile(drive, &args, NULL)) drive->doorlocking = 0; } - if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) - if (do_idedisk_flushcache(drive)) - printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", - drive->name); + ide_cacheflush_p(drive); drive->usage--; return 0; } diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Sat Mar 15 18:40:42 2003 +++ b/drivers/ide/ide-dma.c Sat Mar 15 18:40:42 2003 @@ -664,11 +664,6 @@ if (drive->media != ide_disk) return 0; - /* paranoia check */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - command = (lba48) ? WIN_READDMA_EXT : WIN_READDMA; if (drive->vdma) @@ -680,8 +675,7 @@ } /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); - + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); return HWIF(drive)->ide_dma_count(drive); } @@ -702,11 +696,6 @@ if (drive->media != ide_disk) return 0; - /* paranoia check */ - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); - command = (lba48) ? WIN_WRITEDMA_EXT : WIN_WRITEDMA; if (drive->vdma) command = (lba48) ? WIN_WRITE_EXT: WIN_WRITE; @@ -717,7 +706,7 @@ } /* issue cmd to drive */ - hwif->OUTB(command, IDE_COMMAND_REG); + ide_execute_command(drive, command, &ide_dma_intr, 2*WAIT_CMD, dma_timer_expiry); return HWIF(drive)->ide_dma_count(drive); } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Sat Mar 15 18:40:42 2003 +++ b/drivers/ide/ide-floppy.c Sat Mar 15 18:40:42 2003 @@ -1077,14 +1077,11 @@ } if (test_bit (IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) { - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, + /* Issue the packet command */ + ide_execute_command(drive, WIN_PACKETCMD, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL); - /* Issue the packet command */ - HWIF(drive)->OUTB(WIN_PACKETCMD, IDE_COMMAND_REG); return ide_started; } else { /* Issue the packet command */ diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Sat Mar 15 18:40:44 2003 +++ b/drivers/ide/ide-io.c Sat Mar 15 18:40:44 2003 @@ -358,18 +358,15 @@ * Issue a simple drive command with interrupts. * The drive must be selected beforehand. */ - + void ide_cmd (ide_drive_t *drive, u8 cmd, u8 nsect, ide_handler_t *handler) { ide_hwif_t *hwif = HWIF(drive); - if (HWGROUP(drive)->handler != NULL) - BUG(); - ide_set_handler(drive, handler, WAIT_CMD, NULL); if (IDE_CONTROL_REG) hwif->OUTB(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */ SELECT_MASK(drive,0); hwif->OUTB(nsect,IDE_NSECTOR_REG); - hwif->OUTB(cmd,IDE_COMMAND_REG); + ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); } EXPORT_SYMBOL(ide_cmd); @@ -841,14 +838,14 @@ * happens anyway when any interrupt comes in, IDE or otherwise * -- the kernel masks the IRQ while it is being handled. */ - if (masked_irq && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) disable_irq_nosync(hwif->irq); spin_unlock(&ide_lock); local_irq_enable(); /* allow other IRQs while we start this request */ startstop = start_request(drive, rq); spin_lock_irq(&ide_lock); - if (masked_irq && hwif->irq != masked_irq) + if (hwif->irq != masked_irq) enable_irq(hwif->irq); if (startstop == ide_released) goto queue_next; @@ -864,7 +861,7 @@ */ void do_ide_request(request_queue_t *q) { - ide_do_request(q->queuedata, 0); + ide_do_request(q->queuedata, IDE_NO_IRQ); } /* @@ -1012,7 +1009,7 @@ hwgroup->busy = 0; } } - ide_do_request(hwgroup, 0); + ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); } @@ -1302,7 +1299,7 @@ insert_end = 0; } __elv_add_request(&drive->queue, rq, insert_end, 0); - ide_do_request(hwgroup, 0); + ide_do_request(hwgroup, IDE_NO_IRQ); spin_unlock_irqrestore(&ide_lock, flags); err = 0; diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c --- a/drivers/ide/ide-iops.c Sat Mar 15 18:40:41 2003 +++ b/drivers/ide/ide-iops.c Sat Mar 15 18:40:41 2003 @@ -59,11 +59,11 @@ { } -static void ide_unplugged_outb (u8 addr, unsigned long port) +static void ide_unplugged_outb (u8 val, unsigned long port) { } -static void ide_unplugged_outw (u16 addr, unsigned long port) +static void ide_unplugged_outw (u16 val, unsigned long port) { } @@ -71,7 +71,7 @@ { } -static void ide_unplugged_outl (u32 addr, unsigned long port) +static void ide_unplugged_outl (u32 val, unsigned long port) { } @@ -125,14 +125,14 @@ insl(port, addr, count); } -static void ide_outb (u8 addr, unsigned long port) +static void ide_outb (u8 val, unsigned long port) { - outb(addr, port); + outb(val, port); } -static void ide_outw (u16 addr, unsigned long port) +static void ide_outw (u16 val, unsigned long port) { - outw(addr, port); + outw(val, port); } static void ide_outsw (unsigned long port, void *addr, u32 count) @@ -140,9 +140,9 @@ outsw(port, addr, count); } -static void ide_outl (u32 addr, unsigned long port) +static void ide_outl (u32 val, unsigned long port) { - outl(addr, port); + outl(val, port); } static void ide_outsl (unsigned long port, void *addr, u32 count) diff -Nru a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c --- a/drivers/ide/ide-lib.c Sat Mar 15 18:40:44 2003 +++ b/drivers/ide/ide-lib.c Sat Mar 15 18:40:44 2003 @@ -171,7 +171,7 @@ BUG(); return min(speed, speed_max[mode]); #else /* !CONFIG_BLK_DEV_IDEDMA */ - return min(speed, (u8)XFER_PIO_4); + return min(speed, XFER_PIO_4); #endif /* CONFIG_BLK_DEV_IDEDMA */ } diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Sat Mar 15 18:40:42 2003 +++ b/drivers/ide/ide-probe.c Sat Mar 15 18:40:42 2003 @@ -1292,11 +1292,8 @@ /* we set it back to 1 if all is ok below */ hwif->present = 0; - if (register_blkdev (hwif->major, hwif->name, ide_fops)) { - printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", - hwif->name, hwif->major); + if (register_blkdev(hwif->major, hwif->name)) return 0; - } if (alloc_disks(hwif) < 0) goto out; diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Sat Mar 15 18:40:39 2003 +++ b/drivers/ide/ide-taskfile.c Sat Mar 15 18:40:39 2003 @@ -177,8 +177,7 @@ hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG); if (task->handler != NULL) { - ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL); - hwif->OUTB(taskfile->command, IDE_COMMAND_REG); + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, task->rq); return ide_started; @@ -1880,9 +1879,8 @@ if (task->handler == NULL) return ide_stopped; - ide_set_handler(drive, task->handler, WAIT_WORSTCASE, NULL); /* Issue the command */ - hwif->OUTB(taskfile->command, IDE_COMMAND_REG); + ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL); if (task->prehandler != NULL) return task->prehandler(drive, HWGROUP(drive)->rq); } diff -Nru a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c --- a/drivers/ide/legacy/hd.c Sat Mar 15 18:40:39 2003 +++ b/drivers/ide/legacy/hd.c Sat Mar 15 18:40:39 2003 @@ -708,10 +708,10 @@ static int __init hd_init(void) { int drive; - if (register_blkdev(MAJOR_NR,"hd",&hd_fops)) { - printk("hd: unable to get major %d for hard disk\n",MAJOR_NR); + + if (register_blkdev(MAJOR_NR,"hd")) return -1; - } + blk_init_queue(&hd_queue, do_hd_request, &hd_lock); blk_queue_max_sectors(&hd_queue, 255); init_timer(&device_timer); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Sat Mar 15 18:40:45 2003 +++ b/drivers/ide/pci/amd74xx.c Sat Mar 15 18:40:45 2003 @@ -82,7 +82,7 @@ #include #include -static long amd_base; +static unsigned long amd_base; static struct pci_dev *bmide_dev; extern int (*amd74xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */ @@ -102,7 +102,7 @@ amd_print("----------AMD BusMastering IDE Configuration----------------"); - amd_print("Driver Version: 2.8"); + amd_print("Driver Version: 2.9"); amd_print("South Bridge: %s", bmide_dev->dev.name); pci_read_config_byte(dev, PCI_REVISION_ID, &t); @@ -284,7 +284,7 @@ * and initialize its drive independent registers. */ -unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) +static unsigned int __init init_chipset_amd74xx(struct pci_dev *dev, const char *name) { unsigned char t; unsigned int u; @@ -378,12 +378,12 @@ return 0; } -unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) +static unsigned int __init ata66_amd74xx(ide_hwif_t *hwif) { return ((amd_enabled & amd_80w) >> hwif->channel) & 1; } -void __init init_hwif_amd74xx(ide_hwif_t *hwif) +static void __init init_hwif_amd74xx(ide_hwif_t *hwif) { int i; diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c Sat Mar 15 18:40:39 2003 +++ b/drivers/ide/pci/via82cxxx.c Sat Mar 15 18:40:39 2003 @@ -1,16 +1,6 @@ /* - * $Id: via82cxxx.c,v 3.35-ac2 2002/09/111 Alan Exp $ * - * Copyright (c) 2000-2001 Vojtech Pavlik - * - * Based on the work of: - * Michel Aubry - * Jeff Garzik - * Andre Hedrick - */ - -/* - * Version 3.35 + * Version 3.36 * * VIA IDE driver for Linux. Supported southbridges: * @@ -24,6 +14,10 @@ * Michel Aubry * Jeff Garzik * Andre Hedrick + * + * Documentation: + * Obsolete device documentation publically available from via.com.tw + * Current device documentation available under NDA only */ /* @@ -67,6 +61,7 @@ #define VIA_SET_FIFO 0x040 /* Needs to have FIFO split set */ #define VIA_NO_UNMASK 0x080 /* Doesn't work with IRQ unmasking on */ #define VIA_BAD_ID 0x100 /* Has wrong vendor ID (0x1107) */ +#define VIA_BAD_AST 0x200 /* Don't touch Address Setup Timing */ /* * VIA SouthBridge chips. @@ -82,8 +77,8 @@ #ifdef FUTURE_BRIDGES { "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 }, #endif - { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 }, - { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 }, + { "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, + { "vt8233a", PCI_DEVICE_ID_VIA_8233A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST }, { "vt8233c", PCI_DEVICE_ID_VIA_8233C_0, 0x00, 0x2f, VIA_UDMA_100 }, { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_100 }, @@ -152,7 +147,7 @@ via_print("----------VIA BusMastering IDE Configuration" "----------------"); - via_print("Driver Version: 3.35-ac"); + via_print("Driver Version: 3.36"); via_print("South Bridge: VIA %s", via_config->name); @@ -292,9 +287,11 @@ { u8 t; - pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); - t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); - pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + if (~via_config->flags & VIA_BAD_AST) { + pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); + t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1)); + pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t); + } pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)), ((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1)); diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c --- a/drivers/isdn/hardware/avm/b1pci.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hardware/avm/b1pci.c Sat Mar 15 18:40:39 2003 @@ -343,12 +343,16 @@ static void __devexit b1pci_pci_remove(struct pci_dev *pdev) { +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 avmcard *card = pci_get_drvdata(pdev); if (card->dma) b1pciv4_remove(pdev); else b1pci_remove(pdev); +#else + b1pci_remove(pdev); +#endif } static struct pci_driver b1pci_pci_driver = { diff -Nru a/drivers/isdn/hisax/amd7930.c b/drivers/isdn/hisax/amd7930.c --- a/drivers/isdn/hisax/amd7930.c Sat Mar 15 18:40:41 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,717 +0,0 @@ -/* $Id: amd7930.c,v 1.5.6.4 2001/09/23 22:24:46 kai Exp $ - * - * HiSax ISDN driver - chip specific routines for AMD 7930 - * - * Author Brent Baccala - * Copyright by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * - Existing ISDN HiSax driver provides all the smarts - * - it compiles, runs, talks to an isolated phone switch, connects - * to a Cisco, pings go through - * - AMD 7930 support only (no DBRI yet) - * - no US NI-1 support (may not work on US phone system - untested) - * - periodic packet loss, apparently due to lost interrupts - * - ISDN sometimes freezes, requiring reboot before it will work again - * - * The code is unreliable enough to be consider alpha - * - * This file is (c) under GNU General Public License - * - * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the - * SparcStation 1+. The chip provides microphone and speaker interfaces - * which provide mono-channel audio at 8K samples per second via either - * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an - * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface, - * which performs basic D channel LAPD processing and provides raw - * B channel data. The digital audio channel, the two ISDN B channels, - * and two 64 Kbps channels to the microprocessor are all interconnected - * via a multiplexer. - * - * This driver interfaces to the Linux HiSax ISDN driver, which performs - * all high-level Q.921 and Q.931 ISDN functions. The file is not - * itself a hardware driver; rather it uses functions exported by - * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio), - * allowing the chip to be simultaneously used for both audio and ISDN data. - * The hardware driver does _no_ buffering, but provides several callbacks - * which are called during interrupt service and should therefore run quickly. - * - * D channel transmission is performed by passing the hardware driver the - * address and size of an skb's data area, then waiting for a callback - * to signal successful transmission of the packet. A task is then - * queued to notify the HiSax driver that another packet may be transmitted. - * - * D channel reception is quite simple, mainly because of: - * 1) the slow speed of the D channel - 16 kbps, and - * 2) the presence of an 8- or 32-byte (depending on chip version) FIFO - * to buffer the D channel data on the chip - * Worst case scenario of back-to-back packets with the 8 byte buffer - * at 16 kbps yields an service time of 4 ms - long enough to preclude - * the need for fancy buffering. We queue a background task that copies - * data out of the receive buffer into an skb, and the hardware driver - * simply does nothing until we're done with the receive buffer and - * reset it for a new packet. - * - * B channel processing is more complex, because of: - * 1) the faster speed - 64 kbps, - * 2) the lack of any on-chip buffering (it interrupts for every byte), and - * 3) the lack of any chip support for HDLC encapsulation - * - * The HiSax driver can put each B channel into one of three modes - - * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay), - * and L1_MODE_HDLC (HDLC encapsulation by low-level driver). - * L1_MODE_HDLC is the most common, used for almost all "pure" digital - * data sessions. L1_MODE_TRANS is used for ISDN audio. - * - * HDLC B channel transmission is performed via a large buffer into - * which the skb is copied while performing HDLC bit-stuffing. A CRC - * is computed and attached to the end of the buffer, which is then - * passed to the low-level routines for raw transmission. Once - * transmission is complete, the hardware driver is set to enter HDLC - * idle by successive transmission of mark (all 1) bytes, waiting for - * the ISDN driver to prepare another packet for transmission and - * deliver it. - * - * HDLC B channel reception is performed via an X-byte ring buffer - * divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4. - * As the hardware driver notifies us that each section is full, we - * hand it the next section and schedule a background task to peruse - * the received section, bit-by-bit, with an HDLC decoder. As - * packets are detected, they are copied into a large buffer while - * decoding HDLC bit-stuffing. The ending CRC is verified, and if - * it is correct, we alloc a new skb of the correct length (which we - * now know), copy the packet into it, and hand it to the upper layers. - * Optimization: for large packets, we hand the buffer (which also - * happens to be an skb) directly to the upper layer after an skb_trim, - * and alloc a new large buffer for future packets, thus avoiding a copy. - * Then we return to HDLC processing; state is saved between calls. - * - */ - -#include "hisax.h" -#include "../../sbus/audio/amd7930.h" -#include "isac.h" -#include "isdnl1.h" -#include "rawhdlc.h" -#include - -static const char *amd7930_revision = "$Revision: 1.5.6.4 $"; - -#define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ -#define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into - * (must divide RCV_BUFSIZE) */ - -static void Bchan_fill_fifo(struct BCState *, struct sk_buff *); - -static void -Bchan_xmt_bh(void *data) -{ - struct BCState *bcs = data; - struct sk_buff *skb; - - if (bcs->hw.amd7930.tx_skb != NULL) { - dev_kfree_skb(bcs->hw.amd7930.tx_skb); - bcs->hw.amd7930.tx_skb = NULL; - } - xmit_ready_b(bcs); -} - -static void -Bchan_xmit_callback(struct BCState *bcs) -{ - schedule_work(&bcs->hw.amd7930.xmt_work); -} - -/* B channel transmission: two modes (three, if you count L1_MODE_NULL) - * - * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting - * the packet (i.e. make_raw_hdlc_data). Since this can be a - * time-consuming operation, our completion callback just schedules - * a bottom half to do encapsulation for the next packet. In between, - * the link will just idle - * - * L1_MODE_TRANS - Data goes through, well, transparent. No HDLC encap, - * and we can't just let the link idle, so the "bottom half" actually - * gets called during the top half (it's our callback routine in this case), - * but it's a lot faster now since we don't call make_raw_hdlc_data - */ - -static void -Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - int len; - - if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) { - char tmp[1024]; - char *t = tmp; - - t += sprintf(t, "amd7930_fill_fifo %c cnt %d", - bcs->channel ? 'B' : 'A', skb->len); - if (cs->debug & L1_DEB_HSCX_FIFO) - QuickHex(t, skb->data, skb->len); - debugl1(cs, tmp); - } - - if (bcs->mode == L1_MODE_HDLC) { - len = make_raw_hdlc_data(skb->data, skb->len, - bcs->hw.amd7930.tx_buff, RAW_BUFMAX); - if (len > 0) - amd7930_bxmit(0, bcs->channel, - bcs->hw.amd7930.tx_buff, len, - (void *) &Bchan_xmit_callback, - (void *) bcs); - dev_kfree_skb(skb); - } else if (bcs->mode == L1_MODE_TRANS) { - amd7930_bxmit(0, bcs->channel, - bcs->hw.amd7930.tx_buff, skb->len, - (void *) &Bchan_xmt_bh, - (void *) bcs); - bcs->hw.amd7930.tx_skb = skb; - } else { - dev_kfree_skb(skb); - } -} - -static void -Bchan_mode(struct BCState *bcs, int mode, int bc) -{ - struct IsdnCardState *cs = bcs->cs; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[40]; - sprintf(tmp, "AMD 7930 mode %d bchan %d/%d", - mode, bc, bcs->channel); - debugl1(cs, tmp); - } - bcs->mode = mode; -} - -/* Bchan_l2l1 is the entry point for upper layer routines that want to - * transmit on the B channel. PH_DATA_REQ is a normal packet that - * we either start transmitting (if idle) or queue (if busy). - * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF) - * once the link is idle. After a "pull" callback, the upper layer - * routines can use PH_PULL_IND to send data. - */ - -static void -Bchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct sk_buff *skb = arg; - - switch (pr) { - case (PH_DATA_REQ): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - } else { - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - } - break; - case (PH_PULL_IND): - if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - printk(KERN_WARNING "amd7930: this shouldn't happen\n"); - break; - } - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - Bchan_fill_fifo(st->l1.bcs, skb); - break; - case (PH_PULL_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) { - clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -/* Receiver callback and bottom half - decodes HDLC at leisure (if - * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue. If - * a large packet is received, stick rv_skb (the buffer that the - * packet has been decoded into) on the receive queue and alloc a new - * (large) skb to act as buffer for future receives. If a small - * packet is received, leave rv_skb alone, alloc a new skb of the - * correct size, and copy the packet into it - */ - -static void -Bchan_recv_callback(struct BCState *bcs) -{ - struct amd7930_hw *hw = &bcs->hw.amd7930; - - hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_in %= RCV_BUFSIZE; - - if (hw->rv_buff_in != hw->rv_buff_out) { - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, (void *) bcs); - } - - schedule_work(&hw->rcv_work); -} - -static void -Bchan_rcv_bh(void *data) -{ - struct BCState *bcs = data; - struct IsdnCardState *cs = bcs->cs; - struct amd7930_hw *hw = &bcs->hw.amd7930; - struct sk_buff *skb; - int len; - - if (cs->debug & L1_DEB_HSCX) { - char tmp[1024]; - - sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)", - hw->rv_buff_in, hw->rv_buff_out); - debugl1(cs, tmp); - QuickHex(tmp, hw->rv_buff + hw->rv_buff_out, - RCV_BUFSIZE/RCV_BUFBLKS); - debugl1(cs, tmp); - } - - do { - if (bcs->mode == L1_MODE_HDLC) { - while ((len = read_raw_hdlc_data(hw->hdlc_state, - hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS, - hw->rv_skb->tail, HSCX_BUFMAX))) { - if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) { - char tmp[1024]; - char *t = tmp; - - t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len); - QuickHex(t, hw->rv_skb->tail, len); - debugl1(cs, tmp); - } - - if (len > HSCX_BUFMAX/2) { - /* Large packet received */ - - if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING "amd7930: receive out of memory"); - } else { - skb_put(hw->rv_skb, len); - skb_queue_tail(&bcs->rqueue, hw->rv_skb); - hw->rv_skb = skb; - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } else if (len > 0) { - /* Small packet received */ - - if (!(skb = dev_alloc_skb(len))) { - printk(KERN_WARNING "amd7930: receive out of memory\n"); - } else { - memcpy(skb_put(skb, len), hw->rv_skb->tail, len); - skb_queue_tail(&bcs->rqueue, skb); - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } else { - /* Reception Error */ - /* printk("amd7930: B channel receive error\n"); */ - } - } - } else if (bcs->mode == L1_MODE_TRANS) { - if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) { - printk(KERN_WARNING "amd7930: receive out of memory\n"); - } else { - memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS), - hw->rv_buff + hw->rv_buff_out, - RCV_BUFSIZE/RCV_BUFBLKS); - skb_queue_tail(&bcs->rqueue, skb); - bcs->event |= 1 << B_RCVBUFREADY; - schedule_work(&bcs->work); - } - } - - if (hw->rv_buff_in == hw->rv_buff_out) { - /* Buffer was filled up - need to restart receiver */ - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, - RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, - (void *) bcs); - } - - hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS; - hw->rv_buff_out %= RCV_BUFSIZE; - - } while (hw->rv_buff_in != hw->rv_buff_out); -} - -static void -Bchan_close(struct BCState *bcs) -{ - struct sk_buff *skb; - - Bchan_mode(bcs, 0, 0); - amd7930_bclose(0, bcs->channel); - - if (test_bit(BC_FLG_INIT, &bcs->Flag)) { - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - } - test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); -} - -static int -Bchan_open(struct BCState *bcs) -{ - struct amd7930_hw *hw = &bcs->hw.amd7930; - - if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - } - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - - amd7930_bopen(0, bcs->channel, 0xff); - hw->rv_buff_in = 0; - hw->rv_buff_out = 0; - hw->tx_skb = NULL; - init_hdlc_state(hw->hdlc_state, 0); - amd7930_brecv(0, bcs->channel, - hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS, - (void *) &Bchan_recv_callback, (void *) bcs); - - bcs->event = 0; - bcs->tx_cnt = 0; - return (0); -} - -static void -Bchan_init(struct BCState *bcs) -{ - if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.tx_buff\n"); - return; - } - if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.rv_buff\n"); - return; - } - if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.rv_skb\n"); - return; - } - if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state), - GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for amd7930.hdlc_state\n"); - return; - } - - INIT_WORK(&bcs->hw.amd7930.rcv_work, &Bchan_rcv_bh, bcs); - INIT_WORK(&bcs->hw.amd7930.xmt_work, &Bchan_xmt_bh, bcs); -} - -static void -Bchan_manl1(struct PStack *st, int pr, - void *arg) -{ - switch (pr) { - case (PH_ACTIVATE_REQ): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc); - st->l1.l1man(st, PH_ACTIVATE_CNF, NULL); - break; - case (PH_DEACTIVATE_REQ): - if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) - Bchan_mode(st->l1.bcs, 0, 0); - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - break; - } -} - -int -setstack_amd7930(struct PStack *st, struct BCState *bcs) -{ - if (Bchan_open(bcs)) - return (-1); - st->l1.bcs = bcs; - st->l2.l2l1 = Bchan_l2l1; - st->ma.manl1 = Bchan_manl1; - setstack_manager(st); - bcs->st = st; - return (0); -} - - -static void -amd7930_drecv_callback(void *arg, int error, unsigned int count) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct work_struct task; - struct sk_buff *skb; - - /* NOTE: This function is called directly from an interrupt handler */ - - if (1) { - if (!(skb = alloc_skb(count, GFP_ATOMIC))) - printk(KERN_WARNING "HiSax: D receive out of memory\n"); - else { - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - } - - INIT_WORK(&task, (void *) DChannel_proc_rcv, (void *) cs); - schedule_work(&task); - } - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "amd7930 Drecv cnt %d", count); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->rcvbuf, count); - debugl1(cs, tmp); - } - - amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &amd7930_drecv_callback, cs); -} - -static void -amd7930_dxmit_callback(void *arg, int error) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) arg; - static struct work_struct task; - - /* NOTE: This function is called directly from an interrupt handler */ - - /* may wish to do retransmission here, if error indicates collision */ - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char tmp[128]; - char *t = tmp; - - t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len); - if (error) t += sprintf(t, " ERR %x", error); - QuickHex(t, cs->tx_skb->data, cs->tx_skb->len); - debugl1(cs, tmp); - } - - cs->tx_skb = NULL; - - INIT_WORK(&task, (void *) DChannel_proc_xmt, (void *) cs); - schedule_work(&task); -} - -static void -amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg) -{ - struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; - struct sk_buff *skb = arg; - char str[64]; - - switch (pr) { - case (PH_DATA_REQ): - if (cs->tx_skb) { - skb_queue_tail(&cs->sq, skb); -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA Queued", 0); -#endif - } else { - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { - /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data+4, skb->len-4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - amd7930_dxmit(0, skb->data, skb->len, - &amd7930_dxmit_callback, cs); - } - break; - case (PH_PULL_IND): - if (cs->tx_skb) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); - skb_queue_tail(&cs->sq, skb); - break; - } - if ((cs->dlogflag) && (!(skb->data[2] & 1))) { /* I-FRAME */ - LogFrame(cs, skb->data, skb->len); - sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei); - dlogframe(cs, skb->data + 4, skb->len - 4, - str); - } - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len, - &amd7930_dxmit_callback, cs); - break; - case (PH_PULL_REQ): -#ifdef L2FRAME_DEBUG /* psa */ - if (cs->debug & L1_DEB_LAPD) - debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - if (!cs->tx_skb) { - test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l1.l1l2(st, PH_PULL_CNF, NULL); - } else - test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - break; - } -} - -int -setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs) -{ - st->l2.l2l1 = amd7930_Dchan_l2l1; - if (! cs->rcvbuf) { - printk("setDstack_amd7930: No cs->rcvbuf!\n"); - } else { - amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN, - &amd7930_drecv_callback, cs); - } - return (0); -} - -static void -manl1_msg(struct IsdnCardState *cs, int msg, void *arg) { - struct PStack *st; - - st = cs->stlist; - while (st) { - st->ma.manl1(st, msg, arg); - st = st->next; - } -} - -static void -amd7930_new_ph(struct IsdnCardState *cs) -{ - switch (amd7930_get_liu_state(0)) { - case 3: - manl1_msg(cs, PH_POWERUP_CNF, NULL); - break; - - case 7: - manl1_msg(cs, PH_I4_P8_IND, NULL); - break; - - case 8: - manl1_msg(cs, PH_RSYNC_IND, NULL); - break; - } -} - -/* amd7930 LIU state change callback */ - -static void -amd7930_liu_callback(struct IsdnCardState *cs) -{ - static struct work_struct task; - - if (!cs) - return; - - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0)); - debugl1(cs, tmp); - } - - INIT_WORK(&task, (void *) &amd7930_new_ph, (void *) cs); - schedule_work(&task); -} - -void -amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg) -{ - u8 val; - char tmp[32]; - - if (cs->debug & L1_DEB_ISAC) { - char tmp[32]; - sprintf(tmp, "amd7930_l1cmd msg %x", msg); - debugl1(cs, tmp); - } - - switch(msg) { - case PH_RESET_REQ: - if (amd7930_get_liu_state(0) <= 3) - amd7930_liu_activate(0,0); - else - amd7930_liu_deactivate(0); - break; - case PH_ENABLE_REQ: - break; - case PH_INFO3_REQ: - amd7930_liu_activate(0,0); - break; - case PH_TESTLOOP_REQ: - break; - default: - if (cs->debug & L1_DEB_WARN) { - sprintf(tmp, "amd7930_l1cmd unknown %4x", msg); - debugl1(cs, tmp); - } - break; - } -} - -static void init_amd7930(struct IsdnCardState *cs) -{ - Bchan_init(&cs->bcs[0]); - Bchan_init(&cs->bcs[1]); - cs->bcs[0].BC_SetStack = setstack_amd7930; - cs->bcs[1].BC_SetStack = setstack_amd7930; - cs->bcs[0].BC_Close = Bchan_close; - cs->bcs[1].BC_Close = Bchan_close; - Bchan_mode(cs->bcs, 0, 0); - Bchan_mode(cs->bcs + 1, 0, 0); -} - -static int -amd7930_init(struct IsdnCardState *cs) -{ - cs->l1cmd = amd7930_l1cmd; - amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs); - init_amd7930(cs); - return 0; -} - -static struct card_ops amd7930_ops = { - .init = amd7930_init, -}; - -int __init -setup_amd7930(struct IsdnCard *card) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, amd7930_revision); - printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp)); - - cs->irq = amd7930_get_irqnum(0); - if (cs->irq == 0) - return 0; - - cs->card_ops = &amd7930_ops; - return 1; -} diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Sat Mar 15 18:40:45 2003 +++ b/drivers/isdn/hisax/asuscom.c Sat Mar 15 18:40:45 2003 @@ -231,6 +231,51 @@ .irq_func = ipac_irq, }; +static int __init +asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + u8 val; + + printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + + cs->hw.asus.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn")) + goto err; + + rc = -ENODEV; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; + val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); + if ((val == 1) || (val == 2)) { + cs->subtyp = ASUS_IPAC; + cs->card_ops = &asuscom_ipac_ops; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + } else { + cs->subtyp = ASUS_ISACHSCX; + cs->card_ops = &asuscom_ops; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; + cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; + cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + } + printk(KERN_INFO "ISDNLink: resetting card\n"); + cs->card_ops->reset(cs); + return 0; + + err: + hisax_release_resources(cs); + return rc; +} + #ifdef __ISAPNP__ static struct isapnp_device_id asus_ids[] __initdata = { { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688), @@ -255,9 +300,6 @@ int __init setup_asuscom(struct IsdnCard *card) { - int bytecnt; - struct IsdnCardState *cs = card->cs; - u8 val; char tmp[64]; strcpy(tmp, Asuscom_revision); @@ -310,36 +352,7 @@ } } #endif - bytecnt = 8; - cs->hw.asus.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) - goto err; - printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", - cs->hw.asus.cfg_reg, cs->irq); - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; - val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); - if ((val == 1) || (val == 2)) { - cs->subtyp = ASUS_IPAC; - cs->card_ops = &asuscom_ipac_ops; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->subtyp = ASUS_ISACHSCX; - cs->card_ops = &asuscom_ops; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; - cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; - cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - printk(KERN_INFO "ISDNLink: resetting card\n"); - cs->card_ops->reset(cs); + if (asuscom_probe(card->cs, card) < 0) + return 0; return 1; - err: - hisax_release_resources(cs); - return 0; } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hisax/avm_a1.c Sat Mar 15 18:40:39 2003 @@ -160,16 +160,16 @@ .irq_func = avm_a1_interrupt, }; -int __init -setup_avm_a1(struct IsdnCard *card) +static int __init +avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card) { + int rc; u8 val; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + rc = -EBUSY; cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); if (!cs->hw.avm.cfg_reg) goto err; cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); @@ -216,23 +216,24 @@ printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg, val); - printk(KERN_INFO - "HiSax: %s config irq:%d cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.avm.cfg_reg); - printk(KERN_INFO - "HiSax: isac:0x%X/0x%X\n", - cs->hw.avm.isac + 32, cs->hw.avm.isacfifo); - printk(KERN_INFO - "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n", - cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0], - cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]); - cs->card_ops = &avm_a1_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return rc; +} + +int __init +setup_avm_a1(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + + if (avm_a1_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Sat Mar 15 18:40:45 2003 +++ b/drivers/isdn/hisax/avm_a1p.c Sat Mar 15 18:40:45 2003 @@ -215,20 +215,13 @@ .irq_func = avm_a1p_interrupt, }; -int __devinit -setup_avm_a1_pcmcia(struct IsdnCard *card) +static int __init +avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card) { u8 model, vers; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", - HiSax_getrev(tmp)); - cs->hw.avm.cfg_reg = card->para[1]; cs->irq = card->para[0]; - + cs->hw.avm.cfg_reg = card->para[1]; outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); @@ -244,11 +237,26 @@ vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", - cs->hw.avm.cfg_reg, cs->irq, model, vers); + cs->hw.avm.cfg_reg, cs->irq, model, vers); cs->card_ops = &avm_a1p_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return 0; + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __devinit +setup_avm_a1_pcmcia(struct IsdnCard *card) +{ + char tmp[64]; + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", + HiSax_getrev(tmp)); + if (avm_a1p_probe(card->cs, card)) + return 0; return 1; } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Sat Mar 15 18:40:41 2003 +++ b/drivers/isdn/hisax/avm_pci.c Sat Mar 15 18:40:41 2003 @@ -497,7 +497,7 @@ .close = close_hdlcstate, }; -void __init +static void __init inithdlc(struct IsdnCardState *cs) { u_int val; @@ -596,6 +596,82 @@ .irq_func = avm_pcipnp_interrupt, }; +static int __init +avm_pcipnp_hw_init(struct IsdnCardState *cs) +{ + cs->bc_hw_ops = &hdlc_hw_ops; + cs->bc_l1_ops = &hdlc_l1_ops; + cs->card_ops = &avm_pci_ops; + avm_pcipnp_reset(cs); + return isac_setup(cs, &isac_ops); +} + +static int __init +avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + int rc; + u32 val; + + printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n", + pci_resource_start(pdev, 1), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = AVM_FRITZ_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI")) + goto err; + + val = inl(cs->hw.avm.cfg_reg); + printk(KERN_INFO "AVM PCI: stat %#x\n", val); + printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", + val & 0xff, (val>>8) & 0xff); + + if (avm_pcipnp_hw_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return rc; +} + +static int __init +avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + u8 val, ver; + + printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n", + card->para[1], card->para[0]); + + cs->subtyp = AVM_FRITZ_PNP; + cs->irq = card->para[0]; + cs->hw.avm.cfg_reg = card->para[1]; + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP")) + goto err; + + val = inb(cs->hw.avm.cfg_reg); + ver = inb(cs->hw.avm.cfg_reg + 1); + printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); + + if (avm_pcipnp_hw_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return rc; +} + static struct pci_dev *dev_avm __initdata = NULL; #ifdef __ISAPNP__ static struct pnp_card *card_avm __initdata = NULL; @@ -605,17 +681,15 @@ int __init setup_avm_pcipnp(struct IsdnCard *card) { - u_int val, ver; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); if (card->para[1]) { /* old manual method */ - cs->hw.avm.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - cs->subtyp = AVM_FRITZ_PNP; + if (avm_pnp_probe(card->cs, card)) + return 0; + return 1; } else { #ifdef __ISAPNP__ if (isapnp_present()) { @@ -647,69 +721,24 @@ pnp_device_detach(pnp_avm); return(0); } - cs->hw.avm.cfg_reg = pnp_port_start(pnp_avm, 0); - cs->irq = pnp_irq(pnp_avm, 0); - cs->subtyp = AVM_FRITZ_PNP; - goto ready; + card->para[1] = pnp_port_start(pnp_avm, 0); + card->para[0] = pnp_irq(pnp_avm, 0); + if (avm_pnp_probe(card->cs, card)) + return 0; + return 1; } } - } else { - printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } #endif #if CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { - cs->irq = dev_avm->irq; - if (!cs->irq) { - printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); - return(0); - } - if (pci_enable_device(dev_avm)) - return(0); - cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); - if (!cs->hw.avm.cfg_reg) { - printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = AVM_FRITZ_PCI; - } else { - printk(KERN_WARNING "FritzPCI: No PCI card found\n"); - return(0); + if (avm_pci_probe(card->cs, dev_avm)) + return 0; + return 1; } - cs->irq_flags |= SA_SHIRQ; #endif /* CONFIG_PCI */ } -ready: - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, - cs->subtyp == AVM_FRITZ_PCI ? "avm PCI" : "avm PnP")) - goto err; - - switch (cs->subtyp) { - case AVM_FRITZ_PCI: - val = inl(cs->hw.avm.cfg_reg); - printk(KERN_INFO "AVM PCI: stat %#x\n", val); - printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", - val & 0xff, (val>>8) & 0xff); - break; - case AVM_FRITZ_PNP: - val = inb(cs->hw.avm.cfg_reg); - ver = inb(cs->hw.avm.cfg_reg + 1); - printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); - avm_pcipnp_reset(cs); - break; - } - printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", - (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", - cs->irq, cs->hw.avm.cfg_reg); - - cs->bc_hw_ops = &hdlc_hw_ops; - cs->bc_l1_ops = &hdlc_l1_ops; - cs->card_ops = &avm_pci_ops; - isac_setup(cs, &isac_ops); - return 1; - err: - hisax_release_resources(cs); + printk(KERN_WARNING "FritzPCI: No card found\n"); return 0; } diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Sat Mar 15 18:40:41 2003 +++ b/drivers/isdn/hisax/bkm_a4t.c Sat Mar 15 18:40:41 2003 @@ -21,11 +21,11 @@ #include "bkm_ax.h" extern const char *CardType[]; +// FIXME needs per card lock static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED; const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $"; - static inline u8 readreg(unsigned int ale, unsigned long adr, u8 off) { @@ -249,15 +249,57 @@ .irq_func = bkm_interrupt, }; +static int __init +bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + I20_REGISTER_FILE *pI20_Regs; + int rc; + + printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n", + pci_resource_start(pdev, 0), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); + + cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T"); + if (!cs->hw.ax.base) + goto err; + + /* Check suspicious address */ + // FIXME needs to use read[bl] + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { + printk(KERN_WARNING "HiSax: address %lx suspicious\n", + cs->hw.ax.base); + goto err; + } + cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.isac_ale = GCS_1; + cs->hw.ax.jade_ale = GCS_3; + + reset_bkm(cs); + cs->card_ops = &bkm_a4t_ops; + isac_setup(cs, &isac_ops); + jade_setup(cs, &jade_ops); + return 0; + + err: + hisax_release_resources(cs); + return rc; +} + static struct pci_dev *dev_a4t __initdata = NULL; int __init setup_bkm_a4t(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; - u_int pci_memaddr = 0, found = 0; - I20_REGISTER_FILE *pI20_Regs; strcpy(tmp, bkm_a4t_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); @@ -268,49 +310,13 @@ sub_vendor = dev_a4t->subsystem_vendor; sub_sys = dev_a4t->subsystem_device; - if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { - if (pci_enable_device(dev_a4t)) - return(0); - found = 1; - pci_memaddr = pci_resource_start(dev_a4t, 0); - cs->irq = dev_a4t->irq; - break; + if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && + sub_vendor == PCI_VENDOR_ID_BERKOM) { + if (bkm_a4t_probe(card->cs, dev_a4t)) + return 0; + return 1; } } - if (!found) { - printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); - return (0); - } - if (!cs->irq) { /* IRQ range check ?? */ - printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); - return (0); - } - cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs,pci_memaddr, 4096, "Telekom A4T"); - if (!cs->hw.ax.base) { - printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); - return (0); - } - - /* Check suspecious address */ - pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { - printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", - CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); - hisax_release_resources(cs); - return (0); - } - cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.isac_ale = GCS_1; - cs->hw.ax.jade_ale = GCS_3; - - printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", - CardType[card->typ], cs->hw.ax.base, cs->irq); - - reset_bkm(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &bkm_a4t_ops; - isac_setup(cs, &isac_ops); - jade_setup(cs, &jade_ops); - return 1; + printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); + return 0; } diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/config.c Sat Mar 15 18:40:44 2003 @@ -490,125 +490,36 @@ __setup("hisax=", HiSax_setup); #endif /* MODULES */ -#if CARD_TELES0 extern int setup_teles0(struct IsdnCard *card); -#endif - -#if CARD_TELES3 extern int setup_teles3(struct IsdnCard *card); -#endif - -#if CARD_S0BOX extern int setup_s0box(struct IsdnCard *card); -#endif - -#if CARD_TELESPCI extern int setup_telespci(struct IsdnCard *card); -#endif - -#if CARD_AVM_A1 extern int setup_avm_a1(struct IsdnCard *card); -#endif - -#if CARD_AVM_A1_PCMCIA extern int setup_avm_a1_pcmcia(struct IsdnCard *card); -#endif - -#if CARD_FRITZPCI extern int setup_avm_pcipnp(struct IsdnCard *card); -#endif - -#if CARD_ELSA extern int setup_elsa(struct IsdnCard *card); -#endif - -#if CARD_IX1MICROR2 extern int setup_ix1micro(struct IsdnCard *card); -#endif - -#if CARD_DIEHLDIVA extern int setup_diva(struct IsdnCard *card); -#endif - -#if CARD_ASUSCOM extern int setup_asuscom(struct IsdnCard *card); -#endif - -#if CARD_TELEINT extern int setup_TeleInt(struct IsdnCard *card); -#endif - -#if CARD_SEDLBAUER extern int setup_sedlbauer(struct IsdnCard *card); -#endif - -#if CARD_SPORTSTER extern int setup_sportster(struct IsdnCard *card); -#endif - -#if CARD_MIC extern int setup_mic(struct IsdnCard *card); -#endif - -#if CARD_NETJET_S extern int setup_netjet_s(struct IsdnCard *card); -#endif - -#if CARD_HFCS extern int setup_hfcs(struct IsdnCard *card); -#endif - -#if CARD_HFC_PCI extern int setup_hfcpci(struct IsdnCard *card); -#endif - -#if CARD_HFC_SX extern int setup_hfcsx(struct IsdnCard *card); -#endif - -#if CARD_AMD7930 extern int setup_amd7930(struct IsdnCard *card); -#endif - -#if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); -#endif - -#if CARD_ISURF extern int setup_isurf(struct IsdnCard *card); -#endif - -#if CARD_HSTSAPHIR extern int setup_saphir(struct IsdnCard *card); -#endif - -#if CARD_TESTEMU extern int setup_testemu(struct IsdnCard *card); -#endif - -#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); -#endif - -#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); -#endif - -#if CARD_GAZEL extern int setup_gazel(struct IsdnCard *card); -#endif - -#if CARD_W6692 extern int setup_w6692(struct IsdnCard *card); -#endif - -#if CARD_NETJET_U extern int setup_netjet_u(struct IsdnCard *card); -#endif - -#if CARD_FN_ENTERNOW_PCI extern int setup_enternow_pci(struct IsdnCard *card); -#endif /* * Find card with given driverId @@ -703,16 +614,16 @@ return 8; } -static u8 tmpbuf[HISAX_STATUS_BUFSIZE]; +static char tmpbuf[HISAX_STATUS_BUFSIZE]; -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args) { /* if head == NULL the fmt contains the full info */ unsigned long flags; int count, i; - u8 *p; + char *p; isdn_ctrl ic; int len; @@ -727,7 +638,7 @@ len = p - tmpbuf; p = tmpbuf; } else { - p = fmt; + p = (char *) fmt; len = strlen(fmt); } if (!cs) { @@ -814,12 +725,6 @@ ic.command = ISDN_STAT_UNLOAD; ic.driver = cs->myid; cs->iif.statcallb(&ic); - if (cs->status_buf) - kfree(cs->status_buf); - cs->status_read = NULL; - cs->status_write = NULL; - cs->status_end = NULL; - kfree(cs->dlog); } static void closecard(int cardnr) @@ -893,59 +798,97 @@ return 3; } +static struct IsdnCardState * +alloc_IsdnCardState(void) +{ + struct IsdnCardState *cs; + + cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME + if (!cs) + goto err; + + memset(cs, 0, sizeof(*cs)); + + cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC); + if (!cs->dlog) + goto err_cs; + + cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC); + if (!cs->status_buf) + goto err_dlog; + + cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC); + if (!cs->rcvbuf) + goto err_status_buf; + + cs->chanlimit = 2; /* maximum B-channel number */ + cs->debug = L1_DEB_WARN; + cs->irq_flags = I4L_IRQ_FLAG; + cs->stlist = NULL; + cs->status_read = cs->status_buf; + cs->status_write = cs->status_buf; + cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; + cs->rcvidx = 0; + cs->tx_skb = NULL; + cs->tx_cnt = 0; + cs->event = 0; + + skb_queue_head_init(&cs->rq); + skb_queue_head_init(&cs->sq); + + spin_lock_init(&cs->lock); + resources_init(&cs->rs); + return cs; + + err_status_buf: + kfree(cs->status_buf); + err_dlog: + kfree(cs->dlog); + err_cs: + kfree(cs); + err: + return NULL; +} + +static void +free_IsdnCardState(struct IsdnCardState *cs) +{ + kfree(cs->rcvbuf); + kfree(cs->status_buf); + kfree(cs->dlog); + kfree(cs); +} + static int __devinit checkcard(int cardnr, char *id, int *busy_flag) { int ret = 0; struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + cs = alloc_IsdnCardState(); if (!cs) { printk(KERN_WARNING "HiSax: No memory for IsdnCardState(card %d)\n", cardnr + 1); goto out; } - memset(cs, 0, sizeof(struct IsdnCardState)); card->cs = cs; - cs->chanlimit = 2; /* maximum B-channel number */ - cs->logecho = 0; /* No echo logging */ - cs->cardnr = cardnr; - cs->debug = L1_DEB_WARN; - cs->HW_Flags = 0; - cs->busy_flag = busy_flag; - cs->irq_flags = I4L_IRQ_FLAG; #if TEI_PER_CARD if (card->protocol == ISDN_PTYPE_NI1) test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); #else test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); #endif + cs->cardnr = cardnr; cs->protocol = card->protocol; + cs->typ = card->typ; + cs->busy_flag = busy_flag; if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { printk(KERN_WARNING "HiSax: Card Type %d out of range\n", card->typ); goto outf_cs; } - if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for dlog(card %d)\n", cardnr + 1); - goto outf_cs; - } - if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { - printk(KERN_WARNING - "HiSax: No memory for status_buf(card %d)\n", - cardnr + 1); - goto outf_dlog; - } - cs->stlist = NULL; - cs->status_read = cs->status_buf; - cs->status_write = cs->status_buf; - cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; - cs->typ = card->typ; - spin_lock_init(&cs->lock); - resources_init(&cs->rs); SET_MODULE_OWNER(&cs->iif); strcpy(cs->iif.id, id); cs->iif.channels = 2; @@ -982,13 +925,13 @@ (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : "NONE", cs->iif.id, cs->myid); switch (card->typ) { -#if CARD_TELES0 +#ifdef CONFIG_HISAX_16_0 case ISDN_CTYPE_16_0: case ISDN_CTYPE_8_0: ret = setup_teles0(card); break; #endif -#if CARD_TELES3 +#ifdef CONFIG_HISAX_16_3 case ISDN_CTYPE_16_3: case ISDN_CTYPE_PNP: case ISDN_CTYPE_TELESPCMCIA: @@ -996,32 +939,32 @@ ret = setup_teles3(card); break; #endif -#if CARD_S0BOX +#ifdef CONFIG_HISAX_S0BOX case ISDN_CTYPE_S0BOX: ret = setup_s0box(card); break; #endif -#if CARD_TELESPCI +#ifdef CONFIG_HISAX_TELESPCI case ISDN_CTYPE_TELESPCI: ret = setup_telespci(card); break; #endif -#if CARD_AVM_A1 +#ifdef CONFIG_HISAX_AVM_A1 case ISDN_CTYPE_A1: ret = setup_avm_a1(card); break; #endif -#if CARD_AVM_A1_PCMCIA +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA case ISDN_CTYPE_A1_PCMCIA: ret = setup_avm_a1_pcmcia(card); break; #endif -#if CARD_FRITZPCI +#ifdef CONFIG_HISAX_FRITZPCI case ISDN_CTYPE_FRITZPCI: ret = setup_avm_pcipnp(card); break; #endif -#if CARD_ELSA +#ifdef CONFIG_HISAX_ELSA case ISDN_CTYPE_ELSA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: @@ -1029,115 +972,115 @@ ret = setup_elsa(card); break; #endif -#if CARD_IX1MICROR2 +#ifdef CONFIG_HISAX_IX1MICROR2 case ISDN_CTYPE_IX1MICROR2: ret = setup_ix1micro(card); break; #endif -#if CARD_DIEHLDIVA +#ifdef CONFIG_HISAX_DIEHLDIVA case ISDN_CTYPE_DIEHLDIVA: ret = setup_diva(card); break; #endif -#if CARD_ASUSCOM +#ifdef CONFIG_HISAX_ASUSCOM case ISDN_CTYPE_ASUSCOM: ret = setup_asuscom(card); break; #endif -#if CARD_TELEINT +#ifdef CONFIG_HISAX_TELEINT case ISDN_CTYPE_TELEINT: ret = setup_TeleInt(card); break; #endif -#if CARD_SEDLBAUER +#ifdef CONFIG_HISAX_SEDLBAUER case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: case ISDN_CTYPE_SEDLBAUER_FAX: ret = setup_sedlbauer(card); break; #endif -#if CARD_SPORTSTER +#ifdef CONFIG_HISAX_SPORTSTER case ISDN_CTYPE_SPORTSTER: ret = setup_sportster(card); break; #endif -#if CARD_MIC +#ifdef CONFIG_HISAX_MIC case ISDN_CTYPE_MIC: ret = setup_mic(card); break; #endif -#if CARD_NETJET_S +#ifdef CONFIG_HISAX_NETJET case ISDN_CTYPE_NETJET_S: ret = setup_netjet_s(card); break; #endif -#if CARD_HFCS +#ifdef CONFIG_HISAX_HFCS case ISDN_CTYPE_TELES3C: case ISDN_CTYPE_ACERP10: ret = setup_hfcs(card); break; #endif -#if CARD_HFC_PCI +#ifdef CONFIG_HISAX_HFC_PCI case ISDN_CTYPE_HFC_PCI: ret = setup_hfcpci(card); break; #endif -#if CARD_HFC_SX +#ifdef CONFIG_HISAX_HFC_SX case ISDN_CTYPE_HFC_SX: ret = setup_hfcsx(card); break; #endif -#if CARD_NICCY +#ifdef CONFIG_HISAX_NICCY case ISDN_CTYPE_NICCY: ret = setup_niccy(card); break; #endif -#if CARD_AMD7930 +#ifdef CONFIG_HISAX_AMD7930 case ISDN_CTYPE_AMD7930: ret = setup_amd7930(card); break; #endif -#if CARD_ISURF +#ifdef CONFIG_HISAX_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); break; #endif -#if CARD_HSTSAPHIR +#ifdef CONFIG_HISAX_HSTSAPHIR case ISDN_CTYPE_HSTSAPHIR: ret = setup_saphir(card); break; #endif -#if CARD_TESTEMU +#ifdef CONFIG_HISAX_TESTEMU case ISDN_CTYPE_TESTEMU: ret = setup_testemu(card); break; #endif -#if CARD_BKM_A4T +#ifdef CONFIG_HISAX_BKM_A4T case ISDN_CTYPE_BKM_A4T: ret = setup_bkm_a4t(card); break; #endif -#if CARD_SCT_QUADRO +#ifdef CONFIG_HISAX_SCT_QUADRO case ISDN_CTYPE_SCT_QUADRO: ret = setup_sct_quadro(card); break; #endif -#if CARD_GAZEL +#ifdef CONFIG_HISAX_GAZEL case ISDN_CTYPE_GAZEL: ret = setup_gazel(card); break; #endif -#if CARD_W6692 +#ifdef CONFIG_HISAX_W6692 case ISDN_CTYPE_W6692: ret = setup_w6692(card); break; #endif -#if CARD_NETJET_U +#ifdef CONFIG_HISAX_NETJET_U case ISDN_CTYPE_NETJET_U: ret = setup_netjet_u(card); break; #endif -#if CARD_FN_ENTERNOW_PCI +#ifdef CONFIG_HISAX_ENTERNOW_PCI case ISDN_CTYPE_ENTERNOW: ret = setup_enternow_pci(card); break; @@ -1156,19 +1099,6 @@ ll_unload(cs); goto outf_cs; } - if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) { - printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n"); - ll_unload(cs); - goto outf_cs; - } - cs->rcvidx = 0; - cs->tx_skb = NULL; - cs->tx_cnt = 0; - cs->event = 0; - - skb_queue_head_init(&cs->rq); - skb_queue_head_init(&cs->sq); - init_bcstate(cs, 0); init_bcstate(cs, 1); @@ -1201,10 +1131,8 @@ ret = 1; goto out; - outf_dlog: - kfree(cs->dlog); outf_cs: - kfree(cs); + free_IsdnCardState(cs); card->cs = NULL; out: return ret; @@ -1253,8 +1181,8 @@ i++; } else { printk(KERN_WARNING - "HiSax: Card %s not installed !\n", - CardType[cards[i].typ]); + "HiSax: Card type %d not installed !\n", + cards[i].typ); HiSax_shiftcards(i); nrcards--; } diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/diva.c Sat Mar 15 18:40:44 2003 @@ -362,7 +362,7 @@ static void diva_release(struct IsdnCardState *cs) { - del_timer(&cs->hw.diva.tl); + del_timer_sync(&cs->hw.diva.tl); if (cs->hw.diva.cfg_reg) byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ @@ -515,6 +515,162 @@ .irq_func = diva_ipacx_pci_irq, }; +static int __init +diva_ipac_probe(struct IsdnCardState *cs) +{ + u8 val; + + // request_io + val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, + cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + return (val == 1 || val == 2); +} + +static int __init +diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = DIVA_IPAC_ISA; + cs->irq = card->para[0]; + cs->hw.diva.cfg_reg = card->para[1]; + cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + goto err; + diva_ipac_isa_reset(cs); + cs->card_ops = &diva_ipac_isa_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = DIVA_ISA; + cs->irq = card->para[0]; + cs->hw.diva.cfg_reg = card->para[1]; + cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "ISA", cs->hw.diva.cfg_reg, cs->irq); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + goto err; + diva_reset(cs); + init_timer(&cs->hw.diva.tl); + cs->hw.diva.tl.function = (void *) diva_led_handler; + cs->hw.diva.tl.data = (long) cs; + cs->card_ops = &diva_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int is_ipac; + cs->hw.diva.cfg_reg = card->para[1]; + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) + return -EBUSY; + + is_ipac = diva_ipac_probe(cs); + hisax_release_resources(cs); + + if (is_ipac) + return diva_ipac_isa_probe(cs, card); + else + return diva_isac_isa_probe(cs, card); +} + +static int __init +diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.diva.cfg_reg = pci_resource_start(pdev, 2); + cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; + cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; + cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; + cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "PCI", cs->hw.diva.pci_cfg); + if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn")) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_IPAC_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.diva.pci_cfg = (unsigned long)request_mmio( + &cs->rs, pci_resource_start(pdev, 0), 4096, "diva"); + cs->hw.diva.cfg_reg = (unsigned long)request_mmio( + &cs->rs, pci_resource_start(pdev, 1), 4096, "diva"); + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "IPAC PCI", cs->hw.diva.pci_cfg); + diva_ipac_pci_reset(cs); + cs->card_ops = &diva_ipac_pci_ops; + if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = DIVA_IPACX_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", + "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq); + printk(KERN_INFO "Diva: %s space at %#lx\n", + "IPACX PCI", cs->hw.diva.pci_cfg); + diva_ipacx_pci_reset(cs); + cs->card_ops = &diva_ipacx_pci_ops; + if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; @@ -545,101 +701,60 @@ static struct pnp_card *pnp_c __devinitdata = NULL; #endif - int __init setup_diva(struct IsdnCard *card) { - int bytecnt = 8; - u8 val; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Diva_revision); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); if (card->para[1]) { - cs->hw.diva.ctrl_reg = 0; - cs->hw.diva.cfg_reg = card->para[1]; - val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, - cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); - if ((val == 1) || (val==2)) { - cs->subtyp = DIVA_IPAC_ISA; - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; - } else { - cs->subtyp = DIVA_ISA; - cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; - } - cs->irq = card->para[0]; - } else { + if (diva_isa_probe(card->cs, card) < 0) + return 0; + return 1; + + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Diva PnP: attach failed\n"); + if (isapnp_present()) { + struct pnp_card *pb; + struct pnp_dev *pd; + + while(pdev->card_vendor) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, pnp_c))) { + pnp_c = pb; + pd = NULL; + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { + printk(KERN_INFO "HiSax: %s detected\n", + (char *)pdev->driver_data); + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Diva PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "Diva PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); + return(0); + } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); + if (pdev->function == ISAPNP_FUNCTION(0xA1)) { + if (diva_ipac_isa_probe(cs->card, cs)) return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Diva PnP: activate failed\n"); - pnp_device_detach(pd); + return 1; + } else { + if (diva_isac_isa_probe(cs->card, cs)) return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return(0); - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.diva.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0xA1)) { - cs->subtyp = DIVA_IPAC_ISA; - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = - card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.hscx = - card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = - card->para[1] + DIVA_IPAC_ADR; - cs->hw.diva.hscx_adr = - card->para[1] + DIVA_IPAC_ADR; - } else { - cs->subtyp = DIVA_ISA; - cs->hw.diva.ctrl = - card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = - card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = - card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = - card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = - card->para[1] + DIVA_HSCX_ADR; - } - goto ready; + return 1; } else { printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); return(0); @@ -652,111 +767,29 @@ printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); } } + } #endif #if CONFIG_PCI - cs->subtyp = 0; - if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { - if (pci_enable_device(dev_diva)) - return(0); - cs->subtyp = DIVA_PCI; - cs->irq = dev_diva->irq; - cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); - } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { - if (pci_enable_device(dev_diva_u)) - return(0); - cs->subtyp = DIVA_PCI; - cs->irq = dev_diva_u->irq; - cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); - } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { - if (pci_enable_device(dev_diva201)) - return(0); - cs->subtyp = DIVA_IPAC_PCI; - cs->irq = dev_diva201->irq; - cs->hw.diva.pci_cfg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 0), 4096, "diva"); - cs->hw.diva.cfg_reg = (unsigned long)request_mmio(&cs->rs, pci_resource_start(dev_diva201, 1), 4096, "diva"); - } else { - printk(KERN_WARNING "Diva: No PCI card found\n"); - return(0); - } - - if (!cs->irq) { - printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); - goto err; - } - - if (!cs->hw.diva.cfg_reg) { - printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); - goto err; - } - cs->irq_flags |= SA_SHIRQ; -#endif /* CONFIG_PCI */ - if ((cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) ) { - cs->hw.diva.ctrl = 0; - cs->hw.diva.isac = 0; - cs->hw.diva.hscx = 0; - cs->hw.diva.isac_adr = 0; - cs->hw.diva.hscx_adr = 0; - bytecnt = 0; - } else { - cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; - cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; - cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; - cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; - bytecnt = 32; - } - } -ready: - printk(KERN_INFO - "Diva: %s card configured at %#lx IRQ %d\n", - (cs->subtyp == DIVA_PCI) ? "PCI" : - (cs->subtyp == DIVA_ISA) ? "ISA" : - (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : - (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", - cs->hw.diva.cfg_reg, cs->irq); - if ((cs->subtyp == DIVA_IPAC_PCI) || - (cs->subtyp == DIVA_IPACX_PCI) || - (cs->subtyp == DIVA_PCI) ) - printk(KERN_INFO "Diva: %s space at %#lx\n", - (cs->subtyp == DIVA_PCI) ? "PCI" : - (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", - cs->hw.diva.pci_cfg); - if ((cs->subtyp != DIVA_IPAC_PCI) && - (cs->subtyp != DIVA_IPACX_PCI) ) { - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) + if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20, + dev_diva))) { + if (diva_pci_probe(card->cs, dev_diva)) return 0; + return 1; + } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20_U, + dev_diva_u))) { + if (diva_pci_probe(card->cs, dev_diva_u)) + return 0; + return 1; + } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA201, + dev_diva201))) { + if (diva_ipac_pci_probe(card->cs, dev_diva201)) + return 0; + return 1; } - if (cs->subtyp == DIVA_IPAC_ISA) { - diva_ipac_isa_reset(cs); - cs->card_ops = &diva_ipac_isa_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else if (cs->subtyp == DIVA_IPAC_PCI) { - diva_ipac_pci_reset(cs); - cs->card_ops = &diva_ipac_pci_ops; - if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) - goto err; - } else if (cs->subtyp == DIVA_IPACX_PCI) { - diva_ipacx_pci_reset(cs); - cs->card_ops = &diva_ipacx_pci_ops; - if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) - goto err; - } else { /* DIVA 2.0 */ - diva_reset(cs); - cs->hw.diva.tl.function = (void *) diva_led_handler; - cs->hw.diva.tl.data = (long) cs; - init_timer(&cs->hw.diva.tl); - cs->card_ops = &diva_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - return 1; - err: - diva_release(cs); + printk(KERN_WARNING "Diva: No PCI card found\n"); +#endif /* CONFIG_PCI */ return 0; - } diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/elsa.c Sat Mar 15 18:40:40 2003 @@ -690,7 +690,47 @@ .irq_func = elsa_interrupt_ipac, }; -static unsigned char +static void __init +elsa_arcofi_init(struct IsdnCardState *cs) +{ +#if ARCOFI_USE + init_arcofi(cs); +#endif +} + +static void __init +elsa_timer_init(struct IsdnCardState *cs) +{ + cs->hw.elsa.tl.function = (void *) elsa_led_handler; + cs->hw.elsa.tl.data = (long) cs; + init_timer(&cs->hw.elsa.tl); +} + +static int __init +elsa_timer_test(struct IsdnCardState *cs) +{ + /* test timer */ + byteout(cs->hw.elsa.trig, 0xff); + byteout(cs->hw.elsa.timer, 0); + if (!TimerRun(cs)) { + byteout(cs->hw.elsa.timer, 0); /* second attempt */ + if (!TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer does not start\n"); + goto err; + } + } + HZDELAY(10 * HZ / 1000); /* wait >=10 ms */ + if (TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer does not run\n"); + goto err; + } + printk(KERN_INFO "Elsa: timer OK; resetting card\n"); + return 0; + err: + return -EBUSY; +} + +static unsigned char __init probe_elsa_adr(unsigned int adr, int typ) { int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, @@ -699,15 +739,13 @@ /* In case of the elsa pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (typ != ISDN_CTYPE_ELSA_PCMCIA && check_region(adr, 8)) { - printk(KERN_WARNING - "Elsa: Probing Port 0x%x: already in use\n", - adr); - return (0); + if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) { + printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n", adr); + return 0; } for (i = 0; i < 16; i++) { - in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ - in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ + in1 = inb(adr + ELSA_CONFIG); /* 'toggels' at */ + in2 = inb(adr + ELSA_CONFIG); /* each access */ p16_1 += 0x04 & in1; p16_2 += 0x04 & in2; p8_1 += 0x02 & in1; @@ -717,6 +755,7 @@ pfp_1 += 0x40 & in1; pfp_2 += 0x40 & in2; } + release_region(adr, 8); printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); if (65 == ++p16_1 * ++p16_2) { printk(" PCC-16/PCF found\n"); @@ -736,18 +775,227 @@ } } -static unsigned int -probe_elsa(struct IsdnCardState *cs) +static int __init +elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - int i; - unsigned int CARD_portlist[] = - {0x160, 0x170, 0x260, 0x360, 0}; - - for (i = 0; CARD_portlist[i]; i++) { - if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) + u8 val; + int i, bytecnt = 8; + unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0}; + + cs->hw.elsa.base = card->para[0]; + printk(KERN_INFO "Elsa: Microlink IO probing\n"); + if (cs->hw.elsa.base) { + cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ); + if (!cs->subtyp) { + printk(KERN_WARNING "Elsa: no Microlink at %#lx\n", + cs->hw.elsa.base); + goto err; + } + } else { + for (i = 0; CARD_portlist[i]; i++) { + cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ); + if (cs->subtyp) + cs->hw.elsa.base = CARD_portlist[i]; break; + } + } + if (!cs->hw.elsa.base) + goto err; + + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + val = bytein(cs->hw.elsa.cfg); + if (cs->subtyp == ELSA_PC) { + const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; + } else if (cs->subtyp == ELSA_PCC8) { + const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; + } else { + const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; } - return (CARD_portlist[i]); + val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; + if (val < 3) + val |= 8; + val += 'A' - 3; + if (val == 'B' || val == 'C') + val ^= 1; + if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) + val = 'C'; + printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq); + val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; + if (val) { + printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n"); + cs->hw.elsa.status |= ELSA_BAD_PWR; + } + switch (cs->subtyp) { + case ELSA_PCFPRO: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + if (elsa_timer_test(cs)) + goto err; + elsa_reset(cs); + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + if (cs->subtyp == ELSA_PC) { + val = readitac(cs, ITAC_SYS); + printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); + writeitac(cs, ITAC_ISEN, 0); + writeitac(cs, ITAC_RFIE, 0); + writeitac(cs, ITAC_XFIE, 0); + writeitac(cs, ITAC_SCIE, 0); + writeitac(cs, ITAC_STIE, 0); + } + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int bytecnt = 8; + + cs->irq = card->para[0]; + cs->hw.elsa.base = card->para[1]; + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); + switch (cs->subtyp) { + case ELSA_QS3000: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + if (elsa_timer_test(cs)) + goto err; + elsa_reset(cs); + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = ELSA_QS1000; + return elsa_qs_probe(cs, card); +} + +static int __init +elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = ELSA_QS3000; + return elsa_qs_probe(cs, card); +} + +static int __init +elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->irq = card->para[0]; + cs->hw.elsa.base = card->para[1]; + cs->hw.elsa.ale = cs->hw.elsa.base + 0; + val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); + if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ + cs->subtyp = ELSA_PCMCIA_IPAC; + cs->hw.elsa.isac = cs->hw.elsa.base + 2; + } else { + cs->subtyp = ELSA_PCMCIA; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + } + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->hw.elsa.ctrl = 0; + printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); + elsa_arcofi_init(cs); + elsa_reset(cs); + if (cs->subtyp == ELSA_PCMCIA_IPAC) { + cs->card_ops = &elsa_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + } else { + cs->card_ops = &elsa_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + } + return 0; + err: + elsa_release(cs); + return -EBUSY; +} + +static int __init +elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, + int subtyp) +{ + int bytecnt = 2; + u8 pci_rev; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = subtyp; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.elsa.cfg = pci_resource_start(pdev, 1); + cs->hw.elsa.base = pci_resource_start(pdev, 3); + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { + printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); + __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); + } + cs->hw.elsa.ale = cs->hw.elsa.base; + cs->hw.elsa.isac = cs->hw.elsa.base +1; + cs->hw.elsa.hscx = cs->hw.elsa.base +1; + printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n", + Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg, + cs->irq); + switch (cs->subtyp) { + case ELSA_QS3000PCI: bytecnt = 16; break; + } + if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) + goto err; + if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) + goto err; + elsa_arcofi_init(cs); + elsa_timer_init(cs); + elsa_reset(cs); + cs->card_ops = &elsa_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + return 0; + err: + elsa_release(cs); + return -EBUSY; } static struct pci_dev *dev_qs1000 __devinitdata = NULL; @@ -771,83 +1019,21 @@ int __devinit setup_elsa(struct IsdnCard *card) { - int bytecnt; - u8 val, pci_rev; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Elsa_revision); printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.elsa.ctrl_reg = 0; - cs->hw.elsa.status = 0; - cs->hw.elsa.MFlag = 0; - cs->subtyp = 0; - if (cs->typ == ISDN_CTYPE_ELSA) { - cs->hw.elsa.base = card->para[0]; - printk(KERN_INFO "Elsa: Microlink IO probing\n"); - if (cs->hw.elsa.base) { - if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, - cs->typ))) { - printk(KERN_WARNING - "Elsa: no Elsa Microlink at %#lx\n", - cs->hw.elsa.base); - return (0); - } - } else - cs->hw.elsa.base = probe_elsa(cs); - if (cs->hw.elsa.base) { - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - val = bytein(cs->hw.elsa.cfg); - if (cs->subtyp == ELSA_PC) { - const u8 CARD_IrqTab[8] = - {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; - } else if (cs->subtyp == ELSA_PCC8) { - const u8 CARD_IrqTab[8] = - {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; - } else { - const u8 CARD_IrqTab[8] = - {15, 10, 15, 3, 11, 5, 11, 9}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; - } - val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; - if (val < 3) - val |= 8; - val += 'A' - 3; - if (val == 'B' || val == 'C') - val ^= 1; - if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) - val = 'C'; - printk(KERN_INFO - "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - val, cs->irq); - val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; - if (val) { - printk(KERN_WARNING - "Elsa: Microlink S0 bus power bad\n"); - cs->hw.elsa.status |= ELSA_BAD_PWR; - } - } else { - printk(KERN_WARNING - "No Elsa Microlink found\n"); - return (0); - } - } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { + + if (card->typ == ISDN_CTYPE_ELSA) { + if (elsa_probe(card->cs, card)) + return 0; + return 1; + } else if (card->typ == ISDN_CTYPE_ELSA_PNP) { #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { struct pnp_card *pb; struct pnp_dev *pd; - + while(pdev->card_vendor) { if ((pb = pnp_find_card(pdev->card_vendor, pdev->card_device, @@ -878,10 +1064,15 @@ } card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0x133)) - cs->subtyp = ELSA_QS1000; - else - cs->subtyp = ELSA_QS3000; + if (pdev->function == ISAPNP_FUNCTION(0x133)) { + if (elsa_qs1000_probe(card->cs, card)) + return 0; + return 1; + } else { + if (elsa_qs3000_probe(card->cs, card)) + return 0; + return 1; + } break; } else { printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); @@ -897,184 +1088,33 @@ } } #endif - if (card->para[1] && card->para[0]) { - cs->hw.elsa.base = card->para[1]; - cs->irq = card->para[0]; - if (!cs->subtyp) - cs->subtyp = ELSA_QS1000; - } else { - printk(KERN_ERR "Elsa PnP: no parameter\n"); - } - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - printk(KERN_INFO - "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->irq); - } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) { - cs->hw.elsa.base = card->para[1]; - cs->irq = card->para[0]; - cs->hw.elsa.ale = cs->hw.elsa.base + 0; - val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); - if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ - cs->subtyp = ELSA_PCMCIA_IPAC; - cs->hw.elsa.isac = cs->hw.elsa.base + 2; - cs->hw.elsa.hscx = cs->hw.elsa.base + 2; - } else { - cs->subtyp = ELSA_PCMCIA; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - } - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->hw.elsa.ctrl = 0; - printk(KERN_INFO - "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->irq); - } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { + if (elsa_qs1000_probe(card->cs, card)) + return 0; + return 1; + + } else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) { + if (elsa_pcmcia_probe(card->cs, card)) + return 0; + return 1; + } else if (card->typ == ISDN_CTYPE_ELSA_PCI) { #if CONFIG_PCI - cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { - if (pci_enable_device(dev_qs1000)) - return(0); - cs->subtyp = ELSA_QS1000PCI; - cs->irq = dev_qs1000->irq; - cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); - cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); - pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev); + if (elsa_qs_pci_probe(card->cs, dev_qs1000, + ELSA_QS1000PCI)) + return 0; + return 1; } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { - if (pci_enable_device(dev_qs3000)) - return(0); - cs->subtyp = ELSA_QS3000PCI; - cs->irq = dev_qs3000->irq; - cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); - cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); - pci_read_config_byte(dev_qs1000, PCI_REVISION_ID, &pci_rev); + if (elsa_qs_pci_probe(card->cs, dev_qs3000, + ELSA_QS3000PCI)) + return 0; + return 1; } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); - return(0); + return 0; } - if (!cs->irq) { - printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); - return(0); - } - - if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { - printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); - return(0); - } - if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { - printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); - set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } - cs->hw.elsa.ale = cs->hw.elsa.base; - cs->hw.elsa.isac = cs->hw.elsa.base +1; - cs->hw.elsa.hscx = cs->hw.elsa.base +1; - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->irq_flags |= SA_SHIRQ; - printk(KERN_INFO - "Elsa: %s defined at %#lx/0x%x IRQ %d\n", - Elsa_Types[cs->subtyp], - cs->hw.elsa.base, - cs->hw.elsa.cfg, - cs->irq); #endif /* CONFIG_PCI */ - } else - return (0); - - switch (cs->subtyp) { - case ELSA_PC: - case ELSA_PCC8: - case ELSA_PCC16: - case ELSA_QS1000: - case ELSA_PCMCIA: - case ELSA_PCMCIA_IPAC: - bytecnt = 8; - break; - case ELSA_PCFPRO: - case ELSA_PCF: - case ELSA_QS3000: - case ELSA_QS3000PCI: - bytecnt = 16; - break; - case ELSA_QS1000PCI: - bytecnt = 2; - break; - default: - printk(KERN_WARNING - "Unknown ELSA subtype %d\n", cs->subtyp); - return (0); - } - /* In case of the elsa pcmcia card, this region is in use, - reserved for us by the card manager. So we do not check it - here, it would fail. */ - if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA) - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - - if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) - if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) - goto err; - -#if ARCOFI_USE - init_arcofi(cs); -#endif - - cs->hw.elsa.tl.function = (void *) elsa_led_handler; - cs->hw.elsa.tl.data = (long) cs; - init_timer(&cs->hw.elsa.tl); - /* Teste Timer */ - if (cs->hw.elsa.timer) { - byteout(cs->hw.elsa.trig, 0xff); - byteout(cs->hw.elsa.timer, 0); - if (!TimerRun(cs)) { - byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */ - if (!TimerRun(cs)) { - printk(KERN_WARNING - "Elsa: timer do not start\n"); - goto err; - } - } - HZDELAY(1); /* wait >=10 ms */ - if (TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer do not run down\n"); - goto err; - } - printk(KERN_INFO "Elsa: timer OK; resetting card\n"); - } - elsa_reset(cs); - if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; } - if (cs->subtyp == ELSA_PC) { - val = readitac(cs, ITAC_SYS); - printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); - writeitac(cs, ITAC_ISEN, 0); - writeitac(cs, ITAC_RFIE, 0); - writeitac(cs, ITAC_XFIE, 0); - writeitac(cs, ITAC_SCIE, 0); - writeitac(cs, ITAC_STIE, 0); - } - return 1; - err: - elsa_release(cs); return 0; } diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/enternow_pci.c Sat Mar 15 18:40:43 2003 @@ -263,13 +263,65 @@ .irq_func = enpci_interrupt, }; +static int __init +enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) + goto err; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD + + /* Reset an */ + cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + /* 50 ms Pause */ + schedule_timeout((50*HZ)/1000); + + cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0x00; // war 0xc0 + cs->hw.njet.dmactrl = 0; + + OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); + OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); + OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); + + printk(KERN_INFO + "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + reset_enpci(cs); + cs->hw.njet.last_is0 = 0; + cs->hw.njet.bc_activate = enpci_bc_activate; + cs->hw.njet.bc_deactivate = enpci_bc_deactivate; + amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); + + cs->card_ops = &enpci_ops; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; /* called by config.c */ int __init setup_enternow_pci(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN @@ -278,72 +330,22 @@ strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n"); - return(0); - } - /* checks Sub-Vendor ID because system crashes with Traverse-Card */ - if ((dev_netjet->subsystem_vendor != 0x55) || - (dev_netjet->subsystem_device != 0x02)) { - printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n"); - return(0); - } - } else { - printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); - return(0); + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + if (dev_netjet->subsystem_vendor != 0x55 || + dev_netjet->subsystem_device != 0x02) { + printk(KERN_WARNING "enter:now: You tried to load " + "this driver with an incompatible " + "TigerJet-card\n"); + printk(KERN_WARNING "Use type=20 for Traverse " + "NetJet PCI Card.\n"); + return 0; } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - - /* Reset an */ - cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - /* 50 ms Pause */ - schedule_timeout((50*HZ)/1000); - - cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0x00; // war 0xc0 - cs->hw.njet.dmactrl = 0; - - OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); - OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); - OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); - - break; - } - printk(KERN_INFO - "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) + if (enpci_probe(card->cs, dev_netjet)) + return 1; return 0; - reset_enpci(cs); - cs->hw.njet.last_is0 = 0; - cs->hw.njet.bc_activate = enpci_bc_activate; - cs->hw.njet.bc_deactivate = enpci_bc_deactivate; - amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); - - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &enpci_ops; - - return 1; + } + printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Sat Mar 15 18:40:42 2003 +++ b/drivers/isdn/hisax/gazel.c Sat Mar 15 18:40:42 2003 @@ -294,60 +294,6 @@ inithscxisac(cs); } -static int -r647_reserve_regions(struct IsdnCardState *cs) -{ - int i, base = cs->hw.gazel.hscx[0]; - - for (i = 0; i < 0xc000; i += 0x1000) { - if (!request_io(&cs->rs, i + base, 16, "gazel")) - goto err; - } - if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r685_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r742_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int -r753_reserve_regions(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - static struct card_ops r647_ops = { .init = gazel_init, .reset = r647_reset, @@ -377,194 +323,213 @@ }; static int __init -setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) +gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); - // we got an irq parameter, assume it is an ISA card - // R742 decodes address even in not started... - // R647 returns FF if not present or not started - // eventually needs improvment - cs->hw.gazel.ipac = card->para[1]; - if (ipac_read(cs, IPAC_ID) == 1) - cs->subtyp = R742; - else - cs->subtyp = R647; + int i, base; + cs->subtyp = R647; + cs->irq = card->para[0]; cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; + + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.hscx[0] = card->para[1]; cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; - cs->irq = card->para[0]; cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - switch (cs->subtyp) { - case R647: - printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - - return r647_reserve_regions(cs); - case R742: - printk(KERN_INFO "Gazel: Card ISA R742 found\n"); - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X\n", - cs->irq, cs->hw.gazel.ipac); - return r742_reserve_regions(cs); + base = cs->hw.gazel.hscx[0]; + for (i = 0; i < 0xc000; i += 0x1000) { + if (!request_io(&cs->rs, base + i, 16, "gazel")) + goto err; } + if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) + goto err; + + cs->card_ops = &r647_ops; + if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) + goto err; + + cs->card_ops->reset(cs); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; } -static struct pci_dev *dev_tel __initdata = NULL; - static int __init -setup_gazelpci(struct IsdnCardState *cs) +gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; - u8 pci_irq = 0, found; - u_int nbseek, seekcard; - u8 pci_rev; + cs->subtyp = R742; + cs->irq = card->para[0]; + cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; - printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); - found = 0; - if (!pci_present()) { - printk(KERN_WARNING "Gazel: No PCI bus present\n"); - return 1; - } - seekcard = PCI_DEVICE_ID_PLX_R685; - for (nbseek = 0; nbseek < 3; nbseek++) { - if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { - if (pci_enable_device(dev_tel)) - return 1; - pci_irq = dev_tel->irq; - pci_ioaddr0 = pci_resource_start(dev_tel, 1); - pci_ioaddr1 = pci_resource_start(dev_tel, 2); - found = 1; - } - if (found) - break; - else { - switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - seekcard = PCI_DEVICE_ID_PLX_R753; - break; - case PCI_DEVICE_ID_PLX_R753: - seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; - break; - } - } - } - if (!found) { - printk(KERN_WARNING "Gazel: No PCI card found\n"); - return -ENODEV; - } - if (!pci_irq) { - printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); - return -ENODEV; - } - cs->hw.gazel.pciaddr[0] = pci_ioaddr0; - cs->hw.gazel.pciaddr[1] = pci_ioaddr1; + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; - pci_ioaddr1 &= 0xfffe; - cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; - cs->hw.gazel.ipac = pci_ioaddr1; - cs->hw.gazel.isac = pci_ioaddr1 + 0x80; - cs->hw.gazel.hscx[0] = pci_ioaddr1; - cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; - cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + cs->card_ops = &r742_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + + cs->card_ops->reset(cs); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = R685; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80; + cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2); + cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - cs->irq = pci_irq; - cs->irq_flags |= SA_SHIRQ; + cs->dc.isac.adf2 = 0x87; - switch (seekcard) { - case PCI_DEVICE_ID_PLX_R685: - printk(KERN_INFO "Gazel: Card PCI R685 found\n"); - cs->subtyp = R685; - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO - "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - return r685_reserve_regions(cs); - case PCI_DEVICE_ID_PLX_R753: - case PCI_DEVICE_ID_PLX_DJINN_ITOO: - printk(KERN_INFO "Gazel: Card PCI R753 found\n"); - cs->subtyp = R753; - printk(KERN_INFO - "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); - /* - * Erratum for PLX9050, revision 1: - * If bit 7 of BAR 0/1 is set, local config registers - * can not be read (write is okay) - */ - if (cs->hw.gazel.cfg_reg & 0x80) { - pci_read_config_byte(dev_tel, PCI_REVISION_ID, &pci_rev); - if (pci_rev == 1) { - printk(KERN_INFO "Gazel: PLX9050 rev1 workaround activated\n"); - set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } + if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; + + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + + cs->card_ops = &r685_ops; + if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) + goto err; + + cs->card_ops->reset(cs); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + u8 pci_rev; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = R753; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); + cs->hw.gazel.ipac = pci_resource_start(pdev, 2); + + if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) + goto err; + if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) + goto err; + + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + /* + * Erratum for PLX9050, revision 1: + * If bit 7 of BAR 0/1 is set, local config registers + * can not be read (write is okay) + */ + if (cs->hw.gazel.cfg_reg & 0x80) { + pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); + if (pci_rev == 1) { + printk(KERN_INFO "Gazel: PLX9050 rev1 workaround " + "activated\n"); + __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); } - return r753_reserve_regions(cs); } + cs->card_ops = &r753_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + goto err; + + cs->card_ops->reset(cs); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; } +static struct pci_dev *dev_tel __initdata = NULL; +static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685; + int __init setup_gazel(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, gazel_revision); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); if (card->para[0]) { - if (setup_gazelisa(card, cs)) - return (0); - } else { - if (setup_gazelpci(cs)) - return (0); + printk(KERN_INFO "Gazel: ISA card automatic recognition\n"); + // we got an irq parameter, assume it is an ISA card + // R742 decodes address even in not started... + // R647 returns FF if not present or not started + // eventually needs improvment + card->cs->hw.gazel.ipac = card->para[1]; + if (ipac_read(card->cs, IPAC_ID) == 1) { + if (gazel742_probe(card->cs, card)) + return 0; + } else { + if (gazel647_probe(card->cs, card)) + return 0; + } + return 1; } - switch (cs->subtyp) { - case R647: - case R685: - if (cs->subtyp == R647) { - cs->card_ops = &r647_ops; - if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) - goto err; - } else { - cs->card_ops = &r685_ops; - if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) - goto err; + for (;;) { + dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel); + if (dev_tel) { + switch (dev_id) { + case PCI_DEVICE_ID_PLX_R685: + if (gazel685_probe(card->cs, dev_tel)) + return 0; + return 1; + case PCI_DEVICE_ID_PLX_R753: + case PCI_DEVICE_ID_PLX_DJINN_ITOO: + if (gazel753_probe(card->cs, dev_tel)) + return 0; + return 1; + } } - cs->card_ops->reset(cs); - break; - case R742: - case R753: - if (cs->subtyp == R742) { - cs->card_ops = &r742_ops; - } else { - cs->card_ops = &r753_ops; + switch (dev_id) { + case PCI_DEVICE_ID_PLX_R685: + dev_id = PCI_DEVICE_ID_PLX_R753; + case PCI_DEVICE_ID_PLX_R753: + dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO; + default: + break; } - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - cs->card_ops->reset(cs); - break; } - return 1; - err: - hisax_release_resources(cs); + printk(KERN_WARNING "Gazel: No PCI card found\n"); return 0; } + + diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Sat Mar 15 18:40:41 2003 +++ b/drivers/isdn/hisax/hfc_pci.c Sat Mar 15 18:40:41 2003 @@ -1382,72 +1382,41 @@ }; -/* this variable is used as card index when more than one cards are present */ -static struct pci_dev *dev_hfcpci __initdata = NULL; - -int __init -setup_hfcpci(struct IsdnCard *card) +static int __init +niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - int i; - struct pci_dev *tmp_hfcpci = NULL; + int rc; - strcpy(tmp, hfcpci_revision); - printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.hfcpci.int_s1 = 0; - cs->dc.hfcpci.ph_state = 0; - cs->hw.hfcpci.fifo = 255; + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; - i = 0; - while (id_list[i].vendor_id) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - i++; - if (tmp_hfcpci) { - if (pci_enable_device(tmp_hfcpci)) - continue; - pci_set_master(tmp_hfcpci); - if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) - continue; - else - break; - } - } + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.hfcpci.pdev = pdev; + + cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, + pci_resource_start(pdev, 1), 128, + "hfc_pci"); + if (!cs->hw.hfcpci.pci_io) + goto err; - if (tmp_hfcpci) { - i--; - dev_hfcpci = tmp_hfcpci; /* old device */ - cs->irq = dev_hfcpci->irq; - cs->hw.hfcpci.pdev = tmp_hfcpci; - if (!cs->irq) { - printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); - return (0); - } - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); - } else { - printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); - return (0); - } /* Allocate memory for FIFOS */ - cs->hw.hfcpci.fifos = pci_alloc_consistent(tmp_hfcpci, 32768, &cs->hw.hfcpci.fifos_dma); - if (!cs->hw.hfcpci.fifos) { - printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); - return 0; - } + rc = -ENOMEM; + cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, + &cs->hw.hfcpci.fifos_dma); + if (!cs->hw.hfcpci.fifos) + goto err; + pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, (u_int)cs->hw.hfcpci.fifos_dma); - cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, dev_hfcpci->resource[ 1].start, 256, "hfc_pci"); - if (!cs->hw.hfcpci.pci_io) - goto err; - - printk(KERN_INFO - "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", - (u_int) cs->hw.hfcpci.pci_io, - (u_int) cs->hw.hfcpci.fifos, - (u_int) cs->hw.hfcpci.fifos_dma, - cs->irq, HZ); + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n", + id_list[i].vendor_name, id_list[i].card_name); + printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n", + (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, + (u_int) cs->hw.hfcpci.fifos_dma, cs->irq); printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ cs->hw.hfcpci.int_m1 = 0; @@ -1456,17 +1425,46 @@ /* At this point the needed PCI config is done */ /* fifos are still not enabled */ - cs->irq_flags |= SA_SHIRQ; - + init_timer(&cs->hw.hfcpci.timer); cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; cs->hw.hfcpci.timer.data = (long) cs; - init_timer(&cs->hw.hfcpci.timer); hfcpci_reset(cs); cs->auxcmd = &hfcpci_auxcmd; cs->card_ops = &hfcpci_ops; - return 1; + return 0; err: hisax_release_resources(cs); + return -EBUSY; +} + +/* this variable is used as card index when more than one cards are present */ +static struct pci_dev *dev_hfcpci __initdata = NULL; + +int __init +setup_hfcpci(struct IsdnCard *card) +{ + struct IsdnCardState *cs = card->cs; + char tmp[64]; + int i; + struct pci_dev *tmp_hfcpci = NULL; + + strcpy(tmp, hfcpci_revision); + printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); + cs->hw.hfcpci.int_s1 = 0; + cs->dc.hfcpci.ph_state = 0; + cs->hw.hfcpci.fifo = 255; + + for (i = 0; id_list[i].vendor_id; i++) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + if (!tmp_hfcpci) + continue; + + if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0) + return 0; + return 1; + } return 0; } diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hisax/hfc_sx.c Sat Mar 15 18:40:39 2003 @@ -1159,6 +1159,74 @@ .irq_func = hfcsx_interrupt, }; +static int __init +hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + int rc; + char c; + + cs->irq = card->para[0]; + cs->hw.hfcsx.base = card->para[1] & 0xfffe; + + cs->hw.hfcsx.fifo = 255; + cs->hw.hfcsx.int_s1 = 0; + cs->dc.hfcsx.ph_state = 0; + + rc = -EBUSY; + if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) + goto err; + + rc = -ENODEV; + byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); + byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); + udelay(10); + cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); + switch (cs->hw.hfcsx.chip >> 4) { + case 1: + c ='+'; + break; + case 9: + c ='P'; + break; + default: + printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", + cs->hw.hfcsx.chip >> 4); + goto err; + } + if (!ccd_sp_irqtab[cs->irq & 0xF]) { + printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", + cs->irq & 0xF); + goto err; + } + rc = -ENOMEM; + cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC); + if (!cs->hw.hfcsx.extra) { + printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); + goto err; + } + printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n", + c, (u_int) cs->hw.hfcsx.base, cs->irq); + + cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcsx.int_m1 = 0; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); + + init_timer(&cs->hw.hfcsx.timer); + cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; + cs->hw.hfcsx.timer.data = (long) cs; + cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ + cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */ + + hfcsx_reset(cs); + cs->auxcmd = &hfcsx_auxcmd; + cs->card_ops = &hfcsx_ops; + return 0; + err: + hisax_release_resources(cs); + return rc; +} + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), @@ -1174,7 +1242,6 @@ int __devinit setup_hfcsx(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcsx_revision); @@ -1227,62 +1294,7 @@ } } #endif - cs->hw.hfcsx.base = card->para[1] & 0xfffe; - cs->irq = card->para[0]; - cs->hw.hfcsx.int_s1 = 0; - cs->dc.hfcsx.ph_state = 0; - cs->hw.hfcsx.fifo = 255; - - if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) - return 0; - byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); - byteout(cs->hw.hfcsx.base + 1, - ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); - udelay(10); - cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); - switch (cs->hw.hfcsx.chip >> 4) { - case 1: - tmp[0] ='+'; - break; - case 9: - tmp[0] ='P'; - break; - default: - printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", - cs->hw.hfcsx.chip >> 4); - hisax_release_resources(cs); + if (hfcsx_probe(card->cs, card) < 0) return 0; - } - if (!ccd_sp_irqtab[cs->irq & 0xF]) { - printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", - cs->irq & 0xF); - hisax_release_resources(cs); - return 0; - } - cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), - GFP_ATOMIC); - if (!cs->hw.hfcsx.extra) { - hisax_release_resources(cs); - printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); - return 0; - } - - printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", - tmp[0], (u_int) cs->hw.hfcsx.base, - cs->irq, HZ); - cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcsx.int_m1 = 0; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - - cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; - cs->hw.hfcsx.timer.data = (long) cs; - cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ - cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ - init_timer(&cs->hw.hfcsx.timer); - - hfcsx_reset(cs); - cs->auxcmd = &hfcsx_auxcmd; - cs->card_ops = &hfcsx_ops; return 1; } diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c --- a/drivers/isdn/hisax/hfcscard.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/hfcscard.c Sat Mar 15 18:40:44 2003 @@ -133,6 +133,50 @@ .irq_func = hfcs_interrupt, }; +static int __init +hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.hfcD.addr = card->para[1]; + + if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) + goto err; + + printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n", + cs->hw.hfcD.addr, cs->irq); + + cs->hw.hfcD.cip = 0; + cs->hw.hfcD.int_s1 = 0; + cs->hw.hfcD.send = NULL; + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->hw.hfcD.dfifosize = 512; + cs->dc.hfcd.ph_state = 0; + cs->hw.hfcD.fifo = 255; + + if (cs->typ == ISDN_CTYPE_TELES3C) { + cs->hw.hfcD.bfifosize = 1024 + 512; + /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x56, cs->hw.hfcD.addr | 1); + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + cs->hw.hfcD.bfifosize = 7*1024 + 512; + /* Acer P10 IO ADR is 0x300 */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x57, cs->hw.hfcD.addr | 1); + } + set_cs_func(cs); + init_timer(&cs->hw.hfcD.timer); + cs->hw.hfcD.timer.function = (void *) hfcs_Timer; + cs->hw.hfcD.timer.data = (long) cs; + hfcs_reset(cs); + cs->card_ops = &hfcs_ops; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id hfc_ids[] __initdata = { { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114), @@ -166,7 +210,6 @@ int __init setup_hfcs(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcs_revision); @@ -220,42 +263,8 @@ } } #endif - cs->hw.hfcD.addr = card->para[1] & 0xfffe; - cs->irq = card->para[0]; - cs->hw.hfcD.cip = 0; - cs->hw.hfcD.int_s1 = 0; - cs->hw.hfcD.send = NULL; - cs->bcs[0].hw.hfc.send = NULL; - cs->bcs[1].hw.hfc.send = NULL; - cs->hw.hfcD.dfifosize = 512; - cs->dc.hfcd.ph_state = 0; - cs->hw.hfcD.fifo = 255; - if (cs->typ == ISDN_CTYPE_TELES3C) { - cs->hw.hfcD.bfifosize = 1024 + 512; - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - cs->hw.hfcD.bfifosize = 7*1024 + 512; - } else - return (0); - if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) + if (hfcs_probe(card->cs, card) < 0) return 0; - printk(KERN_INFO - "HFCS: defined at 0x%x IRQ %d HZ %d\n", - cs->hw.hfcD.addr, - cs->irq, HZ); - if (cs->typ == ISDN_CTYPE_TELES3C) { - /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x56, cs->hw.hfcD.addr | 1); - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - /* Acer P10 IO ADR is 0x300 */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x57, cs->hw.hfcD.addr | 1); - } - set_cs_func(cs); - cs->hw.hfcD.timer.function = (void *) hfcs_Timer; - cs->hw.hfcD.timer.data = (long) cs; - init_timer(&cs->hw.hfcD.timer); - hfcs_reset(cs); - cs->card_ops = &hfcs_ops; - return (1); + return 1; + } diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/hisax.h Sat Mar 15 18:40:43 2003 @@ -782,7 +782,6 @@ struct gazel_hw { unsigned int cfg_reg; - unsigned int pciaddr[2]; signed int ipac; signed int isac; signed int hscx[2]; @@ -1073,264 +1072,17 @@ #define ISDN_CTYPE_COUNT 41 -#ifdef ISDN_CHIP_ISAC -#undef ISDN_CHIP_ISAC -#endif - -#ifdef CONFIG_HISAX_16_0 -#define CARD_TELES0 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELES0 0 -#endif - -#ifdef CONFIG_HISAX_16_3 -#define CARD_TELES3 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELES3 0 -#endif - -#ifdef CONFIG_HISAX_TELESPCI -#define CARD_TELESPCI 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELESPCI 0 -#endif - -#ifdef CONFIG_HISAX_AVM_A1 -#define CARD_AVM_A1 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_AVM_A1 0 -#endif - -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA -#define CARD_AVM_A1_PCMCIA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_AVM_A1_PCMCIA 0 -#endif - -#ifdef CONFIG_HISAX_FRITZPCI -#define CARD_FRITZPCI 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_FRITZPCI 0 -#endif - -#ifdef CONFIG_HISAX_ELSA -#define CARD_ELSA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ELSA 0 -#endif - -#ifdef CONFIG_HISAX_IX1MICROR2 -#define CARD_IX1MICROR2 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_IX1MICROR2 0 -#endif - -#ifdef CONFIG_HISAX_DIEHLDIVA -#define CARD_DIEHLDIVA 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_DIEHLDIVA 0 -#endif - -#ifdef CONFIG_HISAX_ASUSCOM -#define CARD_ASUSCOM 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ASUSCOM 0 -#endif - -#ifdef CONFIG_HISAX_TELEINT -#define CARD_TELEINT 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_TELEINT 0 -#endif - -#ifdef CONFIG_HISAX_SEDLBAUER -#define CARD_SEDLBAUER 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SEDLBAUER 0 -#endif - -#ifdef CONFIG_HISAX_SPORTSTER -#define CARD_SPORTSTER 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SPORTSTER 0 -#endif - -#ifdef CONFIG_HISAX_MIC -#define CARD_MIC 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_MIC 0 -#endif - -#ifdef CONFIG_HISAX_NETJET -#define CARD_NETJET_S 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_NETJET_S 0 -#endif - -#ifdef CONFIG_HISAX_HFCS -#define CARD_HFCS 1 -#else -#define CARD_HFCS 0 -#endif - -#ifdef CONFIG_HISAX_HFC_PCI -#define CARD_HFC_PCI 1 -#else -#define CARD_HFC_PCI 0 -#endif - -#ifdef CONFIG_HISAX_HFC_SX -#define CARD_HFC_SX 1 -#else -#define CARD_HFC_SX 0 -#endif - -#ifdef CONFIG_HISAX_AMD7930 -#define CARD_AMD7930 1 -#else -#define CARD_AMD7930 0 -#endif - -#ifdef CONFIG_HISAX_NICCY -#define CARD_NICCY 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_NICCY 0 -#endif - -#ifdef CONFIG_HISAX_ISURF -#define CARD_ISURF 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_ISURF 0 -#endif - -#ifdef CONFIG_HISAX_S0BOX -#define CARD_S0BOX 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_S0BOX 0 -#endif - -#ifdef CONFIG_HISAX_HSTSAPHIR -#define CARD_HSTSAPHIR 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_HSTSAPHIR 0 -#endif - #ifdef CONFIG_HISAX_TESTEMU -#define CARD_TESTEMU 1 #define ISDN_CTYPE_TESTEMU 99 #undef ISDN_CTYPE_COUNT #define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU -#else -#define CARD_TESTEMU 0 -#endif - -#ifdef CONFIG_HISAX_BKM_A4T -#define CARD_BKM_A4T 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_BKM_A4T 0 -#endif - -#ifdef CONFIG_HISAX_SCT_QUADRO -#define CARD_SCT_QUADRO 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_SCT_QUADRO 0 -#endif - -#ifdef CONFIG_HISAX_GAZEL -#define CARD_GAZEL 1 -#ifndef ISDN_CHIP_ISAC -#define ISDN_CHIP_ISAC 1 -#endif -#else -#define CARD_GAZEL 0 -#endif - -#ifdef CONFIG_HISAX_W6692 -#define CARD_W6692 1 -#ifndef ISDN_CHIP_W6692 -#define ISDN_CHIP_W6692 1 -#endif -#else -#define CARD_W6692 0 #endif #ifdef CONFIG_HISAX_NETJET_U -#define CARD_NETJET_U 1 -#ifndef ISDN_CHIP_ICC -#define ISDN_CHIP_ICC 1 -#endif #ifndef HISAX_UINTERFACE #define HISAX_UINTERFACE 1 #endif #else -#define CARD_NETJET_U 0 -#endif - -#ifdef CONFIG_HISAX_ENTERNOW_PCI -#define CARD_FN_ENTERNOW_PCI 1 #endif #define TEI_PER_CARD 1 @@ -1402,7 +1154,7 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args); void HiSax_reportcard(int cardnr, int sel); int QuickHex(char *txt, u8 * p, int cnt); void LogFrame(struct IsdnCardState *cs, u8 * p, int size); diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c --- a/drivers/isdn/hisax/hisax_fcclassic.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/hisax_fcclassic.c Sat Mar 15 18:40:40 2003 @@ -231,7 +231,7 @@ adapter->isac.write_isac = &fcclassic_write_isac; adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo; adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo; - isac_setup(&adapter->isac); + hisax_isac_setup(&adapter->isac); for (i = 0; i < 2; i++) { hscx_init(&adapter->hscx[i]); adapter->hscx[i].priv = adapter; diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Sat Mar 15 18:40:43 2003 @@ -46,24 +46,22 @@ MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver"); -// FIXME temporary hack until I sort out the new PnP stuff -#define __ISAPNP__ - static struct pci_device_id fcpci_ids[] __devinitdata = { - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1 , PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI" }, - { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID, - 0, 0, (unsigned long) "Fritz!Card PCI v2" }, - { } + { .vendor = PCI_VENDOR_ID_AVM, + .device = PCI_DEVICE_ID_AVM_A1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) "Fritz!Card PCI", + }, + { .vendor = PCI_VENDOR_ID_AVM, + .device = PCI_DEVICE_ID_AVM_A1_V2, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = (unsigned long) "Fritz!Card PCI v2" }, + {} }; -MODULE_DEVICE_TABLE(pci, fcpci_ids); -static struct pnp_card_device_id fcpnp_ids[] __devinitdata = { - { .id = "AVM0900", - .driver_data = (unsigned long) "Fritz!Card PnP", - .devs = { { "AVM0900" } } } -}; -MODULE_DEVICE_TABLE(pnp_card, fcpnp_ids); +MODULE_DEVICE_TABLE(pci, fcpci_ids); static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); @@ -782,7 +780,7 @@ case AVM_FRITZ_PCI: case AVM_FRITZ_PNP: fcpci_init(adapter); - isac_setup(&adapter->isac); + hisax_isac_setup(&adapter->isac); break; } val = adapter->read_hdlc_status(adapter, 0); @@ -908,10 +906,10 @@ .id_table = fcpci_ids, }; -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD static int __devinit fcpnp_probe(struct pnp_card *card, - const struct pnp_card_device_id *card_id) + const struct pnp_card_id *card_id) { struct fritz_adapter *adapter; struct pnp_dev *pnp_dev; @@ -957,6 +955,14 @@ delete_adapter(adapter); } +static struct pnp_card_id fcpnp_ids[] __devinitdata = { + { .id = "AVM0900", + .driver_data = (unsigned long) "Fritz!Card PnP", + .devs = { { "AVM0900" } }, + }, + {} +}; + static struct pnpc_driver fcpnp_driver = { .name = "fcpnp", .probe = fcpnp_probe, @@ -968,7 +974,7 @@ static int __init hisax_fcpcipnp_init(void) { - int retval, pci_nr_found; + int retval = 0, pci_nr_found; printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); @@ -977,10 +983,8 @@ goto out; pci_nr_found = retval; -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD retval = pnpc_register_driver(&fcpnp_driver); -#else - retval = 0; #endif if (retval < 0) goto out_unregister_pci; @@ -988,14 +992,14 @@ #if !defined(CONFIG_HOTPLUG) || defined(MODULE) if (pci_nr_found + retval == 0) { retval = -ENODEV; - goto out_unregister_isapnp; + goto out_unregister_pnp; } #endif return 0; #if !defined(CONFIG_HOTPLUG) || defined(MODULE) - out_unregister_isapnp: -#ifdef __ISAPNP__ + out_unregister_pnp: +#ifdef CONFIG_PNP_CARD pnpc_unregister_driver(&fcpnp_driver); #endif #endif @@ -1007,7 +1011,7 @@ static void __exit hisax_fcpcipnp_exit(void) { -#ifdef __ISAPNP__ +#ifdef CONFIG_PNP_CARD pnpc_unregister_driver(&fcpnp_driver); #endif pci_unregister_driver(&fcpci_driver); diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c --- a/drivers/isdn/hisax/hisax_isac.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hisax/hisax_isac.c Sat Mar 15 18:40:39 2003 @@ -770,7 +770,7 @@ FsmInitTimer(&isac->l1m, &isac->timer); } -void isac_setup(struct isac *isac) +void hisax_isac_setup(struct isac *isac) { int val, eval; @@ -890,7 +890,7 @@ EXPORT_SYMBOL(isacsx_setup); EXPORT_SYMBOL(isacsx_irq); -EXPORT_SYMBOL(isac_setup); +EXPORT_SYMBOL(hisax_isac_setup); EXPORT_SYMBOL(isac_irq); module_init(hisax_isac_init); diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h --- a/drivers/isdn/hisax/hisax_isac.h Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/hisax_isac.h Sat Mar 15 18:40:43 2003 @@ -36,7 +36,7 @@ void isac_init(struct isac *isac); void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); -void isac_setup(struct isac *isac); +void hisax_isac_setup(struct isac *isac); void isac_irq(struct isac *isac); void isacsx_setup(struct isac *isac); diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/isdnl1.c Sat Mar 15 18:40:40 2003 @@ -126,7 +126,7 @@ }; void -debugl1(struct IsdnCardState *cs, char *fmt, ...) +debugl1(struct IsdnCardState *cs, const char *fmt, ...) { va_list args; char tmp[8]; diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/isdnl1.h Sat Mar 15 18:40:43 2003 @@ -28,7 +28,7 @@ #define B_LL_CONNECT 9 #define B_LL_OK 10 -extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); +extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs); extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Sat Mar 15 18:40:42 2003 +++ b/drivers/isdn/hisax/isurf.c Sat Mar 15 18:40:42 2003 @@ -187,95 +187,92 @@ static struct pnp_card *pnp_surf __devinitdata = NULL; #endif -int __init -setup_isurf(struct IsdnCard *card) +static int __init +isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; unsigned long phymem; - char tmp[64]; - strcpy(tmp, ISurf_revision); - printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); - - if (card->para[1] && card->para[2]) { - cs->hw.isurf.reset = card->para[1]; - phymem = card->para[2]; - cs->irq = card->para[0]; - } else { -#ifdef __ISAPNP__ - struct pnp_card *pb; - struct pnp_dev *pd; + phymem = card->para[2]; + cs->hw.isurf.reset = card->para[1]; + cs->irq = card->para[0]; - if (isapnp_present()) { - cs->subtyp = 0; - if ((pb = pnp_find_card( - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pnp_surf))) { - pnp_surf = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_surf, - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pd))) { - printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); - return (0); - } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ISurfPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ISurfPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { - printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); - return(0); - } - cs->hw.isurf.reset = pnp_port_start(pd, 0); - phymem = pnp_port_start(pd, 1); - cs->irq = pnp_irq(pd, 0); - } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); - return(0); - } - } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n"); - return(0); - } -#else - printk(KERN_WARNING "HiSax: %s port/mem not set\n", - CardType[card->typ]); - return (0); -#endif - } if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) goto err; - cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, "isurf iomem"); + + cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, + "isurf iomem"); if (!cs->hw.isurf.isar) goto err; cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; - printk(KERN_INFO - "ISurf: defined at 0x%x 0x%lx IRQ %d\n", - cs->hw.isurf.reset, - card->para[2], - cs->irq); + printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", + cs->hw.isurf.reset, phymem, cs->irq); cs->auxcmd = &isurf_auxcmd; cs->card_ops = &isurf_ops; cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; reset_isurf(cs, ISURF_RESET); - test_and_set_bit(HW_ISAR, &cs->HW_Flags); + __set_bit(HW_ISAR, &cs->HW_Flags); isac_setup(cs, &isac_ops); if (isar_setup(cs, &isar_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} +int __init +setup_isurf(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, ISurf_revision); + printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); + +#ifdef __ISAPNP__ + if (!card->para[1] || !card->para[2]) { + struct pnp_card *pb; + struct pnp_dev *pd; + + cs->subtyp = 0; + if ((pb = pnp_find_card( + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_surf))) { + pnp_surf = pb; + pd = NULL; + if (!(pd = pnp_find_dev(pnp_surf, + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pd))) { + printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); + return (0); + } + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "ISurfPnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "ISurfPnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { + printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); + pnp_device_detach(pd); + return(0); + } + card->para[1] = pnp_port_start(pd, 0); + card->para[2] = pnp_port_start(pd, 1); + card->para[0] = pnp_irq(pd, 0); + } else { + printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); + return 0; + } + } +#endif + if (isurf_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/ix1_micro.c Sat Mar 15 18:40:44 2003 @@ -162,6 +162,29 @@ .irq_func = hscxisac_irq, }; +static int __init +ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; + cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; + cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; + cs->hw.ix1.cfg_reg = card->para[1]; + if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) + goto err; + + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); + ix1_reset(cs); + cs->card_ops = &ix1_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id itk_ids[] __initdata = { { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25), @@ -181,14 +204,18 @@ int __init setup_ix1micro(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ix1_revision); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); + if (card->para[1]) { + if (ix1_probe(card->cs, card)) + return 0; + return 1; + } #ifdef __ISAPNP__ - if (!card->para[1] && isapnp_present()) { + if (isapnp_present()) { struct pnp_card *pb; struct pnp_dev *pd; @@ -221,7 +248,9 @@ } card->para[1] = pnp_port_start(pd, 0); card->para[0] = pnp_irq(pd, 0); - break; + if (ix1_probe(card->cs, card)) + return 0; + return 1; } else { printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); } @@ -231,27 +260,8 @@ } if (!idev->card_vendor) { printk(KERN_INFO "ITK PnP: no ISAPnP card found\n"); - return(0); } } #endif - /* IO-Ports */ - cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; - cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; - cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; - cs->hw.ix1.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) - goto err; - - printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); - ix1_reset(cs); - cs->card_ops = &ix1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; - err: - hisax_release_resources(cs); return 0; } diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/mic.c Sat Mar 15 18:40:43 2003 @@ -138,17 +138,11 @@ .irq_func = hscxisac_irq, }; -int __init -setup_mic(struct IsdnCard *card) +static int __init +mic_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, mic_revision); - printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); - - cs->hw.mic.cfg_reg = card->para[1]; cs->irq = card->para[0]; + cs->hw.mic.cfg_reg = card->para[1]; cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; @@ -158,11 +152,25 @@ printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", cs->hw.mic.cfg_reg, cs->irq); + cs->card_ops = &mic_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} + +int __init +setup_mic(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, mic_revision); + printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); + + if (mic_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Sat Mar 15 18:40:41 2003 +++ b/drivers/isdn/hisax/niccy.c Sat Mar 15 18:40:41 2003 @@ -199,6 +199,70 @@ .irq_func = niccy_interrupt, }; +static int __init +niccy_probe(struct IsdnCardState *cs) +{ + printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", + CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", + cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); + cs->card_ops = &niccy_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -EBUSY; + return 0; +} + +static int __init +niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = NICCY_PNP; + cs->irq = card->para[0]; + cs->hw.niccy.isac = card->para[1] + ISAC_PNP; + cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; + cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; + cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; + cs->hw.niccy.cfg_reg = 0; + + if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) + goto err; + if (niccy_probe(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + u32 pci_ioaddr; + + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = NICCY_PCI; + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0); + pci_ioaddr = pci_resource_start(pdev, 1); + cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; + cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; + cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; + cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; + if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) + goto err; + if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) + goto err; + if (niccy_probe(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *niccy_dev __initdata = NULL; #ifdef __ISAPNP__ static struct pnp_card *pnp_c __devinitdata = NULL; @@ -207,7 +271,6 @@ int __init setup_niccy(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, niccy_revision); @@ -252,66 +315,18 @@ } #endif if (card->para[1]) { - cs->hw.niccy.isac = card->para[1] + ISAC_PNP; - cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; - cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; - cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; - cs->hw.niccy.cfg_reg = 0; - cs->subtyp = NICCY_PNP; - cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) - goto err; + if (niccy_pnp_probe(card->cs, card) < 0) + return 0; + return 1; } else { #if CONFIG_PCI - u_int pci_ioaddr; - cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { - if (pci_enable_device(niccy_dev)) - return(0); - /* get IRQ */ - if (!niccy_dev->irq) { - printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); - return(0); - } - cs->irq = niccy_dev->irq; - cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0); - if (!cs->hw.niccy.cfg_reg) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); - return(0); - } - pci_ioaddr = pci_resource_start(niccy_dev, 1); - if (!pci_ioaddr) { - printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); - return(0); - } - cs->subtyp = NICCY_PCI; - } else { - printk(KERN_WARNING "Niccy: No PCI card found\n"); - return(0); + if (niccy_pci_probe(card->cs, niccy_dev) < 0) + return 0; + return 1; } - cs->irq_flags |= SA_SHIRQ; - cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; - cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; - cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; - cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - - if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) - goto err; #endif /* CONFIG_PCI */ } - printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", - CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", - cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - cs->card_ops = &niccy_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; - err: - niccy_release(cs); return 0; } diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/nj_s.c Sat Mar 15 18:40:40 2003 @@ -106,96 +106,99 @@ .irq_func = nj_s_interrupt, }; +static int __init +nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.pdev = pdev; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.auxa, 0); + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) { + case 0 : + break; + case 3 : + printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); + goto err; + default : + printk(KERN_WARNING "NETjet-S: No PCI card found\n" ); + goto err; + } + printk(KERN_INFO + "NETjet-S: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + + nj_s_reset(cs); + cs->irq_flags |= SA_SHIRQ; + cs->card_ops = &nj_s_ops; + isac_setup(cs, &netjet_dc_ops); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_s(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_S_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", + HiSax_getrev(tmp)); - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - pci_set_master(dev_netjet); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n"); - return(0); - } - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ - if ((dev_netjet->subsystem_vendor == 0x55) && - (dev_netjet->subsystem_device == 0x02)) { - printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n"); - return(0); - } - /* end new code */ - cs->hw.njet.pdev = dev_netjet; - } else { - printk(KERN_WARNING "NETjet-S: No PCI card found\n"); - return(0); + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ + if (dev_netjet->subsystem_vendor == 0x55 && + dev_netjet->subsystem_device == 0x02) { + printk(KERN_WARNING "Netjet: You tried to load this " + "driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=41 for Formula-n " + "enter:now ISDN PCI and compatible\n"); + return 0; } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) - { - case 0 : - break; - - case 3 : - printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); - continue; - - default : - printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); - return 0; - } - break; - } - printk(KERN_INFO - "NETjet-S: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) + if (nj_s_probe(card->cs, dev_netjet)) + return 1; return 0; - - nj_s_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_s_ops; - isac_setup(cs, &netjet_dc_ops); - return 1; + } + printk(KERN_WARNING "NETjet-S: No PCI card found\n"); + return 0; } + diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/nj_u.c Sat Mar 15 18:40:40 2003 @@ -110,88 +110,85 @@ .irq_func = nj_u_interrupt, }; +static int __init +nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + pci_set_master(pdev); + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.njet.pdev = pdev; + cs->hw.njet.base = pci_resource_start(pdev, 0); + if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn")) + goto err; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3) { + case 3: + break; + case 0: + printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); + goto err; + default: + printk(KERN_WARNING "NETspider-U: No PCI card found\n" ); + goto err; + } + printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + + nj_u_reset(cs); + cs->card_ops = &nj_u_ops; + icc_setup(cs, &netjet_dc_ops); + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_netjet __initdata = NULL; int __init setup_netjet_u(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_U_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); - - for ( ;; ) { - if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { - if (pci_enable_device(dev_netjet)) - return(0); - pci_set_master(dev_netjet); - cs->irq = dev_netjet->irq; - if (!cs->irq) { - printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.njet.base = pci_resource_start(dev_netjet, 0); - if (!cs->hw.njet.base) { - printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n"); - return(0); - } - cs->hw.njet.pdev = dev_netjet; - } else { - printk(KERN_WARNING "NETspider-U: No PCI card found\n"); - return(0); - } - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.auxa, 0); - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) ) - { - case 3 : - break; - - case 0 : - printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); - continue; - - default : - printk( KERN_WARNING "NETspider-U: No PCI card found\n" ); - return 0; - } - break; - } - printk(KERN_INFO - "NETspider-U: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) - return 0; + printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", + HiSax_getrev(tmp)); - nj_u_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_u_ops; - icc_setup(cs, &netjet_dc_ops); - return 1; + dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet); + if (dev_netjet) { + if (nj_u_probe(card->cs, dev_netjet)) + return 1; + return 0; + } + printk(KERN_WARNING "NETspider-U: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hisax/s0box.c Sat Mar 15 18:40:39 2003 @@ -172,14 +172,9 @@ .irq_func = hscxisac_irq, }; -int __init -setup_s0box(struct IsdnCard *card) +static int __init +s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, s0box_revision); - printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[1] = 0x0; @@ -200,8 +195,20 @@ cs->card_ops = &s0box_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); - return 0; + return -EBUSY; +} + +int __init +setup_s0box(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, s0box_revision); + printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); + if (s0box_probe(card->cs, card)) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/hisax/saphir.c Sat Mar 15 18:40:39 2003 @@ -201,36 +201,21 @@ .irq_func = saphir_interrupt, }; -int __init -setup_saphir(struct IsdnCard *card) +static int __init +saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, saphir_rev); - printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ != ISDN_CTYPE_HSTSAPHIR) - return (0); - - init_timer(&cs->hw.saphir.timer); - /* IO-Ports */ cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->irq = card->para[0]; + if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) goto err; - printk(KERN_INFO - "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.saphir.cfg_reg); + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); - cs->hw.saphir.timer.function = (void *) SaphirWatchDog; - cs->hw.saphir.timer.data = (long) cs; - cs->hw.saphir.timer.expires = jiffies + 4*HZ; - add_timer(&cs->hw.saphir.timer); if (saphir_reset(cs)) goto err; @@ -238,8 +223,27 @@ if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; - err: - saphir_release(cs); + init_timer(&cs->hw.saphir.timer); + cs->hw.saphir.timer.function = (void *) SaphirWatchDog; + cs->hw.saphir.timer.data = (long) cs; + cs->hw.saphir.timer.expires = jiffies + 4*HZ; + add_timer(&cs->hw.saphir.timer); return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_saphir(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, saphir_rev); + printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (saphir_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/sedlbauer.c Sat Mar 15 18:40:44 2003 @@ -73,7 +73,6 @@ #define SEDL_SPEEDFAX_PYRAMID 7 #define SEDL_SPEEDFAX_PCI 8 -#define SEDL_CHIP_TEST 0 #define SEDL_CHIP_ISAC_HSCX 1 #define SEDL_CHIP_ISAC_ISAR 2 #define SEDL_CHIP_IPAC 3 @@ -452,6 +451,241 @@ .irq_func = sedlbauer_isar_interrupt, }; +static int __init +sedl_ipac_probe(struct IsdnCardState *cs) +{ + u8 val; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); + printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); + return (val == 1 || val == 2); +} + +static int __init +sedl_ipac_init(struct IsdnCardState *cs) +{ + cs->card_ops = &sedlbauer_ipac_ops; + if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) + return -ENODEV; + sedlbauer_reset(cs); + return 0; +} + +static int __init +sedl_isac_isar_init(struct IsdnCardState *cs) +{ + cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; + cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; + __set_bit(HW_ISAR, &cs->HW_Flags); + cs->card_ops = &sedlbauer_isar_ops; + cs->auxcmd = &isar_auxcmd; + isac_setup(cs, &isac_ops); + return isar_setup(cs, &isar_ops); +} + +static int __init +sedl_isac_hscx_init(struct IsdnCardState *cs) +{ + cs->card_ops = &sedlbauer_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -ENODEV; + sedlbauer_reset(cs); + return 0; +} + +static int __init +sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.sedl.cfg_reg = card->para[1]; + cs->hw.sedl.bus = SEDL_BUS_ISA; + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn")) + goto err; + + if (sedl_ipac_probe(cs)) { + cs->subtyp = SEDL_SPEED_WIN2_PC104; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + if (sedl_ipac_init(cs)) + goto err; + } else { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; + if (sedl_isac_hscx_init(cs)) + goto err; + } + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.sedl.bus = SEDL_BUS_PCMCIA; + if (sedl_ipac_probe(cs)) { + cs->subtyp = SEDL_SPEED_STAR2; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + if (sedl_ipac_init(cs)) + goto err; + } else { + cs->subtyp = SEDL_SPEED_STAR; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + if (sedl_isac_hscx_init(cs)) + goto err; + } + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn")) + goto err; + + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq); + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0); + cs->hw.sedl.bus = SEDL_BUS_PCI; + + if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn")) + return -EBUSY; + + printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", + Sedlbauer_Types[cs->subtyp], + cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq); + + cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; + cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; + byteout(cs->hw.sedl.cfg_reg, 0xff); + byteout(cs->hw.sedl.cfg_reg, 0x00); + byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); + byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout((10*HZ)/1000); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + return 0; +} + +static int __init +sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEEDFAX_PYRAMID; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEEDFAX_PCI; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; + if (sedl_isac_isar_init(cs)) + goto err; + + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + if (pci_enable_device(pdev)) + goto err; + + cs->subtyp = SEDL_SPEED_PCI; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + if (sedl_pci_init(cs, pdev)) + goto err; + + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + if (sedl_ipac_init(cs)) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + static struct pci_dev *dev_sedl __devinitdata = NULL; #ifdef __ISAPNP__ @@ -472,265 +706,117 @@ int __devinit setup_sedlbauer(struct IsdnCard *card) { - int bytecnt, val; struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; strcpy(tmp, Sedlbauer_revision); - printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", + HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_SEDLBAUER) { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { - cs->subtyp = SEDL_SPEED_STAR; - cs->hw.sedl.bus = SEDL_BUS_PCMCIA; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - } else - return (0); - - bytecnt = 8; if (card->para[1]) { - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - bytecnt = 16; + if (cs->typ == ISDN_CTYPE_SEDLBAUER) { + if (sedl_card_win_probe(card->cs, card) < 0) + return 0; + return 1; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { + if (sedl_star_probe(card->cs, card) < 0) + return 0; + return 1; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { + if (sedl_fax_probe(card->cs, card) < 0) + return 0; + return 1; } - } else { + } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); - pnp_device_detach(pd); + if (isapnp_present()) { + struct pnp_card *pb; + struct pnp_dev *pd; + + while(pdev->card_vendor) { + if ((pb = pnp_find_card(pdev->card_vendor, + pdev->card_device, + pnp_c))) { + pnp_c = pb; + pd = NULL; + if ((pd = pnp_find_dev(pnp_c, + pdev->vendor, + pdev->function, + pd))) { + printk(KERN_INFO "HiSax: %s detected\n", + (char *)pdev->driver_data); + if (pnp_device_attach(pd) < 0) { + printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); + return 0; + } + if (pnp_activate_dev(pd) < 0) { + printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); + pnp_device_detach(pd); + return 0; + } + if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", + pnp_irq(pd, 0), pnp_port_start(pd, 0)); + pnp_device_detach(pd); + goto err; + } + card->para[1] = pnp_port_start(pd, 0); + card->para[0] = pnp_irq(pd, 0); + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (pdev->function == ISAPNP_FUNCTION(0x2)) { + if (sedl_fax_probe(card->cs, card)) return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - goto err; - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0x2)) { - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - bytecnt = 16; - } else { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.chip = SEDL_CHIP_TEST; - } - goto ready; + return 1; } else { - printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - goto err; + if (sedl_card_win_probe(card->cs, card)) + return 0; + return 1; } + } else { + printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); + goto err; } - pdev++; - pnp_c=NULL; - } - if (!pdev->card_vendor) { - printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } + pdev++; + pnp_c=NULL; + } + if (!pdev->card_vendor) { + printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } + } #endif /* Probe for Sedlbauer speed pci */ #if CONFIG_PCI - if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { - if (pci_enable_device(dev_sedl)) - goto err; - cs->irq = dev_sedl->irq; - if (!cs->irq) { - printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); - goto err; - } - cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); - } else { - printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); - goto err; - } - cs->irq_flags |= SA_SHIRQ; - cs->hw.sedl.bus = SEDL_BUS_PCI; + dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_100, dev_sedl); + if (dev_sedl) { sub_vendor_id = dev_sedl->subsystem_vendor; sub_id = dev_sedl->subsystem_device; printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", - sub_vendor_id, sub_id); - printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", - cs->hw.sedl.cfg_reg); + sub_vendor_id, sub_id); if (sub_id != PCI_SUB_ID_SEDLBAUER) { printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); - goto err; + return 0; } if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - cs->subtyp = SEDL_SPEEDFAX_PYRAMID; + if (sedl_fax_pyramid_probe(cs, dev_sedl)) + return 0; + return 1; } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - cs->subtyp = SEDL_SPEEDFAX_PCI; + if (sedl_fax_pci_probe(cs, dev_sedl)) + return 0; + return 1; } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->subtyp = SEDL_SPEED_PCI; - } else { - printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", - sub_vendor_id); - goto err; - } - bytecnt = 256; - cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; - cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; - byteout(cs->hw.sedl.cfg_reg, 0xff); - byteout(cs->hw.sedl.cfg_reg, 0x00); - byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); - byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); -#endif /* CONFIG_PCI */ - } -ready: - /* In case of the sedlbauer pcmcia card, this region is in use, - * reserved for us by the card manager. So we do not check it - * here, it would fail. - */ - if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA) { - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) - goto err; - } - - printk(KERN_INFO - "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", - cs->hw.sedl.cfg_reg, - cs->hw.sedl.cfg_reg + bytecnt, - cs->irq); - -/* - * testing ISA and PCMCIA Cards for IPAC, default is ISAC - * do not test for PCI card, because ports are different - * and PCI card uses only IPAC (for the moment) - */ - if (cs->hw.sedl.bus != SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, - IPAC_ID); - printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); - if ((val == 1) || (val == 2)) { - /* IPAC */ - cs->subtyp = SEDL_SPEED_WIN2_PC104; - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { - cs->subtyp = SEDL_SPEED_STAR2; - } - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - } else { - /* ISAC_HSCX oder ISAC_ISAR */ - if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - } - } - } - -/* - * hw.sedl.chip is now properly set - */ - printk(KERN_INFO "Sedlbauer: %s detected\n", - Sedlbauer_Types[cs->subtyp]); - - - if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { - if (cs->hw.sedl.bus == SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - } - cs->card_ops = &sedlbauer_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - sedlbauer_reset(cs); - } else { - /* ISAC_HSCX oder ISAC_ISAR */ - if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { - if (cs->hw.sedl.bus == SEDL_BUS_PCI) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + - SEDL_ISAR_PCI_ISAR; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + - SEDL_ISAR_ISA_ISAR_RESET_OFF; - } - cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; - cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; - test_and_set_bit(HW_ISAR, &cs->HW_Flags); - cs->card_ops = &sedlbauer_isar_ops; - cs->auxcmd = &isar_auxcmd; - isac_setup(cs, &isac_ops); - if (isar_setup(cs, &isar_ops)) - goto err; - } else { - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - } else { - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; - } - cs->card_ops = &sedlbauer_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - - sedlbauer_reset(cs); + if (sedl_pci_probe(cs, dev_sedl)) + return 0; + return 1; } + printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", + sub_vendor_id); + return 0; } - return 1; - err: - hisax_release_resources(cs); +#endif /* CONFIG_PCI */ return 0; } diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Sat Mar 15 18:40:40 2003 +++ b/drivers/isdn/hisax/sportster.c Sat Mar 15 18:40:40 2003 @@ -189,42 +189,29 @@ } return 0; } - -int __init -setup_sportster(struct IsdnCard *card) -{ - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, sportster_revision); - printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.spt.cfg_reg = card->para[1]; +static int __init +sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ cs->irq = card->para[0]; + cs->hw.spt.cfg_reg = card->para[1]; if (!get_io_range(cs)) - return (0); + return -EBUSY; cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC; cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA; cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB; switch(cs->irq) { - case 5: cs->hw.spt.res_irq = 1; - break; - case 7: cs->hw.spt.res_irq = 2; - break; - case 10:cs->hw.spt.res_irq = 3; - break; - case 11:cs->hw.spt.res_irq = 4; - break; - case 12:cs->hw.spt.res_irq = 5; - break; - case 14:cs->hw.spt.res_irq = 6; - break; - case 15:cs->hw.spt.res_irq = 7; - break; - default:sportster_release(cs); - printk(KERN_WARNING "Sportster: wrong IRQ\n"); - return(0); + case 5: cs->hw.spt.res_irq = 1; break; + case 7: cs->hw.spt.res_irq = 2; break; + case 10:cs->hw.spt.res_irq = 3; break; + case 11:cs->hw.spt.res_irq = 4; break; + case 12:cs->hw.spt.res_irq = 5; break; + case 14:cs->hw.spt.res_irq = 6; break; + case 15:cs->hw.spt.res_irq = 7; break; + default: + printk(KERN_WARNING "Sportster: wrong IRQ\n"); + goto err; } sportster_reset(cs); printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", @@ -234,8 +221,22 @@ cs->card_ops = &sportster_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; - err: - hisax_release_resources(cs); return 0; + err: + sportster_release(cs); + return -EBUSY; +} + +int __init +setup_sportster(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, sportster_revision); + printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (sportster_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Sat Mar 15 18:40:45 2003 +++ b/drivers/isdn/hisax/teleint.c Sat Mar 15 18:40:45 2003 @@ -256,15 +256,9 @@ .irq_func = teleint_interrupt, }; -int __init -setup_TeleInt(struct IsdnCard *card) +static int __init +teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, TeleInt_revision); - printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); - cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->irq = card->para[0]; cs->hw.hfc.cirm = HFC_CIRM; @@ -284,42 +278,54 @@ byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); switch (cs->irq) { - case 3: - cs->hw.hfc.cirm |= HFC_INTA; - break; - case 4: - cs->hw.hfc.cirm |= HFC_INTB; - break; - case 5: - cs->hw.hfc.cirm |= HFC_INTC; - break; - case 7: - cs->hw.hfc.cirm |= HFC_INTD; - break; - case 10: - cs->hw.hfc.cirm |= HFC_INTE; - break; - case 11: - cs->hw.hfc.cirm |= HFC_INTF; - break; - default: - printk(KERN_WARNING "TeleInt: wrong IRQ\n"); - goto err; + case 3: + cs->hw.hfc.cirm |= HFC_INTA; + break; + case 4: + cs->hw.hfc.cirm |= HFC_INTB; + break; + case 5: + cs->hw.hfc.cirm |= HFC_INTC; + break; + case 7: + cs->hw.hfc.cirm |= HFC_INTD; + break; + case 10: + cs->hw.hfc.cirm |= HFC_INTE; + break; + case 11: + cs->hw.hfc.cirm |= HFC_INTF; + break; + default: + printk(KERN_WARNING "TeleInt: wrong IRQ\n"); + goto err; } byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); - printk(KERN_INFO - "TeleInt: defined at 0x%x IRQ %d\n", - cs->hw.hfc.addr, - cs->irq); + printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n", + cs->hw.hfc.addr, cs->irq); cs->card_ops = &teleint_ops; teleint_reset(cs); isac_setup(cs, &isac_ops); hfc_setup(cs, &hfc_ops); - return 1; - err: - teleint_release(cs); return 0; + + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_TeleInt(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, TeleInt_revision); + printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + + if (teleint_probe(card->cs, card) < 0) + return 0; + return 1; } diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Sat Mar 15 18:40:42 2003 +++ b/drivers/isdn/hisax/teles0.c Sat Mar 15 18:40:42 2003 @@ -165,72 +165,95 @@ .irq_func = hscxisac_irq, }; -int __init -setup_teles0(struct IsdnCard *card) +static int __init +teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card) { - u8 val; - struct IsdnCardState *cs = card->cs; - char tmp[64]; - - strcpy(tmp, teles0_revision); - printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp)); - if (cs->typ == ISDN_CTYPE_16_0) - cs->hw.teles0.cfg_reg = card->para[2]; - else /* 8.0 */ - cs->hw.teles0.cfg_reg = 0; - - if (card->para[1] < 0x10000) { - card->para[1] <<= 4; - printk(KERN_INFO - "Teles0: membase configured DOSish, assuming 0x%lx\n", - (unsigned long) card->para[1]); - } cs->irq = card->para[0]; - if (cs->hw.teles0.cfg_reg) { - if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) - goto err; - - if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 1, val); - goto err; - } - val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - */ - if (val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 2, val); - goto err; - } - } /* 16.0 and 8.0 designed for IOM1 */ test_and_set_bit(HW_IOM1, &cs->HW_Flags); cs->hw.teles0.phymem = card->para[1]; - cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem"); + cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, + TELES_IOMEM_SIZE, "teles iomem"); if (!cs->hw.teles0.membase) - goto err; + return -EBUSY; - printk(KERN_INFO - "HiSax: %s config irq:%d mem:0x%p cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); if (teles0_reset(cs)) { printk(KERN_WARNING "Teles0: wrong IRQ\n"); - goto err; + return -EBUSY; } cs->card_ops = &teles0_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 1; + return -EBUSY; + return 0; +} + +static int __init +teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->hw.teles0.cfg_reg = card->para[2]; + if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) + goto err; + + if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 0, val); + goto err; + } + if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 1, val); + goto err; + } + val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + */ + if (val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 2, val); + goto err; + } + if (teles0_probe(cs, card) < 0) + goto err; + + return 0; err: hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles0.cfg_reg = 0; + + if (teles0_probe(cs, card) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +int __init +setup_teles0(struct IsdnCard *card) +{ + char tmp[64]; + + strcpy(tmp, teles0_revision); + printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", + HiSax_getrev(tmp)); + + if (card->cs->typ == ISDN_CTYPE_16_0) { + if (teles16_0_probe(card->cs, card) < 0) + return 0; + } else { + if (teles8_0_probe(card->cs, card) < 0) + return 0; + } + return 1; } diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Sat Mar 15 18:40:45 2003 +++ b/drivers/isdn/hisax/teles3.c Sat Mar 15 18:40:45 2003 @@ -176,6 +176,152 @@ .irq_func = hscxisac_irq, }; +static int +teles_hw_init(struct IsdnCardState *cs) +{ + + printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); + printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n", + cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + + if (teles3_reset(cs)) { + printk(KERN_WARNING "Teles3: wrong IRQ\n"); + return -EBUSY; + } + cs->card_ops = &teles3_ops; + if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) + return -EBUSY; + return 0; +} + +static void __init +teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->irq = card->para[0]; + cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; + cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; + cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; +} + +static int __init +telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.hscx[0] = card->para[1] - 0x20; + cs->hw.teles3.hscx[1] = card->para[1]; + cs->hw.teles3.isac = card->para[1] + 0x20; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, + "HiSax Teles PCMCIA")) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +teles_request_io(struct IsdnCardState *cs) +{ + if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) + return -EBUSY; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A")) + return -EBUSY; + if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B")) + return -EBUSY; + return 0; +} + +static int __init +teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + u8 val; + + cs->hw.teles3.cfg_reg = card->para[1]; + switch (cs->hw.teles3.cfg_reg) { + case 0x180: + case 0x280: + case 0x380: + cs->hw.teles3.cfg_reg |= 0xc00; + break; + } + cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; + cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; + cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) + goto err; + if (teles_request_io(cs) < 0) + goto err; + if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 0, val); + goto err; + } + if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 1, val); + goto err; + } + /* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???, + * 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */ + val = bytein(cs->hw.teles3.cfg_reg + 2); + if (val != 0x46 && val != 0x39 && val != 0x38 && + val != 0x1c && val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 2, val); + goto err; + } + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = card->para[3]; + cs->hw.teles3.isac = card->para[2] - 32; + cs->hw.teles3.hscx[0] = card->para[1] - 32; + cs->hw.teles3.hscx[1] = card->para[1]; + teles_setup_io(cs, card); + if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) + goto err; + if (teles_request_io(cs) < 0) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + +static int __init +telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +{ + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.isac = card->para[1] - 32; + cs->hw.teles3.hscx[0] = card->para[2] - 32; + cs->hw.teles3.hscx[1] = card->para[2]; + teles_setup_io(cs, card); + if (teles_request_io(cs) < 0) + goto err; + if (teles_hw_init(cs) < 0) + goto err; + return 0; + err: + hisax_release_resources(cs); + return -EBUSY; +} + #ifdef __ISAPNP__ static struct isapnp_device_id teles_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), @@ -197,16 +343,10 @@ int __devinit setup_teles3(struct IsdnCard *card) { - u8 val; - struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles3_revision); printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp)); - if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP) - && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) - return (0); - #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { struct pnp_card *pnp_card; @@ -258,100 +398,18 @@ } } #endif - if (cs->typ == ISDN_CTYPE_16_3) { - cs->hw.teles3.cfg_reg = card->para[1]; - switch (cs->hw.teles3.cfg_reg) { - case 0x180: - case 0x280: - case 0x380: - cs->hw.teles3.cfg_reg |= 0xc00; - break; - } - cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; - cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; - cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; - } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.hscx[0] = card->para[1] - 0x20; - cs->hw.teles3.hscx[1] = card->para[1]; - cs->hw.teles3.isac = card->para[1] + 0x20; - } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - cs->hw.teles3.cfg_reg = card->para[3]; - cs->hw.teles3.isac = card->para[2] - 32; - cs->hw.teles3.hscx[0] = card->para[1] - 32; - cs->hw.teles3.hscx[1] = card->para[1]; + if (card->cs->typ == ISDN_CTYPE_16_3) { + if (teles16_3_probe(card->cs, card) < 0) + return 0; + } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) { + if (telespcmcia_probe(card->cs, card) < 0) + return 0; + } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + if (compaq_probe(card->cs, card) < 0) + return 0; } else { /* PNP */ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.isac = card->para[1] - 32; - cs->hw.teles3.hscx[0] = card->para[2] - 32; - cs->hw.teles3.hscx[1] = card->para[2]; - } - cs->irq = card->para[0]; - cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; - cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; - cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; - if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) - goto err; - } else { - if (cs->hw.teles3.cfg_reg) { - if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) - goto err; - } else { - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) - goto err; - } - } - if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) - goto err; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) - goto err; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) - goto err; - } - if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { - if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 1, val); - goto err; - } - val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - * 0x39 16.3 1.1 - * 0x38 16.3 1.3 - * 0x46 16.3 with AB + Video (Teles-Vision) - */ - if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 2, val); - goto err; - } - } - printk(KERN_INFO - "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); - printk(KERN_INFO - "HiSax: hscx A:0x%X hscx B:0x%X\n", - cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); - - if (teles3_reset(cs)) { - printk(KERN_WARNING "Teles3: wrong IRQ\n"); - goto err; + if (telespnp_probe(card->cs, card) < 0) + return 0; } - cs->card_ops = &teles3_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; return 1; - err: - hisax_release_resources(cs); - return 0; - } diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/hisax/telespci.c Sat Mar 15 18:40:43 2003 @@ -231,36 +231,23 @@ .irq_func = telespci_interrupt, }; -static struct pci_dev *dev_tel __initdata = NULL; - -int __init -setup_telespci(struct IsdnCard *card) +static int __init +telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) { - struct IsdnCardState *cs = card->cs; - char tmp[64]; + int rc; -#ifdef __BIG_ENDIAN -#error "not running on big endian machines now" -#endif - strcpy(tmp, telespci_revision); - printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); - if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { - if (pci_enable_device(dev_tel)) - return(0); - cs->irq = dev_tel->irq; - if (!cs->irq) { - printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); - return(0); - } - cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(dev_tel, 0), 4096, "telespci"); - if (!cs->hw.teles0.membase) - goto err; - printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", - pci_resource_start(dev_tel, 0), dev_tel->irq); - } else { - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return(0); - } + printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n", + pci_resource_start(pdev, 0), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci"); + if (!cs->hw.teles0.membase) + goto err; /* Initialize Zoran PCI controller */ writel(0x00000000, cs->hw.teles0.membase + 0x28); @@ -270,17 +257,36 @@ writel(0x70000000, cs->hw.teles0.membase + 0x3C); writel(0x61000000, cs->hw.teles0.membase + 0x40); /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ - printk(KERN_INFO - "HiSax: %s config irq:%d mem:%p\n", - CardType[cs->typ], cs->irq, - cs->hw.teles0.membase); - cs->irq_flags |= SA_SHIRQ; cs->card_ops = &telespci_ops; if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) goto err; - return 1; + return 0; err: hisax_release_resources(cs); + return rc; +} + +static struct pci_dev *dev_tel __initdata = NULL; + +int __init +setup_telespci(struct IsdnCard *card) +{ + char tmp[64]; + +#ifdef __BIG_ENDIAN +#error "not running on big endian machines now" +#endif + strcpy(tmp, telespci_revision); + printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", + HiSax_getrev(tmp)); + dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, + PCI_DEVICE_ID_ZORAN_36120, dev_tel); + if (dev_tel) { + if (telespci_probe(card->cs, dev_tel) < 0) + return 0; + return 1; + } + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); return 0; } diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Sat Mar 15 18:40:44 2003 +++ b/drivers/isdn/hisax/w6692.c Sat Mar 15 18:40:44 2003 @@ -669,11 +669,11 @@ static struct pci_dev *dev_w6692 __initdata = NULL; static int -w6692_setup(struct IsdnCardState *cs, struct dc_hw_ops *dc_ops, - struct bc_hw_ops *bc_ops) +w6692_hw_init(struct IsdnCardState *cs) { - cs->dc_hw_ops = dc_ops; - cs->bc_hw_ops = bc_ops; + cs->card_ops = &w6692_ops; + cs->dc_hw_ops = &w6692_dc_hw_ops, + cs->bc_hw_ops = &w6692_bc_hw_ops; dc_l1_init(cs, &w6692_dc_l1_ops); cs->bc_l1_ops = &w6692_bc_l1_ops; W6692Version(cs, "W6692:"); @@ -685,14 +685,45 @@ return 0; } +static int __init +w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +{ + int rc; + + printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n", + id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, + pci_resource_start(pdev, 1), pdev->irq); + + rc = -EBUSY; + if (pci_enable_device(pdev)) + goto err; + + /* USR ISDN PCI card TA need some special handling */ + if (cs->subtyp == W6692_WINBOND) { + if (pdev->subsystem_vendor == W6692_SV_USR && + pdev->subsystem_device == W6692_SD_USR) { + cs->subtyp = W6692_USR; + } + } + cs->irq = pdev->irq; + cs->irq_flags |= SA_SHIRQ; + cs->hw.w6692.iobase = pci_resource_start(pdev, 1); + + if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, + id_list[cs->subtyp].card_name)) + goto err; + + w6692_hw_init(cs); + return 0; + err: + hisax_release_resources(cs); + return rc; +} + int __init setup_w6692(struct IsdnCard *card) { - struct IsdnCardState *cs = card->cs; char tmp[64]; - u8 found = 0; - u8 pci_irq = 0; - u_int pci_ioaddr = 0; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" @@ -704,54 +735,13 @@ id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { - if (pci_enable_device(dev_w6692)) - continue; - cs->subtyp = id_idx; - break; + card->cs->subtyp = id_idx; + if (w6692_probe(card->cs, dev_w6692) < 0) + return 0; + return 1; } id_idx++; } - if (dev_w6692) { - found = 1; - pci_irq = dev_w6692->irq; - /* I think address 0 is allways the configuration area */ - /* and address 1 is the real IO space KKe 03.09.99 */ - pci_ioaddr = pci_resource_start(dev_w6692, 1); - /* USR ISDN PCI card TA need some special handling */ - if (cs->subtyp == W6692_WINBOND) { - if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && - (W6692_SD_USR == dev_w6692->subsystem_device)) { - cs->subtyp = W6692_USR; - } - } - } - if (!found) { - printk(KERN_WARNING "W6692: No PCI card found\n"); - return (0); - } - cs->irq = pci_irq; - if (!cs->irq) { - printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); - return (0); - } - if (!pci_ioaddr) { - printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); - return (0); - } - cs->hw.w6692.iobase = pci_ioaddr; - printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", - id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, - pci_ioaddr, pci_irq); - if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, id_list[cs->subtyp].card_name)) - return 0; - - printk(KERN_INFO - "HiSax: %s config irq:%d I/O:%x\n", - id_list[cs->subtyp].card_name, cs->irq, - cs->hw.w6692.iobase); - - cs->card_ops = &w6692_ops; - w6692_setup(cs, &w6692_dc_hw_ops, &w6692_bc_hw_ops); - cs->irq_flags |= SA_SHIRQ; - return (1); + printk(KERN_WARNING "W6692: No PCI card found\n"); + return 0; } diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig --- a/drivers/isdn/i4l/Kconfig Sat Mar 15 18:40:41 2003 +++ b/drivers/isdn/i4l/Kconfig Sat Mar 15 18:40:41 2003 @@ -85,7 +85,7 @@ config ISDN_X25 bool "X.25 PLP on top of ISDN" - depends on X25 + depends on X25 && BROKEN help This feature provides the X.25 protocol over ISDN connections. See for more information diff -Nru a/drivers/isdn/i4l/isdn_net_lib.c b/drivers/isdn/i4l/isdn_net_lib.c --- a/drivers/isdn/i4l/isdn_net_lib.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/i4l/isdn_net_lib.c Sat Mar 15 18:40:39 2003 @@ -58,6 +58,7 @@ #include "isdn_net.h" #include "isdn_ppp.h" #include "isdn_ciscohdlck.h" +#include "isdn_concap.h" #define ISDN_NET_TX_TIMEOUT (20*HZ) diff -Nru a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c --- a/drivers/isdn/i4l/isdn_ppp.c Sat Mar 15 18:40:43 2003 +++ b/drivers/isdn/i4l/isdn_ppp.c Sat Mar 15 18:40:43 2003 @@ -867,7 +867,7 @@ skb_pull(skb, 1); } else { if (skb->len < 2) - return -1; + return -EINVAL; get_u16(skb->data, proto); skb_pull(skb, 2); } @@ -1037,7 +1037,7 @@ isdn_ppp_frame_log("xmit1", skb->data, skb->len, 32, ipppd->unit, -1); ippp_push_proto(ind_ppp, skb, proto); - ippp_mp_xmit(idev, skb, proto); + ippp_mp_xmit(idev, skb); return 0; drop: diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.c b/drivers/isdn/i4l/isdn_ppp_mp.c --- a/drivers/isdn/i4l/isdn_ppp_mp.c Sat Mar 15 18:40:39 2003 +++ b/drivers/isdn/i4l/isdn_ppp_mp.c Sat Mar 15 18:40:39 2003 @@ -91,12 +91,13 @@ } void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) +ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) { struct ind_ppp *ind_ppp = idev->ind_priv; struct inl_ppp *inl_ppp = idev->mlp->inl_priv; unsigned char *p; - long txseq; + u32 txseq; + u16 proto; if (!(inl_ppp->mp_cfg & SC_MP_PROT)) { return ippp_xmit(idev, skb); diff -Nru a/drivers/isdn/i4l/isdn_ppp_mp.h b/drivers/isdn/i4l/isdn_ppp_mp.h --- a/drivers/isdn/i4l/isdn_ppp_mp.h Sat Mar 15 18:40:45 2003 +++ b/drivers/isdn/i4l/isdn_ppp_mp.h Sat Mar 15 18:40:45 2003 @@ -19,7 +19,7 @@ int ippp_mp_bind(isdn_net_dev *idev); void ippp_mp_disconnected(isdn_net_dev *idev); int ippp_mp_bundle(isdn_net_dev *idev, int val); -void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); +void ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb); void ippp_mp_receive(isdn_net_dev *idev, struct sk_buff *skb, u16 proto); #else @@ -42,9 +42,9 @@ } static inline void -ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb, u16 proto) +ippp_mp_xmit(isdn_net_dev *idev, struct sk_buff *skb) { - ippp_xmit(idev, skb, proto); + ippp_xmit(idev, skb); } static inline void diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c --- a/drivers/macintosh/macserial.c Sat Mar 15 18:40:44 2003 +++ b/drivers/macintosh/macserial.c Sat Mar 15 18:40:44 2003 @@ -3043,10 +3043,12 @@ /* * Register console. */ -void __init mac_scc_console_init(void) +static void __init mac_scc_console_init(void) { register_console(&sercons); } +console_initcall(mac_scc_console_init); + #endif /* ifdef CONFIG_SERIAL_CONSOLE */ #ifdef CONFIG_KGDB diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c --- a/drivers/md/dm.c Sat Mar 15 18:40:43 2003 +++ b/drivers/md/dm.c Sat Mar 15 18:40:43 2003 @@ -79,9 +79,8 @@ return -ENOMEM; _major = major; - r = register_blkdev(_major, _name, &dm_blk_dops); + r = register_blkdev(_major, _name); if (r < 0) { - DMERR("register_blkdev failed"); kmem_cache_destroy(_io_cache); return r; } diff -Nru a/drivers/md/linear.c b/drivers/md/linear.c --- a/drivers/md/linear.c Sat Mar 15 18:40:41 2003 +++ b/drivers/md/linear.c Sat Mar 15 18:40:41 2003 @@ -203,36 +203,34 @@ return 0; } bio->bi_bdev = tmp_dev->rdev->bdev; - bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1); + bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset; return 1; } -static int linear_status (char *page, mddev_t *mddev) +static void linear_status (struct seq_file *seq, mddev_t *mddev) { - int sz = 0; #undef MD_DEBUG #ifdef MD_DEBUG int j; linear_conf_t *conf = mddev_to_conf(mddev); - sz += sprintf(page+sz, " "); + seq_printf(seq, " "); for (j = 0; j < conf->nr_zones; j++) { - sz += sprintf(page+sz, "[%s", + seq_printf(seq, "[%s", bdev_partition_name(conf->hash_table[j].dev0->rdev->bdev)); if (conf->hash_table[j].dev1) - sz += sprintf(page+sz, "/%s] ", + seq_printf(seq, "/%s] ", bdev_partition_name(conf->hash_table[j].dev1->rdev->bdev)); else - sz += sprintf(page+sz, "] "); + seq_printf(seq, "] "); } - sz += sprintf(page+sz, "\n"); + seq_printf(seq, "\n"); #endif - sz += sprintf(page+sz, " %dk rounding", mddev->chunk_size/1024); - return sz; + seq_printf(seq, " %dk rounding", mddev->chunk_size/1024); } diff -Nru a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c Sat Mar 15 18:40:40 2003 +++ b/drivers/md/md.c Sat Mar 15 18:40:40 2003 @@ -124,9 +124,6 @@ { .ctl_name = 0 } }; -static void md_recover_arrays(void); -static mdk_thread_t *md_recovery_thread; - sector_t md_size[MAX_MD_DEVS]; static struct block_device_operations md_fops; @@ -222,6 +219,7 @@ init_MUTEX(&new->reconfig_sem); INIT_LIST_HEAD(&new->disks); INIT_LIST_HEAD(&new->all_mddevs); + init_timer(&new->safemode_timer); atomic_set(&new->active, 1); blk_queue_make_request(&new->queue, md_fail_request); @@ -272,40 +270,35 @@ return NULL; } -static sector_t calc_dev_sboffset(struct block_device *bdev) +inline static sector_t calc_dev_sboffset(struct block_device *bdev) { sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; return MD_NEW_SIZE_BLOCKS(size); } -static sector_t calc_dev_size(struct block_device *bdev, mddev_t *mddev) +static sector_t calc_dev_size(mdk_rdev_t *rdev, unsigned chunk_size) { sector_t size; - if (mddev->persistent) - size = calc_dev_sboffset(bdev); - else - size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; - if (mddev->chunk_size) - size &= ~((sector_t)mddev->chunk_size/1024 - 1); + size = rdev->sb_offset; + + if (chunk_size) + size &= ~((sector_t)chunk_size/1024 - 1); return size; } static sector_t zoned_raid_size(mddev_t *mddev) { - sector_t mask; mdk_rdev_t * rdev; struct list_head *tmp; /* * do size and offset calculations. */ - mask = ~((sector_t)mddev->chunk_size/1024 - 1); - ITERATE_RDEV(mddev,rdev,tmp) { - rdev->size &= mask; + ITERATE_RDEV(mddev,rdev,tmp) md_size[mdidx(mddev)] += rdev->size; - } + return 0; } @@ -389,7 +382,6 @@ static int read_disk_sb(mdk_rdev_t * rdev) { - sector_t sb_offset; if (!rdev->sb_page) { MD_BUG(); @@ -398,16 +390,8 @@ if (rdev->sb_loaded) return 0; - /* - * Calculate the position of the superblock, - * it's at the end of the disk. - * - * It also happens to be a multiple of 4Kb. - */ - sb_offset = calc_dev_sboffset(rdev->bdev); - rdev->sb_offset = sb_offset; - if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ)) + if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ)) goto fail; rdev->sb_loaded = 1; return 0; @@ -486,7 +470,7 @@ * We rely on user-space to write the initial superblock, and support * reading and updating of superblocks. * Interface methods are: - * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev) + * int load_super(mdk_rdev_t *dev, mdk_rdev_t *refdev, int minor_version) * loads and validates a superblock on dev. * if refdev != NULL, compare superblocks on both devices * Return: @@ -511,7 +495,7 @@ struct super_type { char *name; struct module *owner; - int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev); + int (*load_super)(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version); int (*validate_super)(mddev_t *mddev, mdk_rdev_t *rdev); void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev); }; @@ -519,10 +503,20 @@ /* * load_super for 0.90.0 */ -static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev) +static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) { mdp_super_t *sb; int ret; + sector_t sb_offset; + + /* + * Calculate the position of the superblock, + * it's at the end of the disk. + * + * It also happens to be a multiple of 4Kb. + */ + sb_offset = calc_dev_sboffset(rdev->bdev); + rdev->sb_offset = sb_offset; ret = read_disk_sb(rdev); if (ret) return ret; @@ -557,6 +551,12 @@ } rdev->preferred_minor = sb->md_minor; + rdev->data_offset = 0; + + if (sb->level == MULTIPATH) + rdev->desc_nr = -1; + else + rdev->desc_nr = sb->this_disk.number; if (refdev == 0) ret = 1; @@ -582,7 +582,7 @@ else ret = 0; } - + rdev->size = calc_dev_size(rdev, sb->chunk_size); abort: return ret; @@ -597,7 +597,7 @@ mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); if (mddev->raid_disks == 0) { - mddev->major_version = sb->major_version; + mddev->major_version = 0; mddev->minor_version = sb->minor_version; mddev->patch_version = sb->patch_version; mddev->persistent = ! sb->not_persistent; @@ -634,7 +634,6 @@ return -EINVAL; } if (mddev->level != LEVEL_MULTIPATH) { - rdev->desc_nr = sb->this_disk.number; rdev->raid_disk = -1; rdev->in_sync = rdev->faulty = 0; desc = sb->disks + rdev->desc_nr; @@ -704,10 +703,8 @@ sb->recovery_cp = mddev->recovery_cp; sb->cp_events_hi = (mddev->events>>32); sb->cp_events_lo = (u32)mddev->events; - if (mddev->recovery_cp == MaxSector) { - printk(KERN_INFO "md: marking sb clean...\n"); + if (mddev->recovery_cp == MaxSector) sb->state = (1<< MD_SB_CLEAN); - } } else sb->recovery_cp = 0; @@ -717,7 +714,7 @@ sb->disks[0].state = (1<raid_disk >= 0) + if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) rdev2->desc_nr = rdev2->raid_disk; else rdev2->desc_nr = next_spare++; @@ -726,7 +723,7 @@ d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0) + if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ @@ -766,6 +763,210 @@ sb->sb_csum = calc_sb_csum(sb); } +/* + * version 1 superblock + */ + +static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb) +{ + unsigned int disk_csum, csum; + int size = 256 + sb->max_dev*2; + + disk_csum = sb->sb_csum; + sb->sb_csum = 0; + csum = csum_partial((void *)sb, size, 0); + sb->sb_csum = disk_csum; + return csum; +} + +static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) +{ + struct mdp_superblock_1 *sb; + int ret; + sector_t sb_offset; + + /* + * Calculate the position of the superblock. + * It is always aligned to a 4K boundary and + * depeding on minor_version, it can be: + * 0: At least 8K, but less than 12K, from end of device + * 1: At start of device + * 2: 4K from start of device. + */ + switch(minor_version) { + case 0: + sb_offset = rdev->bdev->bd_inode->i_size >> 9; + sb_offset -= 8*2; + sb_offset &= ~(4*2); + /* convert from sectors to K */ + sb_offset /= 2; + break; + case 1: + sb_offset = 0; + break; + case 2: + sb_offset = 4; + break; + default: + return -EINVAL; + } + rdev->sb_offset = sb_offset; + + ret = read_disk_sb(rdev); + if (ret) return ret; + + + sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + if (sb->magic != cpu_to_le32(MD_SB_MAGIC) || + sb->major_version != cpu_to_le32(1) || + le32_to_cpu(sb->max_dev) > (4096-256)/2 || + le64_to_cpu(sb->super_offset) != (rdev->sb_offset<<1) || + sb->feature_map != 0) + return -EINVAL; + + if (calc_sb_1_csum(sb) != sb->sb_csum) { + printk(BAD_CSUM, bdev_partition_name(rdev->bdev)); + return -EINVAL; + } + rdev->preferred_minor = 0xffff; + rdev->data_offset = le64_to_cpu(sb->data_offset); + + if (refdev == 0) + return 1; + else { + __u64 ev1, ev2; + struct mdp_superblock_1 *refsb = + (struct mdp_superblock_1*)page_address(refdev->sb_page); + + if (memcmp(sb->set_uuid, refsb->set_uuid, 16) != 0 || + sb->level != refsb->level || + sb->layout != refsb->layout || + sb->chunksize != refsb->chunksize) { + printk(KERN_WARNING "md: %s has strangely different superblock to %s\n", + bdev_partition_name(rdev->bdev), + bdev_partition_name(refdev->bdev)); + return -EINVAL; + } + ev1 = le64_to_cpu(sb->events); + ev2 = le64_to_cpu(refsb->events); + + if (ev1 > ev2) + return 1; + } + if (minor_version) + rdev->size = ((rdev->bdev->bd_inode->i_size>>9) - le64_to_cpu(sb->data_offset)) / 2; + else + rdev->size = rdev->sb_offset; + if (rdev->size < le64_to_cpu(sb->data_size)/2) + return -EINVAL; + rdev->size = le64_to_cpu(sb->data_size)/2; + if (le32_to_cpu(sb->chunksize)) + rdev->size &= ~((sector_t)le32_to_cpu(sb->chunksize)/2 - 1); + return 0; +} + +static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) +{ + struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + if (mddev->raid_disks == 0) { + mddev->major_version = 1; + mddev->minor_version = 0; + mddev->patch_version = 0; + mddev->persistent = 1; + mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9; + mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); + mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); + mddev->level = le32_to_cpu(sb->level); + mddev->layout = le32_to_cpu(sb->layout); + mddev->raid_disks = le32_to_cpu(sb->raid_disks); + mddev->size = (u32)le64_to_cpu(sb->size); + mddev->events = le64_to_cpu(sb->events); + + mddev->recovery_cp = le64_to_cpu(sb->resync_offset); + memcpy(mddev->uuid, sb->set_uuid, 16); + + mddev->max_disks = (4096-256)/2; + } else { + __u64 ev1; + ev1 = le64_to_cpu(sb->events); + ++ev1; + if (ev1 < mddev->events) + return -EINVAL; + } + + if (mddev->level != LEVEL_MULTIPATH) { + int role; + rdev->desc_nr = le32_to_cpu(sb->dev_number); + role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); + switch(role) { + case 0xffff: /* spare */ + rdev->in_sync = 0; + rdev->faulty = 0; + rdev->raid_disk = -1; + break; + case 0xfffe: /* faulty */ + rdev->in_sync = 0; + rdev->faulty = 1; + rdev->raid_disk = -1; + break; + default: + rdev->in_sync = 1; + rdev->faulty = 0; + rdev->raid_disk = role; + break; + } + } + return 0; +} + +static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) +{ + struct mdp_superblock_1 *sb; + struct list_head *tmp; + mdk_rdev_t *rdev2; + int max_dev, i; + /* make rdev->sb match mddev and rdev data. */ + + sb = (struct mdp_superblock_1*)page_address(rdev->sb_page); + + sb->feature_map = 0; + sb->pad0 = 0; + memset(sb->pad1, 0, sizeof(sb->pad1)); + memset(sb->pad2, 0, sizeof(sb->pad2)); + memset(sb->pad3, 0, sizeof(sb->pad3)); + + sb->utime = cpu_to_le64((__u64)mddev->utime); + sb->events = cpu_to_le64(mddev->events); + if (mddev->in_sync) + sb->resync_offset = cpu_to_le64(mddev->recovery_cp); + else + sb->resync_offset = cpu_to_le64(0); + + max_dev = 0; + ITERATE_RDEV(mddev,rdev2,tmp) + if (rdev2->desc_nr > max_dev) + max_dev = rdev2->desc_nr; + + sb->max_dev = max_dev; + for (i=0; idev_roles[max_dev] = cpu_to_le16(0xfffe); + + ITERATE_RDEV(mddev,rdev2,tmp) { + i = rdev2->desc_nr; + if (rdev2->faulty) + sb->dev_roles[i] = cpu_to_le16(0xfffe); + else if (rdev2->in_sync) + sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); + else + sb->dev_roles[i] = cpu_to_le16(0xffff); + } + + sb->recovery_offset = cpu_to_le64(0); /* not supported yet */ +} + + struct super_type super_types[] = { [0] = { .name = "0.90.0", @@ -774,9 +975,14 @@ .validate_super = super_90_validate, .sync_super = super_90_sync, }, + [1] = { + .name = "md-1", + .owner = THIS_MODULE, + .load_super = super_1_load, + .validate_super = super_1_validate, + .sync_super = super_1_sync, + }, }; - - static mdk_rdev_t * match_dev_unit(mddev_t *mddev, mdk_rdev_t *dev) { @@ -804,13 +1010,13 @@ static LIST_HEAD(pending_raid_disks); -static void bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) +static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) { mdk_rdev_t *same_pdev; if (rdev->mddev) { MD_BUG(); - return; + return -EINVAL; } same_pdev = match_dev_unit(mddev, rdev); if (same_pdev) @@ -820,9 +1026,25 @@ mdidx(mddev), bdev_partition_name(rdev->bdev), bdev_partition_name(same_pdev->bdev)); + /* Verify rdev->desc_nr is unique. + * If it is -1, assign a free number, else + * check number is not in use + */ + if (rdev->desc_nr < 0) { + int choice = 0; + if (mddev->pers) choice = mddev->raid_disks; + while (find_rdev_nr(mddev, choice)) + choice++; + rdev->desc_nr = choice; + } else { + if (find_rdev_nr(mddev, rdev->desc_nr)) + return -EBUSY; + } + list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; printk(KERN_INFO "md: bind<%s>\n", bdev_partition_name(rdev->bdev)); + return 0; } static void unbind_rdev_from_array(mdk_rdev_t * rdev) @@ -910,6 +1132,7 @@ if (!list_empty(&mddev->disks)) MD_BUG(); mddev->raid_disks = 0; + mddev->major_version = 0; } #undef BAD_CSUM @@ -994,8 +1217,6 @@ static int write_disk_sb(mdk_rdev_t * rdev) { - sector_t sb_offset; - sector_t size; if (!rdev->sb_loaded) { MD_BUG(); @@ -1006,35 +1227,12 @@ return 1; } - sb_offset = calc_dev_sboffset(rdev->bdev); - if (rdev->sb_offset != sb_offset) { - printk(KERN_INFO "%s's sb offset has changed from %llu to %llu, skipping\n", - bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->sb_offset, - (unsigned long long)sb_offset); - goto skip; - } - /* - * If the disk went offline meanwhile and it's just a spare, then - * its size has changed to zero silently, and the MD code does - * not yet know that it's faulty. - */ - size = calc_dev_size(rdev->bdev, rdev->mddev); - if (size != rdev->size) { - printk(KERN_INFO "%s's size has changed from %llu to %llu since import, skipping\n", - bdev_partition_name(rdev->bdev), - (unsigned long long)rdev->size, - (unsigned long long)size); - goto skip; - } - - printk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), (unsigned long long)sb_offset); + dprintk(KERN_INFO "(write) %s's sb offset: %llu\n", bdev_partition_name(rdev->bdev), + (unsigned long long)rdev->sb_offset); + + if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE)) + return 0; - if (!sync_page_io(rdev->bdev, sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE)) - goto fail; -skip: - return 0; -fail: printk("md: write_disk_sb failed for device %s\n", bdev_partition_name(rdev->bdev)); return 1; } @@ -1045,7 +1243,8 @@ struct list_head *tmp; ITERATE_RDEV(mddev,rdev,tmp) { - super_90_sync(mddev, rdev); + super_types[mddev->major_version]. + sync_super(mddev, rdev); rdev->sb_loaded = 1; } } @@ -1079,20 +1278,20 @@ if (!mddev->persistent) return; - printk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n", + dprintk(KERN_INFO "md: updating md%d RAID superblock on device (in sync %d)\n", mdidx(mddev),mddev->in_sync); err = 0; ITERATE_RDEV(mddev,rdev,tmp) { - printk(KERN_INFO "md: "); + dprintk(KERN_INFO "md: "); if (rdev->faulty) - printk("(skipping faulty "); + dprintk("(skipping faulty "); - printk("%s ", bdev_partition_name(rdev->bdev)); + dprintk("%s ", bdev_partition_name(rdev->bdev)); if (!rdev->faulty) { err += write_disk_sb(rdev); } else - printk(")\n"); + dprintk(")\n"); if (!err && mddev->level == LEVEL_MULTIPATH) /* only need to write one superblock... */ break; @@ -1107,7 +1306,7 @@ } /* - * Import a device. If 'on_disk', then sanity check the superblock + * Import a device. If 'super_format' >= 0, then sanity check the superblock * * mark the device faulty if: * @@ -1116,7 +1315,7 @@ * * a faulty rdev _never_ has rdev->sb set. */ -static mdk_rdev_t *md_import_device(dev_t newdev, int on_disk) +static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_minor) { int err; mdk_rdev_t *rdev; @@ -1141,6 +1340,7 @@ rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; + rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; @@ -1152,8 +1352,9 @@ goto abort_free; } - if (on_disk) { - err = super_90_load(rdev, NULL); + if (super_format >= 0) { + err = super_types[super_format]. + load_super(rdev, NULL, super_minor); if (err == -EINVAL) { printk(KERN_WARNING "md: %s has invalid sb, not importing!\n", bdev_partition_name(rdev->bdev)); @@ -1206,7 +1407,8 @@ freshest = NULL; ITERATE_RDEV(mddev,rdev,tmp) - switch (super_90_load(rdev, freshest)) { + switch (super_types[mddev->major_version]. + load_super(rdev, freshest, mddev->minor_version)) { case 1: freshest = rdev; break; @@ -1218,12 +1420,14 @@ } - super_90_validate(mddev, freshest); + super_types[mddev->major_version]. + validate_super(mddev, freshest); i = 0; ITERATE_RDEV(mddev,rdev,tmp) { if (rdev != freshest) - if (super_90_validate(mddev, rdev)) { + if (super_types[mddev->major_version]. + validate_super(mddev, rdev)) { printk(KERN_WARNING "md: kicking non-fresh %s from array!\n", bdev_partition_name(rdev->bdev)); kick_rdev_from_array(rdev); @@ -1278,11 +1482,6 @@ ITERATE_RDEV(mddev,rdev,tmp) { if (rdev->faulty) continue; - if (rdev->size) { - MD_BUG(); - continue; - } - rdev->size = calc_dev_size(rdev->bdev, mddev); if (rdev->size < mddev->chunk_size / 1024) { printk(KERN_WARNING "md: Dev %s smaller than chunk_size: %lluk < %dk\n", @@ -1380,6 +1579,16 @@ return NULL; } +void md_wakeup_thread(mdk_thread_t *thread); + +static void md_safemode_timeout(unsigned long data) +{ + mddev_t *mddev = (mddev_t *) data; + + mddev->safemode = 1; + md_wakeup_thread(mddev->thread); +} + #define TOO_BIG_CHUNKSIZE KERN_ERR \ "too big chunk_size: %d > %d\n" @@ -1521,13 +1730,14 @@ } atomic_set(&mddev->writes_pending,0); mddev->safemode = 0; - if (mddev->pers->sync_request) - mddev->in_sync = 0; - else - mddev->in_sync = 1; + mddev->safemode_timer.function = md_safemode_timeout; + mddev->safemode_timer.data = (unsigned long) mddev; + mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ + mddev->in_sync = 1; md_update_sb(mddev); - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); set_capacity(disk, md_size[mdidx(mddev)]<<1); return (0); } @@ -1553,7 +1763,6 @@ goto out; mddev->safemode = 0; - mddev->in_sync = 0; md_update_sb(mddev); mddev->ro = 0; set_disk_ro(disk, 0); @@ -1563,7 +1772,8 @@ /* * Kick recovery or resync if necessary */ - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); err = 0; } else { printk(KERN_ERR "md: md%d has no personality assigned.\n", @@ -1593,12 +1803,13 @@ if (mddev->pers) { if (mddev->sync_thread) { - if (mddev->recovery_running > 0) - mddev->recovery_running = -1; + set_bit(MD_RECOVERY_INTR, &mddev->recovery); md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; } + del_timer_sync(&mddev->safemode_timer); + invalidate_device(mk_kdev(disk->major, disk->first_minor), 1); if (ro) { @@ -1699,7 +1910,7 @@ printk(KERN_INFO "md: considering %s ...\n", bdev_partition_name(rdev0->bdev)); INIT_LIST_HEAD(&candidates); ITERATE_RDEV_PENDING(rdev,tmp) - if (super_90_load(rdev, rdev0) >= 0) { + if (super_90_load(rdev, rdev0, 0) >= 0) { printk(KERN_INFO "md: adding %s ...\n", bdev_partition_name(rdev->bdev)); list_move(&rdev->same_set, &candidates); } @@ -1717,7 +1928,8 @@ if (mddev_lock(mddev)) printk(KERN_WARNING "md: md%d locked, cannot run\n", mdidx(mddev)); - else if (mddev->raid_disks || !list_empty(&mddev->disks)) { + else if (mddev->raid_disks || mddev->major_version + || !list_empty(&mddev->disks)) { printk(KERN_WARNING "md: md%d already running, cannot run %s\n", mdidx(mddev), bdev_partition_name(rdev0->bdev)); mddev_unlock(mddev); @@ -1725,7 +1937,8 @@ printk(KERN_INFO "md: created md%d\n", mdidx(mddev)); ITERATE_RDEV_GENERIC(candidates,rdev,tmp) { list_del_init(&rdev->same_set); - bind_rdev_to_array(rdev, mddev); + if (bind_rdev_to_array(rdev, mddev)) + export_rdev(rdev); } autorun_array(mddev); mddev_unlock(mddev); @@ -1778,7 +1991,7 @@ mdp_super_t *sb = NULL; mdk_rdev_t *start_rdev = NULL, *rdev; - start_rdev = md_import_device(startdev, 1); + start_rdev = md_import_device(startdev, 0, 0); if (IS_ERR(start_rdev)) { printk(KERN_WARNING "md: could not import %s!\n", partition_name(startdev)); return err; @@ -1812,7 +2025,7 @@ continue; if (dev == startdev) continue; - rdev = md_import_device(dev, 1); + rdev = md_import_device(dev, 0, 0); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: could not import %s, trying to run array nevertheless.\n", partition_name(dev)); @@ -1875,9 +2088,8 @@ } info.major_version = mddev->major_version; - info.major_version = mddev->major_version; info.minor_version = mddev->minor_version; - info.patch_version = mddev->patch_version; + info.patch_version = 1; info.ctime = mddev->ctime; info.level = mddev->level; info.size = mddev->size; @@ -1888,7 +2100,7 @@ info.utime = mddev->utime; info.state = 0; - if (mddev->recovery_cp == MaxSector) + if (mddev->in_sync) info.state = (1<major,info->minor); if (!mddev->raid_disks) { + int err; /* expecting a device which has a superblock */ - rdev = md_import_device(dev, 1); + rdev = md_import_device(dev, mddev->major_version, mddev->minor_version); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); return PTR_ERR(rdev); @@ -1957,7 +2169,8 @@ if (!list_empty(&mddev->disks)) { mdk_rdev_t *rdev0 = list_entry(mddev->disks.next, mdk_rdev_t, same_set); - int err = super_90_load(rdev, rdev0); + int err = super_types[mddev->major_version] + .load_super(rdev, rdev0, mddev->minor_version); if (err < 0) { printk(KERN_WARNING "md: %s has different UUID to %s\n", bdev_partition_name(rdev->bdev), bdev_partition_name(rdev0->bdev)); @@ -1965,12 +2178,52 @@ return -EINVAL; } } - bind_rdev_to_array(rdev, mddev); - return 0; + err = bind_rdev_to_array(rdev, mddev); + if (err) + export_rdev(rdev); + return err; + } + + /* + * add_new_disk can be used once the array is assembled + * to add "hot spares". They must already have a superblock + * written + */ + if (mddev->pers) { + int err; + if (!mddev->pers->hot_add_disk) { + printk(KERN_WARNING "md%d: personality does not support diskops!\n", + mdidx(mddev)); + return -EINVAL; + } + rdev = md_import_device(dev, mddev->major_version, + mddev->minor_version); + if (IS_ERR(rdev)) { + printk(KERN_WARNING "md: md_import_device returned %ld\n", PTR_ERR(rdev)); + return PTR_ERR(rdev); + } + rdev->in_sync = 0; /* just to be sure */ + rdev->raid_disk = -1; + err = bind_rdev_to_array(rdev, mddev); + if (err) + export_rdev(rdev); + if (mddev->thread) + md_wakeup_thread(mddev->thread); + return err; + } + + /* otherwise, add_new_disk is only allowed + * for major_version==0 superblocks + */ + if (mddev->major_version != 0) { + printk(KERN_WARNING "md%d: ADD_NEW_DISK not supported\n", + mdidx(mddev)); + return -EINVAL; } if (!(info->state & (1<in_sync = 0; - bind_rdev_to_array(rdev, mddev); + err = bind_rdev_to_array(rdev, mddev); + if (err) { + export_rdev(rdev); + return err; + } - if (!mddev->persistent) + if (!mddev->persistent) { printk(KERN_INFO "md: nonpersistent superblock ...\n"); + rdev->sb_offset = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; + } else + rdev->sb_offset = calc_dev_sboffset(rdev->bdev); + rdev->size = calc_dev_size(rdev, mddev->chunk_size); - size = calc_dev_size(rdev->bdev, mddev); - rdev->sb_offset = calc_dev_sboffset(rdev->bdev); - - if (!mddev->size || (mddev->size > size)) - mddev->size = size; + if (!mddev->size || (mddev->size > rdev->size)) + mddev->size = rdev->size; } return 0; @@ -2066,7 +2324,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) { - int i, err; + int err; unsigned int size; mdk_rdev_t *rdev; @@ -2076,19 +2334,26 @@ printk(KERN_INFO "md: trying to hot-add %s to md%d ... \n", partition_name(dev), mdidx(mddev)); + if (mddev->major_version != 0) { + printk(KERN_WARNING "md%d: HOT_ADD may only be used with version-0 superblocks.\n", + mdidx(mddev)); + return -EINVAL; + } if (!mddev->pers->hot_add_disk) { printk(KERN_WARNING "md%d: personality does not support diskops!\n", mdidx(mddev)); return -EINVAL; } - rdev = md_import_device (dev, 0); + rdev = md_import_device (dev, -1, 0); if (IS_ERR(rdev)) { printk(KERN_WARNING "md: error, md_import_device() returned %ld\n", PTR_ERR(rdev)); return -EINVAL; } - size = calc_dev_size(rdev->bdev, mddev); + rdev->sb_offset = calc_dev_sboffset(rdev->bdev); + size = calc_dev_size(rdev, mddev->chunk_size); + rdev->size = size; if (size < mddev->size) { printk(KERN_WARNING "md%d: disk size %llu blocks < array size %llu\n", @@ -2105,27 +2370,21 @@ goto abort_export; } rdev->in_sync = 0; + rdev->desc_nr = -1; bind_rdev_to_array(rdev, mddev); /* * The rest should better be atomic, we can have disk failures * noticed in interrupt contexts ... */ - rdev->size = size; - rdev->sb_offset = calc_dev_sboffset(rdev->bdev); - for (i = mddev->raid_disks; i < mddev->max_disks; i++) - if (find_rdev_nr(mddev,i)==NULL) - break; - - if (i == mddev->max_disks) { + if (rdev->desc_nr == mddev->max_disks) { printk(KERN_WARNING "md%d: can not hot-add to full array!\n", mdidx(mddev)); err = -EBUSY; goto abort_unbind_export; } - rdev->desc_nr = i; rdev->raid_disk = -1; md_update_sb(mddev); @@ -2134,7 +2393,8 @@ * Kick recovery, maybe this spare has to be added to the * array immediately. */ - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); return 0; @@ -2146,9 +2406,37 @@ return err; } +/* + * set_array_info is used two different ways + * The original usage is when creating a new array. + * In this usage, raid_disks is > = and it together with + * level, size, not_persistent,layout,chunksize determine the + * shape of the array. + * This will always create an array with a type-0.90.0 superblock. + * The newer usage is when assembling an array. + * In this case raid_disks will be 0, and the major_version field is + * use to determine which style super-blocks are to be found on the devices. + * The minor and patch _version numbers are also kept incase the + * super_block handler wishes to interpret them. + */ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info) { + if (info->raid_disks == 0) { + /* just setting version number for superblock loading */ + if (info->major_version < 0 || + info->major_version >= sizeof(super_types)/sizeof(super_types[0]) || + super_types[info->major_version].name == NULL) { + /* maybe try to auto-load a module? */ + printk(KERN_INFO "md: superblock version %d not known\n", + info->major_version); + return -EINVAL; + } + mddev->major_version = info->major_version; + mddev->minor_version = info->minor_version; + mddev->patch_version = info->patch_version; + return 0; + } mddev->major_version = MD_MAJOR_VERSION; mddev->minor_version = MD_MINOR_VERSION; mddev->patch_version = MD_PATCHLEVEL_VERSION; @@ -2169,6 +2457,7 @@ mddev->layout = info->layout; mddev->chunk_size = info->chunk_size; + mddev->max_disks = MD_SB_DISKS; /* @@ -2282,9 +2571,11 @@ err = -EBUSY; goto abort_unlock; } - if (arg) { + { mdu_array_info_t info; - if (copy_from_user(&info, (void*)arg, sizeof(info))) { + if (!arg) + memset(&info, 0, sizeof(info)); + else if (copy_from_user(&info, (void*)arg, sizeof(info))) { err = -EFAULT; goto abort_unlock; } @@ -2473,12 +2764,6 @@ .ioctl = md_ioctl, }; - -static inline void flush_curr_signals(void) -{ - flush_signals(current); -} - int md_thread(void * arg) { mdk_thread_t *thread = arg; @@ -2489,7 +2774,7 @@ * Detach thread */ - daemonize(thread->name); + daemonize(thread->name, mdidx(thread->mddev)); current->exit_signal = SIGCHLD; allow_signal(SIGKILL); @@ -2510,7 +2795,7 @@ complete(thread->event); while (thread->run) { - void (*run)(void *data); + void (*run)(mddev_t *); wait_event_interruptible(thread->wqueue, test_bit(THREAD_WAKEUP, &thread->flags)); @@ -2521,11 +2806,11 @@ run = thread->run; if (run) { - run(thread->data); + run(thread->mddev); blk_run_queues(); } if (signal_pending(current)) - flush_curr_signals(); + flush_signals(current); } complete(thread->event); return 0; @@ -2538,8 +2823,8 @@ wake_up(&thread->wqueue); } -mdk_thread_t *md_register_thread(void (*run) (void *), - void *data, const char *name) +mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, + const char *name) { mdk_thread_t *thread; int ret; @@ -2556,7 +2841,7 @@ init_completion(&event); thread->event = &event; thread->run = run; - thread->data = data; + thread->mddev = mddev; thread->name = name; ret = kernel_thread(md_thread, thread, 0); if (ret < 0) { @@ -2591,16 +2876,6 @@ kfree(thread); } -static void md_recover_arrays(void) -{ - if (!md_recovery_thread) { - MD_BUG(); - return; - } - md_wakeup_thread(md_recovery_thread); -} - - void md_error(mddev_t *mddev, mdk_rdev_t *rdev) { dprintk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", @@ -2618,33 +2893,34 @@ if (!mddev->pers->error_handler) return; mddev->pers->error_handler(mddev,rdev); - md_recover_arrays(); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); } -static int status_unused(char * page) +/* seq_file implementation /proc/mdstat */ + +static void status_unused(struct seq_file *seq) { - int sz = 0, i = 0; + int i = 0; mdk_rdev_t *rdev; struct list_head *tmp; - sz += sprintf(page + sz, "unused devices: "); + seq_printf(seq, "unused devices: "); ITERATE_RDEV_PENDING(rdev,tmp) { i++; - sz += sprintf(page + sz, "%s ", + seq_printf(seq, "%s ", bdev_partition_name(rdev->bdev)); } if (!i) - sz += sprintf(page + sz, ""); + seq_printf(seq, ""); - sz += sprintf(page + sz, "\n"); - return sz; + seq_printf(seq, "\n"); } -static int status_resync(char * page, mddev_t * mddev) +static void status_resync(struct seq_file *seq, mddev_t * mddev) { - int sz = 0; unsigned long max_blocks, resync, res, dt, db, rt; resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2; @@ -2655,21 +2931,22 @@ */ if (!max_blocks) { MD_BUG(); - return 0; + return; } res = (resync/1024)*1000/(max_blocks/1024 + 1); { int i, x = res/50, y = 20-x; - sz += sprintf(page + sz, "["); + seq_printf(seq, "["); for (i = 0; i < x; i++) - sz += sprintf(page + sz, "="); - sz += sprintf(page + sz, ">"); + seq_printf(seq, "="); + seq_printf(seq, ">"); for (i = 0; i < y; i++) - sz += sprintf(page + sz, "."); - sz += sprintf(page + sz, "] "); + seq_printf(seq, "."); + seq_printf(seq, "] "); } - sz += sprintf(page + sz, " %s =%3lu.%lu%% (%lu/%lu)", - (mddev->spares ? "recovery" : "resync"), + seq_printf(seq, " %s =%3lu.%lu%% (%lu/%lu)", + (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ? + "resync" : "recovery"), res/10, res % 10, resync, max_blocks); /* @@ -2686,44 +2963,110 @@ db = resync - (mddev->resync_mark_cnt/2); rt = (dt * ((max_blocks-resync) / (db/100+1)))/100; - sz += sprintf(page + sz, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); + seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6); + + seq_printf(seq, " speed=%ldK/sec", db/dt); +} + +static void *md_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct list_head *tmp; + loff_t l = *pos; + mddev_t *mddev; + + if (l > 0x10000) + return NULL; + if (!l--) + /* header */ + return (void*)1; + + spin_lock(&all_mddevs_lock); + list_for_each(tmp,&all_mddevs) + if (!l--) { + mddev = list_entry(tmp, mddev_t, all_mddevs); + mddev_get(mddev); + spin_unlock(&all_mddevs_lock); + return mddev; + } + spin_unlock(&all_mddevs_lock); + return (void*)2;/* tail */ +} + +static void *md_seq_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct list_head *tmp; + mddev_t *next_mddev, *mddev = v; + + ++*pos; + if (v == (void*)2) + return NULL; - sz += sprintf(page + sz, " speed=%ldK/sec", db/dt); + spin_lock(&all_mddevs_lock); + if (v == (void*)1) + tmp = all_mddevs.next; + else + tmp = mddev->all_mddevs.next; + if (tmp != &all_mddevs) + next_mddev = mddev_get(list_entry(tmp,mddev_t,all_mddevs)); + else { + next_mddev = (void*)2; + *pos = 0x10000; + } + spin_unlock(&all_mddevs_lock); - return sz; + if (v != (void*)1) + mddev_put(mddev); + return next_mddev; + +} + +static void md_seq_stop(struct seq_file *seq, void *v) +{ + mddev_t *mddev = v; + + if (mddev && v != (void*)1 && v != (void*)2) + mddev_put(mddev); } -static int md_status_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) +static int md_seq_show(struct seq_file *seq, void *v) { - int sz = 0, j; + mddev_t *mddev = v; sector_t size; - struct list_head *tmp, *tmp2; + struct list_head *tmp2; mdk_rdev_t *rdev; - mddev_t *mddev; + int i; - sz += sprintf(page + sz, "Personalities : "); - for (j = 0; j < MAX_PERSONALITY; j++) - if (pers[j]) - sz += sprintf(page+sz, "[%s] ", pers[j]->name); + if (v == (void*)1) { + seq_printf(seq, "Personalities : "); + for (i = 0; i < MAX_PERSONALITY; i++) + if (pers[i]) + seq_printf(seq, "[%s] ", pers[i]->name); - sz += sprintf(page+sz, "\n"); + seq_printf(seq, "\n"); + return 0; + } + if (v == (void*)2) { + status_unused(seq); + return 0; + } - ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) { - sz += sprintf(page + sz, "md%d : %sactive", mdidx(mddev), + if (mddev_lock(mddev)!=0) + return -EINTR; + if (mddev->pers || mddev->raid_disks || !list_empty(&mddev->disks)) { + seq_printf(seq, "md%d : %sactive", mdidx(mddev), mddev->pers ? "" : "in"); if (mddev->pers) { if (mddev->ro) - sz += sprintf(page + sz, " (read-only)"); - sz += sprintf(page + sz, " %s", mddev->pers->name); + seq_printf(seq, " (read-only)"); + seq_printf(seq, " %s", mddev->pers->name); } size = 0; ITERATE_RDEV(mddev,rdev,tmp2) { - sz += sprintf(page + sz, " %s[%d]", + seq_printf(seq, " %s[%d]", bdev_partition_name(rdev->bdev), rdev->desc_nr); if (rdev->faulty) { - sz += sprintf(page + sz, "(F)"); + seq_printf(seq, "(F)"); continue; } size += rdev->size; @@ -2731,34 +3074,50 @@ if (!list_empty(&mddev->disks)) { if (mddev->pers) - sz += sprintf(page + sz, "\n %llu blocks", + seq_printf(seq, "\n %llu blocks", (unsigned long long)md_size[mdidx(mddev)]); else - sz += sprintf(page + sz, "\n %llu blocks", (unsigned long long)size); + seq_printf(seq, "\n %llu blocks", (unsigned long long)size); } - if (!mddev->pers) { - sz += sprintf(page+sz, "\n"); - mddev_unlock(mddev); - continue; + if (mddev->pers) { + mddev->pers->status (seq, mddev); + seq_printf(seq, "\n "); + if (mddev->curr_resync > 2) + status_resync (seq, mddev); + else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) + seq_printf(seq, " resync=DELAYED"); } - sz += mddev->pers->status (page+sz, mddev); + seq_printf(seq, "\n"); + } + mddev_unlock(mddev); + + return 0; +} - sz += sprintf(page+sz, "\n "); - if (mddev->curr_resync > 2) - sz += status_resync (page+sz, mddev); - else if (mddev->curr_resync == 1 || mddev->curr_resync == 2) - sz += sprintf(page + sz, " resync=DELAYED"); +static struct seq_operations md_seq_ops = { + .start = md_seq_start, + .next = md_seq_next, + .stop = md_seq_stop, + .show = md_seq_show, +}; - sz += sprintf(page + sz, "\n"); - mddev_unlock(mddev); - } - sz += status_unused(page + sz); +static int md_seq_open(struct inode *inode, struct file *file) +{ + int error; - return sz; + error = seq_open(file, &md_seq_ops); + return error; } +static struct file_operations md_seq_fops = { + .open = md_seq_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + int register_md_personality(int pnum, mdk_personality_t *p) { if (pnum >= MAX_PERSONALITY) { @@ -2803,7 +3162,9 @@ idle = 1; ITERATE_RDEV(mddev,rdev,tmp) { struct gendisk *disk = rdev->bdev->bd_contains->bd_disk; - curr_events = disk->read_sectors + disk->write_sectors - disk->sync_io; + curr_events = disk_stat_read(disk, read_sectors) + + disk_stat_read(disk, write_sectors) - + disk->sync_io; if ((curr_events - rdev->last_events) > 32) { rdev->last_events = curr_events; idle = 0; @@ -2818,9 +3179,8 @@ atomic_sub(blocks, &mddev->recovery_active); wake_up(&mddev->recovery_wait); if (!ok) { - mddev->recovery_error = -EIO; - mddev->recovery_running = -1; - md_recover_arrays(); + set_bit(MD_RECOVERY_ERR, &mddev->recovery); + md_wakeup_thread(mddev->thread); // stop recovery, signal do_sync .... } } @@ -2828,40 +3188,49 @@ void md_write_start(mddev_t *mddev) { - if (mddev->safemode && !atomic_read(&mddev->writes_pending)) { + if (!atomic_read(&mddev->writes_pending)) { mddev_lock_uninterruptible(mddev); - atomic_inc(&mddev->writes_pending); if (mddev->in_sync) { mddev->in_sync = 0; + del_timer(&mddev->safemode_timer); md_update_sb(mddev); } + atomic_inc(&mddev->writes_pending); mddev_unlock(mddev); } else atomic_inc(&mddev->writes_pending); } -void md_write_end(mddev_t *mddev, mdk_thread_t *thread) +void md_write_end(mddev_t *mddev) { - if (atomic_dec_and_test(&mddev->writes_pending) && mddev->safemode) - md_wakeup_thread(thread); + if (atomic_dec_and_test(&mddev->writes_pending)) { + if (mddev->safemode == 2) + md_wakeup_thread(mddev->thread); + else + mod_timer(&mddev->safemode_timer, jiffies + mddev->safemode_delay); + } } + static inline void md_enter_safemode(mddev_t *mddev) { - mddev_lock_uninterruptible(mddev); - if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && !mddev->recovery_running) { + if (mddev->safemode && !atomic_read(&mddev->writes_pending) && + !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; md_update_sb(mddev); } mddev_unlock(mddev); + + if (mddev->safemode == 1) + mddev->safemode = 0; } void md_handle_safemode(mddev_t *mddev) { if (signal_pending(current)) { - printk(KERN_INFO "md: md%d in safe mode\n",mdidx(mddev)); - mddev->safemode= 1; - flush_curr_signals(); + printk(KERN_INFO "md: md%d in immediate safe mode\n",mdidx(mddev)); + mddev->safemode = 2; + flush_signals(current); } if (mddev->safemode) md_enter_safemode(mddev); @@ -2872,9 +3241,8 @@ #define SYNC_MARKS 10 #define SYNC_MARK_STEP (3*HZ) -static void md_do_sync(void *data) +static void md_do_sync(mddev_t *mddev) { - mddev_t *mddev = data; mddev_t *mddev2; unsigned int max_sectors, currspeed = 0, j, window, err; @@ -2885,7 +3253,7 @@ unsigned long last_check; /* just incase thread restarts... */ - if (mddev->recovery_running <= 0) + if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) return; /* we overload curr_resync somewhat here. @@ -2912,14 +3280,16 @@ } if (wait_event_interruptible(resync_wait, mddev2->curr_resync < mddev->curr_resync)) { - flush_curr_signals(); + flush_signals(current); err = -EINTR; mddev_put(mddev2); goto skip; } } - if (mddev->curr_resync == 1) + if (mddev->curr_resync == 1) { + mddev_put(mddev2); break; + } } } while (mddev->curr_resync < 2); @@ -2932,9 +3302,13 @@ sysctl_speed_limit_max); is_mddev_idle(mddev); /* this also initializes IO event counters */ + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + j = mddev->recovery_cp; + else + j = 0; for (m = 0; m < SYNC_MARKS; m++) { mark[m] = jiffies; - mark_cnt[m] = mddev->recovery_cp; + mark_cnt[m] = j; } last_mark = 0; mddev->resync_mark = mark[last_mark]; @@ -2951,12 +3325,10 @@ init_waitqueue_head(&mddev->recovery_wait); last_check = 0; - mddev->recovery_error = 0; - - if (mddev->recovery_cp) + if (j) printk(KERN_INFO "md: resuming recovery of md%d from checkpoint.\n", mdidx(mddev)); - for (j = mddev->recovery_cp; j < max_sectors;) { + while (j < max_sectors) { int sectors; sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min); @@ -2973,6 +3345,10 @@ last_check = j; + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) || + test_bit(MD_RECOVERY_ERR, &mddev->recovery)) + break; + blk_run_queues(); repeat: @@ -2993,7 +3369,7 @@ * got a signal, exit. */ printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n"); - flush_curr_signals(); + flush_signals(current); err = -EINTR; goto out; } @@ -3027,39 +3403,42 @@ out: wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); - if (mddev->recovery_running < 0 && - !mddev->recovery_error && mddev->curr_resync > 2) - { - /* interrupted but no write errors */ - printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev)); - mddev->recovery_cp = mddev->curr_resync; - } - /* tell personality that we are finished */ mddev->pers->sync_request(mddev, max_sectors, 1); - skip: - mddev->curr_resync = 0; + if (err) - mddev->recovery_running = -1; - if (mddev->recovery_running > 0) - mddev->recovery_running = 0; - if (mddev->recovery_running == 0) - mddev->recovery_cp = MaxSector; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); + if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) && + mddev->curr_resync > 2 && + mddev->curr_resync > mddev->recovery_cp) { + if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { + printk(KERN_INFO "md: checkpointing recovery of md%d.\n", mdidx(mddev)); + mddev->recovery_cp = mddev->curr_resync; + } else + mddev->recovery_cp = MaxSector; + } + if (mddev->safemode) md_enter_safemode(mddev); - md_recover_arrays(); + skip: + mddev->curr_resync = 0; + set_bit(MD_RECOVERY_DONE, &mddev->recovery); + md_wakeup_thread(mddev->thread); } /* - * This is the kernel thread that watches all md arrays for re-sync and other - * action that might be needed. + * This routine is regularly called by all per-raid-array threads to + * deal with generic issues like resync and super-block update. + * Raid personalities that don't have a thread (linear/raid0) do not + * need this as they never do any recovery or update the superblock. + * * It does not do any resync itself, but rather "forks" off other threads * to do that as needed. - * When it is determined that resync is needed, we set "->recovery_running" and - * create a thread at ->sync_thread. - * When the thread finishes it clears recovery_running (or sets an error) - * and wakeup up this thread which will reap the thread and finish up. + * When it is determined that resync is needed, we set MD_RECOVERY_RUNNING in + * "->recovery" and create a thread at ->sync_thread. + * When the thread finishes it sets MD_RECOVERY_DONE (and might set MD_RECOVERY_ERR) + * and wakeups up this thread which will reap the thread and finish up. * This thread also removes any faulty devices (with nr_pending == 0). * * The overall approach is: @@ -3070,41 +3449,47 @@ * 5/ If array is degraded, try to add spares devices * 6/ If array has spares or is not in-sync, start a resync thread. */ -void md_do_recovery(void *data) +void md_check_recovery(mddev_t *mddev) { - mddev_t *mddev; mdk_rdev_t *rdev; - struct list_head *tmp, *rtmp; + struct list_head *rtmp; dprintk(KERN_INFO "md: recovery thread got woken up ...\n"); - ITERATE_MDDEV(mddev,tmp) if (mddev_lock(mddev)==0) { - if (!mddev->raid_disks || !mddev->pers || mddev->ro) - goto unlock; + if (mddev->ro) + return; + if ( ! ( + mddev->sb_dirty || + test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) || + test_bit(MD_RECOVERY_DONE, &mddev->recovery) + )) + return; + if (mddev_trylock(mddev)==0) { + int spares =0; if (mddev->sb_dirty) md_update_sb(mddev); - if (mddev->recovery_running > 0) + if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) && + !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) /* resync/recovery still happening */ goto unlock; if (mddev->sync_thread) { /* resync has finished, collect result */ md_unregister_thread(mddev->sync_thread); mddev->sync_thread = NULL; - if (mddev->recovery_running == 0) { + if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery)) { /* success...*/ /* activate any spares */ mddev->pers->spare_active(mddev); - mddev->spares = 0; } md_update_sb(mddev); - mddev->recovery_running = 0; + mddev->recovery = 0; wake_up(&resync_wait); goto unlock; } - if (mddev->recovery_running) { + if (mddev->recovery) { /* that's odd.. */ - mddev->recovery_running = 0; + mddev->recovery = 0; wake_up(&resync_wait); } @@ -3112,7 +3497,6 @@ * remove any failed drives, then * add spares if possible */ - mddev->spares = 0; ITERATE_RDEV(mddev,rdev,rtmp) { if (rdev->raid_disk >= 0 && rdev->faulty && @@ -3121,43 +3505,41 @@ rdev->raid_disk = -1; } if (!rdev->faulty && rdev->raid_disk >= 0 && !rdev->in_sync) - mddev->spares++; + spares++; } if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 && !rdev->faulty) { - if (mddev->pers->hot_add_disk(mddev,rdev)) { - mddev->spares++; - mddev->recovery_cp = 0; - } + if (mddev->pers->hot_add_disk(mddev,rdev)) + spares++; else break; } } - if (!mddev->spares && (mddev->recovery_cp == MaxSector )) { + if (!spares && (mddev->recovery_cp == MaxSector )) { /* nothing we can do ... */ goto unlock; } if (mddev->pers->sync_request) { + set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); + if (!spares) + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); mddev->sync_thread = md_register_thread(md_do_sync, mddev, - "md_resync"); + "md%d_resync"); if (!mddev->sync_thread) { printk(KERN_ERR "md%d: could not start resync thread...\n", mdidx(mddev)); /* leave the spares where they are, it shouldn't hurt */ - mddev->recovery_running = 0; + mddev->recovery = 0; } else { - mddev->recovery_running = 1; md_wakeup_thread(mddev->sync_thread); } } unlock: mddev_unlock(mddev); } - dprintk(KERN_INFO "md: recovery thread finished ...\n"); - } int md_notify_reboot(struct notifier_block *this, @@ -3192,6 +3574,7 @@ static void md_geninit(void) { + struct proc_dir_entry *p; int i; for(i = 0; i < MAX_MD_DEVS; i++) { @@ -3201,24 +3584,24 @@ dprintk("md: sizeof(mdp_super_t) = %d\n", (int)sizeof(mdp_super_t)); #ifdef CONFIG_PROC_FS - create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL); + p = create_proc_entry("mdstat", S_IRUGO, NULL); + if (p) + p->proc_fops = &md_seq_fops; #endif } int __init md_init(void) { - static char * name = "mdrecoveryd"; int minor; printk(KERN_INFO "md: md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); - if (register_blkdev (MAJOR_NR, "md", &md_fops)) { - printk(KERN_ALERT "md: Unable to get major %d for md\n", MAJOR_NR); - return (-1); - } - devfs_mk_dir (NULL, "md", NULL); + if (register_blkdev(MAJOR_NR, "md")) + return -1; + + devfs_mk_dir(NULL, "md", NULL); blk_register_region(MKDEV(MAJOR_NR, 0), MAX_MD_DEVS, THIS_MODULE, md_probe, NULL, NULL); for (minor=0; minor < MAX_MD_DEVS; ++minor) { @@ -3228,11 +3611,6 @@ S_IFBLK | S_IRUSR | S_IWUSR, &md_fops, NULL); } - md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); - if (!md_recovery_thread) - printk(KERN_ALERT - "md: bug: couldn't allocate md_recovery_thread\n"); - register_reboot_notifier(&md_notifier); raid_table_header = register_sysctl_table(raid_root_table, 1); @@ -3267,7 +3645,7 @@ for (i = 0; i < dev_cnt; i++) { dev_t dev = detected_devices[i]; - rdev = md_import_device(dev,1); + rdev = md_import_device(dev,0, 0); if (IS_ERR(rdev)) { printk(KERN_ALERT "md: could not import %s!\n", partition_name(dev)); @@ -3290,7 +3668,6 @@ { int i; blk_unregister_region(MKDEV(MAJOR_NR,0), MAX_MD_DEVS); - md_unregister_thread(md_recovery_thread); for (i=0; i < MAX_MD_DEVS; i++) devfs_remove("md/%d", i); devfs_remove("md"); @@ -3330,4 +3707,5 @@ EXPORT_SYMBOL(md_wakeup_thread); EXPORT_SYMBOL(md_print_devices); EXPORT_SYMBOL(md_interrupt_thread); +EXPORT_SYMBOL(md_check_recovery); MODULE_LICENSE("GPL"); diff -Nru a/drivers/md/multipath.c b/drivers/md/multipath.c --- a/drivers/md/multipath.c Sat Mar 15 18:40:41 2003 +++ b/drivers/md/multipath.c Sat Mar 15 18:40:41 2003 @@ -86,7 +86,6 @@ { unsigned long flags; mddev_t *mddev = mp_bh->mddev; - multipath_conf_t *conf = mddev_to_conf(mddev); spin_lock_irqsave(&retry_list_lock, flags); if (multipath_retry_list == NULL) @@ -95,7 +94,7 @@ multipath_retry_tail = &mp_bh->next_mp; mp_bh->next_mp = NULL; spin_unlock_irqrestore(&retry_list_lock, flags); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); } @@ -185,19 +184,18 @@ return 0; } -static int multipath_status (char *page, mddev_t *mddev) +static void multipath_status (struct seq_file *seq, mddev_t *mddev) { multipath_conf_t *conf = mddev_to_conf(mddev); - int sz = 0, i; + int i; - sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", + seq_printf (seq, "%s", conf->multipaths[i].rdev && conf->multipaths[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); - return sz; + seq_printf (seq, "]"); } #define LAST_DISK KERN_ALERT \ @@ -334,14 +332,14 @@ * 3. Performs writes following reads for array syncronising. */ -static void multipathd (void *data) +static void multipathd (mddev_t *mddev) { struct multipath_bh *mp_bh; struct bio *bio; unsigned long flags; - mddev_t *mddev; mdk_rdev_t *rdev; + md_check_recovery(mddev); for (;;) { spin_lock_irqsave(&retry_list_lock, flags); mp_bh = multipath_retry_list; @@ -471,10 +469,10 @@ } { - const char * name = "multipathd"; + const char * name = "md%d_multipath"; - conf->thread = md_register_thread(multipathd, conf, name); - if (!conf->thread) { + mddev->thread = md_register_thread(multipathd, mddev, name); + if (!mddev->thread) { printk(THREAD_ERROR, mdidx(mddev)); goto out_free_conf; } @@ -513,7 +511,7 @@ { multipath_conf_t *conf = mddev_to_conf(mddev); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); mempool_destroy(conf->pool); kfree(conf); mddev->private = NULL; diff -Nru a/drivers/md/raid0.c b/drivers/md/raid0.c --- a/drivers/md/raid0.c Sat Mar 15 18:40:42 2003 +++ b/drivers/md/raid0.c Sat Mar 15 18:40:42 2003 @@ -349,7 +349,7 @@ * is the only IO operation happening on this bh. */ bio->bi_bdev = tmp_dev->bdev; - bio->bi_sector = rsect; + bio->bi_sector = rsect + tmp_dev->data_offset; /* * Let the main block layer submit the IO and resolve recursion: @@ -372,41 +372,40 @@ return 0; } -static int raid0_status (char *page, mddev_t *mddev) +static void raid0_status (struct seq_file *seq, mddev_t *mddev) { - int sz = 0; #undef MD_DEBUG #ifdef MD_DEBUG int j, k; raid0_conf_t *conf = mddev_to_conf(mddev); - sz += sprintf(page + sz, " "); + seq_printf(seq, " "); for (j = 0; j < conf->nr_zones; j++) { - sz += sprintf(page + sz, "[z%d", + seq_printf(seq, "[z%d", conf->hash_table[j].zone0 - conf->strip_zone); if (conf->hash_table[j].zone1) - sz += sprintf(page+sz, "/z%d] ", + seq_printf(seq, "/z%d] ", conf->hash_table[j].zone1 - conf->strip_zone); else - sz += sprintf(page+sz, "] "); + seq_printf(seq, "] "); } - sz += sprintf(page + sz, "\n"); + seq_printf(seq, "\n"); for (j = 0; j < conf->nr_strip_zones; j++) { - sz += sprintf(page + sz, " z%d=[", j); + seq_printf(seq, " z%d=[", j); for (k = 0; k < conf->strip_zone[j].nb_dev; k++) - sz += sprintf (page+sz, "%s/", bdev_partition_name( + seq_printf (seq, "%s/", bdev_partition_name( conf->strip_zone[j].dev[k]->bdev)); - sz--; - sz += sprintf (page+sz, "] zo=%d do=%d s=%d\n", + + seq_printf (seq, "] zo=%d do=%d s=%d\n", conf->strip_zone[j].zone_offset, conf->strip_zone[j].dev_offset, conf->strip_zone[j].size); } #endif - sz += sprintf(page + sz, " %dk chunks", mddev->chunk_size/1024); - return sz; + seq_printf(seq, " %dk chunks", mddev->chunk_size/1024); + return; } static mdk_personality_t raid0_personality= diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c Sat Mar 15 18:40:42 2003 +++ b/drivers/md/raid1.c Sat Mar 15 18:40:42 2003 @@ -225,13 +225,12 @@ { unsigned long flags; mddev_t *mddev = r1_bio->mddev; - conf_t *conf = mddev_to_conf(mddev); spin_lock_irqsave(&retry_list_lock, flags); list_add(&r1_bio->retry_list, &retry_list_head); spin_unlock_irqrestore(&retry_list_lock, flags); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); } /* @@ -320,7 +319,7 @@ * already. */ if (atomic_dec_and_test(&r1_bio->remaining)) { - md_write_end(r1_bio->mddev,conf->thread); + md_write_end(r1_bio->mddev); raid_end_bio_io(r1_bio, uptodate); } } @@ -494,7 +493,7 @@ BUG(); r1_bio->read_bio = read_bio; - read_bio->bi_sector = r1_bio->sector; + read_bio->bi_sector = r1_bio->sector + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = end_request; read_bio->bi_rw = r1_bio->cmd; @@ -529,7 +528,7 @@ mbio = bio_clone(bio, GFP_NOIO); r1_bio->write_bios[i] = mbio; - mbio->bi_sector = r1_bio->sector; + mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = end_request; mbio->bi_rw = r1_bio->cmd; @@ -542,7 +541,7 @@ * If all mirrors are non-operational * then return an IO error: */ - md_write_end(mddev,conf->thread); + md_write_end(mddev); raid_end_bio_io(r1_bio, 0); return 0; } @@ -571,19 +570,18 @@ return 0; } -static int status(char *page, mddev_t *mddev) +static void status(struct seq_file *seq, mddev_t *mddev) { conf_t *conf = mddev_to_conf(mddev); - int sz = 0, i; + int i; - sz += sprintf(page+sz, " [%d/%d] [", conf->raid_disks, + seq_printf(seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf(page+sz, "%s", + seq_printf(seq, "%s", conf->mirrors[i].rdev && conf->mirrors[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); - return sz; + seq_printf(seq, "]"); } #define LAST_DISK KERN_ALERT \ @@ -624,10 +622,9 @@ mddev->degraded++; conf->working_disks--; /* - * if recovery was running, stop it now. + * if recovery is running, make sure it aborts. */ - if (mddev->recovery_running) - mddev->recovery_running = -EIO; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); } rdev->in_sync = 0; rdev->faulty = 1; @@ -859,7 +856,7 @@ mbio = bio_clone(bio, GFP_NOIO); r1_bio->write_bios[i] = mbio; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; - mbio->bi_sector = r1_bio->sector; + mbio->bi_sector = r1_bio->sector | conf->mirrors[i].rdev->data_offset; mbio->bi_end_io = end_sync_write; mbio->bi_rw = WRITE; mbio->bi_private = r1_bio; @@ -900,17 +897,17 @@ * 3. Performs writes following reads for array syncronising. */ -static void raid1d(void *data) +static void raid1d(mddev_t *mddev) { struct list_head *head = &retry_list_head; r1bio_t *r1_bio; struct bio *bio; unsigned long flags; - mddev_t *mddev; - conf_t *conf = data; + conf_t *conf = mddev_to_conf(mddev); mdk_rdev_t *rdev; - md_handle_safemode(conf->mddev); + md_check_recovery(mddev); + md_handle_safemode(mddev); for (;;) { spin_lock_irqsave(&retry_list_lock, flags); @@ -937,7 +934,7 @@ printk(REDIRECT_SECTOR, bdev_partition_name(rdev->bdev), (unsigned long long)r1_bio->sector); bio->bi_bdev = rdev->bdev; - bio->bi_sector = r1_bio->sector; + bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_rw = r1_bio->cmd; generic_make_request(bio); @@ -1048,7 +1045,7 @@ read_bio = bio_clone(r1_bio->master_bio, GFP_NOIO); - read_bio->bi_sector = sector_nr; + read_bio->bi_sector = sector_nr + mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = end_sync_read; read_bio->bi_rw = READ; @@ -1190,10 +1187,8 @@ { - snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid1d_md%d",mdidx(mddev)); - - conf->thread = md_register_thread(raid1d, conf, conf->thread_name); - if (!conf->thread) { + mddev->thread = md_register_thread(raid1d, mddev, "md%d_raid1"); + if (!mddev->thread) { printk(THREAD_ERROR, mdidx(mddev)); goto out_free_conf; } @@ -1219,7 +1214,8 @@ { conf_t *conf = mddev_to_conf(mddev); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); + mddev->thread = NULL; if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); kfree(conf); diff -Nru a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c Sat Mar 15 18:40:40 2003 +++ b/drivers/md/raid5.c Sat Mar 15 18:40:40 2003 @@ -71,12 +71,12 @@ list_add_tail(&sh->lru, &conf->delayed_list); else list_add_tail(&sh->lru, &conf->handle_list); - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } else { if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { atomic_dec(&conf->preread_active_stripes); if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } list_add_tail(&sh->lru, &conf->inactive_list); atomic_dec(&conf->active_stripes); @@ -463,10 +463,9 @@ conf->failed_disks++; rdev->in_sync = 0; /* - * if recovery was running, stop it now. + * if recovery was running, make sure it aborts. */ - if (mddev->recovery_running) - mddev->recovery_running = -EIO; + set_bit(MD_RECOVERY_ERR, &mddev->recovery); } rdev->faulty = 1; printk (KERN_ALERT @@ -913,7 +912,7 @@ struct bio *nextbi = bi->bi_next; clear_bit(BIO_UPTODATE, &bi->bi_flags); if (--bi->bi_phys_segments == 0) { - md_write_end(conf->mddev, conf->thread); + md_write_end(conf->mddev); bi->bi_next = return_bi; return_bi = bi; } @@ -970,7 +969,7 @@ while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { wbi2 = wbi->bi_next; if (--wbi->bi_phys_segments == 0) { - md_write_end(conf->mddev, conf->thread); + md_write_end(conf->mddev); wbi->bi_next = return_bi; return_bi = wbi; } @@ -1113,7 +1112,7 @@ if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) { atomic_dec(&conf->preread_active_stripes); if (atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD) - md_wakeup_thread(conf->thread); + md_wakeup_thread(conf->mddev->thread); } } } @@ -1207,7 +1206,7 @@ bi->bi_bdev = rdev->bdev; PRINTK("for %llu schedule op %ld on disc %d\n", (unsigned long long)sh->sector, bi->bi_rw, i); atomic_inc(&sh->count); - bi->bi_sector = sh->sector; + bi->bi_sector = sh->sector + rdev->data_offset; bi->bi_flags = 1 << BIO_UPTODATE; bi->bi_vcnt = 1; bi->bi_idx = 0; @@ -1251,7 +1250,7 @@ if (blk_remove_plug(q)) raid5_activate_delayed(conf); - md_wakeup_thread(conf->thread); + md_wakeup_thread(mddev->thread); spin_unlock_irqrestore(&conf->device_lock, flags); } @@ -1304,7 +1303,7 @@ int bytes = bi->bi_size; if ( bio_data_dir(bi) == WRITE ) - md_write_end(mddev,conf->thread); + md_write_end(mddev); bi->bi_size = 0; bi->bi_end_io(bi, bytes, 0); } @@ -1356,16 +1355,17 @@ * During the scan, completed stripes are saved for us by the interrupt * handler, so that they will not have to wait for our next wakeup. */ -static void raid5d (void *data) +static void raid5d (mddev_t *mddev) { struct stripe_head *sh; - raid5_conf_t *conf = data; - mddev_t *mddev = conf->mddev; + raid5_conf_t *conf = mddev_to_conf(mddev); int handled; PRINTK("+++ raid5d active\n"); + md_check_recovery(mddev); md_handle_safemode(mddev); + handled = 0; spin_lock_irq(&conf->device_lock); while (1) { @@ -1486,10 +1486,8 @@ } { - snprintf(conf->thread_name,MD_THREAD_NAME_MAX,"raid5d_md%d",mdidx(mddev)); - - conf->thread = md_register_thread(raid5d, conf, conf->thread_name); - if (!conf->thread) { + mddev->thread = md_register_thread(raid5d, mddev, "md%d_raid5"); + if (!mddev->thread) { printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); goto abort; } @@ -1500,7 +1498,7 @@ if (grow_stripes(conf, conf->max_nr_stripes)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); shrink_stripes(conf); - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); goto abort; } else printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); @@ -1536,7 +1534,8 @@ { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; - md_unregister_thread(conf->thread); + md_unregister_thread(mddev->thread); + mddev->thread = NULL; shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); kfree(conf); @@ -1574,29 +1573,26 @@ } } spin_unlock_irq(&conf->device_lock); - - PRINTK("--- raid5d inactive\n"); } #endif -static int status (char *page, mddev_t *mddev) +static void status (struct seq_file *seq, mddev_t *mddev) { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; - int sz = 0, i; + int i; - sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout); - sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); + seq_printf (seq, " level %d, %dk chunk, algorithm %d", mddev->level, mddev->chunk_size >> 10, mddev->layout); + seq_printf (seq, " [%d/%d] [", conf->raid_disks, conf->working_disks); for (i = 0; i < conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", + seq_printf (seq, "%s", conf->disks[i].rdev && conf->disks[i].rdev->in_sync ? "U" : "_"); - sz += sprintf (page+sz, "]"); + seq_printf (seq, "]"); #if RAID5_DEBUG #define D(x) \ - sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x)) + seq_printf (seq, "<"#x":%d>", atomic_read(&conf->x)) printall(conf); #endif - return sz; } static void print_raid5_conf (raid5_conf_t *conf) diff -Nru a/drivers/media/radio/miropcm20-rds.c b/drivers/media/radio/miropcm20-rds.c --- a/drivers/media/radio/miropcm20-rds.c Sat Mar 15 18:40:40 2003 +++ b/drivers/media/radio/miropcm20-rds.c Sat Mar 15 18:40:40 2003 @@ -12,8 +12,9 @@ #include #include #include -#include +#include #include +#include #include "miropcm20-rds-core.h" static char * text_buffer; @@ -103,28 +104,39 @@ } } -static struct file_operations rds_f_ops = { +static struct file_operations rds_fops = { .owner = THIS_MODULE, .read = rds_f_read, .open = rds_f_open, .release = rds_f_release }; +static struct miscdevice rds_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "radiotext" + .fops = &rds_fops, +}; static int __init miropcm20_rds_init(void) { - if (!devfs_register(NULL, "v4l/rds/radiotext", - DEVFS_FL_DEFAULT | DEVFS_FL_AUTO_DEVNUM, - 0, 0, S_IRUGO | S_IFCHR, &rds_f_ops, NULL)) - return -EINVAL; + int error; - printk("miropcm20-rds: userinterface driver loaded.\n"); - return 0; + error = misc_register(&rds_miscdev); + if (error) + return error; + + error = devfs_mk_symlink(NULL, "v4l/rds/radiotext", 0, + "../misc/radiotext", NULL, NULL); + if (error) + misc_deregister(&rds_miscdev) + + return error; } static void __exit miropcm20_rds_cleanup(void) { devfs_remove("v4l/rds/radiotext"); + misc_deregister(&rds_miscdev) } module_init(miropcm20_rds_init); diff -Nru a/drivers/media/video/audiochip.h b/drivers/media/video/audiochip.h --- a/drivers/media/video/audiochip.h Sat Mar 15 18:40:40 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -#ifndef AUDIOCHIP_H -#define AUDIOCHIP_H - -/* ---------------------------------------------------------------------- */ - -#define MIN(a,b) (((a)>(b))?(b):(a)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - -/* v4l device was opened in Radio mode */ -#define AUDC_SET_RADIO _IO('m',2) -/* select from TV,radio,extern,MUTE */ -#define AUDC_SET_INPUT _IOW('m',17,int) - -/* audio inputs */ -#define AUDIO_TUNER 0x00 -#define AUDIO_RADIO 0x01 -#define AUDIO_EXTERN 0x02 -#define AUDIO_INTERN 0x03 -#define AUDIO_OFF 0x04 -#define AUDIO_ON 0x05 -#define AUDIO_MUTE 0x80 -#define AUDIO_UNMUTE 0x81 - -/* all the stuff below is obsolete and just here for reference. I'll - * remove it once the driver is tested and works fine. - * - * Instead creating alot of tiny API's for all kinds of different - * chips, we'll just pass throuth the v4l ioctl structs (v4l2 not - * yet...). It is a bit less flexible, but most/all used i2c chips - * make sense in v4l context only. So I think that's acceptable... - */ - -/* misc stuff to pass around config info to i2c chips */ -#define AUDC_CONFIG_PINNACLE _IOW('m',32,int) - -#endif /* AUDIOCHIP_H */ diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c --- a/drivers/media/video/bttv-cards.c Sat Mar 15 18:40:42 2003 +++ b/drivers/media/video/bttv-cards.c Sat Mar 15 18:40:42 2003 @@ -36,7 +36,6 @@ #include #include "bttvp.h" -#include "tuner.h" #include "bt832.h" /* fwd decl */ diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c --- a/drivers/media/video/bttv-driver.c Sat Mar 15 18:40:43 2003 +++ b/drivers/media/video/bttv-driver.c Sat Mar 15 18:40:43 2003 @@ -37,7 +37,6 @@ #include #include "bttvp.h" -#include "tuner.h" int bttv_num; /* number of Bt848s in use */ struct bttv bttvs[BTTV_MAX]; diff -Nru a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c --- a/drivers/media/video/bttv-if.c Sat Mar 15 18:40:40 2003 +++ b/drivers/media/video/bttv-if.c Sat Mar 15 18:40:40 2003 @@ -34,7 +34,6 @@ #include #include "bttvp.h" -#include "tuner.h" static struct i2c_algo_bit_data bttv_i2c_algo_template; static struct i2c_adapter bttv_i2c_adap_template; diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h --- a/drivers/media/video/bttvp.h Sat Mar 15 18:40:41 2003 +++ b/drivers/media/video/bttvp.h Sat Mar 15 18:40:41 2003 @@ -34,10 +34,12 @@ #include #include +#include +#include +#include + #include "bt848.h" #include "bttv.h" -#include "video-buf.h" -#include "audiochip.h" #ifdef __KERNEL__ diff -Nru a/drivers/media/video/bw-qcam.c b/drivers/media/video/bw-qcam.c --- a/drivers/media/video/bw-qcam.c Sat Mar 15 18:40:40 2003 +++ b/drivers/media/video/bw-qcam.c Sat Mar 15 18:40:40 2003 @@ -83,11 +83,9 @@ static unsigned int yieldlines=4; /* Yield after this many during capture */ static int video_nr = -1; -#if LINUX_VERSION_CODE >= 0x020117 MODULE_PARM(maxpoll,"i"); MODULE_PARM(yieldlines,"i"); MODULE_PARM(video_nr,"i"); -#endif static inline int read_lpstatus(struct qcam_device *q) { diff -Nru a/drivers/media/video/id.h b/drivers/media/video/id.h --- a/drivers/media/video/id.h Sat Mar 15 18:40:42 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,35 +0,0 @@ -/* FIXME: this temporarely, until these are included in linux/i2c-id.h */ - -/* drivers */ -#ifndef I2C_DRIVERID_TVMIXER -# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0 -#endif -#ifndef I2C_DRIVERID_TVAUDIO -# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1 -#endif - -/* chips */ -#ifndef I2C_DRIVERID_DPL3518 -# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2 -#endif -#ifndef I2C_DRIVERID_TDA9873 -# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3 -#endif -#ifndef I2C_DRIVERID_TDA9875 -# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4 -#endif -#ifndef I2C_DRIVERID_PIC16C54_PV951 -# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5 -#endif -#ifndef I2C_DRIVERID_TDA7432 -# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6 -#endif -#ifndef I2C_DRIVERID_TDA9874 -# define I2C_DRIVERID_TDA9874 I2C_DRIVERID_EXP0+7 -#endif - -/* algorithms */ -#ifndef I2C_ALGO_SAA7134 -# define I2C_ALGO_SAA7134 0x090000 -#endif - diff -Nru a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c --- a/drivers/media/video/msp3400.c Sat Mar 15 18:40:42 2003 +++ b/drivers/media/video/msp3400.c Sat Mar 15 18:40:42 2003 @@ -56,7 +56,7 @@ #define __KERNEL_SYSCALLS__ #include -#include "audiochip.h" +#include #include "msp3400.h" /* Addresses to scan */ @@ -1495,8 +1495,8 @@ VIDEO_AUDIO_MUTABLE; if (msp->muted) va->flags |= VIDEO_AUDIO_MUTE; - va->volume=MAX(msp->left,msp->right); - va->balance=(32768*MIN(msp->left,msp->right))/ + va->volume=max(msp->left,msp->right); + va->balance=(32768*min(msp->left,msp->right))/ (va->volume ? va->volume : 1); va->balance=(msp->leftright)? (65535-va->balance) : va->balance; @@ -1517,9 +1517,9 @@ dprintk(KERN_DEBUG "msp34xx: VIDIOCSAUDIO\n"); msp->muted = (va->flags & VIDEO_AUDIO_MUTE); - msp->left = (MIN(65536 - va->balance,32768) * + msp->left = (min(65536 - va->balance,32768) * va->volume) / 32768; - msp->right = (MIN(va->balance,32768) * + msp->right = (min(va->balance,(__u16)32768) * va->volume) / 32768; msp->bass = va->bass; msp->treble = va->treble; diff -Nru a/drivers/media/video/planb.c b/drivers/media/video/planb.c --- a/drivers/media/video/planb.c Sat Mar 15 18:40:44 2003 +++ b/drivers/media/video/planb.c Sat Mar 15 18:40:44 2003 @@ -181,12 +181,7 @@ /* Let's wait 30msec for this one */ current->state = TASK_INTERRUPTIBLE; -#if LINUX_VERSION_CODE >= 0x02017F schedule_timeout(30 * HZ / 1000); -#else - current->timeout = jiffies + 30 * HZ / 1000; /* 30 ms */; - schedule(); -#endif return (unsigned char)in_8 (&planb_regs->saa_status); } diff -Nru a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c --- a/drivers/media/video/saa7134/saa7134-cards.c Sat Mar 15 18:40:44 2003 +++ b/drivers/media/video/saa7134/saa7134-cards.c Sat Mar 15 18:40:44 2003 @@ -24,7 +24,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" /* commly used strings */ static char name_mute[] = "mute"; diff -Nru a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c --- a/drivers/media/video/saa7134/saa7134-core.c Sat Mar 15 18:40:41 2003 +++ b/drivers/media/video/saa7134/saa7134-core.c Sat Mar 15 18:40:41 2003 @@ -30,7 +30,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" MODULE_DESCRIPTION("v4l2 driver module for saa7130/34 based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c --- a/drivers/media/video/saa7134/saa7134-i2c.c Sat Mar 15 18:40:40 2003 +++ b/drivers/media/video/saa7134/saa7134-i2c.c Sat Mar 15 18:40:40 2003 @@ -30,8 +30,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" -#include "id.h" /* ----------------------------------------------------------- */ diff -Nru a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c --- a/drivers/media/video/saa7134/saa7134-video.c Sat Mar 15 18:40:40 2003 +++ b/drivers/media/video/saa7134/saa7134-video.c Sat Mar 15 18:40:40 2003 @@ -29,8 +29,6 @@ #include "saa7134-reg.h" #include "saa7134.h" -#include "tuner.h" -#include "audiochip.h" /* ------------------------------------------------------------------ */ diff -Nru a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h --- a/drivers/media/video/saa7134/saa7134.h Sat Mar 15 18:40:43 2003 +++ b/drivers/media/video/saa7134/saa7134.h Sat Mar 15 18:40:43 2003 @@ -22,7 +22,11 @@ #include #include #include -#include "video-buf.h" + +#include +#include +#include +#include #define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,2) diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c --- a/drivers/media/video/tda7432.c Sat Mar 15 18:40:43 2003 +++ b/drivers/media/video/tda7432.c Sat Mar 15 18:40:43 2003 @@ -49,8 +49,8 @@ #include #include "bttv.h" -#include "audiochip.h" -#include "id.h" +#include +#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c --- a/drivers/media/video/tda9875.c Sat Mar 15 18:40:41 2003 +++ b/drivers/media/video/tda9875.c Sat Mar 15 18:40:41 2003 @@ -31,8 +31,8 @@ #include #include "bttv.h" -#include "audiochip.h" -#include "id.h" +#include +#include MODULE_PARM(debug,"i"); MODULE_LICENSE("GPL"); @@ -316,17 +316,15 @@ /* min is -84 max is 24 */ left = (t->lvol+84)*606; right = (t->rvol+84)*606; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ + va->volume=max(left,right); + va->balance=(32768*min(left,right))/ (va->volume ? va->volume : 1); va->balance=(leftbalance) : va->balance; va->bass = (t->bass+12)*2427; /* min -12 max +15 */ va->treble = (t->treble+12)*2730;/* min -12 max +12 */ - va->mode |= VIDEO_SOUND_MONO; - break; /* VIDIOCGAUDIO case */ } @@ -336,9 +334,9 @@ int left,right; dprintk("VIDEOCSAUDIO...\n"); - left = (MIN(65536 - va->balance,32768) * + left = (min(65536 - va->balance,32768) * va->volume) / 32768; - right = (MIN(va->balance,32768) * + right = (min(va->balance,(__u16)32768) * va->volume) / 32768; t->lvol = ((left/606)-84) & 0xff; if (t->lvol > 24) diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c --- a/drivers/media/video/tda9887.c Sat Mar 15 18:40:39 2003 +++ b/drivers/media/video/tda9887.c Sat Mar 15 18:40:39 2003 @@ -7,8 +7,8 @@ #include #include -#include "id.h" -#include "audiochip.h" +#include +#include /* Chips: TDA9885 (PAL, NTSC) diff -Nru a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c --- a/drivers/media/video/tuner-3036.c Sat Mar 15 18:40:41 2003 +++ b/drivers/media/video/tuner-3036.c Sat Mar 15 18:40:41 2003 @@ -27,7 +27,7 @@ #include #include -#include "tuner.h" +#include static int debug; /* insmod parameter */ static int this_adap; diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c --- a/drivers/media/video/tuner.c Sat Mar 15 18:40:44 2003 +++ b/drivers/media/video/tuner.c Sat Mar 15 18:40:44 2003 @@ -12,8 +12,8 @@ #include #include -#include "tuner.h" -#include "audiochip.h" +#include +#include /* Addresses to scan */ static unsigned short normal_i2c[] = {I2C_CLIENT_END}; diff -Nru a/drivers/media/video/tuner.h b/drivers/media/video/tuner.h --- a/drivers/media/video/tuner.h Sat Mar 15 18:40:43 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,94 +0,0 @@ -/* - tuner.h - definition for different tuners - - Copyright (C) 1997 Markus Schroeder (schroedm@uni-duesseldorf.de) - minor modifications by Ralph Metzler (rjkm@thp.uni-koeln.de) - - 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 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., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _TUNER_H -#define _TUNER_H - -#include "id.h" - -#define TUNER_TEMIC_PAL 0 /* 4002 FH5 (3X 7756, 9483) */ -#define TUNER_PHILIPS_PAL_I 1 -#define TUNER_PHILIPS_NTSC 2 -#define TUNER_PHILIPS_SECAM 3 /* you must actively select B/G, L, L` */ -#define TUNER_ABSENT 4 -#define TUNER_PHILIPS_PAL 5 -#define TUNER_TEMIC_NTSC 6 /* 4032 FY5 (3X 7004, 9498, 9789) */ -#define TUNER_TEMIC_PAL_I 7 /* 4062 FY5 (3X 8501, 9957) */ -#define TUNER_TEMIC_4036FY5_NTSC 8 /* 4036 FY5 (3X 1223, 1981, 7686) */ -#define TUNER_ALPS_TSBH1_NTSC 9 -#define TUNER_ALPS_TSBE1_PAL 10 -#define TUNER_ALPS_TSBB5_PAL_I 11 -#define TUNER_ALPS_TSBE5_PAL 12 -#define TUNER_ALPS_TSBC5_PAL 13 -#define TUNER_TEMIC_4006FH5_PAL 14 /* 4006 FH5 (3X 9500, 9501, 7291) */ -#define TUNER_ALPS_TSHC6_NTSC 15 -#define TUNER_TEMIC_PAL_DK 16 /* 4016 FY5 (3X 1392, 1393) */ -#define TUNER_PHILIPS_NTSC_M 17 -#define TUNER_TEMIC_4066FY5_PAL_I 18 /* 4066 FY5 (3X 7032, 7035) */ -#define TUNER_TEMIC_4006FN5_MULTI_PAL 19 /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/ -#define TUNER_TEMIC_4009FR5_PAL 20 /* incl. FM radio (3X 7607, 7488, 7711)*/ -#define TUNER_TEMIC_4039FR5_NTSC 21 /* incl. FM radio (3X 7246, 7578, 7732)*/ -#define TUNER_TEMIC_4046FM5 22 /* you must actively select B/G, D/K, I, L, L` ! (3X 7804, 7806, 8103, 8104)*/ -#define TUNER_PHILIPS_PAL_DK 23 -#define TUNER_PHILIPS_FQ1216ME 24 /* you must actively select B/G/D/K, I, L, L` */ -#define TUNER_LG_PAL_I_FM 25 -#define TUNER_LG_PAL_I 26 -#define TUNER_LG_NTSC_FM 27 -#define TUNER_LG_PAL_FM 28 -#define TUNER_LG_PAL 29 -#define TUNER_TEMIC_4009FN5_MULTI_PAL_FM 30 /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/ -#define TUNER_SHARP_2U5JF5540_NTSC 31 -#define TUNER_Samsung_PAL_TCPM9091PD27 32 -#define TUNER_MT2032 33 -#define TUNER_TEMIC_4106FH5 34 /* 4106 FH5 (3X 7808, 7865)*/ -#define TUNER_TEMIC_4012FY5 35 /* 4012 FY5 (3X 0971, 1099)*/ -#define TUNER_TEMIC_4136FY5 36 /* 4136 FY5 (3X 7708, 7746)*/ -#define TUNER_LG_PAL_NEW_TAPC 37 -#define TUNER_PHILIPS_FM1216ME_MK3 38 -#define TUNER_LG_NTSC_NEW_TAPC 39 - - - - -#define NOTUNER 0 -#define PAL 1 /* PAL_BG */ -#define PAL_I 2 -#define NTSC 3 -#define SECAM 4 - -#define NoTuner 0 -#define Philips 1 -#define TEMIC 2 -#define Sony 3 -#define Alps 4 -#define LGINNOTEK 5 -#define SHARP 6 -#define Samsung 7 -#define Microtune 8 - -#define TUNER_SET_TYPE _IOW('t',1,int) /* set tuner type */ -#define TUNER_SET_TVFREQ _IOW('t',2,int) /* set tv freq */ -#if 0 /* obsolete */ -# define TUNER_SET_RADIOFREQ _IOW('t',3,int) /* set radio freq */ -# define TUNER_SET_MODE _IOW('t',4,int) /* set tuner mode */ -#endif - -#endif diff -Nru a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c --- a/drivers/media/video/tvaudio.c Sat Mar 15 18:40:41 2003 +++ b/drivers/media/video/tvaudio.c Sat Mar 15 18:40:41 2003 @@ -29,9 +29,10 @@ #include #include -#include "audiochip.h" +#include +#include + #include "tvaudio.h" -#include "id.h" /* ---------------------------------------------------------------------- */ @@ -1477,8 +1478,8 @@ if (desc->flags & CHIP_HAS_VOLUME) { va->flags |= VIDEO_AUDIO_VOLUME; - va->volume = MAX(chip->left,chip->right); - va->balance = (32768*MIN(chip->left,chip->right))/ + va->volume = max(chip->left,chip->right); + va->balance = (32768*min(chip->left,chip->right))/ (va->volume ? va->volume : 1); } if (desc->flags & CHIP_HAS_BASSTREBLE) { @@ -1500,9 +1501,9 @@ struct video_audio *va = arg; if (desc->flags & CHIP_HAS_VOLUME) { - chip->left = (MIN(65536 - va->balance,32768) * + chip->left = (min(65536 - va->balance,32768) * va->volume) / 32768; - chip->right = (MIN(va->balance,32768) * + chip->right = (min(va->balance,(__u16)32768) * va->volume) / 32768; chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); diff -Nru a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c --- a/drivers/media/video/tvmixer.c Sat Mar 15 18:40:44 2003 +++ b/drivers/media/video/tvmixer.c Sat Mar 15 18:40:44 2003 @@ -16,8 +16,6 @@ #include #include -#include "audiochip.h" -#include "id.h" #define DEV_MAX 4 @@ -136,16 +134,16 @@ case MIXER_WRITE(SOUND_MIXER_VOLUME): left = mix_to_v4l(val); right = mix_to_v4l(val >> 8); - va.volume = MAX(left,right); - va.balance = (32768*MIN(left,right)) / (va.volume ? va.volume : 1); + va.volume = max(left,right); + va.balance = (32768*min(left,right)) / (va.volume ? va.volume : 1); va.balance = (leftdriver->command(client,VIDIOCSAUDIO,&va); client->driver->command(client,VIDIOCGAUDIO,&va); /* fall throuth */ case MIXER_READ(SOUND_MIXER_VOLUME): - left = (MIN(65536 - va.balance,32768) * + left = (min(65536 - va.balance,32768) * va.volume) / 32768; - right = (MIN(va.balance,32768) * + right = (min(va.balance,32768) * va.volume) / 32768; ret = v4l_to_mix2(left,right); break; diff -Nru a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c --- a/drivers/media/video/video-buf.c Sat Mar 15 18:40:42 2003 +++ b/drivers/media/video/video-buf.c Sat Mar 15 18:40:42 2003 @@ -31,7 +31,7 @@ # define TryLockPage TestSetPageLocked #endif -#include "video-buf.h" +#include static int debug = 0; @@ -83,6 +83,8 @@ return NULL; memset(sglist, 0, sizeof(*sglist) * nr_pages); + if (NULL == pages[0]) + goto nopage; if (PageHighMem(pages[0])) /* DMA to highmem pages might not work */ goto highmem; @@ -118,7 +120,7 @@ for (i = 0; i < nr_pages; i++) if (TryLockPage(pages[i])) goto err; - dprintk(2,"lock ok\n"); + dprintk(2,"lock ok [%d pages]\n",nr_pages); return 0; err: @@ -136,7 +138,7 @@ dprintk(2,"unlock start ...\n"); for (i = 0; i < nr_pages; i++) unlock_page(pages[i]); - dprintk(2,"unlock ok\n"); + dprintk(2,"unlock ok [%d pages]\n",nr_pages); return 0; } @@ -270,7 +272,7 @@ /* --------------------------------------------------------------------- */ -void* videobuf_alloc(int size) +void* videobuf_alloc(unsigned int size) { struct videobuf_buffer *vb; @@ -340,7 +342,7 @@ spinlock_t *irqlock, enum v4l2_buf_type type, enum v4l2_field field, - int msize) + unsigned int msize) { memset(q,0,sizeof(*q)); @@ -417,11 +419,11 @@ if (V4L2_FIELD_ALTERNATE == field) { if (V4L2_FIELD_TOP == q->last) { - field = V4L2_FIELD_TOP; - q->last = V4L2_FIELD_TOP; - } else { field = V4L2_FIELD_BOTTOM; q->last = V4L2_FIELD_BOTTOM; + } else { + field = V4L2_FIELD_TOP; + q->last = V4L2_FIELD_TOP; } } return field; @@ -463,7 +465,8 @@ videobuf_reqbufs(struct file *file, struct videobuf_queue *q, struct v4l2_requestbuffers *req) { - int size,count,retval; + unsigned int size,count; + int retval; if (req->type != q->type) return -EINVAL; @@ -477,6 +480,8 @@ size = 0; q->ops->buf_setup(file,&count,&size); size = PAGE_ALIGN(size); + dprintk(1,"reqbufs: bufs=%d, size=0x%x [%d pages total]\n", + count, size, (count*size)>>PAGE_SHIFT); retval = videobuf_mmap_setup(file,q,count,size); if (retval < 0) @@ -660,7 +665,10 @@ retval = videobuf_waiton(q->read_buf,0,0); if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); - retval = q->read_buf->size; + if (STATE_ERROR == q->read_buf->state) + retval = -EIO; + else + retval = q->read_buf->size; } done: @@ -676,7 +684,8 @@ { enum v4l2_field field; unsigned long flags; - int retval, bytes, size, nbufs; + unsigned size, nbufs, bytes; + int retval; down(&q->lock); @@ -686,7 +695,7 @@ count >= size && !(file->f_flags & O_NONBLOCK)) { retval = videobuf_read_zerocopy(file,q,data,count,ppos); - if (retval >= 0) + if (retval >= 0 || retval == -EIO) /* ok, all done */ goto done; /* fallback to kernel bounce buffer on failures */ @@ -714,6 +723,15 @@ goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); + if (STATE_ERROR == q->read_buf->state) { + /* catch I/O errors */ + q->ops->buf_release(file,q->read_buf); + kfree(q->read_buf); + q->read_buf = NULL; + retval = -EIO; + goto done; + } + /* copy to userspace */ bytes = count; if (bytes > q->read_buf->size - q->read_off) @@ -788,8 +806,8 @@ char *data, size_t count, loff_t *ppos, int vbihack) { - unsigned int *fc; - int err, bytes, retval; + unsigned int *fc, bytes; + int err, retval; unsigned long flags; down(&q->lock); @@ -968,9 +986,10 @@ }; int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize) + unsigned int bcount, unsigned int bsize) { - int i,err; + unsigned int i; + int err; err = videobuf_mmap_free(file,q); if (0 != err) @@ -1008,7 +1027,8 @@ struct videobuf_queue *q) { struct videobuf_mapping *map; - int first,last,size,i,retval; + unsigned int first,last,size,i; + int retval; down(&q->lock); retval = -EINVAL; @@ -1025,7 +1045,7 @@ for (first = 0; first < VIDEO_MAX_FRAME; first++) { if (NULL == q->bufs[first]) continue; - if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) + if (q->bufs[first]->boff == (vma->vm_pgoff << PAGE_SHIFT)) break; } if (VIDEO_MAX_FRAME == first) { diff -Nru a/drivers/media/video/video-buf.h b/drivers/media/video/video-buf.h --- a/drivers/media/video/video-buf.h Sat Mar 15 18:40:42 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,232 +0,0 @@ -/* - * generic helper functions for video4linux capture buffers, to handle - * memory management and PCI DMA. Right now bttv + saa7134 use it. - * - * The functions expect the hardware being able to scatter gatter - * (i.e. the buffers are not linear in physical memory, but fragmented - * into PAGE_SIZE chunks). They also assume the driver does not need - * to touch the video data (thus it is probably not useful for USB as - * data often must be uncompressed by the drivers). - * - * (c) 2001,02 Gerd Knorr - * - * 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 - -/* --------------------------------------------------------------------- */ - -/* - * Return a scatterlist for some page-aligned vmalloc()'ed memory - * block (NULL on errors). Memory for the scatterlist is allocated - * using kmalloc. The caller must free the memory. - */ -struct scatterlist* videobuf_vmalloc_to_sg(unsigned char *virt, int nr_pages); - -/* - * Return a scatterlist for a an array of userpages (NULL on errors). - * Memory for the scatterlist is allocated using kmalloc. The caller - * must free the memory. - */ -struct scatterlist* videobuf_pages_to_sg(struct page **pages, int nr_pages, - int offset); -int videobuf_lock(struct page **pages, int nr_pages); -int videobuf_unlock(struct page **pages, int nr_pages); - -/* --------------------------------------------------------------------- */ - -/* - * A small set of helper functions to manage buffers (both userland - * and kernel) for DMA. - * - * videobuf_init_*_dmabuf() - * creates a buffer. The userland version takes a userspace - * pointer + length. The kernel version just wants the size and - * does memory allocation too using vmalloc_32(). - * - * videobuf_pci_*_dmabuf() - * see Documentation/DMA-mapping.txt, these functions to - * basically the same. The map function does also build a - * scatterlist for the buffer (and unmap frees it ...) - * - * videobuf_free_dmabuf() - * no comment ... - * - */ - -struct videobuf_dmabuf { - /* for userland buffer */ - int offset; - struct page **pages; - - /* for kernel buffers */ - void *vmalloc; - - /* common */ - struct scatterlist *sglist; - int sglen; - int nr_pages; - int direction; -}; - -int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, - unsigned long data, unsigned long size); -int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, - int nr_pages); -int videobuf_dma_pci_map(struct pci_dev *dev, struct videobuf_dmabuf *dma); -int videobuf_dma_pci_sync(struct pci_dev *dev, - struct videobuf_dmabuf *dma); -int videobuf_dma_pci_unmap(struct pci_dev *dev, struct videobuf_dmabuf *dma); -int videobuf_dma_free(struct videobuf_dmabuf *dma); - -/* --------------------------------------------------------------------- */ - -/* - * A small set of helper functions to manage video4linux buffers. - * - * struct videobuf_buffer holds the data structures used by the helper - * functions, additionally some commonly used fields for v4l buffers - * (width, height, lists, waitqueue) are in there. That struct should - * be used as first element in the drivers buffer struct. - * - * about the mmap helpers (videobuf_mmap_*): - * - * The mmaper function allows to map any subset of contingous buffers. - * This includes one mmap() call for all buffers (which the original - * video4linux API uses) as well as one mmap() for every single buffer - * (which v4l2 uses). - * - * If there is a valid mapping for a buffer, buffer->baddr/bsize holds - * userspace address + size which can be feeded into the - * videobuf_dma_init_user function listed above. - * - */ - -struct videobuf_buffer; -struct videobuf_queue; - -struct videobuf_mapping { - int count; - int highmem_ok; - unsigned long start; - unsigned long end; - struct videobuf_queue *q; -}; - -enum videobuf_state { - STATE_NEEDS_INIT = 0, - STATE_PREPARED = 1, - STATE_QUEUED = 2, - STATE_ACTIVE = 3, - STATE_DONE = 4, - STATE_ERROR = 5, - STATE_IDLE = 6, -}; - -struct videobuf_buffer { - int i; - - /* info about the buffer */ - int width; - int height; - long size; - enum v4l2_field field; - enum videobuf_state state; - struct videobuf_dmabuf dma; - struct list_head stream; /* QBUF/DQBUF list */ - - /* for mmap'ed buffers */ - off_t boff; /* buffer offset (mmap) */ - size_t bsize; /* buffer size */ - unsigned long baddr; /* buffer addr (userland ptr!) */ - struct videobuf_mapping *map; - - /* touched by irq handler */ - struct list_head queue; - wait_queue_head_t done; - int field_count; - struct timeval ts; -}; - -struct videobuf_queue_ops { - int (*buf_setup)(struct file *file, int *count, int *size); - int (*buf_prepare)(struct file *file,struct videobuf_buffer *vb, - enum v4l2_field field); - void (*buf_queue)(struct file *file,struct videobuf_buffer *vb); - void (*buf_release)(struct file *file,struct videobuf_buffer *vb); -}; - -struct videobuf_queue { - struct semaphore lock; - spinlock_t *irqlock; - struct pci_dev *pci; - - enum v4l2_buf_type type; - int msize; - enum v4l2_field field; - enum v4l2_field last; /* for field=V4L2_FIELD_ALTERNATE */ - struct videobuf_buffer *bufs[VIDEO_MAX_FRAME]; - struct videobuf_queue_ops *ops; - - /* capture via mmap() + ioctl(QBUF/DQBUF) */ - int streaming; - struct list_head stream; - - /* capture via read() */ - int reading; - int read_off; - struct videobuf_buffer *read_buf; -}; - -void* videobuf_alloc(int size); -int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); -int videobuf_iolock(struct pci_dev *pci, struct videobuf_buffer *vb); - -void videobuf_queue_init(struct videobuf_queue *q, - struct videobuf_queue_ops *ops, - struct pci_dev *pci, spinlock_t *irqlock, - enum v4l2_buf_type type, - enum v4l2_field field, int msize); -int videobuf_queue_is_busy(struct videobuf_queue *q); -void videobuf_queue_cancel(struct file *file, struct videobuf_queue *q); - -void videobuf_status(struct v4l2_buffer *b, struct videobuf_buffer *vb, - enum v4l2_buf_type type); -int videobuf_reqbufs(struct file *file, struct videobuf_queue *q, - struct v4l2_requestbuffers *req); -int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b); -int videobuf_qbuf(struct file *file, struct videobuf_queue *q, - struct v4l2_buffer *b); -int videobuf_dqbuf(struct file *file, struct videobuf_queue *q, - struct v4l2_buffer *b); -int videobuf_streamon(struct file *file, struct videobuf_queue *q); -int videobuf_streamoff(struct file *file, struct videobuf_queue *q); - -int videobuf_read_start(struct file *file, struct videobuf_queue *q); -void videobuf_read_stop(struct file *file, struct videobuf_queue *q); -ssize_t videobuf_read_stream(struct file *file, struct videobuf_queue *q, - char *data, size_t count, loff_t *ppos, - int vbihack); -ssize_t videobuf_read_one(struct file *file, struct videobuf_queue *q, - char *data, size_t count, loff_t *ppos); -unsigned int videobuf_poll_stream(struct file *file, - struct videobuf_queue *q, - poll_table *wait); - -int videobuf_mmap_setup(struct file *file, struct videobuf_queue *q, - int bcount, int bsize); -int videobuf_mmap_free(struct file *file, struct videobuf_queue *q); -int videobuf_mmap_mapper(struct vm_area_struct *vma, - struct videobuf_queue *q); - -/* --------------------------------------------------------------------- */ - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -Nru a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h --- a/drivers/media/video/zoran.h Sat Mar 15 18:40:43 2003 +++ b/drivers/media/video/zoran.h Sat Mar 15 18:40:43 2003 @@ -32,10 +32,6 @@ #include -#if LINUX_VERSION_CODE < 0x20212 -typedef struct wait_queue *wait_queue_head_t; -#endif - /* The Buz only supports a maximum width of 720, but some V4L applications (e.g. xawtv are more happy with 768). If XAWTV_HACK is defined, we try to fake a device with bigger width */ diff -Nru a/drivers/media/video/zr36120.c b/drivers/media/video/zr36120.c --- a/drivers/media/video/zr36120.c Sat Mar 15 18:40:42 2003 +++ b/drivers/media/video/zr36120.c Sat Mar 15 18:40:42 2003 @@ -943,7 +943,6 @@ return -EINVAL; } -#if LINUX_VERSION_CODE >= 0x020100 static unsigned int zoran_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -964,7 +963,6 @@ return mask; } -#endif /* append a new clipregion to the vector of video_clips */ static @@ -1745,7 +1743,6 @@ return count; } -#if LINUX_VERSION_CODE >= 0x020100 static unsigned int vbi_poll(struct video_device *dev, struct file *file, poll_table *wait) { @@ -1766,7 +1763,6 @@ return mask; } -#endif static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg) diff -Nru a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h --- a/drivers/message/fusion/lsi/mpi_raid.h Sat Mar 15 18:40:42 2003 +++ b/drivers/message/fusion/lsi/mpi_raid.h Sat Mar 15 18:40:42 2003 @@ -184,7 +184,7 @@ /****************************************************************************/ -/* Mailbox reqeust structure */ +/* Mailbox request structure */ /****************************************************************************/ typedef struct _MSG_MAILBOX_REQUEST diff -Nru a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c --- a/drivers/message/i2o/i2o_block.c Sat Mar 15 18:40:43 2003 +++ b/drivers/message/i2o/i2o_block.c Sat Mar 15 18:40:43 2003 @@ -1608,12 +1608,8 @@ /* * Register the block device interfaces */ - - if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) { - printk(KERN_ERR "Unable to get major number %d for i2o_block\n", - MAJOR_NR); + if (register_blkdev(MAJOR_NR, "i2o_block")) return -EIO; - } for (i = 0; i < MAX_I2OB; i++) { struct gendisk *disk = alloc_disk(16); diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Sat Mar 15 18:40:44 2003 +++ b/drivers/mtd/ftl.c Sat Mar 15 18:40:44 2003 @@ -1281,11 +1281,9 @@ static spinlock_t lock = SPIN_LOCK_UNLOCKED; DEBUG(0, "$Id: ftl.c,v 1.39 2001/10/02 15:05:11 dwmw2 Exp $\n"); - if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { - printk(KERN_NOTICE "ftl_cs: unable to grab major " - "device number!\n"); + if (register_blkdev(FTL_MAJOR, "ftl")) return -EAGAIN; - } + blk_init_queue(&ftl_queue, &do_ftl_request, &lock); register_mtd_user(&ftl_notifier); return 0; diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Sat Mar 15 18:40:41 2003 +++ b/drivers/mtd/mtdblock.c Sat Mar 15 18:40:41 2003 @@ -570,11 +570,10 @@ int __init init_mtdblock(void) { spin_lock_init(&mtdblks_lock); - if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); + + if (register_blkdev(MAJOR_NR, DEVICE_NAME)) return -EAGAIN; - } + #ifdef CONFIG_DEVFS_FS devfs_mk_dir(NULL, DEVICE_NAME, NULL); #endif diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c --- a/drivers/mtd/mtdblock_ro.c Sat Mar 15 18:40:42 2003 +++ b/drivers/mtd/mtdblock_ro.c Sat Mar 15 18:40:42 2003 @@ -240,20 +240,13 @@ int __init init_mtdblock(void) { - int err; - - if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_BLOCK_MAJOR); - err = -EAGAIN; - goto out; - } + if (register_blkdev(MAJOR_NR, DEVICE_NAME)) + return -EAGAIN; blk_init_queue(&mtdro_queue, &mtdblock_request, &mtdro_lock); register_mtd_user(¬ifier); - err = 0; - out: - return err; + + return 0; } static void __exit cleanup_mtdblock(void) diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Sat Mar 15 18:40:39 2003 +++ b/drivers/mtd/nftlcore.c Sat Mar 15 18:40:39 2003 @@ -928,10 +928,8 @@ printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.82 $, nftlmount.c %s\n", nftlmountrev); #endif - if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)) { - printk("unable to register NFTL block device on major %d\n", MAJOR_NR); + if (register_blkdev(MAJOR_NR, "nftl")) return -EBUSY; - } blk_register_region(MKDEV(MAJOR_NR, 0), 256, THIS_MODULE, nftl_probe, NULL, NULL); diff -Nru a/drivers/net/bonding.c b/drivers/net/bonding.c --- a/drivers/net/bonding.c Sat Mar 15 18:40:44 2003 +++ b/drivers/net/bonding.c Sat Mar 15 18:40:44 2003 @@ -2574,6 +2574,13 @@ return 0; } + if (bond->slave_cnt == 0) { + /* no slaves in the bond, frame not sent */ + dev_kfree_skb(skb); + read_unlock_irqrestore(&bond->lock, flags); + return 0; + } + slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt; while ( (slave_no > 0) && (slave != (slave_t *)bond) ) { diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c --- a/drivers/net/dgrs.c Sat Mar 15 18:40:39 2003 +++ b/drivers/net/dgrs.c Sat Mar 15 18:40:39 2003 @@ -981,7 +981,7 @@ { DGRS_PRIV *priv0 = (DGRS_PRIV *) dev0->priv; int is; - int i; + unsigned long i; static int iv2is[16] = { 0, 0, 0, ES4H_IS_INT3, @@ -1140,7 +1140,7 @@ dgrs_probe1(struct net_device *dev) { DGRS_PRIV *priv = (DGRS_PRIV *) dev->priv; - int i; + unsigned long i; int rc; printk("%s: Digi RightSwitch io=%lx mem=%lx irq=%d plx=%lx dma=%lx\n", diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c --- a/drivers/net/eepro100.c Sat Mar 15 18:40:43 2003 +++ b/drivers/net/eepro100.c Sat Mar 15 18:40:43 2003 @@ -529,8 +529,6 @@ static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static void eepro100_remove_one (struct pci_dev *pdev); - static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); @@ -843,6 +841,7 @@ sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE); sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE); init_timer(&sp->timer); /* used in ioctl() */ + spin_lock_init(&sp->lock); sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { @@ -994,7 +993,6 @@ sp->dirty_tx = 0; sp->last_cmd = 0; sp->tx_full = 0; - spin_lock_init(&sp->lock); sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ diff -Nru a/drivers/net/eth16i.c b/drivers/net/eth16i.c --- a/drivers/net/eth16i.c Sat Mar 15 18:40:44 2003 +++ b/drivers/net/eth16i.c Sat Mar 15 18:40:44 2003 @@ -1404,7 +1404,6 @@ static char* mediatype[MAX_ETH16I_CARDS]; static int debug = -1; -#if (LINUX_VERSION_CODE >= 0x20115) MODULE_AUTHOR("Mika Kuoppala "); MODULE_DESCRIPTION("ICL EtherTeam 16i/32 driver"); MODULE_LICENSE("GPL"); @@ -1423,7 +1422,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM_DESC(debug, "eth16i debug level (0-6)"); -#endif int init_module(void) { diff -Nru a/drivers/net/mac8390.c b/drivers/net/mac8390.c --- a/drivers/net/mac8390.c Sat Mar 15 18:40:42 2003 +++ b/drivers/net/mac8390.c Sat Mar 15 18:40:42 2003 @@ -376,11 +376,9 @@ } #ifdef MODULE -#if LINUX_VERSION_CODE > 0x20118 MODULE_AUTHOR("David Huggins-Daines and others"); MODULE_DESCRIPTION("Macintosh NS8390-based Nubus Ethernet driver"); MODUEL_LICENSE("GPL"); -#endif int init_module(void) { diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Sat Mar 15 18:40:42 2003 +++ b/drivers/net/pppoe.c Sat Mar 15 18:40:42 2003 @@ -538,7 +538,7 @@ if (!sk) return 0; - if (sk->dead != 0) + if (test_bit(SOCK_DEAD, &sk->flags)) return -EBADF; pppox_unbind_sock(sk); @@ -777,7 +777,7 @@ int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, - int total_len, struct scm_cookie *scm) + int total_len) { struct sk_buff *skb = NULL; struct sock *sk = sock->sk; @@ -788,7 +788,7 @@ struct net_device *dev; char *start; - if (sk->dead || !(sk->state & PPPOX_CONNECTED)) { + if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) { error = -ENOTCONN; goto end; } @@ -864,7 +864,7 @@ int data_len = skb->len; struct sk_buff *skb2; - if (sk->dead || !(sk->state & PPPOX_CONNECTED)) + if (test_bit(SOCK_DEAD, &sk->flags) || !(sk->state & PPPOX_CONNECTED)) goto abort; hdr.ver = 1; @@ -937,7 +937,8 @@ struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL }; -int pppoe_rcvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags, struct scm_cookie *scm) +int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *m, int total_len, int flags) { struct sock *sk = sock->sk; struct sk_buff *skb = NULL; @@ -1089,7 +1090,7 @@ .setsockopt = sock_no_setsockopt, .getsockopt = sock_no_getsockopt, .sendmsg = pppoe_sendmsg, - .recvmsg = pppoe_rcvmsg, + .recvmsg = pppoe_recvmsg, .mmap = sock_no_mmap }; diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Sat Mar 15 18:40:43 2003 +++ b/drivers/net/shaper.c Sat Mar 15 18:40:43 2003 @@ -88,10 +88,10 @@ #include struct shaper_cb { + unsigned long shapeclock; /* Time it should go out */ + unsigned long shapestamp; /* Stamp for shaper */ __u32 shapelatency; /* Latency on frame */ - __u32 shapeclock; /* Time it should go out */ __u32 shapelen; /* Frame length in clocks */ - __u32 shapestamp; /* Stamp for shaper */ __u16 shapepend; /* Pending */ }; #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb)) @@ -335,7 +335,7 @@ */ if(sh_debug) - printk("Clock = %d, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies); + printk("Clock = %ld, jiffies = %ld\n", SHAPERCB(skb)->shapeclock, jiffies); if(time_before_eq(SHAPERCB(skb)->shapeclock - jiffies, SHAPER_BURST)) { /* diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c --- a/drivers/net/sis900.c Sat Mar 15 18:40:41 2003 +++ b/drivers/net/sis900.c Sat Mar 15 18:40:41 2003 @@ -509,7 +509,7 @@ { struct sis900_private * sis_priv = net_dev->priv; u16 poll_bit = MII_STAT_LINK, status = 0; - unsigned int timeout = jiffies + 5 * HZ; + unsigned long timeout = jiffies + 5 * HZ; int phy_addr; u8 revision; diff -Nru a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h --- a/drivers/net/sk98lin/h/skgepnm2.h Sat Mar 15 18:40:43 2003 +++ b/drivers/net/sk98lin/h/skgepnm2.h Sat Mar 15 18:40:43 2003 @@ -341,7 +341,7 @@ #if SK_TICKS_PER_SEC == 100 #define SK_PNMI_HUNDREDS_SEC(t) (t) #else -#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) +#define SK_PNMI_HUNDREDS_SEC(t) ((((long)t) * 100) / (SK_TICKS_PER_SEC)) #endif /* diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c --- a/drivers/net/sk_mca.c Sat Mar 15 18:40:43 2003 +++ b/drivers/net/sk_mca.c Sat Mar 15 18:40:43 2003 @@ -649,9 +649,7 @@ skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_NONE; priv->stat.rx_packets++; -#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.rx_bytes += descr.Len; -#endif netif_rx(skb); dev->last_rx = jiffies; } @@ -709,9 +707,7 @@ /* update statistics */ if ((descr.Flags & TXDSCR_FLAGS_ERR) == 0) { priv->stat.tx_packets++; -#if LINUX_VERSION_CODE >= 0x020119 /* byte counters for >= 2.1.25 */ priv->stat.tx_bytes++; -#endif } else { priv->stat.tx_errors++; if ((descr.Status & TXDSCR_STATUS_UFLO) != 0) { @@ -1001,13 +997,8 @@ tx_done: - /* When did that change exactly ? */ - -#if LINUX_VERSION_CODE >= 0x020200 dev_kfree_skb(skb); -#else - dev_kfree_skb(skb, FREE_WRITE); -#endif + return retval; } @@ -1146,9 +1137,7 @@ mca_set_adapter_name(slot, "SKNET MC2+ Ethernet Adapter"); mca_set_adapter_procfn(slot, (MCA_ProcFn) skmca_getinfo, dev); -#if LINUX_VERSION_CODE >= 0x020200 mca_mark_as_used(slot); -#endif /* announce success */ printk("%s: SKNet %s adapter found in slot %d\n", dev->name, @@ -1283,9 +1272,7 @@ free_irq(dev->irq, dev); dev->irq = 0; unregister_netdev(dev); -#if LINUX_VERSION_CODE >= 0x020200 mca_mark_as_unused(priv->slot); -#endif mca_set_adapter_procfn(priv->slot, NULL, NULL); kfree(dev->priv); dev->priv = NULL; diff -Nru a/drivers/net/wan/comx-hw-munich.c b/drivers/net/wan/comx-hw-munich.c --- a/drivers/net/wan/comx-hw-munich.c Sat Mar 15 18:40:40 2003 +++ b/drivers/net/wan/comx-hw-munich.c Sat Mar 15 18:40:40 2003 @@ -812,13 +812,8 @@ printk("munich_probe: munich chip found, IRQ %d\n", pci->irq); -#if (LINUX_VERSION_CODE < 0x02030d) - bar1 = ioremap_nocache(pci->base_address[0], 0x100); - lbi = ioremap_nocache(pci->base_address[1], 0x100); -#else bar1 = ioremap_nocache(pci->resource[0].start, 0x100); lbi = ioremap_nocache(pci->resource[1].start, 0x100); -#endif if (bar1 && lbi) { diff -Nru a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c --- a/drivers/net/wan/pc300_tty.c Sat Mar 15 18:40:41 2003 +++ b/drivers/net/wan/pc300_tty.c Sat Mar 15 18:40:41 2003 @@ -198,12 +198,6 @@ int port, aux; st_cpc_tty_area * cpc_tty; - if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)) { - printk("%s-tty: Error: TTY driver is supported on 2.4.X kernel!\n", - ((struct net_device*)(pc300dev->hdlc))->name); - return; - } - /* hdlcX - X=interface number */ port = ((struct net_device*)(pc300dev->hdlc))->name[4] - '0'; if (port >= CPC_TTY_NPORTS) { diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c --- a/drivers/net/wan/sdla_chdlc.c Sat Mar 15 18:40:42 2003 +++ b/drivers/net/wan/sdla_chdlc.c Sat Mar 15 18:40:42 2003 @@ -60,14 +60,9 @@ #include /* ARPHRD_* defines */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include - #include -#else - #include - #include /* Adding new route entries : 2.0.X kernels */ -#endif +#include +#include +#include #include /* sockaddr_in */ #include @@ -153,13 +148,11 @@ unsigned short timer_int_enabled; char update_comms_stats; /* updating comms stats */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ unsigned long tq_working; volatile int bh_write; volatile int bh_read; atomic_t bh_buff_used; -#endif unsigned char interface_down; @@ -204,15 +197,8 @@ static int if_header (struct sk_buff* skb, netdevice_t* dev, unsigned short type, void* daddr, void* saddr, unsigned len); -#if defined(LINUX_2_1) || defined(LINUX_2_4) - static int if_rebuild_hdr (struct sk_buff *skb); - static struct net_device_stats* if_stats (netdevice_t* dev); - -#else - static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); - static struct enet_statistics* if_stats (netdevice_t* dev); -#endif +static int if_rebuild_hdr (struct sk_buff *skb); +static struct net_device_stats* if_stats (netdevice_t* dev); static int if_send (struct sk_buff* skb, netdevice_t* dev); @@ -228,9 +214,7 @@ static int chdlc_disable_comm_shutdown (sdla_t *card); -#ifdef LINUX_2_4 - static void if_tx_timeout (netdevice_t *dev); -#endif +static void if_tx_timeout (netdevice_t *dev); /* Miscellaneous CHDLC Functions */ static int set_chdlc_config (sdla_t* card); @@ -260,12 +244,10 @@ static void rx_intr (sdla_t* card); static void timer_intr(sdla_t *); -#if defined(LINUX_2_1) || defined(LINUX_2_4) - /* Bottom half handlers */ - static void chdlc_work (netdevice_t *); - static int chdlc_work_cleanup (netdevice_t *); - static int bh_enqueue (netdevice_t *, struct sk_buff *); -#endif +/* Bottom half handlers */ +static void chdlc_work (netdevice_t *); +static int chdlc_work_cleanup (netdevice_t *); +static int bh_enqueue (netdevice_t *, struct sk_buff *); /* Miscellaneous functions */ static int chk_bcast_mcast_addr(sdla_t* card, netdevice_t* dev, @@ -287,8 +269,6 @@ /* TTY Global Definitions */ -#if defined(LINUX_2_4) || defined(LINUX_2_1) - #define NR_PORTS 4 #define WAN_TTY_MAJOR 226 #define WAN_TTY_MINOR 0 @@ -321,8 +301,6 @@ static void* tty_card_map[NR_PORTS] = {NULL,NULL,NULL,NULL}; -#endif - /****** Public Functions ****************************************************/ @@ -569,7 +547,6 @@ } if ((card->tty_opt=conf->tty) == WANOPT_YES){ -#if defined(LINUX_2_4) || defined(LINUX_2_1) int err; card->tty_minor = conf->tty_minor; @@ -582,11 +559,6 @@ if (err){ return err; } -#else - printk(KERN_INFO "%s: Error: TTY driver is not supported on 2.0.X kernels!\n", - card->devname); - return -EINVAL; -#endif }else{ @@ -851,18 +823,6 @@ min_t(unsigned int, conf->slarp_timer, MAX_SLARP_REQ_TIMER) : DEFAULT_SLARP_REQ_TIMER; -#ifdef LINUX_2_0 - if (card->u.c.slarp_timer){ - printk(KERN_INFO - "%s: Error: Dynamic IP support not available for 2.0.X kernels\n", - card->devname); - printk(KERN_INFO "%s: Defaulting to Static IP addressing\n", - card->devname); - } - card->u.c.slarp_timer=0; -#endif - - if (conf->hdlc_streaming == WANOPT_YES) { printk(KERN_INFO "%s: Enabling HDLC STREAMING Mode\n", wandev->name); @@ -892,40 +852,24 @@ } } else if( strcmp(conf->usedby, "API") == 0) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->u.c.usedby = API; printk(KERN_INFO "%s: Running in API mode !\n", wandev->name); -#else - printk(KERN_INFO "%s: API Mode is not supported for kernels lower than 2.2.X!\n", - wandev->name); - printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel fro the API support\n", - wandev->name); - kfree(chdlc_priv_area); - return -EINVAL; -#endif } } -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Tells us that if this interface is a * gateway or not */ if ((chdlc_priv_area->gateway = conf->gateway) == WANOPT_YES){ printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", card->devname,card->u.c.if_name); } -#endif /* Get Multicast Information */ chdlc_priv_area->mc = conf->mc; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.c.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); - sprintf(dev->name, "%s", card->u.c.if_name); -#endif dev->init = &if_init; dev->priv = chdlc_priv_area; @@ -958,9 +902,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -969,10 +910,8 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ @@ -984,16 +923,8 @@ dev->flags |= IFF_MULTICAST; } -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif - if (chdlc_priv_area->true_if_encoding){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) dev->type = ARPHRD_HDLC; /* This breaks the tcpdump */ -#else - dev->type = ARPHRD_PPP; -#endif }else{ dev->type = ARPHRD_PPP; } @@ -1019,11 +950,6 @@ */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif return 0; } @@ -1043,10 +969,9 @@ /* Only one open per interface is allowed */ - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Initialize the work queue entry */ chdlc_priv_area->tq_working=0; @@ -1058,18 +983,11 @@ chdlc_priv_area->bh_head = kmalloc((sizeof(bh_data_t)*(MAX_BH_BUFF+1)),GFP_ATOMIC); memset(chdlc_priv_area->bh_head,0,(sizeof(bh_data_t)*(MAX_BH_BUFF+1))); atomic_set(&chdlc_priv_area->bh_buff_used, 0); -#endif do_gettimeofday(&tv); chdlc_priv_area->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); @@ -1100,8 +1018,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if (chdlc_priv_area->bh_head){ int i; struct sk_buff *skb; @@ -1109,18 +1025,14 @@ for (i=0; i<(MAX_BH_BUFF+1); i++){ skb = ((bh_data_t *)&chdlc_priv_area->bh_head[i])->skb; if (skb != NULL){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } kfree(chdlc_priv_area->bh_head); chdlc_priv_area->bh_head=NULL; } -#endif - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); del_timer(&chdlc_priv_area->poll_delay_timer); return 0; @@ -1136,7 +1048,6 @@ flags->interrupt_info_struct.interrupt_permission = 0; } -#if defined(LINUX_2_4) || defined(LINUX_2_1) if (!tty_init_cnt) return; @@ -1160,7 +1071,6 @@ state = &rs_table[card->tty_minor]; memset(state,0,sizeof(state)); } -#endif return; } @@ -1183,7 +1093,6 @@ } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1203,7 +1112,6 @@ printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); netif_wake_queue (dev); } -#endif @@ -1213,18 +1121,11 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb) { return 1; } -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ - return 1; -} -#endif + /*============================================================================ * Send a packet on a network interface. @@ -1253,9 +1154,7 @@ unsigned long smp_flags; int err=0; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL){ /* If we get here, some higher layer thinks we've missed an @@ -1264,31 +1163,10 @@ printk(KERN_INFO "%s: interface %s got kicked!\n", card->devname, dev->name); - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy){ - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - ++card->wandev.stats.collisions; - if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit timeout !\n", - card->devname); - - /* unbusy the interface */ - clear_bit(0,&dev->tbusy); - } -#endif - if (ntohs(skb->protocol) != htons(PVC_PROT)){ /* check the udp packet type */ @@ -1301,7 +1179,7 @@ chdlc_int->interrupt_permission |= APP_INT_ON_TIMER; } - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1309,8 +1187,8 @@ /* multicast IP address */ if(chk_bcast_mcast_addr(card, dev, skb)){ ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } } @@ -1325,17 +1203,17 @@ printk(KERN_INFO "%s: Critical in if_send: %lx\n", card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } if(card->u.c.state != WAN_CONNECTED){ ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); }else if(!skb->protocol){ ++card->wandev.stats.tx_errors; - start_net_queue(dev); + netif_start_queue(dev); }else { void* data = skb->data; @@ -1355,7 +1233,7 @@ (len <= sizeof(api_tx_hdr_t))) { ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } @@ -1366,25 +1244,21 @@ } if(chdlc_send(card, data, len)) { - stop_net_queue(dev); + netif_stop_queue(dev); }else{ ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif - start_net_queue(dev); + netif_start_queue(dev); -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif } } if_send_exit_crit: - if (!(err=is_queue_stopped(dev))) { - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))) { + dev_kfree_skb_any(skb); }else{ chdlc_priv_area->tick_counter = jiffies; chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; @@ -1409,14 +1283,12 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif + /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 12); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -1425,9 +1297,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -1552,7 +1421,6 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev) { sdla_t *my_card; @@ -1564,19 +1432,7 @@ my_card = chdlc_priv_area->card; return &my_card->wandev.stats; } -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area = dev->priv; - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} -#endif /****** Cisco HDLC Firmware Interface Functions *******************************/ @@ -1846,7 +1702,7 @@ return 0; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) + /********** Bottom Half Handlers ********************************************/ /* NOTE: There is no API, BH support for Kernels lower than 2.2.X. @@ -1873,7 +1729,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); chdlc_work_cleanup(dev); continue; } @@ -1921,7 +1777,7 @@ if (atomic_read(&chan->bh_buff_used) == (MAX_BH_BUFF+1)){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -1940,7 +1796,6 @@ /* END OF API BH Support */ -#endif /****** Interrupt Handlers **************************************************/ @@ -2017,24 +1872,19 @@ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TX_FRAME; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if (card->tty_opt){ wanpipe_tty_trigger_poll(card); break; } - if (dev && is_queue_stopped(dev)){ + if (dev && netif_queue_stopped(dev)){ if (card->u.c.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } -#else - wake_net_dev(dev); -#endif break; case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ @@ -2120,7 +1970,6 @@ len = rxbuf->frame_length; -#if defined(LINUX_2_4) || defined(LINUX_2_1) if (card->tty_opt){ if (rxbuf->error_flag){ @@ -2138,7 +1987,6 @@ wanpipe_tty_receive(card,addr,len); goto rx_exit; } -#endif dev = card->wandev.dev; @@ -2146,7 +1994,7 @@ goto rx_exit; } - if (!is_dev_running(dev)) + if (!netif_running(dev)) goto rx_exit; chdlc_priv_area = dev->priv; @@ -2177,9 +2025,7 @@ skb->protocol = htons(ETH_P_IP); card->wandev.stats.rx_packets ++; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif udp_type = udp_pkt_type( skb, card ); if(udp_type == UDP_CPIPE_TYPE) { @@ -2189,7 +2035,6 @@ interrupt_permission |= APP_INT_ON_TIMER; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) } else if(card->u.c.usedby == API) { api_rx_hdr_t* api_rx_hdr; @@ -2207,7 +2052,6 @@ if (!test_and_set_bit(0,&chdlc_priv_area->tq_working)) wanpipe_queue_work(&chdlc_priv_area->common.wanpipe_work); -#endif }else{ /* FIXME: we should check to see if the received packet is a multicast packet so that we can increment the multicast @@ -2331,7 +2175,6 @@ netdevice_t * dev = card->wandev.dev; chdlc_private_area_t *chdlc_priv_area = dev->priv; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev = dev->ip_ptr; if(in_dev != NULL) { @@ -2344,12 +2187,6 @@ chdlc_priv_area->IP_netmask = ntohl(ifa->ifa_mask); } } -#else - cfg.IP_address = ntohl(dev->pa_addr); - cfg.IP_netmask = ntohl(dev->pa_mask); - chdlc_priv_area->IP_address = ntohl(dev->pa_addr); - chdlc_priv_area->IP_netmask = ntohl(dev->pa_mask); -#endif /* FIXME: We must re-think this message in next release if((cfg.IP_address & 0x000000FF) > 2) { @@ -2647,15 +2484,10 @@ u32 remote_IP_addr = 0; u32 IP_netmask, IP_addr; int err = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; mm_segment_t fs; struct ifreq if_info; struct sockaddr_in *if_data1, *if_data2; -#else - unsigned long fs = 0; - struct rtentry route; -#endif chdlc_priv_area = dev->priv; port_num = card->u.c.comm_port; @@ -2705,7 +2537,6 @@ return; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { @@ -2715,11 +2546,6 @@ IP_netmask = ifa->ifa_mask; } } -#else - local_IP_addr = dev->pa_addr; - remote_IP_addr = dev->pa_dstaddr; - IP_netmask = dev->pa_mask; -#endif }else{ /* According to Cisco HDLC, if the point-to-point address is A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa. @@ -2749,44 +2575,20 @@ fs = get_fs(); /* Save file system */ set_fs(get_ds()); /* Get user space block */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Setup a structure for adding/removing routes */ memset(&if_info, 0, sizeof(if_info)); strcpy(if_info.ifr_name, dev->name); -#else - /* Setup a structure for adding/removing routes */ - dev->pa_mask = IP_netmask; - dev->pa_dstaddr = remote_IP_addr; - dev->pa_addr = local_IP_addr; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; -#endif - switch (chdlc_priv_area->route_status) { case ADD_ROUTE: if(!card->u.c.slarp_timer) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; if_data2->sin_addr.s_addr = remote_IP_addr; if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); -#else - err = ip_rt_new(&route); -#endif } else { -#if defined(LINUX_2_1) || defined(LINUX_2_4) if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; if_data1->sin_addr.s_addr = local_IP_addr; if_data1->sin_family = AF_INET; @@ -2796,9 +2598,6 @@ if_data2->sin_family = AF_INET; err = devinet_ioctl(SIOCSIFDSTADDR, &if_info); } -#else - err = ip_rt_new(&route); -#endif } if(err) { @@ -2819,7 +2618,6 @@ case REMOVE_ROUTE: -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Change the local ip address of the interface to 0. * This will also delete the destination route. */ @@ -2835,11 +2633,6 @@ err = devinet_ioctl(SIOCSIFADDR,&if_info); } -#else - /* set the point-to-point IP address to 0.0.0.0 */ - dev->pa_dstaddr = 0; - err = ip_rt_kill(&route); -#endif if(err) { printk(KERN_INFO "%s: Remove route %u.%u.%u.%u failed, (err %d)\n", @@ -2880,9 +2673,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -3256,9 +3049,7 @@ if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { ++ card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif } } } else { @@ -3808,30 +3599,21 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); if (card->next){ spin_lock(&card->next->wandev.lock); } -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) if (card->next){ spin_unlock(&card->next->wandev.lock); } spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } //*********** TTY SECTION **************** -#if defined(LINUX_2_4) || defined(LINUX_2_1) static void wanpipe_tty_trigger_tx_irq(sdla_t *card) { @@ -3858,8 +3640,7 @@ (tty->ldisc.write_wakeup)(tty); } wake_up_interruptible(&tty->write_wait); -#if defined(SERIAL_HAVE_POLL_WAIT) || \ - (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)) +#if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif return; @@ -4479,8 +4260,7 @@ return; wake_up_interruptible(&tty->write_wait); -#if defined(SERIAL_HAVE_POLL_WAIT) || \ - (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15)) +#if defined(SERIAL_HAVE_POLL_WAIT) wake_up_interruptible(&tty->poll_wait); #endif if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && @@ -4721,8 +4501,6 @@ INIT_WORK(&card->tty_work, tty_poll_work, (void*)card); return 0; } - -#endif MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c --- a/drivers/net/wan/sdla_fr.c Sat Mar 15 18:40:44 2003 +++ b/drivers/net/wan/sdla_fr.c Sat Mar 15 18:40:45 2003 @@ -229,11 +229,7 @@ int inarp_interval; /* Time between InArp Requests */ unsigned long inarp_tick; /* InArp jiffies tick counter */ long interface_down; /* Bring interface down on disconnect */ - #if defined(LINUX_2_1) || defined(LINUX_2_4) struct net_device_stats ifstats; /* interface statistics */ - #else - struct enet_statistics ifstats; - #endif if_send_stat_t drvstats_if_send; rx_intr_stat_t drvstats_rx_intr; pipe_mgmt_stat_t drvstats_gen; @@ -242,14 +238,11 @@ unsigned short transmit_length; struct sk_buff *delay_skb; - - #if defined(LINUX_2_1) || defined(LINUX_2_4) bh_data_t *bh_head; /* Circular buffer for chdlc_bh */ unsigned long tq_working; volatile int bh_write; volatile int bh_read; atomic_t bh_buff_used; - #endif /* Polling task queue. Each interface * has its own task queue, which is used @@ -343,26 +336,14 @@ static int if_open(netdevice_t *dev); static int if_close(netdevice_t *dev); - -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb); -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); -#endif static int if_send(struct sk_buff *skb, netdevice_t *dev); static int chk_bcast_mcast_addr(sdla_t *card, netdevice_t* dev, struct sk_buff *skb); -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev); -#else -static struct enet_statistics* if_stats (netdevice_t* dev); -#endif /* Interrupt handlers */ static void fr_isr(sdla_t *card); @@ -417,13 +398,11 @@ netdevice_t * move_dev_to_next (sdla_t *, netdevice_t *); static int check_tx_status(sdla_t *, netdevice_t *); -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Frame Relay Socket API */ static void trigger_fr_bh (fr_channel_t *); static void fr_bh (netdevice_t *); static int fr_bh_cleanup (netdevice_t *); static int bh_enqueue (netdevice_t *, struct sk_buff *); -#endif static void trigger_fr_poll (netdevice_t *); static void fr_poll (netdevice_t *); @@ -886,26 +865,14 @@ chan->common.usedby = BRIDGE; -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE) mode.\n", card->devname); -#else - printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", - card->devname); - err = -EPROTONOSUPPORT; -#endif }else if( strcmp(conf->usedby, "BRIDGE_N") == 0 ){ chan->common.usedby = BRIDGE_NODE; -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Running in WANPIPE (BRIDGE_NODE) mode.\n", card->devname); -#else - printk(KERN_INFO "%s: WANPIPE Bridging mode not supported in 2.0.X kernels.\n", - card->devname); - err = -EPROTONOSUPPORT; -#endif } if (!err){ @@ -922,18 +889,9 @@ } else if(strcmp(conf->usedby, "API") == 0){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->common.usedby = API; printk(KERN_INFO "%s: Running in API mode.\n", wandev->name); -#else - printk(KERN_INFO "%s: The API Mode is not supported for" - "kernels lower than 2.2.X !\n", - wandev->name); - printk(KERN_INFO "%s: Please upgrade to a 2.2.X kernel for the API support\n", - wandev->name); - err = -EINVAL; -#endif } if (err) { @@ -980,16 +938,9 @@ chan->mc = conf->mc; if (conf->inarp == WANOPT_YES){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: Inverse ARP Support Enabled\n",card->devname); chan->inarp = conf->inarp ? INARP_REQUEST : INARP_NONE; chan->inarp_interval = conf->inarp_interval ? conf->inarp_interval : 10; -#else - printk(KERN_INFO "%s: Warning, Inverse ARP Support not available for 2.0.X kernels!\n", - card->devname); - chan->inarp = INARP_NONE; - chan->inarp_interval = 10; -#endif }else{ printk(KERN_INFO "%s: Inverse ARP Support Disabled\n",card->devname); chan->inarp = INARP_NONE; @@ -1023,17 +974,7 @@ chan->transmit_length = 0; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,chan->name); -#else - dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chan); - return -ENOMEM; - } - sprintf(dev->name, "%s", chan->name); -#endif dev->init = &if_init; dev->priv = chan; @@ -1042,9 +983,6 @@ * We need a poll routine for each network * interface. */ -#ifndef LINUX_2_4 - chan->fr_poll_task.next = NULL; -#endif chan->fr_poll_task.sync = 0; chan->fr_poll_task.routine = (void *)(void *)fr_poll; chan->fr_poll_task.data = dev; @@ -1138,8 +1076,6 @@ int err, len; fr_cmd_t cmd; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if(copy_from_user((void*)&cmd, u_cmd, sizeof(cmd))) return -EFAULT; @@ -1169,44 +1105,6 @@ if (len && u_data && !copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; return 0; - -#else - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(fr_cmd_t))) - return -EFAULT; - - memcpy_fromfs((void*)&cmd, u_cmd, sizeof(cmd)); - - if (cmd.length) { - - if (!u_data || verify_area(VERIFY_READ, u_data, cmd.length)) - return -EFAULT; - } - - /* execute command */ - do - { - memcpy(&mbox->cmd, &cmd, sizeof(cmd)); - - if (cmd.length) - memcpy_fromfs((void*)&mbox->data, u_data, cmd.length); - - if (sdla_exec(mbox)) - err = mbox->cmd.result; - - else return -EIO; - } while (err && retry-- && fr_event(card, err, mbox)); - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(fr_cmd_t)); - len = mbox->cmd.length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)) - memcpy_tofs(u_data, (void*)&mbox->data, len); - - return 0; - -#endif - } /****** Network Device Interface ********************************************/ @@ -1223,9 +1121,6 @@ fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -1234,15 +1129,11 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif if (chan->common.usedby == WANPIPE || chan->common.usedby == API){ -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif + /* Initialize media-specific parameters */ if (chan->true_if_encoding){ dev->type = ARPHRD_DLCI; /* This breaks tcpdump */ @@ -1274,11 +1165,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif }else{ /* Setup the interface for Bridging */ @@ -1315,16 +1201,12 @@ int err = 0; struct timeval tv; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Initialize the task queue */ chan->tq_working=0; -#ifndef LINUX_2_4 - chan->common.wanpipe_task.next = NULL; -#endif chan->common.wanpipe_task.sync = 0; chan->common.wanpipe_task.routine = (void *)(void *)fr_bh; chan->common.wanpipe_task.data = dev; @@ -1333,15 +1215,8 @@ chan->bh_head = kmalloc((sizeof(bh_data_t)*MAX_BH_BUFF),GFP_ATOMIC); memset(chan->bh_head,0,(sizeof(bh_data_t)*MAX_BH_BUFF)); atomic_set(&chan->bh_buff_used, 0); -#endif -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); do_gettimeofday( &tv ); @@ -1370,10 +1245,7 @@ chan->inarp = INARP_REQUEST; } - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); return 0; @@ -1385,18 +1257,10 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff* skb) { -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) netdevice_t *dev = skb->dev; -#endif fr_channel_t* chan = dev->priv; sdla_t* card = chan->card; @@ -1405,7 +1269,6 @@ return 1; } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1429,7 +1292,7 @@ netif_wake_queue (dev); } -#endif + /*============================================================================ * Send a packet on a network interface. @@ -1448,7 +1311,7 @@ * 1. This routine is called either by the protocol stack or by the "net * bottom half" (with interrupts enabled). * - * 2. Using the start_net_queue() and stop_net_queue() MACROS + * 2. Using netif_start_queue() and netif_stop_queue() * will inhibit further transmit requests from the protocol stack * and can be used for flow control with protocol layer. */ @@ -1466,9 +1329,7 @@ chan->drvstats_if_send.if_send_entry++; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL) { /* if we get here, some higher layer thinks we've missed an @@ -1478,7 +1339,7 @@ card->devname, dev->name); chan->drvstats_if_send.if_send_skb_null ++; - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } @@ -1488,8 +1349,8 @@ printk(KERN_INFO "%s: Critical in if_send(): Peripheral running!\n", card->devname); - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1500,37 +1361,13 @@ */ set_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); if(chan->transmit_length) { - stop_net_queue(dev); + netif_stop_queue(dev); chan->tick_counter = jiffies; clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); return 1; } clear_bit(SEND_TXIRQ_CRIT, (void*)&card->wandev.critical); -#ifndef LINUX_2_4 - if (dev->tbusy) { - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - chan->drvstats_if_send.if_send_tbusy++; - ++chan->ifstats.collisions; - - if ((jiffies - chan->tick_counter) < (5 * HZ)) { - return 1; - } - - printk(KERN_INFO "%s: Transmit timed out on %s\n", - card->devname, chan->name); - chan->drvstats_if_send.if_send_tbusy_timeout ++; - dev->tbusy = 0; - } -#endif - - /* Move the if_header() code to here. By inserting frame * relay header in if_header() we would break the * tcpdump and other packet sniffers */ @@ -1539,8 +1376,8 @@ ++chan->ifstats.tx_dropped; ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1557,7 +1394,7 @@ if_send_PIPE_request ++; } } - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1569,8 +1406,8 @@ if(chk_bcast_mcast_addr(card, dev, skb)){ ++chan->ifstats.tx_dropped; ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb, FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } } @@ -1691,26 +1528,22 @@ ++chan->ifstats.tx_packets; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += skb->len; card->wandev.stats.tx_bytes += skb->len; -#endif -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif } } } if_send_start_and_exit: - start_net_queue(dev); + netif_start_queue(dev); /* If we queued the packet for transmission, we must not * deallocate it. The packet is unlinked from the IP stack * not copied. Therefore, we must keep the original packet */ if (!test_bit(1,&delay_tx_queued)) { - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ adptr_flags->imask |= FR_INTR_TXRDY; card->u.f.tx_interrupts_pending ++; @@ -1786,16 +1619,13 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif fr_channel_t* chan = dev->priv; /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 14); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -1804,9 +1634,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -1999,11 +1826,7 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev) -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -#endif { fr_channel_t* chan = dev->priv; @@ -2193,7 +2016,7 @@ skb = dev_alloc_skb(len); - if (!is_dev_running(dev) || (skb == NULL)){ + if (!netif_running(dev) || (skb == NULL)){ ++chan->ifstats.rx_dropped; @@ -2206,11 +2029,11 @@ chan->drvstats_rx_intr.rx_intr_no_socket ++; } - if (!is_dev_running(dev)){ + if (!netif_running(dev)){ chan->drvstats_rx_intr. rx_intr_dev_not_started ++; if (skb){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } goto rx_done; @@ -2252,7 +2075,6 @@ } } -#if defined(LINUX_2_1) || defined(LINUX_2_4) }else if (chan->common.usedby == API) { /* We are in API mode. @@ -2281,7 +2103,6 @@ bh_enqueue(dev, skb); trigger_fr_bh(chan); - #endif }else if (handle_IPXWAN(skb->data,chan->name,chan->enable_IPX, chan->network_number)){ @@ -2289,7 +2110,7 @@ //if (chan->enable_IPX) { // fr_send(card, dlci, 0, skb->len,skb->data); //} - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else if (is_arp(skb->data)) { @@ -2304,7 +2125,7 @@ card->devname); } } - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else if (skb->data[0] != 0x03) { @@ -2312,7 +2133,7 @@ printk(KERN_INFO "%s: Non IETF packet discarded.\n", card->devname); } - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } else { @@ -2341,7 +2162,7 @@ if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); ++chan->drvstats_rx_intr.rx_intr_bfr_not_passed_to_stack; ++chan->ifstats.rx_errors; @@ -2359,10 +2180,8 @@ ++chan->ifstats.rx_packets; ++card->wandev.stats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += len_incl_hdr; card->wandev.stats.rx_bytes += len_incl_hdr; -#endif } rx_done: @@ -2454,36 +2273,28 @@ ++chan->ifstats.tx_packets; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += chan->transmit_length; card->wandev.stats.tx_bytes += chan->transmit_length; -#endif /* We must free an sk buffer, which we used * for delayed transmission; Otherwise, the sock * will run out of memory */ - wan_dev_kfree_skb(chan->delay_skb, FREE_WRITE); + dev_kfree_skb_any(chan->delay_skb); chan->delay_skb = NULL; chan->transmit_length = 0; -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif -#ifdef LINUX_2_0 - wake_net_dev(dev); -#else - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ /* If using API, than wakeup socket BH handler */ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } -#endif } end_of_tx_intr: @@ -2778,8 +2589,6 @@ fr_channel_t *chan = dev->priv; sdla_t *card = chan->card; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - struct ifreq if_info; struct sockaddr_in *if_data; mm_segment_t fs = get_fs(); @@ -2851,66 +2660,6 @@ } /* Case Statement */ -#else - /* Dynamic Route adding/removing */ - struct rtentry route; - int err = 0; - unsigned long fs = get_fs(); - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - - ((struct sockaddr_in *) &(route.rt_dst)) -> - sin_addr.s_addr=dev->pa_dstaddr; - ((struct sockaddr_in *) &(route.rt_dst)) -> - sin_family = AF_INET; - ((struct sockaddr_in *) &(route.rt_genmask)) -> - sin_addr.s_addr = 0xFFFFFFFF; - ((struct sockaddr_in *) &(route.rt_genmask)) -> - sin_family = AF_INET; - switch(chan->route_flag) { - - case ADD_ROUTE: - - set_fs(get_ds()); /* get user space block */ - err = ip_rt_new(&route); - set_fs(fs); /* restore old block */ - - if (err) { - printk(KERN_INFO "%s: Adding of route failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - chan->name, NIPQUAD(dev->pa_dstaddr) ); - } - else { - chan->route_flag = ROUTE_ADDED; - } - break; - - case REMOVE_ROUTE: - - set_fs(get_ds()); /* get user space block */ - err = ip_rt_kill(&route); - set_fs(fs); /* restore old block */ - - if (err) { - printk(KERN_INFO "%s: Deleting of route failed. Error: %d\n", - card->devname,err); - printk(KERN_INFO "%s: Address: %u.%u.%u.%u\n", - dev->name,NIPQUAD(dev->pa_dstaddr) ); - } else { - - printk(KERN_INFO "%s: Removed route.\n", - ((fr_channel_t*)dev->priv)->name); - chan->route_flag = NO_ROUTE; - - } - break; - } - -#endif - } @@ -3468,7 +3217,7 @@ "%s: DLCI %u is inactive!\n", card->devname, dlci); - if (dev && is_dev_running(dev)) + if (dev && netif_running(dev)) set_chan_state(dev, WAN_DISCONNECTED); } @@ -3478,7 +3227,7 @@ "%s: DLCI %u has been deleted!\n", card->devname, dlci); - if (dev && is_dev_running(dev)){ + if (dev && netif_running(dev)){ fr_channel_t *chan = dev->priv; @@ -3743,9 +3492,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -4173,8 +3922,6 @@ { int err=0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - arphdr_1490_t *ArpPacket; arphdr_fr_t *arphdr; fr_channel_t *chan = dev->priv; @@ -4225,47 +3972,6 @@ return 1; } -#else - arphdr_1490_t *ArpPacket; - arphdr_fr_t *arphdr; - fr_channel_t *chan = dev->priv; - - ArpPacket = kmalloc(sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), GFP_ATOMIC); - /* SNAP Header indicating ARP */ - ArpPacket->control = 0x03; - ArpPacket->pad = 0x00; - ArpPacket->NLPID = 0x80; - ArpPacket->OUI[0] = 0; - ArpPacket->OUI[1] = 0; - ArpPacket->OUI[2] = 0; - ArpPacket->PID = 0x0608; - - arphdr = (arphdr_fr_t *)(ArpPacket + 1); // Go to ARP Packet - /* InARP request */ - arphdr->ar_hrd = 0x0F00; /* Frame Relay HW type */ - arphdr->ar_pro = 0x0008; /* IP Protocol */ - arphdr->ar_hln = 2; /* HW addr length */ - arphdr->ar_pln = 4; /* IP addr length */ - arphdr->ar_op = htons(0x08); /* InARP Request */ - arphdr->ar_sha = 0; /* src HW DLCI - Doesn't matter */ - arphdr->ar_sip = dev->pa_addr; /* Local Address */ - arphdr->ar_tha = 0; /* dst HW DLCI - Doesn't matter */ - arphdr->ar_tip = 0; /* Remote Address -- what we want */ - - printk(KERN_INFO "%s: Sending InARP request on DLCI %d.\n", card->devname, chan->dlci); - err = fr_send(card, chan->dlci, 0, - sizeof(arphdr_1490_t) + sizeof(arphdr_fr_t), - (void *)ArpPacket); - - if (!err){ - printk(KERN_INFO "\n%s: Sending InARP request on DLCI %d.\n", - card->devname, chan->dlci); - clear_bit(ARP_CRIT,&card->wandev.critical); - } - - kfree(ArpPacket); -#endif - return 0; } @@ -4293,15 +3999,10 @@ { -#if defined(LINUX_2_1) || defined(LINUX_2_4) arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ fr_rx_buf_ctl_t* frbuf = card->rxmb; struct in_device *in_dev; fr_channel_t *chan = dev->priv; -#else - arphdr_fr_t *arphdr = (arphdr_fr_t *)(ArpPacket + 1); /* Skip header */ - fr_rx_buf_ctl_t* frbuf = card->rxmb; -#endif /* Before we transmit ARP packet, we must check * to see that we are not currently transmitting a @@ -4316,8 +4017,6 @@ return 0; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) - in_dev = dev->ip_ptr; /* Check that IP addresses exist for our network address */ @@ -4434,87 +4133,6 @@ } return 0; -#else - - switch (ntohs(arphdr->ar_op)) { - - case 0x08: // Inverse ARP request -- Send Reply, add route. - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Req\n", - ((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip)); - - - if (dev->pa_mask != 0xFFFFFFFF){ - - if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) { - printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", - card->devname); - return -1; - } - } - - if (dev->pa_addr == arphdr->ar_sip) { - printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - arphdr->ar_op = htons(0x09); /* InARP Reply */ - - /* Set addresses */ - arphdr->ar_tip = arphdr->ar_sip; - arphdr->ar_sip = dev->pa_addr; - - fr_send(card, frbuf->dlci, 0, frbuf->length, (void *)ArpPacket); - - clear_bit(ARP_CRIT,&card->wandev.critical); - - /* Modify Point-to-Point Address */ - dev->pa_dstaddr = arphdr->ar_tip; - - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE; - trigger_fr_poll(dev); - - break; - case 0x09: // Inverse ARP reply - - /* Check for valid Address */ - printk(KERN_INFO "%s: Recvd PtP addr %u.%u.%u.%u -InArp Reply\n", - ((fr_channel_t *)dev->priv)->name, NIPQUAD(arphdr->ar_sip)); - - if ((dev->pa_mask & arphdr->ar_sip) != (dev->pa_mask & dev->pa_addr)) { - printk(KERN_INFO "%s: Invalid PtP address. InARP ignored.\n", - card->devname); - return -1; - } - - if (dev->pa_addr == arphdr->ar_sip) { - printk(KERN_INFO "%s: Local addr = PtP addr. InARP ignored.\n", - card->devname); - return -1; - } - - /* Modify Point-to-Point Address */ - dev->pa_dstaddr = arphdr->ar_sip; - /* Add Route Flag */ - /* The route will be added in the polling routine so - that it is not interrupt context. */ - - ((fr_channel_t *) dev->priv)->route_flag = ADD_ROUTE; - ((fr_channel_t *) dev->priv)->inarp = INARP_CONFIGURED; - trigger_fr_poll(dev); - - break; - default: // ARP's and RARP's -- Shouldn't happen. - } - - return 0; - -#endif } @@ -4706,15 +4324,9 @@ { if (card->hw.type != SDLA_S514){ -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); -#else - disable_irq(card->hw.irq); -#endif }else{ -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock(&card->u.f.if_send_lock); -#endif } return; } @@ -4724,23 +4336,15 @@ { if (card->hw.type != SDLA_S514){ -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock_irqrestore (&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif }else{ -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock(&card->u.f.if_send_lock); -#endif } return; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) - /*---------------------------------------------------------------------- RECEIVE INTERRUPT: BOTTOM HALF HANDLERS ----------------------------------------------------------------------*/ @@ -4770,7 +4374,7 @@ if (atomic_read(&chan->bh_buff_used) == MAX_BH_BUFF){ ++card->wandev.stats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -4859,7 +4463,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ ++card->wandev.stats.rx_dropped; ++chan->ifstats.rx_dropped; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); fr_bh_cleanup(dev); continue; } @@ -4896,7 +4500,6 @@ atomic_dec(&chan->bh_buff_used); return 0; } -#endif /*---------------------------------------------------------------------- @@ -4919,11 +4522,7 @@ static void trigger_fr_poll (netdevice_t *dev) { fr_channel_t* chan = dev->priv; -#ifdef LINUX_2_4 schedule_task(&chan->fr_poll_task); -#else - queue_task(&chan->fr_poll_task, &tq_scheduler); -#endif return; } @@ -5047,7 +4646,7 @@ } } - if (is_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) + if (netif_queue_stopped(dev) || (card->u.f.tx_interrupts_pending)) return 1; return 0; @@ -5295,7 +4894,6 @@ * an Ethernet header */ if (op_mode == BRIDGE || op_mode == BRIDGE_NODE){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Encapsulate the packet as a bridged Ethernet frame. */ #ifdef DEBUG @@ -5316,12 +4914,6 @@ skb->protocol = ETH_P_802_3; return 8; -#else - - /* BRIDGING is not supported in 2.0.X */ - return -EINVAL; - -#endif } return 0; diff -Nru a/drivers/net/wan/sdla_ft1.c b/drivers/net/wan/sdla_ft1.c --- a/drivers/net/wan/sdla_ft1.c Sat Mar 15 18:40:40 2003 +++ b/drivers/net/wan/sdla_ft1.c Sat Mar 15 18:40:40 2003 @@ -252,8 +252,6 @@ CHDLC_MAILBOX_STRUCT* mbox = card->mbox; int len; - -#if defined(LINUX_2_1) || defined(LINUX_2_4) if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){ return -EFAULT; } @@ -281,36 +279,6 @@ if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){ return -EFAULT; } - -#else - - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ft1_exec_cmd_t))){ - return -EFAULT; - } - - memcpy_fromfs((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t)); - - len = mbox->buffer_length; - - if (len) { - if (!u_data || verify_area(VERIFY_READ, u_data, len)) - return -EFAULT; - memcpy_fromfs((void*)&mbox->data, u_data, len); - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t)); - len = mbox->buffer_length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)){ - memcpy_tofs(u_data, (void*)&mbox->data, len); - } - -#endif return 0; diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c --- a/drivers/net/wan/sdla_ppp.c Sat Mar 15 18:40:40 2003 +++ b/drivers/net/wan/sdla_ppp.c Sat Mar 15 18:40:40 2003 @@ -104,15 +104,9 @@ #include /* sockaddr_in */ -/* ---- 2.4.X KERNEL SUPPORT -----------------------*/ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include - #include -#else - #include - #include /* Adding new route entries : 2.0.X kernels */ -#endif +#include +#include +#include #include #include /* PPP firmware API definitions */ @@ -163,10 +157,6 @@ #define NUM_AUTH_REQ_WITHOUT_REPLY 10 #define END_OFFSET 0x1F0 -#if LINUX_VERSION_CODE < 0x020125 -#define test_and_set_bit set_bit -#define net_ratelimit() 1 -#endif /******Data Structures*****************************************************/ @@ -255,18 +245,10 @@ static int if_header(struct sk_buff *skb, netdevice_t *dev, unsigned short type, void *daddr, void *saddr, unsigned len); -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr(struct sk_buff *skb); static struct net_device_stats *if_stats(netdevice_t *dev); -#else -static struct enet_statistics *if_stats(netdevice_t *dev); -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb); -#endif static int if_send(struct sk_buff *skb, netdevice_t *dev); @@ -615,17 +597,7 @@ } /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.p.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.p.if_name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(ppp_priv_area); - return -ENOMEM; - } - sprintf(dev->name, "%s", card->u.p.if_name); -#endif dev->init = &if_init; dev->priv = ppp_priv_area; @@ -673,7 +645,6 @@ ppp_mbox_t *mbox = card->mbox; int len; -#if defined(LINUX_2_1) || defined(LINUX_2_4) if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) return -EFAULT; @@ -698,35 +669,6 @@ if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) return -EFAULT; -#else - - if (!u_cmd || verify_area(VERIFY_WRITE, u_cmd, sizeof(ppp_cmd_t))) - return -EFAULT; - - memcpy_fromfs((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t)); - - len = mbox->cmd.length; - - if (len) { - - if (!u_data || verify_area(VERIFY_READ, u_data, len)) - return -EFAULT; - } - - /* execute command */ - if (!sdla_exec(mbox)) - return -EIO; - - /* return result */ - memcpy_tofs(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t)); - len = mbox->cmd.length; - - if (len && u_data && !verify_area(VERIFY_WRITE, u_data, len)) - memcpy_tofs(u_data, (void*)&mbox->data, len); - - -#endif - return 0; } @@ -744,9 +686,6 @@ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; wan_device_t *wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -755,10 +694,8 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ dev->type = ARPHRD_PPP; /* ARP h/w type */ @@ -770,9 +707,6 @@ dev->flags |= IFF_MULTICAST; } -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif dev->mtu = wandev->mtu; dev->hard_header_len = PPP_HDR_LEN; /* media header length */ @@ -786,12 +720,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ - #if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); - #endif - return 0; } @@ -809,18 +737,12 @@ struct timeval tv; //unsigned long smp_flags; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; wanpipe_open(card); -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif do_gettimeofday( &tv ); ppp_priv_area->router_start_time = tv.tv_sec; @@ -852,10 +774,7 @@ ppp_private_area_t *ppp_priv_area = dev->priv; sdla_t *card = ppp_priv_area->card; - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); del_timer (&ppp_priv_area->poll_delay_timer); @@ -894,7 +813,6 @@ * Return: 1 physical address resolved. * 0 physical address not resolved */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static int if_rebuild_hdr (struct sk_buff *skb) { netdevice_t *dev = skb->dev; @@ -906,16 +824,6 @@ return 1; } -#else -static int if_rebuild_hdr (void* hdr, netdevice_t* dev, unsigned long raddr, - struct sk_buff* skb) -{ - return 1; - -} -#endif - -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -937,7 +845,6 @@ ++chan->if_send_stat.if_send_tbusy_timeout; netif_wake_queue (dev); } -#endif @@ -970,9 +877,7 @@ ++ppp_priv_area->if_send_stat.if_send_entry; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL) { @@ -984,36 +889,10 @@ ++ppp_priv_area->if_send_stat.if_send_skb_null; - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy) { - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - - ++ppp_priv_area->if_send_stat.if_send_tbusy; - ++card->wandev.stats.collisions; - - if ((jiffies - ppp_priv_area->tick_counter) < (5*HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit times out on %s\n",card->devname,dev->name); - - ++ppp_priv_area->if_send_stat.if_send_tbusy_timeout; - ++card->wandev.stats.collisions; - - /* unbusy the card (because only one interface per card)*/ - dev->tbusy = 0; - } -#endif - sendpacket = skb->data; udp_type = udp_pkt_type( skb, card ); @@ -1025,7 +904,7 @@ flags->imask |= PPP_INTR_TIMER; } ++ppp_priv_area->if_send_stat.if_send_PIPE_request; - start_net_queue(dev); + netif_start_queue(dev); return 0; } @@ -1034,8 +913,8 @@ */ if(chk_bcast_mcast_addr(card, dev, skb)){ ++card->wandev.stats.tx_dropped; - wan_dev_kfree_skb(skb,FREE_WRITE); - start_net_queue(dev); + dev_kfree_skb_any(skb); + netif_start_queue(dev); return 0; } @@ -1051,7 +930,7 @@ ++card->wandev.stats.tx_dropped; ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } @@ -1059,12 +938,12 @@ ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); } else if (!skb->protocol) { ++ppp_priv_area->if_send_stat.if_send_protocol_error; ++card->wandev.stats.tx_errors; - start_net_queue(dev); + netif_start_queue(dev); } else { @@ -1075,32 +954,28 @@ ppp_priv_area->network_number, 0); } else { ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_exit_crit; } } if (ppp_send(card, skb->data, skb->len, skb->protocol)) { - stop_net_queue(dev); + netif_stop_queue(dev); ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; } else { ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += skb->len; -#endif - start_net_queue(dev); -#ifdef LINUX_2_4 + netif_start_queue(dev); dev->trans_start = jiffies; -#endif } } if_send_exit_crit: - if (!(err=is_queue_stopped(dev))){ - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))){ + dev_kfree_skb_any(skb); }else{ ppp_priv_area->tick_counter = jiffies; flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ @@ -1134,13 +1009,8 @@ udp_pkt_stored = 1; }else{ if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ -#if defined(LINUX_2_1) || defined(LINUX_2_4) printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", card->devname, skb->len); -#else - printk(KERN_INFO "%s: PIPEMON UDP request too long : %li\n", - card->devname, skb->len); -#endif }else{ printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", card->devname); @@ -1149,9 +1019,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); @@ -1319,11 +1189,7 @@ * Get ethernet-style interface statistics. * Return a pointer to struct net_device_stats. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats *if_stats(netdevice_t *dev) -#else -static struct enet_statistics *if_stats(netdevice_t *dev) -#endif { ppp_private_area_t *ppp_priv_area = dev->priv; @@ -1743,7 +1609,7 @@ case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ ++card->statistics.isr_tx; flags->imask &= ~PPP_INTR_TXRDY; - wake_net_dev(dev); + netif_wake_queue(dev); break; case PPP_INTR_CMD: /* interface command completed */ @@ -1821,7 +1687,7 @@ return; } - if (dev && is_dev_running(dev) && dev->priv){ + if (dev && netif_running(dev) && dev->priv){ len = rxbuf->length; ppp_priv_area = dev->priv; @@ -1881,7 +1747,7 @@ if (!test_bit(SEND_CRIT, &card->wandev.critical)){ ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); } - wan_dev_kfree_skb(skb,FREE_READ); + dev_kfree_skb_any(skb); } else { ++card->wandev.stats.rx_dropped; @@ -1892,9 +1758,7 @@ skb->mac.raw = skb->data; ++card->wandev.stats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); dev->last_rx = jiffies; @@ -2244,8 +2108,6 @@ netdevice_t *dev = card->wandev.dev; ppp_private_area_t *ppp_priv_area = dev->priv; -#if defined(LINUX_2_1) || defined(LINUX_2_4) - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && (flags->ip_state == 0x09)){ @@ -2276,29 +2138,6 @@ } } } -#else - - if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && - (flags->ip_state == 0x09)){ - - if (ppp_priv_area->ip_local == 0) - return; - - printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname); - if (read_info( card )) { - printk(KERN_INFO - "%s: An error occurred in IP assignment.\n", - card->devname); - } else { - printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", - card->devname, NIPQUAD(dev->pa_addr)); - printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%U\n", - card->devname, NIPQUAD(dev->pa_dstaddr)); - } - } - -#endif - } /*============================================================================ @@ -2328,9 +2167,7 @@ static int config508(netdevice_t *dev, sdla_t *card) { ppp508_conf_t cfg; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev = dev->ip_ptr; -#endif ppp_private_area_t *ppp_priv_area = dev->priv; /* Prepare PPP configuration structure */ @@ -2393,14 +2230,8 @@ printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname); cfg.ip_options = L_AND_R_IP_NO_ASSIG | ENABLE_IP; -#if defined(LINUX_2_1) || defined(LINUX_2_4) cfg.ip_local = in_dev->ifa_list->ifa_local; cfg.ip_remote = in_dev->ifa_list->ifa_address; -#else - cfg.ip_local = dev->pa_addr; - cfg.ip_remote = dev->pa_dstaddr; -#endif - /* Debugging code used to check that IP addresses * obtained from the kernel are correct */ @@ -2414,14 +2245,8 @@ cfg.ip_options = L_IP_LOCAL_ASSIG | R_IP_LOCAL_ASSIG | ENABLE_IP; -#if defined(LINUX_2_1) || defined(LINUX_2_4) cfg.ip_local = in_dev->ifa_list->ifa_local; cfg.ip_remote = in_dev->ifa_list->ifa_address; -#else - cfg.ip_local = dev->pa_addr; - cfg.ip_remote = dev->pa_dstaddr; -#endif - /* Debugging code used to check that IP addresses * obtained from the kernel are correct */ NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", @@ -2431,8 +2256,6 @@ case WANOPT_PPP_PEER: -#if defined(LINUX_2_1) || defined(LINUX_2_4) - printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname); cfg.ip_options = L_IP_REMOTE_ASSIG | R_IP_REMOTE_ASSIG | @@ -2441,16 +2264,6 @@ cfg.ip_remote = 0x00; break; -#else - - /* No PEER support for 2.0.X kernels, drop down to default - * condition */ - - printk(KERN_INFO "%s: ERROR, PEER mode is not supported in 2.0.X kernels\n", - card->devname); - -#endif - default: printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n", card->devname); @@ -3038,19 +2851,9 @@ ppp_private_area_t *ppp_priv_area = dev->priv; int err; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct ifreq if_info; struct sockaddr_in *if_data1, *if_data2; mm_segment_t fs; -#else -#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_ - struct rtentry route; -#endif -#endif - - - -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Set Local and remote addresses */ memset(&if_info, 0, sizeof(if_info)); @@ -3074,39 +2877,6 @@ set_fs(fs); /* restore old block */ -#else - /* FIXME: Dynamic Routing in 2.0.X kernels is not - * supported. Sorry ! I'll come back to it when I get - * a chance. */ - - printk(KERN_INFO "%s: ERROR, Dynamic routing is not supported in 2.0.X kernels\n", - card->devname); - printk(KERN_INFO "%s: Please use the STATIC IP mode!\n", - card->devname); - - err = 0; - -#ifdef _DYNAMIC_ROUTE_20X_SUPPORT_ - dev->pa_dstaddr = ppp_priv_area->ip_remote; - dev->pa_addr = ppp_priv_area->ip_local; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; - - err = ip_rt_new(&route); - -#endif - -#endif - if (err) { printk (KERN_INFO "%s: Adding of route failed: %i\n", card->devname,err); @@ -3130,32 +2900,21 @@ long ip_addr; int err; -#if defined(LINUX_2_1) || defined(LINUX_2_4) mm_segment_t fs; struct ifreq if_info; struct sockaddr_in *if_data1; struct in_device *in_dev = dev->ip_ptr; struct in_ifaddr *ifa = in_dev->ifa_list; -#else - unsigned long fs = 0; - struct rtentry route; -#endif - -#if defined(LINUX_2_1) || defined(LINUX_2_4) ip_addr = ifa->ifa_local; /* Set Local and remote addresses */ memset(&if_info, 0, sizeof(if_info)); strcpy(if_info.ifr_name, dev->name); -#endif - fs = get_fs(); set_fs(get_ds()); /* get user space block */ - -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* Change the local ip address of the interface to 0. * This will also delete the destination route. */ @@ -3163,26 +2922,6 @@ if_data1->sin_addr.s_addr = 0; if_data1->sin_family = AF_INET; err = devinet_ioctl( SIOCSIFADDR, &if_info ); -#else - - ip_addr = dev->pa_addr; - dev->pa_dstaddr = 0; - - memset(&route, 0, sizeof(route)); - route.rt_dev = dev->name; - route.rt_flags = 0; - ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr = - dev->pa_dstaddr; - ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr = - 0xFFFFFFFF; - ((struct sockaddr_in *)&(route.rt_genmask))->sin_family = - AF_INET; - - - err = ip_rt_kill(&route); - -#endif set_fs(fs); /* restore old block */ @@ -3288,14 +3027,12 @@ { u32 src_ip_addr; u32 broadcast_ip_addr = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct in_device *in_dev; -#endif + /* read the IP source address from the outgoing packet */ src_ip_addr = *(u32 *)(skb->data + 12); /* read the IP broadcast address for the device */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) in_dev = dev->ip_ptr; if(in_dev != NULL) { struct in_ifaddr *ifa= in_dev->ifa_list; @@ -3304,9 +3041,6 @@ else return 0; } -#else - broadcast_ip_addr = dev->pa_brdaddr; -#endif /* check if the IP Source Address is a Broadcast address */ if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { @@ -3328,20 +3062,12 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } static int read_connection_info (sdla_t *card) diff -Nru a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c --- a/drivers/net/wan/sdla_x25.c Sat Mar 15 18:40:43 2003 +++ b/drivers/net/wan/sdla_x25.c Sat Mar 15 18:40:43 2003 @@ -95,12 +95,7 @@ #include #include /* Experimental delay */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include -#else - #include - #include -#endif +#include #include #include @@ -281,11 +276,7 @@ int ch_idx; unsigned char enable_IPX; unsigned long network_number; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct net_device_stats ifstats; /* interface statistics */ -#else - struct enet_statistics ifstats; -#endif unsigned short transmit_length; unsigned short tx_offset; char transmit_buffer[X25_CHAN_MTU+sizeof(x25api_hdr_t)]; @@ -369,9 +360,7 @@ static int if_send (struct sk_buff* skb, netdevice_t* dev); static struct net_device_stats *if_stats (netdevice_t* dev); -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif /*================================================= * Interrupt handlers @@ -792,9 +781,6 @@ init_global_statistics(card); -#ifndef LINUX_2_4 - card->u.x.x25_poll_task.next = NULL; -#endif card->u.x.x25_poll_task.sync=0; card->u.x.x25_poll_task.routine = (void*)(void*)wpx_poll; card->u.x.x25_poll_task.data = card; @@ -1011,18 +997,8 @@ chan->network_number = 0xDEADBEEF; /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,chan->name); -#else - dev->name = (char *)kmalloc(strlen(chan->name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chan); - dev->priv = NULL; - return -ENOMEM; - } - sprintf(dev->name, "%s", chan->name); -#endif + dev->init = &if_init; init_x25_channel_struct(chan); @@ -1124,9 +1100,6 @@ x25_channel_t* chan = dev->priv; sdla_t* card = chan->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* Initialize device driver entry points */ dev->open = &if_open; @@ -1135,19 +1108,11 @@ dev->rebuild_header = &if_rebuild_hdr; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; - -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif /* Initialize media-specific parameters */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) dev->type = ARPHRD_PPP; /* ARP h/w type */ -#else - dev->family = AF_INET; /* address family */ - dev->type = ARPHRD_PPP; /* no x25 type */ -#endif dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_NOARP; @@ -1174,11 +1139,6 @@ /* Set transmit buffer queue length */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif /* FIXME Why are we doing this */ set_chan_state(dev, WAN_DISCONNECTED); return 0; @@ -1214,15 +1174,12 @@ struct timeval tv; unsigned long smp_flags; - if (is_dev_running(dev)) + if (netif_running(dev)) return -EBUSY; chan->tq_working = 0; /* Initialize the task queue */ -#ifndef LINUX_2_4 - chan->common.wanpipe_task.next = NULL; -#endif chan->common.wanpipe_task.sync = 0; chan->common.wanpipe_task.routine = (void *)(void *)x25api_bh; chan->common.wanpipe_task.data = dev; @@ -1276,13 +1233,8 @@ do_gettimeofday( &tv ); chan->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif + return 0; } @@ -1314,10 +1266,7 @@ sdla_t* card = chan->card; unsigned long smp_flags; - stop_net_queue(dev); -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); if ((chan->common.state == WAN_CONNECTED) || (chan->common.state == WAN_CONNECTING)){ @@ -1336,7 +1285,7 @@ for (i=0; i<(MAX_BH_BUFF+1); i++){ skb = ((bh_data_t *)&chan->bh_head[i])->skb; if (skb != NULL){ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } kfree(chan->bh_head); @@ -1405,7 +1354,6 @@ } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -1425,7 +1373,6 @@ card->devname, dev->name); netif_wake_queue (dev); } -#endif /*========================================================================= @@ -1457,33 +1404,11 @@ ++chan->if_send_stat.if_send_entry; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif /* No need to check frame length, since socket code * will perform the check for us */ -#ifndef LINUX_2_4 - if (dev->tbusy){ - netdevice_t *dev2; - - ++chan->if_send_stat.if_send_tbusy; - if ((jiffies - chan->tick_counter) < (5*HZ)){ - return 1; - } - printk(KERN_INFO "%s: Transmit time out %s!\n", - card->devname, dev->name); - - for( dev2 = card->wandev.dev; dev2; - dev2 = *((netdevice_t**)dev2->priv)){ - - dev2->tbusy = 0; - } - ++chan->if_send_stat.if_send_tbusy_timeout; - } -#endif - chan->tick_counter = jiffies; /* Critical region starts here */ @@ -1506,7 +1431,7 @@ chan->if_send_stat.if_send_PIPE_request++; } } - start_net_queue(dev); + netif_start_queue(dev); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); S508_S514_unlock(card, &smp_flags); return 0; @@ -1518,7 +1443,7 @@ chan->transmit_length=0; atomic_set(&chan->common.driver_busy,0); }else{ - stop_net_queue(dev); + netif_stop_queue(dev); ++card->u.x.tx_interrupts_pending; status->imask |= INTR_ON_TX_FRAME; clear_bit(SEND_CRIT,(void*)&card->wandev.critical); @@ -1589,9 +1514,9 @@ if_send_crit_exit: - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); - start_net_queue(dev); + netif_start_queue(dev); clear_bit(SEND_CRIT,(void*)&card->wandev.critical); S508_S514_unlock(card, &smp_flags); return 0; @@ -1787,14 +1712,12 @@ ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return; } ++chan->ifstats.rx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len; -#endif chan->rx_skb = NULL; @@ -1814,7 +1737,7 @@ /* Decapsulate packet, if necessary */ if (!skb->protocol && !wanrouter_type_trans(skb, dev)){ /* can't decapsulate packet */ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); ++chan->ifstats.rx_errors; ++chan->ifstats.rx_dropped; ++card->wandev.stats.rx_dropped; @@ -1829,7 +1752,7 @@ if(chan_send(dev, skb->data, skb->len,0)){ chan->tx_skb = skb; }else{ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; } }else{ @@ -1839,9 +1762,7 @@ } }else{ skb->mac.raw = skb->data; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.rx_bytes += skb->len; -#endif ++chan->ifstats.rx_packets; ++chan->rx_intr_stat.rx_intr_bfr_passed_to_stack; netif_rx(skb); @@ -1898,7 +1819,7 @@ if (skb_tailroom(new_skb) < len){ /* No room for the packet. Call off the whole thing! */ - wan_dev_kfree_skb(new_skb, FREE_READ); + dev_kfree_skb_any(new_skb); if (chan->common.usedby == WANPIPE){ chan->rx_skb = NULL; if (qdm & 0x01){ @@ -1985,12 +1906,12 @@ chan->transmit_length = 0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } dev = move_dev_to_next(card,dev); @@ -2092,12 +2013,12 @@ /* If we are in API mode, wakeup the * sock BH handler, not the NET_BH */ - if (is_queue_stopped(dev)){ + if (netif_queue_stopped(dev)){ if (chan->common.usedby == API){ - start_net_queue(dev); + netif_start_queue(dev); wakeup_sk_bh(dev); }else{ - wake_net_dev(dev); + netif_wake_queue(dev); } } return 0; @@ -2342,11 +2263,7 @@ static void trigger_x25_poll(sdla_t *card) { -#ifdef LINUX_2_4 schedule_task(&card->u.x.x25_poll_task); -#else - queue_task(&card->u.x.x25_poll_task, &tq_scheduler); -#endif } /*==================================================================== @@ -3658,8 +3575,8 @@ chan->transmit_length=0; atomic_set(&chan->common.driver_busy,0); chan->tx_offset=0; - if (is_queue_stopped(dev)){ - wake_net_dev(dev); + if (netif_queue_stopped(dev)){ + netif_wake_queue(dev); } } atomic_set(&chan->common.command,0); @@ -3766,9 +3683,7 @@ case 0x00: /* success */ chan->i_timeout_sofar = jiffies; -#ifdef LINUX_2_4 dev->trans_start=jiffies; -#endif if ((qdm & M_BIT) && !card->u.x.LAPB_hdlc){ if (!tx_intr){ @@ -3780,9 +3695,7 @@ chan->tx_offset += len; ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif if (chan->tx_offset < orig_len){ setup_for_delayed_transmit (dev, buff, data_len); @@ -3795,9 +3708,7 @@ * be X number of times larger than max data size. */ ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif ++chan->if_send_stat.if_send_bfr_passed_to_adptr; chan->tx_offset += len; @@ -3817,9 +3728,7 @@ } }else{ ++chan->ifstats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) chan->ifstats.tx_bytes += len; -#endif ++chan->if_send_stat.if_send_bfr_passed_to_adptr; res=0; } @@ -4288,7 +4197,7 @@ if (chan->common.sk == NULL || chan->common.func == NULL){ printk(KERN_INFO "%s: BH: Socket disconnected, dropping\n", card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); x25api_bh_cleanup(dev); ++chan->ifstats.rx_dropped; ++chan->rx_intr_stat.rx_intr_bfr_not_passed_to_stack; @@ -4745,7 +4654,7 @@ if (card->func(skb,card->sk) < 0){ printk(KERN_INFO "%s: MAJOR ERROR: Failed to send up place call \n",card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return 1; } @@ -4912,7 +4821,7 @@ if (chan->common.func(skb,dev,chan->common.sk) < 0){ if (bh_enqueue(dev,skb)){ printk(KERN_INFO "%s: Dropping OOB MSG\n",card->devname); - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } } @@ -4940,7 +4849,7 @@ if (skb_tailroom(new_skb) < len){ /* No room for the packet. Call off the whole thing! */ - wan_dev_kfree_skb(new_skb, FREE_READ); + dev_kfree_skb_any(new_skb); printk(KERN_INFO "%s: Listen: unexpectedly long packet sequence\n" ,card->devname); *skb = NULL; @@ -5448,9 +5357,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK){ - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); }else{ - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); } return(udp_pkt_stored); diff -Nru a/drivers/net/wan/sdladrv.c b/drivers/net/wan/sdladrv.c --- a/drivers/net/wan/sdladrv.c Sat Mar 15 18:40:40 2003 +++ b/drivers/net/wan/sdladrv.c Sat Mar 15 18:40:40 2003 @@ -108,16 +108,8 @@ #define _OUTB(port, byte) (outb((byte),(port))) #define SYSTEM_TICK jiffies +#include -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include -#else - #include /* BIOS32, PCI BIOS functions and definitions */ - #define ioremap vremap - #define iounmap vfree - extern void * vremap (unsigned long offset, unsigned long size); - extern void vfree (void *addr); -#endif #elif defined(_SCO_UNIX_) /****** SCO Unix ****************************/ @@ -381,9 +373,7 @@ * < 0 error */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_setup); -#endif int sdla_setup (sdlahw_t* hw, void* sfm, unsigned len) { @@ -528,9 +518,7 @@ * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_down); -#endif int sdla_down (sdlahw_t* hw) { @@ -572,7 +560,6 @@ *(char *)hw->vector = S514_CPU_HALT; CPU_no = hw->S514_cpu_no[0]; -#if defined(LINUX_2_1) || defined(LINUX_2_4) /* disable the PCI IRQ and disable memory access */ pci_read_config_dword(hw->pci_dev, PCI_INT_CONFIG, &int_config); int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; @@ -585,22 +572,6 @@ else pci_write_config_dword(hw->pci_dev, PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE); -#else - /* disable the PCI IRQ and disable memory access */ - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, &int_config); - int_config &= (CPU_no == S514_CPU_A) ? ~PCI_DISABLE_IRQ_CPU_A : ~PCI_DISABLE_IRQ_CPU_B; - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, int_config); - read_S514_int_stat(hw, &int_status); - S514_intack(hw, int_status); - // disable PCI memory access - if(CPU_no == S514_CPU_A) - pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func, - PCI_MAP0_DWORD, PCI_CPU_A_MEM_DISABLE); - else - pcibios_write_config_dword(hw->pci_bus,hw->pci_dev_func, PCI_MAP1_DWORD, PCI_CPU_B_MEM_DISABLE); -#endif /* free up the allocated virtual memory */ iounmap((void *)hw->dpmbase); @@ -618,9 +589,7 @@ * Map shared memory window into SDLA address space. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_mapmem); -#endif int sdla_mapmem (sdlahw_t* hw, unsigned long addr) { @@ -681,9 +650,7 @@ * Enable interrupt generation. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_inten); -#endif int sdla_inten (sdlahw_t* hw) { @@ -739,9 +706,7 @@ * Disable interrupt generation. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intde); -#endif int sdla_intde (sdlahw_t* hw) { @@ -796,9 +761,7 @@ * Acknowledge SDLA hardware interrupt. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intack); -#endif int sdla_intack (sdlahw_t* hw) { @@ -848,18 +811,11 @@ * Acknowledge S514 hardware interrupt. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(S514_intack); -#endif void S514_intack (sdlahw_t* hw, u32 int_status) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_write_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -#else - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_STATUS, int_status); -#endif } @@ -867,18 +823,11 @@ * Read the S514 hardware interrupt status. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(read_S514_int_stat); -#endif void read_S514_int_stat (sdlahw_t* hw, u32* int_status) { -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_read_config_dword(hw->pci_dev, PCI_INT_STATUS, int_status); -#else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_STATUS, - int_status); -#endif } @@ -886,9 +835,7 @@ * Generate an interrupt to adapter's CPU. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_intr); -#endif int sdla_intr (sdlahw_t* hw) { @@ -932,9 +879,7 @@ * o Return number of loops made, or 0 if command timed out. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_exec); -#endif int sdla_exec (void* opflag) { @@ -970,9 +915,7 @@ * interrupt routines are accessing adapter shared memory. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_peek); -#endif int sdla_peek (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) { @@ -1054,9 +997,7 @@ * interrupt routines are accessing adapter shared memory. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(sdla_poke); -#endif int sdla_poke (sdlahw_t* hw, unsigned long addr, void* buf, unsigned len) { @@ -1961,20 +1902,11 @@ int number_S514_cards = 0; u32 S514_mem_base_addr = 0; u32 ut_u32; - -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev; -#else - u8 ut_u8; -#endif #ifdef CONFIG_PCI -#if defined(LINUX_2_1) || defined(LINUX_2_4) if(!pci_present()) -#else - if(!pcibios_present()) -#endif { printk(KERN_INFO "%s: PCI BIOS not present!\n", modname); return 0; @@ -2029,26 +1961,12 @@ } } - #if defined(LINUX_2_4) pci_dev = hw->pci_dev; /* read the physical memory base address */ S514_mem_base_addr = (CPU_no == S514_CPU_A) ? (pci_dev->resource[1].start) : (pci_dev->resource[2].start); - #elif defined (LINUX_2_1) - pci_dev = hw->pci_dev; - /* read the physical memory base address */ - S514_mem_base_addr = (CPU_no == S514_CPU_A) ? - (pci_dev->base_address[1] & PCI_BASE_ADDRESS_MEM_MASK) : - (pci_dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK); - - #else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MEM_BASE0_DWORD : - PCI_MEM_BASE1_DWORD, &S514_mem_base_addr); - #endif - printk(KERN_INFO "%s: S514 PCI memory at 0x%X\n", modname, S514_mem_base_addr); if(!S514_mem_base_addr) { @@ -2060,24 +1978,14 @@ } /* enable the PCI memory */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) pci_read_config_dword(pci_dev, (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, &ut_u32); pci_write_config_dword(pci_dev, (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, (ut_u32 | PCI_MEMORY_ENABLE)); -#else - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - &ut_u32); - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - (CPU_no == S514_CPU_A) ? PCI_MAP0_DWORD : PCI_MAP1_DWORD, - (ut_u32 | PCI_MEMORY_ENABLE)); -#endif /* check the IRQ allocated and enable IRQ usage */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) if(!(hw->irq = pci_dev->irq)) { printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", modname); @@ -2099,29 +2007,6 @@ ut_u32 |= (CPU_no == S514_CPU_A) ? PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; pci_write_config_dword(pci_dev, PCI_INT_CONFIG, ut_u32); -#else - /* the INTPIN must not be 0 - if it is, then the S514 adapter is not */ - /* configured for IRQ usage */ - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_PIN_BYTE, &ut_u8); - if(!ut_u8) { - printk(KERN_INFO "%s: invalid setting for INTPIN on S514 card\n", modname); - printk(KERN_INFO "Please contact your Sangoma representative\n"); - return 0; - } - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_LINE_BYTE, (unsigned char *)&hw->irq); - if(hw->irq == PCI_IRQ_NOT_ALLOCATED) { - printk(KERN_INFO "%s: IRQ not allocated to S514 adapter\n", - modname); - return 0; - } - pcibios_read_config_dword(hw->pci_bus, hw->pci_dev_func, PCI_INT_CONFIG, &ut_u32); - ut_u32 |= (CPU_no == S514_CPU_A) ? - PCI_ENABLE_IRQ_CPU_A : PCI_ENABLE_IRQ_CPU_B; - pcibios_write_config_dword(hw->pci_bus, hw->pci_dev_func, - PCI_INT_CONFIG, ut_u32); -#endif printk(KERN_INFO "%s: IRQ %d allocated to the S514 card\n", modname, hw->irq); @@ -2157,15 +2042,10 @@ char S514_found_in_slot = 0; u16 PCI_subsys_vendor; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev = NULL; -#else - int pci_index; -#endif slot_no = hw->S514_slot_no; -#if defined(LINUX_2_1) || defined(LINUX_2_4) while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) != NULL) { @@ -2197,40 +2077,6 @@ } } -#else - //LINUX VERSION 2.0.X - for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) { - if (pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index, - &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) { - break; - } - - pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func, - PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor); - - if (PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - if (find_first_S514_card) - return(1); - - number_S514_cards ++; - - printk(KERN_INFO "%s: S514 card found, bus #%d, slot #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK)); - - if (hw->auto_pci_cfg){ - hw->S514_slot_no = ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) - slot_no = hw->S514_slot_no; - - }else if (((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK) == slot_no) { - S514_found_in_slot = 1; - break; - } - } -#endif - /* if no S514 adapter has been found, then exit */ if (!number_S514_cards) { printk(KERN_INFO "%s: Error, no S514 adapters found\n", modname); @@ -2408,17 +2254,11 @@ u16 PCI_subsys_vendor; u16 PCI_card_type; -#if defined(LINUX_2_1) || defined(LINUX_2_4) struct pci_dev *pci_dev = NULL; struct pci_bus *bus = NULL; -#else - int pci_index; - u8 irq; -#endif slot_no = 0; -#if defined(LINUX_2_1) || defined(LINUX_2_4) while ((pci_dev = pci_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_dev)) != NULL) { @@ -2453,52 +2293,13 @@ } } -#else - for (pci_index = 0; pci_index < MAX_S514_CARDS; pci_index ++) { - - if(pcibios_find_device(V3_VENDOR_ID, V3_DEVICE_ID, pci_index, - &hw->pci_bus, &hw->pci_dev_func)!=PCIBIOS_SUCCESSFUL) { - break; - } - pcibios_read_config_word(hw->pci_bus, hw->pci_dev_func, - PCI_SUBSYS_VENDOR_WORD, &PCI_subsys_vendor); - if(PCI_subsys_vendor != SANGOMA_SUBSYS_VENDOR) - continue; - - pcibios_read_config_word(hw->pci_bus,hw->pci_dev_func,PCI_CARD_TYPE, - &PCI_card_type); - - pcibios_read_config_byte(hw->pci_bus, hw->pci_dev_func, - PCI_INT_LINE_BYTE, &irq); - - /* A dual cpu card can support up to 4 physical connections, - * where a single cpu card can support up to 2 physical - * connections. The FT1 card can only support a single - * connection, however we cannot distinguish between a Single - * CPU card and an FT1 card. */ - if (PCI_card_type == S514_DUAL_CPU){ - number_S514_cards += 4; - printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 2, bus #%d, slot #%d, irq #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq); - }else{ - printk(KERN_INFO "%s: S514-PCI card found, cpu(s) 1, bus #%d, slot #%d, irq #%d\n", - modname, hw->pci_bus, - ((hw->pci_dev_func >> 3) & PCI_DEV_SLOT_MASK),irq); - number_S514_cards += 2; - } - } -#endif - return number_S514_cards; } -#if defined(LINUX_2_1) || defined(LINUX_2_4) EXPORT_SYMBOL(wanpipe_hw_probe); -#endif unsigned wanpipe_hw_probe(void) { diff -Nru a/drivers/net/wan/sdlamain.c b/drivers/net/wan/sdlamain.c --- a/drivers/net/wan/sdlamain.c Sat Mar 15 18:40:43 2003 +++ b/drivers/net/wan/sdlamain.c Sat Mar 15 18:40:43 2003 @@ -64,26 +64,10 @@ #include #include -#if defined(LINUX_2_4) +#define netdevice_t struct net_device - #include /* kernel <-> user copy */ - #include - #define netdevice_t struct net_device - -#elif defined(LINUX_2_1) - - #include /* kernel <-> user copy */ - #include - #define netdevice_t struct device - -#else - - #include - #define devinet_ioctl(x,y) dev_ioctl(x,y) - #define netdevice_t struct device - #define test_and_set_bit set_bit - typedef unsigned long mm_segment_t; -#endif +#include /* kernel <-> user copy */ +#include #include #include @@ -240,23 +224,12 @@ * function, which will execute all pending, * tasks in wanpipe_tq_custom queue */ -#ifdef LINUX_2_4 DECLARE_TASK_QUEUE(wanpipe_tq_custom); static struct tq_struct wanpipe_tq_task = { .routine = (void (*)(void *)) run_wanpipe_tq, .data = &wanpipe_tq_custom }; -#else -static struct tq_struct *wanpipe_tq_custom = NULL; -static struct tq_struct wanpipe_tq_task = -{ - NULL, - 0, - (void *)(void *) run_wanpipe_tq, - &wanpipe_tq_custom -}; -#endif static int wanpipe_bh_critical=0; @@ -511,9 +484,7 @@ if (!card->configured){ /* Initialize the Spin lock */ -#if defined(__SMP__) || defined(LINUX_2_4) printk(KERN_INFO "%s: Initializing for SMP\n",wandev->name); -#endif /* Piggyback spin lock has already been initialized, * in check_s514/s508_conflicts() */ @@ -974,26 +945,13 @@ unsigned long smp_flags; int err = 0; - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_from_user((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t))) return -EFAULT; - #else - if ((u_dump == NULL) || - verify_area(VERIFY_READ, u_dump, sizeof(sdla_dump_t))) - return -EFAULT; - memcpy_fromfs((void*)&dump, (void*)u_dump, sizeof(sdla_dump_t)); - #endif if ((dump.magic != WANPIPE_MAGIC) || (dump.offset + dump.length > card->hw.memory)) return -EINVAL; - #ifdef LINUX_2_0 - if ((dump.ptr == NULL) || - verify_area(VERIFY_WRITE, dump.ptr, dump.length)) - return -EFAULT; - #endif - winsize = card->hw.dpmsize; if(card->hw.type != SDLA_S514) { @@ -1014,17 +972,13 @@ break; } - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_to_user((void *)dump.ptr, (u8 *)card->hw.dpmbase + pos, len)){ unlock_adapter_irq(&card->wandev.lock, &smp_flags); return -EFAULT; } - #else - memcpy_tofs((void*)(dump.ptr), - (void*)(card->hw.dpmbase + pos), len); - #endif + dump.length -= len; dump.offset += len; (char*)dump.ptr += len; @@ -1035,15 +989,10 @@ }else { - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_to_user((void *)dump.ptr, (u8 *)card->hw.dpmbase + dump.offset, dump.length)){ return -EFAULT; } - #else - memcpy_tofs((void*)(dump.ptr), - (void*)(card->hw.dpmbase + dump.offset), dump.length); - #endif } return err; @@ -1064,15 +1013,8 @@ return -ENODEV; } - #if defined(LINUX_2_1) || defined(LINUX_2_4) if(copy_from_user((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t))) return -EFAULT; - #else - if ((u_exec == NULL) || - verify_area(VERIFY_READ, u_exec, sizeof(sdla_exec_t))) - return -EFAULT; - memcpy_fromfs((void*)&exec, (void*)u_exec, sizeof(sdla_exec_t)); - #endif if ((exec.magic != WANPIPE_MAGIC) || (exec.cmd == NULL)) return -EINVAL; @@ -1345,60 +1287,33 @@ unsigned long get_ip_address (netdevice_t *dev, int option) { - #ifdef LINUX_2_4 struct in_ifaddr *ifaddr; struct in_device *in_dev; if ((in_dev = __in_dev_get(dev)) == NULL){ return 0; } - #elif defined(LINUX_2_1) - struct in_ifaddr *ifaddr; - struct in_device *in_dev; - - if ((in_dev = dev->ip_ptr) == NULL){ - return 0; - } - #endif - #if defined(LINUX_2_1) || defined(LINUX_2_4) if ((ifaddr = in_dev->ifa_list)== NULL ){ return 0; } - #endif switch (option){ case WAN_LOCAL_IP: - #ifdef LINUX_2_0 - return dev->pa_addr; - #else return ifaddr->ifa_local; - #endif break; case WAN_POINTOPOINT_IP: - #ifdef LINUX_2_0 - return dev->pa_dstaddr; - #else return ifaddr->ifa_address; - #endif break; case WAN_NETMASK_IP: - #ifdef LINUX_2_0 - return dev->pa_mask; - #else return ifaddr->ifa_mask; - #endif break; case WAN_BROADCAST_IP: - #ifdef LINUX_2_0 - return dev->pa_brdaddr; - #else return ifaddr->ifa_broadcast; - #endif break; default: return 0; @@ -1431,11 +1346,7 @@ oldfs = get_fs(); set_fs(get_ds()); - #if defined(LINUX_2_1) || defined(LINUX_2_4) res = ip_rt_ioctl(SIOCADDRT,&route); - #else - res = ip_rt_new(&route); - #endif set_fs(oldfs); if (res == 0){ diff -Nru a/drivers/net/wan/wanpipe_multppp.c b/drivers/net/wan/wanpipe_multppp.c --- a/drivers/net/wan/wanpipe_multppp.c Sat Mar 15 18:40:45 2003 +++ b/drivers/net/wan/wanpipe_multppp.c Sat Mar 15 18:40:45 2003 @@ -42,19 +42,11 @@ #include -#if defined(LINUX_2_1) || defined(LINUX_2_4) - #include - #include +#include +#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3) - #include -#else - #include "syncppp.h" -#endif +#include -#else - #include /* Adding new route entries */ -#endif /****** Defines & Macros ****************************************************/ @@ -148,15 +140,9 @@ static int if_open (netdevice_t* dev); static int if_close (netdevice_t* dev); static int if_send (struct sk_buff* skb, netdevice_t* dev); -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev); -#else -static struct enet_statistics* if_stats (netdevice_t* dev); -#endif -#ifdef LINUX_2_4 static void if_tx_timeout (netdevice_t *dev); -#endif /* CHDLC Firmware interface functions */ static int chdlc_configure (sdla_t* card, void* data); @@ -601,18 +587,8 @@ /* prepare network device data space for registration */ -#ifdef LINUX_2_4 strcpy(dev->name,card->u.c.if_name); -#else - dev->name = (char *)kmalloc(strlen(card->u.c.if_name) + 2, GFP_KERNEL); - if(dev->name == NULL) - { - kfree(chdlc_priv_area); - return -ENOMEM; - } - sprintf(dev->name, "%s", card->u.c.if_name); -#endif - + /* Attach PPP protocol layer to pppdev * The sppp_attach() will initilize the dev structure * and setup ppp layer protocols. @@ -620,11 +596,7 @@ * if_open(), if_close(), if_send() and get_stats() functions. */ sppp_attach(pppdev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,16) dev = pppdev->dev; -#else - dev = &pppdev->dev; -#endif sp = &pppdev->sppp; /* Enable PPP Debugging */ @@ -684,9 +656,6 @@ chdlc_private_area_t* chdlc_priv_area = dev->priv; sdla_t* card = chdlc_priv_area->card; wan_device_t* wandev = &card->wandev; -#ifdef LINUX_2_0 - int i; -#endif /* NOTE: Most of the dev initialization was * done in sppp_attach(), called by new_if() @@ -699,16 +668,10 @@ dev->stop = &if_close; dev->hard_start_xmit = &if_send; dev->get_stats = &if_stats; -#ifdef LINUX_2_4 dev->tx_timeout = &if_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; -#endif -#ifdef LINUX_2_0 - dev->family = AF_INET; -#endif - /* Initialize hardware parameters */ dev->irq = wandev->irq; dev->dma = wandev->dma; @@ -724,17 +687,10 @@ */ dev->tx_queue_len = 100; - /* Initialize socket buffers */ -#if !defined(LINUX_2_1) && !defined(LINUX_2_4) - for (i = 0; i < DEV_NUMBUFFS; ++i) - skb_queue_head_init(&dev->buffs[i]); -#endif - return 0; } -#ifdef LINUX_2_4 /*============================================================================ * Handle transmit timeout event from netif watchdog */ @@ -754,8 +710,6 @@ printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); netif_wake_queue (dev); } -#endif - /*============================================================================ @@ -773,14 +727,8 @@ SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags; /* Only one open per interface is allowed */ - -#ifdef LINUX_2_4 if (netif_running(dev)) return -EBUSY; -#else - if (dev->start) - return -EBUSY; /* only one open is allowed */ -#endif /* Start PPP Layer */ if (sppp_open(dev)){ @@ -790,13 +738,7 @@ do_gettimeofday(&tv); chdlc_priv_area->router_start_time = tv.tv_sec; -#ifdef LINUX_2_4 netif_start_queue(dev); -#else - dev->interrupt = 0; - dev->tbusy = 0; - dev->start = 1; -#endif wanpipe_open(card); @@ -817,11 +759,7 @@ /* Stop the PPP Layer */ sppp_close(dev); - stop_net_queue(dev); - -#ifndef LINUX_2_4 - dev->start=0; -#endif + netif_stop_queue(dev); wanpipe_close(card); @@ -855,9 +793,7 @@ unsigned long smp_flags; int err=0; -#ifdef LINUX_2_4 netif_stop_queue(dev); -#endif if (skb == NULL){ @@ -867,32 +803,10 @@ printk(KERN_INFO "%s: Received NULL skb buffer! interface %s got kicked!\n", card->devname, dev->name); - wake_net_dev(dev); + netif_wake_queue(dev); return 0; } -#ifndef LINUX_2_4 - if (dev->tbusy){ - - /* If our device stays busy for at least 5 seconds then we will - * kick start the device by making dev->tbusy = 0. We expect - * that our device never stays busy more than 5 seconds. So this - * is only used as a last resort. - */ - ++card->wandev.stats.collisions; - - if((jiffies - chdlc_priv_area->tick_counter) < (5 * HZ)) { - return 1; - } - - printk (KERN_INFO "%s: Transmit (tbusy) timeout !\n", - card->devname); - - /* unbusy the interface */ - dev->tbusy = 0; - } -#endif - if (ntohs(skb->protocol) != htons(PVC_PROT)){ /* check the udp packet type */ @@ -903,7 +817,7 @@ chdlc_int->interrupt_permission |= APP_INT_ON_TIMER; } - start_net_queue(dev); + netif_start_queue(dev); return 0; } } @@ -918,33 +832,29 @@ printk(KERN_INFO "%s: Critical in if_send: %lx\n", card->wandev.name,card->wandev.critical); ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_crit_exit; } if (card->wandev.state != WAN_CONNECTED){ ++card->wandev.stats.tx_dropped; - start_net_queue(dev); + netif_start_queue(dev); goto if_send_crit_exit; } if (chdlc_send(card, skb->data, skb->len)){ - stop_net_queue(dev); + netif_stop_queue(dev); }else{ ++card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += skb->len; -#endif -#ifdef LINUX_2_4 dev->trans_start = jiffies; -#endif - start_net_queue(dev); + netif_start_queue(dev); } if_send_crit_exit: - if (!(err=is_queue_stopped(dev))){ - wan_dev_kfree_skb(skb, FREE_WRITE); + if (!(err=netif_queue_stopped(dev))){ + dev_kfree_skb_any(skb); }else{ chdlc_priv_area->tick_counter = jiffies; chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME; @@ -1063,7 +973,6 @@ * Get ethernet-style interface statistics. * Return a pointer to struct enet_statistics. */ -#if defined(LINUX_2_1) || defined(LINUX_2_4) static struct net_device_stats* if_stats (netdevice_t* dev) { sdla_t *my_card; @@ -1079,23 +988,7 @@ my_card = chdlc_priv_area->card; return &my_card->wandev.stats; } -#else -static struct enet_statistics* if_stats (netdevice_t* dev) -{ - sdla_t *my_card; - chdlc_private_area_t* chdlc_priv_area = dev->priv; - /* Shutdown bug fix. In del_if() we kill - * dev->priv pointer. This function, gets - * called after del_if(), thus check - * if pointer has been deleted */ - if ((chdlc_priv_area=dev->priv) == NULL) - return NULL; - - my_card = chdlc_priv_area->card; - return &my_card->wandev.stats; -} -#endif /****** Cisco HDLC Firmware Interface Functions *******************************/ @@ -1417,7 +1310,7 @@ flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_TX_FRAME; - wake_net_dev(dev); + netif_wake_queue(dev); break; case COMMAND_COMPLETE_APP_INT_PEND:/* 0x04: cmd cplt */ @@ -1505,15 +1398,9 @@ goto rx_exit; } -#ifdef LINUX_2_4 if (!netif_running(dev)){ goto rx_exit; } -#else - if (!dev->start){ - goto rx_exit; - } -#endif chdlc_priv_area = dev->priv; @@ -1555,9 +1442,7 @@ skb->protocol = htons(ETH_P_WAN_PPP); card->wandev.stats.rx_packets ++; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.rx_bytes += skb->len; -#endif udp_type = udp_pkt_type( skb, card ); if(udp_type == UDP_CPIPE_TYPE) { @@ -1795,9 +1680,9 @@ } if(udp_pkt_src == UDP_PKT_FRM_STACK) - wan_dev_kfree_skb(skb, FREE_WRITE); + dev_kfree_skb_any(skb); else - wan_dev_kfree_skb(skb, FREE_READ); + dev_kfree_skb_any(skb); return(udp_pkt_stored); } @@ -2156,9 +2041,7 @@ if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) { ++ card->wandev.stats.tx_packets; -#if defined(LINUX_2_1) || defined(LINUX_2_4) card->wandev.stats.tx_bytes += len; -#endif } } else { @@ -2360,28 +2243,20 @@ void s508_lock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) spin_lock_irqsave(&card->wandev.lock, *smp_flags); if (card->next){ /* It is ok to use spin_lock here, since we * already turned off interrupts */ spin_lock(&card->next->wandev.lock); } -#else - disable_irq(card->hw.irq); -#endif } void s508_unlock (sdla_t *card, unsigned long *smp_flags) { -#if defined(__SMP__) || defined(LINUX_2_4) if (card->next){ spin_unlock(&card->next->wandev.lock); } spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); -#else - enable_irq(card->hw.irq); -#endif } diff -Nru a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c --- a/drivers/oprofile/buffer_sync.c Sat Mar 15 18:40:40 2003 +++ b/drivers/oprofile/buffer_sync.c Sat Mar 15 18:40:40 2003 @@ -277,10 +277,7 @@ */ static struct mm_struct * take_task_mm(struct task_struct * task) { - struct mm_struct * mm; - task_lock(task); - mm = task->mm; - task_unlock(task); + struct mm_struct * mm = task->mm; /* if task->mm !NULL, mm_count must be at least 1. It cannot * drop to 0 without the task exiting, which will have to sleep @@ -310,6 +307,32 @@ } +/* compute number of filled slots in cpu_buffer queue */ +static unsigned long nr_filled_slots(struct oprofile_cpu_buffer * b) +{ + unsigned long head = b->head_pos; + unsigned long tail = b->tail_pos; + + if (head >= tail) + return head - tail; + + return head + (b->buffer_size - tail); +} + + +static void increment_tail(struct oprofile_cpu_buffer * b) +{ + unsigned long new_tail = b->tail_pos + 1; + + rmb(); + + if (new_tail < (b->buffer_size)) + b->tail_pos = new_tail; + else + b->tail_pos = 0; +} + + /* Sync one of the CPU's buffers into the global event buffer. * Here we need to go through each batch of samples punctuated * by context switch notes, taking the task's mmap_sem and doing @@ -322,10 +345,14 @@ struct task_struct * new; unsigned long cookie; int in_kernel = 1; - int i; + unsigned int i; - for (i=0; i < cpu_buf->pos; ++i) { - struct op_sample * s = &cpu_buf->buffer[i]; + /* Remember, only we can modify tail_pos */ + + unsigned long const available_elements = nr_filled_slots(cpu_buf); + + for (i=0; i < available_elements; ++i) { + struct op_sample * s = &cpu_buf->buffer[cpu_buf->tail_pos]; if (is_ctx_switch(s->eip)) { if (s->event <= 1) { @@ -345,6 +372,8 @@ } else { add_sample(mm, s, in_kernel); } + + increment_tail(cpu_buf); } release_mm(mm); @@ -369,17 +398,8 @@ cpu_buf = &cpu_buffer[i]; - /* We take a spin lock even though we might - * sleep. It's OK because other users are try - * lockers only, and this region is already - * protected by buffer_sem. It's raw to prevent - * the preempt bogometer firing. Fruity, huh ? */ - if (cpu_buf->pos > 0) { - _raw_spin_lock(&cpu_buf->int_lock); - add_cpu_switch(i); - sync_buffer(cpu_buf); - _raw_spin_unlock(&cpu_buf->int_lock); - } + add_cpu_switch(i); + sync_buffer(cpu_buf); } up(&buffer_sem); diff -Nru a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c --- a/drivers/oprofile/cpu_buffer.c Sat Mar 15 18:40:39 2003 +++ b/drivers/oprofile/cpu_buffer.c Sat Mar 15 18:40:39 2003 @@ -26,8 +26,6 @@ struct oprofile_cpu_buffer cpu_buffer[NR_CPUS] __cacheline_aligned; -static unsigned long buffer_size; - static void __free_cpu_buffers(int num) { int i; @@ -47,7 +45,7 @@ { int i; - buffer_size = fs_cpu_buffer_size; + unsigned long buffer_size = fs_cpu_buffer_size; for (i=0; i < NR_CPUS; ++i) { struct oprofile_cpu_buffer * b = &cpu_buffer[i]; @@ -59,12 +57,12 @@ if (!b->buffer) goto fail; - spin_lock_init(&b->int_lock); - b->pos = 0; b->last_task = 0; b->last_is_kernel = -1; + b->buffer_size = buffer_size; + b->tail_pos = 0; + b->head_pos = 0; b->sample_received = 0; - b->sample_lost_locked = 0; b->sample_lost_overflow = 0; b->sample_lost_task_exit = 0; } @@ -80,11 +78,38 @@ __free_cpu_buffers(NR_CPUS); } - -/* Note we can't use a semaphore here as this is supposed to - * be safe from any context. Instead we trylock the CPU's int_lock. - * int_lock is taken by the processing code in sync_cpu_buffers() - * so we avoid disturbing that. + +/* compute number of available slots in cpu_buffer queue */ +static unsigned long nr_available_slots(struct oprofile_cpu_buffer const * b) +{ + unsigned long head = b->head_pos; + unsigned long tail = b->tail_pos; + + if (tail > head) + return tail - head; + + return tail + (b->buffer_size - head); +} + + +static void increment_head(struct oprofile_cpu_buffer * b) +{ + unsigned long new_head = b->head_pos + 1; + + /* Ensure anything written to the slot before we + * increment is visible */ + wmb(); + + if (new_head < (b->buffer_size)) + b->head_pos = new_head; + else + b->head_pos = 0; +} + + +/* This must be safe from any context. It's safe writing here + * because of the head/tail separation of the writer and reader + * of the CPU buffer. * * is_kernel is needed because on some architectures you cannot * tell if you are in kernel or user space simply by looking at @@ -101,14 +126,10 @@ cpu_buf->sample_received++; - if (!spin_trylock(&cpu_buf->int_lock)) { - cpu_buf->sample_lost_locked++; - return; - } - if (cpu_buf->pos > buffer_size - 2) { + if (nr_available_slots(cpu_buf) < 3) { cpu_buf->sample_lost_overflow++; - goto out; + return; } task = current; @@ -116,18 +137,18 @@ /* notice a switch from user->kernel or vice versa */ if (cpu_buf->last_is_kernel != is_kernel) { cpu_buf->last_is_kernel = is_kernel; - cpu_buf->buffer[cpu_buf->pos].eip = ~0UL; - cpu_buf->buffer[cpu_buf->pos].event = is_kernel; - cpu_buf->pos++; + cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; + cpu_buf->buffer[cpu_buf->head_pos].event = is_kernel; + increment_head(cpu_buf); } /* notice a task switch */ if (cpu_buf->last_task != task) { cpu_buf->last_task = task; if (!(task->flags & PF_EXITING)) { - cpu_buf->buffer[cpu_buf->pos].eip = ~0UL; - cpu_buf->buffer[cpu_buf->pos].event = (unsigned long)task; - cpu_buf->pos++; + cpu_buf->buffer[cpu_buf->head_pos].eip = ~0UL; + cpu_buf->buffer[cpu_buf->head_pos].event = (unsigned long)task; + increment_head(cpu_buf); } } @@ -138,23 +159,20 @@ */ if (task->flags & PF_EXITING) { cpu_buf->sample_lost_task_exit++; - goto out; + return; } - cpu_buf->buffer[cpu_buf->pos].eip = eip; - cpu_buf->buffer[cpu_buf->pos].event = event; - cpu_buf->pos++; -out: - spin_unlock(&cpu_buf->int_lock); + cpu_buf->buffer[cpu_buf->head_pos].eip = eip; + cpu_buf->buffer[cpu_buf->head_pos].event = event; + increment_head(cpu_buf); } + /* resets the cpu buffer to a sane state - should be called with * cpu_buf->int_lock held */ void cpu_buffer_reset(struct oprofile_cpu_buffer *cpu_buf) { - cpu_buf->pos = 0; - /* reset these to invalid values; the next sample * collected will populate the buffer with proper * values to initialize the buffer @@ -162,4 +180,3 @@ cpu_buf->last_is_kernel = -1; cpu_buf->last_task = 0; } - diff -Nru a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h --- a/drivers/oprofile/cpu_buffer.h Sat Mar 15 18:40:44 2003 +++ b/drivers/oprofile/cpu_buffer.h Sat Mar 15 18:40:44 2003 @@ -30,14 +30,13 @@ }; struct oprofile_cpu_buffer { - spinlock_t int_lock; - /* protected by int_lock */ - unsigned long pos; + volatile unsigned long head_pos; + volatile unsigned long tail_pos; + unsigned long buffer_size; struct task_struct * last_task; int last_is_kernel; struct op_sample * buffer; unsigned long sample_received; - unsigned long sample_lost_locked; unsigned long sample_lost_overflow; unsigned long sample_lost_task_exit; } ____cacheline_aligned; diff -Nru a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c --- a/drivers/oprofile/oprofile_stats.c Sat Mar 15 18:40:43 2003 +++ b/drivers/oprofile/oprofile_stats.c Sat Mar 15 18:40:43 2003 @@ -27,7 +27,6 @@ cpu_buf = &cpu_buffer[i]; cpu_buf->sample_received = 0; - cpu_buf->sample_lost_locked = 0; cpu_buf->sample_lost_overflow = 0; cpu_buf->sample_lost_task_exit = 0; } @@ -63,8 +62,6 @@ */ oprofilefs_create_ro_ulong(sb, cpudir, "sample_received", &cpu_buf->sample_received); - oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_locked", - &cpu_buf->sample_lost_locked); oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_overflow", &cpu_buf->sample_lost_overflow); oprofilefs_create_ro_ulong(sb, cpudir, "sample_lost_task_exit", diff -Nru a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c --- a/drivers/parport/ieee1284.c Sat Mar 15 18:40:39 2003 +++ b/drivers/parport/ieee1284.c Sat Mar 15 18:40:39 2003 @@ -170,7 +170,7 @@ { int ret; int usec; - long deadline; + unsigned long deadline; unsigned char status; usec = port->physport->spintime; /* usecs of fast polling */ diff -Nru a/drivers/parport/ieee1284_ops.c b/drivers/parport/ieee1284_ops.c --- a/drivers/parport/ieee1284_ops.c Sat Mar 15 18:40:44 2003 +++ b/drivers/parport/ieee1284_ops.c Sat Mar 15 18:40:44 2003 @@ -58,7 +58,7 @@ parport_write_control (port, ctl); parport_data_forward (port); while (count < len) { - long expire = jiffies + dev->timeout; + unsigned long expire = jiffies + dev->timeout; long wait = (HZ + 99) / 100; unsigned char mask = (PARPORT_STATUS_ERROR | PARPORT_STATUS_BUSY); @@ -431,7 +431,7 @@ | PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { - long expire = jiffies + port->cad->timeout; + unsigned long expire = jiffies + port->cad->timeout; unsigned char byte; byte = *buf; @@ -520,7 +520,7 @@ parport_write_control (port, ctl | PARPORT_CONTROL_AUTOFD); while (count < len) { - long expire = jiffies + dev->timeout; + unsigned long expire = jiffies + dev->timeout; unsigned char byte; int command; @@ -668,7 +668,7 @@ PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_INIT); for (written = 0; written < len; written++, buf++) { - long expire = jiffies + port->cad->timeout; + unsigned long expire = jiffies + port->cad->timeout; unsigned char byte; byte = *buf; diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Sat Mar 15 18:40:44 2003 +++ b/drivers/pci/Makefile Sat Mar 15 18:40:44 2003 @@ -2,7 +2,7 @@ # Makefile for the PCI bus specific drivers. # -obj-y += access.o probe.o pci.o pool.o quirks.o \ +obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ names.o pci-driver.o search.o hotplug.o \ pci-sysfs.o obj-$(CONFIG_PM) += power.o diff -Nru a/drivers/pci/bus.c b/drivers/pci/bus.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/bus.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,127 @@ +/* + * drivers/pci/bus.c + * + * From setup-res.c, by: + * Dave Rusling (david.rusling@reo.mts.dec.com) + * David Mosberger (davidm@cs.arizona.edu) + * David Miller (davem@redhat.com) + * Ivan Kokshaysky (ink@jurassic.park.msu.ru) + */ +#include +#include +#include +#include +#include +#include +#include + +#include "pci.h" + +/** + * pci_bus_alloc_resource - allocate a resource from a parent bus + * @bus: PCI bus + * @res: resource to allocate + * @size: size of resource to allocate + * @align: alignment of resource to allocate + * @min: minimum /proc/iomem address to allocate + * @type_mask: IORESOURCE_* type flags + * @alignf: resource alignment function + * @alignf_data: data argument for resource alignment function + * + * Given the PCI bus a device resides on, the size, minimum address, + * alignment and type, try to find an acceptable resource allocation + * for a specific device resource. + */ +int +pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, + unsigned long size, unsigned long align, unsigned long min, + unsigned int type_mask, + void (*alignf)(void *, struct resource *, + unsigned long, unsigned long), + void *alignf_data) +{ + int i, ret = -ENOMEM; + + type_mask |= IORESOURCE_IO | IORESOURCE_MEM; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *r = bus->resource[i]; + if (!r) + continue; + + /* type_mask must match */ + if ((res->flags ^ r->flags) & type_mask) + continue; + + /* We cannot allocate a non-prefetching resource + from a pre-fetching area */ + if ((r->flags & IORESOURCE_PREFETCH) && + !(res->flags & IORESOURCE_PREFETCH)) + continue; + + /* Ok, try it out.. */ + ret = allocate_resource(r, res, size, min, -1, align, + alignf, alignf_data); + if (ret == 0) + break; + } + return ret; +} + +/** + * pci_bus_add_devices - insert newly discovered PCI devices + * @bus: bus to check for new devices + * + * Add newly discovered PCI devices (which are on the bus->devices + * list) to the global PCI device list, add the sysfs and procfs + * entries. Where a bridge is found, add the discovered bus to + * the parents list of child buses, and recurse. + * + * Call hotplug for each new devices. + */ +void __devinit pci_bus_add_devices(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + /* + * Skip already-present devices (which are on the + * global device list.) + */ + if (!list_empty(&dev->global_list)) + continue; + + device_register(&dev->dev); + list_add_tail(&dev->global_list, &pci_devices); +#ifdef CONFIG_PROC_FS + pci_proc_attach_device(dev); +#endif + pci_create_sysfs_dev_files(dev); + + /* + * If there is an unattached subordinate bus, attach + * it and then scan for unattached PCI devices. + */ + if (dev->subordinate && list_empty(&dev->subordinate->node)) { + list_add_tail(&dev->subordinate->node, &dev->bus->children); + pci_bus_add_devices(dev->subordinate); + } + } +} + +void pci_enable_bridges(struct pci_bus *bus) +{ + struct pci_dev *dev; + + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->subordinate) { + pci_enable_device(dev); + pci_set_master(dev); + pci_enable_bridges(dev->subordinate); + } + } +} + +EXPORT_SYMBOL(pci_bus_alloc_resource); +EXPORT_SYMBOL(pci_bus_add_devices); +EXPORT_SYMBOL(pci_enable_bridges); diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Sat Mar 15 18:40:43 2003 +++ b/drivers/pci/probe.c Sat Mar 15 18:40:43 2003 @@ -221,47 +221,64 @@ b = kmalloc(sizeof(*b), GFP_KERNEL); if (b) { memset(b, 0, sizeof(*b)); + INIT_LIST_HEAD(&b->node); INIT_LIST_HEAD(&b->children); INIT_LIST_HEAD(&b->devices); } return b; } -struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +static struct pci_bus * __devinit +pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) { struct pci_bus *child; - int i; /* * Allocate a new bus, and inherit stuff from the parent.. */ child = pci_alloc_bus(); - list_add_tail(&child->node, &parent->children); - child->self = dev; - dev->subordinate = child; - child->parent = parent; - child->ops = parent->ops; - child->sysdata = parent->sysdata; - child->dev = &dev->dev; + if (child) { + int i; - /* - * Set up the primary, secondary and subordinate - * bus numbers. - */ - child->number = child->secondary = busnr; - child->primary = parent->secondary; - child->subordinate = 0xff; - - /* Set up default resource pointers and names.. */ - for (i = 0; i < 4; i++) { - child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; - child->resource[i]->name = child->name; + child->self = bridge; + child->parent = parent; + child->ops = parent->ops; + child->sysdata = parent->sysdata; + child->dev = &bridge->dev; + + /* + * Set up the primary, secondary and subordinate + * bus numbers. + */ + child->number = child->secondary = busnr; + child->primary = parent->secondary; + child->subordinate = 0xff; + + /* Set up default resource pointers and names.. */ + for (i = 0; i < 4; i++) { + child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i]; + child->resource[i]->name = child->name; + } + + bridge->subordinate = child; } return child; } +struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) +{ + struct pci_bus *child; + + child = pci_alloc_child_bus(parent, dev, busnr); + if (child) + list_add_tail(&child->node, &parent->children); + return child; +} + +static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus); + /* * If it's a bridge, configure it and scan the bus behind it. * For CardBus bridges, we don't scan behind as the devices will @@ -288,12 +305,12 @@ */ if (pass) return max; - child = pci_add_new_bus(bus, dev, 0); + child = pci_alloc_child_bus(bus, dev, 0); child->primary = buses & 0xFF; child->secondary = (buses >> 8) & 0xFF; child->subordinate = (buses >> 16) & 0xFF; child->number = child->secondary; - cmax = pci_do_scan_bus(child); + cmax = pci_scan_child_bus(child); if (cmax > max) max = cmax; } else { /* @@ -306,18 +323,27 @@ /* Clear errors */ pci_write_config_word(dev, PCI_STATUS, 0xffff); - child = pci_add_new_bus(bus, dev, ++max); + child = pci_alloc_child_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->secondary) << 8) | ((unsigned int)(child->subordinate) << 16); + + /* + * yenta.c forces a secondary latency timer of 176. + * Copy that behaviour here. + */ + if (is_cardbus) + buses = (buses & 0x00ffffff) | (176 << 24); + /* * We need to blast all three values with a single write. */ pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses); + if (!is_cardbus) { /* Now we can scan all subordinate buses... */ - max = pci_do_scan_bus(child); + max = pci_scan_child_bus(child); } else { /* * For CardBus bridges, we leave 4 bus numbers @@ -374,7 +400,8 @@ dev->class = class; class >>= 8; - DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, dev->vendor, dev->device, class, dev->hdr_type); + DBG("Found %02x:%02x [%04x/%04x] %06x %02x\n", dev->bus->number, dev->devfn, + dev->vendor, dev->device, class, dev->hdr_type); /* "Unknown power state" */ dev->current_state = 4; @@ -427,23 +454,35 @@ * Read the config data for a PCI device, sanity-check it * and fill in the dev structure... */ -struct pci_dev * __devinit pci_scan_device(struct pci_dev *temp) +static struct pci_dev * __devinit +pci_scan_device(struct pci_bus *bus, int devfn) { struct pci_dev *dev; u32 l; + u8 hdr_type; + + if (pci_bus_read_config_byte(bus, devfn, PCI_HEADER_TYPE, &hdr_type)) + return NULL; - if (pci_read_config_dword(temp, PCI_VENDOR_ID, &l)) + if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l)) return NULL; /* some broken boards return 0 or ~0 if a slot is empty: */ if (l == 0xffffffff || l == 0x00000000 || l == 0x0000ffff || l == 0xffff0000) return NULL; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); + dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL); if (!dev) return NULL; - memcpy(dev, temp, sizeof(*dev)); + memset(dev, 0, sizeof(struct pci_dev)); + dev->bus = bus; + dev->sysdata = bus->sysdata; + dev->dev.parent = bus->dev; + dev->dev.bus = &pci_bus_type; + dev->devfn = devfn; + dev->hdr_type = hdr_type & 0x7f; + dev->multifunction = !!(hdr_type & 0x80); dev->vendor = l & 0xffff; dev->device = (l >> 16) & 0xffff; @@ -461,74 +500,63 @@ strcpy(dev->dev.bus_id,dev->slot_name); dev->dev.dma_mask = &dev->dma_mask; - device_register(&dev->dev); return dev; } -struct pci_dev * __devinit pci_scan_slot(struct pci_dev *temp) +/** + * pci_scan_slot - scan a PCI slot on a bus for devices. + * @bus: PCI bus to scan + * @devfn: slot number to scan (must have zero function.) + * + * Scan a PCI slot on the specified PCI bus for devices, adding + * discovered devices to the @bus->devices list. New devices + * will have an empty dev->global_list head. + */ +int __devinit pci_scan_slot(struct pci_bus *bus, int devfn) { - struct pci_bus *bus = temp->bus; - struct pci_dev *dev; - struct pci_dev *first_dev = NULL; - int func = 0; - int is_multi = 0; - u8 hdr_type; + int func, nr = 0; - for (func = 0; func < 8; func++, temp->devfn++) { - if (func && !is_multi) /* not a multi-function device */ - continue; - if (pci_read_config_byte(temp, PCI_HEADER_TYPE, &hdr_type)) - continue; - temp->hdr_type = hdr_type & 0x7f; + for (func = 0; func < 8; func++, devfn++) { + struct pci_dev *dev; - dev = pci_scan_device(temp); + dev = pci_scan_device(bus, devfn); if (!dev) continue; - if (!func) { - is_multi = hdr_type & 0x80; - first_dev = dev; - } - /* - * Link the device to both the global PCI device chain and - * the per-bus list of devices and add the /proc entry. - */ - pci_insert_device (dev, bus); + if (func != 0) + dev->multifunction = 1; /* Fix up broken headers */ pci_fixup_device(PCI_FIXUP_HEADER, dev); + + /* + * Add the device to our list of discovered devices + * and the bus list for fixup functions, etc. + */ + INIT_LIST_HEAD(&dev->global_list); + list_add_tail(&dev->bus_list, &bus->devices); + nr++; + + /* + * If this is a single function device, + * don't scan past the first function. + */ + if (!dev->multifunction) + break; } - return first_dev; + return nr; } -unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) +static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) { - unsigned int devfn, max, pass; - struct list_head *ln; + unsigned int devfn, pass, max = bus->secondary; struct pci_dev *dev; - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - printk(KERN_ERR "Out of memory in %s\n", __FUNCTION__); - return 0; - } - DBG("Scanning bus %02x\n", bus->number); - max = bus->secondary; - - /* Create a device template */ - memset(dev, 0, sizeof(*dev)); - dev->bus = bus; - dev->sysdata = bus->sysdata; - dev->dev.parent = bus->dev; - dev->dev.bus = &pci_bus_type; /* Go find them, Rover! */ - for (devfn = 0; devfn < 0x100; devfn += 8) { - dev->devfn = devfn; - pci_scan_slot(dev); - } - kfree(dev); + for (devfn = 0; devfn < 0x100; devfn += 8) + pci_scan_slot(bus, devfn); /* * After performing arch-dependent fixup of the bus, look behind @@ -537,9 +565,9 @@ DBG("Fixups for bus %02x\n", bus->number); pcibios_fixup_bus(bus); for (pass=0; pass < 2; pass++) - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - dev = pci_dev_b(ln); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) + list_for_each_entry(dev, &bus->devices, bus_list) { + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || + dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) max = pci_scan_bridge(bus, dev, max, pass); } @@ -551,6 +579,20 @@ * Return how far we've got finding sub-buses. */ DBG("Bus scan for %02x returning with max=%02x\n", bus->number, max); + return max; +} + +unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus) +{ + unsigned int max; + + max = pci_scan_child_bus(bus); + + /* + * Make the discovered devices available. + */ + pci_bus_add_devices(bus); + return max; } diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c --- a/drivers/pci/quirks.c Sat Mar 15 18:40:39 2003 +++ b/drivers/pci/quirks.c Sat Mar 15 18:40:39 2003 @@ -167,6 +167,22 @@ } } +/* + * Ali Magik requires workarounds to be used by the drivers + * that DMA to AGP space. Latency must be set to 0xA and triton + * workaround applied too + * [Info kindly provided by ALi] + */ + +static void __init quirk_alimagik(struct pci_dev *dev) +{ + if((pci_pci_problems&PCIPCI_ALIMAGIK)==0) + { + printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n"); + pci_pci_problems|=PCIPCI_ALIMAGIK|PCIPCI_TRITON; + } +} + /* * Natoma has some interesting boundary conditions with Zoran stuff @@ -219,7 +235,7 @@ static void __devinit quirk_ati_exploding_mce(struct pci_dev *dev) { printk(KERN_INFO "ATI Northbridge, reserving I/O ports 0x3b0 to 0x3bb.\n"); - /* Mae rhaid in i beidio a edrych ar y lleoliad I/O hyn */ + /* Mae rhaid i ni beidio ag edrych ar y lleoliadiau I/O hyn */ request_region(0x3b0, 0x0C, "RadeonIGP"); request_region(0x3d3, 0x01, "RadeonIGP"); } @@ -535,6 +551,92 @@ } } +/* + * As per PCI spec, ignore base address registers 0-3 of the IDE controllers + * running in Compatible mode (bits 0 and 2 in the ProgIf for primary and + * secondary channels respectively). If the device reports Compatible mode + * but does use BAR0-3 for address decoding, we assume that firmware has + * programmed these BARs with standard values (0x1f0,0x3f4 and 0x170,0x374). + * Exceptions (if they exist) must be handled in chip/architecture specific + * fixups. + * + * Note: for non x86 people. You may need an arch specific quirk to handle + * moving IDE devices to native mode as well. Some plug in card devices power + * up in compatible mode and assume the BIOS will adjust them. + * + * Q: should we load the 0x1f0,0x3f4 into the registers or zap them as + * we do now ? We don't want is pci_enable_device to come along + * and assign new resources. Both approaches work for that. + */ + +static void __devinit quirk_ide_bases(struct pci_dev *dev) +{ + struct resource *res; + int first_bar = 2, last_bar = 0; + + if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + + res = &dev->resource[0]; + + /* primary channel: ProgIf bit 0, BAR0, BAR1 */ + if (!(dev->class & 1) && (res[0].flags || res[1].flags)) { + res[0].start = res[0].end = res[0].flags = 0; + res[1].start = res[1].end = res[1].flags = 0; + first_bar = 0; + last_bar = 1; + } + + /* secondary channel: ProgIf bit 2, BAR2, BAR3 */ + if (!(dev->class & 4) && (res[2].flags || res[3].flags)) { + res[2].start = res[2].end = res[2].flags = 0; + res[3].start = res[3].end = res[3].flags = 0; + last_bar = 3; + } + + if (!last_bar) + return; + + printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n", + first_bar, last_bar, dev->slot_name); +} + +/* + * Ensure C0 rev restreaming is off. This is normally done by + * the BIOS but in the odd case it is not the results are corruption + * hence the presence of a Linux check + */ + +static void __init quirk_disable_pxb(struct pci_dev *pdev) +{ + u16 config; + u8 rev; + + pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); + if(rev != 0x04) /* Only C0 requires this */ + return; + pci_read_config_word(pdev, 0x40, &config); + if(config & (1<<6)) + { + config &= ~(1<<6); + pci_write_config_word(pdev, 0x40, config); + printk(KERN_INFO "PCI: C0 revision 450NX. Disabling PCI restreaming.\n"); + } +} + +/* + * VIA northbridges care about PCI_INTERRUPT_LINE + */ + +int interrupt_line_quirk; + +static void __init quirk_via_bridge(struct pci_dev *pdev) +{ + if(pdev->devfn == 0) + interrupt_line_quirk = 1; +} + + /* This was originally an Alpha specific thing, but it really fits here. * The i82375 PCI/EISA bridge appears as non-classified. Fix that. */ @@ -559,7 +661,10 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, quirk_isa_dma_hangs }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, quirk_disable_pxb }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_1, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_2, quirk_isa_dma_hangs }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_CBUS_3, quirk_isa_dma_hangs }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_868, quirk_s3_64M }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_968, quirk_s3_64M }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, quirk_triton }, @@ -574,6 +679,8 @@ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1647, quirk_alimagik }, + { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1651, quirk_alimagik }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, quirk_vialatency }, @@ -586,6 +693,8 @@ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_bridge }, { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy }, #ifdef CONFIG_X86_IO_APIC diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c --- a/drivers/pci/setup-bus.c Sat Mar 15 18:40:44 2003 +++ b/drivers/pci/setup-bus.c Sat Mar 15 18:40:44 2003 @@ -350,6 +350,7 @@ { struct pci_bus *b; int found_vga = pbus_assign_resources_sorted(bus); + struct pci_dev *dev; if (found_vga) { /* Propagate presence of the VGA to upstream bridges */ @@ -357,9 +358,12 @@ b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; } } - list_for_each_entry(b, &bus->children, node) { - pci_bus_assign_resources(b); - pci_setup_bridge(b); + list_for_each_entry(dev, &bus->devices, bus_list) { + b = dev->subordinate; + if (b) { + pci_bus_assign_resources(b); + pci_setup_bridge(b); + } } } EXPORT_SYMBOL(pci_bus_assign_resources); diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c --- a/drivers/pci/setup-res.c Sat Mar 15 18:40:44 2003 +++ b/drivers/pci/setup-res.c Sat Mar 15 18:40:44 2003 @@ -55,84 +55,47 @@ return err; } -/* - * Given the PCI bus a device resides on, try to - * find an acceptable resource allocation for a - * specific device resource.. - */ -static int pci_assign_bus_resource(const struct pci_bus *bus, - struct pci_dev *dev, - struct resource *res, - unsigned long size, - unsigned long min, - unsigned int type_mask, - int resno) +int pci_assign_resource(struct pci_dev *dev, int resno) { - unsigned long align; - int i; - - type_mask |= IORESOURCE_IO | IORESOURCE_MEM; - for (i = 0 ; i < PCI_BUS_NUM_RESOURCES; i++) { - struct resource *r = bus->resource[i]; - if (!r) - continue; - - /* type_mask must match */ - if ((res->flags ^ r->flags) & type_mask) - continue; - - /* We cannot allocate a non-prefetching resource - from a pre-fetching area */ - if ((r->flags & IORESOURCE_PREFETCH) && - !(res->flags & IORESOURCE_PREFETCH)) - continue; - - /* The bridge resources are special, as their - size != alignment. Sizing routines return - required alignment in the "start" field. */ - align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; - - /* Ok, try it out.. */ - if (allocate_resource(r, res, size, min, -1, align, - pcibios_align_resource, dev) < 0) - continue; - - /* Update PCI config space. */ - pcibios_update_resource(dev, r, res, resno); - return 0; - } - return -EBUSY; -} - -int -pci_assign_resource(struct pci_dev *dev, int i) -{ - const struct pci_bus *bus = dev->bus; - struct resource *res = dev->resource + i; - unsigned long size, min; + struct pci_bus *bus = dev->bus; + struct resource *res = dev->resource + resno; + unsigned long size, min, align; + int ret; size = res->end - res->start + 1; min = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; + /* The bridge resources are special, as their + size != alignment. Sizing routines return + required alignment in the "start" field. */ + align = (resno < PCI_BRIDGE_RESOURCES) ? size : res->start; /* First, try exact prefetching match.. */ - if (pci_assign_bus_resource(bus, dev, res, size, min, IORESOURCE_PREFETCH, i) < 0) { + ret = pci_bus_alloc_resource(bus, res, size, align, min, + IORESOURCE_PREFETCH, + pcibios_align_resource, dev); + + if (ret < 0 && (res->flags & IORESOURCE_PREFETCH)) { /* * That failed. * * But a prefetching area can handle a non-prefetching * window (it will just not perform as well). */ - if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) { - printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", - i, res->start, res->end, dev->slot_name); - return -EBUSY; - } + ret = pci_bus_alloc_resource(bus, res, size, align, min, 0, + pcibios_align_resource, dev); } - DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", res->start, - res->end, i, dev->dev.name)); + if (ret) { + printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n", + resno, res->start, res->end, dev->slot_name); + } else { + DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", + res->start, res->end, i, dev->dev.name)); + /* Update PCI config space. */ + pcibios_update_resource(dev, res->parent, res, resno); + } - return 0; + return ret; } /* Sort resources by alignment */ diff -Nru a/drivers/pcmcia/hd64465_ss.c b/drivers/pcmcia/hd64465_ss.c --- a/drivers/pcmcia/hd64465_ss.c Sat Mar 15 18:40:42 2003 +++ b/drivers/pcmcia/hd64465_ss.c Sat Mar 15 18:40:42 2003 @@ -1070,8 +1070,8 @@ } /* hd64465_io_debug = 0; */ - platform_device_register(&hd64465_device); hd64465_device.dev.class_data = &hd64465_data; + platform_device_register(&hd64465_device); return 0; } diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Sat Mar 15 18:40:44 2003 +++ b/drivers/pcmcia/i82365.c Sat Mar 15 18:40:44 2003 @@ -1628,11 +1628,11 @@ request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt); #endif - platform_device_register(&i82365_device); - i82365_data.nsock = sockets; i82365_device.dev.class_data = &i82365_data; + platform_device_register(&i82365_device); + /* Finally, schedule a polling interrupt */ if (poll_interval != 0) { poll_timer.function = pcic_interrupt_wrapper; diff -Nru a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c --- a/drivers/pcmcia/sa1100_generic.c Sat Mar 15 18:40:42 2003 +++ b/drivers/pcmcia/sa1100_generic.c Sat Mar 15 18:40:42 2003 @@ -47,7 +47,6 @@ #include #include #include -#include #include #include diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Sat Mar 15 18:40:42 2003 +++ b/drivers/pcmcia/tcic.c Sat Mar 15 18:40:42 2003 @@ -452,8 +452,6 @@ sockets++; } - platform_device_register(&tcic_device); - switch (socket_table[0].id) { case TCIC_ID_DB86082: printk("DB86082"); break; @@ -526,6 +524,8 @@ tcic_data.nsock = sockets; tcic_device.dev.class_data = &tcic_data; + + platform_device_register(&tcic_device); return 0; diff -Nru a/drivers/pnp/Kconfig b/drivers/pnp/Kconfig --- a/drivers/pnp/Kconfig Sat Mar 15 18:40:42 2003 +++ b/drivers/pnp/Kconfig Sat Mar 15 18:40:42 2003 @@ -30,15 +30,6 @@ If unsure, say Y. -config PNP_CARD - bool "Plug and Play card services" - depends on PNP - help - Select Y if you want the PnP Layer to manage cards. Cards are groups - of PnP devices. Some drivers, especially PnP sound card drivers, use - these cards. If you want to use the protocol ISAPNP you will need to - say Y here. - config PNP_DEBUG bool "PnP Debug Messages" depends on PNP @@ -51,7 +42,7 @@ config ISAPNP bool "ISA Plug and Play support (EXPERIMENTAL)" - depends on PNP && EXPERIMENTAL && PNP_CARD + depends on PNP && EXPERIMENTAL help Say Y here if you would like support for ISA Plug and Play devices. Some information is in . diff -Nru a/drivers/pnp/Makefile b/drivers/pnp/Makefile --- a/drivers/pnp/Makefile Sat Mar 15 18:40:39 2003 +++ b/drivers/pnp/Makefile Sat Mar 15 18:40:39 2003 @@ -2,9 +2,7 @@ # Makefile for the Linux Plug-and-Play Support. # -pnp-card-$(CONFIG_PNP_CARD) = card.o - -obj-y := core.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o $(pnp-card-y) +obj-y := core.o card.o driver.o resource.o manager.o support.o interface.o quirks.o names.o system.o obj-$(CONFIG_PNPBIOS) += pnpbios/ obj-$(CONFIG_ISAPNP) += isapnp/ diff -Nru a/drivers/pnp/card.c b/drivers/pnp/card.c --- a/drivers/pnp/card.c Sat Mar 15 18:40:44 2003 +++ b/drivers/pnp/card.c Sat Mar 15 18:40:44 2003 @@ -16,15 +16,14 @@ #endif #include -#include #include "base.h" - LIST_HEAD(pnp_cards); -static const struct pnp_card_id * match_card(struct pnpc_driver *drv, struct pnp_card *card) + +static const struct pnp_card_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) { - const struct pnp_card_id *drv_id = drv->id_table; + const struct pnp_card_id * drv_id = drv->id_table; while (*drv_id->id){ if (compare_pnp_id(card->id,drv_id->id)) return drv_id; @@ -33,31 +32,33 @@ return NULL; } -static int card_bus_match(struct device *dev, struct device_driver *drv) +static void generic_card_remove(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * pnp_drv = to_pnpc_driver(drv); - if (match_card(pnp_drv, card) == NULL) - return 0; - return 1; + dev->card_link = NULL; } -struct bus_type pnpc_bus_type = { - .name = "pnp_card", - .match = card_bus_match, -}; - +static void generic_card_remove_first(struct pnp_dev * dev) +{ + struct pnp_card_driver * drv = to_pnp_card_driver(dev->driver); + if (!dev->card || !drv) + return; + if (drv->remove) + drv->remove(dev->card_link); + drv->link.remove = &generic_card_remove; + kfree(dev->card_link); + generic_card_remove(dev); +} /** - * pnpc_add_id - adds an EISA id to the specified card + * pnp_add_card_id - adds an EISA id to the specified card * @id: pointer to a pnp_id structure * @card: pointer to the desired card * */ -int pnpc_add_id(struct pnp_id *id, struct pnp_card *card) +int pnp_add_card_id(struct pnp_id *id, struct pnp_card * card) { - struct pnp_id *ptr; + struct pnp_id * ptr; if (!id) return -EINVAL; if (!card) @@ -73,7 +74,7 @@ return 0; } -static void pnpc_free_ids(struct pnp_card *card) +static void pnp_free_card_ids(struct pnp_card * card) { struct pnp_id * id; struct pnp_id *next; @@ -90,47 +91,51 @@ static void pnp_release_card(struct device *dmdev) { struct pnp_card * card = to_pnp_card(dmdev); - pnpc_free_ids(card); + pnp_free_card_ids(card); kfree(card); } /** - * pnpc_add_card - adds a PnP card to the PnP Layer + * pnp_add_card - adds a PnP card to the PnP Layer * @card: pointer to the card to add */ -int pnpc_add_card(struct pnp_card *card) +int pnp_add_card(struct pnp_card * card) { - int error = 0; + int error; + struct list_head * pos; if (!card || !card->protocol) return -EINVAL; + sprintf(card->dev.bus_id, "%02x:%02x", card->protocol->number, card->number); - INIT_LIST_HEAD(&card->rdevs); card->dev.parent = &card->protocol->dev; - card->dev.bus = &pnpc_bus_type; + card->dev.bus = NULL; card->dev.release = &pnp_release_card; - card->status = PNP_READY; error = device_register(&card->dev); - if (error == 0){ - struct list_head *pos; + if (error == 0) { spin_lock(&pnp_lock); list_add_tail(&card->global_list, &pnp_cards); list_add_tail(&card->protocol_list, &card->protocol->cards); spin_unlock(&pnp_lock); + + /* we wait until now to add devices in order to ensure the drivers + * will be able to use all of the related devices on the card + * without waiting any unresonable length of time */ list_for_each(pos,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); __pnp_add_device(dev); } - } + } else + pnp_err("sysfs failure, card '%s' will be unavailable", card->dev.bus_id); return error; } /** - * pnpc_remove_card - removes a PnP card from the PnP Layer + * pnp_remove_card - removes a PnP card from the PnP Layer * @card: pointer to the card to remove */ -void pnpc_remove_card(struct pnp_card *card) +void pnp_remove_card(struct pnp_card * card) { struct list_head *pos, *temp; if (!card) @@ -142,22 +147,24 @@ spin_unlock(&pnp_lock); list_for_each_safe(pos,temp,&card->devices){ struct pnp_dev *dev = card_to_pnp_dev(pos); - pnpc_remove_device(dev); + pnp_remove_card_device(dev); } } /** - * pnpc_add_device - adds a device to the specified card + * pnp_add_card_device - adds a device to the specified card * @card: pointer to the card to add to * @dev: pointer to the device to add */ -int pnpc_add_device(struct pnp_card *card, struct pnp_dev *dev) +int pnp_add_card_device(struct pnp_card * card, struct pnp_dev * dev) { - if (!dev || !dev->protocol || !card) + if (!card || !dev || !dev->protocol) return -EINVAL; dev->dev.parent = &card->dev; - sprintf(dev->dev.bus_id, "%02x:%02x.%02x", dev->protocol->number, card->number,dev->number); + dev->card_link = NULL; + snprintf(dev->dev.bus_id, BUS_ID_SIZE, "%02x:%02x.%02x", dev->protocol->number, + card->number,dev->number); spin_lock(&pnp_lock); dev->card = card; list_add_tail(&dev->card_list, &card->devices); @@ -166,12 +173,12 @@ } /** - * pnpc_remove_device- removes a device from the specified card + * pnp_remove_card_device- removes a device from the specified card * @card: pointer to the card to remove from * @dev: pointer to the device to remove */ -void pnpc_remove_device(struct pnp_dev *dev) +void pnp_remove_card_device(struct pnp_dev * dev) { spin_lock(&pnp_lock); dev->card = NULL; @@ -182,20 +189,21 @@ /** * pnp_request_card_device - Searches for a PnP device under the specified card - * @card: pointer to the card to search under, cannot be NULL + * @lcard: pointer to the card link, cannot be NULL * @id: pointer to a PnP ID structure that explains the rules for finding the device * @from: Starting place to search from. If NULL it will start from the begining. - * - * Will activate the device */ -struct pnp_dev * pnp_request_card_device(struct pnp_card *card, const char *id, struct pnp_dev *from) +struct pnp_dev * pnp_request_card_device(struct pnp_card_link *clink, const char * id, struct pnp_dev * from) { - struct list_head *pos; - struct pnp_dev *dev; - struct pnpc_driver *cdrv; - if (!card || !id) + struct list_head * pos; + struct pnp_dev * dev; + struct pnp_card_driver * drv; + struct pnp_card * card; + if (!clink || !id) goto done; + card = clink->card; + drv = clink->driver; if (!from) { pos = card->devices.next; } else { @@ -205,7 +213,7 @@ } while (pos != &card->devices) { dev = card_to_pnp_dev(pos); - if (compare_pnp_id(dev->id,id)) + if ((!dev->card_link) && compare_pnp_id(dev->id,id)) goto found; pos = pos->next; } @@ -214,168 +222,93 @@ return NULL; found: - if (pnp_device_attach(dev) < 0) - return NULL; - cdrv = to_pnpc_driver(card->dev.driver); - if (dev->active == 0) { - if (!(cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) { - if(pnp_activate_dev(dev)<0) { - pnp_device_detach(dev); - return NULL; - } + down_write(&dev->dev.bus->subsys.rwsem); + dev->card_link = clink; + dev->dev.driver = &drv->link.driver; + if (drv->link.driver.probe) { + if (drv->link.driver.probe(&dev->dev)) { + dev->dev.driver = NULL; + return NULL; } - } else { - if ((cdrv->flags & PNPC_DRIVER_DO_NOT_ACTIVATE)) - pnp_disable_dev(dev); } - spin_lock(&pnp_lock); - list_add_tail(&dev->rdev_list, &card->rdevs); - spin_unlock(&pnp_lock); + device_bind_driver(&dev->dev); + up_write(&dev->dev.bus->subsys.rwsem); + return dev; } /** * pnp_release_card_device - call this when the driver no longer needs the device * @dev: pointer to the PnP device stucture - * - * Will disable the device */ -void pnp_release_card_device(struct pnp_dev *dev) -{ - spin_lock(&pnp_lock); - list_del(&dev->rdev_list); - spin_unlock(&pnp_lock); - pnp_device_detach(dev); -} - -static void pnpc_recover_devices(struct pnp_card *card) -{ - struct list_head *pos, *temp; - list_for_each_safe(pos,temp,&card->rdevs){ - struct pnp_dev *dev = list_entry(pos, struct pnp_dev, rdev_list); - pnp_release_card_device(dev); - } -} - -int pnpc_attach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if(pnp_card->status != PNP_READY){ - spin_unlock(&pnp_lock); - return -EBUSY; - } - pnp_card->status = PNP_ATTACHED; - spin_unlock(&pnp_lock); - return 0; -} - -void pnpc_detach(struct pnp_card *pnp_card) -{ - spin_lock(&pnp_lock); - if (pnp_card->status == PNP_ATTACHED) - pnp_card->status = PNP_READY; - spin_unlock(&pnp_lock); - pnpc_recover_devices(pnp_card); -} - -static int pnpc_card_probe(struct device *dev) -{ - int error = 0; - struct pnpc_driver *drv = to_pnpc_driver(dev->driver); - struct pnp_card *card = to_pnp_card(dev); - const struct pnp_card_id *card_id = NULL; - - pnp_dbg("pnp: match found with the PnP card '%s' and the driver '%s'", dev->bus_id,drv->name); - - error = pnpc_attach(card); - if (error < 0) - return error; - if (drv->probe) { - card_id = match_card(drv, card); - if (card_id != NULL) - error = drv->probe(card, card_id); - if (error >= 0){ - card->driver = drv; - error = 0; - } else - pnpc_detach(card); - } - return error; -} - -static int pnpc_card_remove(struct device *dev) +void pnp_release_card_device(struct pnp_dev * dev) { - struct pnp_card * card = to_pnp_card(dev); - struct pnpc_driver * drv = card->driver; - - if (drv) { - if (drv->remove) - drv->remove(card); - card->driver = NULL; - } - pnpc_detach(card); - return 0; + struct pnp_card_driver * drv = dev->card_link->driver; + if (!drv) + return; + down_write(&dev->dev.bus->subsys.rwsem); + drv->link.remove = &generic_card_remove; + device_release_driver(&dev->dev); + drv->link.remove = &generic_card_remove_first; + up_write(&dev->dev.bus->subsys.rwsem); } /** - * pnpc_register_driver - registers a PnP card driver with the PnP Layer - * @cdrv: pointer to the driver to register + * pnp_register_card_driver - registers a PnP card driver with the PnP Layer + * @drv: pointer to the driver to register */ -int pnpc_register_driver(struct pnpc_driver * drv) +int pnp_register_card_driver(struct pnp_card_driver * drv) { - int count; - struct list_head *pos; - - drv->driver.name = drv->name; - drv->driver.bus = &pnpc_bus_type; - drv->driver.probe = pnpc_card_probe; - drv->driver.remove = pnpc_card_remove; - - pnp_dbg("the card driver '%s' has been registered", drv->name); - - count = driver_register(&drv->driver); + int count = 0; + struct list_head *pos, *temp; - /* get the number of initial matches */ - if (count >= 0){ - count = 0; - list_for_each(pos,&drv->driver.devices){ - count++; + drv->link.name = drv->name; + drv->link.id_table = NULL; /* this will disable auto matching */ + drv->link.flags = drv->flags; + drv->link.probe = NULL; + drv->link.remove = &generic_card_remove_first; + + pnp_register_driver(&drv->link); + + list_for_each_safe(pos,temp,&pnp_cards){ + struct pnp_card *card = list_entry(pos, struct pnp_card, global_list); + const struct pnp_card_id *id = match_card(drv,card); + if (id) { + struct pnp_card_link * clink = pnp_alloc(sizeof(struct pnp_card_link)); + if (!clink) + continue; + clink->card = card; + clink->driver = drv; + if (drv->probe) { + if (drv->probe(clink, id)>=0) + count++; + } else + count++; } } return count; } /** - * pnpc_unregister_driver - unregisters a PnP card driver from the PnP Layer - * @cdrv: pointer to the driver to unregister - * - * Automatically disables requested devices + * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer + * @drv: pointer to the driver to unregister */ -void pnpc_unregister_driver(struct pnpc_driver *drv) +void pnp_unregister_card_driver(struct pnp_card_driver * drv) { - driver_unregister(&drv->driver); - pnp_dbg("the card driver '%s' has been unregistered", drv->name); -} + pnp_unregister_driver(&drv->link); -static int __init pnp_card_init(void) -{ - printk(KERN_INFO "pnp: Enabling Plug and Play Card Services.\n"); - return bus_register(&pnpc_bus_type); + pnp_dbg("the card driver '%s' has been unregistered", drv->name); } -subsys_initcall(pnp_card_init); - -EXPORT_SYMBOL(pnpc_add_card); -EXPORT_SYMBOL(pnpc_remove_card); -EXPORT_SYMBOL(pnpc_add_device); -EXPORT_SYMBOL(pnpc_remove_device); +EXPORT_SYMBOL(pnp_add_card); +EXPORT_SYMBOL(pnp_remove_card); +EXPORT_SYMBOL(pnp_add_card_device); +EXPORT_SYMBOL(pnp_remove_card_device); +EXPORT_SYMBOL(pnp_add_card_id); EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); -EXPORT_SYMBOL(pnpc_register_driver); -EXPORT_SYMBOL(pnpc_unregister_driver); -EXPORT_SYMBOL(pnpc_add_id); -EXPORT_SYMBOL(pnpc_attach); -EXPORT_SYMBOL(pnpc_detach); +EXPORT_SYMBOL(pnp_register_card_driver); +EXPORT_SYMBOL(pnp_unregister_card_driver); diff -Nru a/drivers/pnp/driver.c b/drivers/pnp/driver.c --- a/drivers/pnp/driver.c Sat Mar 15 18:40:43 2003 +++ b/drivers/pnp/driver.c Sat Mar 15 18:40:43 2003 @@ -53,12 +53,11 @@ static const struct pnp_device_id * match_device(struct pnp_driver *drv, struct pnp_dev *dev) { const struct pnp_device_id *drv_id = drv->id_table; - if (!drv) + if (!drv_id) return NULL; - if (!dev) - return NULL; - while (*drv_id->id){ - if (compare_pnp_id(dev->id,drv_id->id)) + + while (*drv_id->id) { + if (compare_pnp_id(dev->id, drv_id->id)) return drv_id; drv_id++; } @@ -102,14 +101,19 @@ return error; if (pnp_dev->active == 0) { - if (!(pnp_drv->flags & PNP_DRIVER_DO_NOT_ACTIVATE)) { + if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { error = pnp_activate_dev(pnp_dev); if (error < 0) return error; } + } else if ((pnp_drv->flags & PNP_DRIVER_RES_DISABLE) + == PNP_DRIVER_RES_DISABLE) { + error = pnp_disable_dev(pnp_dev); + if (error < 0) + return error; } error = 0; - if (pnp_drv->probe && pnp_dev->active) { + if (pnp_drv->probe) { dev_id = match_device(pnp_drv, pnp_dev); if (dev_id != NULL) error = pnp_drv->probe(pnp_dev, dev_id); @@ -117,9 +121,8 @@ if (error >= 0){ pnp_dev->driver = pnp_drv; error = 0; - } - else - goto fail; + } else + goto fail; return error; fail: diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c --- a/drivers/pnp/interface.c Sat Mar 15 18:40:40 2003 +++ b/drivers/pnp/interface.c Sat Mar 15 18:40:40 2003 @@ -332,11 +332,18 @@ buffer->buffer = buf; buffer->curr = buffer->buffer; + pnp_printf(buffer,"mode = "); + if (dev->config_mode & PNP_CONFIG_MANUAL) + pnp_printf(buffer,"manual\n"); + else + pnp_printf(buffer,"auto\n"); + pnp_printf(buffer,"state = "); if (dev->active) pnp_printf(buffer,"active\n"); else pnp_printf(buffer,"disabled\n"); + for (i = 0; i < PNP_MAX_PORT; i++) { if (pnp_port_valid(dev, i)) { pnp_printf(buffer,"io"); @@ -402,13 +409,13 @@ retval = pnp_activate_dev(dev); goto done; } - if (!strnicmp(buf,"auto-config",11)) { + if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; retval = pnp_auto_config_dev(dev); goto done; } - if (!strnicmp(buf,"clear-config",12)) { + if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; spin_lock(&pnp_lock); diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Sat Mar 15 18:40:42 2003 +++ b/drivers/pnp/isapnp/core.c Sat Mar 15 18:40:42 2003 @@ -626,7 +626,7 @@ isapnp_peek(name, size1); name[size1] = '\0'; *size -= size1; - + /* clean whitespace from end of string */ while (size1 > 0 && name[--size1] == ' ') name[size1] = '\0'; @@ -647,7 +647,7 @@ return 1; if (pnp_build_resource(dev, 0) == NULL) return 1; - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); while (1) { if (isapnp_read_tag(&type, &size)<0) return 1; @@ -659,7 +659,7 @@ if ((dev = isapnp_parse_device(card, size, number++)) == NULL) return 1; pnp_build_resource(dev,0); - pnpc_add_device(card,dev); + pnp_add_card_device(card,dev); size = 0; skip = 0; } else { @@ -852,7 +852,7 @@ device & 0x0f, (device >> 12) & 0x0f, (device >> 8) & 0x0f); - pnpc_add_id(id,card); + pnp_add_card_id(id,card); } @@ -962,7 +962,7 @@ isapnp_parse_current_resources(dev, &dev->res); } - pnpc_add_card(card); + pnp_add_card(card); } isapnp_wait(); return 0; diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c --- a/drivers/pnp/manager.c Sat Mar 15 18:40:44 2003 +++ b/drivers/pnp/manager.c Sat Mar 15 18:40:44 2003 @@ -532,6 +532,39 @@ return error; } +static void pnp_process_manual_resources(struct pnp_resource_table * ctab, struct pnp_resource_table * ntab) +{ + int idx; + for (idx = 0; idx < PNP_MAX_IRQ; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->irq_resource[idx].start; + ctab->irq_resource[idx].end = ntab->irq_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->irq_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_DMA; idx++) { + if (ntab->dma_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->dma_resource[idx].start = ntab->dma_resource[idx].start; + ctab->dma_resource[idx].end = ntab->dma_resource[idx].end; + ctab->dma_resource[idx].flags = ntab->dma_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_PORT; idx++) { + if (ntab->port_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->port_resource[idx].start = ntab->port_resource[idx].start; + ctab->port_resource[idx].end = ntab->port_resource[idx].end; + ctab->port_resource[idx].flags = ntab->port_resource[idx].flags; + } + for (idx = 0; idx < PNP_MAX_MEM; idx++) { + if (ntab->irq_resource[idx].flags & IORESOURCE_AUTO) + continue; + ctab->irq_resource[idx].start = ntab->mem_resource[idx].start; + ctab->irq_resource[idx].end = ntab->mem_resource[idx].end; + ctab->irq_resource[idx].flags = ntab->mem_resource[idx].flags; + } +} + /** * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table * @dev: pointer to the desired device @@ -554,7 +587,7 @@ *bak = dev->res; spin_lock(&pnp_lock); - dev->res = *res; + pnp_process_manual_resources(&dev->res, res); if (!(mode & PNP_CONFIG_FORCE)) { for (i = 0; i < PNP_MAX_PORT; i++) { if(pnp_check_port(dev,i)) @@ -681,7 +714,7 @@ return -1; } dev->active = 0; /* just in case the protocol doesn't do this */ - pnp_dbg("the device '%s' has been disabled.", dev->dev.bus_id); + pnp_dbg("res: the device '%s' has been disabled.", dev->dev.bus_id); return 0; } diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c Sat Mar 15 18:40:42 2003 +++ b/drivers/pnp/resource.c Sat Mar 15 18:40:42 2003 @@ -558,25 +558,25 @@ table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; table->irq_resource[idx].end = -1; - table->irq_resource[idx].flags = 0; + table->irq_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_DMA; idx++) { table->dma_resource[idx].name = NULL; table->dma_resource[idx].start = -1; table->dma_resource[idx].end = -1; - table->dma_resource[idx].flags = 0; + table->dma_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_PORT; idx++) { table->port_resource[idx].name = NULL; table->port_resource[idx].start = 0; table->port_resource[idx].end = 0; - table->port_resource[idx].flags = 0; + table->port_resource[idx].flags = IORESOURCE_AUTO; } for (idx = 0; idx < PNP_MAX_MEM; idx++) { table->mem_resource[idx].name = NULL; table->mem_resource[idx].start = 0; table->mem_resource[idx].end = 0; - table->mem_resource[idx].flags = 0; + table->mem_resource[idx].flags = IORESOURCE_AUTO; } } diff -Nru a/drivers/pnp/system.c b/drivers/pnp/system.c --- a/drivers/pnp/system.c Sat Mar 15 18:40:45 2003 +++ b/drivers/pnp/system.c Sat Mar 15 18:40:45 2003 @@ -93,8 +93,8 @@ static struct pnp_driver system_pnp_driver = { .name = "system", - .flags = PNP_DRIVER_DO_NOT_ACTIVATE, .id_table = pnp_dev_table, + .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, .probe = system_pnp_probe, .remove = NULL, }; diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c --- a/drivers/s390/block/dasd_3990_erp.c Sat Mar 15 18:40:44 2003 +++ b/drivers/s390/block/dasd_3990_erp.c Sat Mar 15 18:40:44 2003 @@ -2445,7 +2445,7 @@ * - exit with permanent error * * PARAMETER - * erp ERP which is in progress wiht no retry left + * erp ERP which is in progress with no retry left * * RETURN VALUES * erp modified/additional ERP diff -Nru a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c --- a/drivers/s390/block/dasd_genhd.c Sat Mar 15 18:40:43 2003 +++ b/drivers/s390/block/dasd_genhd.c Sat Mar 15 18:40:43 2003 @@ -60,11 +60,8 @@ } /* Register block device. */ - new_major = register_blkdev(major, "dasd", &dasd_device_operations); + new_major = register_blkdev(major, "dasd"); if (new_major < 0) { - MESSAGE(KERN_WARNING, - "Cannot register to major no %d, rc = %d", - major, new_major); kfree(mi); return new_major; } diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Sat Mar 15 18:40:43 2003 +++ b/drivers/s390/block/xpram.c Sat Mar 15 18:40:43 2003 @@ -430,13 +430,11 @@ /* * Register xpram major. */ - rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME, &xpram_devops); - if (rc < 0) { - PRINT_ERR("Can't get xpram major %d\n", XPRAM_MAJOR); + rc = register_blkdev(XPRAM_MAJOR, XPRAM_NAME); + if (rc < 0) goto out; - } - devfs_mk_dir (NULL, "slram", NULL); + devfs_mk_dir(NULL, "slram", NULL); /* * Assign the other needed values: make request function, sizes and @@ -452,6 +450,7 @@ for (i = 0; i < xpram_devs; i++) { struct gendisk *disk = xpram_disks[i]; char name[16]; + xpram_devices[i].size = xpram_sizes[i] / 4; xpram_devices[i].offset = offset; offset += xpram_devices[i].size; diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Sat Mar 15 18:40:43 2003 +++ b/drivers/s390/char/con3215.c Sat Mar 15 18:40:43 2003 @@ -862,7 +862,7 @@ spin_unlock_irqrestore(raw->lock, flags); } -static int __init +static int __init con3215_consetup(struct console *co, char *options) { return 0; @@ -884,7 +884,7 @@ * 3215 console initialization code called from console_init(). * NOTE: This is called before kmalloc is available. */ -void __init +static void __init con3215_init(void) { struct ccw_device *cdev; @@ -1122,6 +1122,7 @@ spin_unlock_irqrestore(raw->lock, flags); } } +console_initcall(con3215_init); /* * Disable writing to a 3215 tty diff -Nru a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c --- a/drivers/s390/char/sclp_con.c Sat Mar 15 18:40:42 2003 +++ b/drivers/s390/char/sclp_con.c Sat Mar 15 18:40:42 2003 @@ -237,3 +237,5 @@ /* enable printk-access to this driver */ register_console(&sclp_console); } + +console_initcall(sclp_console_init); diff -Nru a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c --- a/drivers/s390/char/sclp_tty.c Sat Mar 15 18:40:40 2003 +++ b/drivers/s390/char/sclp_tty.c Sat Mar 15 18:40:40 2003 @@ -797,3 +797,6 @@ if (tty_register_driver(&sclp_tty_driver)) panic("Couldn't register sclp_tty driver\n"); } + +console_initcall(sclp_tty_init); + diff -Nru a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c --- a/drivers/s390/char/tape_block.c Sat Mar 15 18:40:43 2003 +++ b/drivers/s390/char/tape_block.c Sat Mar 15 18:40:43 2003 @@ -333,12 +333,10 @@ int rc; /* Register the tape major number to the kernel */ - rc = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops); - if (rc < 0) { - PRINT_ERR("can't get major %d for block device\n", - tapeblock_major); + rc = register_blkdev(tapeblock_major, "tBLK"); + if (rc < 0) return rc; - } + if (tapeblock_major == 0) tapeblock_major = rc; PRINT_INFO("tape gets major %d for block device\n", tapeblock_major); diff -Nru a/drivers/s390/char/tuball.c b/drivers/s390/char/tuball.c --- a/drivers/s390/char/tuball.c Sat Mar 15 18:40:44 2003 +++ b/drivers/s390/char/tuball.c Sat Mar 15 18:40:44 2003 @@ -131,7 +131,7 @@ #else #define tub3270_con_devno console_device -void __init tub3270_con_init(void) +static void __init tub3270_con_init(void) { tub3270_con_bcb.bc_len = 65536; if (!CONSOLE_IS_3270) @@ -140,6 +140,8 @@ tub3270_con_bcb.bc_len); register_console(&tub3270_con); } +console_initcall(tub3270_con_init); + #endif static kdev_t diff -Nru a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c --- a/drivers/sbus/char/jsflash.c Sat Mar 15 18:40:41 2003 +++ b/drivers/sbus/char/jsflash.c Sat Mar 15 18:40:41 2003 @@ -570,9 +570,7 @@ jsfd_disk[i] = disk; } - if (register_blkdev(JSFD_MAJOR, "jsfd", &jsfd_fops)) { - printk("jsfd_init: unable to get major number %d\n", - JSFD_MAJOR); + if (register_blkdev(JSFD_MAJOR, "jsfd")) { err = -EIO; goto out; } diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Sat Mar 15 18:40:44 2003 +++ b/drivers/scsi/Kconfig Sat Mar 15 18:40:44 2003 @@ -946,16 +946,6 @@ Please read for more information. -config SCSI_ZALON - tristate "Zalon SCSI support" - depends on GSC && SCSI - help - The Zalon is a GSC/HSC bus interface chip that sits between the - PA-RISC processor and the NCR 53c720 SCSI controller on C100, - C110, J200, J210 and some D, K & R-class machines. It's also - used on the add-in Bluefish, Barracuda & Shrike SCSI cards. - Say Y here if you have one of these machines or cards. - config SCSI_SYM53C8XX_DMA_ADDRESSING_MODE int "DMA addressing mode" depends on SCSI_SYM53C8XX_2 @@ -1010,9 +1000,19 @@ If you say Y here, the driver will preferently use normal IO rather than memory mapped IO. +config SCSI_ZALON + tristate "Zalon SCSI support" + depends on GSC && SCSI + help + The Zalon is a GSC/HSC bus interface chip that sits between the + PA-RISC processor and the NCR 53c720 SCSI controller on C100, + C110, J200, J210 and some D, K & R-class machines. It's also + used on the add-in Bluefish, Barracuda & Shrike SCSI cards. + Say Y here if you have one of these machines or cards. + config SCSI_NCR53C8XX tristate "NCR53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI + depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI ---help--- This is the BSD ncr driver adapted to Linux for the NCR53C8XX family of PCI-SCSI controllers. This driver supports parity checking, diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile --- a/drivers/scsi/aic7xxx/aicasm/Makefile Sat Mar 15 18:40:44 2003 +++ b/drivers/scsi/aic7xxx/aicasm/Makefile Sat Mar 15 18:40:44 2003 @@ -10,9 +10,10 @@ GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c) SRCS= ${CSRCS} ${GENSRCS} +LIBS= -ldb CLEANFILES= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) # Override default kernel CFLAGS. This is a userland app. -AICASM_CFLAGS:= -I/usr/include -I. -ldb +AICASM_CFLAGS:= -I/usr/include -I. YFLAGS= -d NOMAN= noman @@ -30,7 +31,7 @@ endif $(PROG): ${GENHDRS} $(SRCS) - $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) + $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS) aicdb.h: @if [ -e "/usr/include/db3/db_185.h" ]; then \ @@ -45,8 +46,9 @@ echo "*** Install db development libraries"; \ fi +clean-files := $(CLEANFILES) $(PROG) clean: - rm -f $(CLEANFILES) $(PROG) + rm -f $(clean-files) aicasm_gram.c aicasm_gram.h: aicasm_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) $< diff -Nru a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c --- a/drivers/scsi/fdomain.c Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/fdomain.c Sat Mar 15 18:40:43 2003 @@ -271,13 +271,8 @@ **************************************************************************/ +#include #include - -#ifdef PCMCIA -#undef MODULE -#endif - -#include /* for CONFIG_PCI */ #include #include #include @@ -295,9 +290,13 @@ #include "scsi.h" #include "hosts.h" -#include "fdomain.h" + +MODULE_AUTHOR("Rickard E. Faith"); +MODULE_DESCRIPTION("Future domain SCSI driver"); +MODULE_LICENSE("GPL"); + -#define VERSION "$Revision: 5.50 $" +#define VERSION "$Revision: 5.51 $" /* START OF USER DEFINABLE OPTIONS */ @@ -421,15 +420,12 @@ static void do_fdomain_16x0_intr( int irq, void *dev_id, struct pt_regs * regs ); +int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); -#ifdef MODULE - /* Allow insmod parameters to be like LILO - parameters. For example: - insmod fdomain fdomain=0x140,11 - */ +/* Allow insmod parameters to be like LILO parameters. For example: + insmod fdomain fdomain=0x140,11 */ static char * fdomain = NULL; MODULE_PARM(fdomain, "s"); -#endif static unsigned long addresses[] = { 0xc8000, @@ -561,7 +557,7 @@ printk( "\n" ); } -static int __init fdomain_setup(char *str) +int __init fdomain_setup(char *str) { int ints[4]; @@ -862,7 +858,7 @@ } #endif -static int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) +struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ) { int retcode; struct Scsi_Host *shpnt; @@ -879,13 +875,6 @@ unsigned char buf[buflen]; #endif - tpnt->proc_name = "fdomain"; - -#ifdef MODULE - if (fdomain) - fdomain_setup(fdomain); -#endif - if (setup_called) { #if DEBUG_DETECT printk( "scsi: No BIOS, using port_base = 0x%x, irq = %d\n", @@ -895,7 +884,7 @@ printk( "scsi: Cannot locate chip at port base 0x%x\n", port_base ); printk( "scsi: Bad LILO/INSMOD parameters?\n" ); - return 0; + return NULL; } } else { int flag = 0; @@ -910,7 +899,7 @@ if (!flag) { printk( "scsi: Detection failed (no card)\n" ); - return 0; + return NULL; } } } @@ -936,7 +925,7 @@ if (setup_called) { printk(KERN_ERR "scsi: Bad LILO/INSMOD parameters?\n"); } - return 0; + return NULL; } if (this_id) { @@ -957,7 +946,7 @@ shpnt = scsi_register( tpnt, 0 ); if(shpnt == NULL) - return 0; + return NULL; shpnt->irq = interrupt_level; shpnt->io_port = port_base; scsi_set_device(shpnt, &pdev->dev); @@ -967,7 +956,7 @@ /* Log IRQ with kernel */ if (!interrupt_level) { printk(KERN_ERR "scsi: Card Detected, but driver not loaded (no IRQ)\n" ); - return 0; + return NULL; } else { /* Register the IRQ with the kernel */ @@ -988,7 +977,7 @@ printk(KERN_ERR " Send mail to faith@acm.org\n" ); } printk(KERN_ERR "scsi: Detected, but driver not loaded (IRQ)\n" ); - return 0; + return NULL; } } @@ -1048,7 +1037,14 @@ } #endif - return 1; /* Maximum of one adapter will be detected. */ + return shpnt; +} + +static int fdomain_16x0_detect( Scsi_Host_Template *tpnt ) +{ + if (fdomain) + fdomain_setup(fdomain); + return (__fdomain_16x0_detect(tpnt) != NULL); } static const char *fdomain_16x0_info( struct Scsi_Host *ignore ) @@ -1150,8 +1146,9 @@ { int status; unsigned long timeout; +#if ERRORS_ONLY static int flag = 0; - +#endif outb( 0x82, SCSI_Cntl_port ); /* Bus Enable + Select */ outb( adapter_mask | (1 << target), SCSI_Data_NoACK_port ); @@ -1574,6 +1571,7 @@ /* End of code derived from Tommy Thorn's work. */ +#if DEBUG_ABORT static void print_info(Scsi_Cmnd *SCpnt) { unsigned int imr; @@ -1643,6 +1641,7 @@ printk( "Configuration 2 = 0x%02x\n", inb( port_base + Configuration2 ) ); } +#endif static int fdomain_16x0_abort( Scsi_Cmnd *SCpnt) { @@ -1670,7 +1669,7 @@ return SUCCESS; } -static int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt) +int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt) { outb( 1, SCSI_Cntl_port ); do_pause( 2 ); @@ -1866,9 +1865,29 @@ return 0; } -MODULE_LICENSE("GPL"); - -/* Eventually this will go into an include file, but this will be later */ -static Scsi_Host_Template driver_template = FDOMAIN_16X0; +Scsi_Host_Template fdomain_driver_template = { + .module = THIS_MODULE, + .name = "fdomain", + .proc_name = "fdomain", + .proc_info = fdomain_16x0_proc_info, + .detect = fdomain_16x0_detect, + .info = fdomain_16x0_info, + .command = fdomain_16x0_command, + .queuecommand = fdomain_16x0_queue, + .eh_abort_handler = fdomain_16x0_abort, + .eh_bus_reset_handler = fdomain_16x0_bus_reset, + .eh_device_reset_handler = fdomain_16x0_device_reset, + .eh_host_reset_handler = fdomain_16x0_host_reset, + .bios_param = fdomain_16x0_biosparam, + .release = fdomain_16x0_release, + .can_queue = 1, + .this_id = 6, + .sg_tablesize = 64, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; +#ifndef PCMCIA +#define driver_template fdomain_driver_template #include "scsi_module.c" +#endif diff -Nru a/drivers/scsi/fdomain.h b/drivers/scsi/fdomain.h --- a/drivers/scsi/fdomain.h Sat Mar 15 18:40:40 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,59 +0,0 @@ -/* fdomain.h -- Header for Future Domain TMC-16x0 driver - * Created: Sun May 3 18:47:33 1992 by faith@cs.unc.edu - * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org - * Author: Rickard E. Faith, faith@cs.unc.edu - * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith - * - * $Id: fdomain.h,v 5.12 1995/10/12 19:01:09 root Exp $ - - * 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, or (at your option) any - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -#ifndef _FDOMAIN_H -#define _FDOMAIN_H - -static int fdomain_16x0_detect( Scsi_Host_Template *); -static int fdomain_16x0_command( Scsi_Cmnd *); -static int fdomain_16x0_abort(Scsi_Cmnd *); -static const char *fdomain_16x0_info(struct Scsi_Host *); -static int fdomain_16x0_bus_reset(Scsi_Cmnd *); -static int fdomain_16x0_host_reset(Scsi_Cmnd *); -static int fdomain_16x0_device_reset(Scsi_Cmnd *); -static int fdomain_16x0_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -static int fdomain_16x0_biosparam(struct scsi_device *, - struct block_device *, sector_t, int * ); -static int fdomain_16x0_proc_info(char *buffer, char **start, off_t offset, - int length, int hostno, int inout ); -static int fdomain_16x0_release(struct Scsi_Host *shpnt); - -#define FDOMAIN_16X0 { .proc_info = fdomain_16x0_proc_info, \ - .detect = fdomain_16x0_detect, \ - .info = fdomain_16x0_info, \ - .command = fdomain_16x0_command, \ - .queuecommand = fdomain_16x0_queue, \ - .eh_abort_handler = fdomain_16x0_abort, \ - .eh_bus_reset_handler = fdomain_16x0_bus_reset, \ - .eh_device_reset_handler = fdomain_16x0_device_reset, \ - .eh_host_reset_handler = fdomain_16x0_host_reset, \ - .bios_param = fdomain_16x0_biosparam, \ - .release = fdomain_16x0_release, \ - .can_queue = 1, \ - .this_id = 6, \ - .sg_tablesize = 64, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ -} -#endif diff -Nru a/drivers/scsi/i91uscsi.h b/drivers/scsi/i91uscsi.h --- a/drivers/scsi/i91uscsi.h Sat Mar 15 18:40:42 2003 +++ b/drivers/scsi/i91uscsi.h Sat Mar 15 18:40:42 2003 @@ -70,12 +70,6 @@ #ifndef NULL #define NULL 0 /* zero */ #endif -#ifndef TRUE -#define TRUE (1) /* boolean true */ -#endif -#ifndef FALSE -#define FALSE (0) /* boolean false */ -#endif #ifndef FAILURE #define FAILURE (-1) #endif @@ -597,11 +591,9 @@ TCS HCS_Tcs[MAX_TARGETS]; /* 78 */ ULONG pSRB_head; /* SRB save queue header */ ULONG pSRB_tail; /* SRB save queue tail */ -#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spinlock_t HCS_AvailLock; spinlock_t HCS_SemaphLock; spinlock_t pSRB_lock; /* SRB queue lock */ -#endif } HCS; /* Bit Definition for HCB_Config */ diff -Nru a/drivers/scsi/imm.c b/drivers/scsi/imm.c --- a/drivers/scsi/imm.c Sat Mar 15 18:40:45 2003 +++ b/drivers/scsi/imm.c Sat Mar 15 18:40:45 2003 @@ -174,6 +174,7 @@ parport_unregister_device(imm_hosts[i].dev); continue; } + /* now the glue ... */ switch (imm_hosts[i].mode) { case IMM_NIBBLE: @@ -218,7 +219,7 @@ /* This is to give the imm driver a way to modify the timings (and other * parameters) by writing to the /proc/scsi/imm/0 file. - * Very simple method really... (To simple, no error checking :( ) + * Very simple method really... (Too simple, no error checking :( ) * Reason: Kernel hackers HATE having to unload and reload modules for * testing... * Also gives a method to use a script to obtain optimum timings (TODO) @@ -948,7 +949,7 @@ unsigned char l = 0, h = 0; int retv, x; - /* First check for any errors that may of occurred + /* First check for any errors that may have occurred * Here we check for internal errors */ if (tmp->failed) diff -Nru a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c --- a/drivers/scsi/inia100.c Sat Mar 15 18:40:41 2003 +++ b/drivers/scsi/inia100.c Sat Mar 15 18:40:41 2003 @@ -67,12 +67,6 @@ * - Fix allocation of scsi host structs and private data **************************************************************************/ -#define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S) - -#ifndef LINUX_VERSION_CODE -#include -#endif - #include #include diff -Nru a/drivers/scsi/inia100.h b/drivers/scsi/inia100.h --- a/drivers/scsi/inia100.h Sat Mar 15 18:40:39 2003 +++ b/drivers/scsi/inia100.h Sat Mar 15 18:40:39 2003 @@ -63,14 +63,6 @@ * merged them into a single header used by both .c files. ****************************************************************************/ -#ifndef CVT_LINUX_VERSION -#define CVT_LINUX_VERSION(V,P,S) (((V) * 65536) + ((P) * 256) + (S)) -#endif - -#ifndef LINUX_VERSION_CODE -#include -#endif - #include #include #include @@ -116,12 +108,6 @@ #ifndef NULL #define NULL 0 /* zero */ -#endif -#ifndef TRUE -#define TRUE (1) /* boolean true */ -#endif -#ifndef FALSE -#define FALSE (0) /* boolean false */ #endif #ifndef FAILURE #define FAILURE (-1) diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Sat Mar 15 18:40:41 2003 +++ b/drivers/scsi/ncr53c8xx.c Sat Mar 15 18:40:41 2003 @@ -5024,7 +5024,6 @@ **========================================================== */ -#ifdef MODULE static int ncr_detach(ncb_p np) { ccb_p cp; @@ -5160,7 +5159,6 @@ return 1; } -#endif /*========================================================== ** @@ -8935,7 +8933,6 @@ } -#ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *host) { #ifdef DEBUG_NCR53C8XX @@ -8945,7 +8942,6 @@ return 1; } -#endif /* diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h --- a/drivers/scsi/ncr53c8xx.h Sat Mar 15 18:40:41 2003 +++ b/drivers/scsi/ncr53c8xx.h Sat Mar 15 18:40:41 2003 @@ -60,17 +60,12 @@ int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int ncr53c8xx_reset(Scsi_Cmnd *, unsigned int); int ncr53c8xx_slave_configure(Scsi_Device *); - -#ifdef MODULE int ncr53c8xx_release(struct Scsi_Host *); -#else -#define ncr53c8xx_release NULL -#endif #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) -#define NCR53C8XX { .name = "", \ +#define NCR53C8XX { .name = "ncr53c8xx", \ .detect = ncr53c8xx_detect, \ .release = ncr53c8xx_release, \ .info = ncr53c8xx_info, \ diff -Nru a/drivers/scsi/pcmcia/Kconfig b/drivers/scsi/pcmcia/Kconfig --- a/drivers/scsi/pcmcia/Kconfig Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/pcmcia/Kconfig Sat Mar 15 18:40:43 2003 @@ -3,22 +3,11 @@ # menu "PCMCIA SCSI adapter support" - depends on SCSI!=n && HOTPLUG && PCMCIA!=n - -config SCSI_PCMCIA - bool "PCMCIA SCSI adapter support" - help - Say Y here if you intend to attach a PCMCIA or CardBus card to your - computer which acts as a SCSI host adapter. These are credit card - size devices often used with laptops. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions PCMCIA SCSI host adapters. + depends on SCSI!=n && PCMCIA!=n config PCMCIA_AHA152X tristate "Adaptec AHA152X PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -30,7 +19,7 @@ config PCMCIA_FDOMAIN tristate "Future Domain PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -42,7 +31,7 @@ config PCMCIA_NINJA_SCSI tristate "NinjaSCSI-3 / NinjaSCSI-32Bi (16bit) PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help If you intend to attach this type of PCMCIA SCSI host adapter to your computer, say Y here and read @@ -55,7 +44,7 @@ config PCMCIA_QLOGIC tristate "Qlogic PCMCIA support" - depends on SCSI_PCMCIA && m + depends on m help Say Y here if you intend to attach this type of PCMCIA SCSI host adapter to your computer. @@ -65,10 +54,4 @@ whenever you want). If you want to compile it as a module, say M here and read . -config PCMCIA_SCSICARD - bool - depends on PCMCIA_QLOGIC=y || PCMCIA_AHA152X=y || PCMCIA_FDOMAIN=y || PCMCIA_NINJA_SCSI=y - default y - endmenu - diff -Nru a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c --- a/drivers/scsi/pcmcia/fdomain_stub.c Sat Mar 15 18:40:42 2003 +++ b/drivers/scsi/pcmcia/fdomain_stub.c Sat Mar 15 18:40:42 2003 @@ -61,15 +61,15 @@ MODULE_DESCRIPTION("Future Domain PCMCIA SCSI driver"); MODULE_LICENSE("Dual MPL/GPL"); -#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") - /* Bit map of interrupts to choose from */ -INT_MODULE_PARM(irq_mask, 0xdeb8); +static int irq_mask = 0xdeb8; +MODULE_PARM(irq_mask, "i"); static int irq_list[4] = { -1 }; MODULE_PARM(irq_list, "1-4i"); #ifdef PCMCIA_DEBUG -INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG); +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) static char *version = "fdomain_cs.c 1.47 2001/10/13 00:08:52 (David Hinds)"; @@ -81,11 +81,15 @@ typedef struct scsi_info_t { dev_link_t link; + struct Scsi_Host *host; int ndev; dev_node_t node[8]; } scsi_info_t; +extern Scsi_Host_Template fdomain_driver_template; extern void fdomain_setup(char *str, int *ints); +extern struct Scsi_Host *__fdomain_16x0_detect( Scsi_Host_Template *tpnt ); +extern int fdomain_16x0_bus_reset(Scsi_Cmnd *SCpnt); static void fdomain_release(u_long arg); static int fdomain_event(event_t event, int priority, @@ -94,8 +98,6 @@ static dev_link_t *fdomain_attach(void); static void fdomain_detach(dev_link_t *); -#define driver_template fdomain_driver_template -extern Scsi_Host_Template fdomain_driver_template; static dev_link_t *dev_list = NULL; @@ -231,7 +233,6 @@ link->conf.ConfigBase = parse.config.base; /* Configure card */ - driver_template.module = &__this_module; link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -260,14 +261,18 @@ sprintf(str, "%d,%d", link->io.BasePort1, link->irq.AssignedIRQ); fdomain_setup(str, ints); - scsi_register_host(&driver_template); + host = __fdomain_16x0_detect(&fdomain_driver_template); + if (!host) { + printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); + goto cs_failed; + } + + scsi_add_host(host, NULL); tail = &link->dev; info->ndev = 0; - for (host = scsi_host_get_next(NULL); host; - host = scsi_host_get_next(host)) - if (host->hostt == &driver_template) - list_for_each_entry (dev, &host->my_devices, siblings) { + + list_for_each_entry (dev, &host->my_devices, siblings) { u_long arg[2], id; kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) + @@ -296,10 +301,11 @@ } *tail = node; tail = &node->next; info->ndev++; - } + + } + *tail = NULL; - if (info->ndev == 0) - printk(KERN_INFO "fdomain_cs: no SCSI devices found\n"); + info->host = host; link->state &= ~DEV_CONFIG_PENDING; return; @@ -316,30 +322,22 @@ static void fdomain_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; + scsi_info_t *info = link->priv; DEBUG(0, "fdomain_release(0x%p)\n", link); -#warning This does not protect you. You need some real fix for your races. -#if 0 - if (GET_USE_COUNT(&__this_module) != 0) { - DEBUG(1, "fdomain_cs: release postponed, " - "device still open\n"); - link->state |= DEV_STALE_CONFIG; - return; - } -#endif - - scsi_unregister_host(&driver_template); + scsi_remove_host(info->host); link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); - + + scsi_unregister(info->host); + link->state &= ~DEV_CONFIG; if (link->state & DEV_STALE_LINK) fdomain_detach(link); - } /* fdomain_release */ /*====================================================================*/ @@ -374,7 +372,7 @@ case CS_EVENT_CARD_RESET: if (link->state & DEV_CONFIG) { CardServices(RequestConfiguration, link->handle, &link->conf); - fdomain_16x0_reset(NULL, 0); + fdomain_16x0_bus_reset(NULL); } break; } diff -Nru a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c --- a/drivers/scsi/pcmcia/qlogic_stub.c Sat Mar 15 18:40:42 2003 +++ b/drivers/scsi/pcmcia/qlogic_stub.c Sat Mar 15 18:40:42 2003 @@ -55,7 +55,11 @@ #include #include + +extern Scsi_Host_Template qlogicfas_driver_template; extern void qlogicfas_preset(int port, int irq); +extern struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *); +extern int qlogicfas_bus_reset(Scsi_Cmnd *); #ifdef PCMCIA_DEBUG static int pc_debug = PCMCIA_DEBUG; @@ -81,6 +85,7 @@ typedef struct scsi_info_t { dev_link_t link; + struct Scsi_Host *host; unsigned short manf_id; int ndev; dev_node_t node[8]; @@ -92,9 +97,6 @@ static dev_link_t *qlogic_attach(void); static void qlogic_detach(dev_link_t *); -/* Import our driver template */ -extern Scsi_Host_Template qlogicfas_driver_template; -#define driver_template qlogicfas_driver_template static dev_link_t *dev_list = NULL; @@ -233,7 +235,6 @@ info->manf_id = le16_to_cpu(tuple.TupleData[0]); /* Configure card */ - driver_template.module = &__this_module; link->state |= DEV_CONFIG; tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -272,46 +273,52 @@ else qlogicfas_preset(link->io.BasePort1, link->irq.AssignedIRQ); - scsi_register_host(&driver_template); - tail = &link->dev; info->ndev = 0; - for (host = scsi_host_get_next(NULL); host; host = scsi_host_get_next(host)) - if (host->hostt == &driver_template) - list_for_each_entry (dev, &host->my_devices, siblings) { - u_long arg[2], id; - kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); - id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - sprintf(node->dev_name, "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - sprintf(node->dev_name, "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - sprintf(node->dev_name, "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - sprintf(node->dev_name, "sg#%04lx", id); - break; - } - *tail = node; - tail = &node->next; - info->ndev++; - } - *tail = NULL; - if (info->ndev == 0) + + host = __qlogicfas_detect(&qlogicfas_driver_template); + if (!host) { printk(KERN_INFO "qlogic_cs: no SCSI devices found\n"); + goto out; + } + + scsi_add_host(host, NULL); + + list_for_each_entry(dev, &host->my_devices, siblings) { + u_long arg[2], id; + kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg); + id = (arg[0] & 0x0f) + ((arg[0] >> 4) & 0xf0) + ((arg[0] >> 8) & 0xf00) + ((arg[0] >> 12) & 0xf000); + node = &info->node[info->ndev]; + node->minor = 0; + switch (dev->type) { + case TYPE_TAPE: + node->major = SCSI_TAPE_MAJOR; + sprintf(node->dev_name, "st#%04lx", id); + break; + case TYPE_DISK: + case TYPE_MOD: + node->major = SCSI_DISK0_MAJOR; + sprintf(node->dev_name, "sd#%04lx", id); + break; + case TYPE_ROM: + case TYPE_WORM: + node->major = SCSI_CDROM_MAJOR; + sprintf(node->dev_name, "sr#%04lx", id); + break; + default: + node->major = SCSI_GENERIC_MAJOR; + sprintf(node->dev_name, "sg#%04lx", id); + break; + } + *tail = node; + tail = &node->next; + info->ndev++; + } + *tail = NULL; + info->host = host; + +out: link->state &= ~DEV_CONFIG_PENDING; return; @@ -327,29 +334,22 @@ static void qlogic_release(u_long arg) { dev_link_t *link = (dev_link_t *) arg; + scsi_info_t *info = link->priv; DEBUG(0, "qlogic_release(0x%p)\n", link); -#warning This does not protect you. You need some real fix for your races. -#if 0 - if (GET_USE_COUNT(&__this_module) != 0) { - DEBUG(0, "qlogic_cs: release postponed, device still open\n"); - link->state |= DEV_STALE_CONFIG; - return; - } -#endif - - scsi_unregister_host(&driver_template); + scsi_remove_host(info->host); link->dev = NULL; CardServices(ReleaseConfiguration, link->handle); CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); + scsi_unregister(info->host); + link->state &= ~DEV_CONFIG; if (link->state & DEV_STALE_LINK) qlogic_detach(link); - } /* qlogic_release */ /*====================================================================*/ @@ -390,7 +390,7 @@ outb(0x04, link->io.BasePort1 + 0xd); } /* Ugggglllyyyy!!! */ - driver_template.eh_bus_reset_handler(NULL); + qlogicfas_bus_reset(NULL); } break; } diff -Nru a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c --- a/drivers/scsi/qlogicfas.c Sat Mar 15 18:40:45 2003 +++ b/drivers/scsi/qlogicfas.c Sat Mar 15 18:40:45 2003 @@ -127,11 +127,6 @@ #endif #include - -#ifdef PCMCIA -#undef MODULE -#endif - #include /* to get disk capacity */ #include #include @@ -148,7 +143,6 @@ #include "scsi.h" #include "hosts.h" -#include "qlogicfas.h" /*----------------------------------------------------------------*/ /* driver state info, local to driver */ @@ -166,6 +160,8 @@ static int qlcfg9 = ((XTALFREQ + 4) / 5); static int qlcfgc = (FASTCLK << 3) | (FASTSCSI << 4); +int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); + /*----------------------------------------------------------------*/ /* The qlogic card uses two register maps - These macros select which one */ #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) @@ -631,14 +627,12 @@ * Look for qlogic card and init if found */ -int __devinit qlogicfas_detect(Scsi_Host_Template * host) +struct Scsi_Host *__qlogicfas_detect(Scsi_Host_Template *host) { int i, j; /* these are only used by IRQ detect */ int qltyp; /* type of chip */ struct Scsi_Host *hreg; /* registered host structure */ - host->proc_name = "qlogicfas"; - /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself * decodes the address - I check 230 first since MIDI cards are * typically at 0x330 @@ -659,7 +653,7 @@ release_region(qbase, 0x10); } if (qbase == 0x430) - return 0; + return NULL;; } else printk(KERN_INFO "Ql: Using preset base address of %03x\n", qbase); @@ -726,16 +720,21 @@ qltyp, qbase, qlirq, QL_TURBO_PDMA); host->name = qinfo; - return 1; + return hreg; err_release_mem: release_region(qbase, 0x10); if (host->can_queue) free_irq(qlirq, do_ql_ihandl); - return 0; + return NULL;; } +int __devinit qlogicfas_detect(Scsi_Host_Template *sht) +{ + return (__qlogicfas_detect(sht) != NULL); +} + /* * Return bios parameters */ @@ -777,7 +776,7 @@ * the PCMCIA qlogic_stub code. This wants fixing */ -static int qlogicfas_bus_reset(Scsi_Cmnd * cmd) +int qlogicfas_bus_reset(Scsi_Cmnd * cmd) { qabort = 2; ql_zap(); @@ -818,9 +817,27 @@ /* * The driver template is also needed for PCMCIA */ - -Scsi_Host_Template qlogicfas_driver_template = QLOGICFAS; -#define driver_template qlogicfas_driver_template +Scsi_Host_Template qlogicfas_driver_template = { + .module = THIS_MODULE, + .name = "qlogicfas", + .proc_name = "qlogicfas", + .detect = qlogicfas_detect, + .info = qlogicfas_info, + .command = qlogicfas_command, + .queuecommand = qlogicfas_queuecommand, + .eh_abort_handler = qlogicfas_abort, + .eh_bus_reset_handler = qlogicfas_bus_reset, + .eh_device_reset_handler= qlogicfas_device_reset, + .eh_host_reset_handler = qlogicfas_host_reset, + .bios_param = qlogicfas_biosparam, + .can_queue = 0, + .this_id = -1, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 1, + .use_clustering = DISABLE_CLUSTERING, +}; +#ifndef PCMCIA +#define driver_template qlogicfas_driver_template #include "scsi_module.c" - +#endif diff -Nru a/drivers/scsi/qlogicfas.h b/drivers/scsi/qlogicfas.h --- a/drivers/scsi/qlogicfas.h Sat Mar 15 18:40:41 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -#ifndef _QLOGICFAS_H -#define _QLOGICFAS_H - -static int qlogicfas_detect(Scsi_Host_Template * ); -static const char * qlogicfas_info(struct Scsi_Host *); -static int qlogicfas_command(Scsi_Cmnd *); -static int qlogicfas_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *)); -static int qlogicfas_abort(Scsi_Cmnd *); -static int qlogicfas_bus_reset(Scsi_Cmnd *); -static int qlogicfas_device_reset(Scsi_Cmnd *); -static int qlogicfas_host_reset(Scsi_Cmnd *); -static int qlogicfas_biosparam(struct scsi_device *, struct block_device *, - sector_t, int[]); - -#define QLOGICFAS { \ - .detect = qlogicfas_detect, \ - .info = qlogicfas_info, \ - .command = qlogicfas_command, \ - .queuecommand = qlogicfas_queuecommand, \ - .eh_abort_handler = qlogicfas_abort, \ - .eh_bus_reset_handler = qlogicfas_bus_reset, \ - .eh_device_reset_handler = qlogicfas_device_reset, \ - .eh_host_reset_handler = qlogicfas_host_reset, \ - .bios_param = qlogicfas_biosparam, \ - .can_queue = 0, \ - .this_id = -1, \ - .sg_tablesize = SG_ALL, \ - .cmd_per_lun = 1, \ - .use_clustering = DISABLE_CLUSTERING \ -} -#endif /* _QLOGICFAS_H */ - - - diff -Nru a/drivers/scsi/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/qlogicfc.c Sat Mar 15 18:40:43 2003 @@ -694,7 +694,7 @@ int isp2x00_detect(Scsi_Host_Template * tmpt) { int hosts = 0; - int wait_time; + unsigned long wait_time; struct Scsi_Host *host = NULL; struct isp2x00_hostdata *hostdata; struct pci_dev *pdev; diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Sat Mar 15 18:40:40 2003 +++ b/drivers/scsi/scsi.h Sat Mar 15 18:40:40 2003 @@ -280,26 +280,7 @@ #define SCSI_SET_IOCTL_LOGGING(LEVEL) \ SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL); -/* - * the return of the status word will be in the following format : - * The low byte is the status returned by the SCSI command, - * with vendor specific bits masked. - * - * The next byte is the message which followed the SCSI status. - * This allows a stos to be used, since the Intel is a little - * endian machine. - * - * The final byte is a host return code, which is one of the following. - * - * IE - * lsb msb - * status msg host code - * - * Our errors returned by OUR driver, NOT SCSI message. Or'd with - * SCSI message passed back to driver . - */ - - +/* host byte codes */ #define DID_OK 0x00 /* NO error */ #define DID_NO_CONNECT 0x01 /* Couldn't connect before timeout period */ #define DID_BUS_BUSY 0x02 /* BUS stayed busy through time out period */ diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Sat Mar 15 18:40:39 2003 +++ b/drivers/scsi/scsi_error.c Sat Mar 15 18:40:39 2003 @@ -92,10 +92,8 @@ * * Notes: * This should be turned into an inline function. Each scsi command - * has it's own timer, and as it is added to the queue, we set up the - * timer. When the command completes, we cancel the timer. Pretty - * simple, really, especially compared to the old way of handling this - * crap. + * has its own timer, and as it is added to the queue, we set up the + * timer. When the command completes, we cancel the timer. **/ void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, void (*complete)(struct scsi_cmnd *)) @@ -249,6 +247,7 @@ { if (!SCSI_SENSE_VALID(scmd)) return FAILED; + if (scmd->sense_buffer[2] & 0xe0) return SUCCESS; @@ -515,7 +514,7 @@ * actually did complete normally. */ if (rtn == SUCCESS) { - int rtn = scsi_eh_completed_normally(scmd); + rtn = scsi_eh_completed_normally(scmd); SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scsi_eh_completed_normally %x\n", __FUNCTION__, rtn)); @@ -545,20 +544,20 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) { static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 255, 0}; - unsigned char scsi_result0[256], *scsi_result = &scsi_result0[0]; + {REQUEST_SENSE, 0, 0, 0, 254, 0}; + unsigned char *scsi_result; int saved_result; int rtn; memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense)); - if (scmd->device->host->hostt->unchecked_isa_dma) { - scsi_result = kmalloc(512, GFP_ATOMIC | __GFP_DMA); - if (unlikely(!scsi_result)) { - printk(KERN_ERR "%s: cannot allocate scsi_result.\n", - __FUNCTION__); - return FAILED; - } + scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0); + + + if (unlikely(!scsi_result)) { + printk(KERN_ERR "%s: cannot allocate scsi_result.\n", + __FUNCTION__); + return FAILED; } /* @@ -568,11 +567,11 @@ * address (db). 0 is not a valid sense code. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); - memset(scsi_result, 0, 256); + memset(scsi_result, 0, 254); saved_result = scmd->result; scmd->request_buffer = scsi_result; - scmd->request_bufflen = 256; + scmd->request_bufflen = 254; scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); scmd->sc_data_direction = SCSI_DATA_READ; @@ -581,13 +580,12 @@ rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); /* last chance to have valid sense data */ - if (!SCSI_SENSE_VALID(scmd)) { + if(!SCSI_SENSE_VALID(scmd)) { memcpy(scmd->sense_buffer, scmd->request_buffer, - sizeof(scmd->sense_buffer)); + sizeof(scmd->sense_buffer)); } - if (scsi_result != &scsi_result0[0]) - kfree(scsi_result); + kfree(scsi_result); /* * when we eventually call scsi_finish, we really wish to complete @@ -703,25 +701,14 @@ * upper level. */ if (rtn == SUCCESS) - scsi_eh_finish_cmd(scmd, done_q); - if (rtn != NEEDS_RETRY) - continue; - - /* - * we only come in here if we want to retry a - * command. the test to see whether the command - * should be retried should be keeping track of the - * number of tries, so we don't end up looping, of - * course. - */ - scmd->state = NEEDS_RETRY; - rtn = scsi_eh_retry_cmd(scmd); - if (rtn != SUCCESS) + /* we don't want this command reissued, just + * finished with the sense data, so set + * retries to the max allowed to ensure it + * won't get reissued */ + scmd->retries = scmd->allowed; + else if (rtn != NEEDS_RETRY) continue; - /* - * we eventually hand this one back to the top level. - */ scsi_eh_finish_cmd(scmd, done_q); } @@ -1193,12 +1180,12 @@ * Notes: * This is *only* called when we are examining the status after sending * out the actual data command. any commands that are queued for error - * recovery (i.e. test_unit_ready) do *not* come through here. + * recovery (e.g. test_unit_ready) do *not* come through here. * * When this routine returns failed, it means the error handler thread - * is woken. in cases where the error code indicates an error that + * is woken. In cases where the error code indicates an error that * doesn't require the error handler read (i.e. we don't need to - * abort/reset), then this function should return SUCCESS. + * abort/reset), this function should return SUCCESS. **/ int scsi_decide_disposition(struct scsi_cmnd *scmd) { @@ -1214,11 +1201,11 @@ __FUNCTION__)); return SUCCESS; } + /* * first check the host byte, to see if there is anything in there * that would indicate what we need to do. */ - switch (host_byte(scmd->result)) { case DID_PASSTHROUGH: /* @@ -1296,11 +1283,11 @@ /* * next, check the message byte. */ - if (msg_byte(scmd->result) != COMMAND_COMPLETE) { + if (msg_byte(scmd->result) != COMMAND_COMPLETE) return FAILED; - } + /* - * now, check the status byte to see if this indicates anything special. + * check the status byte to see if this indicates anything special. */ switch (status_byte(scmd->result)) { case QUEUE_FULL: @@ -1321,9 +1308,12 @@ return SUCCESS; case CHECK_CONDITION: rtn = scsi_check_sense(scmd); - if (rtn == NEEDS_RETRY) { + if (rtn == NEEDS_RETRY) goto maybe_retry; - } + /* if rtn == FAILED, we have no sense information; + * returning FAILED will wake the error handler thread + * to collect the sense and redo the decide + * disposition */ return rtn; case CONDITION_GOOD: case INTERMEDIATE_GOOD: @@ -1490,9 +1480,9 @@ struct list_head *work_q, struct list_head *done_q) { - if (scsi_eh_bus_device_reset(shost, work_q, done_q)) - if (scsi_eh_bus_reset(shost, work_q, done_q)) - if (scsi_eh_host_reset(work_q, done_q)) + if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) + if (!scsi_eh_bus_reset(shost, work_q, done_q)) + if (!scsi_eh_host_reset(work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Sat Mar 15 18:40:42 2003 +++ b/drivers/scsi/scsi_lib.c Sat Mar 15 18:40:42 2003 @@ -265,7 +265,6 @@ cmd->serial_number = 0; cmd->serial_number_at_timeout = 0; cmd->flags = 0; - cmd->retries = 0; cmd->abort_reason = 0; memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Sat Mar 15 18:40:44 2003 +++ b/drivers/scsi/scsi_scan.c Sat Mar 15 18:40:44 2003 @@ -960,7 +960,6 @@ SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: host %d channel %d" " id %d lun %d name/id: '%s'\n", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun, sdev->sdev_driverfs_dev.name)); - return; } /** diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/sd.c Sat Mar 15 18:40:43 2003 @@ -1197,7 +1197,7 @@ return; } - buffer = kmalloc(512, GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { printk(KERN_WARNING "(sd_init_onedisk:) Memory allocation " "failure.\n"); @@ -1389,14 +1389,9 @@ SCSI_LOG_HLQUEUE(3, printk("init_sd: sd driver entry point\n")); - for (i = 0; i < SD_MAJORS; i++) { - if (register_blkdev(sd_major(i), "sd", &sd_fops)) - printk(KERN_NOTICE - "Unable to get major %d for SCSI disk\n", - sd_major(i)); - else + for (i = 0; i < SD_MAJORS; i++) + if (register_blkdev(sd_major(i), "sd") == 0) majors++; - } if (!majors) return -ENODEV; @@ -1409,7 +1404,7 @@ } /** - * exit_sd - exit point for this driver (when it is a module). + * exit_sd - exit point for this driver (when it is a module). * * Note: this function unregisters this driver from the scsi mid-level. **/ diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Sat Mar 15 18:40:40 2003 +++ b/drivers/scsi/sr.c Sat Mar 15 18:40:40 2003 @@ -604,7 +604,7 @@ struct scsi_request *SRpnt = NULL; request_queue_t *queue; - buffer = kmalloc(512, GFP_DMA); + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) goto Enomem; SRpnt = scsi_allocate_request(cd->device); @@ -698,7 +698,7 @@ goto out; } -void get_capabilities(struct scsi_cd *cd) +static void get_capabilities(struct scsi_cd *cd) { struct cdrom_generic_command cgc; unsigned char *buffer; @@ -716,9 +716,8 @@ "" }; - buffer = kmalloc(512, GFP_DMA); - if (!buffer) - { + buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); + if (!buffer) { printk(KERN_ERR "sr: out of memory.\n"); return; } @@ -835,7 +834,7 @@ { int rc; - rc = register_blkdev(SCSI_CDROM_MAJOR, "sr", &sr_bdops); + rc = register_blkdev(SCSI_CDROM_MAJOR, "sr"); if (rc) return rc; return scsi_register_device(&sr_template); diff -Nru a/drivers/scsi/sym53c8xx.c b/drivers/scsi/sym53c8xx.c --- a/drivers/scsi/sym53c8xx.c Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/sym53c8xx.c Sat Mar 15 18:40:43 2003 @@ -112,8 +112,8 @@ #include #endif #include +#include #include -#include #include #include #include @@ -7214,7 +7214,6 @@ **========================================================== */ -#ifdef MODULE static int ncr_detach(ncb_p np) { int i; @@ -7260,7 +7259,6 @@ return 1; } -#endif /*========================================================== ** @@ -12958,6 +12956,7 @@ } if (i != count) /* Ignore this device if we already have it */ continue; + pci_set_master(pcidev); devp = &devtbl[count]; devp->host_id = driver_setup.host_id; devp->attach_done = 0; @@ -13798,7 +13797,6 @@ } -#ifdef MODULE int sym53c8xx_release(struct Scsi_Host *host) { #ifdef DEBUG_SYM53C8XX @@ -13808,7 +13806,6 @@ return 1; } -#endif /* diff -Nru a/drivers/scsi/sym53c8xx.h b/drivers/scsi/sym53c8xx.h --- a/drivers/scsi/sym53c8xx.h Sat Mar 15 18:40:41 2003 +++ b/drivers/scsi/sym53c8xx.h Sat Mar 15 18:40:41 2003 @@ -75,17 +75,11 @@ int sym53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int sym53c8xx_reset(Scsi_Cmnd *, unsigned int); int sym53c8xx_slave_configure(Scsi_Device *); - -#ifdef MODULE int sym53c8xx_release(struct Scsi_Host *); -#else -#define sym53c8xx_release NULL -#endif - #if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,75) -#define SYM53C8XX { .name = "", \ +#define SYM53C8XX { .name = "sym53c8xx", \ .detect = sym53c8xx_detect, \ .release = sym53c8xx_release, \ .info = sym53c8xx_info, \ diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c Sat Mar 15 18:40:39 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c Sat Mar 15 18:40:39 2003 @@ -221,7 +221,7 @@ */ static void sym_soft_reset (hcb_p np) { - u_char istat; + u_char istat = 0; int i; if (!(np->features & FE_ISTAT1) || !(INB (nc_istat1) & SCRUN)) diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c --- a/drivers/scsi/zalon.c Sat Mar 15 18:40:43 2003 +++ b/drivers/scsi/zalon.c Sat Mar 15 18:40:43 2003 @@ -151,7 +151,6 @@ return (hosts_used != 0); } -#ifdef MODULE extern int ncr53c8xx_release(struct Scsi_Host *host); int zalon7xx_release(struct Scsi_Host *host) @@ -160,4 +159,3 @@ unregister_parisc_driver(&zalon_driver); return 1; } -#endif diff -Nru a/drivers/scsi/zalon.h b/drivers/scsi/zalon.h --- a/drivers/scsi/zalon.h Sat Mar 15 18:40:42 2003 +++ b/drivers/scsi/zalon.h Sat Mar 15 18:40:42 2003 @@ -15,12 +15,7 @@ int zalon7xx_detect(Scsi_Host_Template *tpnt); const char *ncr53c8xx_info(struct Scsi_Host *host); int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); - -#ifdef MODULE int zalon7xx_release(struct Scsi_Host *); -#else -#define zalon7xx_release NULL -#endif #define GSC_SCSI_ZALON_OFFSET 0x800 diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Sat Mar 15 18:40:43 2003 +++ b/drivers/serial/21285.c Sat Mar 15 18:40:43 2003 @@ -501,11 +501,12 @@ .index = -1, }; -void __init rs285_console_init(void) +static void __init rs285_console_init(void) { serial21285_setup_ports(); register_console(&serial21285_console); } +console_initcall(rs285_console_init); #define SERIAL_21285_CONSOLE &serial21285_console #else diff -Nru a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c --- a/drivers/serial/68328serial.c Sat Mar 15 18:40:44 2003 +++ b/drivers/serial/68328serial.c Sat Mar 15 18:40:44 2003 @@ -1691,8 +1691,9 @@ }; -void m68328_console_init(void) +static void __init m68328_console_init(void) { register_console(&m68328_driver); } +console_initcall(m68328_console_init); diff -Nru a/drivers/serial/68328serial.h b/drivers/serial/68328serial.h --- a/drivers/serial/68328serial.h Sat Mar 15 18:40:44 2003 +++ b/drivers/serial/68328serial.h Sat Mar 15 18:40:44 2003 @@ -161,8 +161,8 @@ int xmit_head; int xmit_tail; int xmit_cnt; - struct workqueue tqueue; - struct workqueue tqueue_hangup; + struct work_struct tqueue; + struct work_struct tqueue_hangup; struct termios normal_termios; struct termios callout_termios; wait_queue_head_t open_wait; diff -Nru a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c --- a/drivers/serial/68360serial.c Sat Mar 15 18:40:44 2003 +++ b/drivers/serial/68360serial.c Sat Mar 15 18:40:44 2003 @@ -74,8 +74,6 @@ static char *serial_name = "CPM UART driver"; static char *serial_version = "0.03"; -static DECLARE_TASK_QUEUE(tq_serial); - static struct tty_driver serial_driver, callout_driver; static int serial_refcount; int serial_console_setup(struct console *co, char *options); @@ -243,7 +241,7 @@ int magic; int flags; - struct serial_state *state; + struct serial_state *state; /* struct serial_struct *state; */ /* struct async_struct *state; */ @@ -261,12 +259,10 @@ int blocked_open; /* # of blocked opens */ long session; /* Session of opening process */ long pgrp; /* pgrp of opening process */ - struct tq_struct tqueue; - struct tq_struct tqueue_hangup; + struct work_struct tqueue; + struct work_struct tqueue_hangup; wait_queue_head_t open_wait; wait_queue_head_t close_wait; -/* struct wait_queue *open_wait; */ -/* struct wait_queue *close_wait;i */ /* CPM Buffer Descriptor pointers. @@ -324,7 +320,7 @@ #elif defined(CONFIG_CONSOLE_115200) #define CONSOLE_BAUDRATE 115200 #else - #warn "console baud rate undefined" + #warning "console baud rate undefined" #define CONSOLE_BAUDRATE 9600 #endif @@ -405,18 +401,6 @@ * ----------------------------------------------------------------------- */ -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static _INLINE_ void rs_sched_event(ser_info_t *info, - int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - static _INLINE_ void receive_chars(ser_info_t *info) { struct tty_struct *tty = info->tty; @@ -556,7 +540,7 @@ info->rx_cur = (QUICC_BD *)bdp; - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_work(&tty->flip.work); } static _INLINE_ void receive_break(ser_info_t *info) @@ -573,7 +557,7 @@ *(tty->flip.char_buf_ptr++) = 0; tty->flip.count++; - queue_task(&tty->flip.tqueue, &tq_timer); + schedule_work(&tty->flip.work); } static _INLINE_ void transmit_chars(ser_info_t *info) @@ -581,7 +565,7 @@ if ((info->flags & TX_WAKEUP) || (info->tty->flags & (1 << TTY_DO_WRITE_WAKEUP))) { - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); + schedule_work(&info->tqueue); } #ifdef SERIAL_DEBUG_INTR @@ -717,19 +701,6 @@ * ------------------------------------------------------------------- */ -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); -} static void do_softint(void *private_) { @@ -749,8 +720,6 @@ } - - /* * This routine is called from the scheduler tqueue when the interrupt * routine has signalled that a hangup has occurred. The path of @@ -772,11 +741,6 @@ tty_hangup(tty); } -/*static void rs_360_timer(void) -{ - printk("rs_360_timer\n"); -}*/ - static int startup(ser_info_t *info) { @@ -1841,7 +1805,7 @@ */ char_time = 1; if (timeout) - char_time = min(char_time, timeout); + char_time = min(char_time, (unsigned long)timeout); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); printk("jiff=%lu...", jiffies); @@ -2078,7 +2042,7 @@ ser_info_t *info; int retval, line; - line = MINOR(tty->device) - tty->driver.minor_start; + line = minor(tty->device) - tty->driver.minor_start; if ((line < 0) || (line >= NR_PORTS)) return -ENODEV; retval = get_async_struct(line, &info); @@ -2612,8 +2576,6 @@ volatile struct uart_pram *sup; /* volatile immap_t *immap; */ - init_bh(SERIAL_BH, do_serial_bh); - show_serial_version(); /* Initialize the tty_driver structure */ @@ -2763,17 +2725,14 @@ /* info = kmalloc(sizeof(ser_info_t), GFP_KERNEL); */ info = &quicc_ser_info[i]; if (info) { - /* __clear_user(info,sizeof(ser_info_t)); */ memset (info, 0, sizeof(ser_info_t)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); info->magic = SERIAL_MAGIC; - info->flags = state->flags; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->tqueue_hangup.routine = do_serial_hangup; - info->tqueue_hangup.data = info; info->line = i; + info->flags = state->flags; + INIT_WORK(&info->tqueue, do_softint, info); + INIT_WORK(&info->tqueue_hangup, do_serial_hangup, info); + init_waitqueue_head(&info->open_wait); + init_waitqueue_head(&info->close_wait); info->state = state; state->info = (struct async_struct *)info; @@ -2818,15 +2777,6 @@ *(uint *)_periph_base = sipex_mode_bits; /* printk ("sipex bits = 0x%08x\n", sipex_mode_bits); */ #endif - - scp = &pquicc->scc_regs[idx]; - sup = &pquicc->pram[info->state->port].scc.pscc.u; - sup->rbase = dp_addr; - } - else { - sp = &cp->smc_regs[idx]; - up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u; - up->rbase = dp_addr; } dp_addr = m360_cpm_dpalloc(sizeof(QUICC_BD) * TX_NUM_FIFO); @@ -2856,6 +2806,9 @@ bdp->status = (BD_SC_WRAP | BD_SC_INTRPT); if (info->state->smc_scc_num & NUM_IS_SCC) { + scp = &pquicc->scc_regs[idx]; + sup = &pquicc->pram[info->state->port].scc.pscc.u; + sup->rbase = dp_addr; sup->tbase = dp_addr; /* Set up the uart parameters in the @@ -2919,6 +2872,8 @@ /* Configure SMCs Tx/Rx instead of port B * parallel I/O. */ + up = &pquicc->pram[info->state->port].scc.pothers.idma_smc.psmc.u; + up->rbase = dp_addr; iobits = 0xc0 << (idx * 4); cp->pip_pbpar |= iobits; @@ -2964,6 +2919,7 @@ /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ + sp = &cp->smc_regs[idx]; sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; /* Disable all interrupts and clear all pending @@ -3008,8 +2964,7 @@ int serial_console_setup( struct console *co, char *options) { struct serial_state *ser; - uint mem_addr, dp_addr, bidx, idx, iobits; - int i; + uint mem_addr, dp_addr, bidx, idx, iobits; ushort chan; QUICC_BD *bdp; volatile QUICC *cp; @@ -3038,18 +2993,11 @@ idx = PORT_NUM(ser->smc_scc_num); if (ser->smc_scc_num & NUM_IS_SCC) { - scp = &cp->scc_regs[idx]; - /* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */ - sup = &pquicc->pram[ser->port].scc.pscc.u; /* TODO: need to set up SCC pin assignment etc. here */ } else { - sp = &cp->smc_regs[idx]; - /* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */ - up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u; - iobits = 0xc0 << (idx * 4); cp->pip_pbpar |= iobits; cp->pip_pbdir &= ~iobits; @@ -3096,6 +3044,9 @@ /* Set up the uart parameters in the parameter ram. */ if (ser->smc_scc_num & NUM_IS_SCC) { + scp = &cp->scc_regs[idx]; + /* sup = (scc_uart_t *)&cp->cp_dparam[ser->port]; */ + sup = &pquicc->pram[ser->port].scc.pscc.u; sup->rbase = dp_addr; sup->tbase = dp_addr + sizeof(QUICC_BD); @@ -3153,6 +3104,9 @@ } else { + /* up = (smc_uart_t *)&cp->cp_dparam[ser->port]; */ + up = &pquicc->pram[ser->port].scc.pothers.idma_smc.psmc.u; + up->rbase = dp_addr; /* Base of receive buffer desc. */ up->tbase = dp_addr+sizeof(QUICC_BD); /* Base of xmt buffer desc. */ up->rfcr = SMC_EB; @@ -3167,12 +3121,12 @@ */ chan = smc_chan_map[idx]; cp->cp_cr = mk_cr_cmd(chan, CPM_CR_INIT_TRX) | CPM_CR_FLG; - printk(""); while (cp->cp_cr & CPM_CR_FLG); /* Set UART mode, 8 bit, no parity, one stop. * Enable receive and transmit. */ + sp = &cp->smc_regs[idx]; sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART; /* And finally, enable Rx and Tx. diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Sat Mar 15 18:40:39 2003 +++ b/drivers/serial/8250.c Sat Mar 15 18:40:39 2003 @@ -93,13 +93,15 @@ #ifdef CONFIG_SERIAL_8250_MULTIPORT #define CONFIG_SERIAL_MULTIPORT 1 #endif +#ifdef CONFIG_SERIAL_8250_MANY_PORTS +#define CONFIG_SERIAL_MANY_PORTS 1 +#endif /* * HUB6 is always on. This will be removed once the header * files have been cleaned. */ #define CONFIG_HUB6 1 -#define CONFIG_SERIAL_MANY_PORTS 1 #include @@ -1982,11 +1984,13 @@ .index = -1, }; -void __init serial8250_console_init(void) +static int __init serial8250_console_init(void) { serial8250_isa_init_ports(); register_console(&serial8250_console); + return 0; } +console_initcall(serial8250_console_init); #define SERIAL8250_CONSOLE &serial8250_console #else @@ -2093,6 +2097,28 @@ } } +/** + * serial8250_suspend_port - suspend one serial port + * @line: serial line number + * + * Suspend one serial port. + */ +void serial8250_suspend_port(int line, u32 level) +{ + uart_suspend_port(&serial8250_reg, &serial8250_ports[line].port, level); +} + +/** + * serial8250_resume_port - resume one serial port + * @line: serial line number + * + * Resume one serial port. + */ +void serial8250_resume_port(int line, u32 level) +{ + uart_resume_port(&serial8250_reg, &serial8250_ports[line].port, level); +} + static int __init serial8250_init(void) { int ret, i; @@ -2126,6 +2152,8 @@ EXPORT_SYMBOL(register_serial); EXPORT_SYMBOL(unregister_serial); EXPORT_SYMBOL(serial8250_get_irq_map); +EXPORT_SYMBOL(serial8250_suspend_port); +EXPORT_SYMBOL(serial8250_resume_port); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic 8250/16x50 serial driver $Revision: 1.90 $"); diff -Nru a/drivers/serial/8250.h b/drivers/serial/8250.h --- a/drivers/serial/8250.h Sat Mar 15 18:40:39 2003 +++ b/drivers/serial/8250.h Sat Mar 15 18:40:39 2003 @@ -27,6 +27,8 @@ int serial8250_register_probe(struct serial8250_probe *probe); void serial8250_unregister_probe(struct serial8250_probe *probe); void serial8250_get_irq_map(unsigned int *map); +void serial8250_suspend_port(int line, u32 level); +void serial8250_resume_port(int line, u32 level); struct old_serial_port { unsigned int uart; diff -Nru a/drivers/serial/8250_acorn.c b/drivers/serial/8250_acorn.c --- a/drivers/serial/8250_acorn.c Sat Mar 15 18:40:44 2003 +++ b/drivers/serial/8250_acorn.c Sat Mar 15 18:40:44 2003 @@ -1,7 +1,7 @@ /* * linux/drivers/serial/acorn.c * - * Copyright (C) 1996-2002 Russell King. + * Copyright (C) 1996-2003 Russell King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -9,6 +9,8 @@ */ #include #include +#include +#include #include #include #include @@ -16,6 +18,7 @@ #include #include +#include #include #include @@ -24,36 +27,41 @@ struct serial_card_type { unsigned int num_ports; unsigned int baud_base; - int type; - int speed; - int offset[MAX_PORTS]; + unsigned int type; + unsigned int offset[MAX_PORTS]; }; struct serial_card_info { unsigned int num_ports; int ports[MAX_PORTS]; - unsigned long base[MAX_PORTS]; }; -static inline int serial_register_onedev(unsigned long port, int irq, unsigned int baud_base) +static inline int +serial_register_onedev(unsigned long baddr, void *vaddr, int irq, unsigned int baud_base) { struct serial_struct req; memset(&req, 0, sizeof(req)); - req.baud_base = baud_base; - req.irq = irq; - req.port = port; - req.flags = 0; + req.irq = irq; + req.flags = UPF_AUTOPROBE | UPF_RESOURCES | + UPF_SHARE_IRQ; + req.baud_base = baud_base; + req.io_type = UPIO_MEM; + req.iomem_base = vaddr; + req.iomem_reg_shift = 2; + req.iomap_base = baddr; return register_serial(&req); } -static int __devinit serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) +static int __devinit +serial_card_probe(struct expansion_card *ec, const struct ecard_id *id) { struct serial_card_info *info; struct serial_card_type *type = id->data; - unsigned long cardaddr, address; - int port; + unsigned long bus_addr; + unsigned char *virt_addr; + unsigned int port; info = kmalloc(sizeof(struct serial_card_info), GFP_KERNEL); if (!info) @@ -64,20 +72,19 @@ ecard_set_drvdata(ec, info); - cardaddr = ecard_address(ec, type->type, type->speed); + bus_addr = ec->resource[type->type].start; + virt_addr = ioremap(bus_addr, ec->resource[type->type].end - bus_addr + 1); + if (!virt_addr) { + kfree(info); + return -ENOMEM; + } for (port = 0; port < info->num_ports; port ++) { - address = cardaddr + type->offset[port]; - - info->ports[port] = -1; - info->base[port] = address; + unsigned long baddr = bus_addr + type->offset[port]; + unsigned char *vaddr = virt_addr + type->offset[port]; - if (!request_region(address, 8, "acornserial")) - continue; - - info->ports[port] = serial_register_onedev(address, ec->irq, type->baud_base); - if (info->ports[port] < 0) - break; + info->ports[port] = serial_register_onedev(baddr, vaddr, + ec->irq, type->baud_base); } return 0; @@ -90,12 +97,9 @@ ecard_set_drvdata(ec, NULL); - for (i = 0; i < info->num_ports; i++) { - if (info->ports[i] > 0) { + for (i = 0; i < info->num_ports; i++) + if (info->ports[i] > 0) unregister_serial(info->ports[i]); - release_region(info->base[i], 8); - } - } kfree(info); } @@ -103,17 +107,15 @@ static struct serial_card_type atomwide_type = { .num_ports = 3, .baud_base = 7372800 / 16, - .type = ECARD_IOC, - .speed = ECARD_SLOW, - .offset = { 0xa00, 0x900, 0x800 }, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2800, 0x2400, 0x2000 }, }; static struct serial_card_type serport_type = { .num_ports = 2, .baud_base = 3686400 / 16, - .type = ECARD_IOC, - .speed = ECARD_SLOW, - .offset = { 0x800, 0x808 }, + .type = ECARD_RES_IOCSLOW, + .offset = { 0x2000, 0x2020 }, }; static const struct ecard_id serial_cids[] = { @@ -127,7 +129,8 @@ .remove = __devexit_p(serial_card_remove), .id_table = serial_cids, .drv = { - .name = "acornserial", + .devclass = &tty_devclass, + .name = "8250_acorn", }, }; @@ -142,6 +145,7 @@ } MODULE_AUTHOR("Russell King"); +MODULE_DESCRIPTION("Acorn 8250-compatible serial port expansion card driver"); MODULE_LICENSE("GPL"); module_init(serial_card_init); diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c Sat Mar 15 18:40:43 2003 +++ b/drivers/serial/8250_pci.c Sat Mar 15 18:40:43 2003 @@ -20,8 +20,9 @@ #include #include #include +#include #include -#include +#include #include #include @@ -30,174 +31,213 @@ #include "8250.h" +/* + * Definitions for PCI support. + */ +#define FL_BASE_MASK 0x0007 +#define FL_BASE0 0x0000 +#define FL_BASE1 0x0001 +#define FL_BASE2 0x0002 +#define FL_BASE3 0x0003 +#define FL_BASE4 0x0004 +#define FL_GET_BASE(x) (x & FL_BASE_MASK) + +#define FL_IRQ_MASK (0x0007 << 4) +#define FL_IRQBASE0 (0x0000 << 4) +#define FL_IRQBASE1 (0x0001 << 4) +#define FL_IRQBASE2 (0x0002 << 4) +#define FL_IRQBASE3 (0x0003 << 4) +#define FL_IRQBASE4 (0x0004 << 4) +#define FL_GET_IRQBASE(x) ((x & FL_IRQ_MASK) >> 4) + +/* Use successive BARs (PCI base address registers), + else use offset into some specified BAR */ +#define FL_BASE_BARS 0x0008 -#ifndef IS_PCI_REGION_IOPORT -#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_IO) -#endif -#ifndef IS_PCI_REGION_IOMEM -#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \ - IORESOURCE_MEM) -#endif -#ifndef PCI_IRQ_RESOURCE -#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start) -#endif +/* Use the irq resource table instead of dev->irq */ +#define FL_IRQRESOURCE 0x0080 -#ifndef pci_get_subvendor -#define pci_get_subvendor(dev) ((dev)->subsystem_vendor) -#define pci_get_subdevice(dev) ((dev)->subsystem_device) -#endif +/* Use the Base address register size to cap number of ports */ +#define FL_REGION_SZ_CAP 0x0100 -struct serial_private { - unsigned int nr; - struct pci_board *board; - int line[0]; +struct pci_board { + unsigned int flags; + unsigned int num_ports; + unsigned int base_baud; + unsigned int uart_offset; + unsigned int reg_shift; + unsigned int first_offset; }; /* - * init_fn returns: + * init function returns: * > 0 - number of ports * = 0 - use board->num_ports * < 0 - error */ -struct pci_board { - int flags; - int num_ports; - int base_baud; - int uart_offset; - int reg_shift; - int (*init_fn)(struct pci_dev *dev, int enable); - int first_uart_offset; +struct pci_serial_quirk { + u32 vendor; + u32 device; + u32 subvendor; + u32 subdevice; + int (*init)(struct pci_dev *dev); + int (*setup)(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx); + void (*exit)(struct pci_dev *dev); +}; + +#define PCI_NUM_BAR_RESOURCES 6 + +struct serial_private { + unsigned int nr; + void *remapped_bar[PCI_NUM_BAR_RESOURCES]; + struct pci_serial_quirk *quirk; + int line[0]; }; +static void moan_device(const char *str, struct pci_dev *dev) +{ + printk(KERN_WARNING "%s: %s\n" + KERN_WARNING "Please send the output of lspci -vv, this\n" + KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + KERN_WARNING "manufacturer and name of serial board or\n" + KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n", + dev->slot_name, str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); +} + static int -get_pci_port(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +setup_port(struct pci_dev *dev, struct serial_struct *req, + int bar, int offset, int regshift) { - unsigned long port; - int base_idx; - int max_port; - int offset; + struct serial_private *priv = pci_get_drvdata(dev); + unsigned long port, len; + + if (bar >= PCI_NUM_BAR_RESOURCES) + return -EINVAL; - base_idx = SPCI_FL_GET_BASE(board->flags); - if (board->flags & SPCI_FL_BASE_TABLE) - base_idx += idx; - - if (board->flags & SPCI_FL_REGION_SZ_CAP) { - max_port = pci_resource_len(dev, base_idx) / 8; - if (idx >= max_port) - return 1; + if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { + port = pci_resource_start(dev, bar); + len = pci_resource_len(dev, bar); + + if (!priv->remapped_bar[bar]) + priv->remapped_bar[bar] = ioremap(port, len); + if (!priv->remapped_bar[bar]) + return -ENOMEM; + + req->io_type = UPIO_MEM; + req->iomap_base = port; + req->iomem_base = priv->remapped_bar[bar] + offset; + req->iomem_reg_shift = regshift; + } else { + port = pci_resource_start(dev, bar) + offset; + req->io_type = UPIO_PORT; + req->port = port; + if (HIGH_BITS_OFFSET) + req->port_high = port >> HIGH_BITS_OFFSET; } - - offset = board->first_uart_offset; + return 0; +} - /* - * Timedia/SUNIX uses a mixture of BARs and offsets - * Ugh, this is ugly as all hell --- TYT - */ - if (dev->vendor == PCI_VENDOR_ID_TIMEDIA) - switch(idx) { - case 0: - base_idx = 0; - break; - case 1: - base_idx = 0; - offset = 8; - break; - case 2: - base_idx = 1; - break; - case 3: - base_idx = 1; - offset = 8; - break; - case 4: /* BAR 2 */ - case 5: /* BAR 3 */ - case 6: /* BAR 4 */ - case 7: /* BAR 5 */ - base_idx = idx - 2; - } +/* + * AFAVLAB uses a different mixture of BARs and offsets + * Not that ugly ;) -- HW + */ +static int +afavlab_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset; + + bar = FL_GET_BASE(board->flags); + if (idx < 4) + bar += idx; + else + offset += (idx - 4) * board->uart_offset; - /* AFAVLAB uses a different mixture of BARs and offsets */ - /* Not that ugly ;) -- HW */ - if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) { - base_idx = 4; - offset = (idx - 4) * 8; - } + return setup_port(dev, req, bar, offset, board->reg_shift); +} - /* Some Titan cards are also a little weird */ - if (dev->vendor == PCI_VENDOR_ID_TITAN && - (dev->device == PCI_DEVICE_ID_TITAN_400L || - dev->device == PCI_DEVICE_ID_TITAN_800L)) { - switch (idx) { - case 0: base_idx = 1; - break; - case 1: base_idx = 2; - break; - default: - base_idx = 4; - offset = 8 * (idx - 2); - } - } +/* + * HP's Remote Management Console. The Diva chip came in several + * different versions. N-class, L2000 and A500 have two Diva chips, each + * with 3 UARTs (the third UART on the second chip is unused). Superdome + * and Keystone have one Diva chip with 3 UARTs. Some later machines have + * one Diva chip, but it has been expanded to 5 UARTs. + */ +static int __devinit pci_hp_diva_init(struct pci_dev *dev) +{ + int rc = 0; - /* HP's Diva chip puts the 4th/5th serial port further out, and - * some serial ports are supposed to be hidden on certain models. - */ - if (dev->vendor == PCI_VENDOR_ID_HP && - dev->device == PCI_DEVICE_ID_HP_DIVA) { - switch (dev->subsystem_device) { - case PCI_DEVICE_ID_HP_DIVA_MAESTRO: - if (idx == 3) - idx++; - break; - case PCI_DEVICE_ID_HP_DIVA_EVEREST: - if (idx > 0) - idx++; - if (idx > 2) - idx++; - break; - } - if (idx > 2) { - offset = 0x18; - } + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_TOSCA1: + case PCI_DEVICE_ID_HP_DIVA_HALFDOME: + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + rc = 3; + break; + case PCI_DEVICE_ID_HP_DIVA_TOSCA2: + rc = 2; + break; + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + rc = 4; + break; + case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + rc = 1; + break; } - port = pci_resource_start(dev, base_idx) + offset; + return rc; +} - if ((board->flags & SPCI_FL_BASE_TABLE) == 0) - port += idx * (board->uart_offset ? board->uart_offset : 8); +/* + * HP's Diva chip puts the 4th/5th serial port further out, and + * some serial ports are supposed to be hidden on certain models. + */ +static int +pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int offset = board->first_offset; + unsigned int bar = FL_GET_BASE(board->flags); - if (IS_PCI_REGION_IOPORT(dev, base_idx)) { - req->port = port; - if (HIGH_BITS_OFFSET) - req->port_high = port >> HIGH_BITS_OFFSET; - else - req->port_high = 0; - return 0; + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + if (idx == 3) + idx++; + break; + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + if (idx > 0) + idx++; + if (idx > 2) + idx++; + break; } - req->io_type = SERIAL_IO_MEM; - req->iomap_base = port; - req->iomem_base = ioremap(port, board->uart_offset); - if (req->iomem_base == NULL) - return -ENOMEM; - req->iomem_reg_shift = board->reg_shift; - req->port = 0; - return 0; + if (idx > 2) + offset = 0x18; + + offset += idx * board->uart_offset; + + return setup_port(dev, req, bar, offset, board->reg_shift); } -static _INLINE_ int -get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +/* + * Added for EKF Intel i960 serial boards + */ +static int __devinit pci_inteli960ni_init(struct pci_dev *dev) { - int base_idx; + unsigned long oldval; - if ((board->flags & SPCI_FL_IRQRESOURCE) == 0) - return dev->irq; + if (!(dev->subsystem_device & 0x1000)) + return -ENODEV; - base_idx = SPCI_FL_GET_IRQBASE(board->flags); - if (board->flags & SPCI_FL_IRQ_TABLE) - base_idx += idx; - - return PCI_IRQ_RESOURCE(dev, base_idx); + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, (void*) &oldval); + if (oldval == 0x00001000L) { /* RESET value */ + printk(KERN_DEBUG "Local i960 firmware missing"); + return -ENODEV; + } + return 0; } /* @@ -206,26 +246,29 @@ * seems to be mainly needed on card using the PLX which also use I/O * mapped memory. */ -static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable) +static int __devinit pci_plx9050_init(struct pci_dev *dev) { - u8 *p, irq_config = 0; + u8 *p, irq_config; - if (enable) { - irq_config = 0x41; - if (dev->vendor == PCI_VENDOR_ID_PANACOM) - irq_config = 0x43; - if ((dev->vendor == PCI_VENDOR_ID_PLX) && - (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { - /* - * As the megawolf cards have the int pins active - * high, and have 2 UART chips, both ints must be - * enabled on the 9050. Also, the UARTS are set in - * 16450 mode by default, so we have to enable the - * 16C950 'enhanced' mode so that we can use the - * deep FIFOs - */ - irq_config = 0x5b; - } + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) { + moan_device("no memory in bar 0", dev); + return 0; + } + + irq_config = 0x41; + if (dev->vendor == PCI_VENDOR_ID_PANACOM) + irq_config = 0x43; + if ((dev->vendor == PCI_VENDOR_ID_PLX) && + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { + /* + * As the megawolf cards have the int pins active + * high, and have 2 UART chips, both ints must be + * enabled on the 9050. Also, the UARTS are set in + * 16450 mode by default, so we have to enable the + * 16C950 'enhanced' mode so that we can use the + * deep FIFOs + */ + irq_config = 0x5b; } /* @@ -245,6 +288,27 @@ return 0; } +static void __devexit pci_plx9050_exit(struct pci_dev *dev) +{ + u8 *p; + + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) + return; + + /* + * disable interrupts + */ + p = ioremap(pci_resource_start(dev, 0), 0x80); + if (p != NULL) { + writel(0, p + 0x4c); + + /* + * Read the register back to ensure that it took effect. + */ + readl(p + 0x4c); + iounmap(p); + } +} /* * SIIG serial cards have an PCI interface chip which also controls @@ -270,23 +334,20 @@ #define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) #define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) -int pci_siig10x_fn(struct pci_dev *dev, int enable) +static int pci_siig10x_init(struct pci_dev *dev) { u16 data, *p; - if (!enable) - return 0; - switch (dev->device & 0xfff8) { - case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ - data = 0xffdf; - break; - case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ - data = 0xf7ff; - break; - default: /* 1S1P, 4S */ - data = 0xfffb; - break; + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ + data = 0xffdf; + break; + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ + data = 0xf7ff; + break; + default: /* 1S1P, 4S */ + data = 0xfffb; + break; } p = ioremap(pci_resource_start(dev, 0), 0x80); @@ -294,22 +355,18 @@ return -ENOMEM; writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); + readw((unsigned long)p + 0x28); iounmap(p); return 0; } -EXPORT_SYMBOL(pci_siig10x_fn); - #define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) #define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) -int pci_siig20x_fn(struct pci_dev *dev, int enable) +static int pci_siig20x_init(struct pci_dev *dev) { u8 data; - if (!enable) - return 0; - /* Change clock frequency for the first UART. */ pci_read_config_byte(dev, 0x6f, &data); pci_write_config_byte(dev, 0x6f, data & 0xef); @@ -323,28 +380,25 @@ return 0; } -EXPORT_SYMBOL(pci_siig20x_fn); - -/* Added for EKF Intel i960 serial boards */ -static int __devinit pci_inteli960ni_fn(struct pci_dev *dev, int enable) +int pci_siig10x_fn(struct pci_dev *dev, int enable) { - unsigned long oldval; - - if (!(pci_get_subdevice(dev) & 0x1000)) - return -ENODEV; + int ret = 0; + if (enable) + ret = pci_siig10x_init(dev); + return ret; +} - if (!enable) /* is there something to deinit? */ - return 0; - - /* is firmware started? */ - pci_read_config_dword(dev, 0x44, (void*) &oldval); - if (oldval == 0x00001000L) { /* RESET value */ - printk(KERN_DEBUG "Local i960 firmware missing"); - return -ENODEV; - } - return 0; +int pci_siig20x_fn(struct pci_dev *dev, int enable) +{ + int ret = 0; + if (enable) + ret = pci_siig20x_init(dev); + return ret; } +EXPORT_SYMBOL(pci_siig10x_fn); +EXPORT_SYMBOL(pci_siig20x_fn); + /* * Timedia has an explosion of boards, and to avoid the PCI table from * growing *huge*, we use this function to collapse some 70 entries @@ -385,78 +439,453 @@ { 0, 0 } }; -static int __devinit pci_timedia_fn(struct pci_dev *dev, int enable) +static int __devinit pci_timedia_init(struct pci_dev *dev) { - int i, j; unsigned short *ids; - - if (!enable) - return 0; + int i, j; for (i = 0; timedia_data[i].num; i++) { ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) - if (pci_get_subdevice(dev) == ids[j]) + if (dev->subsystem_device == ids[j]) return timedia_data[i].num; } return 0; } /* - * HP's Remote Management Console. The Diva chip came in several - * different versions. N-class, L2000 and A500 have two Diva chips, each - * with 3 UARTs (the third UART on the second chip is unused). Superdome - * and Keystone have one Diva chip with 3 UARTs. Some later machines have - * one Diva chip, but it has been expanded to 5 UARTs. + * Timedia/SUNIX uses a mixture of BARs and offsets + * Ugh, this is ugly as all hell --- TYT */ -static int __devinit pci_hp_diva(struct pci_dev *dev, int enable) +static int +pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) { - int rc = 0; - - if (!enable) - return 0; + unsigned int bar = 0, offset = board->first_offset; - switch (dev->subsystem_device) { - case PCI_DEVICE_ID_HP_DIVA_TOSCA1: - case PCI_DEVICE_ID_HP_DIVA_HALFDOME: - case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: - case PCI_DEVICE_ID_HP_DIVA_EVEREST: - rc = 3; + switch (idx) { + case 0: + bar = 0; break; - case PCI_DEVICE_ID_HP_DIVA_TOSCA2: - rc = 2; + case 1: + offset = board->uart_offset; + bar = 0; break; - case PCI_DEVICE_ID_HP_DIVA_MAESTRO: - rc = 4; - break; - case PCI_DEVICE_ID_HP_DIVA_POWERBAR: - rc = 1; + case 2: + bar = 1; break; + case 3: + offset = board->uart_offset; + bar = 1; + case 4: /* BAR 2 */ + case 5: /* BAR 3 */ + case 6: /* BAR 4 */ + case 7: /* BAR 5 */ + bar = idx - 2; } - return rc; + return setup_port(dev, req, bar, offset, board->reg_shift); } +/* + * Some Titan cards are also a little weird + */ +static int +titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset; -static int __devinit pci_xircom_fn(struct pci_dev *dev, int enable) + switch (idx) { + case 0: + bar = 1; + break; + case 1: + bar = 2; + break; + default: + bar = 4; + offset = (idx - 2) * board->uart_offset; + } + + return setup_port(dev, req, bar, offset, board->reg_shift); +} + +static int __devinit pci_xircom_init(struct pci_dev *dev) { __set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(HZ/10); return 0; } +static int +pci_default_setup(struct pci_dev *dev, struct pci_board *board, + struct serial_struct *req, int idx) +{ + unsigned int bar, offset = board->first_offset, maxnr; + + bar = FL_GET_BASE(board->flags); + if (board->flags & FL_BASE_BARS) + bar += idx; + else + offset += idx * board->uart_offset; + + maxnr = (pci_resource_len(dev, bar) - board->uart_offset) / + (8 << board->reg_shift); + + if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) + return 1; + + return setup_port(dev, req, bar, offset, board->reg_shift); +} + +/* + * Master list of serial port init/setup/exit quirks. + * This does not describe the general nature of the port. + * (ie, baud base, number and location of ports, etc) + * + * This list is ordered alphabetically by vendor then device. + * Specific entries must come before more generic entries. + */ +static struct pci_serial_quirk pci_serial_quirks[] = { + /* + * AFAVLAB cards. + * It is not clear whether this applies to all products. + */ + { + .vendor = PCI_VENDOR_ID_AFAVLAB, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = afavlab_setup, + }, + /* + * HP Diva + */ + { + .vendor = PCI_VENDOR_ID_HP, + .device = PCI_DEVICE_ID_HP_DIVA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_hp_diva_init, + .setup = pci_hp_diva_setup, + }, + /* + * Intel + */ + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_80960_RP, + .subvendor = 0xe4bf, + .subdevice = PCI_ANY_ID, + .init = pci_inteli960ni_init, + .setup = pci_default_setup, + }, + /* + * Panacom + */ + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_QUADMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_DUALMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + /* + * PLX + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_SUBVENDOR_ID_KEYSPAN, + .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_ROMULUS, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, + /* + * SIIG cards. + * It is not clear whether these could be collapsed. + */ + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_10x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig10x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_1S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_2S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_550, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_650, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_DEVICE_ID_SIIG_4S_20x_850, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig20x_init, + .setup = pci_default_setup, + }, + /* + * Titan cards + */ + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_400L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_800L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + /* + * Timedia cards + */ + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_DEVICE_ID_TIMEDIA_1889, + .subvendor = PCI_VENDOR_ID_TIMEDIA, + .subdevice = PCI_ANY_ID, + .init = pci_timedia_init, + .setup = pci_timedia_setup, + }, + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_timedia_setup, + }, + /* + * Xircom cards + */ + { + .vendor = PCI_VENDOR_ID_XIRCOM, + .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_xircom_init, + .setup = pci_default_setup, + }, + /* + * Default "match everything" terminator entry + */ + { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + } +}; + +static inline int quirk_id_matches(u32 quirk_id, u32 dev_id) +{ + return quirk_id == PCI_ANY_ID || quirk_id == dev_id; +} + +static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) +{ + struct pci_serial_quirk *quirk; + + for (quirk = pci_serial_quirks; ; quirk++) + if (quirk_id_matches(quirk->vendor, dev->vendor) && + quirk_id_matches(quirk->device, dev->device) && + quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) && + quirk_id_matches(quirk->subdevice, dev->subsystem_device)) + break; + return quirk; +} + +static _INLINE_ int +get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +{ + int base_idx; + + if ((board->flags & FL_IRQRESOURCE) == 0) + return dev->irq; + + base_idx = FL_GET_IRQBASE(board->flags); + + if (base_idx > DEVICE_COUNT_IRQ) + return 0; + + return dev->irq_resource[base_idx].start; +} + /* * This is the configuration table for all of the PCI serial boards * which we support. It is directly indexed by the pci_board_num_t enum * value, which is encoded in the pci_device_id PCI probe table's * driver_data member. + * + * The makeup of these names are: + * pbn_bn{_bt}_n_baud + * + * bn = PCI BAR number + * bt = Index using PCI BARs + * n = number of serial ports + * baud = baud rate + * + * Please note: in theory if n = 1, _bt infix should make no difference. + * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 */ enum pci_board_num_t { - pbn_b0_1_115200, pbn_default = 0, + pbn_b0_1_115200, pbn_b0_2_115200, pbn_b0_4_115200, + pbn_b0_5_115200, pbn_b0_1_921600, pbn_b0_2_921600, @@ -465,171 +894,465 @@ pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, pbn_b0_bt_8_115200, + pbn_b0_bt_1_460800, pbn_b0_bt_2_460800, + pbn_b0_bt_1_921600, + pbn_b0_bt_2_921600, + pbn_b0_bt_4_921600, + pbn_b0_bt_8_921600, + pbn_b1_1_115200, pbn_b1_2_115200, pbn_b1_4_115200, pbn_b1_8_115200, + pbn_b1_1_921600, pbn_b1_2_921600, pbn_b1_4_921600, pbn_b1_8_921600, + pbn_b1_bt_2_921600, + pbn_b1_2_1382400, pbn_b1_4_1382400, pbn_b1_8_1382400, pbn_b2_1_115200, pbn_b2_8_115200, + + pbn_b2_1_460800, pbn_b2_4_460800, pbn_b2_8_460800, pbn_b2_16_460800, + + pbn_b2_1_921600, pbn_b2_4_921600, pbn_b2_8_921600, pbn_b2_bt_1_115200, pbn_b2_bt_2_115200, pbn_b2_bt_4_115200, + pbn_b2_bt_2_921600, + pbn_b2_bt_4_921600, + + pbn_b3_4_115200, + pbn_b3_8_115200, + /* + * Board-specific versions. + */ pbn_panacom, pbn_panacom2, pbn_panacom4, pbn_plx_romulus, pbn_oxsemi, - pbn_timedia, pbn_intel_i960, pbn_sgi_ioc3, - pbn_hp_diva, pbn_nec_nile4, - - pbn_dci_pccom4, - pbn_dci_pccom8, - - pbn_xircom_combo, - - pbn_siig10x_0, - pbn_siig10x_1, - pbn_siig10x_2, - pbn_siig10x_4, - pbn_siig20x_0, - pbn_siig20x_2, - pbn_siig20x_4, - pbn_computone_4, pbn_computone_6, pbn_computone_8, }; static struct pci_board pci_boards[] __devinitdata = { + [pbn_default] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_1_115200] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_2_115200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_4_115200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_5_115200] = { + .flags = FL_BASE0, + .num_ports = 5, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b0_1_921600] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_2_921600] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_4_921600] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_2_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_8_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b0_bt_2_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_2_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_4_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_8_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_1_115200] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_2_115200] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_4_115200] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_8_115200] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b1_1_921600] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_2_921600] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_4_921600] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_8_921600] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_bt_2_921600] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_2_1382400] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_4_1382400] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_8_1382400] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 1382400, + .uart_offset = 8, + }, + + [pbn_b2_1_115200] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_8_115200] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_1_460800] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_4_460800] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_8_460800] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_16_460800] = { + .flags = FL_BASE2, + .num_ports = 16, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b2_1_921600] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_4_921600] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_8_921600] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b2_bt_1_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_2_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_4_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_bt_2_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_bt_4_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b3_4_115200] = { + .flags = FL_BASE3, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b3_8_115200] = { + .flags = FL_BASE3, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + /* - * PCI Flags, Number of Ports, Base (Maximum) Baud Rate, - * Offset to get to next UART's registers, - * Register shift to use for memory-mapped I/O, - * Initialization function, first UART offset - */ - - /* Generic serial board, pbn_b0_1_115200, pbn_default */ - { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200, - pbn_default */ - - { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */ - { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */ - - { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */ - { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */ - { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */ - - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */ - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */ - - { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */ - { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */ - { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */ - { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */ - - { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */ - { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */ - { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */ - - { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */ - { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */ - { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */ - - { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */ - { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */ - { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */ - { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */ - { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */ - { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */ - { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */ - - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */ - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */ - - { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */ - 0x400, 7, pci_plx9050_fn }, - { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */ - 0x20, 2, pci_plx9050_fn, 0x03 }, + * Entries following this are board-specific. + */ + + /* + * Panacom - IOMEM + */ + [pbn_panacom] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom2] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom4] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + + /* I think this entry is broken - the first_offset looks wrong --rmk */ + [pbn_plx_romulus] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x03, + }, /* * This board uses the size of PCI Base region 0 to * signal now many ports are available */ - { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */ - { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */ - 0, 0, pci_timedia_fn }, - /* EKF addition for i960 Boards form EKF with serial port */ - { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */ - 8<<2, 2, pci_inteli960ni_fn, 0x10000}, - { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */ - 1, 458333, 0, 0, 0, 0x20178 }, - { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */ + [pbn_oxsemi] = { + .flags = FL_BASE0|FL_REGION_SZ_CAP, + .num_ports = 32, + .base_baud = 115200, + .uart_offset = 8, + }, /* - * NEC Vrc-5074 (Nile 4) builtin UART. + * EKF addition for i960 Boards form EKF with serial port. + * Max 256 ports. */ - { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */ - 64, 3, NULL, 0x300 }, - - { SPCI_FL_BASE3, 4, 115200, 8 }, /* pbn_dci_pccom4 */ - { SPCI_FL_BASE3, 8, 115200, 8 }, /* pbn_dci_pccom8 */ + [pbn_intel_i960] = { + .flags = FL_BASE0, + .num_ports = 32, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x10000, + }, + [pbn_sgi_ioc3] = { + .flags = FL_BASE0|FL_IRQRESOURCE, + .num_ports = 1, + .base_baud = 458333, + .uart_offset = 8, + .reg_shift = 0, + .first_offset = 0x20178, + }, - { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */ - 0, 0, pci_xircom_fn }, + /* + * NEC Vrc-5074 (Nile 4) builtin UART. + */ + [pbn_nec_nile4] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 520833, + .uart_offset = 8 << 3, + .reg_shift = 3, + .first_offset = 0x300, + }, - { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */ - 0, 0, pci_siig10x_fn }, - { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */ - 0, 0, pci_siig20x_fn }, - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */ - 0, 0, pci_siig20x_fn }, - - { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */ - 0x40, 2, NULL, 0x200 }, - { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */ - 0x40, 2, NULL, 0x200 }, + /* + * Computone - uses IOMEM. + */ + [pbn_computone_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_6] = { + .flags = FL_BASE0, + .num_ports = 6, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, }; /* @@ -640,8 +1363,7 @@ static int __devinit serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) { - int num_iomem = 0, num_port = 0, first_port = -1; - int i; + int num_iomem, num_port, first_port = -1, i; /* * If it is not a communications device or the programming @@ -655,36 +1377,63 @@ (dev->class & 0xff) > 6) return -ENODEV; - for (i = 0; i < 6; i++) { - if (IS_PCI_REGION_IOPORT(dev, i)) { + num_iomem = num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO) { num_port++; if (first_port == -1) first_port = i; } - if (IS_PCI_REGION_IOMEM(dev, i)) + if (pci_resource_flags(dev, i) & IORESOURCE_MEM) num_iomem++; } /* - * If there is 1 or 0 iomem regions, and exactly one port, use - * it. + * If there is 1 or 0 iomem regions, and exactly one port, + * use it. We guess the number of ports based on the IO + * region size. */ if (num_iomem <= 1 && num_port == 1) { board->flags = first_port; + board->num_ports = pci_resource_len(dev, first_port) / 8; return 0; } + + /* + * Now guess if we've got a board which indexes by BARs. + * Each IO BAR should be 8 bytes, and they should follow + * consecutively. + */ + first_port = -1; + num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO && + pci_resource_len(dev, i) == 8 && + (first_port == -1 || (first_port + num_port) == i)) { + num_port++; + if (first_port == -1) + first_port = i; + } + } + + if (num_port > 1) { + board->flags = first_port | FL_BASE_BARS; + board->num_ports = num_port; + return 0; + } + return -ENODEV; } static inline int -serial_pci_matches(struct pci_board *board, int index) +serial_pci_matches(struct pci_board *board, struct pci_board *guessed) { return - board->base_baud == pci_boards[index].base_baud && - board->num_ports == pci_boards[index].num_ports && - board->uart_offset == pci_boards[index].uart_offset && - board->reg_shift == pci_boards[index].reg_shift && - board->first_uart_offset == pci_boards[index].first_uart_offset; + board->num_ports == guessed->num_ports && + board->base_baud == guessed->base_baud && + board->uart_offset == guessed->uart_offset && + board->reg_shift == guessed->reg_shift && + board->first_offset == guessed->first_offset; } /* @@ -692,10 +1441,11 @@ * to the arrangement of serial ports on a PCI card. */ static int __devinit -pci_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) { struct serial_private *priv; struct pci_board *board, tmp; + struct pci_serial_quirk *quirk; struct serial_struct serial_req; int base_baud, rc, nr_ports, i; @@ -732,92 +1482,109 @@ * detect this boards settings with our heuristic, * then we no longer need this entry. */ + memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board)); rc = serial_pci_guess_board(dev, &tmp); - if (rc == 0 && serial_pci_matches(board, pbn_default)) { - printk(KERN_INFO - "Redundant entry in serial pci_table. Please send the output\n" - "of lspci -vv, this message (0x%04x,0x%04x,0x%04x,0x%04x),\n" - "the manufacturer and name of serial board or modem board to\n" - "rmk@arm.linux.org.uk.\n", - dev->vendor, dev->device, - pci_get_subvendor(dev), pci_get_subdevice(dev)); - } + if (rc == 0 && serial_pci_matches(board, &tmp)) + moan_device("Redundant entry in serial pci_table.", + dev); } nr_ports = board->num_ports; /* - * Run the initialization function, if any. The initialization - * function returns: + * Find an init and setup quirks. + */ + quirk = find_quirk(dev); + + /* + * Run the new-style initialization function. + * The initialization function returns: * <0 - error * 0 - use board->num_ports * >0 - number of ports */ - if (board->init_fn) { - rc = board->init_fn(dev, 1); + if (quirk->init) { + rc = quirk->init(dev); if (rc < 0) goto disable; - if (rc) nr_ports = rc; } priv = kmalloc(sizeof(struct serial_private) + - sizeof(unsigned int) * nr_ports, - GFP_KERNEL); + sizeof(unsigned int) * nr_ports, + GFP_KERNEL); if (!priv) { rc = -ENOMEM; goto deinit; } + memset(priv, 0, sizeof(struct serial_private) + + sizeof(unsigned int) * nr_ports); + + priv->quirk = quirk; + pci_set_drvdata(dev, priv); + base_baud = board->base_baud; - if (!base_baud) + if (!base_baud) { + moan_device("Board entry does not specify baud rate.", dev); base_baud = BASE_BAUD; - memset(&serial_req, 0, sizeof(serial_req)); + } for (i = 0; i < nr_ports; i++) { + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | + UPF_RESOURCES | UPF_SHARE_IRQ; + serial_req.baud_base = base_baud; serial_req.irq = get_pci_irq(dev, board, i); - if (get_pci_port(dev, board, &serial_req, i)) + if (quirk->setup(dev, board, &serial_req, i)) break; #ifdef SERIAL_DEBUG_PCI printk("Setup PCI port: port %x, irq %d, type %d\n", serial_req.port, serial_req.irq, serial_req.io_type); #endif - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE; - serial_req.baud_base = base_baud; priv->line[i] = register_serial(&serial_req); if (priv->line[i] < 0) break; } - priv->board = board; priv->nr = i; - pci_set_drvdata(dev, priv); - return 0; deinit: - if (board->init_fn) - board->init_fn(dev, 0); + if (quirk->exit) + quirk->exit(dev); disable: pci_disable_device(dev); return rc; } -static void __devexit pci_remove_one(struct pci_dev *dev) +static void __devexit pciserial_remove_one(struct pci_dev *dev) { struct serial_private *priv = pci_get_drvdata(dev); - int i; pci_set_drvdata(dev, NULL); if (priv) { + struct pci_serial_quirk *quirk; + int i; + for (i = 0; i < priv->nr; i++) unregister_serial(priv->line[i]); - if (priv->board->init_fn) - priv->board->init_fn(dev, 0); + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (priv->remapped_bar[i]) + iounmap(priv->remapped_bar[i]); + priv->remapped_bar[i] = NULL; + } + + /* + * Find the exit quirks. + */ + quirk = find_quirk(dev); + if (quirk->exit) + quirk->exit(dev); pci_disable_device(dev); @@ -825,6 +1592,53 @@ } } +static int pciserial_save_state_one(struct pci_dev *dev, u32 state) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + for (i = 0; i < priv->nr; i++) + serial8250_suspend_port(priv->line[i], SUSPEND_SAVE_STATE); + } + return 0; +} + +static int pciserial_suspend_one(struct pci_dev *dev, u32 state) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + for (i = 0; i < priv->nr; i++) + serial8250_suspend_port(priv->line[i], SUSPEND_POWER_DOWN); + } + return 0; +} + +static int pciserial_resume_one(struct pci_dev *dev) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) { + int i; + + /* + * Ensure that the board is correctly configured. + */ + if (priv->quirk->init) + priv->quirk->init(dev); + + for (i = 0; i < priv->nr; i++) { + serial8250_resume_port(priv->line[i], RESUME_POWER_ON); + serial8250_resume_port(priv->line[i], RESUME_RESTORE_STATE); + } + } + return 0; +} + static struct pci_device_id serial_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, PCI_SUBVENDOR_ID_CONNECT_TECH, @@ -908,7 +1722,9 @@ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_bt_2_921600 }, - /* VScom SPCOM800, from sl@s.pl */ + /* + * VScom SPCOM800, from sl@s.pl + */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_921600 }, @@ -949,8 +1765,10 @@ PCI_SUBVENDOR_ID_CHASE_PCIRAS, PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, pbn_b2_8_460800 }, - /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ - /* (Exoray@isys.ca) */ + /* + * Megawolf Romulus PCI Serial Card, from Mike Hudson + * (Exoray@isys.ca) + */ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, 0x10b5, 0x106a, 0, 0, pbn_plx_romulus }, @@ -976,16 +1794,24 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_115200 }, - /* Digitan DS560-558, from jimd@esoft.com */ + /* + * Digitan DS560-558, from jimd@esoft.com + */ { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b1_1_115200 }, - /* 3Com US Robotics 56k Voice Internal PCI model 5610 */ + /* + * 3Com US Robotics 56k Voice Internal PCI model 5610 + */ { PCI_VENDOR_ID_USR, 0x1008, - PCI_ANY_ID, PCI_ANY_ID, }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, - /* Titan Electronic cards */ + /* + * Titan Electronic cards + * The 400L and 800L have a custom setup quirk. + */ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_1_921600 }, @@ -999,120 +1825,76 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_4_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1, 1, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 }, - /* The 400L and 800L have a custom hack in get_pci_port */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 4, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, - PCI_ANY_ID, PCI_ANY_ID, - SPCI_FL_BASE_TABLE, 8, 921600 }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_1 }, + pbn_b2_1_460800 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_2 }, + pbn_b2_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig10x_4 }, + pbn_b2_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_0 }, + pbn_b0_1_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_2 }, + pbn_b0_bt_2_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_siig20x_4 }, + pbn_b0_bt_4_921600 }, - /* Computone devices submitted by Doug McNash dmcnash@computone.com */ + /* + * Computone devices submitted by Doug McNash dmcnash@computone.com + */ { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, 0, 0, pbn_computone_4 }, @@ -1124,18 +1906,22 @@ 0, 0, pbn_computone_6 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi }, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi }, { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, - PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia }, + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_921600 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - /* AFAVLAB serial card, from Harald Welte */ + /* + * AFAVLAB serial card, from Harald Welte + */ { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_8_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_115200 }, @@ -1158,26 +1944,40 @@ PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_460800 }, - /* RAStel 2 port modem, gerg@moreton.com.au */ + /* + * RAStel 2 port modem, gerg@moreton.com.au + */ { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_bt_2_115200 }, - /* EKF addition for i960 Boards form EKF with serial port */ - { PCI_VENDOR_ID_INTEL, 0x1960, + /* + * EKF addition for i960 Boards form EKF with serial port + */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP, 0xE4BF, PCI_ANY_ID, 0, 0, pbn_intel_i960 }, - /* Xircom Cardbus/Ethernet combos */ + /* + * Xircom Cardbus/Ethernet combos + */ { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_xircom_combo }, + pbn_b0_1_115200 }, + /* + * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry) + */ + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, /* * Untested PCI modems, sent in from various folks... */ - /* Elsa Model 56K PCI Modem, from Andreas Rath */ + /* + * Elsa Model 56K PCI Modem, from Andreas Rath + */ { PCI_VENDOR_ID_ROCKWELL, 0x1004, 0x1048, 0x1500, 0, 0, pbn_b1_1_115200 }, @@ -1186,10 +1986,12 @@ 0xFF00, 0, 0, 0, pbn_sgi_ioc3 }, - /* HP Diva card */ + /* + * HP Diva card + */ { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_hp_diva }, + pbn_b0_5_115200 }, { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_1_115200 }, @@ -1203,15 +2005,14 @@ { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_dci_pccom4 }, + pbn_b3_4_115200 }, { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_dci_pccom8 }, + pbn_b3_8_115200 }, /* - * These entries match devices with class - * COMMUNICATION_SERIAL, COMMUNICATION_MODEM - * or COMMUNICATION_MULTISERIAL + * These entries match devices with class COMMUNICATION_SERIAL, + * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -1230,9 +2031,15 @@ static struct pci_driver serial_pci_driver = { .name = "serial", - .probe = pci_init_one, - .remove = __devexit_p(pci_remove_one), + .probe = pciserial_init_one, + .remove = __devexit_p(pciserial_remove_one), + .save_state = pciserial_save_state_one, + .suspend = pciserial_suspend_one, + .resume = pciserial_resume_one, .id_table = serial_pci_tbl, + .driver = { + .devclass = &tty_devclass, + }, }; static int __init serial8250_pci_init(void) diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Sat Mar 15 18:40:44 2003 +++ b/drivers/serial/Kconfig Sat Mar 15 18:40:44 2003 @@ -412,9 +412,10 @@ help This driver supports the SCC serial ports of the Motorola 68360 CPU. -config 68360_SERIAL +config SERIAL_68360 bool - depends on SERIAL_68360_SMC || SERIAL_68630_SCC + depends on SERIAL_68360_SMC || SERIAL_68360_SCC + default y endmenu diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- a/drivers/serial/amba.c Sat Mar 15 18:40:40 2003 +++ b/drivers/serial/amba.c Sat Mar 15 18:40:40 2003 @@ -705,10 +705,11 @@ .index = -1, }; -void __init ambauart_console_init(void) +static void __init ambauart_console_init(void) { register_console(&amba_console); } +console_initcall(ambauart_console_init); #define AMBA_CONSOLE &amba_console #else diff -Nru a/drivers/serial/anakin.c b/drivers/serial/anakin.c --- a/drivers/serial/anakin.c Sat Mar 15 18:40:40 2003 +++ b/drivers/serial/anakin.c Sat Mar 15 18:40:40 2003 @@ -502,11 +502,12 @@ .index = -1, }; -void __init +static void __init anakin_console_init(void) { register_console(&anakin_console); } +console_initcall(anakin_console_init); #define ANAKIN_CONSOLE &anakin_console #else diff -Nru a/drivers/serial/clps711x.c b/drivers/serial/clps711x.c --- a/drivers/serial/clps711x.c Sat Mar 15 18:40:40 2003 +++ b/drivers/serial/clps711x.c Sat Mar 15 18:40:40 2003 @@ -567,10 +567,11 @@ .index = -1, }; -void __init clps711xuart_console_init(void) +static void __init clps711xuart_console_init(void) { register_console(&clps711x_console); } +console_initcall(clps711xuart_console_init); #define CLPS711X_CONSOLE &clps711x_console #else diff -Nru a/drivers/serial/core.c b/drivers/serial/core.c --- a/drivers/serial/core.c Sat Mar 15 18:40:40 2003 +++ b/drivers/serial/core.c Sat Mar 15 18:40:40 2003 @@ -21,9 +21,6 @@ * 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 - * - * $Id: core.c,v 1.100 2002/07/28 10:03:28 rmk Exp $ - * */ #include #include @@ -31,9 +28,9 @@ #include #include #include -#include #include #include +#include #include /* for serial_state and serial_icounter_struct */ #include @@ -46,11 +43,6 @@ #define DPRINTK(x...) do { } while (0) #endif -#ifndef CONFIG_PM -#define pm_access(pm) do { } while (0) -#define pm_unregister(pm) do { } while (0) -#endif - /* * This is used to lock changes in serial line configuration. */ @@ -58,8 +50,17 @@ #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) -static void uart_change_speed(struct uart_info *info, struct termios *old_termios); +#define uart_users(state) ((state)->count + ((state)->info ? (state)->info->blocked_open : 0)) + +#ifdef CONFIG_SERIAL_CORE_CONSOLE +#define uart_console(port) ((port)->cons && (port)->cons->index == (port)->line) +#else +#define uart_console(port) (0) +#endif + +static void uart_change_speed(struct uart_state *state, struct termios *old_termios); static void uart_wait_until_sent(struct tty_struct *tty, int timeout); +static void uart_change_pm(struct uart_state *state, int pm_state); /* * This routine is used by the interrupt handler to schedule processing in @@ -73,8 +74,8 @@ static void uart_stop(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; spin_lock_irqsave(&port->lock, flags); @@ -84,32 +85,31 @@ static void __uart_start(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; - if (!uart_circ_empty(&info->xmit) && info->xmit.buf && + if (!uart_circ_empty(&state->info->xmit) && state->info->xmit.buf && !tty->stopped && !tty->hw_stopped) port->ops->start_tx(port, 1); } static void uart_start(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; - pm_access(info->state->pm); - - spin_lock_irqsave(&info->port->lock, flags); + spin_lock_irqsave(&port->lock, flags); __uart_start(tty); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } static void uart_tasklet_action(unsigned long data) { - struct uart_info *info = (struct uart_info *)data; + struct uart_state *state = (struct uart_state *)data; struct tty_struct *tty; - tty = info->tty; + tty = state->info->tty; if (tty) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -137,11 +137,12 @@ /* * Startup the port. This will be called once per open. All calls - * will be serialised by the global port semaphore. + * will be serialised by the per-port semaphore. */ -static int uart_startup(struct uart_info *info, int init_hw) +static int uart_startup(struct uart_state *state, int init_hw) { - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; unsigned long page; int retval = 0; @@ -182,7 +183,7 @@ /* * Initialise the hardware port settings. */ - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); /* * Setup the RTS and DTR signals once the @@ -194,8 +195,7 @@ info->flags |= UIF_INITIALIZED; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); + clear_bit(TTY_IO_ERROR, &info->tty->flags); } if (retval && capable(CAP_SYS_ADMIN)) @@ -207,11 +207,12 @@ /* * This routine will shutdown a serial port; interrupts are disabled, and * DTR is dropped if the hangup on close termio flag is on. Calls to - * uart_shutdown are serialised by port_sem. + * uart_shutdown are serialised by the per-port semaphore. */ -static void uart_shutdown(struct uart_info *info) +static void uart_shutdown(struct uart_state *state) { - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; if (!(info->flags & UIF_INITIALIZED)) return; @@ -220,7 +221,7 @@ * Turn off DTR and RTS early. */ if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - uart_clear_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + uart_clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); /* * clear delta_msr_wait queue to avoid mem leaks: we may free @@ -412,10 +413,10 @@ EXPORT_SYMBOL(uart_get_divisor); static void -uart_change_speed(struct uart_info *info, struct termios *old_termios) +uart_change_speed(struct uart_state *state, struct termios *old_termios) { - struct tty_struct *tty = info->tty; - struct uart_port *port = info->port; + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; struct termios *termios; /* @@ -431,14 +432,14 @@ * Set flags based on termios cflag */ if (termios->c_cflag & CRTSCTS) - info->flags |= UIF_CTS_FLOW; + state->info->flags |= UIF_CTS_FLOW; else - info->flags &= ~UIF_CTS_FLOW; + state->info->flags &= ~UIF_CTS_FLOW; if (termios->c_cflag & CLOCAL) - info->flags &= ~UIF_CHECK_CD; + state->info->flags &= ~UIF_CHECK_CD; else - info->flags |= UIF_CHECK_CD; + state->info->flags |= UIF_CHECK_CD; port->ops->set_termios(port, termios, old_termios); } @@ -526,10 +527,10 @@ static void uart_put_char(struct tty_struct *tty, unsigned char ch) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; if (tty) - __uart_put_char(info->port, &info->xmit, ch); + __uart_put_char(state->port, &state->info->xmit, ch); } static void uart_flush_chars(struct tty_struct *tty) @@ -541,16 +542,16 @@ uart_write(struct tty_struct *tty, int from_user, const unsigned char * buf, int count) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; int ret; - if (!tty || !info->xmit.buf) + if (!tty || !state->info->xmit.buf) return 0; if (from_user) - ret = __uart_user_write(info->port, &info->xmit, buf, count); + ret = __uart_user_write(state->port, &state->info->xmit, buf, count); else - ret = __uart_kern_write(info->port, &info->xmit, buf, count); + ret = __uart_kern_write(state->port, &state->info->xmit, buf, count); uart_start(tty); return ret; @@ -558,29 +559,30 @@ static int uart_write_room(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; - return uart_circ_chars_free(&info->xmit); + return uart_circ_chars_free(&state->info->xmit); } static int uart_chars_in_buffer(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; - return uart_circ_chars_pending(&info->xmit); + return uart_circ_chars_pending(&state->info->xmit); } static void uart_flush_buffer(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; DPRINTK("uart_flush_buffer(%d) called\n", minor(tty->device) - tty->driver.minor_start); - spin_lock_irqsave(&info->port->lock, flags); - uart_circ_clear(&info->xmit); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_lock_irqsave(&port->lock, flags); + uart_circ_clear(&state->info->xmit); + spin_unlock_irqrestore(&port->lock, flags); wake_up_interruptible(&tty->write_wait); if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) @@ -593,8 +595,8 @@ */ static void uart_send_xchar(struct tty_struct *tty, char ch) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long flags; if (port->ops->send_xchar) @@ -611,19 +613,19 @@ static void uart_throttle(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; if (I_IXOFF(tty)) uart_send_xchar(tty, STOP_CHAR(tty)); if (tty->termios->c_cflag & CRTSCTS) - uart_clear_mctrl(info->port, TIOCM_RTS); + uart_clear_mctrl(state->port, TIOCM_RTS); } static void uart_unthrottle(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; if (I_IXOFF(tty)) { if (port->x_char) @@ -636,10 +638,9 @@ uart_set_mctrl(port, TIOCM_RTS); } -static int uart_get_info(struct uart_info *info, struct serial_struct *retinfo) +static int uart_get_info(struct uart_state *state, struct serial_struct *retinfo) { - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_port *port = state->port; struct serial_struct tmp; memset(&tmp, 0, sizeof(tmp)); @@ -649,7 +650,7 @@ if (HIGH_BITS_OFFSET) tmp.port_high = (long) port->iobase >> HIGH_BITS_OFFSET; tmp.irq = port->irq; - tmp.flags = port->flags | info->flags; + tmp.flags = port->flags; tmp.xmit_fifo_size = port->fifosize; tmp.baud_base = port->uartclk / 16; tmp.close_delay = state->close_delay; @@ -666,11 +667,10 @@ } static int -uart_set_info(struct uart_info *info, struct serial_struct *newinfo) +uart_set_info(struct uart_state *state, struct serial_struct *newinfo) { struct serial_struct new_serial; - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_port *port = state->port; unsigned long new_port; unsigned int change_irq, change_port, old_flags; unsigned int old_custom_divisor; @@ -692,7 +692,7 @@ * module insertion/removal doesn't change anything * under us. */ - down(&port_sem); + down(&state->sem); change_irq = new_serial.irq != port->irq; @@ -745,14 +745,14 @@ /* * Make sure that we are the sole user of this port. */ - if (state->count > 1 || info->blocked_open != 0) + if (uart_users(state) > 1) goto exit; /* * We need to shutdown the serial port at the old * port/type/irq combination. */ - uart_shutdown(info); + uart_shutdown(state); } if (change_port) { @@ -813,18 +813,21 @@ port->irq = new_serial.irq; port->uartclk = new_serial.baud_base * 16; - port->flags = new_serial.flags & UPF_CHANGE_MASK; + port->flags = (port->flags & ~UPF_CHANGE_MASK) | + (new_serial.flags & UPF_CHANGE_MASK); port->custom_divisor = new_serial.custom_divisor; state->close_delay = new_serial.close_delay * HZ / 100; state->closing_wait = new_serial.closing_wait * HZ / 100; port->fifosize = new_serial.xmit_fifo_size; - info->tty->low_latency = (port->flags & UPF_LOW_LATENCY) ? 1 : 0; + if (state->info->tty) + state->info->tty->low_latency = + (port->flags & UPF_LOW_LATENCY) ? 1 : 0; check_and_exit: retval = 0; if (port->type == PORT_UNKNOWN) goto exit; - if (info->flags & UIF_INITIALIZED) { + if (state->info->flags & UIF_INITIALIZED) { if (((old_flags ^ port->flags) & UPF_SPD_MASK) || old_custom_divisor != port->custom_divisor) { /* If they're setting up a custom divisor or speed, @@ -832,25 +835,26 @@ * need to rate-limit; it's CAP_SYS_ADMIN only. */ if (port->flags & UPF_SPD_MASK) { printk(KERN_NOTICE "%s sets custom speed on %s%d. This is deprecated.\n", - current->comm, info->tty->driver.name, - info->port->line); + current->comm, state->info->tty->driver.name, + state->port->line); } - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); } } else - retval = uart_startup(info, 1); + retval = uart_startup(state, 1); exit: - up(&port_sem); + up(&state->sem); return retval; } /* - * uart_get_lsr_info - get line status register info + * uart_get_lsr_info - get line status register info. + * Note: uart_ioctl protects us against hangups. */ -static int uart_get_lsr_info(struct uart_info *info, unsigned int *value) +static int uart_get_lsr_info(struct uart_state *state, unsigned int *value) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; unsigned int result; result = port->ops->tx_empty(port); @@ -861,9 +865,9 @@ * avoid a race condition (depending on when the transmit * interrupt happens). */ - if (info->port->x_char || - ((uart_circ_chars_pending(&info->xmit) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) + if (port->x_char || + ((uart_circ_chars_pending(&state->info->xmit) > 0) && + !state->info->tty->stopped && !state->info->tty->hw_stopped)) result &= ~TIOCSER_TEMT; return put_user(result, value); @@ -888,6 +892,8 @@ if (get_user(arg, value)) return -EFAULT; + arg &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2; + set = clear = 0; switch (cmd) { case TIOCMBIS: @@ -911,8 +917,8 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; BUG_ON(!kernel_locked()); @@ -920,25 +926,25 @@ port->ops->break_ctl(port, break_state); } -static int uart_do_autoconfig(struct uart_info *info) +static int uart_do_autoconfig(struct uart_state *state) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; int flags, ret; if (!capable(CAP_SYS_ADMIN)) return -EPERM; /* - * Take the 'count' lock. This prevents count - * from incrementing, and hence any extra opens - * of the port while we're auto-configging. + * Take the per-port semaphore. This prevents count from + * changing, and hence any extra opens of the port while + * we're auto-configuring. */ - if (down_interruptible(&port_sem)) + if (down_interruptible(&state->sem)) return -ERESTARTSYS; ret = -EBUSY; - if (info->state->count == 1 && info->blocked_open == 0) { - uart_shutdown(info); + if (uart_users(state) == 1) { + uart_shutdown(state); /* * If we already have a port type configured, @@ -957,16 +963,22 @@ */ port->ops->config_port(port, flags); - ret = uart_startup(info, 1); + ret = uart_startup(state, 1); } - up(&port_sem); + up(&state->sem); return ret; } +/* + * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change + * - mask passed in arg for lines of interest + * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) + * Caller should use TIOCGICOUNT to see which one it was + */ static int -uart_wait_modem_status(struct uart_info *info, unsigned long arg) +uart_wait_modem_status(struct uart_state *state, unsigned long arg) { - struct uart_port *port = info->port; + struct uart_port *port = state->port; DECLARE_WAITQUEUE(wait, current); struct uart_icount cprev, cnow; int ret; @@ -983,7 +995,7 @@ port->ops->enable_ms(port); spin_unlock_irq(&port->lock); - add_wait_queue(&info->delta_msr_wait, &wait); + add_wait_queue(&state->info->delta_msr_wait, &wait); for (;;) { spin_lock_irq(&port->lock); memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); @@ -1011,117 +1023,144 @@ } current->state = TASK_RUNNING; - remove_wait_queue(&info->delta_msr_wait, &wait); + remove_wait_queue(&state->info->delta_msr_wait, &wait); return ret; } /* - * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) + * Return: write counters to the user passed counter struct + * NB: both 1->0 and 0->1 transitions are counted except for + * RI where only 0->1 is counted. */ static int -uart_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, - unsigned long arg) +uart_get_count(struct uart_state *state, struct serial_icounter_struct *icnt) { - struct uart_info *info = tty->driver_data; struct serial_icounter_struct icount; struct uart_icount cnow; + struct uart_port *port = state->port; + + spin_lock_irq(&port->lock); + memcpy(&cnow, &port->icount, sizeof(struct uart_icount)); + spin_unlock_irq(&port->lock); + + icount.cts = cnow.cts; + icount.dsr = cnow.dsr; + icount.rng = cnow.rng; + icount.dcd = cnow.dcd; + icount.rx = cnow.rx; + icount.tx = cnow.tx; + icount.frame = cnow.frame; + icount.overrun = cnow.overrun; + icount.parity = cnow.parity; + icount.brk = cnow.brk; + icount.buf_overrun = cnow.buf_overrun; + + return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; +} + +/* + * Called via sys_ioctl under the BKL. We can use spin_lock_irq() here. + */ +static int +uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, + unsigned long arg) +{ + struct uart_state *state = tty->driver_data; int ret = -ENOIOCTLCMD; BUG_ON(!kernel_locked()); - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; + /* + * These ioctls don't rely on the hardware to be present. + */ + switch (cmd) { + case TIOCGSERIAL: + ret = uart_get_info(state, (struct serial_struct *)arg); + break; + + case TIOCSSERIAL: + ret = uart_set_info(state, (struct serial_struct *)arg); + break; + + case TIOCSERCONFIG: + ret = uart_do_autoconfig(state); + break; + + case TIOCSERGWILD: /* obsolete */ + case TIOCSERSWILD: /* obsolete */ + ret = 0; + break; } - switch (cmd) { - case TIOCMGET: - ret = uart_get_modem_info(info->port, - (unsigned int *)arg); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - ret = uart_set_modem_info(info->port, cmd, - (unsigned int *)arg); - break; + if (tty->flags & (1 << TTY_IO_ERROR)) { + ret = -EIO; + goto out; + } - case TIOCGSERIAL: - ret = uart_get_info(info, (struct serial_struct *)arg); - break; + /* + * The following should only be used when hardware is present. + */ + switch (cmd) { + case TIOCMIWAIT: + ret = uart_wait_modem_status(state, arg); + break; - case TIOCSSERIAL: - ret = uart_set_info(info, (struct serial_struct *)arg); - break; + case TIOCGICOUNT: + ret = uart_get_count(state, (struct serial_icounter_struct *)arg); + break; + } - case TIOCSERCONFIG: - ret = uart_do_autoconfig(info); - break; + if (ret != -ENOIOCTLCMD) + goto out; - case TIOCSERGETLSR: /* Get line status register */ - ret = uart_get_lsr_info(info, (unsigned int *)arg); - break; + down(&state->sem); - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - ret = uart_wait_modem_status(info, arg); - break; + if (tty_hung_up_p(filp)) { + ret = -EIO; + goto out_up; + } - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - spin_lock_irq(&info->port->lock); - memcpy(&cnow, &info->port->icount, - sizeof(struct uart_icount)); - spin_unlock_irq(&info->port->lock); - - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; + /* + * All these rely on hardware being present and need to be + * protected against the tty being hung up. + */ + switch (cmd) { + case TIOCMGET: + ret = uart_get_modem_info(state->port, (unsigned int *)arg); + break; - ret = copy_to_user((void *)arg, &icount, sizeof(icount)) - ? -EFAULT : 0; - break; + case TIOCMBIS: + case TIOCMBIC: + case TIOCMSET: + ret = uart_set_modem_info(state->port, cmd, + (unsigned int *)arg); + break; - case TIOCSERGWILD: /* obsolete */ - case TIOCSERSWILD: /* obsolete */ - ret = 0; - break; + case TIOCSERGETLSR: /* Get line status register */ + ret = uart_get_lsr_info(state, (unsigned int *)arg); + break; - default: { - struct uart_port *port = info->port; - if (port->ops->ioctl) - ret = port->ops->ioctl(port, cmd, arg); - break; - } + default: { + struct uart_port *port = state->port; + if (port->ops->ioctl) + ret = port->ops->ioctl(port, cmd, arg); + break; + } } + out_up: + up(&state->sem); + out: return ret; } static void uart_set_termios(struct tty_struct *tty, struct termios *old_termios) { - struct uart_info *info = tty->driver_data; + struct uart_state *state = tty->driver_data; unsigned long flags; unsigned int cflag = tty->termios->c_cflag; @@ -1137,11 +1176,11 @@ RELEVANT_IFLAG(tty->termios->c_iflag ^ old_termios->c_iflag) == 0) return; - uart_change_speed(info, old_termios); + uart_change_speed(state, old_termios); /* Handle transition to B0 status */ if ((old_termios->c_cflag & CBAUD) && !(cflag & CBAUD)) - uart_clear_mctrl(info->port, TIOCM_RTS | TIOCM_DTR); + uart_clear_mctrl(state->port, TIOCM_RTS | TIOCM_DTR); /* Handle transition away from B0 status */ if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) { @@ -1149,15 +1188,15 @@ if (!(cflag & CRTSCTS) || !test_bit(TTY_THROTTLED, &tty->flags)) mask |= TIOCM_RTS; - uart_set_mctrl(info->port, mask); + uart_set_mctrl(state->port, mask); } /* Handle turning off CRTSCTS */ if ((old_termios->c_cflag & CRTSCTS) && !(cflag & CRTSCTS)) { - spin_lock_irqsave(&info->port->lock, flags); + spin_lock_irqsave(&state->port->lock, flags); tty->hw_stopped = 0; __uart_start(tty); - spin_unlock_irqrestore(&info->port->lock, flags); + spin_unlock_irqrestore(&state->port->lock, flags); } #if 0 @@ -1169,7 +1208,7 @@ */ if (!(old_termios->c_cflag & CLOCAL) && (tty->termios->c_cflag & CLOCAL)) - wake_up_interruptible(&info->open_wait); + wake_up_interruptible(&state->info->open_wait); #endif } @@ -1180,29 +1219,17 @@ */ static void uart_close(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; - struct uart_state *state; - unsigned long flags; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; BUG_ON(!kernel_locked()); + DPRINTK("uart_close(%d) called\n", port->line); - if (!info) - return; - - state = info->state; - - DPRINTK("uart_close() called\n"); + down(&state->sem); - /* - * This is safe, as long as the BKL exists in - * do_tty_hangup(), and we're protected by the BKL. - */ if (tty_hung_up_p(filp)) goto done; - spin_lock_irqsave(&info->port->lock, flags); if ((tty->count == 1) && (state->count != 1)) { /* * Uh, oh. tty->count is 1, which means that the tty @@ -1217,34 +1244,28 @@ } if (--state->count < 0) { printk("rs_close: bad serial port count for %s%d: %d\n", - tty->driver.name, info->port->line, state->count); + tty->driver.name, port->line, state->count); state->count = 0; } - if (state->count) { - spin_unlock_irqrestore(&info->port->lock, flags); + if (state->count) goto done; - } - - /* - * The UIF_CLOSING flag protects us against further opens - * of this port. - */ - info->flags |= UIF_CLOSING; - spin_unlock_irqrestore(&info->port->lock, flags); /* * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. + * the line discipline to only process XON/XOFF characters by + * setting tty->closing. */ tty->closing = 1; - if (info->state->closing_wait != USF_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->state->closing_wait); + + if (state->closing_wait != USF_CLOSING_WAIT_NONE) + tty_wait_until_sent(tty, state->closing_wait); /* * At this point, we stop accepting input. To do this, we * disable the receive line status interrupts. */ - if (info->flags & UIF_INITIALIZED) { + if (state->info->flags & UIF_INITIALIZED) { + unsigned long flags; spin_lock_irqsave(&port->lock, flags); port->ops->stop_rx(port); spin_unlock_irqrestore(&port->lock, flags); @@ -1255,46 +1276,38 @@ */ uart_wait_until_sent(tty, port->timeout); } - down(&port_sem); - uart_shutdown(info); - up(&port_sem); + + uart_shutdown(state); uart_flush_buffer(tty); if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); tty->closing = 0; - info->tty = NULL; - if (info->blocked_open) { - if (info->state->close_delay) { + state->info->tty = NULL; + + if (state->info->blocked_open) { + if (state->close_delay) { set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->state->close_delay); + schedule_timeout(state->close_delay); set_current_state(TASK_RUNNING); } - } else { -#ifdef CONFIG_PM - /* - * Put device into D3 state. - */ - pm_send(info->state->pm, PM_SUSPEND, (void *)3); -#else - if (port->ops->pm) - port->ops->pm(port, 3, 0); -#endif + } else if (!uart_console(port)) { + uart_change_pm(state, 3); } /* * Wake up anyone trying to open this port. */ - info->flags &= ~(UIF_NORMAL_ACTIVE|UIF_CLOSING); - wake_up_interruptible(&info->open_wait); + state->info->flags &= ~UIF_NORMAL_ACTIVE; + wake_up_interruptible(&state->info->open_wait); done: - module_put(drv->owner); + up(&state->sem); } static void uart_wait_until_sent(struct tty_struct *tty, int timeout) { - struct uart_info *info = tty->driver_data; - struct uart_port *port = info->port; + struct uart_state *state = tty->driver_data; + struct uart_port *port = state->port; unsigned long char_time, expire; BUG_ON(!kernel_locked()); @@ -1358,23 +1371,22 @@ */ static void uart_hangup(struct tty_struct *tty) { - struct uart_info *info = tty->driver_data; - struct uart_state *state = info->state; + struct uart_state *state = tty->driver_data; BUG_ON(!kernel_locked()); + DPRINTK("uart_hangup(%d)\n", state->port->line); - uart_flush_buffer(tty); - down(&port_sem); - if (info->flags & UIF_CLOSING) { - up(&port_sem); - return; + down(&state->sem); + if (state->info && state->info->flags & UIF_NORMAL_ACTIVE) { + uart_flush_buffer(tty); + uart_shutdown(state); + state->count = 0; + state->info->flags &= ~UIF_NORMAL_ACTIVE; + state->info->tty = NULL; + wake_up_interruptible(&state->info->open_wait); + wake_up_interruptible(&state->info->delta_msr_wait); } - uart_shutdown(info); - state->count = 0; - info->flags &= ~UIF_NORMAL_ACTIVE; - info->tty = NULL; - up(&port_sem); - wake_up_interruptible(&info->open_wait); + up(&state->sem); } /* @@ -1383,18 +1395,15 @@ * kernel settings, and the settings init adopts when it opens the port * for the first time. */ -static void uart_update_termios(struct uart_info *info) +static void uart_update_termios(struct uart_state *state) { - struct tty_struct *tty = info->tty; - -#ifdef CONFIG_SERIAL_CORE_CONSOLE - struct console *c = info->port->cons; + struct tty_struct *tty = state->info->tty; + struct uart_port *port = state->port; - if (c && c->cflag && c->index == info->port->line) { - tty->termios->c_cflag = c->cflag; - c->cflag = 0; + if (uart_console(port) && port->cons->cflag) { + tty->termios->c_cflag = port->cons->cflag; + port->cons->cflag = 0; } -#endif /* * If the device failed to grab its irq resources, @@ -1405,22 +1414,26 @@ /* * Make termios settings take effect. */ - uart_change_speed(info, NULL); + uart_change_speed(state, NULL); /* * And finally enable the RTS and DTR signals. */ if (tty->termios->c_cflag & CBAUD) - uart_set_mctrl(info->port, TIOCM_DTR | TIOCM_RTS); + uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS); } } +/* + * Block the open until the port is ready. We must be called with + * the per-port semaphore held. + */ static int -uart_block_til_ready(struct file *filp, struct uart_info *info) +uart_block_til_ready(struct file *filp, struct uart_state *state) { DECLARE_WAITQUEUE(wait, current); - struct uart_state *state = info->state; - struct uart_port *port = info->port; + struct uart_info *info = state->info; + struct uart_port *port = state->port; info->blocked_open++; state->count--; @@ -1432,18 +1445,10 @@ /* * If we have been hung up, tell userspace/restart open. */ - if (tty_hung_up_p(filp)) + if (tty_hung_up_p(filp) || info->tty == NULL) break; /* - * If the device is in the middle of being closed, block - * until it's done. We will need to re-initialise the - * port. Hmm, is it legal to block a non-blocking open? - */ - if (info->flags & UIF_CLOSING) - goto wait; - - /* * If the port has been closed, tell userspace/restart open. */ if (!(info->flags & UIF_INITIALIZED)) @@ -1470,7 +1475,7 @@ * the data from the modem. */ if (info->tty->termios->c_cflag & CBAUD) - uart_set_mctrl(info->port, TIOCM_DTR); + uart_set_mctrl(port, TIOCM_DTR); /* * and wait for the carrier to indicate that the @@ -1479,8 +1484,9 @@ if (port->ops->get_mctrl(port) & TIOCM_CAR) break; - wait: + up(&state->sem); schedule(); + down(&state->sem); if (signal_pending(current)) break; @@ -1494,52 +1500,56 @@ if (signal_pending(current)) return -ERESTARTSYS; - if (info->tty->flags & (1 << TTY_IO_ERROR)) - return 0; - - if (tty_hung_up_p(filp) || !(info->flags & UIF_INITIALIZED)) + if (!info->tty || tty_hung_up_p(filp)) return (port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; return 0; } -static struct uart_info *uart_get(struct uart_driver *drv, int line) +static struct uart_state *uart_get(struct uart_driver *drv, int line) { - struct uart_state *state = drv->state + line; - struct uart_info *info = NULL; + struct uart_state *state; down(&port_sem); - if (!state->port) + state = drv->state + line; + if (down_interruptible(&state->sem)) { + state = ERR_PTR(-ERESTARTSYS); goto out; + } state->count++; - info = state->info; + if (!state->port) { + state->count--; + up(&state->sem); + state = ERR_PTR(-ENXIO); + goto out; + } - if (!info) { - info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); - if (info) { - memset(info, 0, sizeof(struct uart_info)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->delta_msr_wait); + if (!state->info) { + state->info = kmalloc(sizeof(struct uart_info), GFP_KERNEL); + if (state->info) { + memset(state->info, 0, sizeof(struct uart_info)); + init_waitqueue_head(&state->info->open_wait); + init_waitqueue_head(&state->info->delta_msr_wait); /* * Link the info into the other structures. */ - info->port = state->port; - info->state = state; - state->port->info = info; - - tasklet_init(&info->tlet, uart_tasklet_action, - (unsigned long)info); - state->info = info; - } else + state->port->info = state->info; + + tasklet_init(&state->info->tlet, uart_tasklet_action, + (unsigned long)state); + } else { state->count--; + up(&state->sem); + state = ERR_PTR(-ENOMEM); + } } out: up(&port_sem); - return info; + return state; } /* @@ -1555,11 +1565,10 @@ static int uart_open(struct tty_struct *tty, struct file *filp) { struct uart_driver *drv = (struct uart_driver *)tty->driver.driver_state; - struct uart_info *info; + struct uart_state *state; int retval, line = minor(tty->device) - tty->driver.minor_start; BUG_ON(!kernel_locked()); - DPRINTK("uart_open(%d) called\n", line); /* @@ -1572,92 +1581,66 @@ goto fail; /* - * If we fail to increment the module use count, we can't have - * any other users of this tty (since this implies that the module - * is about to be unloaded). Therefore, it is safe to set - * tty->driver_data to be NULL, so uart_close() doesn't bite us. - */ - if (!try_module_get(drv->owner)) { - tty->driver_data = NULL; + * We take the semaphore inside uart_get to guarantee that we won't + * be re-entered while allocating the info structure, or while we + * request any IRQs that the driver may need. This also has the nice + * side-effect that it delays the action of uart_hangup, so we can + * guarantee that info->tty will always contain something reasonable. + */ + state = uart_get(drv, line); + if (IS_ERR(state)) { + retval = PTR_ERR(state); goto fail; } /* - * FIXME: This one isn't fun. We can't guarantee that the tty isn't - * already in open, nor can we guarantee the state of tty->driver_data - */ - info = uart_get(drv, line); - retval = -ENOMEM; - if (!info) { - if (tty->driver_data) - goto fail; - else - goto out; - } - - /* * Once we set tty->driver_data here, we are guaranteed that * uart_close() will decrement the driver module use count. * Any failures from here onwards should not touch the count. */ - tty->driver_data = info; - tty->low_latency = (info->port->flags & UPF_LOW_LATENCY) ? 1 : 0; + tty->driver_data = state; + tty->low_latency = (state->port->flags & UPF_LOW_LATENCY) ? 1 : 0; tty->alt_speed = 0; - info->tty = tty; + state->info->tty = tty; /* * If the port is in the middle of closing, bail out now. */ - if (tty_hung_up_p(filp) || (info->flags & UIF_CLOSING)) { - wait_event_interruptible(info->open_wait, - !(info->flags & UIF_CLOSING)); - retval = (info->port->flags & UPF_HUP_NOTIFY) ? + if (tty_hung_up_p(filp)) { + retval = (state->port->flags & UPF_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS; + state->count--; + up(&state->sem); goto fail; } /* * Make sure the device is in D0 state. */ - if (info->state->count == 1) { -#ifdef CONFIG_PM - pm_send(info->state->pm, PM_RESUME, (void *)0); -#else - struct uart_port *port = info->port; - if (port->ops->pm) - port->ops->pm(port, 0, 3); -#endif - } + if (state->count == 1) + uart_change_pm(state, 0); /* - * Start up the serial port. We have this semaphore here to - * prevent uart_startup or uart_shutdown being re-entered if - * we sleep while requesting an IRQ. + * Start up the serial port. */ - down(&port_sem); - retval = uart_startup(info, 0); - up(&port_sem); - if (retval) - goto fail; + retval = uart_startup(state, 0); /* - * Wait until the port is ready. + * If we succeeded, wait until the port is ready. */ - retval = uart_block_til_ready(filp, info); + if (retval == 0) + retval = uart_block_til_ready(filp, state); + up(&state->sem); /* * If this is the first open to succeed, adjust things to suit. */ - if (retval == 0 && !(info->flags & UIF_NORMAL_ACTIVE)) { - info->flags |= UIF_NORMAL_ACTIVE; + if (retval == 0 && !(state->info->flags & UIF_NORMAL_ACTIVE)) { + state->info->flags |= UIF_NORMAL_ACTIVE; - uart_update_termios(info); + uart_update_termios(state); } - return retval; - - out: - module_put(drv->owner); fail: return retval; } @@ -1890,153 +1873,100 @@ return 0; } +#endif /* CONFIG_SERIAL_CORE_CONSOLE */ -extern void ambauart_console_init(void); -extern void anakin_console_init(void); -extern void clps711xuart_console_init(void); -extern void rs285_console_init(void); -extern void sa1100_rs_console_init(void); -extern void serial8250_console_init(void); -extern void uart00_console_init(void); - -/* - * Central "initialise all serial consoles" container. Needs to be killed. - */ -void __init uart_console_init(void) +static void uart_change_pm(struct uart_state *state, int pm_state) { -#ifdef CONFIG_SERIAL_AMBA_CONSOLE - ambauart_console_init(); -#endif -#ifdef CONFIG_SERIAL_ANAKIN_CONSOLE - anakin_console_init(); -#endif -#ifdef CONFIG_SERIAL_CLPS711X_CONSOLE - clps711xuart_console_init(); -#endif -#ifdef CONFIG_SERIAL_21285_CONSOLE - rs285_console_init(); -#endif -#ifdef CONFIG_SERIAL_SA1100_CONSOLE - sa1100_rs_console_init(); -#endif -#ifdef CONFIG_SERIAL_8250_CONSOLE - serial8250_console_init(); -#endif -#ifdef CONFIG_SERIAL_UART00_CONSOLE - uart00_console_init(); -#endif + struct uart_port *port = state->port; + if (port->ops->pm) + port->ops->pm(port, pm_state, state->pm_state); + state->pm_state = pm_state; } -#endif /* CONFIG_SERIAL_CORE_CONSOLE */ -#ifdef CONFIG_PM -/* - * Serial port power management. - * - * This is pretty coarse at the moment - either all on or all off. We - * should probably some day do finer power management here some day. - * - * We don't actually save any state; the serial driver already has the - * state held internally to re-setup the port when we come out of D3. - */ -static int uart_pm_set_state(struct uart_state *state, int pm_state, int oldstate) +int uart_suspend_port(struct uart_driver *drv, struct uart_port *port, u32 level) { - struct uart_port *port; - struct uart_ops *ops; - int running = state->info && - state->info->flags & UIF_INITIALIZED; + struct uart_state *state = drv->state + port->line; - down(&port_sem); + down(&state->sem); - if (!state->port || state->port->type == PORT_UNKNOWN) { - up(&port_sem); - return 0; - } - - port = state->port; - ops = port->ops; + switch (level) { + case SUSPEND_SAVE_STATE: + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; - DPRINTK("pm: %08x: %d -> %d, %srunning\n", - port->iobase, dev->state, pm_state, running ? "" : "not "); + spin_lock_irq(&port->lock); + ops->stop_tx(port, 0); + ops->set_mctrl(port, 0); + ops->stop_rx(port); + spin_unlock_irq(&port->lock); - if (pm_state == 0) { - if (ops->pm) - ops->pm(port, pm_state, oldstate); - if (running) { /* - * The port lock isn't taken here - - * the port isn't initialised. + * Wait for the transmitter to empty. */ - ops->set_mctrl(port, 0); - ops->startup(port); - uart_change_speed(state->info, NULL); - spin_lock_irq(&port->lock); - ops->set_mctrl(port, port->mctrl); - ops->start_tx(port, 0); - spin_unlock_irq(&port->lock); + while (!ops->tx_empty(port)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(10*HZ/1000); + } + set_current_state(TASK_RUNNING); + + ops->shutdown(port); } + break; - /* - * Re-enable the console device after suspending. - */ - if (port->cons && port->cons->index == port->line) - port->cons->flags |= CON_ENABLED; - } else if (pm_state == 1) { - if (ops->pm) - ops->pm(port, pm_state, oldstate); - } else { + case SUSPEND_POWER_DOWN: /* * Disable the console device before suspending. */ - if (port->cons && port->cons->index == port->line) + if (uart_console(port)) port->cons->flags &= ~CON_ENABLED; - if (running) { - spin_lock_irq(&port->lock); - ops->stop_tx(port, 0); - ops->set_mctrl(port, 0); - ops->stop_rx(port); - spin_unlock_irq(&port->lock); - ops->shutdown(port); - } - if (ops->pm) - ops->pm(port, pm_state, oldstate); + uart_change_pm(state, 3); + break; } - up(&port_sem); + + up(&state->sem); return 0; } -/* - * Wakeup support. - */ -static int uart_pm_set_wakeup(struct uart_state *state, int data) +int uart_resume_port(struct uart_driver *drv, struct uart_port *port, u32 level) { - int err = 0; + struct uart_state *state = drv->state + port->line; - if (state->port->ops->set_wake) - err = state->port->ops->set_wake(state->port, data); + down(&state->sem); - return err; -} - -static int uart_pm(struct pm_dev *dev, pm_request_t rqst, void *data) -{ - struct uart_state *state = dev->data; - int err = 0; + switch (level) { + case RESUME_POWER_ON: + uart_change_pm(state, 0); - switch (rqst) { - case PM_SUSPEND: - case PM_RESUME: - err = uart_pm_set_state(state, (int)(long)data, dev->state); + /* + * Re-enable the console device after suspending. + */ + if (uart_console(port)) { + uart_change_speed(state, NULL); + port->cons->flags |= CON_ENABLED; + } break; - case PM_SET_WAKEUP: - err = uart_pm_set_wakeup(state, (int)(long)data); + case RESUME_RESTORE_STATE: + if (state->info && state->info->flags & UIF_INITIALIZED) { + struct uart_ops *ops = port->ops; + + ops->set_mctrl(port, 0); + ops->startup(port); + uart_change_speed(state, NULL); + spin_lock_irq(&port->lock); + ops->set_mctrl(port, port->mctrl); + ops->start_tx(port, 0); + spin_unlock_irq(&port->lock); + } break; } - return err; + + up(&state->sem); + + return 0; } -#endif static inline void uart_report_port(struct uart_driver *drv, struct uart_port *port) @@ -2058,17 +1988,11 @@ } static void -__uart_register_port(struct uart_driver *drv, struct uart_state *state, - struct uart_port *port) +uart_configure_port(struct uart_driver *drv, struct uart_state *state, + struct uart_port *port) { unsigned int flags; - state->port = port; - - spin_lock_init(&port->lock); - port->cons = drv->cons; - port->info = state->info; - /* * If there isn't a port here, don't do anything further. */ @@ -2087,12 +2011,6 @@ port->ops->config_port(port, flags); } - /* - * Register the port whether it's detected or not. This allows - * setserial to be used to alter this ports parameters. - */ - tty_register_device(drv->tty_driver, drv->minor + port->line); - if (port->type != PORT_UNKNOWN) { unsigned long flags; @@ -2106,51 +2024,33 @@ port->ops->set_mctrl(port, 0); spin_unlock_irqrestore(&port->lock, flags); -#ifdef CONFIG_PM /* * Power down all ports by default, except the - * console if we have one. We need to drop the - * port semaphore here. + * console if we have one. */ - if (state->pm && (!drv->cons || port->line != drv->cons->index)) { - up(&port_sem); - pm_send(state->pm, PM_SUSPEND, (void *)3); - down(&port_sem); - } -#endif + if (!uart_console(port)) + uart_change_pm(state, 3); } } /* - * Hangup the port. This must be done outside the port_sem - * since uart_hangup() grabs this same semaphore. Grr. + * This reverses the affects of uart_configure_port, hanging up the + * port before removal. */ static void -__uart_hangup_port(struct uart_driver *drv, struct uart_state *state) +uart_unconfigure_port(struct uart_driver *drv, struct uart_state *state) { + struct uart_port *port = state->port; struct uart_info *info = state->info; if (info && info->tty) tty_vhangup(info->tty); -} -/* - * This reverses the affects of __uart_register_port. - */ -static void -__uart_unregister_port(struct uart_driver *drv, struct uart_state *state) -{ - struct uart_port *port = state->port; - struct uart_info *info = state->info; + down(&state->sem); state->info = NULL; /* - * Remove the devices from devfs - */ - tty_unregister_device(drv->tty_driver, drv->minor + port->line); - - /* * Free the port IO and memory resources, if any. */ if (port->type != PORT_UNKNOWN) @@ -2168,6 +2068,8 @@ tasklet_kill(&info->tlet); kfree(info); } + + up(&state->sem); } /** @@ -2222,6 +2124,7 @@ drv->tty_driver = normal; normal->magic = TTY_DRIVER_MAGIC; + normal->owner = drv->owner; normal->driver_name = drv->driver_name; normal->name = drv->dev_name; normal->major = drv->major; @@ -2268,20 +2171,13 @@ state->close_delay = 5 * HZ / 10; state->closing_wait = 30 * HZ; -#ifdef CONFIG_PM - state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm); - if (state->pm) - state->pm->data = state; -#endif + + init_MUTEX(&state->sem); } retval = tty_register_driver(normal); out: if (retval < 0) { -#ifdef CONFIG_PM - for (i = 0; i < drv->nr; i++) - pm_unregister(drv->state[i].pm); -#endif kfree(normal); kfree(drv->state); kfree(termios); @@ -2300,11 +2196,6 @@ */ void uart_unregister_driver(struct uart_driver *drv) { - int i; - - for (i = 0; i < drv->nr; i++) - pm_unregister(drv->state[i].pm); - tty_unregister_driver(drv->tty_driver); kfree(drv->state); @@ -2325,6 +2216,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) { struct uart_state *state; + int ret = 0; BUG_ON(in_interrupt()); @@ -2334,10 +2226,29 @@ state = drv->state + port->line; down(&port_sem); - __uart_register_port(drv, state, port); + if (state->port) { + ret = -EINVAL; + goto out; + } + + state->port = port; + + spin_lock_init(&port->lock); + port->cons = drv->cons; + port->info = state->info; + + uart_configure_port(drv, state, port); + + /* + * Register the port whether it's detected or not. This allows + * setserial to be used to alter this ports parameters. + */ + tty_register_device(drv->tty_driver, drv->minor + port->line); + + out: up(&port_sem); - return 0; + return ret; } /** @@ -2359,10 +2270,14 @@ printk(KERN_ALERT "Removing wrong port: %p != %p\n", state->port, port); - __uart_hangup_port(drv, state); - down(&port_sem); - __uart_unregister_port(drv, state); + + /* + * Remove the devices from devfs + */ + tty_unregister_device(drv->tty_driver, drv->minor + port->line); + + uart_unconfigure_port(drv, state); state->port = NULL; up(&port_sem); @@ -2462,8 +2377,7 @@ * alter it underneath itself - the port may be open and * trying to do useful work. */ - if (state->count != 0 || - (state->info && state->info->blocked_open != 0)) { + if (uart_users(state) != 0) { ret = -EBUSY; goto out; } @@ -2483,7 +2397,7 @@ state->port->line = state - drv->state; state->port->mapbase = port->mapbase; - __uart_register_port(drv, state, state->port); + uart_configure_port(drv, state, state->port); } ret = state->port->line; @@ -2515,16 +2429,16 @@ state = drv->state + line; - __uart_hangup_port(drv, state); - down(&port_sem); - __uart_unregister_port(drv, state); + uart_unconfigure_port(drv, state); up(&port_sem); } EXPORT_SYMBOL(uart_write_wakeup); EXPORT_SYMBOL(uart_register_driver); EXPORT_SYMBOL(uart_unregister_driver); +EXPORT_SYMBOL(uart_suspend_port); +EXPORT_SYMBOL(uart_resume_port); EXPORT_SYMBOL(uart_register_port); EXPORT_SYMBOL(uart_unregister_port); EXPORT_SYMBOL(uart_add_one_port); diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c --- a/drivers/serial/mcfserial.c Sat Mar 15 18:40:41 2003 +++ b/drivers/serial/mcfserial.c Sat Mar 15 18:40:41 2003 @@ -1853,9 +1853,11 @@ .index = -1, }; -void __init mcfrs_console_init(void) +static void __init mcfrs_console_init(void) { register_console(&mcfrs_console); } + +console_initcall(mcfrs_console_init); /****************************************************************************/ diff -Nru a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c --- a/drivers/serial/sa1100.c Sat Mar 15 18:40:40 2003 +++ b/drivers/serial/sa1100.c Sat Mar 15 18:40:40 2003 @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -835,11 +836,12 @@ .index = -1, }; -void __init sa1100_rs_console_init(void) +static void __init sa1100_rs_console_init(void) { sa1100_init_ports(); register_console(&sa1100_console); } +console_initcall(sa1100_rs_console_init); #define SA1100_CONSOLE &sa1100_console #else @@ -856,11 +858,53 @@ .cons = SA1100_CONSOLE, }; +static int sa1100_serial_suspend(struct device *dev, u32 state, u32 level) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_suspend_port(&sa1100_reg, &sa1100_ports[i].port, level); + + return 0; +} + +static int sa1100_serial_resume(struct device *dev, u32 level) +{ + int i; + + for (i = 0; i < NR_PORTS; i++) + uart_resume_port(&sa1100_reg, &sa1100_ports[i].port, level); + + return 0; +} + +static struct device_driver sa11x0_serial_driver = { + .name = "sa11x0_serial", + .bus = &system_bus_type, + .devclass = &tty_devclass, + .suspend = sa1100_serial_suspend, + .resume = sa1100_serial_resume, +}; + +/* + * This "device" covers _all_ ISA 8250-compatible serial devices. + */ +static struct sys_device sa11x0_serial_devs = { + .name = "sa11x0_serial", + .id = 0, + .dev = { + .driver = &sa11x0_serial_driver, + }, +}; + static int __init sa1100_serial_init(void) { int ret; printk(KERN_INFO "Serial: SA11x0 driver $Revision: 1.50 $\n"); + + driver_register(&sa11x0_serial_driver); + sys_device_register(&sa11x0_serial_devs); sa1100_init_ports(); ret = uart_register_driver(&sa1100_reg); diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- a/drivers/serial/uart00.c Sat Mar 15 18:40:41 2003 +++ b/drivers/serial/uart00.c Sat Mar 15 18:40:41 2003 @@ -645,10 +645,11 @@ .index = 0, }; -void __init uart00_console_init(void) +static void __init uart00_console_init(void) { register_console(&uart00_console); } +console_initcall(uart00_console_init); #define UART00_CONSOLE &uart00_console #else diff -Nru a/drivers/sgi/char/sgiserial.c b/drivers/sgi/char/sgiserial.c --- a/drivers/sgi/char/sgiserial.c Sat Mar 15 18:40:40 2003 +++ b/drivers/sgi/char/sgiserial.c Sat Mar 15 18:40:40 2003 @@ -2269,8 +2269,10 @@ /* * Register console. */ -void __init sgi_serial_console_init(void) +static void __init sgi_serial_console_init(void) { register_console(&sgi_console_driver); } +console_initcall(sgi_serial_console_init); + __initcall(rs_init); diff -Nru a/drivers/usb/class/usb-midi.h b/drivers/usb/class/usb-midi.h --- a/drivers/usb/class/usb-midi.h Sat Mar 15 18:40:42 2003 +++ b/drivers/usb/class/usb-midi.h Sat Mar 15 18:40:42 2003 @@ -54,6 +54,10 @@ #define USB_VENDOR_ID_STEINBERG 0x0763 #define USBMIDI_STEINBERG_USB2MIDI 0x1001 +/* Mark of the Unicorn MIDI Devices */ +#define USB_VENDOR_ID_MOTU 0x07fd +#define USBMIDI_MOTU_FASTLANE 0x0001 + /* ------------------------------------------------------------------------- */ /* Supported devices */ @@ -101,8 +105,15 @@ { /* Roland SC8850 */ "Roland SC8850", USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850, 2, -1, - { { 0x81, 15 }, {-1, -1} }, /** cables 0,1,2, and 3 **/ - { { 0x01, 15 }, {-1, -1} }, + { { 0x81, 0x3f }, {-1, -1} }, + { { 0x01, 0x3f }, {-1, -1} }, + }, + + { /* Roland SC8820 */ + "Roland SC8820", + USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820, 2, -1, + { { 0x81, 0x13 }, {-1, -1} }, + { { 0x01, 0x13 }, {-1, -1} }, }, { /* Roland SC8820 */ @@ -123,6 +134,12 @@ USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300, 2, -1, { { 0x81, 1 }, {-1, -1} }, { { 0x01, 1 }, {-1, -1} }, + }, + { /* MOTU Fastlane USB */ + "MOTU Fastlane USB", + USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE, 1, 0, + { { 0x82, 3 }, {-1, -1} }, + { { 0x02, 3 }, {-1, -1} }, } }; @@ -138,7 +155,9 @@ { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_UA100G ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_PC300 ) }, { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8850 ) }, + { USB_DEVICE( USB_VENDOR_ID_ROLAND, USBMIDI_ROLAND_SC8820 ) }, { USB_DEVICE( USB_VENDOR_ID_YAMAHA, USBMIDI_YAMAHA_MU1000 ) }, + { USB_DEVICE( USB_VENDOR_ID_MOTU, USBMIDI_MOTU_FASTLANE ) }, /* { USB_DEVICE( USB_VENDOR_ID_STEINBERG, USBMIDI_STEINBERG_USB2MIDI ) },*/ { } /* Terminating entry */ }; diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c --- a/drivers/usb/core/hub.c Sat Mar 15 18:40:41 2003 +++ b/drivers/usb/core/hub.c Sat Mar 15 18:40:41 2003 @@ -876,6 +876,7 @@ } hub->children[port] = dev; + dev->state = USB_STATE_POWERED; /* Reset the device, and detect its speed */ if (usb_hub_port_reset(hub, port, dev, delay)) { diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Sat Mar 15 18:40:40 2003 +++ b/drivers/usb/core/message.c Sat Mar 15 18:40:40 2003 @@ -904,17 +904,29 @@ break; } } - if (!cp) { + if ((!cp && configuration != 0) || (cp && configuration == 0)) { warn("selecting invalid configuration %d", configuration); return -EINVAL; } + /* if it's already configured, clear out old state first. */ + if (dev->state != USB_STATE_ADDRESS) { + /* FIXME unbind drivers from all "old" interfaces. + * handshake with hcd to reset cached hc endpoint state. + */ + } + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) return ret; - + if (configuration) + dev->state = USB_STATE_CONFIGURED; + else + dev->state = USB_STATE_ADDRESS; dev->actconfig = cp; + + /* reset more hc/hcd endpoint state */ dev->toggle[0] = 0; dev->toggle[1] = 0; usb_set_maxpacket(dev); diff -Nru a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c --- a/drivers/usb/core/urb.c Sat Mar 15 18:40:42 2003 +++ b/drivers/usb/core/urb.c Sat Mar 15 18:40:42 2003 @@ -195,7 +195,9 @@ if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; - if (!(dev = urb->dev) || !dev->present || !dev->bus || dev->devnum <= 0) + if (!(dev = urb->dev) || + (dev->state < USB_STATE_DEFAULT) || + (!dev->bus) || (dev->devnum <= 0)) return -ENODEV; if (!(op = dev->bus->op) || !op->submit_urb) return -ENODEV; @@ -211,6 +213,9 @@ temp = usb_pipetype (pipe); is_out = usb_pipeout (pipe); + if (!usb_pipecontrol (pipe) && dev->state < USB_STATE_CONFIGURED) + return -ENODEV; + /* (actually HCDs may need to duplicate this, endpoint might yet * stall due to queued bulk/intr transactions that complete after * we check) @@ -376,7 +381,16 @@ */ int usb_unlink_urb(struct urb *urb) { - if (urb && urb->dev && urb->dev->present && urb->dev->bus && urb->dev->bus->op) + /* FIXME + * We should not care about the state here, but the host controllers + * die a horrible death if we submit a urb for a device that has been + * physically removed. + */ + if (urb && + urb->dev && + (urb->dev->state >= USB_STATE_DEFAULT) && + urb->dev->bus && + urb->dev->bus->op) return urb->dev->bus->op->unlink_urb(urb); else return -ENODEV; diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c --- a/drivers/usb/core/usb.c Sat Mar 15 18:40:42 2003 +++ b/drivers/usb/core/usb.c Sat Mar 15 18:40:42 2003 @@ -679,7 +679,7 @@ memset(dev, 0, sizeof(*dev)); device_initialize(&dev->dev); - dev->present = 1; + dev->state = USB_STATE_ATTACHED; usb_bus_get(bus); @@ -828,6 +828,11 @@ *pdev = NULL; + /* mark the device as inactive, so any further urb submissions for + * this device will fail. + */ + dev->state = USB_STATE_NOTATTACHED; + dev_info (&dev->dev, "USB disconnect, address %d\n", dev->devnum); /* Free up all the children before we remove this device */ @@ -855,10 +860,6 @@ } device_unregister(&dev->dev); - /* mark the device as not present so any further urb submissions for - * this device will fail. */ - dev->present = 0; - /* Decrement the reference count, it'll auto free everything when */ /* it hits 0 which could very well be now */ usb_put_dev(dev); @@ -906,9 +907,17 @@ // otherwise used internally, for usb_new_device() int usb_set_address(struct usb_device *dev) { - return usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, - // FIXME USB_CTRL_SET_TIMEOUT - 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_GET_TIMEOUT); + int retval; + + if (dev->devnum == 0) + return -EINVAL; + if (dev->state != USB_STATE_DEFAULT && dev->state != USB_STATE_ADDRESS) + return -EINVAL; + retval = usb_control_msg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS, + 0, dev->devnum, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT); + if (retval == 0) + dev->state = USB_STATE_ADDRESS; + return retval; } @@ -1014,7 +1023,8 @@ /* dma masks come from the controller; readonly, except to hcd */ dev->dev.dma_mask = parent->dma_mask; - /* USB device state == default ... it's not usable yet */ + /* it's not usable yet */ + dev->state = USB_STATE_DEFAULT; /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. @@ -1049,6 +1059,7 @@ if (err < 0) { dev_err(&dev->dev, "USB device not accepting new address=%d (error=%d)\n", dev->devnum, err); + dev->state = USB_STATE_DEFAULT; clear_bit(dev->devnum, dev->bus->devmap.devicemap); dev->devnum = -1; return 1; diff -Nru a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c --- a/drivers/usb/host/ohci-pci.c Sat Mar 15 18:40:43 2003 +++ b/drivers/usb/host/ohci-pci.c Sat Mar 15 18:40:43 2003 @@ -18,6 +18,7 @@ #include #include #include +#include #ifndef CONFIG_PM # define CONFIG_PM #endif diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c --- a/drivers/usb/serial/io_edgeport.c Sat Mar 15 18:40:39 2003 +++ b/drivers/usb/serial/io_edgeport.c Sat Mar 15 18:40:39 2003 @@ -522,7 +522,7 @@ case EDGE_DOWNLOAD_FILE_I930: BootMajorVersion = BootCodeImageVersion_GEN1.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN1.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN1.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN1.BuildNumber); BootImage = &BootCodeImage_GEN1[0]; BootSize = sizeof( BootCodeImage_GEN1 ); break; @@ -530,7 +530,7 @@ case EDGE_DOWNLOAD_FILE_80251: BootMajorVersion = BootCodeImageVersion_GEN2.MajorVersion; BootMinorVersion = BootCodeImageVersion_GEN2.MinorVersion; - BootBuildNumber = BootCodeImageVersion_GEN2.BuildNumber; + BootBuildNumber = cpu_to_le16(BootCodeImageVersion_GEN2.BuildNumber); BootImage = &BootCodeImage_GEN2[0]; BootSize = sizeof( BootCodeImage_GEN2 ); break; @@ -542,26 +542,26 @@ // Check Boot Image Version BootCurVer = (edge_serial->boot_descriptor.MajorVersion << 24) + (edge_serial->boot_descriptor.MinorVersion << 16) + - edge_serial->boot_descriptor.BuildNumber; + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber); BootNewVer = (BootMajorVersion << 24) + (BootMinorVersion << 16) + - BootBuildNumber; + le16_to_cpu(BootBuildNumber); dbg("Current Boot Image version %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber); + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); if (BootNewVer > BootCurVer) { dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, - edge_serial->boot_descriptor.BuildNumber, + le16_to_cpu(edge_serial->boot_descriptor.BuildNumber), BootMajorVersion, BootMinorVersion, - BootBuildNumber); + le16_to_cpu(BootBuildNumber)); dbg("Downloading new Boot Image"); @@ -570,12 +570,12 @@ for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = rom_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = rom_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len); + dev_err(&edge_serial->serial->dev->dev, "rom_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len)); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &BootImage[BootSize]) { break; } @@ -678,12 +678,12 @@ if (edge_serial->serial->dev->descriptor.idProduct & ION_DEVICE_ID_GENERATION_2) { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN2.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN2.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN2.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN2.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; } else { product_info->FirmwareMajorVersion = OperationalCodeImageVersion_GEN1.MajorVersion; product_info->FirmwareMinorVersion = OperationalCodeImageVersion_GEN1.MinorVersion; - product_info->FirmwareBuildNumber = OperationalCodeImageVersion_GEN1.BuildNumber; + product_info->FirmwareBuildNumber = cpu_to_le16(OperationalCodeImageVersion_GEN1.BuildNumber); product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; } @@ -729,10 +729,10 @@ dbg(" BoardRev %x", product_info->BoardRev); dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, product_info->BootMinorVersion, - product_info->BootBuildNumber); + le16_to_cpu(product_info->BootBuildNumber)); dbg(" FirmwareMajorVersion %d.%d.%d", product_info->FirmwareMajorVersion, product_info->FirmwareMinorVersion, - product_info->FirmwareBuildNumber); + le16_to_cpu(product_info->FirmwareBuildNumber)); dbg(" ManufactureDescDate %d/%d/%d", product_info->ManufactureDescDate[0], product_info->ManufactureDescDate[1], product_info->ManufactureDescDate[2]+1900); @@ -2326,7 +2326,7 @@ __u16 current_length; unsigned char *transfer_buffer; -// dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); + dbg("%s - %x, %x, %d", __FUNCTION__, extAddr, addr, length); transfer_buffer = kmalloc (64, GFP_KERNEL); if (!transfer_buffer) { @@ -2811,12 +2811,13 @@ * Turns a string from Unicode into ASCII. * Doesn't do a good job with any characters that are outside the normal * ASCII range, but it's only for debugging... + * NOTE: expects the unicode in LE format ****************************************************************************/ static void unicode_to_ascii (char *string, short *unicode, int unicode_size) { int i; for (i = 0; i < unicode_size; ++i) { - string[i] = (char)(unicode[i]); + string[i] = (char)(le16_to_cpu(unicode[i])); } string[unicode_size] = 0x00; } @@ -2880,11 +2881,11 @@ dev_err(&edge_serial->serial->dev->dev, "error in getting boot descriptor\n"); } else { dbg("**Boot Descriptor:"); - dbg(" BootCodeLength: %d", edge_serial->boot_descriptor.BootCodeLength); + dbg(" BootCodeLength: %d", le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); dbg(" MajorVersion: %d", edge_serial->boot_descriptor.MajorVersion); dbg(" MinorVersion: %d", edge_serial->boot_descriptor.MinorVersion); - dbg(" BuildNumber: %d", edge_serial->boot_descriptor.BuildNumber); - dbg(" Capabilities: 0x%x", edge_serial->boot_descriptor.Capabilities); + dbg(" BuildNumber: %d", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); + dbg(" Capabilities: 0x%x", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); dbg(" UConfig0: %d", edge_serial->boot_descriptor.UConfig0); dbg(" UConfig1: %d", edge_serial->boot_descriptor.UConfig1); } @@ -2936,12 +2937,12 @@ for (;;) { record = (struct edge_firmware_image_record *)firmware; - response = sram_write (edge_serial->serial, record->ExtAddr, record->Addr, record->Len, &record->Data[0]); + response = sram_write (edge_serial->serial, le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), le16_to_cpu(record->Len), &record->Data[0]); if (response < 0) { - dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", record->ExtAddr, record->Addr, record->Len); + dev_err(&edge_serial->serial->dev->dev, "sram_write failed (%x, %x, %d)\n", le16_to_cpu(record->ExtAddr), le16_to_cpu(record->Addr), record->Len); break; } - firmware += sizeof (struct edge_firmware_image_record) + record->Len; + firmware += sizeof (struct edge_firmware_image_record) + le16_to_cpu(record->Len); if (firmware >= &FirmwareImage[ImageSize]) { break; } diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c Sat Mar 15 18:40:41 2003 +++ b/drivers/usb/serial/pl2303.c Sat Mar 15 18:40:41 2003 @@ -75,6 +75,7 @@ { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) }, { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) }, + { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) }, { } /* Terminating entry */ }; diff -Nru a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h --- a/drivers/usb/serial/pl2303.h Sat Mar 15 18:40:42 2003 +++ b/drivers/usb/serial/pl2303.h Sat Mar 15 18:40:42 2003 @@ -31,3 +31,6 @@ #define TRIPP_VENDOR_ID 0x2478 #define TRIPP_PRODUCT_ID 0x2008 + +#define RADIOSHACK_VENDOR_ID 0x1453 +#define RADIOSHACK_PRODUCT_ID 0x4026 diff -Nru a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c --- a/drivers/usb/serial/usb-serial.c Sat Mar 15 18:40:41 2003 +++ b/drivers/usb/serial/usb-serial.c Sat Mar 15 18:40:41 2003 @@ -634,6 +634,7 @@ serial->type->throttle(port); exit: + ; } static void serial_unthrottle (struct tty_struct * tty) @@ -656,6 +657,7 @@ serial->type->unthrottle(port); exit: + ; } static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) @@ -704,6 +706,7 @@ serial->type->set_termios(port, old); exit: + ; } static void serial_break (struct tty_struct *tty, int break_state) @@ -726,6 +729,7 @@ serial->type->break_ctl(port, break_state); exit: + ; } static void serial_shutdown (struct usb_serial *serial) diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c --- a/drivers/usb/serial/visor.c Sat Mar 15 18:40:41 2003 +++ b/drivers/usb/serial/visor.c Sat Mar 15 18:40:41 2003 @@ -12,6 +12,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (03/05/2003) gkh + * Think Treo support is now working. + * * (04/03/2002) gkh * Added support for the Sony OS 4.1 devices. Thanks to Hiroyuki ARAKI * for the information. @@ -156,7 +159,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v2.0" +#define DRIVER_VERSION "v2.1" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB HandSpring Visor, Palm m50x, Sony Clié driver" @@ -177,6 +180,7 @@ static void visor_read_bulk_callback (struct urb *urb, struct pt_regs *regs); static void visor_read_int_callback (struct urb *urb, struct pt_regs *regs); static int clie_3_5_startup (struct usb_serial *serial); +static int treo_attach (struct usb_serial *serial); static int palm_os_3_probe (struct usb_serial *serial, const struct usb_device_id *id); static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_id *id); @@ -262,6 +266,7 @@ .close = visor_close, .throttle = visor_throttle, .unthrottle = visor_unthrottle, + .attach = treo_attach, .probe = visor_probe, .calc_num_ports = visor_calc_num_ports, .shutdown = visor_shutdown, @@ -797,6 +802,48 @@ if (result != 1) { dev_err(dev, "%s: get interface number bad return length: %d\n", __FUNCTION__, result); return -EIO; + } + + return 0; +} + +static int treo_attach (struct usb_serial *serial) +{ + struct usb_serial_port *port; + int i; + + /* Only do this endpoint hack for the Handspring devices with + * interrupt in endpoints, which for now are the Treo devices. */ + if ((serial->dev->descriptor.idVendor != HANDSPRING_VENDOR_ID) || + (serial->num_interrupt_in == 0)) + return 0; + + dbg("%s", __FUNCTION__); + + /* Ok, this is pretty ugly, but these devices want to use the + * interrupt endpoint as paired up with a bulk endpoint for a + * "virtual serial port". So let's force the endpoints to be + * where we want them to be. */ + for (i = serial->num_bulk_in; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->read_urb = serial->port[0].read_urb; + port->bulk_in_endpointAddress = serial->port[0].bulk_in_endpointAddress; + port->bulk_in_buffer = serial->port[0].bulk_in_buffer; + } + + for (i = serial->num_bulk_out; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->write_urb = serial->port[0].write_urb; + port->bulk_out_size = serial->port[0].bulk_out_size; + port->bulk_out_endpointAddress = serial->port[0].bulk_out_endpointAddress; + port->bulk_out_buffer = serial->port[0].bulk_out_buffer; + } + + for (i = serial->num_interrupt_in; i < serial->num_ports; ++i) { + port = &serial->port[i]; + port->interrupt_in_urb = serial->port[0].interrupt_in_urb; + port->interrupt_in_endpointAddress = serial->port[0].interrupt_in_endpointAddress; + port->interrupt_in_buffer = serial->port[0].interrupt_in_buffer; } return 0; diff -Nru a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c --- a/drivers/usb/storage/sddr09.c Sat Mar 15 18:40:44 2003 +++ b/drivers/usb/storage/sddr09.c Sat Mar 15 18:40:44 2003 @@ -65,6 +65,7 @@ * NAND Flash Manufacturer ID Codes */ #define NAND_MFR_AMD 0x01 +#define NAND_MFR_NS 0x8f #define NAND_MFR_TOSHIBA 0x98 #define NAND_MFR_SAMSUNG 0xec @@ -72,6 +73,8 @@ switch(manuf_id) { case NAND_MFR_AMD: return "AMD"; + case NAND_MFR_NS: + return "NS"; case NAND_MFR_TOSHIBA: return "Toshiba"; case NAND_MFR_SAMSUNG: @@ -84,10 +87,12 @@ /* * It looks like it is unnecessary to attach manufacturer to the * remaining data: SSFDC prescribes manufacturer-independent id codes. + * + * 256 MB NAND flash has a 5-byte ID with 2nd byte 0xaa, 0xba, 0xca or 0xda. */ static struct nand_flash_dev nand_flash_ids[] = { - /* NAND flash - these I verified */ + /* NAND flash */ { 0x6e, 20, 8, 4, 8, 2}, /* 1 MB */ { 0xe8, 20, 8, 4, 8, 2}, /* 1 MB */ { 0xec, 20, 8, 4, 8, 2}, /* 1 MB */ @@ -101,12 +106,13 @@ { 0x75, 25, 9, 5, 10, 2}, /* 32 MB */ { 0x76, 26, 9, 5, 10, 3}, /* 64 MB */ { 0x79, 27, 9, 5, 10, 3}, /* 128 MB */ - /* There do also exist 96 MB (from Datafab) and 256 MB cards */ - /* MASK ROM - from unknown source */ + /* MASK ROM */ { 0x5d, 21, 9, 4, 8, 2}, /* 2 MB */ { 0xd5, 22, 9, 4, 9, 2}, /* 4 MB */ { 0xd6, 23, 9, 4, 10, 2}, /* 8 MB */ + { 0x57, 24, 9, 4, 11, 2}, /* 16 MB */ + { 0x58, 25, 9, 4, 12, 2}, /* 32 MB */ { 0,} }; diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Sat Mar 15 18:40:41 2003 +++ b/drivers/usb/storage/transport.c Sat Mar 15 18:40:41 2003 @@ -582,20 +582,26 @@ unsigned short old_sg; unsigned old_request_bufflen; unsigned char old_sc_data_direction; + unsigned char old_cmd_len; unsigned char old_cmnd[MAX_COMMAND_SIZE]; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); /* save the old command */ memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); + old_cmd_len = srb->cmd_len; /* set the command and the LUN */ + memset(srb->cmnd, 0, MAX_COMMAND_SIZE); srb->cmnd[0] = REQUEST_SENSE; srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[2] = 0; - srb->cmnd[3] = 0; srb->cmnd[4] = 18; - srb->cmnd[5] = 0; + + /* FIXME: we must do the protocol translation here */ + if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) + srb->cmd_len = 6; + else + srb->cmd_len = 12; /* set the transfer direction */ old_sc_data_direction = srb->sc_data_direction; @@ -621,6 +627,7 @@ srb->request_bufflen = old_request_bufflen; srb->use_sg = old_sg; srb->sc_data_direction = old_sc_data_direction; + srb->cmd_len = old_cmd_len; memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); if (atomic_read(&us->sm_state) == US_STATE_ABORTING) { diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile --- a/drivers/video/Makefile Sat Mar 15 18:40:40 2003 +++ b/drivers/video/Makefile Sat Mar 15 18:40:40 2003 @@ -19,6 +19,7 @@ obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_ATARI) += atafb.o +obj-$(CONFIG_FB_68328) += 68328fb.o obj-$(CONFIG_FB_ATY128) += aty128fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_RADEON) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o @@ -70,9 +71,6 @@ obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -# One by one these are being converted over to the new APIs -#obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o - obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ @@ -84,6 +82,8 @@ obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ cfbfillrect.o obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ + cfbfillrect.o +obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \ cfbfillrect.o # Files generated that shall be removed upon make clean diff -Nru a/drivers/video/bw2.c b/drivers/video/bw2.c --- a/drivers/video/bw2.c Sat Mar 15 18:40:42 2003 +++ b/drivers/video/bw2.c Sat Mar 15 18:40:42 2003 @@ -33,11 +33,11 @@ * Local functions. */ -static int bw2_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int bw2_set_par(struct fb_info *); static int bw2_blank(int, struct fb_info *); static int bw2_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int bw2_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -45,13 +45,12 @@ static struct fb_ops bw2_ops = { .owner = THIS_MODULE, - .fb_check_var = bw2_check_var, - .fb_set_par = bw2_set_par, .fb_blank = bw2_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, + .fb_ioctl = bw2_ioctl, .fb_cursor = soft_cursor, }; @@ -124,39 +123,6 @@ }; /** - * bw2_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int bw2_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * bw2_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -bw2_set_par(struct fb_info *info) -{ - return 0; -} - -/** * bw2_blank - Optional function. Blanks the display. * @blank_mode: the blank mode we want. * @info: frame buffer structure that represents a single frame buffer @@ -212,6 +178,15 @@ vma); } +static int bw2_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct bw2_par *par = (struct bw2_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUN2BW, 1, par->fbsize); +} + /* * Initialisation */ @@ -387,7 +362,6 @@ bw2_blank(0, &all->info); - bw2_set_par(&all->info); bw2_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg14.c b/drivers/video/cg14.c --- a/drivers/video/cg14.c Sat Mar 15 18:40:44 2003 +++ b/drivers/video/cg14.c Sat Mar 15 18:40:44 2003 @@ -28,8 +28,6 @@ * Local functions. */ -static int cg14_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg14_set_par(struct fb_info *); static int cg14_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); @@ -43,8 +41,6 @@ static struct fb_ops cg14_ops = { .owner = THIS_MODULE, - .fb_check_var = cg14_check_var, - .fb_set_par = cg14_set_par, .fb_setcolreg = cg14_setcolreg, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, @@ -220,39 +216,6 @@ } /** - * cg14_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg14_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg14_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg14_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg14_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -358,7 +321,8 @@ break; default: - ret = -EINVAL; + ret = sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_MDICOLOR, 24, par->fbsize); break; }; @@ -523,7 +487,6 @@ return; } - cg14_set_par(&all->info); cg14_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg3.c b/drivers/video/cg3.c --- a/drivers/video/cg3.c Sat Mar 15 18:40:42 2003 +++ b/drivers/video/cg3.c Sat Mar 15 18:40:42 2003 @@ -29,13 +29,13 @@ * Local functions. */ -static int cg3_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg3_set_par(struct fb_info *); static int cg3_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg3_blank(int, struct fb_info *); static int cg3_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg3_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -43,14 +43,13 @@ static struct fb_ops cg3_ops = { .owner = THIS_MODULE, - .fb_check_var = cg3_check_var, - .fb_set_par = cg3_set_par, .fb_setcolreg = cg3_setcolreg, .fb_blank = cg3_blank, .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, + .fb_ioctl = cg3_ioctl, .fb_cursor = soft_cursor, }; @@ -127,39 +126,6 @@ }; /** - * cg3_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg3_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg3_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg3_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg3_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -269,6 +235,15 @@ vma); } +static int cg3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct cg3_par *par = (struct cg3_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUN3COLOR, 8, par->fbsize); +} + /* * Initialisation */ @@ -445,7 +420,6 @@ return; } - cg3_set_par(&all->info); cg3_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/cg6.c b/drivers/video/cg6.c --- a/drivers/video/cg6.c Sat Mar 15 18:40:40 2003 +++ b/drivers/video/cg6.c Sat Mar 15 18:40:40 2003 @@ -29,8 +29,6 @@ * Local functions. */ -static int cg6_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int cg6_set_par(struct fb_info *); static int cg6_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int cg6_blank(int, struct fb_info *); @@ -39,6 +37,8 @@ static void cg6_fillrect(struct fb_info *, struct fb_fillrect *); static int cg6_sync(struct fb_info *); static int cg6_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int cg6_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -46,8 +46,6 @@ static struct fb_ops cg6_ops = { .owner = THIS_MODULE, - .fb_check_var = cg6_check_var, - .fb_set_par = cg6_set_par, .fb_setcolreg = cg6_setcolreg, .fb_blank = cg6_blank, .fb_fillrect = cg6_fillrect, @@ -55,6 +53,7 @@ .fb_imageblit = cg6_imageblit, .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, + .fb_ioctl = cg6_ioctl, .fb_cursor = soft_cursor, }; @@ -406,39 +405,6 @@ } /** - * cg6_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int cg6_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 8) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - return 0; -} - -/** - * cg6_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -cg6_set_par(struct fb_info *info) -{ - return 0; -} - -/** * cg6_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -535,6 +501,15 @@ vma); } +static int cg6_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct cg6_par *par = (struct cg6_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUNFAST_COLOR, 8, par->fbsize); +} + /* * Initialisation */ @@ -731,7 +706,6 @@ return; } - cg6_set_par(&all->info); cg6_init_fix(&all->info, linebytes); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c --- a/drivers/video/fbmem.c Sat Mar 15 18:40:39 2003 +++ b/drivers/video/fbmem.c Sat Mar 15 18:40:39 2003 @@ -158,6 +158,8 @@ extern int p9100_setup(char*); extern int tcx_init(void); extern int tcx_setup(char*); +extern int leo_init(void); +extern int leo_setup(char*); static struct { const char *name; @@ -269,6 +271,9 @@ #endif #ifdef CONFIG_FB_TCX { "tcx", tcx_init, tcx_setup }, +#endif +#ifdef CONFIG_FB_LEO + { "leo", leo_init, leo_setup }, #endif /* diff -Nru a/drivers/video/ffb.c b/drivers/video/ffb.c --- a/drivers/video/ffb.c Sat Mar 15 18:40:45 2003 +++ b/drivers/video/ffb.c Sat Mar 15 18:40:45 2003 @@ -20,6 +20,7 @@ #include #include #include +#include #include "sbuslib.h" @@ -27,8 +28,6 @@ * Local functions. */ -static int ffb_check_var(struct fb_var_screeninfo *, struct fb_info *); -static int ffb_set_par(struct fb_info *); static int ffb_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int ffb_blank(int, struct fb_info *); @@ -39,6 +38,8 @@ static void ffb_copyarea(struct fb_info *, struct fb_copyarea *); static int ffb_sync(struct fb_info *); static int ffb_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int ffb_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); /* * Frame buffer operations @@ -46,8 +47,6 @@ static struct fb_ops ffb_ops = { .owner = THIS_MODULE, - .fb_check_var = ffb_check_var, - .fb_set_par = ffb_set_par, .fb_setcolreg = ffb_setcolreg, .fb_blank = ffb_blank, .fb_fillrect = ffb_fillrect, @@ -55,6 +54,7 @@ .fb_imageblit = ffb_imageblit, .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, + .fb_ioctl = ffb_ioctl, /* XXX Use FFB hw cursor once fb cursor API is better understood... */ .fb_cursor = soft_cursor, @@ -673,41 +673,6 @@ } /** - * ffb_check_var - Optional function. Validates a var passed in. - * @var: frame buffer variable screen structure - * @info: frame buffer structure that represents a single frame buffer - */ -static int ffb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - if (var->bits_per_pixel != 32) - return -EINVAL; - - if (var->xres_virtual != var->xres || var->yres_virtual != var->yres) - return -EINVAL; - if (var->nonstd) - return -EINVAL; - if ((var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) - return -EINVAL; - - if (var->xres != info->var.xres || var->yres != info->var.yres) - return -EINVAL; - - ffb_fixup_var_rgb(var); - - return 0; -} - -/** - * ffb_set_par - Optional function. Alters the hardware state. - * @info: frame buffer structure that represents a single frame buffer - */ -static int -ffb_set_par(struct fb_info *info) -{ - return 0; -} - -/** * ffb_setcolreg - Optional function. Sets a color register. * @regno: boolean, 0 copy local, 1 get_user() function * @red: frame buffer colormap structure @@ -818,6 +783,15 @@ 0, vma); } +static int ffb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct ffb_par *par = (struct ffb_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_CREATOR, 24, par->fbsize); +} + /* * Initialisation */ @@ -972,7 +946,6 @@ return; } - ffb_set_par(&all->info); ffb_init_fix(&all->info); if (register_framebuffer(&all->info) < 0) { diff -Nru a/drivers/video/leo.c b/drivers/video/leo.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/video/leo.c Sat Mar 15 18:40:45 2003 @@ -0,0 +1,587 @@ +/* leo.c: LEO frame buffer driver + * + * Copyright (C) 2003 David S. Miller (davem@redhat.com) + * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) + * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) + * + * Driver layout based loosely on tgafb.c, see that file for credits. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "sbuslib.h" + +/* + * Local functions. + */ + +static int leo_setcolreg(unsigned, unsigned, unsigned, unsigned, + unsigned, struct fb_info *); +static int leo_blank(int, struct fb_info *); + +static int leo_mmap(struct fb_info *, struct file *, struct vm_area_struct *); +static int leo_ioctl(struct inode *, struct file *, unsigned int, + unsigned long, struct fb_info *); + +/* + * Frame buffer operations + */ + +static struct fb_ops leo_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = leo_setcolreg, + .fb_blank = leo_blank, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_mmap = leo_mmap, + .fb_ioctl = leo_ioctl, + .fb_cursor = soft_cursor, +}; + +#define LEO_OFF_LC_SS0_KRN 0x00200000UL +#define LEO_OFF_LC_SS0_USR 0x00201000UL +#define LEO_OFF_LC_SS1_KRN 0x01200000UL +#define LEO_OFF_LC_SS1_USR 0x01201000UL +#define LEO_OFF_LD_SS0 0x00400000UL +#define LEO_OFF_LD_SS1 0x01400000UL +#define LEO_OFF_LD_GBL 0x00401000UL +#define LEO_OFF_LX_KRN 0x00600000UL +#define LEO_OFF_LX_CURSOR 0x00601000UL +#define LEO_OFF_SS0 0x00800000UL +#define LEO_OFF_SS1 0x01800000UL +#define LEO_OFF_UNK 0x00602000UL +#define LEO_OFF_UNK2 0x00000000UL + +#define LEO_CUR_ENABLE 0x00000080 +#define LEO_CUR_UPDATE 0x00000030 +#define LEO_CUR_PROGRESS 0x00000006 +#define LEO_CUR_UPDATECMAP 0x00000003 + +#define LEO_CUR_TYPE_MASK 0x00000000 +#define LEO_CUR_TYPE_IMAGE 0x00000020 +#define LEO_CUR_TYPE_CMAP 0x00000050 + +struct leo_cursor { + u8 xxx0[16]; + volatile u32 cur_type; + volatile u32 cur_misc; + volatile u32 cur_cursxy; + volatile u32 cur_data; +}; + +#define LEO_KRN_TYPE_CLUT0 0x00001000 +#define LEO_KRN_TYPE_CLUT1 0x00001001 +#define LEO_KRN_TYPE_CLUT2 0x00001002 +#define LEO_KRN_TYPE_WID 0x00001003 +#define LEO_KRN_TYPE_UNK 0x00001006 +#define LEO_KRN_TYPE_VIDEO 0x00002003 +#define LEO_KRN_TYPE_CLUTDATA 0x00004000 +#define LEO_KRN_CSR_ENABLE 0x00000008 +#define LEO_KRN_CSR_PROGRESS 0x00000004 +#define LEO_KRN_CSR_UNK 0x00000002 +#define LEO_KRN_CSR_UNK2 0x00000001 + +struct leo_lx_krn { + volatile u32 krn_type; + volatile u32 krn_csr; + volatile u32 krn_value; +}; + +struct leo_lc_ss0_krn { + volatile u32 misc; + u8 xxx0[0x800-4]; + volatile u32 rev; +}; + +struct leo_lc_ss0_usr { + volatile u32 csr; + volatile u32 addrspace; + volatile u32 fontmsk; + volatile u32 fontt; + volatile u32 extent; + volatile u32 src; + u32 dst; + volatile u32 copy; + volatile u32 fill; +}; + +struct leo_lc_ss1_krn { + u8 unknown; +}; + +struct leo_lc_ss1_usr { + u8 unknown; +}; + +struct leo_ld { + u8 xxx0[0xe00]; + volatile u32 csr; + volatile u32 wid; + volatile u32 wmask; + volatile u32 widclip; + volatile u32 vclipmin; + volatile u32 vclipmax; + volatile u32 pickmin; /* SS1 only */ + volatile u32 pickmax; /* SS1 only */ + volatile u32 fg; + volatile u32 bg; + volatile u32 src; /* Copy/Scroll (SS0 only) */ + volatile u32 dst; /* Copy/Scroll/Fill (SS0 only) */ + volatile u32 extent; /* Copy/Scroll/Fill size (SS0 only) */ + u32 xxx1[3]; + volatile u32 setsem; /* SS1 only */ + volatile u32 clrsem; /* SS1 only */ + volatile u32 clrpick; /* SS1 only */ + volatile u32 clrdat; /* SS1 only */ + volatile u32 alpha; /* SS1 only */ + u8 xxx2[0x2c]; + volatile u32 winbg; + volatile u32 planemask; + volatile u32 rop; + volatile u32 z; + volatile u32 dczf; /* SS1 only */ + volatile u32 dczb; /* SS1 only */ + volatile u32 dcs; /* SS1 only */ + volatile u32 dczs; /* SS1 only */ + volatile u32 pickfb; /* SS1 only */ + volatile u32 pickbb; /* SS1 only */ + volatile u32 dcfc; /* SS1 only */ + volatile u32 forcecol; /* SS1 only */ + volatile u32 door[8]; /* SS1 only */ + volatile u32 pick[5]; /* SS1 only */ +}; + +#define LEO_SS1_MISC_ENABLE 0x00000001 +#define LEO_SS1_MISC_STEREO 0x00000002 +struct leo_ld_ss1 { + u8 xxx0[0xef4]; + volatile u32 ss1_misc; +}; + +struct leo_ld_gbl { + u8 unknown; +}; + +struct leo_par { + spinlock_t lock; + struct leo_lx_krn *lx_krn; + struct leo_lc_ss0_usr *lc_ss0_usr; + struct leo_ld_ss0 *ld_ss0; + struct leo_ld_ss1 *ld_ss1; + struct leo_cursor *cursor; + u32 extent; + u32 clut_data[256]; + + u32 flags; +#define LEO_FLAG_BLANKED 0x00000001 + + unsigned long physbase; + unsigned long fbsize; + + struct sbus_dev *sdev; + struct list_head list; +}; + +static void leo_wait(struct leo_lx_krn *lx_krn) +{ + int i; + + for (i = 0; + (sbus_readl(&lx_krn->krn_csr) & LEO_KRN_CSR_PROGRESS) && i < 300000; + i++) + udelay (1); /* Busy wait at most 0.3 sec */ + return; +} + +/** + * leo_setcolreg - Optional function. Sets a color register. + * @regno: boolean, 0 copy local, 1 get_user() function + * @red: frame buffer colormap structure + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure + */ +static int leo_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + unsigned long flags; + u32 val; + int i; + + if (regno >= 256) + return 1; + + red >>= 8; + green >>= 8; + blue >>= 8; + + par->clut_data[regno] = red | (green << 8) | (blue << 16); + + spin_lock_irqsave(&par->lock, flags); + + leo_wait(lx_krn); + + sbus_writel(LEO_KRN_TYPE_CLUTDATA, &lx_krn->krn_type); + for (i = 0; i < 256; i++) + sbus_writel(par->clut_data[i], &lx_krn->krn_value); + sbus_writel(LEO_KRN_TYPE_CLUT0, &lx_krn->krn_type); + + val = sbus_readl(&lx_krn->krn_csr); + val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); + sbus_writel(val, &lx_krn->krn_csr); + + spin_unlock_irqrestore(&par->lock, flags); + + return 0; +} + +/** + * leo_blank - Optional function. Blanks the display. + * @blank_mode: the blank mode we want. + * @info: frame buffer structure that represents a single frame buffer + */ +static int leo_blank(int blank, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + unsigned long flags; + u32 val; + + spin_lock_irqsave(&par->lock, flags); + + switch (blank) { + case 0: /* Unblanking */ + val = sbus_readl(&lx_krn->krn_csr); + val |= LEO_KRN_CSR_ENABLE; + sbus_writel(val, &lx_krn->krn_csr); + par->flags &= ~LEO_FLAG_BLANKED; + break; + + case 1: /* Normal blanking */ + case 2: /* VESA blank (vsync off) */ + case 3: /* VESA blank (hsync off) */ + case 4: /* Poweroff */ + val = sbus_readl(&lx_krn->krn_csr); + val &= ~LEO_KRN_CSR_ENABLE; + sbus_writel(val, &lx_krn->krn_csr); + par->flags |= LEO_FLAG_BLANKED; + break; + } + + spin_unlock_irqrestore(&par->lock, flags); + + return 0; +} + +static struct sbus_mmap_map leo_mmap_map[] = { + { LEO_SS0_MAP, LEO_OFF_SS0, 0x800000 }, + { LEO_LC_SS0_USR_MAP, LEO_OFF_LC_SS0_USR, 0x1000 }, + { LEO_LD_SS0_MAP, LEO_OFF_LD_SS0, 0x1000 }, + { LEO_LX_CURSOR_MAP, LEO_OFF_LX_CURSOR, 0x1000 }, + { LEO_SS1_MAP, LEO_OFF_SS1, 0x800000 }, + { LEO_LC_SS1_USR_MAP, LEO_OFF_LC_SS1_USR, 0x1000 }, + { LEO_LD_SS1_MAP, LEO_OFF_LD_SS1, 0x1000 }, + { LEO_UNK_MAP, LEO_OFF_UNK, 0x1000 }, + { LEO_LX_KRN_MAP, LEO_OFF_LX_KRN, 0x1000 }, + { LEO_LC_SS0_KRN_MAP, LEO_OFF_LC_SS0_KRN, 0x1000 }, + { LEO_LC_SS1_KRN_MAP, LEO_OFF_LC_SS1_KRN, 0x1000 }, + { LEO_LD_GBL_MAP, LEO_OFF_LD_GBL, 0x1000 }, + { LEO_UNK2_MAP, LEO_OFF_UNK2, 0x100000 }, + { 0, 0, 0 } +}; + +static int leo_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma) +{ + struct leo_par *par = (struct leo_par *)info->par; + + return sbusfb_mmap_helper(leo_mmap_map, + par->physbase, par->fbsize, + par->sdev->reg_addrs[0].which_io, + vma); +} + +static int leo_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + + return sbusfb_ioctl_helper(cmd, arg, info, + FBTYPE_SUNLEO, 32, par->fbsize); +} + +/* + * Initialisation + */ + +static void +leo_init_fix(struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *)info->par; + + strncpy(info->fix.id, par->sdev->prom_name, sizeof(info->fix.id) - 1); + info->fix.id[sizeof(info->fix.id)-1] = 0; + + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.visual = FB_VISUAL_TRUECOLOR; + + info->fix.line_length = 8192; + + info->fix.accel = FB_ACCEL_SUN_LEO; +} + +static void leo_wid_put(struct fb_info *info, struct fb_wid_list *wl) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_lx_krn *lx_krn = par->lx_krn; + struct fb_wid_item *wi; + unsigned long flags; + u32 val; + int i, j; + + spin_lock_irqsave(&par->lock, flags); + + leo_wait(lx_krn); + + for (i = 0, wi = wl->wl_list; i < wl->wl_count; i++, wi++) { + switch(wi->wi_type) { + case FB_WID_DBL_8: + j = (wi->wi_index & 0xf) + 0x40; + break; + + case FB_WID_DBL_24: + j = wi->wi_index & 0x3f; + break; + + default: + continue; + }; + sbus_writel(0x5800 + j, &lx_krn->krn_type); + sbus_writel(wi->wi_values[0], &lx_krn->krn_value); + } + sbus_writel(LEO_KRN_TYPE_WID, &lx_krn->krn_type); + + val = sbus_readl(&lx_krn->krn_csr); + val |= (LEO_KRN_CSR_UNK | LEO_KRN_CSR_UNK2); + sbus_writel(val, &lx_krn->krn_csr); + + spin_unlock_irqrestore(&par->lock, flags); +} + +static void leo_init_wids(struct fb_info *info) +{ + struct fb_wid_item wi; + struct fb_wid_list wl; + + wl.wl_count = 1; + wl.wl_list = &wi; + wi.wi_type = FB_WID_DBL_8; + wi.wi_index = 0; + wi.wi_values [0] = 0x2c0; + leo_wid_put(info, &wl); + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put(info, &wl); + wi.wi_index = 2; + wi.wi_values [0] = 0x20; + leo_wid_put(info, &wl); + wi.wi_type = FB_WID_DBL_24; + wi.wi_index = 1; + wi.wi_values [0] = 0x30; + leo_wid_put(info, &wl); + +} + +static void leo_init_hw(struct fb_info *info) +{ + struct leo_par *par = (struct leo_par *) info->par; + struct leo_ld *ss = (struct leo_ld *) par->ld_ss0; + u32 val; + + val = sbus_readl(&par->ld_ss1->ss1_misc); + val |= LEO_SS1_MISC_ENABLE; + sbus_writel(val, &par->ld_ss1->ss1_misc); + + par->extent = ((info->var.xres - 1) | + ((info->var.yres - 1) << 16)); + + sbus_writel(0xffffffff, &ss->wid); + sbus_writel(0xffff, &ss->wmask); + sbus_writel(0, &ss->vclipmin); + sbus_writel(par->extent, &ss->vclipmax); + sbus_writel(0, &ss->fg); + sbus_writel(0xff000000, &ss->planemask); + sbus_writel(0x310850, &ss->rop); + sbus_writel(0, &ss->widclip); + sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), + &par->lc_ss0_usr->extent); + sbus_writel(4, &par->lc_ss0_usr->addrspace); + sbus_writel(0x80000000, &par->lc_ss0_usr->fill); + sbus_writel(0, &par->lc_ss0_usr->fontt); + do { + val = sbus_readl(&par->lc_ss0_usr->csr); + } while (val & 0x20000000); +} + +static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) +{ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; +} + +struct all_info { + struct fb_info info; + struct leo_par par; + struct list_head list; +}; +static LIST_HEAD(leo_list); + +static void leo_init_one(struct sbus_dev *sdev) +{ + struct all_info *all; + int linebytes; + + all = kmalloc(sizeof(*all), GFP_KERNEL); + if (!all) { + printk(KERN_ERR "leo: Cannot allocate memory.\n"); + return; + } + memset(all, 0, sizeof(*all)); + + INIT_LIST_HEAD(&all->list); + + spin_lock_init(&all->par.lock); + all->par.sdev = sdev; + + all->par.physbase = sdev->reg_addrs[0].phys_addr; + + sbusfb_fill_var(&all->info.var, sdev->prom_node, 32); + leo_fixup_var_rgb(&all->info.var); + + linebytes = prom_getintdefault(sdev->prom_node, "linebytes", + all->info.var.xres); + all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + +#ifdef CONFIG_SPARC32 + all->info.screen_base = (char *) + prom_getintdefault(sdev->prom_node, "address", 0); +#endif + if (!all->info.screen_base) + all->info.screen_base = (char *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_SS0, + 0x800000, "leo ram"); + + all->par.lc_ss0_usr = (struct leo_lc_ss0_usr *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LC_SS0_USR, + 0x1000, "leolc ss0usr"); + all->par.ld_ss0 = (struct leo_ld_ss0 *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS0, + 0x1000, "leold ss0"); + all->par.ld_ss1 = (struct leo_ld_ss1 *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LD_SS1, + 0x1000, "leold ss1"); + all->par.lx_krn = (struct leo_lx_krn *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_KRN, + 0x1000, "leolx krn"); + all->par.cursor = (struct leo_cursor *) + sbus_ioremap(&sdev->resource[0], LEO_OFF_LX_CURSOR, + sizeof(struct leo_cursor), "leolx cursor"); + + all->info.node = NODEV; + all->info.flags = FBINFO_FLAG_DEFAULT; + all->info.fbops = &leo_ops; + all->info.currcon = -1; + all->info.par = &all->par; + + leo_init_wids(&all->info); + leo_init_hw(&all->info); + + leo_blank(0, &all->info); + + if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { + printk(KERN_ERR "leo: Could not allocate color map.\n"); + kfree(all); + return; + } + + leo_init_fix(&all->info); + + if (register_framebuffer(&all->info) < 0) { + printk(KERN_ERR "leo: Could not register framebuffer.\n"); + fb_dealloc_cmap(&all->info.cmap); + kfree(all); + return; + } + + list_add(&all->list, &leo_list); + + printk("leo: %s at %lx:%lx\n", + sdev->prom_name, + (long) sdev->reg_addrs[0].which_io, + (long) sdev->reg_addrs[0].phys_addr); +} + +int __init leo_init(void) +{ + struct sbus_bus *sbus; + struct sbus_dev *sdev; + + for_all_sbusdev(sdev, sbus) { + if (!strcmp(sdev->prom_name, "leo")) + leo_init_one(sdev); + } + + return 0; +} + +void __exit leo_exit(void) +{ + struct list_head *pos, *tmp; + + list_for_each_safe(pos, tmp, &leo_list) { + struct all_info *all = list_entry(pos, typeof(*all), list); + + unregister_framebuffer(&all->info); + fb_dealloc_cmap(&all->info.cmap); + kfree(all); + } +} + +int __init +leo_setup(char *arg) +{ + /* No cmdline options yet... */ + return 0; +} + +#ifdef MODULE +module_init(leo_init); +module_exit(leo_exit); +#endif + +MODULE_DESCRIPTION("framebuffer driver for LEO chipsets"); +MODULE_AUTHOR("David S. Miller "); +MODULE_LICENSE("GPL"); diff -Nru a/drivers/video/leofb.c b/drivers/video/leofb.c --- a/drivers/video/leofb.c Sat Mar 15 18:40:45 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,764 +0,0 @@ -/* $Id: leofb.c,v 1.14 2001/10/16 05:44:44 davem Exp $ - * leofb.c: Leo (ZX) 24/8bit frame buffer driver - * - * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz) - * Copyright (C) 1997 Michal Rehacek (Michal.Rehacek@st.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include