# 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.1160 # arch/sparc/Kconfig 1.10 -> 1.11 # drivers/video/fbmem.c 1.58 -> 1.59 # 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 # drivers/block/ps2esdi.c 1.61 -> 1.62 # fs/cifs/file.c 1.9 -> 1.12 # include/linux/kernel.h 1.33 -> 1.34 # drivers/ide/pci/via82cxxx.c 1.9 -> 1.10 # drivers/ide/legacy/hd.c 1.17 -> 1.18 # drivers/scsi/sym53c8xx_2/sym_hipd.c 1.6 -> 1.7 # 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 # drivers/scsi/scsi_error.c 1.38 -> 1.40 # include/asm-ia64/topology.h 1.6 -> 1.7 # drivers/isdn/hisax/saphir.c 1.26 -> 1.27 # arch/ia64/kernel/palinfo.c 1.10 -> 1.12 # drivers/char/vme_scc.c 1.10 -> 1.11 # drivers/ide/ide-taskfile.c 1.11 -> 1.12 # kernel/ksyms.c 1.185 -> 1.187 # drivers/cdrom/gscd.c 1.30 -> 1.31 # arch/arm/kernel/entry-common.S 1.12 -> 1.13 # drivers/oprofile/cpu_buffer.c 1.5 -> 1.6 # arch/arm/mach-sa1100/cpu-sa1110.c 1.17 -> 1.19 # 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 # net/ipv4/xfrm_input.c 1.4 -> 1.5 # 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 # include/linux/mm.h 1.108 -> 1.109 # fs/file_table.c 1.17 -> 1.18 # include/linux/init.h 1.24 -> 1.25 # arch/sparc/kernel/irq.c 1.20 -> 1.21 # drivers/serial/8250.c 1.29 -> 1.30 # drivers/net/dgrs.c 1.14 -> 1.15 # arch/x86_64/vmlinux.lds.S 1.13 -> 1.14 # 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 # arch/i386/oprofile/op_model_p4.c 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 # 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/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 # arch/sparc/vmlinux.lds.S 1.14 -> 1.15 # include/asm-ia64/spinlock.h 1.6 -> 1.7 # net/x25/x25_timer.c 1.9 -> 1.10 # drivers/parport/ieee1284.c 1.5 -> 1.6 # arch/alpha/kernel/core_marvel.c 1.7 -> 1.8 # arch/mips64/sgi-ip22/ip22-int.c 1.6 -> 1.7 # include/linux/netfilter_bridge/ebt_mark_t.h 1.1 -> 1.2 # drivers/isdn/hisax/avm_a1.c 1.23 -> 1.24 # kernel/fork.c 1.111 -> 1.112 # include/linux/sched.h 1.136 -> 1.137 # drivers/isdn/hisax/s0box.c 1.25 -> 1.26 # include/asm-ia64/machvec_hpzx1.h 1.4 -> 1.5 # drivers/block/ll_rw_blk.c 1.155 -> 1.156 # Makefile 1.392 -> 1.394 # drivers/cpufreq/userspace.c 1.1 -> 1.2 # net/bridge/netfilter/ebt_log.c 1.2 -> 1.3 # drivers/video/Makefile 1.76 -> 1.77 # include/asm-ia64/unistd.h 1.23 -> 1.25 # drivers/isdn/hisax/hisax_fcclassic.c 1.2 -> 1.3 # drivers/base/platform.c 1.6 -> 1.7 # include/net/tcp.h 1.30 -> 1.31 # include/asm-ia64/page.h 1.14 -> 1.15 # drivers/serial/amba.c 1.16 -> 1.17 # drivers/net/wan/sdla_ft1.c 1.5 -> 1.6 # drivers/atm/firestream.c 1.16 -> 1.17 # 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 # net/ipv4/af_inet.c 1.38 -> 1.39 # arch/ia64/kernel/setup.c 1.36 -> 1.37 # drivers/serial/sa1100.c 1.18 -> 1.19 # arch/mips/kernel/irq.c 1.8 -> 1.9 # fs/proc/proc_misc.c 1.67 -> 1.68 # drivers/s390/char/sclp_tty.c 1.4 -> 1.5 # drivers/block/cpqarray.c 1.70 -> 1.71 # include/asm-i386/bug.h 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/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.24 # drivers/cdrom/sbpcd.c 1.41 -> 1.42 # arch/ppc/boot/simple/rw4/ppc_40x.h 1.2 -> 1.3 # net/ipv4/udp.c 1.30 -> 1.31 # net/bridge/netfilter/ebt_snat.c 1.1 -> 1.2 # arch/ia64/sn/kernel/mca.c 1.3 -> 1.4 # scripts/modpost.c 1.9 -> 1.10 # arch/i386/vmlinux.lds.S 1.25 -> 1.26 # drivers/net/wan/sdla_ppp.c 1.21 -> 1.22 # arch/parisc/vmlinux.lds.S 1.11 -> 1.12 # drivers/serial/anakin.c 1.13 -> 1.14 # kernel/cpufreq.c 1.21 -> 1.22 # drivers/acorn/block/mfmhd.c 1.48 -> 1.49 # arch/ia64/kernel/time.c 1.13.1.1 -> 1.16 # include/asm-sparc64/termios.h 1.4 -> 1.5 # 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 # 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.39 # drivers/net/wan/sdladrv.c 1.6 -> 1.7 # drivers/usb/core/message.c 1.21 -> 1.22 # drivers/media/video/bw-qcam.c 1.10 -> 1.11 # drivers/net/wan/comx-hw-munich.c 1.8 -> 1.9 # net/bluetooth/sco.c 1.11 -> 1.12 # 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 # drivers/cdrom/optcd.c 1.24 -> 1.25 # net/x25/x25_subr.c 1.8 -> 1.9 # arch/sparc64/kernel/pci_common.c 1.17 -> 1.18 # drivers/scsi/sr.c 1.72 -> 1.73 # net/key/af_key.c 1.21 -> 1.24 # 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.224 # 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 # 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 # drivers/video/cg6.c 1.1 -> 1.4 # drivers/isdn/hisax/isdnl1.c 1.15 -> 1.16 # include/asm-ia64/machvec_dig.h 1.2 -> 1.3 # drivers/char/rio/rioinit.c 1.4 -> 1.5 # drivers/md/md.c 1.143 -> 1.145 # drivers/serial/clps711x.c 1.13 -> 1.14 # fs/cifs/transport.c 1.5 -> 1.6 # arch/mips64/Kconfig 1.9 -> 1.10 # arch/alpha/kernel/core_titan.c 1.13 -> 1.14 # include/asm-alpha/pgtable.h 1.16 -> 1.17 # drivers/video/sbuslib.c 1.1 -> 1.3 # 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 # drivers/scsi/inia100.c 1.18 -> 1.19 # 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 # drivers/usb/serial/visor.c 1.58 -> 1.59 # drivers/char/rio/riocmd.c 1.6 -> 1.7 # 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.36 # include/asm-ia64/posix_types.h 1.1 -> 1.2 # 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 # arch/sparc64/defconfig 1.75 -> 1.76 # drivers/acorn/block/fd1772.c 1.32 -> 1.33 # 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/isdn/hisax/avm_pci.c 1.41 -> 1.42 # drivers/ide/ide-iops.c 1.7 -> 1.8 # fs/namei.c 1.65 -> 1.66 # net/decnet/dn_nsp_in.c 1.7 -> 1.8 # net/bridge/netfilter/ebtables.c 1.4 -> 1.5 # arch/arm/vmlinux-armv.lds.in 1.21 -> 1.22 # fs/intermezzo/fileset.c 1.2 -> 1.3 # arch/sh/kernel/irq.c 1.10 -> 1.11 # arch/i386/Makefile 1.47 -> 1.48 # include/asm-ia64/processor.h 1.30 -> 1.31 # arch/s390/vmlinux.lds.S 1.9 -> 1.10 # 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 # 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.15 # 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 # 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 # drivers/isdn/hisax/niccy.c 1.27 -> 1.28 # 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 # drivers/serial/uart00.c 1.12 -> 1.13 # arch/i386/boot/Makefile 1.23 -> 1.24 # drivers/char/rtc.c 1.22 -> 1.23 # arch/um/kernel/mem.c 1.12 -> 1.14 # net/netsyms.c 1.50 -> 1.52 # include/linux/efs_fs.h 1.8 -> 1.9 # drivers/usb/serial/usb-serial.c 1.72 -> 1.73 # drivers/char/rio/rioctrl.c 1.7 -> 1.8 # 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 # include/asm-s390x/pgtable.h 1.15 -> 1.17 # fs/sysfs/dir.c 1.2 -> 1.3 # drivers/isdn/hisax/hfc_pci.c 1.40 -> 1.41 # arch/x86_64/kernel/irq.c 1.9 -> 1.10 # drivers/serial/mcfserial.c 1.3 -> 1.4 # 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/char/serial167.c 1.14 -> 1.15 # arch/ppc64/kernel/irq.c 1.20 -> 1.21 # drivers/net/wan/pc300_tty.c 1.6 -> 1.7 # 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/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 # drivers/usb/core/hub.c 1.56 -> 1.57 # drivers/block/amiflop.c 1.35 -> 1.36 # drivers/cdrom/mcdx.c 1.29 -> 1.30 # drivers/block/genhd.c 1.71 -> 1.73 # 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 # 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/mips/Kconfig 1.8 -> 1.9 # arch/um/drivers/ubd_kern.c 1.26 -> 1.27 # arch/arm/mach-integrator/cpu.c 1.13 -> 1.15 # drivers/mtd/mtdblock_ro.c 1.23 -> 1.24 # 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 # include/linux/netfilter_ipv4/ipchains_core.h 1.1 -> 1.2 # include/linux/hugetlb.h 1.13 -> 1.15 # arch/ia64/kernel/machvec.c 1.3 -> 1.4 # drivers/net/wan/sdla_chdlc.c 1.19 -> 1.20 # drivers/ide/ide-floppy.c 1.25 -> 1.26 # net/econet/af_econet.c 1.13 -> 1.14 # drivers/media/video/zr36120.c 1.17 -> 1.18 # fs/sysfs/bin.c 1.2 -> 1.3 # 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.22 # net/rose/af_rose.c 1.18 -> 1.19 # 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.19 # include/asm-arm/arch-anakin/time.h 1.3 -> 1.4 # arch/i386/boot/tools/build.c 1.2 -> 1.3 # 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 # drivers/s390/char/sclp_con.c 1.3 -> 1.4 # drivers/usb/core/usb.c 1.115 -> 1.116 # arch/mips64/sgi-ip27/ip27-irq.c 1.6 -> 1.7 # arch/ia64/mm/hugetlbpage.c 1.9 -> 1.10 # arch/s390x/Kconfig 1.8 -> 1.9 # drivers/scsi/i91uscsi.h 1.3 -> 1.4 # arch/alpha/vmlinux.lds.S 1.18 -> 1.20 # 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 # arch/mips/kernel/old-irq.c 1.5 -> 1.6 # include/asm-alpha/core_cia.h 1.5 -> 1.6 # arch/arm/Kconfig 1.9 -> 1.12 # drivers/isdn/hisax/gazel.c 1.31 -> 1.32 # drivers/isdn/hisax/isurf.c 1.22 -> 1.23 # include/asm-ia64/intrinsics.h 1.3 -> 1.4 # 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 # 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 # arch/ppc64/Kconfig 1.13 -> 1.14 # mm/mremap.c 1.28 -> 1.29 # 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.19 # usr/Makefile 1.4 -> 1.5 # include/linux/list.h 1.21 -> 1.22 # scripts/Makefile.modpost 1.2 -> 1.3 # arch/sh/vmlinux.lds.S 1.9 -> 1.10 # net/ipv4/raw.c 1.27 -> 1.28 # net/ipv6/tcp_ipv6.c 1.38 -> 1.40 # drivers/pcmcia/tcic.c 1.15 -> 1.16 # 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 # 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 # arch/ia64/kernel/sys_ia64.c 1.20 -> 1.21 # drivers/block/loop.c 1.82 -> 1.83 # arch/ia64/kernel/signal.c 1.20 -> 1.21 # Documentation/ia64/fsys.txt 1.4 -> 1.5 # net/ipv4/esp.c 1.13 -> 1.15 # drivers/ide/ide-probe.c 1.32 -> 1.33 # 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.64 # drivers/video/bw2.c 1.1 -> 1.4 # arch/m68k/Kconfig 1.9 -> 1.10 # 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 # MAINTAINERS 1.126 -> 1.127 # 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 # usr/gen_init_cpio.c 1.2 -> 1.3 # net/bridge/netfilter/ebt_dnat.c 1.1 -> 1.2 # 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 # drivers/block/rd.c 1.68 -> 1.69 # drivers/char/raw.c 1.28 -> 1.29 # drivers/cdrom/mcd.c 1.29 -> 1.30 # mm/mmap.c 1.72 -> 1.74 # include/linux/netfilter_bridge/ebt_redirect.h 1.1 -> 1.2 # fs/ext2/xattr.c 1.9 -> 1.10 # net/unix/af_unix.c 1.35 -> 1.36 # include/asm-i386/mach-summit/mach_apic.h 1.20 -> 1.21 # drivers/net/pppoe.c 1.21 -> 1.22 # drivers/hotplug/cpci_hotplug_pci.c 1.6 -> 1.7 # fs/intermezzo/file.c 1.8 -> 1.9 # drivers/video/cg3.c 1.1 -> 1.4 # net/bluetooth/rfcomm/sock.c 1.12 -> 1.13 # 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 # drivers/net/eepro100.c 1.57 -> 1.58 # init/do_mounts.h 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 # 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 # include/asm-ia64/machvec_sn1.h 1.5 -> 1.6 # net/packet/af_packet.c 1.18 -> 1.19 # drivers/block/paride/pf.c 1.37 -> 1.38 # mm/page-writeback.c 1.56 -> 1.57 # net/sunrpc/xprt.c 1.50 -> 1.51 # net/ipv4/tcp_output.c 1.23 -> 1.24 # net/bluetooth/l2cap.c 1.18 -> 1.19 # 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 # arch/m68knommu/Kconfig 1.6 -> 1.7 # include/linux/netfilter_bridge/ebt_ip.h 1.2 -> 1.3 # arch/arm/kernel/time.c 1.14 -> 1.15 # arch/ia64/mm/tlb.c 1.14 -> 1.15 # include/linux/ipv6.h 1.3 -> 1.4 # drivers/pci/probe.c 1.30 -> 1.33 # init/do_mounts_rd.c 1.1 -> 1.2 # drivers/video/p9100.c 1.1 -> 1.4 # drivers/message/i2o/i2o_block.c 1.51 -> 1.52 # drivers/usb/host/ohci-pci.c 1.9 -> 1.10 # drivers/net/shaper.c 1.12 -> 1.13 # arch/mips64/mips-boards/malta/malta_int.c 1.3 -> 1.4 # arch/i386/kernel/numaq.c 1.6 -> 1.8 # include/asm-x86_64/pgtable.h 1.13 -> 1.15 # net/ipv4/xfrm_state.c 1.9 -> 1.11 # net/core/skbuff.c 1.19 -> 1.20 # 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.31 # 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 # net/core/sock.c 1.14 -> 1.16 # include/asm-m68k/sun3_pgtable.h 1.3 -> 1.4 # net/ipv6/ip6_input.c 1.6 -> 1.7 # include/asm-i386/pgtable.h 1.26 -> 1.30 # drivers/isdn/hisax/mic.c 1.26 -> 1.27 # drivers/s390/block/xpram.c 1.35 -> 1.36 # 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.104 # 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.23 # arch/ppc64/vmlinux.lds.S 1.12 -> 1.13 # include/asm-arm/proc-armv/tlbflush.h 1.2 -> 1.3 # sound/oss/trident.c 1.35 -> 1.36 # net/ipv6/Makefile 1.9 -> 1.10 # 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 # drivers/s390/block/dasd_genhd.c 1.21 -> 1.22 # arch/v850/kernel/irq.c 1.5 -> 1.6 # mm/slab.c 1.65 -> 1.68 # arch/alpha/kernel/irq.c 1.18 -> 1.19 # drivers/md/dm.c 1.16 -> 1.17 # 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.168 # drivers/media/video/planb.c 1.12 -> 1.13 # drivers/block/paride/pd.c 1.46 -> 1.47 # arch/ia64/kernel/sigframe.h 1.3 -> 1.4 # include/asm-i386/pgtable-3level.h 1.10 -> 1.11 # init/Kconfig 1.10 -> 1.11 # 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 # arch/ppc/kernel/irq.c 1.23 -> 1.24 # 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 # net/ipv6/udp.c 1.18 -> 1.19 # drivers/net/eth16i.c 1.12 -> 1.13 # include/net/xfrm.h 1.13 -> 1.16 # fs/sysfs/mount.c 1.5 -> 1.6 # drivers/s390/block/dasd_3990_erp.c 1.11 -> 1.12 # arch/ia64/vmlinux.lds.S 1.27 -> 1.28 # 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 # 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/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 # arch/m68k/vmlinux-std.lds 1.14 -> 1.15 # arch/arm/mach-integrator/Makefile 1.6 -> 1.7 # drivers/pcmcia/i82365.c 1.23 -> 1.24 # 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 # fs/ext3/super.c 1.51 -> 1.52 # arch/arm/kernel/Makefile 1.15 -> 1.16 # arch/ia64/tools/print_offsets.c 1.13 -> 1.16 # fs/cifs/connect.c 1.11 -> 1.13 # drivers/cdrom/cm206.c 1.29 -> 1.30 # drivers/pci/Makefile 1.23 -> 1.24 # arch/arm/common/sa1111.c 1.22 -> 1.23 # fs/partitions/check.c 1.95 -> 1.96 # arch/cris/Kconfig 1.5 -> 1.6 # include/asm-ia64/siginfo.h 1.11 -> 1.12 # net/ax25/af_ax25.c 1.17 -> 1.18 # 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 # fs/intermezzo/methods.c 1.6 -> 1.7 # 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.7 # drivers/isdn/hisax/diva.c 1.39 -> 1.40 # fs/locks.c 1.37 -> 1.38 # drivers/isdn/hisax/hfcscard.c 1.15 -> 1.16 # 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 # drivers/video/cg14.c 1.1 -> 1.4 # net/x25/af_x25.c 1.21 -> 1.22 # include/asm-ia64/sal.h 1.12 -> 1.14 # drivers/isdn/hisax/ix1_micro.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 # 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 # 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 # 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 # 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.17 # 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/mips64/mips-boards/atlas/atlas_int.c 1.3 -> 1.4 # net/ipv4/igmp.c 1.13 -> 1.14 # 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 # 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 # 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 # drivers/isdn/hisax/teles3.c 1.25 -> 1.26 # drivers/block/umem.c 1.34 -> 1.35 # arch/mips/arc/arc_con.c 1.1 -> 1.2 # net/appletalk/ddp.c 1.16 -> 1.17 # 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.21 # drivers/net/wan/wanpipe_multppp.c 1.11 -> 1.12 # drivers/isdn/hisax/teleint.c 1.19 -> 1.20 # include/asm-ia64/thread_info.h 1.6 -> 1.8 # arch/arm/mach-sa1100/Makefile 1.24 -> 1.26 # 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/arm/mach-sa1100/Kconfig 1.3 -> 1.4 # include/asm-ia64/mmzone.h 1.3 -> 1.4 # fs/block_dev.c 1.122 -> 1.123 # include/asm-sh/pgtable.h 1.13 -> 1.16 # arch/i386/mm/pgtable.c 1.8 -> 1.9 # arch/ia64/kernel/unwind.c 1.11 -> 1.16 # 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 # 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.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 include/asm-ia64/sn/pci/pic.h # (new) -> 1.1 arch/ia64/sn/io/sn2/shub.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 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/ia64/sn/io/sn2/l1.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 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 include/asm-ia64/sn/sn2/geo.h # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/03/04 torvalds@home.transmeta.com 1.1068.1.17 # Linux 2.5.64 # -------------------------------------------- # 03/03/05 davem@redhat.com 1.1068.1.18 # [PATCH] Fix time comparison typing bugs. # # Many places use inappropriate types for comparing jiffies, # int for example. Fix those places up. # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.1.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.1.20 # [SPARC64]: Fix cpufreq config deps. # -------------------------------------------- # 03/03/05 Jeff.Wiedemeier@hp.com 1.1025.20.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.8.1 # [PATCH] USB: add support for Treo devices to the visor driver. # # Finally... # -------------------------------------------- # 03/03/05 clemens@ladisch.de 1.1068.8.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.8.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.1.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.8.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.1.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/05 mochel@osdl.org 1.1068.9.1 # sysfs: Make sure root inode is executable and readable by everyone. # -------------------------------------------- # 03/03/05 mochel@osdl.org 1.1068.9.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.9.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.9.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.1.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.10.1 # Merge bk://ldm.bkbits.net/linux-2.5-core # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/05 kai@tp1.ruhr-uni-bochum.de 1.1068.11.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.11.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.11.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.11.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.11.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.11.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.10.2 # [KERNEL]: Add typecheck macro for verifying types at compile time. # -------------------------------------------- # 03/03/05 davem@nuts.ninka.net 1.1068.10.3 # [JIFFIES]: Use typecheck in time_foo jiffies macros. # -------------------------------------------- # 03/03/05 torvalds@home.transmeta.com 1.1068.10.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 rmk@flint.arm.linux.org.uk 1.1060.3.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.3.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.3.3 # [ARM] Always call schedule_tail() after a fork() # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.4 # [ARM] Always claim the timer IRQ using SA_INTERRUPT. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.5 # [ARM] Add new kernel typedefs for __kernel_{timer,clockid}_t. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.6 # [ARM] Add dummy set_pgd() implementation. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.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.3.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.3.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.3.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.3.11 # [ARM] Update mach-types to latest vesion. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.12 # [ARM] Ensure we preserve other CPSR bits when switching to SVC mode. # -------------------------------------------- # 03/03/06 rmk@flint.arm.linux.org.uk 1.1060.3.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.3.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.3.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.3.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.20.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 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.3.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 rmk@flint.arm.linux.org.uk 1.1060.3.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.10.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.1076 # 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.1.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.1077 # Merge # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.12.1 # ia64: Sync with 2.5.64. # -------------------------------------------- # 03/03/06 davidm@tiger.hpl.hp.com 1.1068.12.2 # ia64: Correct the value of siginfo.si_addr for SIGSEGV signals # triggered by NaT-page-consumption faults. # -------------------------------------------- # 03/03/06 stern@rowland.harvard.edu 1.1068.8.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/06 davidm@tiger.hpl.hp.com 1.1068.12.3 # ia64: Hook up POSIX-timer syscalls. Take advantage of ptrace_notify(). # -------------------------------------------- # 03/03/06 david-b@pacbell.net 1.1068.8.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.8.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.1078 # 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.10.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.2.1 # [IPSEC]: Fix build when ipsec is disabled. # -------------------------------------------- # 03/03/06 davem@kernel.bkbits.net 1.1077.1.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.11.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 kai@tp1.ruhr-uni-bochum.de 1.1077.2.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 torvalds@home.transmeta.com 1.1079 # 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.1080 # Merge bk://bk.arm.linux.org.uk # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1081 # 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.1082 # [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.1083 # [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.1084 # [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.1085 # [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.1086 # [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.1087 # [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.1088 # [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.1089 # [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.1090 # [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.1091 # [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.1092 # [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.1093 # [PATCH] remove __pte_offset # # Patch from Dave Hansen # # ptes this time # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1094 # [PATCH] missed unlock_kernel() in ext3+htree # # Patch from Alex Tomas # # There's a missing unlock_kernel(). # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1095 # [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.1096 # [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.1097 # [PATCH] ext3: fix error-path memory leak # # Fix an error-path memory leak in ext3_fill_super(). # -------------------------------------------- # 03/03/06 akpm@digeo.com 1.1098 # [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.1099 # [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.1100 # [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.13.1 # [PATCH] minor breakage fix from typo fixes # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.2 # [PATCH] minor typo fix that got missed # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.3 # [PATCH] remove 2.2 compatmac stuff from rio driver # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.4 # [PATCH] exterminate 2.2 gunk from video stuff # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.5 # [PATCH] look a typo 8) # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.6 # [PATCH] more 2.0 crap # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.7 # [PATCH] more 2.0/2.2 bits # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.8 # [PATCH] another typo that escaped # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.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.13.10 # [PATCH] remove a pile of 2.0 and 2.2 support # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.11 # [PATCH] filter more 2.2 junk # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.12 # [PATCH] kill stdarg in intermezzo # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.13 # [PATCH] missed patch - static not extern inline in cia # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.14 # [PATCH] correct BUG doc # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.15 # [PATCH] kill the now dead ide_ioreg_t # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.16 # [PATCH] kill long unused macro # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.17 # [PATCH] add serial port table for PC9800 # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.18 # [PATCH] correct BUG doc in parisc # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.19 # [PATCH] remove unused beep macro on sh # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.20 # [PATCH] Add ELF types for Hitach H8 series # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.21 # [PATCH] remove 2.2 junk from efs # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.22 # [PATCH] remove 2.2 bits fromw anpipe # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.23 # [PATCH] remove 2.0 and 2.2 stuff from netfilter # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.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.13.25 # [PATCH] remove 2.0/2.2 stuff # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.26 # [PATCH] remove 2.0/2.2 stuff from wanrouter # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.27 # [PATCH] correct emu10k url # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.28 # [PATCH] correct file names in comments in mm # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.29 # [PATCH] clean up 2.2 stuff in wanrouter code # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.30 # [PATCH] ALi it turns out has a 31bit audio device # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.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.13.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.13.33 # [PATCH] correct building of the old ide/hd.c driver # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.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.13.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.13.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.13.37 # [PATCH] switch ide-floppy to ide_execute_command # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.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.13.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.13.40 # [PATCH] remove spare cast # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.41 # [PATCH] switch ide taskfile ioctls to ide_execute_command # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.42 # [PATCH] fix wrong type and statics in amd ide # -------------------------------------------- # 03/03/06 alan@lxorguk.ukuu.org.uk 1.1068.13.43 # [PATCH] update via driver from 3.35-ac to 3.36 # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1101 # 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.1102 # [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.1103 # [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.1104 # [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.1105 # [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.1106 # [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.1107 # [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.1.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.1.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.1108 # 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.12.4 # ia64: Fix several small bugs/omissions from the 2.5.64 sync. # -------------------------------------------- # 03/03/06 anton@samba.org 1.1107.1.1 # [PATCH] missing include # # list.h must now include stddef since it uses NULL. # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1107.1.2 # Fix "con_init()" function type and stale (and incorrect) declaration # -------------------------------------------- # 03/03/06 torvalds@home.transmeta.com 1.1107.1.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.12.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.12.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.12.7 # ia64: Minor formatting/whitespace fixes in ia64-version of acpi.c. # -------------------------------------------- # 03/03/06 bjorn_helgaas@hp.com 1.1068.12.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.19.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.19.3 # ISDN/HiSax: config.c cleanup # # Consolidate allocation / freeing of various data structures into # one function. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.19.4 # ISDN/HiSax: Remove unused ISDN_CHIP_* macros # # They were only defined, never used. # -------------------------------------------- # 03/03/07 kai@vaio.(none) 1.1025.19.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.19.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 torvalds@home.transmeta.com 1.1109 # 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.1110 # 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.1111 # [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.1112 # [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.1113 # [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.1114 # [PATCH] revert pfn_to_nid change. # # This change was wrong. pfn_to_nid is a macro. # -------------------------------------------- # 03/03/07 zwane@linuxpower.ca 1.1115 # [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.1116 # [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.1117 # [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.1118 # [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 green@namesys.com 1.1119 # [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.1120 # [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.1121 # [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.1122 # [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.1123 # [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.7.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.1124 # 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.1122.1.1 # [SPARC]: One too many chars in INIT_C_CC # -------------------------------------------- # 03/03/07 greg@kroah.com 1.1123.1.1 # gen_init_cpio: Add the ability to add files to the cpio image. # -------------------------------------------- # 03/03/07 greg@kroah.com 1.1123.1.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.1125 # 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.1122.1.2 # [FRAMEBUFFER]: Convert SBUS LEO driver to new APIs. # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1122.1.3 # [SPARC64]: Use pci_remove_bus_device to delete, found by Ben Collins. # -------------------------------------------- # 03/03/07 davem@nuts.ninka.net 1.1126 # 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.1127 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1125.1.1 # Avoid warning due to missing return value # -------------------------------------------- # 03/03/07 torvalds@home.transmeta.com 1.1125.1.2 # Ignore initramfs cpio file # -------------------------------------------- # 03/03/07 kai@tp1.ruhr-uni-bochum.de 1.1122.2.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/07 marcel@holtmann.org 1.1128 # [SPARC64]: Translate AUTOFS_IOC_EXPIRE_MULTI ioctl. # -------------------------------------------- # 03/03/08 davej@codemonkey.org.uk 1.1125.1.3 # [WATCHDOG] amd7xx_tco updates from Zwane, and nuke EXPORT_NO_SYMBOLS # -------------------------------------------- # 03/03/08 rml@tech9.net 1.1125.2.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.1125.2.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.1129 # [SPARC64]: Make sure update_process_times runs inside of irq_{enter,exit} region. # -------------------------------------------- # 03/03/08 davem@kernel.bkbits.net 1.1130 # 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.1125.1.4 # Merge bk://linux-dj.bkbits.net/watchdog # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/08 torvalds@home.transmeta.com 1.1131 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/03/08 mbligh@aracnet.com 1.1132 # [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.1133 # [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.1134 # [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.1135 # [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.1136 # [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.1137 # [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 akpm@digeo.com 1.1138 # [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.1139 # [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.1140 # [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.1141 # [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.1142 # [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.1143 # [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.1144 # [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.1145 # [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.1146 # [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.1147 # [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.1148 # [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.1149 # [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.1150 # [PATCH] usercopy checks in old_readdir() # # Fix up some unchecked copy_to_user()s # -------------------------------------------- # 03/03/08 akpm@digeo.com 1.1151 # [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.1152 # [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.1153 # [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.1154 # [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.1155 # [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.1156 # [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.1157 # [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.1158 # [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.1159 # [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.1160 # [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. # -------------------------------------------- # 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 8 21:41:36 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/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex --- a/Documentation/cdrom/cdrom-standard.tex Sat Mar 8 21:41:33 2003 +++ b/Documentation/cdrom/cdrom-standard.tex Sat Mar 8 21:41:33 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/ia64/fsys.txt b/Documentation/ia64/fsys.txt --- a/Documentation/ia64/fsys.txt Sat Mar 8 21:41:34 2003 +++ b/Documentation/ia64/fsys.txt Sat Mar 8 21:41:34 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/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Sat Mar 8 21:41:34 2003 +++ b/MAINTAINERS Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/Makefile Sat Mar 8 21:41:32 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 @@ -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 diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Sat Mar 8 21:41:35 2003 +++ b/arch/alpha/Kconfig Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/arch/alpha/kernel/core_marvel.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/arch/alpha/kernel/core_titan.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/alpha/kernel/irq.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/arch/alpha/kernel/pci.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/arch/alpha/kernel/sys_nautilus.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/arch/alpha/mm/fault.c Sat Mar 8 21:41:33 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/vmlinux.lds.S b/arch/alpha/vmlinux.lds.S --- a/arch/alpha/vmlinux.lds.S Sat Mar 8 21:41:34 2003 +++ b/arch/alpha/vmlinux.lds.S Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/arm/Kconfig Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/arch/arm/common/sa1111.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/arch/arm/kernel/Makefile Sat Mar 8 21:41:35 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 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/arm/kernel/bios32.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/arm/kernel/ecard.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/arm/kernel/entry-armv.S Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/arch/arm/kernel/entry-common.S Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/arch/arm/kernel/irq.c Sat Mar 8 21:41:32 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 8 21:41:36 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 8 21:41:35 2003 +++ b/arch/arm/kernel/time.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/arch/arm/mach-integrator/Makefile Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/arm/mach-integrator/cpu.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/arm/mach-sa1100/Kconfig Sat Mar 8 21:41:36 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 8 21:41:36 2003 +++ b/arch/arm/mach-sa1100/Makefile Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1100.c Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/arch/arm/mach-sa1100/cpu-sa1110.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/arch/arm/mach-sa1100/generic.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/arm/mach-sa1100/generic.h Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/arm/mach-sa1100/irq.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/arm/mach-sa1100/pm.c Sat Mar 8 21:41:33 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 8 21:41:36 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 8 21:41:35 2003 +++ b/arch/arm/mach-sa1100/system3.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/arm/mm/fault-common.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/arm/tools/mach-types Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/arm/vmlinux-armo.lds.in Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/arm/vmlinux-armv.lds.in Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/cris/Kconfig Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/arch/cris/kernel/irq.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/cris/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/arch/i386/Kconfig Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/arch/i386/Makefile Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/arch/i386/boot/Makefile Sat Mar 8 21:41:33 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: $(obj)/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 + 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 + +# These require being root or having syslinux 2.02 or higher installed +fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 + MTOOLSRC=$(src)/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 + +fdimage288: $(BOOTIMAGE) $(src)/mtools.conf + dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=2880 + MTOOLSRC=$(src)/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 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 8 21:41:34 2003 +++ b/arch/i386/boot/bootsect.S Sat Mar 8 21:41:34 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 8 21:41:36 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 8 21:41:34 2003 +++ b/arch/i386/boot/tools/build.c Sat Mar 8 21:41:34 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/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Sat Mar 8 21:41:36 2003 +++ b/arch/i386/kernel/i386_ksyms.c Sat Mar 8 21:41:36 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/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Sat Mar 8 21:41:33 2003 +++ b/arch/i386/kernel/io_apic.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/arch/i386/kernel/irq.c Sat Mar 8 21:41:32 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/numaq.c b/arch/i386/kernel/numaq.c --- a/arch/i386/kernel/numaq.c Sat Mar 8 21:41:35 2003 +++ b/arch/i386/kernel/numaq.c Sat Mar 8 21:41:35 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/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Sat Mar 8 21:41:34 2003 +++ b/arch/i386/kernel/smpboot.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/i386/kernel/srat.c Sat Mar 8 21:41:33 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/mm/discontig.c b/arch/i386/mm/discontig.c --- a/arch/i386/mm/discontig.c Sat Mar 8 21:41:34 2003 +++ b/arch/i386/mm/discontig.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/arch/i386/mm/fault.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/i386/mm/init.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/i386/mm/ioremap.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/arch/i386/mm/pgtable.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/arch/i386/oprofile/nmi_int.c Sat Mar 8 21:41:35 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_p4.c b/arch/i386/oprofile/op_model_p4.c --- a/arch/i386/oprofile/op_model_p4.c Sat Mar 8 21:41:32 2003 +++ b/arch/i386/oprofile/op_model_p4.c Sat Mar 8 21:41:32 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(); diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c --- a/arch/i386/pci/irq.c Sat Mar 8 21:41:36 2003 +++ b/arch/i386/pci/irq.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/i386/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/ia64/Kconfig Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/arch/ia64/Makefile Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/arch/ia64/hp/sim/simscsi.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/ia64/hp/sim/simserial.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/ia64/ia32/ia32_entry.S Sat Mar 8 21:41:34 2003 @@ -428,6 +428,26 @@ 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 + data8 sys_ni_syscall /* * CAUTION: If any system calls are added beyond this point * then the check in `arch/ia64/kernel/ivt.S' will have 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 8 21:41:32 2003 +++ b/arch/ia64/ia32/ia32_support.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/arch/ia64/ia32/sys_ia32.c Sat Mar 8 21:41:34 2003 @@ -3151,6 +3151,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 +3189,9 @@ return -EFAULT; return ret; +#else + return -ENOSYS; +#endif } asmlinkage long @@ -3433,8 +3437,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 +3471,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 8 21:41:34 2003 +++ b/arch/ia64/kernel/acpi.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/ia64/kernel/entry.S Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/arch/ia64/kernel/fsys.S Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/ia64/kernel/gate.S Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/arch/ia64/kernel/init_task.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/iosapic.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/arch/ia64/kernel/irq.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/ia64/kernel/ivt.S Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/machvec.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/mca.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/arch/ia64/kernel/palinfo.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/ia64/kernel/perfmon.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/process.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/ia64/kernel/ptrace.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/arch/ia64/kernel/setup.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/ia64/kernel/sigframe.h Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/signal.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/ia64/kernel/smp.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/arch/ia64/kernel/sys_ia64.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/ia64/kernel/time.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/arch/ia64/kernel/unwind.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/ia64/kernel/unwind_i.h Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/arch/ia64/mm/fault.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/arch/ia64/mm/hugetlbpage.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/arch/ia64/mm/tlb.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/ia64/pci/pci.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/ia64/sn/io/Makefile Sat Mar 8 21:41:33 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/ia64/sn/kernel/mca.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/arch/ia64/sn/kernel/setup.c Sat Mar 8 21:41:33 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 8 21:41:36 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 8 21:41:35 2003 +++ b/arch/ia64/tools/print_offsets.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/arch/ia64/vmlinux.lds.S Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/m68k/Kconfig Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/arch/m68k/atari/stram.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/arch/m68k/vmlinux-std.lds Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/arch/m68k/vmlinux-sun3.lds Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/m68knommu/Kconfig Sat Mar 8 21:41:35 2003 @@ -9,10 +9,6 @@ bool default n -config SWAP - bool - default n - config FPU bool default n diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Sat Mar 8 21:41:34 2003 +++ b/arch/mips/Kconfig Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/arch/mips/arc/arc_con.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/mips/au1000/common/serial.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/mips/baget/irq.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/mips/dec/irq.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/mips/ite-boards/generic/irq.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/arch/mips/kernel/irq.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/arch/mips/kernel/old-irq.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/mips/mips-boards/atlas/atlas_int.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/arch/mips/philips/nino/irq.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/arch/mips/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/arch/mips64/Kconfig Sat Mar 8 21:41:33 2003 @@ -9,10 +9,6 @@ bool default y -config SWAP - bool - default y - source "init/Kconfig" 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 8 21:41:36 2003 +++ b/arch/mips64/mips-boards/atlas/atlas_int.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/arch/mips64/mips-boards/malta/malta_int.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/arch/mips64/sgi-ip22/ip22-int.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/arch/mips64/sgi-ip27/ip27-irq.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/mips64/vmlinux.lds.S Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/arch/parisc/Kconfig Sat Mar 8 21:41:34 2003 @@ -18,10 +18,6 @@ bool default y -config SWAP - bool - default y - config STACK_GROWSUP bool default y diff -Nru a/arch/parisc/vmlinux.lds.S b/arch/parisc/vmlinux.lds.S --- a/arch/parisc/vmlinux.lds.S Sat Mar 8 21:41:33 2003 +++ b/arch/parisc/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/ppc/8xx_io/uart.c Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/arch/ppc/Kconfig Sat Mar 8 21:41:36 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/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 8 21:41:33 2003 +++ b/arch/ppc/boot/simple/rw4/ppc_40x.h Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/ppc/kernel/irq.c Sat Mar 8 21:41:35 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++) @@ -373,8 +375,10 @@ seq_printf(p, "%s", (irq_desc[i].status & IRQ_LEVEL) ? "Level " : "Edge "); seq_printf(p, " %s", action->name); for (action = action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); + 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){ diff -Nru a/arch/ppc/vmlinux.lds.S b/arch/ppc/vmlinux.lds.S --- a/arch/ppc/vmlinux.lds.S Sat Mar 8 21:41:36 2003 +++ b/arch/ppc/vmlinux.lds.S Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/arch/ppc64/Kconfig Sat Mar 8 21:41:34 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config UID16 bool diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Sat Mar 8 21:41:34 2003 +++ b/arch/ppc64/kernel/irq.c Sat Mar 8 21:41:34 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; diff -Nru a/arch/ppc64/vmlinux.lds.S b/arch/ppc64/vmlinux.lds.S --- a/arch/ppc64/vmlinux.lds.S Sat Mar 8 21:41:35 2003 +++ b/arch/ppc64/vmlinux.lds.S Sat Mar 8 21:41:35 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/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Sat Mar 8 21:41:33 2003 +++ b/arch/s390/Kconfig Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/arch/s390/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/s390x/Kconfig Sat Mar 8 21:41:34 2003 @@ -7,10 +7,6 @@ bool default y -config SWAP - bool - default y - config RWSEM_GENERIC_SPINLOCK bool diff -Nru a/arch/s390x/vmlinux.lds.S b/arch/s390x/vmlinux.lds.S --- a/arch/s390x/vmlinux.lds.S Sat Mar 8 21:41:33 2003 +++ b/arch/s390x/vmlinux.lds.S Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/arch/sh/Kconfig Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/arch/sh/kernel/irq.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/sh/vmlinux.lds.S Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/arch/sparc/Kconfig Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/arch/sparc/kernel/irq.c Sat Mar 8 21:41:32 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/vmlinux.lds.S b/arch/sparc/vmlinux.lds.S --- a/arch/sparc/vmlinux.lds.S Sat Mar 8 21:41:32 2003 +++ b/arch/sparc/vmlinux.lds.S Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/arch/sparc64/Kconfig Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/sparc64/defconfig Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/arch/sparc64/kernel/ioctl32.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/sparc64/kernel/pci_common.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/arch/sparc64/kernel/smp.c Sat Mar 8 21:41:32 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/vmlinux.lds.S b/arch/sparc64/vmlinux.lds.S --- a/arch/sparc64/vmlinux.lds.S Sat Mar 8 21:41:35 2003 +++ b/arch/sparc64/vmlinux.lds.S Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/arch/um/Kconfig Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/um/drivers/stdio_console.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/um/drivers/ubd_kern.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/arch/um/kernel/mem.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/arch/v850/Kconfig Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/arch/v850/kernel/irq.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/arch/x86_64/Kconfig Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/arch/x86_64/boot/Makefile Sat Mar 8 21:41:33 2003 @@ -73,7 +73,7 @@ MTOOLSRC=$(src)/mtools.conf mcopy - a:syslinux.cfg MTOOLSRC=$(src)/mtools.conf mcopy $(BOOTIMAGE) a:linux ; sync -# These require being root or having syslinux run setuid +# These require being root or having syslinux 2.02 or higher installed fdimage fdimage144: $(BOOTIMAGE) $(src)/mtools.conf dd if=/dev/zero of=$(obj)/fdimage bs=1024 count=1440 MTOOLSRC=$(src)/mtools.conf mformat v: ; sync 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 8 21:41:33 2003 +++ b/arch/x86_64/kernel/irq.c Sat Mar 8 21:41:33 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/vmlinux.lds.S b/arch/x86_64/vmlinux.lds.S --- a/arch/x86_64/vmlinux.lds.S Sat Mar 8 21:41:32 2003 +++ b/arch/x86_64/vmlinux.lds.S Sat Mar 8 21:41:32 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/drivers/acorn/block/fd1772.c b/drivers/acorn/block/fd1772.c --- a/drivers/acorn/block/fd1772.c Sat Mar 8 21:41:33 2003 +++ b/drivers/acorn/block/fd1772.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/acorn/block/mfmhd.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/acorn/net/ether1.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/acorn/net/ether3.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/acorn/net/etherh.c Sat Mar 8 21:41:35 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/firestream.c b/drivers/atm/firestream.c --- a/drivers/atm/firestream.c Sat Mar 8 21:41:32 2003 +++ b/drivers/atm/firestream.c Sat Mar 8 21:41:32 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/platform.c b/drivers/base/platform.c --- a/drivers/base/platform.c Sat Mar 8 21:41:32 2003 +++ b/drivers/base/platform.c Sat Mar 8 21:41:32 2003 @@ -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 = { diff -Nru a/drivers/block/DAC960.c b/drivers/block/DAC960.c --- a/drivers/block/DAC960.c Sat Mar 8 21:41:35 2003 +++ b/drivers/block/DAC960.c Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/drivers/block/acsi.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/block/amiflop.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/block/ataflop.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/drivers/block/cciss.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/drivers/block/cciss.h Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/drivers/block/cpqarray.c Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/drivers/block/floppy.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/block/genhd.c Sat Mar 8 21:41:34 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,132 @@ } *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; + + if (devfs_only()) + return 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; + int ret = 0; + + if (devfs_only()) + return 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 || strcmp((*n)->name, name)) + ret = -EINVAL; + else { + p = *n; + *n = p->next; + kfree(p); + } + up_write(&block_subsys.rwsem); + + return ret; } /* @@ -48,6 +177,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 +230,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 +450,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 +458,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 +483,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 +499,7 @@ struct gendisk *disk = to_disk(kobj); kfree(disk->random); kfree(disk->part); + free_disk_stats(disk); kfree(disk); } @@ -384,6 +519,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 8 21:41:32 2003 +++ b/drivers/block/ll_rw_blk.c Sat Mar 8 21:41:32 2003 @@ -1475,17 +1475,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 +1525,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 +1648,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 +2200,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 8 21:41:34 2003 +++ b/drivers/block/loop.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/block/nbd.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/drivers/block/paride/pcd.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/block/paride/pd.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/block/paride/pf.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/block/ps2esdi.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/block/rd.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/block/swim3.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/block/swim_iop.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/block/umem.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/block/xd.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/block/z2ram.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/cdrom/aztcd.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/cdrom/cdu31a.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/cdrom/cm206.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/cdrom/gscd.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/cdrom/mcd.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/cdrom/mcdx.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/cdrom/optcd.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/cdrom/sbpcd.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/cdrom/sjcd.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/cdrom/sonycd535.c Sat Mar 8 21:41:33 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/amiserial.c b/drivers/char/amiserial.c --- a/drivers/char/amiserial.c Sat Mar 8 21:41:36 2003 +++ b/drivers/char/amiserial.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/drivers/char/decserial.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/char/hvc_console.c Sat Mar 8 21:41:35 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/random.c b/drivers/char/random.c --- a/drivers/char/random.c Sat Mar 8 21:41:32 2003 +++ b/drivers/char/random.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/char/raw.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/char/rio/rio_linux.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/char/rio/rioboot.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/char/rio/riocmd.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/char/rio/rioctrl.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/char/rio/rioinit.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/char/rio/riointr.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/char/rio/rioparam.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/char/rio/rioroute.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/char/rio/riotable.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/char/rio/riotty.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/char/rtc.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/char/serial167.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/char/serial_tx3912.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/char/sh-sci.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/char/tty_io.c Sat Mar 8 21:41:34 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; diff -Nru a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c --- a/drivers/char/vme_scc.c Sat Mar 8 21:41:32 2003 +++ b/drivers/char/vme_scc.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/char/vt.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/char/watchdog/amd7xx_tco.c Sat Mar 8 21:41:33 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/userspace.c b/drivers/cpufreq/userspace.c --- a/drivers/cpufreq/userspace.c Sat Mar 8 21:41:32 2003 +++ b/drivers/cpufreq/userspace.c Sat Mar 8 21:41:32 2003 @@ -511,7 +511,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); + device_create_file (policy->dev, &dev_attr_scaling_setspeed); memcpy (¤t_policy[cpu], policy, sizeof(struct cpufreq_policy)); up(&userspace_sem); break; @@ -520,7 +520,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); + device_remove_file (policy->dev, &dev_attr_scaling_setspeed); up(&userspace_sem); module_put(THIS_MODULE); break; diff -Nru a/drivers/hotplug/acpiphp_glue.c b/drivers/hotplug/acpiphp_glue.c --- a/drivers/hotplug/acpiphp_glue.c Sat Mar 8 21:41:33 2003 +++ b/drivers/hotplug/acpiphp_glue.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/hotplug/cpci_hotplug_pci.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/hotplug/cpqphp_pci.c Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/drivers/hotplug/ibmphp_core.c Sat Mar 8 21:41:36 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/ide/Makefile b/drivers/ide/Makefile --- a/drivers/ide/Makefile Sat Mar 8 21:41:34 2003 +++ b/drivers/ide/Makefile Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/ide/ide-disk.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/ide/ide-dma.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/ide/ide-floppy.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/ide/ide-io.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/ide/ide-iops.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/drivers/ide/ide-lib.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/ide/ide-probe.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/ide/ide-taskfile.c Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/drivers/ide/legacy/hd.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/ide/pci/amd74xx.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/drivers/ide/pci/via82cxxx.c Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/drivers/isdn/hardware/avm/b1pci.c Sat Mar 8 21:41:32 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 8 21:41:33 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/asuscom.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/avm_a1.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/avm_a1p.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/avm_pci.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/bkm_a4t.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/config.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/diva.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/elsa.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/enternow_pci.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/gazel.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/hfc_pci.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/hfc_sx.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/hfcscard.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/hisax.h Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/hisax_fcclassic.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/hisax_isac.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/hisax_isac.h Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/isdnl1.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/isdnl1.h Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/isurf.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/ix1_micro.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/mic.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/niccy.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/nj_s.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/nj_u.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/s0box.c Sat Mar 8 21:41:32 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 8 21:41:32 2003 +++ b/drivers/isdn/hisax/saphir.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/sedlbauer.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/drivers/isdn/hisax/sportster.c Sat Mar 8 21:41:33 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/teleint.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/teles0.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/isdn/hisax/teles3.c Sat Mar 8 21:41:36 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 8 21:41:34 2003 +++ b/drivers/isdn/hisax/telespci.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/isdn/hisax/w6692.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/isdn/i4l/Kconfig Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/isdn/i4l/isdn_net_lib.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/isdn/i4l/isdn_ppp.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/isdn/i4l/isdn_ppp_mp.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/isdn/i4l/isdn_ppp_mp.h Sat Mar 8 21:41:36 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 8 21:41:36 2003 +++ b/drivers/macintosh/macserial.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/md/dm.c Sat Mar 8 21:41:35 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/md.c b/drivers/md/md.c --- a/drivers/md/md.c Sat Mar 8 21:41:33 2003 +++ b/drivers/md/md.c Sat Mar 8 21:41:33 2003 @@ -2803,7 +2803,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; @@ -3214,11 +3216,10 @@ 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) { 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 8 21:41:33 2003 +++ b/drivers/media/video/bw-qcam.c Sat Mar 8 21:41:33 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/planb.c b/drivers/media/video/planb.c --- a/drivers/media/video/planb.c Sat Mar 8 21:41:35 2003 +++ b/drivers/media/video/planb.c Sat Mar 8 21:41:35 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/zoran.h b/drivers/media/video/zoran.h --- a/drivers/media/video/zoran.h Sat Mar 8 21:41:35 2003 +++ b/drivers/media/video/zoran.h Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/media/video/zr36120.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/message/fusion/lsi/mpi_raid.h Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/message/i2o/i2o_block.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/mtd/ftl.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/mtd/mtdblock.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/mtd/mtdblock_ro.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/mtd/nftlcore.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/net/bonding.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/net/dgrs.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/net/eepro100.c Sat Mar 8 21:41:34 2003 @@ -843,6 +843,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 +995,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 8 21:41:35 2003 +++ b/drivers/net/eth16i.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/net/mac8390.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/net/pppoe.c Sat Mar 8 21:41:34 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); @@ -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; diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c --- a/drivers/net/shaper.c Sat Mar 8 21:41:35 2003 +++ b/drivers/net/shaper.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/net/sis900.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/net/sk98lin/h/skgepnm2.h Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/net/sk_mca.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/net/wan/comx-hw-munich.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/net/wan/pc300_tty.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/net/wan/sdla_chdlc.c Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/net/wan/sdla_fr.c Sat Mar 8 21:41:36 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 8 21:41:32 2003 +++ b/drivers/net/wan/sdla_ft1.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/drivers/net/wan/sdla_ppp.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/drivers/net/wan/sdla_x25.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/net/wan/sdladrv.c Sat Mar 8 21:41:33 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 8 21:41:35 2003 +++ b/drivers/net/wan/sdlamain.c Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/drivers/net/wan/wanpipe_multppp.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/drivers/oprofile/buffer_sync.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/oprofile/cpu_buffer.c Sat Mar 8 21:41:32 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,41 @@ __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 b->buffer_size; + + 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 +129,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 +140,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 +162,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 +183,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 8 21:41:35 2003 +++ b/drivers/oprofile/cpu_buffer.h Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/oprofile/oprofile_stats.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/parport/ieee1284.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/parport/ieee1284_ops.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/pci/Makefile Sat Mar 8 21:41:35 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 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/pci/probe.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/pci/quirks.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/pci/setup-bus.c Sat Mar 8 21:41:36 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 8 21:41:35 2003 +++ b/drivers/pci/setup-res.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/pcmcia/hd64465_ss.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/pcmcia/i82365.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/pcmcia/sa1100_generic.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/pcmcia/tcic.c Sat Mar 8 21:41:34 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/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c --- a/drivers/s390/block/dasd_3990_erp.c Sat Mar 8 21:41:35 2003 +++ b/drivers/s390/block/dasd_3990_erp.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/s390/block/dasd_genhd.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/s390/block/xpram.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/s390/char/con3215.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/s390/char/sclp_con.c Sat Mar 8 21:41:34 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 8 21:41:32 2003 +++ b/drivers/s390/char/sclp_tty.c Sat Mar 8 21:41:32 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 8 21:41:35 2003 +++ b/drivers/s390/char/tape_block.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/s390/char/tuball.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/sbus/char/jsflash.c Sat Mar 8 21:41:34 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/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile --- a/drivers/scsi/aic7xxx/aicasm/Makefile Sat Mar 8 21:41:35 2003 +++ b/drivers/scsi/aic7xxx/aicasm/Makefile Sat Mar 8 21:41:35 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/i91uscsi.h b/drivers/scsi/i91uscsi.h --- a/drivers/scsi/i91uscsi.h Sat Mar 8 21:41:34 2003 +++ b/drivers/scsi/i91uscsi.h Sat Mar 8 21:41:34 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 8 21:41:36 2003 +++ b/drivers/scsi/imm.c Sat Mar 8 21:41:36 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 8 21:41:33 2003 +++ b/drivers/scsi/inia100.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/scsi/inia100.h Sat Mar 8 21:41:32 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/qlogicfc.c b/drivers/scsi/qlogicfc.c --- a/drivers/scsi/qlogicfc.c Sat Mar 8 21:41:35 2003 +++ b/drivers/scsi/qlogicfc.c Sat Mar 8 21:41:35 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 8 21:41:33 2003 +++ b/drivers/scsi/scsi.h Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/scsi/scsi_error.c Sat Mar 8 21:41:32 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; @@ -1193,12 +1192,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 +1213,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 +1295,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,10 +1320,11 @@ return SUCCESS; case CHECK_CONDITION: rtn = scsi_check_sense(scmd); - if (rtn == NEEDS_RETRY) { + if (rtn == NEEDS_RETRY) goto maybe_retry; - } - return rtn; + /* if rtn == FAILED, we have no sense information */ + /* was: return rtn; */ + return SUCCESS; case CONDITION_GOOD: case INTERMEDIATE_GOOD: case INTERMEDIATE_C_GOOD: @@ -1490,9 +1490,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_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Sat Mar 8 21:41:35 2003 +++ b/drivers/scsi/scsi_scan.c Sat Mar 8 21:41:35 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 8 21:41:35 2003 +++ b/drivers/scsi/sd.c Sat Mar 8 21:41:35 2003 @@ -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 8 21:41:33 2003 +++ b/drivers/scsi/sr.c Sat Mar 8 21:41:33 2003 @@ -835,7 +835,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_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c Sat Mar 8 21:41:32 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c Sat Mar 8 21:41:32 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/serial/21285.c b/drivers/serial/21285.c --- a/drivers/serial/21285.c Sat Mar 8 21:41:35 2003 +++ b/drivers/serial/21285.c Sat Mar 8 21:41:35 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 8 21:41:36 2003 +++ b/drivers/serial/68328serial.c Sat Mar 8 21:41:36 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/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Sat Mar 8 21:41:32 2003 +++ b/drivers/serial/8250.c Sat Mar 8 21:41:32 2003 @@ -1982,11 +1982,12 @@ .index = -1, }; -void __init serial8250_console_init(void) +static void __init serial8250_console_init(void) { serial8250_isa_init_ports(); register_console(&serial8250_console); } +console_initcall(serial8250_console_init); #define SERIAL8250_CONSOLE &serial8250_console #else diff -Nru a/drivers/serial/amba.c b/drivers/serial/amba.c --- a/drivers/serial/amba.c Sat Mar 8 21:41:32 2003 +++ b/drivers/serial/amba.c Sat Mar 8 21:41:32 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 8 21:41:33 2003 +++ b/drivers/serial/anakin.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/serial/clps711x.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/serial/core.c Sat Mar 8 21:41:33 2003 @@ -1890,42 +1890,6 @@ return 0; } - -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) -{ -#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 -} #endif /* CONFIG_SERIAL_CORE_CONSOLE */ #ifdef CONFIG_PM diff -Nru a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c --- a/drivers/serial/mcfserial.c Sat Mar 8 21:41:33 2003 +++ b/drivers/serial/mcfserial.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/serial/sa1100.c Sat Mar 8 21:41:32 2003 @@ -835,11 +835,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 diff -Nru a/drivers/serial/uart00.c b/drivers/serial/uart00.c --- a/drivers/serial/uart00.c Sat Mar 8 21:41:33 2003 +++ b/drivers/serial/uart00.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/sgi/char/sgiserial.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/usb/class/usb-midi.h Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/usb/core/hub.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/usb/core/message.c Sat Mar 8 21:41:33 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 8 21:41:34 2003 +++ b/drivers/usb/core/urb.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/usb/core/usb.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/usb/host/ohci-pci.c Sat Mar 8 21:41:35 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 8 21:41:32 2003 +++ b/drivers/usb/serial/io_edgeport.c Sat Mar 8 21:41:32 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 8 21:41:34 2003 +++ b/drivers/usb/serial/pl2303.c Sat Mar 8 21:41:34 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 8 21:41:34 2003 +++ b/drivers/usb/serial/pl2303.h Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/usb/serial/usb-serial.c Sat Mar 8 21:41:33 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 8 21:41:33 2003 +++ b/drivers/usb/serial/visor.c Sat Mar 8 21:41:33 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/transport.c b/drivers/usb/storage/transport.c --- a/drivers/usb/storage/transport.c Sat Mar 8 21:41:33 2003 +++ b/drivers/usb/storage/transport.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/video/Makefile Sat Mar 8 21:41:32 2003 @@ -70,9 +70,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 +81,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 8 21:41:34 2003 +++ b/drivers/video/bw2.c Sat Mar 8 21:41:34 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 8 21:41:35 2003 +++ b/drivers/video/cg14.c Sat Mar 8 21:41:35 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 8 21:41:34 2003 +++ b/drivers/video/cg3.c Sat Mar 8 21:41:34 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 8 21:41:33 2003 +++ b/drivers/video/cg6.c Sat Mar 8 21:41:33 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 8 21:41:32 2003 +++ b/drivers/video/fbmem.c Sat Mar 8 21:41:32 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 8 21:41:36 2003 +++ b/drivers/video/ffb.c Sat Mar 8 21:41:36 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 8 21:41:36 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 8 21:41:36 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